Chart::Graph::Gnuplot

- NAME
- SYNOPSIS
- DESCRIPTION
- OPTIONS

- USING GNUPLOT TO READ AND PLOT DATE/TIME DATA DIRECTLY

- EXAMPLES

- GENERAL EXAMPLE
- ERRORBARS
- PLOTTING DATES - CUSTOM GNUPLOT OPTIONS
- UNIX TIMESTAMPS
- FUNCTIONS

- MORE INFO
- CONTACT
- AUTHOR
- SEE ALSO

# NAME

Chart::Graph::Gnuplot

# SYNOPSIS

        use Chart::Graph::Gnuplot qw(&gnuplot);

     gnuplot(\%global_options, [\%data_set_options, \@matrix],
                               [\%data_set_options, \@x_column, \@y_column],
                               [\%data_set_options, < filename >], ... );

# DESCRIPTION

gnuplot() is a function in module Chart::Graph that lets you generate graphs on the fly in perl. It was written as a front-end application to gnuplot for hassle-free generation of graphs. gnuplot() can be supplied with many of the same options and arguments that can be given to gnuplot. For more information on gnuplot see the end of this section.

# OPTIONS

gnuplot() has a very large number of options corresponding to options available with the gnuplot application itself. This Perl wrapper provides a large subset of the functionality of the application.

     +----------------------------------------------------------------------------+
     |                             GLOBAL OPTIONS:                                |
     +----------------+-----------------------------+-----------------------------+
     | NAME           |  OPTIONS                    |        DEFAULT              |
     +----------------+-----------------------------+-----------------------------+
     |'title'         |  set your own title         |     'untitled'              |
     |'output type'   |  'pbm','gif','tgif','png',  |     'png'                   |
     |                |   'svg' or "eps $epsoptions"|                             |
     |'output file'   |  set your own output file,  |     'untitled-gnuplot.png'  |
     |                |   undef to output to STDOUT |                             |
     |'x-axis label'  |  set your own label         |     'x-axis'                |
     |'y-axis label'  |  set your own label         |     'y-axis'                |
     |'x2-axis label' |  set your own label         |     none                    |
     |'y2-axis label' |  set your own label         |     none                    |
     |'logscale x'    |  0 or 1                     |     0                       |
     |'logscale y'    |  0 or 1                     |     0                       |
     |'logscale x2'   |  0 or 1                     |     0                       |
     |'logscale y2'   |  0 or 1                     |     0                       |
     | 'xtics'        | set your own tics on x-axis |     none                    |
     |                |   (see example below)       |                             |
     | 'x2tics'       | set your own tics on x2-axis|     none                    |
     |                |   (see example below)       |                             |
     | 'ytics'        | set your own tics on y-axis |     none                    |
     |                |   (see example below)       |                             |
     | 'y2tics'       | set your own tics on y2-axis|     none                    |
     |                |   (see example below)       |                             |
     | 'xrange'       | set xrange, accepts both    |     none                    |
     |                |  string '[$xmin:$xmax]'     |                             |
     |                |  or arrayref [$xmin,$xmax]  |                             |
     | 'yrange'       | set yrange, see xrange      |     none                    |
     |                |                             |                             |
     | 'uts'          | set your own range in unix  |     none                    |
     |                |  timestamps, array ref:     |                             |
     |                |  [start_ts,end_ts,<scale>,  |                             |
     |                |   <use_local_tz> ]          |                             |
     |                |  see UNIX TIMESTAMPS example|                             |
     | 'xdata'        | 'time' to indicate that     |     none                    |
     |                |  x-axis is date/time data   |                             |
     | 'ydata'        | 'time' to indicate that     |     none                    |
     |                |  y-axis is date/time data   |                             |
     | 'x2data'       | 'time' to indicate that     |     none                    |
     |                |  x2-axis is date/time data  |                             |
     | 'y2data'       | 'time' to indicate that     |     none                    |
     |                |  y2-axis is date/time data  |                             |
     | 'timefmt'      | "Input date/time string"    |     none                    |
     |                |  see Gnuplot manual for info|                             |
     | 'format'       | array ref: First element is |                             |
     |                |  axis: 'x', 'y', 'x2', 'y2'.|                             |
     |                |  Second element is          |                             |
     |                |  'output date/time string"  |                             |
     |                |  see Gnuplot manual for info|                             |
     | 'extra_opts'   | set your own Gnuplot        |     none                    |
     |                |  options, either an arrayref|                             |
     |                |  or string ("\n"-separated) |                             |
     | 'size'         | scale the display size of   |     none                    |
     |                |  the plot, arrayref [$x, $y]|                             |
     +----------------+-----------------------------+-----------------------------+

     +----------------------------------------------------------------------------+
     |                       Data Set Options:                                    |
     +----------------+-----------------------------+-----------------------------+
     |      Name      |          Options            |           Default           |
     +----------------+-----------------------------+-----------------------------+
     | 'type'         | 'matrix', 'columns', 'file',|      none                   |
     |                |  'function', see examples   |                             |
     |                |  below                      |                             |
     | 'title'        | set your own title          |     'untitled data'         |
     | 'style'        | 'points','lines','impulses' |     'points'                |
     |                |  'errorbars', etc...        |                             |
     |                |  see ERRORBARS example      |                             |
     | 'axes'         | 'x1y1', 'x2y2', 'x1y2', etc.|      'x1y1'                 |
     | 'using'        | map data to what will be    |      '1:2'                  |
     |                |  plotted, see ERRORBARS     |                             |
     |                |  example                    |                             |
     +----------------+-----------------------------+-----------------------------+

