This is the first of a few posts on plotting in MATLAB. I’ll be describing more than the mechanics of calling the plotting (and related) functions. This series will present suggestions and considerations to get your plot looking “just right” for your paper or presentation. By the end of the series, you will have your own plotting function that can automate as much as possible. I’m focusing on 2D plots generated by the MATLAB “plot” function, which is the most common in MATLAB, but most of the ideas also apply to the other plotting functions, too (like “histogram”), or even to plotting in general (via MATLAB or elsewhere). In this first post, I’m talking about improving the curves themselves. The next post describes annotations and other text.

Every curve plotted in a figure should stand out and be easy to read, whether in color or in black-and-white. We’ll jump right to generating a figure with some data, and then I’ll go over some suggested changes to the default appearance. I assume that you already know what you want to plot (figuring that out would be a series on its own!).

## A Sample Plot

I’m going to start with a sample end result. We’re not going the whole way in this first post, but you get an idea of where we’re headed.

The figure above is clean, clear, and would be as easy to read in black-and-white as it is in color. Now, let’s try to create it. We’ll start with the following simple script:

% Plotting take 1 | |

x = 1e-2:1e-2:100; | |

% Smooth curves | |

y1 = exp(-x); | |

y2 = 1-exp(-x); | |

% Noisy curves | |

n = length(x); | |

z1 = y1.*(1+0.005*randn(1,n)); | |

z2 = y2.*(1+0.005*randn(1,n)); | |

plot(x,y1,x,y2,x,z1,x,z2); | |

xlabel('Time [s]'); | |

ylabel('Exponential Observation'); |

The script above uses the simplest call to “plot” possible. We create 4 arrays of data: 2 “smooth” curves and 2 “noisy” curves. All 4 arrays are plotted at once in a single call to plot. If no figure is currently open, then a new figure is created and the 4 lines are added with default parameters. The result is below:

So this is our first attempt, and it’s rough. You could go to the figure editor to start changing properties, and this is useful to find parameters that you like. However, in the long run you have to repeat everything if you recreate the plot. We’re going to focus on changing the settings via the plotting script.

## Coloring Curves

Aside: MATLAB uses American spelling of the word “Color”, so here I will too.

To start improving the figure, we’re going to do a couple of things. First, we’re going to modify how we create the figure in the first place so that we have more control:

- We call “figure” to create a blank figure
- We call “axes” to place a set of axes on the figure we created
- In the call to “axes” we will also increase the font size and enable grids for the x- and y-axis
- We call “hold” and set it to ‘on’. This way, we can call “plot” multiple times and each new curve won’t replace the existing curves
- We have a separate call to “plot” for each of the 4 curves, and we specify to plot on the axes that we created. For now, the benefit of separate calls is just visual. But this will become more useful in a future post when we will generalize the code.

The first curve property that we will tweak is the color. The default MATLAB curve colors are generally not ideal for papers or presentations. I find them to be too bright, so we’ll increase the contrast. There are multiple ways to specify colors. I find it convenient to specify RGB triplets for the ‘Color’ property in the call to plot. One way to do this is to pass a vector of three doubles with values between 0 and 1. So, for example, default blue is [0 0 1], black is [0 0 0], yellow is [0 1 1], and so on. To get darker variants, decrease the values. For now, the only color that I will make noticeably darker is green.

With all of these changes, the plotting script is now

% Plotting take 2 | |

x = 1e-2:1e-2:100; | |

% Smooth curves | |

y1 = exp(-x); | |

y2 = 1-exp(-x); | |

% Noisy curves | |

n = length(x); | |

z1 = y1.*(1+0.005*randn(1,n)); | |

z2 = y2.*(1+0.005*randn(1,n)); | |

hFig = figure; | |

hAxes = axes('Parent',hFig,… | |

'FontSize',12,'XGrid','on', 'YGrid','on', 'Box', 'on'); | |

hold('on'); | |

plot(hAxes, x,y1, 'Color', [0 0 0]); | |

plot(hAxes, x,y2, 'Color', [0 0 1]); | |

plot(hAxes, x,z1, 'Color', [0 0.6 0]); | |

