Marco Fioretti goes over the finer points of using Gnuplot to design graphs based on mathematical functions and tabular data using conditional plotting.
A couple of months ago, I showed on this blog one of the reasons why I like the command line plotting utility Gnuplot: its ability to understand and display in a very readable way time-based data. This week I'm going to spend a few words to introduce another Gnuplot feature that makes it an essential tool for everybody who needs automatic but flexible plotting.
As you probably already know, Gnuplot can plot both mathematical functions and tabular data from ASCII files. If, for example, you have these numbers in a file called simpledata.txt:
1 -3 15
2 -2 14
3 -1.5 10
4 3 -9.5
5 2.75 -2.58
The following command:
plot [1:5][:] "simpledata.txt" using 1:2 w l t "2nd column of data file", -2*(cos(3*x)*x) +1 w lgenerates the diagram in Figure A.
In that plot, the read line is drawn joining the points defined by the first two columns of the file: the first number of each row becomes the horizontal coordinate x, and the second the vertical one, y. The green curve, instead, is the graphical representation of the function -2*(cos(3*x)*x) +1.
Figure A shows the simplest kind of graphs that Gnuplot can draw. As cool as they are, they also are sort of rigid. Once you have written something like "using 1:2", the corresponding curve on the graph (the red one in Figure A) will use all the content of those columns...and nothing else, for the whole plot. For the same reason, the green curve will always and only show the path of that one function.Luckily, Gnuplot can be much more flexible than this, thanks to conditional plotting. Figure B shows how the previous diagram changes if you modify the Gnuplot command above as follows:
plot [1:5][:] "simpledata.txt" using 1:($1 <=3 ? $2 : 1/0) w l t "2nd column of data file", (x > 3) ? -2*(cos(3*x)*x) +1 : 1/0 w l
The trick is all in the conditional, C-like statements. You must put them right in the places in which you tell Gnuplot which columns (or functions) to use as coordinates for the vertical axis. "1/0" is sort of a Gnuplot keyword to say "nothing." In this snippet of code:
($1 <=3 ? $2 : 1/0)
It means "if the current number in the first column ($1) is less than 3, use the second column ($2), otherwise draw nothing". Similarly, the second condition tells Gnuplot to draw the associated function only for values of x greater than 3.This is the basic Gnuplot conditional plotting trick. Of course, the conditional statements can be nested. In practice, you can use them in several ways. Combining two or more mathematical functions, expressed by formulas, in the single curve of Figure C it's quick:
gnuplot> plot [1:5][:] (x <3) ? -2*(cos(3*x)*x) +1 : (x >=3 && x <4) ? -7*tan(30*x) : 3*x**3 w l t "One curve made of 3 formulas"
plot [1:5][:] "simpledata.txt" using 1:(($1 <=3) ? $2 : $3) w l t "2 columns of the same data file"
What if you wanted to combine in one curve, using this trick, numbers from two different data files, or from one data file and one function? Looking again at Figure B shows that we'd need something more to make the result appear like one curve. Namely, we should tell Gnuplot to always use the same color for the two plots, by adding to each instruction the option lt N, where N is the Gnuplot numeric code for plot colors. To know which color corresponds to each value, type "test" at the Gnuplot prompt.There is another issue that you need to take into account when playing with conditional plotting. You can see what I am talking about by comparing Figure C with Figure E, which I generated plotting only the [2.9:4.1][-20:400] area to make the diagram more readable:
gnuplot> plot [2.9:4.1][-20:200] -2*(cos(3*x)*x) +1 w l t "First curve", -7*tan(30*x) w l t "Second curve", 3*x**3 w l t "Third curve"
What happened? It's simple: when Gnuplot arrives to changing points (x=3 and x=4 in our case) it adds extra straight segments, that connect the last y value of one function with the first y value of the next one.
You just need to know this in advance, in order to have Gnuplot plot exactly what you want. If and when you actually want to draw two separated curves, you must explicitly tell this to Gnuplot. When that's the case, use two conditional controls:
gnuplot > plot [3.9:4.1][:] ( x <4) ? -7*tan(30*x) : 1/0, (x < 4) ? 1/0 : 3*x**3 w l
This tells Gnuplot to draw two independent curves.