Data can be presented to Chart::Graph::Gnuplot in one of 3 formats for the convenience of the user:

     \@matrix: an array reference of [x,y] pairs of data

Alternatively:

     \@x_column, \@y_column: two array references of data of equal length.
     \@x_column is the x-axis data. \@y_column is the y-axis data.

Finally, data can be stored in a file.

## USING GNUPLOT TO READ AND PLOT DATE/TIME DATA DIRECTLY

Gnuplot now has the capability to read date/time data and to create graphs which display date/time on any axis. Unfortunately, mechanism for reading data is less sophisticated than the mechanism for writing data. Chart::Graph::Gnuplot implements date/time data in the same way as Gnuplot itself is presently implemented for consistency with the application.

Any axis can be set to read date/time data instead of numerical data. This is done by setting the options `xdata`, `ydata`, `x2data`, or `y2data` to the value `time`. Unfortunately, you can set only one format to read your data; therefore, consistency is advised. The input format is set using the `timefmt` command noted above. The `timefmt` command takes a string consisting of the elements noted below.

Gnuplot uses the same format codes for date/time input and output so the following table applies to both situations.

     +---------+------------------------------------------------------------------+
     |  Format |                    Explanation                                   |
     +---------+------------------------------------------------------------------+
     |    %d   |       day of the month, 1--31                                    |
     |    %m   |       month of the year, 1--12                                   |
     |    %y   |       year, 0--99                                                |
     |    %Y   |       year, 4-digit                                              |
     |    %j   |       day of the year, 1--365                                    |
     |    %H   |       hour, 0--24                                                |
     |    %M   |       minute, 0--60                                              |
     |    %S   |       second, 0--60                                              |
     |    %b   |       three-character abbreviation of the name of the month      |
     |    %B   |       name of the month                                          |
     +---------+------------------------------------------------------------------+

In addition there are some additional special cases for reading date/time data. To quote from Gnuplot manual: ``Any character is allowed in the string, but must match exactly. `\t` (tab) is recognized. Backslash-octals (`\nnn`) are converted to char. If there is no separating character between the time/date elements, then %d, %m, %y, %H, %M and %S read two digits each, %Y reads four digits and %j reads three digits. %b requires three characters, and %B requires as many as it needs.'' Gnuplot uses the space character as white space pattern match - essentially the same as Perl's: `\s*`.

Gnuplot normally uses whitespace to separate datasets. However, Gnuplot does recognize white space specified in the `timefmt` string. So for example, x-y data can be specified in columns like this:

     25/01/2001 03:05:39 2.05e-5

