The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Gnuplot::Builder::Script - object-oriented builder for gnuplot script

SYNOPSIS

    use Gnuplot::Builder::Script;
    
    my $builder = Gnuplot::Builder::Script->new(<<EOT);
    terminal = png size 500,500 enhanced
    grid     = x y
    xrange   = [-10:10]
    yrange   = [-1:1]
    xlabel   = x offset 0,1
    ylabel   = y offset 1,0
    output   = "sin_wave.png"
    -key
    EOT
    
    $builder->define('f(x) = sin(pi * x)');
    $builder->plot("f(x)");                 ## output sin_wave.png
    
    my $child = $builder->new_child;
    $child->define('f(x) = cos(pi * x)');   ## override parent's setting
    $child->set('output = "cos_wave.png"'); ## override parent's setting
    $child->plot("f(x)");                   ## output cos_wave.png

DESCRIPTION

This is a beta release. API may change in the future.

Gnuplot::Builder::Script is a builder object for a gnuplot script.

The advantages of this module over just printing script text are:

  • It keeps option settings and definitions in a hash-like data structure. So you can change those items individually.

  • It accepts code-refs for script sentences, option settings and definitions. They are evaluated lazily every time it builds the script.

  • It supports prototype-based inheritance similar to JavaScript objects. A child builder can override its parent's settings.

CLASS METHODS

$builder = Gnuplot::Builder::Script->new(@set_args)

The constructor.

The argument @set_args is optional. If it's absent, it creates an empty builder. If it's set, @set_args is directly given to set() method.

OBJECT METHODS - BASICS

Most object methods return the object itself, so that you can chain those methods.

$script = $builder->to_string()

Build and return the gnuplot script string.

$builder = $buider->add($sentence, ...)

Add gnuplot script sentences to the $builder.

This is a low-level method. In most cases you should use set() and define() methods below.

$sentences is a string or a code-ref. A code-ref is evaluated in list context when it builds the script. The returned list of strings are added to the script.

You can pass more than one $sentences.

    $builder->add(<<'EOT');
    set title "sample"
    set xlabel "iteration"
    EOT
    my $unit = "sec";
    $builder->add(sub { qq{set ylabel "Time [$unit]"} });

OBJECT METHODS - GNUPLOT OPTIONS

Methods to manipulate gnuplot options (the "set" and "unset" commands).

$builder = $builder->set($opt_name => $opt_value, ...)

Set a gnuplot option named $opt_name to $opt_value. You can set more than one name-value pairs.

$opt_value is either undef, a string, an array-ref of strings or a code-ref.

  • If $opt_value is undef, the "unset" command is generated for the option.

  • If $opt_value is a string, the option is set to that string.

  • If $opt_value is an array-ref, the "set" command is repeated for each element in it. If the array is empty, no "set" or "unset" command is generated.

        $builder->set(
            terminal => 'png size 200,200',
            key      => undef,
        );
        $builder->to_string();
        ## => set terminal png size 200,200
        ## => unset key
            
        $builder->set(
            arrow => ['1 from 0,0 to 0,1', '2 from 100,0 to 0,100']
        );
        $builder->to_string();
        ## => set terminal png size 200,200
        ## => unset key
        ## => set arrow 1 0,0 to 0,1
        ## => set arrow 2 from 100,0 to 0,100
  • If $opt_value is a code-ref, it is evaluated in list context when the $builder builds the script.

        @returned_values = $opt_value->($builder, $opt_name)

    The $builder and $opt_name are given to the code-ref.

    Then, the option is generated as if $opt_name => \@returned_values was set. You can return single undef to "unset" the option.

        my %SCALE_LABEL = (1 => "", 1000 => "k", 1000000 => "M");
        my $scale = 1000;
        $builder->set(
            xlabel => sub { qq{"Traffic [$SCALE_LABEL{$scale}bps]"} },
        );

The options are stored in the $builder's hash-like structure, so you can change those options individually.

Even if the options are changed later, their order in the script is unchanged.

    $builder->set(
        terminal => 'png size 500,500',
        xrange => '[100:200]',
        output => '"foo.png"',
    );
    $builder->to_string();
    ## => set terminal png size 500,500
    ## => set xrange [100:200]
    ## => set output "foo.png"
    
    $builder->set(
        terminal => 'postscript eps size 5.0,5.0',
        output => '"foo.eps"'
    );
    $builder->to_string();
    ## => set terminal postscript eps size 5.0,5.0
    ## => set xrange [100:200]
    ## => set output "foo.eps"

Note that you are free to use any string as $opt_name. In fact, there may be more than one way to build the same script.

    $builder1->set(
        'style data' => 'lines',
        'style fill' => 'solid 0.5'
    );
    $builder2->set(
        style => ['data lines', 'fill solid 0.5']
    );

