feedgnuplot/guide/guide.org
2021-02-20 14:12:47 -08:00

6.5 KiB

Guide

This is an overview of the capabilities of feedgnuplot and a set of example recipes. The documentation provides a complete reference. The capabilities of gnuplot itself are demonstrated at its demo page.

Tutorial

First, a trivial plot: let's plot a sinusoid

seq 100 | \
perl -nE 'say sin($_/5.)' | \
feedgnuplot

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-1.svg

This was a trivial plot, and was trivially-easy to make: we gave the tool one column of data with no specific instructions, and we got a plot.

The interpretation of the input data is controlled by two arguments: =--domain and --dataid. Here we passed neither, so each line of input is interpreted as y0 y1 y2... with sequential integers (0, 1, 2, …) used for the x coordinate. Let's pass in more than one y per line to plot a sine and a cosine together:

seq 100 | \
perl -nE '$th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          say "$c $s"' | \
feedgnuplot --lines --points

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-2.svg

Here I also passed --lines --points to make more legible plots.

Note that, the lines may have different numbers of points. To plot the cosine from every line, but the sine from every 5th line:

seq 100 | \
perl -nE '$th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          if($.%5) { say "$c";    }
          else     { say "$c $s"; }' | \
feedgnuplot --lines --points

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-3.svg

Each y is referred to as a "dataset" or "curve" in the code and documentation.

With --domain, the x values are read from the data instead of simply encoding line numbers: each line of input is interpreted as x y0 y1 y2.... Let's plot sin(theta) vs. cos(theta), i.e. a circle:

seq 100 | \
perl -nE '$th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          say "$c $s"' | \
feedgnuplot --lines --points --domain

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-4.svg

Hmmm. We asked for a circle, but this looks more like an ellipse. Why? Because gnuplot is autoscaling the x and y axes independently to fill the plot window. We can scale the axes together by passing --square, and we get a circle:

seq 100 | \
perl -nE '$th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          say "$c $s"' | \
feedgnuplot --lines --points --domain --square

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-5.svg

Again, we can have multiple y in each line, and each line may have a different number of y. Let's plot a circle and an ellipse, sampled more coarsely:

seq 100 | \
perl -nE '$th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          if($.%5) { say "$c $s"; }
          else     { $s2 = $s/2;
                     say "$c $s $s2"; }' | \
feedgnuplot --lines --points --domain --square

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-6.svg

We just plotted something where each point is represented by 2 values: x and y. When making 2D plots, this is the most common case, but others are possible. What if we want to color-code our points using another column of data? We feed in the new column, and we tell feedgnuplot that we now have 3 values per point (the tuple size), and we tell gnuplot how we want this plot to be made. Color-coding by the angle, in degrees:

seq 100 | \
perl -nE '$thdeg = $_/100.*360.;
          $th = $_/100.*2.*3.14159;
          $s  = sin($th);
          $c  = cos($th);
          say "$c $s $thdeg";' | \
feedgnuplot --lines --points --domain --square \
            --tuplesizeall 3  \
            --styleall 'with points palette'

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-7.svg

Here we said that all the datasets have 3 values per point. And that all the datasets should be plotted with that particular style. The styles are strings that are passed on to gnuplot verbatim. So the full power of gnuplot is available, and there's nothing feedgnuplot-specific to learn. gnuplot has plenty of documentation about styling details.

The above --styleall argument may be identically replaced with a shorthand:

--with 'points palette'

The styles and tuple sizes can be different for each dataset. For instance, to apply the colors only to the circle (dataset 0), leaving the ellipse (dataset 1) with the default tuple size and style:

seq 100 | \
perl -nE '$thdeg = $_/100.*360.;
          $th = $_/100.*2.*3.14159;
          $s=sin($th); $c=cos($th);
          if($.%5) { say "$c $s $thdeg" }
          else     { $s2 = $s/2;
                     say "$c $s $thdeg $s2"; }' | \
feedgnuplot --lines --points --domain --square \
            --tuplesize 0 3   \
            --style     0 'with points palette' \
            --legend    0 'circle' \
            --legend    1 'ellipse'

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-8.svg

Here we also asked for dataset labels to make it clear to the viewer what's what.

The other significant option involved in the interpretation of data is --dataid. This labels each dataset in the data, so instead of referring to dataset 0, you could refer to dataset circle. With --domain --dataid, each line of input is interpreted as x id0 y0 id1 y1..., with the number of y in each dataset reflecting the tuple size. Naturally, --dataid without --domain is identical, except without the leading x. The previous plot can be reproduced with --dataid:

seq 100 | \
perl -nE '$thdeg = $_/100.*360.;
          $th = $_/100.*2.*3.14159;
          $s=sin($th); $c=cos($th);
          if($.%5) { say "$c circle $s $thdeg" }
          else     { $s2 = $s/2;
                     say "$c circle $s $thdeg ellipse $s2"; }' | \
feedgnuplot --lines --points --domain --dataid --square \
            --tuplesize circle 3   \
            --style     circle 'with points palette' \
            --autolegend

/zhangyiss/feedgnuplot/media/commit/bf818d989805e528cd1e63c8aa6a585fee7b49cc/guide/guide-9.svg

Note that instead of labelling the datasets explicitly, we can pass --autolegend, and the ID will be used to label each dataset. This works without --dataid also, but the IDs are then the unhelpful sequential integers.