Generating Graphs with gnuplot, Part 1

The gnuplot package can be used to generate some very slick two and three dimensional graphs. Tools such as IOzone make use of gnuplot to generate three dimensional plots letting you see the relative effect that the size of IO requests has on performance. While gnuplot has many features which let you interactively explore your data, it is command line driven and if you don't know the commands you don't get to play the game. The default graphical plot window only has a handful of buttons in a toolbar and no menu to help a user unfamiliar with gnuplot create and modify their graphs. In this article series I'll go though how to change the default setup of gnuplot to be more pleasing, how to make plots from data files and finally how to plot data from SQLite and PostgreSQL databases, including the use of pivot tables to massage the data into the format that gnuplot expects.

There are many reasons that one might like to set aside the difficulties in the default user interface and take the time to learn the commands to generate plots with gnuplot. A major benefit of gnuplot is that once you have your graph setup as you like, you can export it as png, jpeg, svg, pdf, postscript, or in many formats that work with LaTeX or plain TeX. You can also save the state of gnuplot to a text file so you can pick up where you left off at a later point. The saved state gnuplot file is a plain text file which contains all the gnuplot commands to setup the same graph again at a later time. This way you can save not only the exported png graphic of the graph but the commands used to generate it. Keeping the saved gnuplot commands around also helps you create new graphs by looking for a graph you have created which is similar to what you are looking to create.

In this first part, I'll go into how to make the default settings for gnuplot more attractive. How to set vector fonts for your png exports, how to set the default image width and height of a png export, changing colors to be more legible and easier on the eye.

The rendering in gnuplot is handled by what is referred to as a terminal. There are interactive terminals such as x11 and wxt and non interactive ones like PDF and jpeg. If you are using the x11 terminal for interactive graphs you might like to switch to the wxt one because it uses Cairo to render and can make anti-aliased and oversampled graphs which look much nicer than those generated by the default x11 terminal. I'll go over how to change your terminal in a moment.

When gnuplot starts up, it reads and interprets the ~/.gnuplot file giving you a chance to set default colors, line thickness, fonts, hotkeys and other settings. One nice feature here is that you can switch your terminal to jpeg or svg and specify how you would like that terminal to operate before switching back to wxt as a default for interactive graph sessions. For example, switching to jpeg terminal and specifying the default width and height to generate as well as the font to use for the graph. This is another area where the system defaults could have been better setup in many gnuplot configurations, if you are using the wxt terminal you should see nice anti-aliased fonts and if you export using the jpeg or png terminal setup with default settings you might notice that the fonts are aliased and ugly. Given that there are some free truetype fonts, for example, the Liberation font set, there is no reason not to have good quality fonts in your gnuplot exports.

You might be wondering why switch to the png terminal, set the font and other preferences, and then switch to the wxt terminal before the end of the ~/.gnuplot file. The reason is that specific settings for a terminal are remembered by gnuplot, so if you later just switch to the png terminal to export the graph to a file, the font settings you made for the png terminal in the ~/.gnuplot file will still effect the png terminal.

When gnuplot is interpreting a function to generate a plot, it will use a predefined number of sample points per axis. By default this can be set quite low, for example 100 samples. Given LCD displays that show 1920 pixels across and CPUs that can handle a few thousand samples before you'll even notice, you might like to make the default number of samples to a few thousand instead of a hundred.

Designing a good color palette is quite an art form. What looks good for line plots might not be the most optimal for a bar chart. For example, the former calls for somewhat bold color differences because the data is plotted with only a fairly thin line to make itself known. For a bar chart a softer palette with more pastel colors would be easier on the eyes.

By default gnuplot uses a stark white background to the graph which can also make longer interactive sessions on LCD displays more painful to the eye than is necessary. There is information about on the Web showing how to change the background color for the x11 terminal but not so readily for the wxt terminal. There is a sure method to change the background for all terminals -- create a colored rectangle with a very low stacking order filled with the color you want as the background. Of course, you can remove this background rectangle when exporting to PDF or svg.

To change a setting in gnuplot, use the set settingname value command. You can see the current value with show settingname and remove any current setting with unset settingname. Removing a setting with unset will return it to the default value.

If you set macro then you can also assign and use your own arbitrary variables in other gnuplot commands. Using macro, your own variables are assigned without using the set command, for example, x=y. You can then just use x in other gnuplot calls that expect a string or use @x to dereference the x variable. When in doubt as to if you should use the @ operator, try both from the gnuplot prompt and see which one works.

