MATLAB graphics can help you see the big picture in your data. It's easy to plot functions or scattered data, to sketch geometric models, to draw contour maps or 3D "mountain" plots, and to make animations. We will quickly introduce some of the MATLAB graphics commands that will be most useful in scientific computing.
We assume that the quantity Y is a function of X, or is related to X in some way. We wish to display a plot that indicates this relationship.
If we have an explicit formula, Y = F(X), the appropriate command is FPLOT, as in this example:
fplot ( 'x .* sin(x)', [ 0, 10*pi ] )The formula must be enclosed in single quotes, and the variable is always called X. The second argument of FPLOT is the limits on X, enclosed in square brackets.
MATLAB Syntax:
Notice that in the above formula we use "*" to compute 10 * pi, but ".*" to indicate that we want to multiply X by SIN(X). The ".*" multiplication indicates that we are multiplying two lists of numbers, and that we want the result to be another list. This is sometimes called elementwise multiplication.
A second way to carry out an X, Y plot occurs if we have a large set of data pairs (X(1),Y(1)), ..., (X(N),Y(N)). This is the most natural data to use in MATLAB. In this example, I'll go ahead and set values to X and Y first, but we could just as easily have gotten these numbers from a long computation or read them from a file.
x = linspace ( 0, 10*pi, 100 ); y = exp ( -0.1 * x ) .* sin ( x ) plot ( x, y )
MATLAB Syntax:
The LINSPACE command can be used to generate evenly spaced values between two limits. The commandx = linspace ( 0, 10*pi, 100 );generates 100 values, from 0 to 10 * PI, stored as a row. Oh, and MATLAB knows about PI, and that's how you spell it.
Now one way to think about this data is that it's a sine curve wiggling between two decaying exponential curves until it's crushed to death. If we want to see the exponential curves, we can add them to the graph by using the HOLD ON command to "hold" the current plot. Then new plots will be put on top of the old one until we say HOLD OFF.
x = linspace ( 0, 10*pi, 100 ); y = exp ( -0.1 * x ) .* sin ( x ) plot ( x, y ) hold on plot ( x, exp ( -0.1 * x ) ) plot ( x, -exp ( -0.1 * x ) ) hold off
MATLAB Syntax:
It may look like we're passing in a symbolic value for the Y's in the plot commandplot ( x, exp ( -0.1 * x ) )but we're not. In the expressionexp ( -0.1 * x )the X is a vector of numbers, not a symbolic value. This is in distinction to the FPLOT command, where the first item of information that we gave the command really was a formula -- we didn't have a particular set of X values in mind there.
By default, MATLAB simply connects all the data points by straight line segments. The result can look beautiful if you give it enough data. But to see what's really going on, suppose we have a "skimpy" set of data pairs:
x = 2 * pi * rand ( 10, 1 ); x = sort ( x ); y = sin ( x ); plot ( x, y )This probably looks terrible. There are so few data points that connecting them with straight lines doesn't give us the impression of a smooth curve.
MATLAB Syntax:
The command "rand ( 10, 1 )" returns 10 uniform random values, between 0 and 1, set up in a column. We'll be using this command a lot. The commandrandis shorthand forrand ( 1, 1 )and returns a single random value. The commandrand ( 10 )is shorthand forrand ( 10, 10 )
MATLAB Syntax:
The commandsort ( x )puts the values of X in order. If I didn't do this, then when I call plot to "connect the dots" the graph would look a real mess; it simply connects the points in the order they are given.
Is there anything we can do to "fix up" skimpy data? We could try to get a smooth curve that passes through the data. This is called interpolation.
One common way to interpolate data is called a cubic spline. In order to make a nice graph, we start with our X, Y data, set up a cubic spline, and then, pick a lot of points XX where we evaluate the spline, calling those values YY. The spline should go right through our data points, but should have a nice curve in between.
In this example, we will include plots of both the original data, marked with stars, and the spline curve:
x = 2 * pi * rand ( 10, 1 ); x = sort ( x ); y = sin ( x ); xx = linspace ( 0, 2*pi, 100 ); yy = spline ( x, y, xx ); plot ( x, y, '*', xx, yy, 'r' )
MATLAB Syntax:
Now we see another way to put two curves on one plot.plot ( x1, y1, x2, y2 )(with the option to set line styles). And you can string more sets of data in the same PLOT command if you like.
If we have a "noisy" set of data pairs, then it may be a mistake to want the curve to go right through each data point. We may have lots of data that's all over the place, and we are trying to find a simple curve that captures the trend of the data. In that case, we want to do something called approximation.
To make up a set of data that has this property, let's start with some nice data and mess it up:
x = linspace ( -2, 2, 10 ); y = x.^3 - x.^2 - 2*x; xx = x; yy = y .* ( 1.0 + 0.5 * randn ( 1, 10 ) ); plot ( x, y, 'b*-', xx, yy, 'ro-' )
MATLAB supplies the POLYFIT command to "fit" or approximate a set of data by a polynomial of a specific order, and the POLYVAL command to evaluate that polynomial. Continuing with the previous example, let's try to fit the noisy data with a cubic:
p = polyfit ( xx, yy, 3 ); xxx = linspace ( -2, 2, 100 ); yyy = polyval ( p, xxx ); plot ( x, y, 'b*', xxx, yyy, 'g' )
We may have a set of data pairs and error estimates, of the form
( X(1), Y(1) +/- dY(1) ), ... ( X(N), Y(N) +/- dY(N) ),or
( X(1) +/- dX(1), Y(1) +/- dY(1) ) ... ( X(N) +/- dX(N), Y(N) +/- dY(N) )
If we want to display the points with an error bar or error box:
x = 0 : 0.1 : 2; taylor = x - x.^3 / 6; error = taylor - sin ( x ); errorbar ( x, taylor, error )
Again, if we want to compare the value of SIN(X), we can superimpose this:
hold on plot ( x, sin ( x ), 'r' ) hold ( off )
MATLAB Syntax:
We've just seen a new way to generate a list of values, called "colon notation". The format isx = start : increment : endso the commandx = 0 : 0.1 : 1generates the row vector of data:[ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 ]
We may have a pair of parametric formulas
X = F(T) Y = G(T)Although the FPLOT command could handle one symbolic formula, it can't handle two. So what we'll have to do is pick a set of T values, and use the formulas to define X and Y, and then pass them to PLOT:
t = 0 : 0.1 : 2*pi; x = t .* sin ( 3 * t ); y = t .* sin ( t ) .* sin ( t ); plot ( x, y )
If we already have parametric data pairs ( X(T), Y(T) ), then we just plot X versus Y as above.
The interesting problem comes if we have a single implicit formula for X and Y. Here is a simple example that you might recognize:
9 x^{2} + 16 y^{2} = 144The way to handle this is to rewrite it as a function of X and Y:
z = 9 x^{2} + 16 y^{2} - 144and then try a contour plot of Z(X,Y)=0. We'll discuss this in a minute.
Usually you don't worry about labeling a graph until you're ready to show it to someone else. Then it's nice to label the axes, and have a title for the whole graph:
xlabel ( 'The X axis' ) ylabel ( 'The Y axis' ) title ( 'This is my plot' )
We've already seen that the PLOT command can have a third argument, called the linestyle. To draw lines in green:
plot ( x, y, 'g' )the color choices are Red, Green, Blue, Cyan, Yellow, Magenta, blacK and White. To mark each data point with a star:
plot ( x, y, '*' )Other choices include 'o', '+', '.' and so on. To draw a dotted line:
plot ( x, y, ':' )Other options include '-' for the regular line, '-.', or '--'. You can combine these options:
plot ( x, y, 'r*:' )
The scale in the X and Y directions is usually different. This means that the plot of a circle will come out as an ellipse, for instance. To force the measurements in both directions to be the same, try the command:
axis equal
The plotting area is usually rectangular. To make it square, try the command:
axis square
When you have a plot set up with a PLOT command. you can use the LINE command to add lines to it:
line ( x, y )where X and Y are lists of the coordinates of the points to join. For instance, to draw the X axis line:
x = linspace ( 0, 2*pi, 100 ); y = sin ( x ); plot ( x, y ) line ( [0, 2*pi], [0, 0] )If you want a particular color for the line, you have to specify its RGB value, a set of three numbers between 0 and 1:
line ( [0, 2*pi], [0, 0], 'Color', [ 0.4, 0.5, 0 ] )
You can put several separate plots on one page, using the SUBPLOT command. You divide the page up into M by N little boxes, and then specify which box a given plot command is to draw in. For instance:
x = linspace ( 0, 2*pi, 100 ); subplot ( 2, 2, 1 ), plot ( x, sin(x) ) subplot ( 2, 2, 2 ), plot ( x, sin(2*x) ) subplot ( 2, 2, 3 ), plot ( x, sin(x+2) ) subplot ( 2, 2, 4 ), plot ( x, sin(x).^2 )The subplots are numbered in the same order as you would read, that is, left to right, and then down a row.
We can handle a polar plot very easily, since it's usually given in the form
R = R(THETA)so we just generate a set of THETA values and compute the corresponding R. Then, of course, we have to convert to X, Y coordinates:
theta = 0 : 0.1 : 8 * pi; r = theta + 1; x = r .* cos ( theta ); y = r .* sin ( theta ); plot ( x, y )
It can be more appropriate to plot polar data on a polar coordinate system. This way, the "graph paper" is appropriate for the data, and you don't have to convert to X, Y format. We simply use the POLAR command:
theta = 0 : 0.1 : 8 * pi; r = theta + 1; polar ( theta, r )
Suppose we have a long unsorted list of integers, and we want to make a histogram, showing the frequency of occurrence. We really want every integer value to be its own "bin".
y = rand ( 1000, 1 ); y = fix ( 20 * y ); hist ( y, 20 )
To make a histogram out of a set of real numbers means that we have to specify ranges for the bins. However, MATLAB will let us use the same commands as we did for the integer data, just using equally spaced bins.
y = randn ( 1000, 1 ); hist ( y, 20 )
MATLAB Syntax:
The commandrandn ( 1000, 1 )returns a column vector of normal random numbers. These have an average value of zero, and most of them aren't too far from zero, but they can wander very far on occasion.
Proportional data: We may have data that represents proportions of a fixed quantity, so that we want to use a pie chart.
Continents = [ 88, 33, 22, 33, 7 ] pie ( Continents )
MATLAB Syntax:
Now we see another way to make a list - by writing down the entries between two square brackets. What we wrote is obviously a row list. How could we write a column list? There are two ways:This second method should give you an idea of how you would type in a table or matrix that had several rows or columns. For instance, the matrix
- write a row list, and then "transpose it" with an apostrophe:
Continents = [ 88, 33, 22, 33, 7 ]; Columns = Continents'- Use semicolons to mark the end of a row:
Columns = [ 88; 33; 22; 33; 7 ]1 2 3 4 5 6would be entered in asA = [ 1, 2, 3; 4, 5, 6 ]
In some cases, you want to construct an object by patching together polygons of different colors. In 2D, this is done with the fill command. In 3D, you can create a surface from polygons using the fill3 command.
The form of the fill command is
fill ( x, y, c )In the simple cases, x and y are the coordinates of the vertices of the polygon, and c specifies the color, either by one of the common abbreviations, such as 'r', or else as a row vector specifying an rgb color.
For instance, these commands would open up a unit square, and draw a red triangle and a blue "kite":
axis ( [ 0, 1, 0, 1 ] ) x1 = [ 0.0, 0.5, 0.5 ]; y1 = [ 0.5, 0.5, 1.0 ]; fill ( x1, y1, 'r' ) hold on x2 = [ 0.75, 1.0, 0.75, 0.5 ]; y2 = [ 0.0, 0.25, 1.0, 0.25]; c2 = [ 0, 0, 1 ]; fill ( x2, y2, c2 )
Our data might simply be a set of points in the plane. We may want to make a dot plot with the SCATTER command:
x = randn ( 20, 1 ); y = randn ( 20, 1 ); scatter ( x, y )
Another way to draw points is to use the PLOT command, but with a line style that specifies drawing a circle at each point, rather than connecting them:
x = randn ( 20, 1 ); y = randn ( 20, 1 ); plot ( x, y, 'bo' )
To draw polygons or filled areas, use the FILL command, listing the vertices and a fill color:
x = [ 1.0, 2.0, 2.0, 3.0, 3.0, 2.0, 2.0, 1.0, 1.0, 0.0, 0.0, 1.0]; y = [ 0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 2.0, 2.0, 1.0, 1.0]; fill ( x, y, 'r' )
The command CONVHULL returns a list of indices of the points that lie on the convex hull.
x = randn ( 20, 1 ); y = randn ( 20, 1 ); scatter ( x, y ) hold on k = convhull ( x, y ); plot ( x(k), y(k) )
We might want to use a set of points as vertices of triangles. There are many ways to do this. One way to do this is the Delaunay triangulation, which tries to avoid using long skinny triangles. The DELAUNAY command returns a triangle array:
x = randn ( 20, 1 ); y = randn ( 20, 1 ); tri = delaunay ( x, y );
Now we need to find out the number of triangles, and to paste on a fourth column that is a copy of the first one:
[ ntri, ncol ] = size ( tri ); tri(:,4) = tri(:,1);Now we plot the points, and then add lines for each triangle:
scatter ( x, y ) for i = 1 : ntri line ( x(tri(i,:)), y(tri(i,:)) ) end
MATLAB Syntax:
Most objects in MATLAB are really tables, or matrices, or two dimensional arrays. The command SIZE tells you the number of rows and columns, and if you want to save these in variables you do it this way:[ nrow, ncol ] = size ( name )If you want a particular entry of TRI, you say TRI(I,J). But if you want column J, you write TRI(:,J). Similar, a row of TRI would be TRI(I,:). If you have an object with NTRI rows and 3 columns, you can increase its size just by defining a new column (or row) as long as it's the right shape. So the commandtri(:,4) = tri(:,1)says "Get the numbers in column 1 of TRI. Paste them into column 4 of TRI. Oh, and by the way, I guess that means TRI will have 4 columns now."
Another way to deal with scattered points is to consider them as the "capitals" of little countries. For each capital city, its country is the set of all points that are closer to it than to any other city. This is the "Voronoi tesselation".
x = randn ( 20, 1 ); y = randn ( 20, 1 ); voronoi ( x, y )
We might have a vector quantity (think of wind velocity, or the flow of a liquid) measured at regularly spaced points in an area.
The most natural plot to draw would exhibit an arrow at each data point (X,Y), whose direction and relative length corresponded to the value of (U,V). Such a plot can easily be drawn with the quiver command:
[x,y] = meshgrid ( 0:0.2:2, 0:0.2:2 ); u = cos(x) .* sin(y); v = sin(x) .* y - log(x+1); quiver ( x, y, u, v )
MATLAB Syntax:
We want our quiver plot to be made at all the points in a regular two dimensional grid. The MESHGRID command constructs a table of (X,Y) values for such a grid.Note, however, that it is not actually necessary for the (X,Y) data to lie on a rectangular grid. The quiver command can handle any arrangement of points.
In some cases, only the direction of the vectors is important. This is especially true in certain flow problems where there are a few places with large flow values. Exhibiting scaled vectors would mean that most of the flow wouldn't show up at all. To get a sense of the flow direction field, simply scale each vector by its Euclidean norm.
x = 2 * rand ( 121, 1 ); y = 2 * rand ( 121, 1 ); u = cos(x) .* sin(y); v = sin(x) .* y - log(x+1); norm = sqrt ( u.*u + v.*v ); indx = find ( norm ); u(indx) = u(indx) ./ norm(indx); v(indx) = v(indx) ./ norm(indx); quiver ( x, y, u, v )
MATLAB Syntax:
The FIND command returns an index vector of the nonzero elements of a vector. This is how we check the NORM vector, and only divide U and V by nonzero norms.
If we ask for too many vectors, our plot becomes cluttered. Another way to present the direction field information is through a streamline plot.
[x,y] = meshgrid ( 0:0.2:2, 0:0.2:2 ); u = cos(x) .* sin(y); v = sin(x) .* y - log(x+1); startx = [0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2]; starty = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]/5; streamline ( x, y, u, v, startx, starty );
You can also use the stream2 function to precompute the cell array of vertex arrays:
xy = stream2 ( x, y, u, v, startx, starty ); streamline ( xy );
MATLAB Syntax:
The stream2 command computes streamline information which can be displayed by streamline. However, it is necessary that the (x,y) data form a regular rectangular array.
Perhaps a more realistic usage of the streamline command might be useful. Our data will not be from a formula, but from external files. We must "reshape" our data so that it has the rectangular shape required by the program. The files nodes6.txt and velocity6.txt contain 65 records each, of coordinates and velocities on a grid of 13 x positions by 5 y positions.
load ( 'nodes6.txt' ); load ( 'velocity6.txt' ); x = nodes6(:,1); y = nodes6(:,2); u = velocity6(:,1); v = velocity6(:,2); xtab = reshape ( x, 5, 13 ); ytab = reshape ( y, 5, 13 ); utab = reshape ( u, 5, 13 ); vtab = reshape ( v, 5, 13 ); xstart = [ 0, 0, 0, 0, 0, 0 ]; ystart = [ 0, 0.2, 0.4, 0.6, 0.8, 1.0]; axis equal streamline ( xtab, ytab, utab, vtab, startx, starty ); hold on; k = convhull ( x, y ); plot ( x(k), y(k), 'r' ); hold off
Suppose we have a scalar quantity Z defined at points in a two dimensional region. We can think of Z as being a temperature, a pressure, a height or something similar. We'd like a picture of how Z varies.
Actually, remember when we had that implicit relationship between X and Y of the form
9 x^{2} + 16 y^{2} = 144Now is the time to see how to plot that. So we'll be looking at a function Z that is zero exactly when the X and Y satisfy the relationship. But in general, the Z function could come from lots of different problems:
[x,y] = meshgrid ( -5:0.2:5, -5:0.2:5 ); z = 9 * x.^2 + 16 * y.^2 - 144; contour ( x, y, z ); axis square axis equal
The default number of contour lines is 10. To get more, just add the desired number as the fourth argument:
contour ( x, y, z, 40 )Instead of the number of contour levels, you can specify the contour values:
contour ( x, y, z, [ 1.0, 2.0, 3.5 ] )If you want to see a color bar to link the line colors to Z values, just type
colorbar. However, if you have only one contour value, you need to specify it twice to keep MATLAB happy. For our problem, we really wanted to see exactly where Z was zero, so we write:
contour ( x, y, z, [ 0.0 0.0 ] )
You can get a plot of the same data, but using contour colors that fill in the areas:
contourf ( x, y, z )
You can also make a "mountain" plot, in which Z(X,Y) is plotted as a height:
[x,y] = meshgrid ( -5:0.2:5, -5:0.2:5 ); z = 9 * x.^2 + 16 * y.^2 - 144; surf ( x, y, z )
There is also a symbolic plotter, EZSURF, that will plot a formula Z(X,Y):
ezsurf ( '(1-x).^2 + 100 * ( x - y.^2 ).^2' )This is another unusual command like FPLOT, because you supply a formula for Z rather than a table of values. If you want to specify the X and Y ranges, you do it like this:
ezsurf ( '(1-x).^2 + 100 * ( x - y.^2 ).^2', [ -2,2, 0,2 ] )
Now suppose we don't have a formula, and we don't have Z defined on a nice grid of X and Y points. Instead, we just have scattered (X,Y,Z) data. Then you have to create a Delaunay triangulation and pass that on to TRISURF:
x = rand ( 10, 1 ); y = rand ( 10, 1 ); z = x.^2 + y.^2; tri = delaunay ( x, y ); trisurf ( tri, x, y, z );
We've seen how to do contour plots for data on a regular grid, or on scattered points. It is common to have data computed on a triangulated set of points. We assume that we have a set of point coordinates P(NP,2), a set of triangle node indices T(NT,3), and a set of scalar values U(NP) associated with the nodes.
The following examples will assume that we have read data from
p = load ( 'lake_nodes.txt' ); t = load ( 'lake_triangles.txt' ); u = load ( 'lake_solution.txt' );
To see a plot of the triangles making up the triangulation, use the trimesh command:
trimesh ( t, p(:,1), p(:,2) )although for nicer results, you might try
N = size ( p, 1 ); trimesh ( t, p(:,1), p(:,2), zeros(N,1), 'EdgeColor', 'Black' ) view ( 2 ) axis equal
To see an unsatisfactory plot of the solution, use the trisurf command:
trisurf ( t, p(:,1), p(:,2), u )
To see a more pleasing plot of the solution using interpolated color, use the trisurf command with some extra arguments:
trisurf ( t, p(:,1), p(:,2), u, 'FaceColor', 'interp', ... 'EdgeColor', 'interp' )
If you really want to, you can customize just about anything in your MATLAB plot. The way to do this is called Handle Graphics. A "handle" is just a identifier given to each plot by MATLAB. In order to change some property of that plot, you have to give MATLAB the handle, the name of the property, and the new value. For instance,
x = linspace ( 0, 2*pi, 100 ); y = sin(x); id = plot ( x, y ); set ( id, 'Marker', 'o' ) set ( id, 'MarkerSize', 15 ) set ( id, 'Color', 'Cyan' )
In your day to day work, you usually don't need this kind of fine control, but it is available, and can be very helpful when you want a particular graph to come out a certain way.
If you're running MATLAB and looking at a plot, you can easily save the plot by going to the plot window and using the "EXPORT" option. The menu you see will give you an option for BMP, EPS, JPG and TIF file output.
However, if you wish to automate the process of converting the displayed graphic into a graphic file, this can be done using commands like this:
F = getframe;where instead of 'JPEG' you also have the option of 'BMP', 'EPS', 'TIF', and various other graphics formats. I can't believe this is the simplest form of the commands to save the displayed graphics into a file, but it's the best I could do from the documentation!
[ X, map ] = frame2im ( F )
imwrite ( X, 'filename.jpg', 'JPEG' )
One way to do an animation is to make a series of plots, and string them together. There are lots of complications to watch out for. MATLAB will tend to scale your data so it just fits in the plot window. That means that, unless you do something about it, when you make a series of plots, the scale will be different on each plot.
nframes = 51; x = linspace ( -12.0, +12.0, 51 ); for i = 1 : nframes t = 2 * ( i - 1 ) * pi / ( nframes - 1 ); y = 5.0 * cos ( 2.0 * x / 12.0 ) .* sin ( t ) .* cos ( t + x ); plot ( x, y ) axis equal my_frames(:,i) = getframe; end movie ( my_frames, 2 )
The GETFRAME command takes a snapshot of the current plot, and we store that as frame number I of the movie. Then the MOVIE command displays the frames in MY_FRAMES two times.
There are lots of complications to watch out for. MATLAB will tend to scale your data so it just fits in the plot window. That means that, unless you do something about it, when you make a series of plots, the scale will be different on each plot.
MATLAB Syntax:
We use the FOR command to make our 51 frames. The linefor i = 1 : nframessays to repeat the following lines, with the special counter variable I starting at 1 and proceeding to NFRAMES. Notice how we use the value of I to set the value of T, and to decide which frame of the movie we've just made.
If at any time you click on the graphics window, there's a menu item of FILE, with a submenu item of PRINT that will print the current image. That's the easiest way to get a permanent copy of your image.
Another FILE submenu item is SAVE AS. If you choose that, MATLAB will create a FIG file that saves all the information about the image. In a later session of MATLAB, you can bring that picture back using the FILE submenu item OPEN.
Another FILE submenu item is EXPORT. This will allow you to save a copy of the file in one of the standard graphics file formats, including EPS, JPG, and TIF. The EPS format will be useful if you want to include the graphic in a TeX document; the JPG and TIF formats can be used in HTML files.
To include an EPS file in a LateX document, you have to do two things:
\usepackage{epsfig}
\epsfig { width=2in, file=my_graph.eps }
To include a graphic in Microsoft Word,
To include a JPG or TIF graphic in an HTML file, at the appropriate place in your file, use a command like: <img src = "my_graph.jpg", alt = "This is my graph", border = 1 >
You can get help on any MATLAB command, and on certain topics, by using the HELP command. For graphics, the main topics worth looking at can be accessed by these commands:
help graph2d help graph3d help specgraph
If you don't know a topic name, or the name of a command, you can try using the LOOKFOR command, which will report any commands that have a particular word in their definition:
lookfor histogram
lookfor polygon
You can also go to the HELP menu, and select DEMOS and then GRAPHICS to get some ideas of what you can do.
You can return to the HTML web page.