The `timefmt` string required would be: `"%d/%m/%y %H:%M:%S"`. Note that while the month and month abbreviation can be accepted, any other text must be matched (excluded) in the timefmt string. Certainly, representing dates as numerically is probably the most conservative.

Creating date/time labels for any of the axes is basically analogous. The Chart::Graph:Gnuplot global option is `format`, and it takes a two element array reference: the axis to be plotted and the format string. In addition to the time options listed above, `format` supports the following additional codes for formatting the numerical data on the axes.

     +-------------+--------------------------------------------------------------+
     |  Format     |                Explanation                                   |
     +-------------+--------------------------------------------------------------+
     |    %f       |   floating point notation                                    |
     |    %e or %E |   exponential notation; an "e" or "E" before the power       |
     |    %g or %G |   the shorter of %e (or %E) and %f                           |
     |    %x or %X |   hex                                                        |
     |    %o or %O |   octal                                                      |
     |    %t       |   mantissa to base 10                                        |
     |    %l       |   mantissa to base of current logscale                       |
     |    %s       |   mantissa to base of current logscale; scientific power     |
     |    %T       |   power to base 10                                           |
     |    %L       |   power to base of current logscale                          |
     |    %S       |   scientific power                                           |
     |    %c       |   character replacement for scientific power                 |
     |    %P       |   multiple of pi                                             |
     +-------------+--------------------------------------------------------------+

As in the case of input there some additional options related to these output formats. Again to quote the Gnuplot manual ``Other acceptable modifiers (which come after the % but before the format specifier) are -, which left-justifies the number; +, which forces all numbers to be explicitly signed; #, which places a decimal point after floats that have only zeroes following the decimal point; a positive integer, which defines the field width; 0 (the digit, not the letter) immediately preceding the field width, which indicates that leading zeroes are to be used instead of leading blanks; and a decimal point followed by a non-negative integer, which defines the precision (the minimum number of digits of an integer, or the number of digits following the decimal point of a float).''

Gnuplot also provides more flexibility in terms of the output format codes available for date/time. In addition to those shared with input, the following codes can be used for formatting output date/time axes only.

     +-------------+--------------------------------------------------------------+
     |  Format     |                Explanation                                   |
     +-------------+--------------------------------------------------------------+
     |    %a       |   abbreviated name of day of the week                        |
     |    %A       |   full name of day of the week                               |
     |    %b or %h |   abbreviated name of the month                              |
     |    %B       |   full name of the month                                     |
     |    %D       |   shorthand for "%m/%d/%y"                                   |
     |    %H or %k |   hour, 0--24                                                |
     |    %I or %l |   hour, 0--12                                                |
     |    %p       |   "am" or "pm"                                               |
     |    %r       |   shorthand for "%I:%M:%S %p"                                |
     |    %R       |   shorthand for %H:%M"                                       |
     |    %T       |   shorthand for "%H:%M:%S"                                   |
     |    %U       |   week of the year (week starts on Sunday)                   |
     |    %w       |   day of the week, 0--6 (Sunday = 0)                         |
     |    %W       |   week of the year (week starts on Monday)                   |
     +-------------+--------------------------------------------------------------+

Finally, Chart::Graph::Gnuplot has an extension to support UNIX timestamps. Note this not built into Gnuplot itself. Users can access this option by setting the `xrange` using the `uts` option instead. UNIX timestamps are only available on the x-axis at this time. They cannot be used on y, x2, or y2. See the last example for more details on using UNIX timestamps.

# EXAMPLES

The following are four examples on how to use Chart::Graph::Gnuplot in a variety of settings.

## GENERAL EXAMPLE