Shown below is the core of a ~/.gnuplot file which performs much of what has been described above. First I turn on macro expansion, then assign a few settings that are used in multiple locations like the font and default pixel size of exports. The next block sets the font, size, and other settings for svg, png, and jpeg terminals. With these settings, you can later use set terminal png to switch to the png terminal for exporting the graph and the fonts and size are already set to something desirable for you.

I then set the line width to something rather think before defining the palette for lines 1-9. When making a line graph gnuplot will start at line number 1 and move forward from there. The set style increment user line tells gnuplot to use our line styles instead of its own by default.

Line style 99 is used for borders in bar charts by gnuplot so it is made a little thicker by default. The set object 1 rectangle command creates a nice light grey background to the graph instead of the stark white one. To remove the background simply unset object 1 to delete the rectangle. Objects are created and referred to by a numerical index, in this case index 1. The last few settings turn off forced aspect ratio, increase the default number of samples taken when plotting a function, and turn on the grid.

set macro

my_font_name = "/usr/fonts/liberation/LiberationSans-Regular.ttf, 15"
my_export_sz = "1600,900"

set t svg size @my_export_sz font my_font_name enhanced dynamic rounded
set terminal png  size @my_export_sz large font my_font_name
set terminal jpeg size @my_export_sz large font my_font_name
set terminal wxt  enhanced

my_line_width = "3"
set style line 1 linecolor rgbcolor "#0000AA" linewidth @my_line_width
set style line 2 linecolor rgbcolor "#990000" linewidth @my_line_width
set style line 3 linecolor rgbcolor "#52015b" linewidth @my_line_width
set style line 4 linecolor rgbcolor "#988f03" linewidth @my_line_width
set style line 5 linecolor rgbcolor "#be7400" linewidth @my_line_width
set style line 6 linecolor rgbcolor "#00AA00" linewidth @my_line_width
set style line 7 linecolor rgbcolor "#00b7be" linewidth @my_line_width
set style line 8 linecolor rgbcolor "#808080" linewidth @my_line_width
set style line 9 linecolor rgbcolor "#d26584" linewidth @my_line_width
## plot 1,2,3,4,5,6,7,8,9
set style increment user
set style arrow 1 filled

## used for bar chart borders
set style line 99 linecolor rgbcolor "#000000" linewidth 12

set object 1 rectangle from screen 0, screen 0 to screen 1, screen 1 behind fc  rgbcolor "#cccccc"
set size noratio
set samples 3000
set grid

You can add your own key bindings for the interactive terminals by using the bind command from the gnuplot console or adding the commands to your ~/.gnuplot file. For example, the first command below will replot the graph when you hit a capital R on the keyboard and the wxt window is active. The second command will call an external gnuplot script when the F1 key is pressed. The script takes a command line argument which is where you want to export your graph too.

bind R "replot"
bind "F1" "call 'export.plt' '/tmp/gnuplot'";

Notice that the full path for export.plt is not specified. I tell gnuplot to look into ~/.gnuplot.d for my scripts through an environment variable which is set in ~/.bashrc.

export GNUPLOT_LIB="$GNUPLOT_LIB:~/.gnuplot.d"

The export script is shown below. Notice that the first command saves the current state to the nominated output file name with the ".gp" extension. This allows you to recreate the entire state that gnuplot was in when it created the graph. The gp file does not contain the data files (referenced with the plot command shown below) that used as raw input for the plot of course. This way you can make minor modifications to the graph as needed and generate new updated graphs.

After the current state is saved to a gp file, the current terminal is saved by using the special "push" terminal. This terminal pushes the current terminal onto a stack so you can retrieve it later with the set terminal pop command. This way if you were using the wxt terminal when you call the script, you will be using it when the script is finished too. Because the png and svg font and output size have already been setup in ~/.gnuplot the export script only has to switch to those terminals and replot the graph to save them in the desired format. I noticed a bug in the gnuplot version 4.2.2 where the closing XML tag in the SVG is not written for some reason. This is why the export script saves to a raw file first and them uses the system command to have xmllint fix the exported SVG graphic.

save "$0.gp"

set terminal push
set terminal png 
set output "$0.png" 
replot

set terminal svg
set output "$0.raw.svg" 
replot
# SVG doesn't include close tag.
system "xmllint --recover " . "$0.raw.svg" . " --output " . "$0.svg"

set output
set terminal pop

In Part 2 of this article series, I will begin the process of generating graphs that can be read from the command line or, more commonly from external files.

5
Average: 5 (1 vote)