In the above example, $builder1 and $builder2 generate the same script. However, $builder2 cannot change the style for "data" or "fill" individually, while $builder1 can.

$builder = $builder->set($options)

If set() method is called with a single string argument $options, it is parsed to set options.

    $builder->set(<<'EOT');
    xrange = [-5:10]
    output = "foo.png"
    grid
    -key
    
    ## terminal = png size 100,200
    terminal = pngcairo size 400,800
    
    tics = mirror in \
           rotate autojustify
    
    arrow = 1 from 0,10 to 10,0
    arrow = 2 from 5,5  to 10,10
    EOT

Here is the parsing rule:

  • Each line is a "set" or "unset" command.

  • A "set" line is a pair of option name and value with "=" between them.

        OPT_NAME = OPT_VALUE
  • An "unset" line is the option name with leading "-".

        -OPT_NAME
  • White spaces around OPT_NAME and OPT_VALUE are ignored.

  • If OPT_VALUE is an empty string in "set" line, you can omit "=".

  • Lines with a trailing backslash continue to the next line. The effect is as if the backslash and newline were not there.

  • Empty lines are ignored.

  • Lines starting with "#" are ignored.

  • You can write more than one lines for the same OPT_NAME. It's the same effect as set($opt_name => [$opt_value1, $opt_value2, ...]).

$builder = $builder->set_option(...)

set_option() is alias of set().

$builder = $builder->setq(...)

setq() method is the same as set() except that eventual option values are quoted.

This method is useful for setting "title", "xlabel", "output" etc.

    $builder->setq(
        output => "hoge.png",
        title  => "hoge's values",
    );
    $builder->to_string;
    ## => set output 'hoge.png'
    ## => set title 'hoge''s values'

If the option value is a list, it quotes the all elements.

$builder = $builder->setq_option(...)

setq_option() is alias of setq().

$builder = $builder->unset($opt_name, ...)

Short-cut for set($opt_name => undef). It generates "unset" command for the option.

You can specify more that one $opt_names.

@opt_values = $builder->get_option($opt_name)

Get the option values for $opt_name.

If $opt_name is set in the $builder, it returns its values. If a code-ref is set to the $opt_name, it is evaluated and its results are returned.

If $opt_name is not set in the $builder, the values of $builder's parent are returned. If $builder does not have parent, it returns an empty list.

Always receive the result of this method by an array, because it may return both (undef) and (). Returning an undef means the option is "unset" explicitly, while returning an empty list means no "set" or "unset" sentence for the option.

$builder = $builder->delete_option($opt_name, ...)

Delete the values for $opt_name from the $builder. You can specify more than one $opt_names.

After $opt_name is deleted, get_option($opt_name) will search the $builder's parent for the values.

Note the difference between delete_option() and unset(). While unset($opt_name) will generate "unset" sentence for the option, delete_option($opt_name) will be likely to generate no sentence (well, strictly speaking, it depends on the parent).

delete_option($opt_name) and set($opt_name => []) are also different if the $builder is a child. set() always overrides the parent setting, while delete_option() resets such overrides.

OBJECT METHODS - GNUPLOT DEFINITIONS

Methods to manipulate user-defined variables and functions.

Most methods in this category are analogous to the methods in "OBJECT METHODS - GNUPLOT OPTIONS".

    +---------------+-------------------+
    |    Options    |    Definitions    |
    +===============+===================+
    | set           | define            |
    | set_option    | set_definition    |
    | setq          | (N/A)             |
    | setq_option   | (N/A)             |
    | unset         | undefine          |
    | get_option    | get_definition    |
    | delete_option | delete_definition |
    +---------------+-------------------+

I'm sure you can understand this analogy by this example.

    $builder->set(
        xtics => 10,
        key   => undef
    );
    $builder->define(
        a      => 100,
        'f(x)' => 'sin(a * x)',
        b      => undef
    );
    $builder->to_string();
    ## => set xtics 10
    ## => unset key
    ## => a = 100
    ## => f(x) = sin(a * x)
    ## => undefine b

$builder = $builder->define($def_name => $def_value, ...)

$builder = $builder->define($definitions)

Set function and variable definitions. See set() method.

$builder = $builder->set_definition(...)

Alias for define() method.

$builder = $builder->undefine($def_name, ...)

Short-cut for define($def_name => undef). See unset() method.

@def_values = $builder->get_definition($def_name)

Get definitions from the $builder. See get_option() method.

$builder = $builder->delete_definition($def_name, ...)

Delete definitions from the $builder. See delete_option() method.

OBJECT METHODS - PLOTTING

Methods for plotting.

All plotting methods are non-mutator, that is, they don't change the state of the $builder. This means you can plot different datasets with the same settings.

Some plotting methods run a gnuplot process background, and let it do the plotting work. The variable @Gnuplot::Builder::Process::COMMAND is used to start the gnuplot process. See Gnuplot::Builder::Process for detail.

