Gnuplotting

Create scientific plots using gnuplot

January 31st, 2014 | 3 Comments

And another plot of the world. This time we are dealing with the raster data from Natural Earth. This data is normally available as tif-files. To use them in gnuplot we have to convert them first, then we can create a plot as shown in Fig. 1.

Cross-blended Hypsometric Tints

Fig. 1 Cross-blended hypsometric tint plot of the world. (code to produce this figure, data)

The conversion is done by the convert_natural_earth script. There the tif-file is first scaled down to the desired resolution using imagemagick. Afterwards it is converted to a text file and reordered for the splot command of gnuplot. The text file includes the longitude, latitude and three rgb color values.
You have to invoke the script in the following way.

$ ./convert_natural_earth $RES $FILE

where $RES is the desired resolution in pixel of your gnuplot plot and $FILE the input tif-file.
After finished we can plot the resulting text file simply by

set datafile separator ','
set size ratio -1
plot 'HYP_50M_SR_W_350px.txt' w rgbimage

which results in Fig. 1.

Natural Earth II Shaded Relief and Water

Fig. 2 Natural Earth II shaded relief and water plot of the world. (code to produce this figure, data)

The image can also be projected on a 3D figure of the world as shown in Fig. 2. To achieve this the three rgb values have to be summarized in one value and the rgb variable line color option has to be chosen together with pm3d.

rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)
set mapping spherical
set angles degrees
splot 'NE2_50M_SR_W_700px.txt' u 1:2:(1):(rgb($3,$4,$5)) w pm3d lc rgb variable

December 21st, 2013 | 2 Comments

After plotting the world several times we will concentrate on a smaller level this time. Ben Johnson was so kind to convert the part dealing with the USA of the 10m states and provinces data set from natural earth to something useful for gnuplot. The result is stored in the file usa.txt.

USA election

Fig. 1 Election results of single U.S. states. (code to produce this figure, USA data, election data)

Two double lines divide the single states. This allows us to plot a single state with the help of the index command. At the end of this post the corresponding index numbers for every state are listed.
In addition to the state border data we have another file that includes results from an example election and strings with the names of the states. The election result can be 1 or 2 – corresponding to blue and red. With the help of these two data sets we are able to create Fig. 1 and Fig. 2.
For drawing a single state in red or blue we first collect the results for every single state in the string variable ELEC. The stats command is suitable for this, because it parses all the data but doesn’t try to plot any of them. During the parsing of every line the election result stored in the second column will be added at the end of the ELEC variable.

ELEC=''
stats 'election.txt' u 1:(ELEC = ELEC.sprintf('%i',$2))

In a second step we plot the state borders and color the states with the help of the ELECstring. ELEC[1:1] will return the election result for the state with the index 0.

plot for [idx=0:48] 'usa.txt' i idx u 2:1 w filledcurves ls ELEC[idx+1:idx+1],\
                    ''              u 2:1 w l ls 3

Alaska and Hawaii are then added with additional plot commands and the help of multiplot.

The data file with the election results includes also the names of the single states and a coordinates to place them. This allows us to put them in the map as well, as you can see in Fig. 2.

USA election

Fig. 2 Names and election results of single U.S. states. (code to produce this figure, USA data, election data)

The plotting of the state names is easily achieved by the labels plotting style:

plot for [idx=0:48] 'usa.txt' i idx u 2:1 w filledcurves ls ELEC[idx+1:idx+1],\
                    ''              u 2:1 w l ls 3,\
                    'election.txt'  u 6:5:3 w labels tc ls 3

At the end we provide the list with the index numbers and the corresponding states. If you want to plot a subset of states – as in Fig. 2 – you should adjust the xrange and yrange values accordingly.

0  Massachusetts
1  Minnesota
2  Montana
3  North Dakota
4  Idaho
5  Washington
6  Arizona
7  California
8  Colorado
9  Nevada
10 New Mexico
11 Oregon
12 Utah
13 Wyoming
14 Arkansas
15 Iowa
16 Kansas
17 Missouri
18 Nebraska
19 Oklahoma
20 South Dakota
21 Louisiana
22 Texas
23 Connecticut
24 New Hampshire
25 Rhode Island
26 Vermont
27 Alabama
28 Florida
29 Georgia
30 Mississippi
31 South Carolina
32 Illinois
33 Indiana
34 Kentucky
35 North Carolina
36 Ohio
37 Tennessee
38 Virginia
39 Wisconsin
40 West Virginia
41 Delaware
42 District of Columbia
43 Maryland
44 New Jersey
45 New York
46 Pennsylvania
47 Maine
48 Michigan
49 Hawaii
50 Alaska

October 24th, 2013 | 4 Comments

If you want to put labels into a graph using the epslatex terminal you are probably interested in using a smaller font for these labes than for the rest of the figure. An example is presented in Fig. 1.

Photo density flux

Fig. 1 Photon flux density for different characteristic tail state energies E0 dependent on the photon energy. (code to produce this figure, data)

Figure 1 shows again the photon flux density from one of the last posts, but this time plotted with the epslatex terminal. The label size is changed by setting it to \footnotesize with the following code. First we introduce a abbreviation for the font size by adding a command definition to the header of our latex file.

set terminal epslatex size 9cm,7cm color colortext standalone header \
   "\\newcommand{\\ft}[0]{\\footnotesize}"

After the definition of the abbreviation we can use it for every label we are interested in.

set label 2 '\ft $5$\,meV'         at 1.38,4e9     rotate by  78.5 center tc ls 1
set label 3 '\ft $10$\,meV'        at 1.24,2e10    rotate by  71.8 center tc ls 2
set label 4 '\ft $20$\,meV'        at 1.01,9e11    rotate by  58.0 center tc ls 3
set label 5 '\ft $40$\,meV'        at 0.81,1e15    rotate by  43.0 center tc ls 4
set label 6 '\ft $60$\,meV'        at 0.76,9e16    rotate by  33.0 center tc ls 5
set label 7 '\ft $80$\,meV'        at 0.74,2.5e18  rotate by  22.0 center tc ls 6
set label 8 '\ft $E_0 = 100$\,meV' at 1.46,5e18    rotate by -40.5 center tc ls 7

August 22nd, 2013 | 30 Comments

On the PGF plots page I found a nice example of visualizing data with cubes. Here we will recreate the same with gnuplot as you can see in Fig. 1.

Cubes

Fig. 1 Cubes with different colors. (code to produce this figure, cube function, data)

We need basically two things in order to achieve it. First we have to plot a single cube with gnuplot. This is not as straight forward as you may think. We have to define a data file for it and plot it with the pm3d style which will result in Fig. 2.

# single cube
0 0 0
0 0 1
0 1 1
0 1 0
0 0 0

1 0 0
1 0 1
1 1 1
1 1 0
1 0 0

0 0 0
1 0 0
1 1 0
0 1 0
0 0 0

0 0 1
1 0 1
1 1 1
0 1 1
0 0 1
set cbrange [0.9:1]
set palette defined (1 '#ce4c7d')
set style line 1 lc rgb '#b90046' lt 1 lw 0.5
set pm3d depthorder hidden3d
set pm3d implicit
unset hidden3d
splot 'cube.txt' u 1:2:3:(1) w l ls 1

The use of the fourth (1) column for the splot command ensures that the cube gets the same color on every side. Only the edges are highlighted by a slighty different color given by the line style.

A single cube

Fig. 2 A single cube. (code to produce this figure, data)

In a second step we reuse the code from the Object placement using a data file entry in order to plot cubes at different positions with different colors. To get the different colors and positions we replace the cube.txt file with a cube function that returns the values for the desired position and color.

add_cube(x,y,z,c) = sprintf('cube(%f,%f,%f,%i) w l ls %i,',x,y,z,c,c)
CMD = ''
stats 'cube_positions.txt' u 1:(CMD = CMD.add_cube($1,$2,$3,$4)) nooutput
CMD = 'splot '.CMD.'1/0 w l ls 2'
eval(CMD)

July 30th, 2013 | 1 Comment

If you have more than one line or data set in your figure, they has to be named somehow. I’m not a big fan of a legend but prefer to put the names directly to the corresponding curves. That makes it easier for the reader. But as an author of the figure you have to find space to place the labels in the figure, and it could be that you have to rotate the labels to stick them to the lines.

Photo density flux

Fig. 1 Photon flux density for different characteristic tail state energies E0 dependent on the photon energy. (code to produce this figure, data)

Figure 1 shows the theoretical curves of photon flux density dependent on the photon energy for different characteristic tail state energies E0. E0 is an indicator for disorder in a crystalline system. To reduce the amount of trail and error for placing the E0 labels, we get the rotation directly from the data by fitting a linear function to the corresponding part of the data.

It is a little bit tricky, because we have a logarithmic y-axis. This can be handled by applying the logarithm to the y data by log($2) and than do the linear fiting.

f(x) = a*x+b
fit [1.30:1.34] [*:*] f(x) 'PL_spectrum_mu_1.0eV_E0_05meV_300K.dat' \
    u 1:(log($2)) via a,b

The first bracket is the range on the x-axis and the second sets the corresponding y range to auto. After we have the value of the slope we convert it to a rotation in degree with the r() function and set our label.

set label 2 '5 meV' at 1.38,4e9 rotate by r(a) center tc ls 1

The conversion to rotation is the most tricky part, because it depends on the range of your axes and the ratio between them. it would be trivial if both axes would go from, for example 1:10 and are equal in length in the figure. Otherwise we have to correct for the ranges and ratio.

# get the relation of x- and y-range
dx = xmax-xmin
dy = log(ymax)-log(ymin)
s1 = dx/dy
# get ratio of axes
s2 = 5/6.7
# helper function for getting the rotation angle of the labels in degree
deg(x) = x/pi*180.0
r(x) = deg(atan(s1*s2*x))

June 21st, 2013 | 7 Comments

Sometimes a classical heat map will not be the best way to visualize your data in a two dimensional plane. This is especially the case, when only a few data points on the plane have different values. For example in Fig. 1 you find a projection from one vector to another to visualize its similarity. This is a method used in normal mode analysis of molecules to determine if two different
calculations yield similar results. As you can see only the data points near the diagonal vary, which is hard to see because of the small size of the points. In addition, points farer away from the diagonal having a small percentage value are more or less invisible – compare to Fig. 2.

Sparse data with image plot style

Fig. 1 Vector dot product expressed in percentage plotted with the image style (code to produce this figure, data)

In order to emphasize the data, we abounded the image plot style and use transparent circles as plotting style for visualizing the data as shown in Fig. 2.

Sparse data with circles plot style

Fig. 2 Vector dot product expressed in percentage plotted with the circles style (code to produce this figure, data)

In order to do so, we remove all values from the plot that are 0, by setting them to 1/0. Further we set the transparency of the circles to 20%. Before plotting the data we are sorting them regarding their percentage value in order to plot the highest values above the lower ones.

f(x) = x>2 ? x : 1/0
set style fill transparent solid 0.8 noborder
plot '<sort -g -k3 vector_projection.txt' u 1:2:(1):(f($3)) w circles lc palette

June 5th, 2013 | 7 Comments

If you are looking for nice color maps which are especially prepared to work with cartographic like plots you should have a look at colorbrewer2.org. On that site hosted by Cynthia Brewer you can pick from a large set of well balanced color maps. The maps are ordered regarding their usage. Figure 1 shows example color maps for three different use cases.

Colorbrew color maps

Fig. 1 Examples of color maps from colorbrewer2.org ordered in three categories (code to produce this figure, data)

The diverging color maps are for data with extremes at both points of a neutral value, for example like the below and above sea level. The sequential color maps are for data ordered from one point to another and the qualitative color maps are for categorically-grouped data with now explicit ordering.
Thanks to Anna Schneider there is an easy way to include them (at least the ones with eight colors each) into gnuplot. Just go to her gnuplot-colorbrewer github site and download the color maps. Place them in the same path as your plotting file, or add the three pathes of the repository to your load pathes, for example by adding the following to your .gnuplot file.

set loadpath '~/git/gnuplot-colorbrewer/diverging' \
    '~/git/gnuplot-colorbrewer/qualitative' \
    '~/git/gnuplot-colorbrewer/sequential'
YlGnBu color map from colorbrewer

Fig. 2 Photoluminescence yield plotted with the YlGnBu color map from colorbrewer2.org (code to produce this figure, data)

After this you can pick the right color map for you on colorbrewer2.org, keep its name and load it before your plot command. For example in Fig. 2 we are plotting again the photoluminescence yield with the sequential color map named YlGnBu. First we load the color map, then switch the two poles of the color map by setting the palette to negative, and finally plotting the data.

load 'YlGnBu.plt'
set palette negative
plot 'matlab_colormap.txt' u ($1/3.0):($2/3.0):($3/1000.0) matrix with image
Paired color map from colorbrewer

Fig. 3 Eight lines plotted with the Paired color map from colorbrewer2.org (code to produce this figure)

The nice thing of the palettes coming with gnuplot-colorbrewer is that they also include the corresponding line colors. In Fig. 3 you see the Paired qualitative color map in action with lines.

load 'Paired.plt'
plot for [ii=1:8] f(x,ii) ls ii lw 2

May 21st, 2013 | 1 Comment

As you may have noted, gnuplot and Matlab have different default color maps. Designing such a default map is not easy, because they should handle a lot of different things (Moreland, 2009):
– The map yields images that are aesthetically pleasing
– The map has a maximal perceptual resolution
– Interference with the shading of 3D surfaces is minimal
– The map is not sensitive to vision deficiencies
– The order of the colors should be intuitively the same for all people
– The perceptual interpolation matches the underlying scalars of the map

In his paper Moreland developed a new default color map that was mentioned already in a user comment. In Fig. 1 the map is used to replot the photoluminescence yield plotted in an earlier entry.

Default color map after Moreland, 2009

Fig. 1 Photoluminescence yield plotted with the default color map after Moreland, 2009 (code to produce this figure, data)

To use the default color map proposed by Moreland, just download default.plt and store it to a path, that is available to gnuplot. For example store it under /home/username/.gnuplotting/default.plt and add the following line to your .gnuplot file.

set loadpath "/home/username/.gnuplotting"

After that you can just load the palette before your plot command via

load 'default.plt'
Default gnuplot color palette

Fig. 2 Photoluminescence yield plotted with gnuplots default color palette (code to produce this figure, data)

In Fig. 2 the same plot is shown using the default color map from gnuplot, which is a little bit dark in my opinion.

Default Matlab color palette

Fig. 3 Photoluminescence yield plotted with Matlabs default color palette (code to produce this figure, data)

Figure 3 shows the jet color map from Matlab, which is a classical rainbow map with all its pros and cons.

April 3rd, 2013 | 3 Comments

In one of the last posts, we came up with an updated data set representing the world. One way to plot this data set is with a 2D plot, as shown in Fig. 2. But if you compare the output with the one you see for example at Google Maps you will noticed a difference. That is due to the fact that Google uses the Mercator projection of the data. This projection preserves the angles around any point on the map, what is useful if you have a close look at some streets. The disadvantage of the Mercator projection is the inaccuracy of the sizes of the countries near to the poles. For example the size of Greenland is completely overemphasized as you can see in Fig. 1.

Mercator projection

Fig. 1 Mercator projection of the world (code to produce this figure, data)

In order to achieve the Mercator projection, we apply the following function.

set angles degrees
mercator(latitude) = log( tan(180/4.0 + latitude/2.0) )
set yrange [-3.1:3.1]
plot 'world_110m.txt' u 1:(mercator($2)) w filledcu ls 2
Equirectangular projection

Fig. 2 Equirectangular projection of the world (code to produce this figure, data)

By just plotting the data as we have done for Fig. 2, we have the Equirectangular projection with constant spacing between the latitudes and meridians. The blue background color in the first two figures can be achieved directly with a terminal setting.

set terminal pngcairo size background '#c8ebff'
Heat map

Fig. 3 Mapping of the Mercator projection (code to produce this figure)

In Fig. 3 the Mercator projection function is shown as an input-output-function of the latitude values. The placing of the latitude values on the y-axis can be easily done with a loop.

set ytics 0
do for [angle=-80:80:20] {
    set ytics add (sprintf('%.0f',angle) mercator(angle))
}

March 12th, 2013 | 12 Comments

We discussed already the plotting of heat maps at more than one occasions. Here we will add the possibility to interpolate the data in a heat map figure.

Heat map

Fig. 1 A simple heat map (code to produce this figure, data)

Suppose we have the following data matrix, stored in heat_map_data.txt.

6 5 4 3 1 0
3 2 2 0 0 1
0 0 0 0 1 0
0 0 0 0 2 3
0 0 1 2 4 3
0 1 2 3 4 5

The normal way of plotting them would be with

plot 'heat_map_data.txt' matrix with image

But to be able to interpolate the data we have to use splot and pm3d instead.

set pm3d map
splot 'heat_map_data.txt' matrix

In Fig. 1 the result of plotting the data just with splot, without interpolation is shown. Note, that the result differs already from the plot command. The plot command would have created six points, whereas the splot command comes up with only five different regions for every axis.

Interpolated heat map

Fig. 2 A heat map interpolated to use twice as much points on every axis (code to produce this figure, data)

Now if we want to double the number of visible points, we can tell pm3d easily to interpolate the data by the interpolate command.

set pm3d interpolate 2,2

The two numbers 2,2 are the number of additional points along the x- and y-axis.
The resulting plot can be found in Fig. 2.

Strong interpolated heat map

Fig. 3 A heat map interpolated with an optimal number of points (code to produce this figure, data)

In addition to explicitly setting the number of points we can tell gnuplot to choose the correct number of interpolation points by itself, by setting them to 0.

set pm3d interpolate 0,0

Now gnuplot decides by itself how to interpolate, which leads to the result in Fig. 3.