RSS

Making Great Plots in Octave (and Matlab, too!)

07 Oct

When it comes to engineering, successful designs often hinge on clearly communicating technical data and analyses, which generally means lots of plots and graphics. Luckily, Octave, a great tool for performing calculations and processing data, can also generate some very professional plots!

I’d like to go over some tips for making your plots presentation-worthy plots in Octave. Firstly, it’s important to note that plotting in Octave is done by passing commands to GNUPlot; however, the developers have worked hard to make this interface seamless, so you shouldn’t have to open GNUPlot at all to make plots.

Well, of course to start with, we’ll have to have something to plot. How about we start with a one-dimensional free-vibration response to a simple spring/mass/damper system? We’ll look at the case of an initial displacement of x_0 = 1 and an initial velocity of \dot{x}_0 = 0. (i.e. the case of pulling a damped spring from its neutral position and letting it go) Here’s the equation:

x(t)=e^{-\zeta \omega_n t}  \left\lbrace  x_0 cos{\sqrt{1-\zeta^2} \omega_n t} +  \frac{\dot{x}_0 + \zeta \omega_n x_0}{\sqrt{1-\zeta^2} \omega_n}  sin{\sqrt{1-\zeta^2} \omega_n t}  \right\rbrace
We should also remember that,
\omega_n=\sqrt{\frac{k}{m}}
And that,
\zeta=\frac{c}{c_c}= \frac{1}{2}\frac{c}{m \omega_n}

Ok, so translating that into a short octave script:

clear;clc;close all;

x0= 0.025; %m
v0= 0.000; %m/s
t = linspace(0,60,1000);
m = 1;     % kg
c = 0.1;   % N*sec/meter
k = 2.5;   % N/m

omega_n = sqrt(k/m)
zeta    = 0.5*c/m/omega_n

x = exp(-zeta*omega_n*t).*(x0*cos(sqrt(1-zeta^2)*omega_n*t) +...
       (v0+zeta*omega_n*x0)/sqrt(1-zeta^2)/omega_n*...
       (sin(sqrt(1-zeta^2)*omega_n*t)));

h=figure(1);
plot(t,x.*1000,'r-');
grid on;
title('Damped Response of a Single Degree of Freedom'...
      ' System to an Initial Excitation');
xlabel('Time (seconds)');
ylabel('Displacement (mm)');

Which produces the following plot:
Screenshot of Octave's standard plot output.

Now, taking a screenshot of the output of the plot command will get the job done if you need to look at something quickly, but it’s not what I would call a presentation-worthy output. What comes to the rescue here is the print command, which outputs a much nicer plot as a file (png, eps, etc.), which can be used elsewhere. Suppose we wanted to send the plot to “vib_plt.png”; the following command might do the job:


print(h,'-dpng','-color','vib_plt.png')

Notice how I grabbed the figure handle, h from the first bit of code? Also, I included the '-color' option because some file formats (eps) default to black and white. The above line of code generates the following png image:
Print Command Output - No Additional Formatting

Not bad, eh? Well, I’ve often felt that the lineweights were a bit light on the default output (especially for such a large plot). Also, the default image size (1,200px × 900px) is probably bigger than what you’re looking for. No fears! A couple more lines of code, and you’ll be making beautiful plots that fit your needs exactly. Firstly, let’s address that linewidth issue. To make the data really stand out (notice I’ve already changed the color to red), you might want to increase the thickness of the plotted line. That can be done easily enough right in the plot command:

plot(t,x.*1000,'r-','LineWidth',4);

Also, let’s try re-sizing the output a bit. The set command provies a solution. By setting the -PaperSize -PaperPosition in the appropriate -PaperUnits, we can scale the output to the correct size:

W = 4; H = 3;
set(h,'PaperUnits','inches')
set(h,'PaperOrientation','portrait');
set(h,'PaperSize',[H,W])
set(h,'PaperPosition',[0,0,W,H])

Which gives the following output:
Free Vibration Plot 2 - Resizing, Line Weight

Whoops! It looks like our title is too big for the resized image. Well, let’s try splitting it into two lines. Here’s where Octave may differ from Matlab a bit; you’ll want to switch to double-quotes around the title, and insert a newline character (\n), like this:

title(["Damped Response of a Single Degree of\n"...
      "Freedom System to an Initial Excitation"]);

While we’re at it, the default typewriter font that’s displayed by default isn’t my favorite, so let’s change it. This is a bit tricky, but a couple of commands and you’re good to go.

FN = findall(h,'-property','FontName');
set(FN,'FontName','/usr/share/fonts/dejavu/DejaVuSerifCondensed.ttf');
FS = findall(h,'-property','FontSize');
set(FS,'FontSize',8);

Which produces the following output:
Vibration Plot - Two-line title, font

