Scientific Computing

Tid-bits, FAQs and How-To's designed to help students survive Graduate School, when the world of computers is against them.

Monday, September 23, 2013

Crash course on Gnuplot

Gnuplot may be my favorite program in the whole world.  Of all the graphs I've made (and every plot I've ever published) 95% of them have been made with gnuplot.  While I am starting to use Python's Matplotlib for more here and there, gnuplot is still my favorite.  It can be used for quick-and-dirty plots and spot checking of data, or the plots can be readily customized and beautified to publication quality.  This How-To will give you a basic working understanding on the program.  I write it because the gnuplot user guide isn't as useful as it could be (and because my favorite FAQ no longer is a webpage...).

Basics


Gnuplot can be run in instantaneous mode or run on a script describing the full plotting arguments.  The syntax is the same either way.  To start off with command line mode, run gnuplot from the console.  If you are on a reasonable system the terminal, or in other words the place where the plot is drawn/written, will be set up so that it will display the plot in a GUI.  Start off by plotting:

gnuplot> plot x**2, 20*sin(x)

Which will show the quadratic and a sine function:
The ** is a funny syntax that means raise x to the power of y.  This is a pretty simple example, and rather arbitrary; but a number of functions can be used and most of the standard functions can be used.  In addition, functions can be defined:

gnuplot> f(x)=ax+b
gnuplot> a=1.5; b=5
gnuplot> set grid
gnuplot> plot f(x)

Which gives the plot:

Here I also used the "set grid" command to turn on the background grid.  The basic syntax is "set option <attributes>" where the option in this case is grid and there are no attributes (there and be a list of attributes after the option).

Of course, the program wouldn't be useful unless you could plot data from experiments and also fit datasets to functions.  Take for example trying to fit an exponential to the decay of a reactant you might see in a first-order reaction: A-->2B.  As an example, I'll use the datafile (in gnuplot comments in datafiles begin with a # symbol):

# t (s)  A (M)  Error (M)
0  3     0.001
1  2.3   0.05
2  1.55  0.05
3  1.22  0.03
4  0.99  0.04
5  0.65  0.02
10 0.145 0.08

We can write a function and fit it to the data:

gnuplot> f(x)=A*exp(-x/tau)
gnuplot> fit f(x) 'datafile.dat' via A, tau
gnuplot> set xlabel "Time (s)"
gnuplot> set ylabel "Concentration (M)"
gnuplot> plot 'datafile.dat' using 1:2:3 with yerrorbars t "Points", '' using 1:2 w l t "Lines", f(x) t "Fit"
gnuplot> set xrange [-0.5:10.5]
gnuplot> replot


The fitting procedure gives parameters of the fit and the certainty of the value:

Final set of parameters            Asymptotic Standard Error
=======================            ==========================

A               = 3.0108           +/- 0.05894      (1.957%)
tau             = 3.33788          +/- 0.1288       (3.858%)

Which gives the plot:

Now this last example was a bit more like what you may want to do.  I'll take you through it step by step.  We used the "set" command to specify the text for the labels.  In addition to the xlabel and ylabel, you can set the title and a number of other "labels".  Next we plot three different things: 1) the points in the datafile with error bars based on the third column (the first two are x and y), 2) a line connecting the data points and 3) the fit to the data.  After that, I realized that I wanted to change the range of the x-axis so I defined a range from -0.5 to 10.5, and then I issued the "replot" command which executes the last "plot" command exactly. Now we are getting somewhere!

However, as you may have noticed that the plots that I have created so far kinda look crappy.  This is because I used basic parameters and printed to the "png" terminal.  To make a slightly prettier plot, we can edit each piece/attribute independently and print to a better file format.  Taking the last example one step further and I'll be plotting the product B concentration.  This time I used a file with the list of commands written out.  This is a nice way to specify a reproducible plot command and also simplifies the process of making a nice graph when we get quite a few commands.  It was plotted with the command gnuplot plotfile.gp, where plotfile.gp looks like:

# Define functions that fit the data
fA(x)=A*exp(-x/tau)
fit fA(x) 'datafile.dat' via A, tau

# Set up the axes for the right sid
set xlabel "Time (s)"
set xrange [-0.5:10.5]
set ylabel "Concentration of A (M)"
set yrange [0:3.5]

# Set up the Y-axis on the right side
set y2label "Concentration of B (M)"
set y2tics
set y2range [0:7]

# Make the points bigger
set pointsize 1.75

# Define where the legend is (i.e. below the plot)
set key below

# Set up file to plot to, make it a postscript file with
#  a pretty print (enhanced option) with and Arial font
#  at 16 points size.  Specify the file name to be
#  concentrations.ps
set terminal postscript color enhanced "Arial" 16
set output 'concentrations.ps'

# Here, "axis x1y2" means the x is the bottom scale and the y
#  is on the right side.  "yerrorbars" means that the third
#  column is the error bar spread.  Similarly, one could
#  use the xerrobars.  "pt" sets the point shape and the "lw"
#  option specifies how thick the lines are.
plot 'datafile.dat' using 1:2 w p t "Average A" pt 7 ,\
     'datafile.dat' using 1:2:3 w yerrorbars t "{/Symbol s}_A" pt 3 lw 3,\
     fA(x) t "Fit A" lw 3,\
     'datafile2.dat' using 1:2:3 w yerrorbars axis x1y2 t "Average and {/Symbol s} of B" pt 5 lw 3

I've included comments (that begin with the # character) so I don't have to describe each command here.  Another thing that was demonstrated was how to plot greek symbols.  You can see the that {/Symbol s} makes a σ, which can only be plotted if you use the "enhanced" option with the postscript terminal.  The greek symbols are indicated by the letter that most closely matches their sound, and a full list (along with a few other symbols) can be found here. The result (converted to a png using another program) looks like:

The terminal can be set to many different output types, you can plot jpegs, pngs, postscript, encapsulated postscript, pdfs, etc.  Virtually any font the system has can be used and any label can be customized with a font or a fontsize all by itself.  In addition, the two x- and y-axes can have different plots to them, for example: axis x1y2, axis x2y1 and axis x2y2.  

Plotting multiple images in the same file is very useful.  The origin for the coordinate system is the bottom left, the same as a standard coordinate system.  A normalized unit system is used, with the 1,1 being the top right.  Schematically this looks like:

Sizes of the subplots are also normalized numbers.  For example you can plot two functions, one on top of the other like:

# Turn on the multiplot capabilities 
set multiplot
set origin 0,0
set size 1,0.5
plot x
set origin 0,0.5
plot x*x

Which creates the following plot:

Note, however, that you need to specify the terminal and the output file before you do any plotting, or before you even specify that multiplot should be used.  I think multiplotting from the gnuplot terminal is practically useless and only really use a plotfile myself.  The multiplot easily allows plotting three plots, one on top of the other and one on the side, such as:
Which was created with:

set terminal postscript color enhanced "Arial" 16
set output 'trip.ps'

set multiplot
# Plot the first
set origin 0,0
set size 0.5,0.5
set xlabel "X Label"
set ylabel "Y Label1"
plot x
# Plot the second with the same x label
set origin 0.0,0.5
unset xlabel
set ylabel "Y Label1"
# Note for math fuctions, integer vs
#  floating point arithmatic (3/2=1 vs 3.0/2.0=1.5)
plot x**(3.0/2.0) t "x^{3/2}"

# Plot the third
set xlabel "X Label"
set ylabel "Y Label2"
set size 0.5,1.0
set origin 0.5,0.0
plot x**2 t "x^2"

More Fun



Now that I've covered the main functionality of gnuplot, I'd like to show you a few other cool things you can do.  I often plot histograms:

# Define a function that calculates which bin 
#  the x value should be in
binwidth=0.05   # width of the bin
bin(x,width)=width*floor(x/width) + binwidth/2.0

# Pretty the plot
set xrange [-1:1.5]
set key below

# Call the bin function on the first column: $1
plot 'histDat.dat' using (bin($1,binwidth)):(1.0) smooth freq with boxes t "Gaussian: <x>=0.2, {/Symbol s}=0.2"


This creates a plot that looks like:
A few things that you should notice is that you can call any function on the column of a file.  For example, with the same distribution I could call plot 'histDat.dat' using 1:(f($1)), which would apply the function f(x) to all the values in the x range.  You can customize the bars in a number off different ways: fill with patterns, solid colors, etc.  

Plotting a 2D surface plot can easily be accomplished using the splot command instead of plot which can plot 2D functions or a file with three columns.  If you use the file you need to separate each line individual line by a blank line.  Usually, I use a heatmap to show the height, instead of the wireframe; its more descriptive.  Going back to our previous example of the gaussian function:

# Define functions and ranges
f(x,y)=1/sqrt(3.14)*exp(-(x**2+y**2))
set xrange [-3:3]
set yrange [-3:3]

# Set the plot to show height with color
set pm3d
# Set the number of boxes to divide the function into
set isosample 500, 500
# Plot
plot f(x,y) with pm3d

Which makes a nice plot:
Also, it is nice to see the contours for a surface plot drawn on the base of the 3D plot sometimes:

# Define a function
f(x,y)=x**2*cos(2*x+0.5*y)

# Set the contour line levels
set cntrparam level incremental 0,2,20
set isosample 25,25

set xrange [-5:5]
set yrange [-5:5]
# Turn off the legend so we don't
#  see all the multitude of contour
#  lines
unset key   

splot f(x,y)

Making the plot:

Well those are about the best of the basics; we have barely scratched the surface.  You can do pretty much anything you can do with Excel--gradients, bar graphs, backgrounds, surfaces, pie charts, ribbon charts--plus quite a few other things.  There are a number of great tutorials that are a bit more full featured, such as this one by Zoltán Vörös, which is one of the more imaginative and unique tutorials online

No comments:

Post a Comment