plot(hAxes, x,z2, 'Color', [1 0 0]); | |

xlabel('Time [s]'); | |

ylabel('Exponential Observation'); |

And the figure is now this:

Of course, we still can’t see all the lines yet. We’ll get there …## Markers and Lines

So far we can only see 2 lines. I want to see the smooth lines as solid curves, and just have markers for the noisy curves. I also want the lines to be a bit thicker. All of these changes are easy to get by setting the right plot properties. The plotting script is now

% Plotting take 3 | |

x = 1e-2:1e-2:100; | |

% Smooth curves | |

y1 = exp(-x); | |

y2 = 1-exp(-x); | |

% Noisy curves | |

n = length(x); | |

z1 = y1.*(1+0.005*randn(1,n)); | |

z2 = y2.*(1+0.005*randn(1,n)); | |

hFig = figure; | |

hAxes = axes('Parent',hFig,… | |

'FontSize',12,'XGrid','on', 'YGrid','on', 'Box', 'on'); | |

hold('on'); | |

plot(hAxes, x,y1,'LineStyle', '-', 'Color', [0 0 0],… | |

'LineWidth', 1); | |

plot(hAxes, x,y2,'LineStyle', '-', 'Color', [0 0 1],… | |

'LineWidth', 1); | |

plot(hAxes, x,z1,'LineStyle', 'none', 'Color', [0 0.6 0],… | |

'LineWidth', 1, 'Marker', 'o'); | |

plot(hAxes, x,z2,'LineStyle', 'none', 'Color', [1 0 0],… | |

'LineWidth', 1, 'Marker', 'o'); | |

xlabel('Time [s]'); | |

ylabel('Exponential Observation'); |

And we get the following plot:

Unfortunately, the markers have made the curves very crowded. You also can’t notice that we made the solid curves thicker. We still have changes to do.

## Limits and Skipping

We’re going to make a final few changes that will let us see the data more easily:

- We’re going to make the x-axis log scale with the “set” function. I recommend log scales if you’re trying to see data over 2 or more orders of magnitude. It would also be acceptable to set the y-axis to log scale here.
- We’re going to control the number of data points plotted. Linear sampling is straightforward. However, the x-axis will be log scale. So, we should have sample indices that increase logarithmically. We can get these using the “logspace” function, which we surround with “round” and “unique” to only get integer indices that don’t repeat.

We now have the following plot script:

% Plotting take 4 | |

numPlotPoints = 50; | |

x = 1e-2:1e-2:100; | |

% Smooth curves | |

y1 = exp(-x); | |

y2 = 1-exp(-x); | |

% Noisy curves | |

n = length(x); | |

z1 = y1.*(1+0.005*randn(1,n)); | |

z2 = y2.*(1+0.005*randn(1,n)); | |

plotInd = unique(floor(logspace(0, log10(n), numPlotPoints))); | |

hFig = figure; | |

hAxes = axes('Parent',hFig,… | |

'FontSize',12,'XGrid','on', 'YGrid','on', 'Box', 'on'); | |

hold('on'); | |

plot(hAxes, x(plotInd),y1(plotInd),'LineStyle', '-', 'Color', [0 0 0],… | |

'LineWidth', 1); | |

plot(hAxes, x(plotInd),y2(plotInd),'LineStyle', '-', 'Color', [0 0 1],… | |

'LineWidth', 1); | |

plot(hAxes, x(plotInd),z1(plotInd),'LineStyle', 'none', 'Color', [0 0.6 0],… | |

'LineWidth', 1, 'Marker', 'o'); | |

plot(hAxes, x(plotInd),z2(plotInd),'LineStyle', 'none', 'Color', [1 0 0],… | |

'LineWidth', 1, 'Marker', 'o'); | |

xlabel('Time [s]'); | |

ylabel('Exponential Observation'); | |

set(hAxes,'XScale','log'); |

Note that we’re now sampling all curves logarithmically via the “plotInd” vector. We didn’t need to do this for the smooth curves. The following plot is created:

## What’s Next

So now the curves are in good shape. You might find it helpful to play around with the settings in the figure editor. You can then update the script with the settings you want.

