This blog post is a bit different. Tammy Kolda originally drafted the following material to explain how to generate good looking Matlab figures. It was based on some notes I had sent her. After discussing it further, we decided to write up a mini-tutorial on this and post it to the blog here. We actually wanted the blog format in order to encourage discussion about it! So please, suggest improvements! We’ve also made the post available as a Matlab file, and github repository for further collaboration and improvements:
- published version of highQualityFigs.m (the basis of this page)
- hq-matlab-figs GitHub repo
Creating high-quality graphics in MATLAB for papers and presentations
- Tamara G. Kolda, Sandia National Laboratories (*)
- David F. Gleich, Purdue University
- April 2013
(*) Sandia National Laboratories is a multi-program laboratory managed and operated by Sandia Corporation, a wholly owned subsidiary of Lockheed Martin Corporation, for the U.S. Department of Energy’s National Nuclear Security Administration under contract DE-AC04-94AL85000.
A simple figure that is hard to view
Here we show a normal image from MATLAB. This example has been adapted from YAGTOM (http://code.google.com/p/yagtom/), an excellent MATLAB resource.
f = @(x) x.^2; g = @(x) 5*sin(x)+5; dmn = -pi:0.001:pi; xeq = dmn(abs(f(dmn) - g(dmn)) < 0.002); figure(1); plot(dmn,f(dmn),'b-',dmn,g(dmn),'r--',xeq,f(xeq),'g*'); xlim([-pi pi]); legend('f(x)', 'g(x)', 'f(x)=g(x)', 'Location', 'SouthEast'); xlabel('x'); title('Example Figure'); print('example', '-dpng', '-r300'); %<-Save as PNG with 300 DPI
The default MATLAB figure does not render well for papers or slides. For instance, suppose we resize the image to 300 pixels high and display in HTML using the following HTML code:
<img src="example.png" height=300>
The image renders as shown below and is not easy to read.
Step 1: Choose parameters (line width, font size, picture size, etc.)
There are a few parameters that can be used to modify a figure so that it prints or displays well. In the table below, we give some suggested values for papers and presentations. Typically, some trial and error is needed to find values that work well for a particular scenario. It’s a good idea to test the final version in its final place (e.g., as a figure in a LaTeX report or an image in a PowerPoint presentation) to make sure the sizes are acceptable.
% Defaults for this blog post width = 3; % Width in inches height = 3; % Height in inches alw = 0.75; % AxesLineWidth fsz = 11; % Fontsize lw = 1.5; % LineWidth msz = 8; % MarkerSize
Step 2: Creating a figure with manually modified properties
Create a new figure. Set its size via the ‘Position’ setting. These commands assume 100 dpi for the sake of on-screen viewing, but this does not impact the resolution of the saved image. For the current axes, set the default fontsize and axes linewidth (different from the plot linewidth). For plotting the results, manually specify the line width and marker sizes as part of the plot command itself. The font size for the legend, axes lables, and title are inherited from the settings for the current axes.
figure(2); pos = get(gcf, 'Position'); set(gcf, 'Position', [pos(1) pos(2) width*100, height*100]); %<- Set size set(gca, 'FontSize', fsz, 'LineWidth', alw); %<- Set properties plot(dmn,f(dmn),'b-',dmn, g(dmn),'r--',xeq,f(xeq),'g*','LineWidth',lw,'MarkerSize',msz); %<- Specify plot properites xlim([-pi pi]); legend('f(x)', 'g(x)', 'f(x)=g(x)', 'Location', 'SouthEast'); xlabel('x'); title('Improved Example Figure');
Step 3: Save the figure to a file and view the final results
Now that you’ve created this fantastic figure, you want to save it to file. There are two caveats:
- Depending on the size of figure, MATLAB may or may not choose tick marks to your liking. These can change again when the figure is saved. Therefore, it’s best to manually specify the tick marks so that they are correctly preserved in both display and saving.
- The size needs to be preserved in the saved (i.e., printed) version. To do this, we have so specify the correct position on the paper.
% Set Tick Marks set(gca,'XTick',-3:3); set(gca,'YTick',0:10); % Here we preserve the size of the image when we save it. set(gcf,'InvertHardcopy','on'); set(gcf,'PaperUnits', 'inches'); papersize = get(gcf, 'PaperSize'); left = (papersize(1)- width)/2; bottom = (papersize(2)- height)/2; myfiguresize = [left, bottom, width, height]; set(gcf,'PaperPosition', myfiguresize); % Save the file as PNG print('improvedExample','-dpng','-r300');
EPS versus PNG
An interesting feature of MATLAB is that the rendering in EPS is not the same as in PNG. To illustrate the point, we save the image as EPS, convert it to PNG, and then show it here. The EPS version is cropped differently. Additionally, the dashed line looks more like the original image in the EPS version than in the PNG version.
print('improvedExample','-depsc2','-r300'); if ispc % Use Windows ghostscript call system('gswin64c -o -q -sDEVICE=png256 -dEPSCrop -r300 -oimprovedExample_eps.png improvedExample.eps'); else % Use Unix/OSX ghostscript call system('gs -o -q -sDEVICE=png256 -dEPSCrop -r300 -oimprovedExample_eps.png improvedExample.eps'); end
GPL Ghostscript 9.07 (2013-02-14) Copyright (C) 2012 Artifex Software, Inc. All rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for details. Loading NimbusSanL-Regu font from %rom%Resource/Font/NimbusSanL-Regu... 3339336 1916509 8109568 6818233 3 done.
Automating the example
There is a way to make this process easier, especially if you are generating many figures that will have the same settings. It involves changing Matlab’s default settings for the current session. Note that these changes apply only a per-session basis; if you restart Matlab, these changes are forgotten! Recently, the Undocumented Matlab Blog had a great post about these hidden defaultshttp://undocumentedmatlab.com/blog/getting-default-hg-property-values/. There are many other properties that can potentially be changed as well.
% The new defaults will not take effect if there are any open figures. To % use them, we close all figures, and then repeat the first example. close all; % The properties we've been using in the figures set(0,'defaultLineLineWidth',lw); % set the default line width to lw set(0,'defaultLineMarkerSize',msz); % set the default line marker size to msz set(0,'defaultLineLineWidth',lw); % set the default line width to lw set(0,'defaultLineMarkerSize',msz); % set the default line marker size to msz % Set the default Size for display defpos = get(0,'defaultFigurePosition'); set(0,'defaultFigurePosition', [defpos(1) defpos(2) width*100, height*100]); % Set the defaults for saving/printing to a file set(0,'defaultFigureInvertHardcopy','on'); % This is the default anyway set(0,'defaultFigurePaperUnits','inches'); % This is the default anyway defsize = get(gcf, 'PaperSize'); left = (defsize(1)- width)/2; bottom = (defsize(2)- height)/2; defsize = [left, bottom, width, height]; set(0, 'defaultFigurePaperPosition', defsize); % Now we repeat the first example but do not need to include anything % special beyond manually specifying the tick marks. figure(1); clf; plot(dmn,f(dmn),'b-',dmn,g(dmn),'r--',xeq,f(xeq),'g*'); xlim([-pi pi]); legend('f(x)', 'g(x)', 'f(x)=g(x)', 'Location', 'SouthEast'); xlabel('x'); title('Automatic Example Figure'); set(gca,'XTick',-3:3); %<- Still need to manually specific tick marks set(gca,'YTick',0:10); %<- Still need to manually specific tick marks
print('autoExample', '-dpng', '-r300');
And here is the saved version rendered via the HTML command
<img src="autoExample.png" height=300>
I’ve encountered the issues above, too. I use
I wondered about other possibilities such as
tikz (e.g., http://almutei.wordpress.com/2012/05/05/pretty-plots-automatically-create-tikz-source-code-for-plots-in-latex-with-matlab)
or using matplotlib in Python, but haven’t tried them.
We talked about exportfig. One thing neither of us liked is that it modifies many figures properties so you need to replot the figure from scratch. Tikz makes beautiful figures, but you pay for it in how long it takes to make them. That is, I think of Matlab’s figure toolbox like a sketch-pad, and tikz as a tool to help with the highest possible quality output. The vast majority of talks or papers don’t merit the tikz treatment, but you can do so much better than just raw sketches with just a tiny bit of extra work in Matlab.
I believe that a post of this nature would be incomplete without mentioning the significant improvements in the upcoming HG2 – http://undocumentedmatlab.com/blog/hg2-update/
Great point. I haven’t tracked down our university copy of 2013a yet to try the eps/png output in HG2.
HG2 has been evolving for the past several years. You can see it even on older releases. There’s no need for 13a specifically, although of course it looks the most polished on 13a. In fact, even if you have an older release and need some good-looking publication-quality outputs, it may well be worth to use HG2 for the outputs.
It doesn’t seem like the output routines are quite ready yet in 2012a (what’s easiest for me to check with …) I got no eps output for our simple example after launching with -hgVersion 2 and the png output seemed to be a screen capture with the grey border intact. If anyone wants to share the default output (i.e. none of our customizations…) from a more recent version, post a link!
I still support http://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz
as one of the best tools for creating really nice plots. It uses pgfplots package http://pgfplots.sourceforge.net/ which has a rather simple syntax itself and again, very good for doing different plotting tasks.
Also, if you look at matplotlib in Python, it now has .pgf export and really nice plots are quite easy to get with close-to-matlab syntax.
I can’t seem to get this to work for JPEG images. When I update the print command to save the image as a jpeg print(‘improvedExample’,’-depsc2′,’-r300′); I is brought into word as a larger size than the 3 x 3. The image is still in the 1:1 ratio but is now a 6.5 x 6.5 image. However when i leave it as a png file, the image is brought into word correctly.
Is there something that I am missing that will allow me to save images as jpeg’s and still maintain the specified sizing?
Thank you in advance
that print command was supposed to be print(‘improvedExample’,’-djpeg’,’-r300′);
Thanks for the great info — you might also consider the following links which have some useful info/tools:
Actually, one reason I am not using matlab2tikz right now is that its capability of processing big data. For example, I am having a *.mat file, which includes at least 6 — 8 column vectors, each vector has approximate 70,000 data values. Using matlab2tikz to process it, I have a tikz output file. However, this output file is pretty large when compared to output from MATLAB directly (EPS) or from matplotlib. For your reference, in my case, a tikz is about 10MB, but a eps from matlab (same data) only 15KB. This is a big obstacle because if we include in LaTeX, the LaTeX file will take longer time to compile and of course, output file of LaTeX would be bigger…. In matlab2tikz homepage, the author mentioned that we should clean figure before export to tikz, I also did it but not improved so much. Until now, I decide to use matplotlib to plot publication-quality figures in python.
Pingback: Publication Quality Figures from Matlab | John G. Mooney