Much better! Note that the TTF file location may be different on your machine, and you might want to choose a different font, after all. On a Linux computer, they’re easy enough to find. Try the command locate -i ttf from the Linux terminal command prompt to find the location of true-type fonts on your machine. There are some great tutorials around the internet describing how to find files in Linux. Also, note that we changed all of the fonts and font sizes at once. It is also possible to tweek the individual components. For example, if we want the title to be an italic font, we could change it using the following command:

title("Response of an Underdamped Single Degree of\n",...
      "Freedom System Subjected to an Initial Excitation",...
      'FontName',...
      '/usr/share/fonts/dejavu/DejaVuSerif-Italic.ttf',...
      'FontSize',8);

Be sure that you issue the above command only after you’ve set the global font parameters; setting the global parameters afterwords will override the command.

While we’re tweeking things, it may be a good idea to consider adding a legend to the plot. In this case, the legend seems like a good spot to display the input to the free-vibration equations above. Unfortunately, Octave legend formatting is somewhat difficult in Octave. In this case, where I’m using multiple lines within the legend, it was necessary to use fixed-width fonts to align everything. Octave can output multiple lines using the same trick that we used for the title. Try this:

L = legend(["x_0 = ", num2str(x0*1000,'%4.1f'), " mm    ",...
          "\nv_0 =  ", num2str(v0*1000,'%4.1f'), " mm/sec",...
          "\n  m =  ", num2str(m,'%4.1f'),       " kg    ",...
          "\n  c = ", num2str(c/1000,'%5.1e'),  " N-s/mm",...
          "\n  k = ", num2str(k/1000,'%5.1e'),  " N/mm  "])
FL1= findall(L,'-property','FontName');
FL2= findall(L,'-property','FontSize');
set(FL1,'FontName','/usr/share/fonts/msttcore/cour.ttf');
set(FL2,'FontSize',8);

Notice how I found the legend handles I was looking for using the findall command?

Well, if we put everything together, the code would look something like this:

clear;clc;close all;

x0= 0.025; %m
v0= 0.000; %m/s
t = linspace(0,60,1000);
m = 1;     % kg
c = 0.1;   % N*sec/meter
k = 2.5;   % N/m

omega_n = sqrt(k/m)
zeta    = 0.5*c/m/omega_n

x = exp(-zeta*omega_n*t).*(x0*cos(sqrt(1-zeta^2)*omega_n*t) +...
   (v0+zeta*omega_n*x0)/sqrt(1-zeta^2)/omega_n*...
   (sin(sqrt(1-zeta^2)*omega_n*t)));

h=figure(1);
plot(t,x.*1000,'r-','LineWidth',4);
grid on;
FN = findall(h,'-property','FontName');
set(FN,'FontName','/usr/share/fonts/dejavu/DejaVuSerifCondensed.ttf');
FS = findall(h,'-property','FontSize');
set(FS,'FontSize',6);
title(["Response of an Underdamped Single Degree of\n"...
      "Freedom System Subjected to an Initial Excitation"],...
      'FontName','/usr/share/fonts/dejavu/DejaVuSerif-Italic.ttf',...
      'FontSize',8);
xlabel('Time (seconds)','FontSize',8);
ylabel('Displacement (mm)','FontSize',8);
L = legend(["x_0 = ", num2str(x0*1000,'%4.1f'), " mm    ",...
          "\nv_0 =  ", num2str(v0*1000,'%4.1f'), " mm/sec",...
          "\n  m =  ", num2str(m,'%4.1f'),       " kg    ",...
          "\n  c = ", num2str(c/1000,'%5.1e'),  " N-s/mm",...
          "\n  k = ", num2str(k/1000,'%5.1e'),  " N/mm  "])
FL1= findall(L,'-property','FontName');
FL2= findall(L,'-property','FontSize');
set(FL1,'FontName','/usr/share/fonts/msttcore/cour.ttf');
set(FL2,'FontSize',8);
H = 3; W = 4;
set(h,'PaperUnits','inches')
set(h,'PaperOrientation','portrait');
set(h,'PaperSize',[H,W])
set(h,'PaperPosition',[0,0,W,H])
print(h,'-dpng','-color','vib_plt4.png');

Which produces a pretty nice plot:
Pretty nice vibration response plot

Now, something that is missing from plotting in Octave is the ability to insert LaTeX into the plot to display really nice equations. This can be done using the psfrag LaTeX package to strip out some dummy text added to the plot (as an EPS file). It’s a bit of a hack, but it produces nice outputs. You can find an example showing how to use psfrag here: Making plots using Octave, gnuplot, and LATEX.