The following example illustrates most of the general capabilities of Chart::Graph::Gnuplot. It creates the output file gnuplot1.png. in the png graphics format. The data is coming from all three sources. The first data source is a matrix, the second is a column, and the last is an external data file.

      use Chart::Graph::Gnuplot qw(gnuplot);

      gnuplot({'title' => 'foo',
               'x2-axis label' => 'bar',
               'logscale x2' => '1',
               'logscale y' => '1',
               'output type' => 'png',
               'output file' => 'gnuplot1.png',
               'xtics' => [ ['small\nfoo', 10], ['medium\nfoo', 20], ['large\nfoo', 30] ],
               'ytics' => [10,20,30,40,50],
               'extra_opts' => 'set key left top Left'},
              [{'title' => 'data1',
                'type' => 'matrix'}, [[1, 10],
                                      [2, 20],
                                      [3, 30]] ],
              [{'title' => 'data2',
                'style' => 'lines',
                'type' => 'columns'}, [8, 26, 50, 60, 70],
                                      [5, 28, 50, 60, 70] ],
              [{'title' => 'data3',
                'style' => 'lines',
                'type' => 'file'}, './samplefile'],);

gnuplot1.png

## ERRORBARS

Gnuplot supports errorbars to aid in data interpretation. To use an arbitrary number of data columns (for errorbars), set `style` to `errorbars` and include extra data columns. The example below produces the file gnuplot2.png

Note the following: These columns MUST be the the following formats: `(x, y, ydelta)`, `(x, y, ylow, yhigh)`, `(x, y, xdelta)`, `(x, y, xlow, xhigh)`, `(x, y, xdelta, ydelta)`, or `(x, y, xlow, xhigh, ylow, yhigh)` This will only work with data type `columns`. Also, you MUST use the `using` option to specify how columns of the data file are to be assigned to `x`, `y`, `ydelta`, `ylow` and `yhigh`, `xdelta`, `xlow` and `xhigh`.

         use Chart::Graph::Gnuplot qw(gnuplot);

         gnuplot({"title" => "Examples of Errorbars",
                  "xrange" => "[:11]",
                  "yrange" => "[:45]",
                  "output file" => "gnuplot2.gif",
                  "output type" => "gif",
                 },
                 # dataset 1
                 [{"title" => "yerrorbars",
                   "style" => "yerrorbars",
                   "using" => "1:2:3:4",
                   "type" => "columns"},
                  [ 1, 2, 3, 4, 5, 6 ], # x
                  [ 5, 7, 12, 19, 28, 39 ], # y
                  [ 3, 5, 10, 17, 26, 38 ], # ylow
                  [ 6, 8, 13, 20, 30, 40 ] ], # yhigh
                 # dataset 2
                 [{"title" => "xerrorbars",
                   "style" => "xerrorbars",
                   "using" => "1:2:3:4",
                   "type" => "columns"},
                  [ 4, 5, 6, 7, 8, 9 ], # x
                  [ 1, 4, 5, 6, 7, 10 ], # y
                  [ 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 ], # xlow
                  [ 4.1, 5.2, 6.1, 7.3, 8.1, 10 ] ], # xhigh
                 # dataset 3
                 [{"title" => "xyerrorbars",
                   "style" => "xyerrorbars",
                   "using" => "1:2:3:4:5:6",
                   "type" => "columns"},
                  [ 1.5, 2.5, 3.5, 4.5, 5.5, 6.5 ], # x
                  [ 2, 3.5, 7.0, 14, 15, 20 ], # y
                  [ 0.9, 1.9, 2.8, 3.7, 4.9, 5.8 ], # xlow
                  [ 1.6, 2.7, 3.7, 4.8, 5.6, 6.7 ], # xhigh
                  [ 1, 2, 3, 5, 7, 8 ], # ylow
                  [ 5, 7, 10, 17, 18, 24 ] ], # yhigh
                 # dataset 4
                 [{"title" => "xerrorbars w/ xdelta",
                   "style" => "xerrorbars",
                   "using" => "1:2:3",
                   "type" => "columns"},
                  [ 4, 5, 6, 7, 8, 9 ], # x
                  [ 2.5, 5.5, 6.5, 7.5, 8.6, 11.7 ], # y
                  [ .2, .2, .1, .1, .3, .3 ] ], # xdelta
                 # dataset 5
                 [{"title" => "yerrorbars w/ ydelta",
                   "style" => "yerrorbars",
                   "using" => "1:2:3",
                   "type" => "columns"},
                  [ .7, 1.7, 2.7, 3.7, 4.7, 5.7 ], # x
                  [ 10, 15, 20, 25, 30, 35 ], # y
                  [ .8, 1.2, 1.1, 2.1, 1.3, 3.3 ] ], # ydelta
                 # dataset 6
                 [{"title" => "dummy data",
                   "type" => "matrix"},
                  [ [1,1] ]],
                 # dataset 7
                 [{"title" => "xyerrorbars w/ xydelta",
                   "style" => "xyerrorbars",
                   "using" => "1:2:3:4",
                   "type" => "columns"},
                   [ 7.5, 8.0, 8.5, 9.0, 9.5, 10.0 ], # x
                   [ 30, 27, 25, 23, 27, 33 ], # y
                   [ .2, .1, .3, .6, .4, .3 ], # xdelta
                  [ .8, .7, .3, .6, 1.0, .3 ] ], # ydelta
               );

gnuplot2.gif

## PLOTTING DATES - CUSTOM GNUPLOT OPTIONS

As noted above, Chart::Graph::Gnuplot includes support for plotting date and times as source data. the following shows how to plot data, where the x-axis contains dates, and the y-axis contains stock prices from a major computer major during the ``dot-com meltdown.'' For date and time data that requires high precision, using UNIX time stamps is probably the best solution (see below.) As used in the first example, any option available to Gnuplot can be passed to Gnuplot using the `extra_opts` option. This example uses this feature to enable two options: a grid over the graph and a timestamp for when the graph was created.

      use Chart::Graph::Gnuplot qw(gnuplot);

      #Debugging aid - save the temporary files if desired
      #$Chart::Graph::save_tmpfiles = 1;
      #Debugging aid - turn on extra debugging messages
      #$Chart::Graph::debug = 1;

      # Call and "usual" global parameters

      gnuplot({'title' => 'Corporate stock values for a major computer maker',
               'x-axis label' => 'Month and Year',
               'y-axis label' => 'Stock price',
               'output type' => 'png',
               'output file' => 'gnuplot3.png',
               # Setting date/time specific options.
               'xdata' => 'time',
               'timefmt' => '%m/%d/%Y',
               'format' => ['x', '%m/%d/%Y'],
               # Set output range - note quoting of date string
               'xrange' => '["06/01/2000":"08/01/2001"]',
               'extra_opts' => join("\n", 'set grid', 'set timestamp'),
              },
              # Data for when stock opened
              [{'title' => 'open',
                'type' => 'matrix',
                'style' => 'lines',
               },
               [
                ['06/01/2000',  '81.75'],
                ['07/01/2000', '52.125'],
                ['08/01/2000', '50.3125'],
                ['09/01/2000', '61.3125'],
                ['10/01/2000', '26.6875'],
                ['11/01/2000', '19.4375'],
                ['12/01/2000', '17'],
                ['01/01/2001', '14.875'],
                ['02/01/2001', '20.6875'],
                ['03/01/2001', '17.8125'],
                ['04/01/2001', '22.09'],
                ['05/01/2001', '25.41'],
                ['06/01/2001', '20.13'],
                ['07/01/2001', '23.64'],
                ['08/01/2001', '19.01'],
               ]
              ],

              # Data for stock high
              [{'title' => 'high',
                'type' => 'matrix',
                'style' => 'lines',
               },
               [
                ['06/01/2000', '103.9375'],
                ['07/01/2000', '60.625'],
                ['08/01/2000', '61.50'],
                ['09/01/2000', '64.125'],
                ['10/01/2000', '26.75'],
                ['11/01/2000', '23'],
                ['12/01/2000', '17.50'],
                ['01/01/2001', '22.50'],
                ['02/01/2001', '21.9375'],
                ['03/01/2001', '23.75'],
                ['04/01/2001', '27.12'],
                ['05/01/2001', '26.70'],
                ['06/01/2001', '25.10'],
                ['07/01/2001', '25.22'],
                ['08/01/2001', '19.90'],
               ]
              ],

              # Data for stock close
              [{'title' => 'close',
                'type' => 'matrix',
                'style' => 'lines',
               },
               [

                ['06/01/2000', '52.375'],
                ['07/01/2000', '50.8125'],
                ['08/01/2000', '60.9375'],
                ['09/01/2000', '25.75'],
                ['10/01/2000', '19.5625'],
                ['11/01/2000', '16.50'],
                ['12/01/2000', '14.875'],
                ['01/01/2001', '21.625'],
                ['02/01/2001', '18.25'],
                ['03/01/2001', '22.07'],
                ['04/01/2001', '25.49'],
                ['05/01/2001', '19.95'],
                ['06/01/2001', '23.25'],
                ['07/01/2001', '18.79'],
                ['08/01/2001', '18.55'],
               ]
              ]
    );

gnuplot3.png

## UNIX TIMESTAMPS

Chart::Graph::Gnuplot can convert Unix timestamps into normal dates for x-axis values. Collisions with existing user x-tics are can be remedied by prepending a literal '\n' (or ``\\n'') to their tic-labels. The 'uts' option takes an array ref with 2 to 4 elements: [ start_timestamp, end_timestamp, <scale>, <use_local_timezone> ] If the optional element 'scale' is > 1 the number of tics will be reduced. If the optional element 'use_local_timezone' is set to non-zero value the local timezone is used, UTC is assumed otherwise. The variables $Chart::Graph::Gnuplot::show_year and $Chart::Graph::Gnuplot::show_seconds influence the formatting of the x-tics.

        [...]

        %options = (
                     'title' => 'uts example',
                     'output file' => 'gnuplot4.gif',
                     'output type' => 'gif',
                     'x2-axis label' => 'time',
                     'xtics' => [ ['\n9pm UTC', 954795600] ],
                     'ytics' => [10,20,30,40,50],
                     'extra_opts' => 'set nokey',
                     'uts' => [954791100, 954799300],
                   );

        $plot = [{'title' => 'Your title',
                  'type' => 'matrix'},
                  [
                    [954792100, 10],
                    [954793100, 18],
                    [954794100, 12],
                    [954795100, 26],
                    [954795600, 13], # 21:00
                    [954796170, 23],
                    [954797500, 37],
                    [954799173, 20],
                    [954799300, 48],
                  ],
                ];

        gnuplot(\%options, $plot);

gnuplot4.gif

Note: The present implementation of UNIX time stamps only supports assigning xtics for x-axis labels. Using the Gnuplot directive: `format` is not supported.

## FUNCTIONS

Chart::Graph::Gnuplot supports the plotting of functions, this can be mixed with other data-types:

       my %options = (
                       'title' => 'plot functions example',
                       'output file' => 'gnuplot5.png',
                     );

       my $data = [{ 'title' => 'data 1',
                     'style' => 'lines',
                     'type' => 'matrix',
                   },
                   [
                     [0,10],
                     [3,30],
                     [6,0],
                     [9,-10],
                     [12,-0],
                   ]
                  ];

       my $fnc1 = [{ 'title' => 'function 1',
                     'style' => 'lines',
                     'type' => 'function',
                   },
                   '10*sin(x)+2*cos(1.1 * x)+.5*tan(x)'
                  ];

       my $fnc2 = [{ 'title' => 'function 2',
                     'style' => 'lines',
                     'type' => 'function',
                   },
                  '20*sin(sqrt(2**x))/sqrt(2**x)'
                  ];

        gnuplot(\%options, $data, $fnc1, $fnc2);

gnuplot5.png

# MORE INFO

This version of Chart::Graph::Gnuplot was tested against Gnuplot Version 4.0 patchlevel 0, some features might not work on older versions of gnuplot.

For more information on gnuplot, please see the gnuplot web page:

     http://www.gnuplot.org/

# CONTACT

Send email to graph-dev@caida.org is you have problems, questions, or comments. To subscribe to the mailing list send mail to graph-dev-request@caida.org with a body of ``subscribe your@email.com''

# AUTHOR

     CAIDA Perl development team (cpan@caida.org)

# SEE ALSO

     gnuplot(1).