Computational Physics, 1B

Examples of using gnuplot


You can download all the files in a single zip file.


1: Plotting functions and making movies

In this example we plot a sin wave,
f(x) = sin(kx-wt)
and increase the value of t, replotting. We then add up multiple sin waves, with different values of wavenumber k and frequency w, and plot the sum for steadily increasing values of t.
The first example just plots one sinusoid. Run it using
load 'gnu.wave'
from within gnuplot.
#### gnu.wave ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )

set xrange [-10:10]

plot f(x) with lines lt 4

pause -1 'ready?' 

 t = 3.1
 replot
The next example plots two sinusoids and their sum.
load 'gnu.wave2'
#### gnu.wave2 ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.2 

set xrange [-10:10]

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x) w l lt 7

pause -1 'ready?' 

 t = 3.1
 replot
The next example shows how to make a movie by using load 'gnu.wave4' to recursively carry out functions that increment t and replot. You should run this command -
load 'gnu.wave3'
#### gnu.wave3 ####
k = 1
w = 2

t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.2 

set xrange [-10:10]

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x) w l lt 7

 load 'gnu.wave4'
# use ?load and ?call to get more information about load and call
- noting that that file loads this one, which then loads itself again...
It loads itself forever, so you will need to hit Ctrl-C to stop it.
[Some window-managers have the annoying feature that by default whenever a fresh plot happens in gnuplot, the window manager gives focus to the gnuplot window; this default behaviour can be disabled. I like to have focus follow the mouse.]
#### gnu.wave4 #### (loaded by gnu.wave3)

pause -1 'ready?' 

 t = t + 0.1

 replot
 load 'gnu.wave4'
 
The next example rectifies the problem of the never-ending movie by loading gnu.wave6 which contains an if before its load command. Run this example using
load 'gnu.wave5'
#### gnu.wave5 ####
k = 1
w = 2

t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.2 

set xrange [-100:100]

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x) w l lt 7

 load 'gnu.wave6'
# use ?load and ?call to get more information about load and call

 
 
This file, gnu.wave6, is used by all the remaining examples.
#### gnu.wave6 ####
pause 0.1

 t = t + 0.4

 replot
if (t<100) load 'gnu.wave6'
 
You'll probably find that the previous example, gnu.wave5, which increased the xrange of the plot, produced a pretty lousy-looking plot, which didn't look like pictures of sinusoids any more. The problem was that the sinusoid has too many wiggles compared with the default number of samples. We fix this problem by cranking up the number of samples. This file, gnu.wave7, shows how.
#### gnu.wave7 ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.2 

set xrange [-100:100]
set samples 1000

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x)+3 w l lt 7

 load 'gnu.wave6'
# use ?load and ?call to get more information about load and call
In these files, gnu.wave8 and gnu.wave9, we play around with the value of w2 a little, seeing the effect of changing the dispersion relation.
#### gnu.wave8 ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.1 

unset mouse; ## disables the lower-left display of (x,y) coordinates

set xrange [-100:100]
set samples 500

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x)+3 w l lt 7

 load 'gnu.wave6'
# use ?load and ?call to get more information about load and call

#### gnu.wave9 ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )

k2 = 1.1 
w2 = 2.3 

unset mouse; ## disables the lower-left display of (x,y) coordinates

set xrange [-100:100]
set samples 500

 plot f(x) w l lt 6, g(x) w l lt 1, f(x)+g(x)+3 w l lt 7

 load 'gnu.wave6'
# use ?load and ?call to get more information about load and call
This file, gnu.wave10, goes the whole hog, adding up five sinusoids. Physicists may find it instructive to play with the definition of the parameter dwdk.
#### gnu.wave10 ####
k = 1
w = 2
t = 3

f(x) =  sin( k * x - w * t )
g(x) =  sin( k2 * x - w2 * t )
h(x) =  sin( k3 * x - w3 * t )
i(x) =  sin( k4 * x - w4 * t )
j(x) =  sin( k5 * x - w5 * t )

dk = 0.05
k2 = k+dk
k3 = k2+dk
k4 = k3+dk
k5 = k4+dk
dwdk = 0.5*w/k
w2 = w  + dk * dwdk
w3 = w2 + dk * dwdk
w4 = w3 + dk * dwdk
w5 = w4 + dk * dwdk

s(x) = 0.45*f(x)+g(x)+1.3*h(x)+i(x)+0.45*j(x)

unset mouse; ## disables the lower-left display of (x,y) coordinates

set xrange [-100:100]
set samples 500

plot f(x) w l lt 6, g(x) w l lt 1, h(x) w l lt 2,i(x) w l lt 3,j(x) w l lt 4, \
 s(x)+5 w l lt 5

 load 'gnu.wave6'
# use ?load and ?call to get more information about load and call
wave10


2: Using gnuplot to fit fairly complicated functions to data

gnuplot has a function called fit which can fit parameterized functions to data files by twiddling whichever parameters you choose.
The objective function that is minimized by the fitting process is the sum of squares of residuals. [The residuals are the differences between the functions and the data points.] This is the standard objective function, widely used in data-fitting, but do be careful to think whether it is an appropriate objective function. It's appropriate, for example, if you wish to model the residuals as coming independently and identically distributed from a gaussian distribution.
fit is a pretty neat function. Its syntax is similar to the plot syntax.
For this section, there are two data fails necessary to run the examples: 2006/Year and 2006/YearTd.
This first file, gnu.fit1, simply plots two data files, one of which contains half-hourly temperature data, and one daily averages of temperatures. It also plots a function
f(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B,
a sinusoid with period 365 days, whose parameters A, o, and B are set to arbitrary values - i.e., the function hasn't been fitted. The syntax of the plot command works like this:
plot '2006/Year' u ($0/48.0):($2) w l lt 6 ,\
 '2006/YearTd' u ($1-0.5):($2) w  l lt 8,\
 f(x)
  1. First line - u ($0/48.0):($2) means plot the line number ($0), divided by 48, on the x axis, and plot column 2 ($2) on the y axis. This line would work the same if it said u ($0/48.0):2. (There are 48 half-hours per day.)
  2. Second line - daily file - u ($1-0.5):($2) means take the number in column 1 (which is the day number), subtract 0.5 from it, and put that on the x-axis. Put the 2nd column on the y axis.
#### gnu.fit1 ####
# Cambridge Temperature data 
# - we'd like to fit temperature with a sinusoid
 set autoscale xy
 set samples 1650
 set noxtics
 set nokey

load 'gnu.months'

set yrange [-10:35]

f(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B

A=10 ; # Amplitude of sinusoidal variation
B=15 ; # Mean temperature
o=50 ; # origin of sinusoid

plot '2006/Year' u ($0/48.0):($2) w l lt 6 ,\
 '2006/YearTd' u ($1-0.5):($2) w l lt 8,\
 f(x)

#### gnu.months ####
 h= -12.065
 x = 7.5
set label 1 'Jan' at x,h
set label 2 'Feb' at x+31,h
set label 3 'Mar' at x+31+28,h
set label 4 'Apr' at x+31+28+31,h
set label 5 'May' at x+31+28+31+30,h
set label 6 'Jun' at x+31+28+31+30+31,h
set label 7 'Jul' at x+31+28+31+30+31+30,h
set label 8 'Aug' at x+31+28+31+30+31+30+31,h
set label 9 'Sep' at x+31+28+31+30+31+30+31+31,h
set label 10 'Oct' at x+31+28+31+30+31+30+31+31+30,h
set label 11 'Nov' at x+31+28+31+30+31+30+31+31+30+31,h
set label 12 'Dec' at x+31+28+31+30+31+30+31+31+30+31+30,h
fit1
The second file, gnu.fit2, plots the data files and f(x) as before, then runs the function
  
fit  f(x) '2006/YearTd'  u ($1-0.5):2 via A,o,B
so as to fit the function f(x) to the average daily data. Note that the syntax of the "u" (using) part is the same as used in the plot. The words via A,o,B instruct the fit function to vary those three parameters so as to optimize the fit of the function f(x) to the specified data.
If all is well, this fit function will come up with a good setting of the parameters, report them with error bars and a correlation matrix, the stop; the next command in the gnuplot file replots the function so you can see how it fits.
#### gnu.fit2 ####
# Cambridge Temperature data 
# - we'd like to fit temperature with a sinusoid
 set autoscale xy
 set samples 100
 set noxtics
 set nokey

load 'gnu.months'

set yrange [-10:35]

f(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B

A=10 ; # Amplitude of sinusoidal variation
B=15 ; # Mean temperature
o=50 ; # origin of sinusoid

plot '2006/Year' u ($0/48.0):($2) w l lt 6 ,\
 '2006/YearTd' u ($1-0.5):($2) w l lt 8,\
 f(x)

 pause -1 " ready to fit f(x)? "
 fit  f(x) '2006/YearTd'  u ($1-0.5):2 via A,o,B

 pause -1 ' ready to replot? '
 replot
 
fit2
gnu.fit3 fits a more complicated model to the half-hourly data - the temperature is modelled as the sum of two sinusoids, one with period one day, and one (as before) with period one year. Here the plot of the function is a fancy 'multiplot' with three parts. To avoid writing everything twice, the details of the plot command are popped into another file, gnu.showTempg, which is loaded whenever we want to make the three-part plot.
#### gnu.fit3 ####
# fit temperature with sums of complicated sinusoids

 set autoscale xy
 set samples 1650
 set noxtics
 set nokey

load 'gnu.months'
set yrange [-10:35]

#        Annual                  + Constant + Daily 
g(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B+  AA*sin( 2*pi* (x-oo) / 1.0 ) 

A=8.336 ; # Amplitude of ANNUAL sinusoidal variation
B=11.47 ; # Mean temperature
o=119.5 ; # origin of sinusoid
AA              = 2.5       ; # DAILY variation amplitude
oo              = 0.3       ; #  and origin

# this plots the data and function on 3 plots
load 'gnu.showTempg'

pause -1 ' ready to fit? '
set autos x ; # crucial to reset the xrange!
     
 fit  g(x) '2006/Year'  u ($0/48.0):2 via AA,oo

load 'gnu.showTempg'

#### gnu.showTempg ####
#### shows the temperature data and the function g(x) in three plots
set multiplot
set size 0.8,0.4 ; set origin 0.1,0.1
set autos x
plot '2006/Year' u ($0/48.0):($2) w l lt 6 ,\
     '2006/YearTd' u ($1-0.5):($2) w l lt 8,\
     g(x) w l lt 3
set xrange [125:135]
set origin 0.55,0.55 ; set size 0.4,0.4
replot
set xrange [5:15]
set origin 0.1,0.55 ; set size 0.4,0.4
replot
unset multiplot
set size 0.8,0.8
set origin 0.1,0.1
set autos x

fit3

gnu.fit4 shows off fit's capabilities by fitting a more complicated model, in which the daily sinusoid has an amplitude that itself varies sinusoidally with a period of one year.

To find out more about fit, use ?fit

#### gnu.fit4 ####
# fit temperature with sums of complicated sinusoids

 set autoscale xy
 set samples 1650
 set noxtics
 set nokey

load 'gnu.months'
set yrange [-10:35]

# let the Daily amplitude vary with time of year
AAA(x) = AA+AAAA*sin( 2*pi* (x-oooo) / 365.0 )

AA   = 3 ;  # average Daily amplitude
AAAA = 1 ;  # change in amplitude
oooo = 100 ; # origin of these variations in daily amplitude

# was:
# g(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B+  AA*sin( 2*pi* (x-oo) / 1.0 ) 
# now:
#        Annual                  + Constant + Daily 
g(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B+  AAA(x)*sin( 2*pi* (x-oo) / 1.0 ) 

A=8.336 ; # Amplitude of ANNUAL sinusoidal variation
B=11.47 ; # Mean temperature
o=119.5 ; # origin of sinusoid
oo              = 0.3       ; #  and origin

# this plots the data and function on 3 plots
load 'gnu.showTempg'

pause -1 ' ready to fit? '
set autos x ; # crucial to reset the xrange!
     
 fit  g(x) '2006/Year'  u ($0/48.0):2 via AA,oo,AAAA,oooo

load 'gnu.showTempg'

pause -1 'ready?'

set mouse
replot

pause -1 'ready?'
set autos xy

f(x) = A*sin( 2*pi* (x-o) / 365.0 ) + B
plot '2006/Year' u ($0/48.0):($2) w l lt 6 ,\
 '2006/YearTd' u ($1-0.5):($2) w l lt 8,\
 f(x) w l lt 4, f(x)+AAA(x) w l lt 3, f(x)-AAA(x) w l lt 3
 

fit4a
fit4b


3: Making movies from datafiles

If you have a load of points in datafiles and want to make a movie, there are two ways with gnuplot.
  1. You can put the points into separate datafiles, one file for each plot, and use the
    load 'blah'
    method that we used before in the first example on this page. [Or if you want to be able to pass arguments when using load, you can use call 'blah' arg1 arg2 arg3 instead.]
  2. Alternatively, with all the points sitting in just one datafile, you can use gnuplot's "every" feature to pluck out the lines you want.
The simplest example of every is
 plot 'datafile' every 10 using 3:5
which plots every 10th line in 'datafile', showing column 3 on the x axis and 5 on the y axis. Use ?every to find out the fancier things you can do with every Note that gnuplot calls the top line of a file line zero, not line one.


The example shown here [run it using load 'gnuC02' ] shows a spaceman and his hammer orbitting the earth. The spaceman is in circular orbit. The spaceman has just given his hammer a kick directly away from the earth.
orbitV This figure shows the circular orbit of the man, his current velocity (magenta), and the velocity of the hammer immediately post-kick (brown).
## Make movies from data files, using "load" and "every"
## gnuC02
set size ratio -1
set nokey
r = 2 ; r2= 2
set xrange [-r:r2]
set yrange [-r:r2]
## set up some plotting styles -- not essential! --
set termoption dashed
set style line 4 ps 6 lt 4 pt 7 ;## for plotting a nice big earth/sun
set style line 5 lt 5 lw 0.3 ;   ## narrow lines
set style line 2 lt 2 lw 0.3 ;   ## narrow lines
set style arrow 1 size 0.125,30   lt 7 ; ## styles for hefty arrows
set style arrow 2 size 0.125,30   lt 2 ; ## (big heads)
set style arrow 3 size 0.125,30   lt 1 ; ##
set pointsize 2.5

### set up the plot for this movie
t=0;   ## start at line zero
dt=7; ## step through lines by this much
T=500; ## go until this line reached
## Plot each object, and the trail of where it has been.
plot 'planet/sun' w p ls 4 , \
 'planet/1' every 1::t::t u (-$3):2 w p ps 5 pt 7,\
 'planet/2' every 1::t::t u (-$3):2 w p ps 2 pt 7,\
 'planet/1' every 10::0::t u (-$3):2 w l ls  5 ,\
 'planet/2' every 10::0::t u (-$3):2 w l ls  2
## (I negate the coordinate in column 3 to make the picture
##  agree with the diagram in the lecture notes)

load 'gnuC11'

## gnuC11 ##
pause 0.02
t=t+dt
replot
if (t+dt<=T) load 'gnuC11'


4: Making histograms

There are several ways to make histograms. For example, you could pop your data into a spreadsheet and use its built-in histogram function. However there is a sneaky way to do the histogram entirely within gnuplot.
To adapt this trick to your problem, change the datafile 'dat' to your data file; change the $1 to point to the correct column number (eg, $2 for column 2); choose the bin_width you want. This example assumes the data is in a file called dat.
gnuHisto
# Making histograms within gnuplot - 
# cunning trick using gnuplot's "smooth frequency"
#
# method 1:
#
# to make a histogram with vertical axis equal to the count
# in a bin:
#
bin_width = 0.3; ## edit this 
bin_number(x) = floor(x/bin_width)
rounded(x) = bin_width * ( bin_number(x) + 0.5 )
UNITY = 1
## column number of data to be histogrammed is here assumed to be 1
## - change $1 to another column if desired
plot 'dat' u (rounded($1)):(UNITY) t 'data' smooth frequency w histeps

pause -1 'ready'
#
# method 2:
#
# to make a histogram with *area* of a bin equal to the count
# in a bin, so the area under the curve is the number of data:
#
bin_width = 0.3
bin_number(x) = floor(x/bin_width)
rounded(x) = bin_width * ( bin_number(x) + 0.5 )
UNITY = 1
plot 'dat' u (rounded($1)):(UNITY/bin_width) t 'data' smooth frequency w histeps

pause -1 'ready'
#
# method 2, second example, which illustrates why you might sometimes
# prefer method 2 to method 1 (namely, to make it possible to
# superpose two histograms of the same data):
#
bin_width = 0.3
bin_number(x) = floor(x/bin_width)
rounded(x) = bin_width * ( bin_number(x) + 0.5 )
bin_width2 = 1.0
bin_number2(x) = floor(x/bin_width2)
rounded2(x) = bin_width2 * ( bin_number2(x) + 0.5 )
UNITY = 1
plot 'dat' u (rounded($1)):(UNITY/bin_width) t 'width 0.3' smooth frequency w histeps,\
  'dat' u (rounded2($1)):(UNITY/bin_width2) t 'width 1' smooth frequency w histeps lt 3


David MacKay
Last modified: Wed Nov 14 10:11:32 2007