Also, I’d like to add a word about file formats. If you’re using your plots in Microsoft Office products (MS PowerPoint, MS Word, etc.), you’ll probably have to stick with bitmap graphics (PNG), since Office doesn’t handle vector graphics well. However, if you’re using another program like Inkscape or Scribus to create slides, or LaTeX or AbiWord to create documents, you’ll find that vector formats like SVG or EPS will rescale much better. I’ve found that Octave/GNUPlot creates wonderful EPS plots. However, I’ve found their SVG engine messes up the fonts on me, so I create EPS plots in Octave and convert them to SVG plots in Inkscape when needed.

Edit:

A quick note: Inkscape does support the EMF format on Windows machines. If you have a Windows computer, EMF files are a great choice for MS Word and PowerPoint documents, since they are vector based and hence resolution independent. You may produce an EPS file and convert it to an EMF file using Inkscape, which produces good results and can even be done in batch mode. Octave also claims to have EMF support on Windows machines, but I haven’t tested it, so use it at your own risk. Happy plotting!

Advertisements
 
19 Comments

Posted by on October 7, 2011 in Free Software, Octave

 

Tags: , , , , , ,

19 responses to “Making Great Plots in Octave (and Matlab, too!)

  1. acl95

    October 13, 2013 at 9:49 pm

    Gracias!

     
  2. Mauro

    November 6, 2013 at 9:35 pm

    Thank you very much, very well explained! I apreciatte your effort doing this article

     
  3. Utsav

    January 17, 2014 at 3:06 pm

    Thankyou !! It’s a great learning resource , especially for beginners like me.

     
    • Chris

      March 21, 2014 at 5:39 pm

      I’m glad to hear that it helped you to learn. I find that once you have a good example, it’s much easier to build on it.

       
  4. andres

    May 1, 2014 at 1:51 pm

    Hi! i don’t know why, but the commands for changing the font of the plot does not work properly… It causes a lot of errors… wich version of octave are you using? Could be some missing package that I have not installed? thanks!!

     
    • Chris

      May 11, 2014 at 11:30 am

      One thing to check is whether you’re selecting the correct location for the font. If you’re using Linux, fonts are often located in the ‘/usr/share/fonts’ directory. In Windows, I think you might look in the ‘C:\Windows\Fonts’ directory. Suffice to say, you may have different fonts on your computer as well. Be sure to pick a font that you have installed on your machine.

       
  5. Chris

    May 15, 2014 at 2:02 am

    I can’t have the two-lined title on plot in the PNG output (I’m using GNU Octave 3.8.1).

     
    • Chris

      May 24, 2014 at 9:31 am

      Good catch. It looks like the Octave folks have updated their syntax to require brackets there. Actually, I think it’s cleaner that way. I’ve updated the post to reflect your comment. Thanks!

       
  6. mauricio

    March 25, 2015 at 12:59 pm

    Thanks for the post! Really clear and simply useful. Good Job!

     
  7. cyril mathew samuel

    May 29, 2015 at 11:45 pm

    How to write a legend , when im plotting several graphs with each in different color . I want the legend saying ; this color – this value …… how to write it ??

     
    • Chris

      November 11, 2015 at 6:18 pm

      When you plot a line, you can grab the handle from that line. You can then use the plot handles to populate your legend. For example:


      p1 = plot(cooltime, coolvariable, 'blue');
      p2 = plot(hottime, hotvariable, 'red');
      legend([p1, p2], 'This is cold', 'This is hot');

      Hope that helps!

       
  8. abe izar

    November 18, 2015 at 6:22 pm

    great post!
    i cant seem to be able to change the fontname.
    i located the actual font locations on my device, and replaced them in your code.
    i still get the default ugly font.

     
  9. ackwamurrine

    February 29, 2016 at 6:41 pm

    Is there a way to specify linewidth within the legend? I get really puny widths that make colors almost indistinguishable in the legend.

     
    • ackwamurrine

      February 29, 2016 at 6:44 pm

      Never mind, answered my own question, based on your code.

      L = legend(. . .);
      FL1 = findall(L, ‘-property’, ‘linewidth’);
      set(FL1, ‘linewidth’, 2);

      does the trick!

       
  10. vicente

    May 5, 2016 at 7:12 am

    Very useful article, a great reference overall. Thank you for your efforts! Never let this go offline!

     
  11. Simon

    June 5, 2016 at 11:37 pm

    awesome post, thanks a lot!

     
  12. luigi

    August 20, 2016 at 8:01 pm

    Your blog helped me a lot, thank you very much. But I want to know more.
    We have a common problem these days, all manuals are reference manuals, so if you know that some magic word exists, then you can manage to use it. But you do not know about the whole.
    I’m writing this in the hope that you know a good source to the “philosophy of use” of the graphical system of octave. Have you ever heard of any of these sources that you can suggest? If there exists a hierarchy of axes, figures, windows, etc. how to use it?

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: