Gnuplotting

Create scientific plots using gnuplot

December 18th, 2012 | 25 Comments

More than a year ago, we draw a map of the world with gnuplot. But it has been pointed out the low resolution of the map data. For example, Denmark is totally missing in the original data file. The good thing is, there is other data available in the web. In this entry we will consider how to use the physical coastline data from http://www.naturalearthdata.com/downloads/ together with gnuplot.

Fig. 1 Plot of the world with the new data file and a resolution of 1:110m (code to produce this figure, data)

At the download page, three different resolutions of the data are available with a scale of 1:10m, 1:50m, or 1:110m. The data itself is stored as shape files on naturalearthdata.com. Hence I wrote a script that converts the data first to a csv file using the ogr2ogr program. Afterwards the data is shaped with sed into the form of the original world.dat file.
Here are the resulting files:

Fig.1 shows the result for a resolution of 1:110m. Note that we have to use linetype instead of linestyle in gnuplot 4.6 in order to set the colors of the grid and coast line.

In order to compare the different resolutions of the coast line files, we plot only the part of the map where Denmark is located (which is completely missing in the original data).
Here is the example code for a scale of 1:110m.

set xrange [7.5:13]
set yrange [54.5:58]
plot 'world_110m.txt' with filledcurves ls 1, \
    '' with l ls 2

Fig. 2 A plot of Denmark at a resolution of 1:110m. (code to produce this figure, data)

Fig. 3 A plot of Denmark at a resolution of 1:50m. (code to produce this figure, data)

Fig. 4 A plot of Denmark at a resolution of 1:10m. (code to produce this figure, data)

25 Comments

  1. AlBundy says:

    Great! Thanks for sharing.

    Sorry, could you recommend a good book about gnuplot?.

  2. jack says:

    Thanks a lot.
    I plot three maps of globe using the three resolutions respectively.

    1:10m : http://d.pr/i/sCzt
    1:50m : http://d.pr/i/eyL1
    1:110m : http://d.pr/i/49v1

    the first and third plot may have bugs. some place is blank.

  3. hagen says:

    @AlBundy: there are not that many gnuplot books. I know only two:
    Gnuplot in Action: Understanding Data with Graphs from Philipp K. Janert
    gnuplot Cookbook from Lee Phillips

    @jack: yes there are some bugs regarding filledcurves plots with the data. That is mainly due to the order of the data in the file. For the 1:110m file I have corrected the data, for the 1:10m it need some work.

  4. jack says:

    @hagen: thanks for reply. I have two more questions.
    1. Could the heatmaps be interpolated?
    http://gnuplot.sourceforge.net/demo_4.6/heatmaps.html
    sometimes, smoothing plot looks better.
    2. Could the zlabel of pm3d be rotated? if string of zlabel is long, it will take much width of plot.

  5. hagen says:

    1. I’m afraid you have to interpolate your data matrix in order to interpolate the image.
    2. Labels can be rotated by rotate by <degrees>

  6. hagen says:

    I have corrected all data files in order to work correctly with the filledcurves option.

    I have also added the Antarctica at the bottom of the files seperated by two blank lines in order to use the index option to generate a plot with correct filling of the Antartica.

    If we plot by the following command, we will get Fig. 5.

    plot 'world_110m.txt' with filledcurves ls 2, \
         '' w lines linestyle 1
    

    Fig. 5 World with a resolution of 1:110m and filledcurves

    If we use the index option and set the reference of the filledcurves to the x-axis for the Antartica, we will get Fig. 6.

    plot 'world_110m.txt' i 0 with filledcurves ls 2, \
         ''               i 1 with filledcurves x1 ls 2, \
         '' w lines linestyle 1
    

    Fig. 6 World with a resolution of 1:110m and filledcurves and correct Antartica

  7. jack says:

    Hi, hagen. As heatmap can’t be interpolated. I use pm3d to complete interpolation.

    ex: http://d.pr/i/BNqq

    [code]
    set terminal pngcairo font "Times New Roman,20" size 800,500
    set output "tec.png"
    set xlabel "Longitude"
    set ylabel "Latitude"
    set xrange [-180:180]
    set xtics -160,40,160
    set mxtics 2
    set yrange [-87.5:87.5]
    set ytics -75,25,75
    set mytics 2
    set cbrange [0:100]
    set cbtics 0,20,100
    unset key
    set palette rgbformulae 22,13,-31
    set pm3d interpolate 0,0
    set view map
    splot "tec.dat" using 3:2:1:4 with pm3d
    set output
    [/code]

    Also, I want to plot world on the same image. Would you please tell me how to do this?

  8. hagen says:

    That is a nice trick. I will write an entry about heat map interpolation.

    For including the world, it is easy with the 3D version, there it just works. For the 2D version we need to align the 3D and 2D plot. That I will discuss also in an extra entry, sometime the next weeks.

  9. MikeS says:

    Thanks. I created a 1:10m of southeast Asia and plotted the frequency of MODIS satellite passes per day (http://d.pr/i/SDXx). Not sure why my gridlines change from grey to black?

  10. hagen says:

    Mh, strange.
    I have created a plot from the same region with the temperature data from the heat map entry and the grid looks fine.

    Heat map with grid

    Fig. 7 World with a resolution of 1:50m, some temperature data and a grey grid (code to produce this figure)

    I have added the grid with the following code

    set style line 2 lc rgb '#808080' lt 0 lw 1
    set grid front ls 2
    

    What exact terminal and code for the grid did you use?

  11. MikeS says:

    I used the PNG terminal and very similar code to yours. The code is here: http://d.pr/f/fJeq. The frequency data is here: http://d.pr/f/aDRG (20 Mbs). The coastline is here: http://d.pr/f/ApzY (3 Mbs)

  12. hagen says:

    I have found the error. You scaled up your tics in a way that they cover most of the graph, and they are in front of the grid.
    I have changed

    set xtics scale 20 border
    set ytics scale 20 border
    

    to

    set xtics scale 0 border
    set ytics scale 0 border
    

    and now your grid looks fine.
    Modis_coverage_20120823_32.png.

    Don’t wonder that the MODIS data are not aligned, that is due to the fact that the range of the x and y values in your given data file are only in this region.

  13. MikeS says:

    Thanks. It looks better now (http://d.pr/i/50bp) with the spatially correct frequency data file (http://d.pr/f/aoHT). Sorry I uploaded an earlier incorrect test data file. Look forward to your next entry.

  14. OriolC says:

    Hi Hagen,

    I am plotting a 3D plot of temperature map on a cylinder. My plot is created from a .dat file with four columns as well. Instead of your “world” I am plotting onto the temperatures the contour lines of the temperature field (how I have created those it is a long story and I can explain it in a further comment if you wish). My problem is that after plotting the temps pm3d + contours lines, the “theoretically” hidden contour lines can still be seen. In your 3D plots of the world temperatures this doesn’t happen. I am wondering if you can give me a hint. The only difference I can see so far is that I am not plotting the cylinder itself and that I am using cartesian cordinates to define the points for both, the temperatures and the contour lines.

    Thanks a lot.
    Oriol

  15. hagen says:

    If you plot both the contour lines and the temperature data, the order of the two commands matters. For example, above I plotted first the contour lines and in the second line the temperature data.
    If this doesn’t help, I’m afraid I have to see your code in order to help.

  16. OriolC says:

    Dear Hagen,

    Thanks your for promt reply. I have been working on it and basically trying to do all the steps you did to make your plot. The hidden contours finally disapeared when using the “hidden3d front” and plotting the cylinder mesh. If any of those two is missing, the hidden contours appear again. As you showed in your code, first plot the temperature data, then the mesh and finally the contours.

    My code is like this:

    reset
    set title "2D Temperature Fluctuations Random fields\nN=32,dt=0.050,fc=10.000,df=0.050,Vm=11.4:t=1.550s" offset 0,1
    set zlabel "Axial distance(m)"
    set cblabel "T.Fluctuations({/Symbol \260}C)" offset 1.0
    set cbrange [-10:10]
    unset key
    set palette rgbformulae 22,13,10
    set ticslevel 0.0
    set mapping cylindrical
    set angles radians
    set hidden3d front
    set parametric
    set isosamples 10
    set urange[0:2*pi]
    set vrange[0:1.4000]
    r=0.0700
    r1=0.0693
    set view 60,60
    splot "Fluctuations.dat" u 2:($1)*r:(r):3 with pm3d, r1*sin(u),r1*cos(u),v w l lt 1 lc -1 , "contoursF.dat" u 2:($1)*r:(r):3 w l lt 1 lw 1
    set term pngcairo enhanced
    set output "3dF_0032.png"
    replot
    

    Now I have got a problem I never really knew how to solve. The length of my pipe (in z axis) is ten times the diameter (in xy plane). How can I fit everything in the screen?

  17. OriolC says:

    Sorry, I forgot to say now I have added the “set view equal xyz” in order to set the same ratio on all axes. Then I can’t get the whole pipe within the terminal :)

    Thanks!

  18. hagen says:

    If you want to stick with the set view equal xyz, you could change the size of the terminal. For example try

    set terminal pngcairo size 350,3500 enhanced
    

    if your z axis is ten times as large as the other ones.

  19. OriolC says:

    After spending some time with the terminal or canvas size finally I found the way to fit the plot inside.
    The “set size” command scales the plot relative to the canvas size, as said in the gnuplot instructions. And that did it! Then it is also necessary to play with “set origin”. Otherwise the plot is not located in the proper relative position.

    Here is my final code:

    reset
    set terminal wxt size 400,1000 enhanced font 'Helvetica,10'
    
    set size 1,0.27 #scales the plot relative to canvas size.
    set origin 0,-0.03 #sets the origin of the plot within the canvas
    
    set title "2D Temperature Random fields\nN=32,dt=0.050,fc=10.000,df=0.050,Vm=11.4:t=1.550s" offset 0,47
    #set zlabel "Axial distance(m)" rotate by 90 font ",15" offset -3
    set xtics 0.04 offset -2,0
    set ytics 0.04 offset 1.0,0
    set ztics offset 0,0.5
    set cblabel "Temperature({/Symbol \260}C)" offset 1.0
    set cbrange [15.0:30.0]
    unset key
    set palette rgbformulae 22,13,10
    set mapping cylindrical
    set angles radians
    set hidden3d front
    set parametric
    set isosamples 10
    set urange[0:2*pi]
    set vrange[0:1.4000]
    r=0.0700
    r1=0.0693
    set view equal xyz
    set view 60,60
    set ticslevel 0.0
    splot "Temperatures.dat" u 2:($1)*r:(r):3 with pm3d, \
    r1*sin(u),r1*cos(u),v w l lt 1 lc -1 , \
    "contoursT.dat" u 2:($1)*r:(r):3 w l lt 1 lw 1
    set terminal pngcairo size 400,1000 enhanced font 'Helvetica,10'
    set output "test.png"
    replot
    

    Thanks for your help!

  20. Irina says:

    Hi Hagen,
    I used your map for Mediterranean region and noticed that the Italic and Greek islands (Sizilien, Rhodes, etc) are not filled with a color. Could you please correct the case?

    And now a question. I’ve changed to the Mercator projection (it looks more natural) with

    plot 'world_10m.txt' using 1:((log(1.0/cos($2*pi/180)+tan($2*pi/180)))*180/pi) with filledcurves ls 1, \
        '' using 1:((log(1.0/cos($2*pi/180)+tan($2*pi/180)))*180/pi) with l ls 2
    

    but in this case the axes have also changed somehow. The longitude sis OK but the latitudes are now corrupt (with about 3 degree). Could youl please help me to solve the problem?

    Thank you in advance,

    Irina

  21. hagen says:

    Hi Irina.

    To use only a little region works not always out of the box with filledcurves. The islands seem to be ok for me. Here is a plot of the Mediterranean region.

    set xrange [5:35]
    set yrange [25:50]
    plot 'world_10m.txt' w filledcu ls 1, \
         ''              w l ls 2
    
    Map of the Mediterranean region

    Fig. 8 A map of the Mediterranean region (code to produce this figure, data)

    But if we do the same with Italy, we get a corrupted picture.

    set xrange [8:19]
    set yrange [35:48]
    plot 'world_10m.txt' w filledcu ls 1, \
         ''              w l ls 2
    
    Corrupted map of Italy

    Fig. 9 A corrupted map of Italy (code to produce this figure, data)

    Now we have to plot different regions at different times and set different reference lines for filledcurves.

    region1_x(x,y) = (x<11.3 && y<37.5) ? 1/0 : x
    region1_y(x,y) = (x<11.3 && y<37.5) ? 1/0 : y
    region2_x(x,y) = (x<11.3 && y<37.5) ? x : 1/0
    region2_y(x,y) = (x<11.3 && y<37.5) ? y : 1/0
    plot 'world_10m.txt' \
            u (region1_x($1,$2)):(region1_y($1,$2)) \
            with filledcurves below y1=50 ls 1, \
        '' u (region2_x($1,$2)):(region2_y($1,$2)) \
            with filledcurves above y1=25 ls 1, \
        '' with l ls 2
    
    Correct map of Italy

    Fig. 10 A map of Italy (code to produce this figure, data)

    For the Mercator projection I think you can solve your problem by looking at this comment. But thank you for the idea, I have created a new entry discussing the Mercator projection.

  22. Valerio Schiavoni says:

    Hello,
    what is the best way to put a set of points (given as latitude,longitude)
    on top of this revised world plot ? I don’t need plot an heatmap, more simply a set of landmarks.
    A code example would be greatly helpful.
    thanks

  23. hagen says:

    Hi,
    that’s relatively easy if you have the points already as latitude, longitude pairs.
    For example assume a file containing the following random points somewhere in Denmark.

    9.1 55.9
    10.3 57.4
    12.0 55.5
    

    Now you can add them to the world plot by

    plot 'world_10m.txt' with filledcurves ls 1, \
         '' with l ls 2, \
         'points.txt' w p ls 3
    

    That will give you Fig. 11 as result.

    Fig. 11 Random points somewhere in Denmark. (code to produce this figure, world data, point data.)

    Should be the same for the 3D plot with splot.

  24. Christoph says:

    Hi,

    I wanted to mention, that the current development version of gnuplot fixes some clipping issues related to the ‘filledcurves’ plotting style. The image italy.png created in hagen’s comment will be plotted correctly.

  25. hagen says:

    This will be very cool, and helps a lot to use gnuplot for cartographic plots.

Leave a Reply