RSS

Tag Archives: octave

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

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: , , , , , ,