Thursday, March 10, 2011

Templates, Why Matlab is the Awesomeness! (Part 3)

Powerpoint is ok for making basic graphs, as I explained yesterday. I still prefer to hardcode in LaTeX, but you can use something like Inkscape instead, which is open source and works with EPS files and is full vector graphics. When you need to plot data though, that's where Matlab comes in handy.

I hear from a lot of my colleagues that Matlab is too cumbersome to make consistent plots for their thesis's (is that the correct plural of thesis?). If you didn't take the time to make a proper template, then yes, it is too cumbersome to make consistent plots. But if you take the time to build a proper template, like yesterday with Powerpoint, you will be able to churn out nice graphs with relative ease. Let's face it, if you're working with large datasets, you're using Matlab anyway...

Basic Figure Setup
I'm going to assume you already have a plot on the screen. Prior to changing the figure properties, you an actual figure to work on. To build a test figure, I'm going to assume we have two datasets ( X and Y) that we want to plot with respect to time (t).

>> h1 = plot( t , X);
>> h2 = line( t , Y);

I typically work with colored figures so I want to change X and Y to blue and red. This is why I plotted them using separate line commands. If you want to change the MarkerStyle, and MarkerSize, and LineWidth, here's your chance.

>> set( h1 , 'Color' , [0 0 1] );
>> set( h1 , 'Color' , [1 0 0] );

The next step is to change the axes to fit the data. So if t is from 0 to 50 seconds and X and Y both range from -10 Volts to 10 Volts, then you need to set the axes to these limits. After setting the axes, it's good to go ahead and make sure you have enough tick marks and label the axes.

>> axis([0 50 -10 10]);
>> set( gca , 'XTick' , [0 : 5 : 50] );
>> set( gca , 'YTick' , [-10 : 2 : 10] );
>> xlabel( gca , 'Time [s]' );
>> ylabel( 'Signal Noise [V]' );

So now you have your figure with the right axes, tick marks, and labels, with the lines the colors that you want. But the figure size is scaled to fit your screen, and your fonts and font sizes are all off. Scaling to a particular width and changing font attributes are generally routine tasks that need to be done for all figures for publications. So I make a separate M-file called "Figure2c.m"and put it in a Path folder. Then I can just run it below my figure when I'm plotting my data.

>> Figure2c

Matlab will then just execute the commands in the file called "Figure2c". The 2c stands for two columns. I have other ones for log plots and wider figures as well.

Start with the Figure Properties.
This sounds eerily like yesterday. But if you know you only have 8.5 cm (sorry but I work in metric) of width to work with, you should start by making your figure only 8.5 cm wide. In you Figure2c file, you want to put the following text:

>> function Figure2c

>> set( gcf , 'PaperUnits' , 'Centimeters' ,...
'Units' , 'Centimeters' ,...
'PaperOrientation' , 'Portrait' ,...
'PaperPositionMode' , 'auto' ,...
'Position' , [2 1 8.5 4.5] );
>> PAPER = get( gcf , 'Position' );
>> set ( gcf , 'PaperSize' , [PAPER(3) PAPER(4)] );

The function command means the file runs when called from another file. The next block changes the current figure properties by grabbing the current figure (GCF). Matlab, by default, plots things relative to your screen size, which you need to change to real units. So I've switched them, and all other units in the figure to centimeters. Then I change the paper position so it start 2 cm from the left edge of the computer screen, 1 cm from the bottom and the figure is 8.5 cm wide by 4.5 high. I find this aspect ratio quite nice for figures. You can go higher if you want. The next two lines get the figure wide and change the maximum paper size to the exact figure size. When you save your figure, you won't have any excess white space around the figure because of the paper. This is critical for saving EPS figures.

Change the Axis Properties
After making the figure the right size, the next trick is to make the axes essentially fill the figure. This takes some trial and error (good thing I've done it for you). Like the figure properties, you need to change the current axis properties to work with your real units. So use the following...

>> set( gca , 'Units' , 'centimeters' ,...
'Position' , [1.3 1.1 6.9 3] ,...
'FontSize' , 8 ,...
'FontName' , 'NewCenturySchoolbook' );

This changes the axis units to centimeters. Now you need to position the axes within the figure box, and include space for the axis labels and tick marks. This where some trial and error can occur. I've found for most figures, the actual plot is 6.9 cm wide by 3 cm high and should start about 1.3 cm from the left edge of the figure window and 1.1 cm up from the bottom of the figure window. Then I change the fonts to 8 pt, New Century Schoolbook.

The last step for this part is to change the axis labels to the right font, fontsize, and color (if needed). To do this you need to first copy the previous label name.

>> holderX = get( gca , 'xlabel' );
>> holderY = get( gca , 'ylabel' );

Then you need to reset it based on the string from your original plot. That's what the first attribute is below. The next two change the font size to 9 and the font to New Century Schoolbook to match the other properties.

>> xlabel( get( holderX , 'String' ) ,...
'FontSize' , 9 ,...
'FontName' , 'NewCenturySchoolBook');
>> ylabel( get( holderY , 'String' ) ,...
'FontSize' , 9 ,...
'FontName' , 'NewCenturySchoolBook');

And there's so much more you can do
Using a template like this, I add gridlines in a light grey, but still have axes that are plotted in black (which is somewhat tricky to do). Also, you can add a format for you legend to make sure you have the right font and font size. You can do two Y-axis plots fairly easily with this and do color coding, etc etc.

The last step: Exporting
So now you have your beautiful plot and you need to save it. Since you're running this in M-files anyway, you might as well save the figure via the M-file as well. I export everything to PNG (portable network graphics) which is good for bringing it into Powerpoint. For papers, I use EPS figures with is a vector format. The two commands I use are based on print which prints the current figure.

>> print -r600 -dpng -loose filename.png
>> print -r600 -depsc -loose filename.eps

-r600 makes sure I have 600 DPI on the figures. -dpng/-depsc are the switches for which print driver to use. Matlab has both by default. -loose is very important. Don't forget that. That ensures the paper size and position that you specified in the beginning will be used for the bounding box. That's crucial for importing EPS figures and working with LaTeX. The last bit is the filename.

There you have it. It's a basic template but it works. If you have any questions or want some more tips on Matlab plotting, let me know.



11 comments:

  1. Great post - it made me considering moving away from using LaPrint.

    I just followed the the steps, and I found out that the figures that are printed to png gets very large in scale so the labels and tickmarklabels get off in scale to the plot.

    Am I doing something wrong?

    The printing to eps works just fine.

    Kind regards
    Halberg

    ReplyDelete
  2. If the EPS works fine and has the right scale, then you can always use the system command to convert the EPS you just made to a PNG (or substitute some other picture format). I use Ghostscript (http://pages.cs.wisc.edu/~ghost/) for viewing and converting EPS figures for LaTeX stuff. I've added Ghostscript to my Windows Path so I don't need the full address. You might need to adjust accordingly.

    >> system('gswin32c -dEPSCrop -sDEVICE#pngalpha -r1000 -o figure.png figure.eps');

    That command executes 'gswin32c.exe' and crops and converts the 'figure.eps' to a 1000 DPI 'figure.png'.

    I think the reason you might have this issue is the 'NewCenturySchoolbook' font may not be recognized by your Matlab installation. Try typing:

    >> listfonts

    and see what you get. Remember to place your font in quotes. If you still have problems, let me know.

    ReplyDelete
  3. The font is recognized,so do you have any other suggestions? My plots look like:

    http://www.student.dtu.dk/~s062536/epstest.eps
    http://www.student.dtu.dk/~s062536/pngtest.png

    The conversion outside of Matlab is of course a solution, but that makes it hard to use it on public computer. I am studying, and sometimes and dont take my laptop to school, so it would be good if it was done in the figure script.

    Thanks for the help

    ReplyDelete
  4. Email me your code prof.gears at gmail dot com

    ReplyDelete
  5. Just as a followup

    It is a known bug in Matlab that caused the problem:

    http://www.mathworks.com/support/bugreports/search_results?search_executed=1&keyword=label+scale+windows&release_filter=Exists+in&release=177&selected_products=103&category_filter%5B%5D=1&commit=Search

    Thanks for the help anyways.

    ReplyDelete
  6. This is very helpful - thanks for posting it.

    I think the plural of thesis is theses.

    http://dictionary.reference.com/browse/thesis

    You did ask. :o)

    Do you have any expertise with importing Matlab plots into inkscape to tweak them? I have been doing this of late and one infuriating thing that keeps happening is that inkscape seems to replace any Greek letters with a worse font. This can just be manually tweaked - for example using the extension "tex text" to replace the one that inkscape has substituted but it'd be better not to have to. If anyone else has had this problem and managed to solve it i'd love to hear how it was done.

    This is kind of related to the above discussion as I often use inkscape to render eps files to png (mainly for maple output rather than matlab as maple's png rendering is dreadful.)

    ReplyDelete
    Replies
    1. hmmm, I haven't imported matlab figure into inkscape simply because I haven't had the need to do so.

      I routinely set up all of my figure parameters in matlab and then save it as both an EPS and as PNG. However, I just call Ghostscript from a command prompt within matlab to do it and generate the PNG from the EPS file. My commands are as follows:

      >> print -r600 -depsc -loose Figure.eps
      >> system('gswin32c -dEPSCrop -sDEVICE#pngalpha -r1000 -o Figure.png Figure.eps');

      This makes a 600 DPI EPS figure and a 1000 DPI PNG figure. You have put gswin32c (Ghostscript) in your windows and matlab paths for this to work.

      Let me know if that helps.

      Delete
  7. Thanks - that is useful. I was adding extra graphics to some Matlab graphs which is why I was putting them into inkscape. I still have my mystery font problem and its happening with ghostscript too. No matter - probably just a local configuration problem. I got around it by manually editing the fonts again in Inkscape with an extension called tex text.

    I also just noticed that the Matlab print command will also do PDF which is interesting as the results look marginally better than a png in PDF latex output and tend to be smaller files.


    thanks

    ReplyDelete
  8. That's helpful. I really was about to freak out after setting parameters for my plots manually, and your article was a bliss for me. Thank you very much!

    Best regards,
    Gleb

    ReplyDelete