$result = $builder->plot($dataset, ...)

Build the script and plot the given $datasets with gnuplot's "plot" command. This method lets a gnuplot process do the actual job.

You can specify more than one $datasets to plot.

The return value $result is the data that the gnuplot process writes to STDOUT and STDERR.

Usually you should use a Gnuplot::Builder::Dataset object for $dataset. In this case, you can skip the rest of this section.

In detail, $dataset is either a string or an object.

  • If $dataset is a string, it's treated as the dataset parameters for "plot" command.

        $builder->plot(
            'sin(x) with lines lw 2',
            'cos(x) with lines lw 5',
            '"datafile.dat" using 1:3 with points ps 4'
        );
  • If $dataset is an object, it must implement params_string() and write_data_to() methods (like Gnuplot::Builder::Dataset).

    params_string() method is supposed to return a string of the dataset parameters, and write_data_to() method provide the inline data if it has.

    The two methods are called like

        ($params_str) = $dataset->params_string();
        $dataset->write_data_to($writer);

    where $writer is a code-ref that you must call with the inline data you have.

        package My::Data;
        
        sub new {
            my ($class, $x_data, $y_data) = @_;
            return bless { x => $x_data, y => $y_data }, $class;
        }
        
        sub params_string { q{"-" using 1:2 title "My Data" with lp} }
        
        sub write_data_to {
            my ($self, $writer) = @_;
            foreach my $i (0 .. $#{$self->{x}}) {
                my ($x, $y) = ($self->{x}[$i], $self->{y}[$i]);
                $writer->("$x $y\n");
            }
        }
        
        $builder->plot(My::Data->new([1,2,3], [1,4,9]));

    If write_data_to() method doesn't pass any data to the $writer, the plot() method doesn't generate the inline data section.

$result = $builder->plot_with(%args)

Plot with more functionalities than plot() method.

Fields in %args are

dataset => DATASETS (mandatory)

Datasets to plot. It is either a dataset or an array-ref of datasets. See plot() for specification of datasets.

output => OUTPUT_FILENAME (optional)

If set, "set output" command is printed just before "plot" command, so that it would output the plot to the specified file. The specified file name is quoted. After "plot" command, it prints "set output" command with no argument to unlock the file.

If not set, it won't print "set output" commands.

writer => CODE-REF (optional)

A code-ref to receive the whole script string. If set, it is called one or more times with the script string that $builder builds. In this case, the return value $result will be an empty string.

If not set, $builder streams the script into the gnuplot process. The return value $result will be the data the gnuplot process writes to STDOUT and STDERR.

async => BOOL (optional, default: false)

If set to true, it won't wait for the gnuplot process to finish. In this case, the return value $result will be an empty string.

Using async option, you can run more than one gnuplot processes to do the job. However, the maximum number of gnuplot processes are limited to the variable $Gnuplot::Builder::Process::MAX_PROCESSES. See Gnuplot::Builder::Process for detail.

If set to false, which is the default, it waits for the gnuplot process to finish and return its output.

    my $script = "";
    $builder->plot_with(
        dataset => ['sin(x)', 'cos(x)'],
        output  => "hoge.eps",
        writer  => sub {
            my ($script_part) = @_;
            $script .= $script_part;
        }
    );
    
    $script;
    ## => set output 'hoge.eps'
    ## => plot sin(x),cos(x)
    ## => set output

$result = $builder->splot($dataset, ...)

Same as plot() method except it uses "splot" command.

$result = $builder->splot_with(%args)

Same as plot_with() method except it uses "splot" command.

OBJECT METHODS - INHERITANCE

A Gnuplot::Builder::Script object can extend and/or override another Gnuplot::Builder::Script object. This is similar to JavaScript's prototype-based inheritance.

Let $parent and $child be the parent and its child builder, respectively. Then $child builds a script on top of what $parent builds. That is,

  • Sentences added by $child->add() method are appended to the $parent's script.

  • Option settings and definitions in $child are appended to the $parent's script, if they are not set in $parent.

  • Option settings and definitions in $child are substituted in the $parent's script, if they are already set in $parent.

$builder = $builder->set_parent($parent_builder)

Set $parent_builder as the $builder's parent.

If $parent_builder is undef, $builder doesn't have a parent anymore.

$parent_builder = $builder->get_parent()

Return the $builder's parent. It returns undef if $builder does not have a parent.

$child_builder = $builder->new_child()

Create and return a new child builder of $builder.

This is a short-cut for Gnuplot::Builder::Script->new->set_parent($builder).

OVERLOAD

When you evaluate a $builder as a string, it executes $builder->to_string(). That is,

    "$builder" eq $builder->to_string;

SEE ALSO

Gnuplot::Builder::Dataset

AUTHOR

Toshio Ito, <toshioito at cpan.org>