The next post in this series describes adding more polish to other parts of the figure. This includes text formatting and adding annotations.

I really like to read your posts 🙂 You mention really important points.

I also want to contribute with some tricks.

First, I want to start with recommending a very good book on this issue: Raj Jain, The art of computer system performance analysis, John Wiley, 1991, ISBN: 0-471-50336-3. It is not specific to computer systems only, I guess take home lessons are more generic and applicable to many domains. Now let me focus on some Matlab tricks that I use

1- If my figure’s empty space is too much, I prefer squeezing the height dimension, instead of using a square plot.

For this kind of resizing, I use set(hFig, ‘Position’, []) command

hFig = figure;

set(gcf,'PaperPositionMode','auto')

set(hFig, 'Position', [0 0 500 375])

2- I always try to automate my figure production process. For reducing the whitespace around the plot area, I use the following code snippet. You just need to paste the same code after your plotting code. For complex plots (i.e., double y-axis plots or combined plots) you may need to modify a bit, but for plot() command you don’t need to modify, you may use as is.

ti = get(gca,'TightInset');

set(gca,'Position',[ti(1) ti(2) 1-ti(3)-ti(1) 1-ti(4)-ti(2)]);

set(gca,'units','centimeters')

pos = get(gca,'Position');

ti = get(gca,'TightInset');

set(gcf, 'PaperUnits','centimeters');

set(gcf, 'PaperSize', [pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);

set(gcf, 'PaperPositionMode', 'manual');

set(gcf, 'PaperPosition',[0 0 pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);

3- Instead of skipping some data points (in some cases you may not skip for not to deteriorate the curve) you may also put one marker at the middle point or at a more informative point (without breaking the legend of course).

hFig = figure;

set(gcf,'PaperPositionMode','auto')

set(hFig, 'Position', [0 0 500 375])

semilogy(x, y1, '-', 'Color', mycmap(2, :), 'LineWidth', 2);

hold all

grid on

p(1) = semilogy(x(marker_index), y1(marker_index), '-.*', 'Color', mycmap(2, :), 'MarkerSize',8 , 'LineWidth', 2);

semilogy(x, y2, '-', 'Color', mycmap(22, :), 'LineWidth', 2);

p(2) = semilogy(x(marker_index), y2(marker_index), '-s', 'Color', mycmap(22, :), 'MarkerSize',8 , 'LineWidth', 2);

semilogy(x, y10, '-', 'Color', mycmap(53, :), 'LineWidth', 2);

p(3) = semilogy(x(marker_index), y10(marker_index), '-<', 'Color', mycmap(53, :), 'MarkerSize',8 , 'LineWidth', 2);

semilogy(x, y20, '-', 'Color', mycmap(63, :), 'LineWidth', 2);

p(4) = semilogy(x(marker_index), y20(marker_index), '-o', 'Color', mycmap(63, :), 'MarkerSize',8 , 'LineWidth', 2);

set(gca, 'fontsize',10, 'fontweight','bold');

xlabel('x');

ylabel('f(x)');

`legend(p, 'f(x) = 1/x', 'f(x) = 2/x', 'f(x) = 10/x', 'f(x) = 20/x', 'Location','northeast');`

P.S. I use oldschool thick curves 🙂 ‘LineWidth’ 1 is not enough for my eyes 🙂

4- I may also suggest using legendflex from Matlab filexchange. It is a very useful tool.

http://www.mathworks.com/matlabcentral/fileexchange/31092-legendflex-m–a-more-flexible–customizable-legend

5- I also try to save within the code and mostly prefer .pdf format for high quality (in this case, if you are using latex then you need to compile with pdflatex for your manuscript production)

print('-dpdf','-r200','filename')

LikeLike

Thanks Birkan for the feedback and your suggestions. I will also be talking about legends, background coloring, and figure exporting in future posts.

Cheers!

LikeLike

Upps ! I hope I didn’t give spoiler too much 🙂

Thanks for the awesome posts, I am waiting for the new ones impatiently.

best

LikeLike

No problem. I should still find something to talk about 🙂

I’m glad you’re enjoying the posts.

Cheers

LikeLike