mirror of
https://github.com/dkogan/feedgnuplot.git
synced 2025-05-05 22:11:12 +08:00
Merge branch 'master' into debian
This commit is contained in:
commit
ae7ce22afc
11
Changes
11
Changes
@ -1,4 +1,11 @@
|
|||||||
feedgnuplot (1.57) unstable; urgency=medium
|
feedgnuplot (1.58)
|
||||||
|
|
||||||
|
* Added --using, --usingall
|
||||||
|
* Added --cmds as a synonym for --extracmds
|
||||||
|
|
||||||
|
-- Dima Kogan <dkogan@debian.org> Thu, 11 Mar 2021 16:24:46 -0800
|
||||||
|
|
||||||
|
feedgnuplot (1.57)
|
||||||
|
|
||||||
* Added --xticlabels to label the x-axis tics from the data
|
* Added --xticlabels to label the x-axis tics from the data
|
||||||
* Added --equation-above and --equation-below to control the equation
|
* Added --equation-above and --equation-below to control the equation
|
||||||
@ -6,7 +13,7 @@ feedgnuplot (1.57) unstable; urgency=medium
|
|||||||
|
|
||||||
-- Dima Kogan <dkogan@debian.org> Sun, 21 Feb 2021 13:56:23 -0800
|
-- Dima Kogan <dkogan@debian.org> Sun, 21 Feb 2021 13:56:23 -0800
|
||||||
|
|
||||||
feedgnuplot (1.56) unstable; urgency=medium
|
feedgnuplot (1.56)
|
||||||
|
|
||||||
* Updated default hardcopy settings
|
* Updated default hardcopy settings
|
||||||
|
|
||||||
|
114
README.pod
114
README.pod
@ -92,13 +92,12 @@ points. New curves will be created as needed.
|
|||||||
|
|
||||||
The most commonly used functionality of gnuplot is supported directly by the
|
The most commonly used functionality of gnuplot is supported directly by the
|
||||||
script. Anything not directly supported can still be done with options such as
|
script. Anything not directly supported can still be done with options such as
|
||||||
C<--set>, C<--extracmds> C<--style>, etc. Arbitrary gnuplot commands can be
|
C<--set>, C<--cmds> C<--style>, etc. Arbitrary gnuplot commands can be passed in
|
||||||
passed in with C<--extracmds>. For example, to turn off the grid, you can pass
|
with C<--cmds>. For example, to turn off the grid, you can pass in C<--cmds
|
||||||
in C<--extracmds 'unset grid'>. Commands C<--set> and C<--unset> exists to
|
'unset grid'>. Commands C<--set> and C<--unset> exists to provide nicer syntax,
|
||||||
provide nicer syntax, so this is equivalent to passing C<--unset grid>. As many
|
so this is equivalent to passing C<--unset grid>. As many of these options as
|
||||||
of these options as needed can be passed in. To add arbitrary curve styles, use
|
needed can be passed in. To add arbitrary curve styles, use C<--style curveID
|
||||||
C<--style curveID extrastyle>. Pass these more than once to affect more than one
|
extrastyle>. Pass these more than once to affect more than one curve.
|
||||||
curve.
|
|
||||||
|
|
||||||
To apply an extra style to I<all> the curves that lack an explicit C<--style>,
|
To apply an extra style to I<all> the curves that lack an explicit C<--style>,
|
||||||
pass in C<--styleall extrastyle>. In the most common case, the extra style is
|
pass in C<--styleall extrastyle>. In the most common case, the extra style is
|
||||||
@ -239,6 +238,79 @@ Note that while gnuplot supports the time/date on any axis, I<feedgnuplot>
|
|||||||
currently supports it I<only> as the x-axis domain. This may change in the
|
currently supports it I<only> as the x-axis domain. This may change in the
|
||||||
future.
|
future.
|
||||||
|
|
||||||
|
=head3 'using' expressions
|
||||||
|
|
||||||
|
We just described how feedgnuplot parses its input data. When passing this data
|
||||||
|
to gnuplot, each curve is sent independently. The domain appears in the leading
|
||||||
|
columns followed by C<--rangesize> columns to complete each row. Without
|
||||||
|
C<--domain>, feedgnuplot explicitly writes out sequential integers. gnuplot then
|
||||||
|
knows how many values it has for each point, and it knows which style we're
|
||||||
|
using, so it's able to interpret the data appropriately, and to make the correct
|
||||||
|
plot.
|
||||||
|
|
||||||
|
As an example, if gnuplot is passed 2 columns of data, and it is plotting C<with
|
||||||
|
points>, it will use column 1 for the x coordinate and column 2 for the y
|
||||||
|
coordinate. This is the default behavior, but the meaning of each column can be
|
||||||
|
controlled via a C<using> expression in gnuplot (not feedgnuplot; keep reading).
|
||||||
|
The default is sequential integers, so this example uses C<using 1:2> by
|
||||||
|
default. We can flip the meaning of the columns by passing C<using 2:1>.
|
||||||
|
Arbitrary expressions may be specified by enclosing each field in C<()>, and
|
||||||
|
using C<$> to denote each data column. So to use the 2nd column as the x
|
||||||
|
coordinate and the sum of the two columns as the y coordinate, C<using
|
||||||
|
2:($1+$2)> is passed. Furthermore, the number of columns can vary. For instance
|
||||||
|
gnuplot can read the same two columns of data, but produce a plot with the extra
|
||||||
|
column encoding the sum as the color: C<using 1:2:($1+$2) with points palette>.
|
||||||
|
Please see the gnuplot documentation for lots of detail.
|
||||||
|
|
||||||
|
That's how I<gnuplot> works. Most of the time, I<feedgnuplot> doesn't pass any
|
||||||
|
C<using> expressions at all, and gnuplot does the default thing. But if we want
|
||||||
|
to do something fancy, feedgnuplot supports C<--using curveID expression> and
|
||||||
|
C<--usingall expression>. So we can plot a parabola:
|
||||||
|
|
||||||
|
seq 100 | feedgnuplot --lines --usingall '1:($2*$2)'
|
||||||
|
|
||||||
|
This is powerful, but there are some things to keep in mind:
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--using> overrides whatever C<using> expression feedgnuplot was going to pass.
|
||||||
|
feedgnuplot passes a C<using> expression only if C<--histogram> or C<--timefmt>
|
||||||
|
or C<--xticlabels> are given. So if C<--using> is given together with any of
|
||||||
|
these, the user must take care to do the right thing (whatever that means at
|
||||||
|
that time).
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
The C<--tuplesize> controls the data passed to feedgnuplot and the data then
|
||||||
|
passed to gnuplot. It does I<not> directly control how gnuplot eventually
|
||||||
|
interprets the data: C<--using> does that. So for instance we can plot
|
||||||
|
color-coded points:
|
||||||
|
|
||||||
|
seq 10 | feedgnuplot --with 'points pt 7 palette' --usingall '1:2:2'
|
||||||
|
|
||||||
|
Here feedgnuplot read 1 column of data. It defauled to C<--tuplesize 2>, so it
|
||||||
|
passed 2 columns of data to gnuplot. gnuplot then produced 3 values for each
|
||||||
|
point, and plotted them as indicated with the C<points palette> style.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
You I<always> need a column of data to generate a curve. You might want to use a
|
||||||
|
C<using> expression to plot a time series I<and> its cumulative integral. The
|
||||||
|
C<using> expression can compute the integral, but you I<must> pass in the data
|
||||||
|
twice; once for each curve to plot:
|
||||||
|
|
||||||
|
seq 100 | \
|
||||||
|
awk '{print $1,$1}' | \
|
||||||
|
feedgnuplot \
|
||||||
|
--cmds 'sum=0' \
|
||||||
|
--cmds 'accum(x) = (sum=sum+x)' \
|
||||||
|
--using 1 '1:(accum($2))' \
|
||||||
|
--lines --y2 1
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=head2 Real-time streaming data
|
=head2 Real-time streaming data
|
||||||
|
|
||||||
To plot real-time data, pass in the C<--stream [refreshperiod]> option. Data
|
To plot real-time data, pass in the C<--stream [refreshperiod]> option. Data
|
||||||
@ -586,8 +658,8 @@ C<--xticlabels>
|
|||||||
If given, the x-axis tic labels are not numerical, but are read from the data.
|
If given, the x-axis tic labels are not numerical, but are read from the data.
|
||||||
This changes the interpretation of the input data: with C<--domain>, each line
|
This changes the interpretation of the input data: with C<--domain>, each line
|
||||||
begins with C<x label ....>. Without C<--domain>, each line begins with C<label
|
begins with C<x label ....>. Without C<--domain>, each line begins with C<label
|
||||||
...>. This does I<not> affect the tuple size. This makes sense only without
|
...>. Clearly, the labels may not contain whitespace. This does I<not> affect
|
||||||
C<--3d>. Please see the guide
|
the tuple size. This makes sense only without C<--3d>. Please see the guide
|
||||||
(L<https://github.com/dkogan/feedgnuplot/blob/master/guide/guide.org>) for usage
|
(L<https://github.com/dkogan/feedgnuplot/blob/master/guide/guide.org>) for usage
|
||||||
examples.
|
examples.
|
||||||
|
|
||||||
@ -671,13 +743,35 @@ I<all> the curves.
|
|||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
C<--extracmds xxx>
|
C<--using curveID expression>
|
||||||
|
|
||||||
|
Specifies a C<using> expression to micromanage the plot. This is a powerful
|
||||||
|
option that allows gnuplot to interpret the input data in arbitrary ways. A
|
||||||
|
C<using> expression tells gnuplot how to map the input columns of data to tuples
|
||||||
|
expected by the plotting style. Please see the L</"'using' expressions"> section above for more detail.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--usingall expression>
|
||||||
|
|
||||||
|
Global "using" expressions. This works exactly like C<--using>, except it
|
||||||
|
applies to I<all> the curves.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--cmds xxx>
|
||||||
|
|
||||||
Additional commands to pass on to gnuplot verbatim. These could contain extra
|
Additional commands to pass on to gnuplot verbatim. These could contain extra
|
||||||
global styles for instance. Can be passed multiple times.
|
global styles for instance. Can be passed multiple times.
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
|
C<--extracmds xxx>
|
||||||
|
|
||||||
|
Synonym for C<--cmds xxx>
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
C<--set xxx>
|
C<--set xxx>
|
||||||
|
|
||||||
Additional 'set' commands to pass on to gnuplot verbatim. C<--set 'a b c'> will
|
Additional 'set' commands to pass on to gnuplot verbatim. C<--set 'a b c'> will
|
||||||
|
251
bin/feedgnuplot
251
bin/feedgnuplot
@ -16,7 +16,7 @@ use Pod::Usage;
|
|||||||
use Time::Piece;
|
use Time::Piece;
|
||||||
|
|
||||||
# Makefile.PL assumes this is in ''
|
# Makefile.PL assumes this is in ''
|
||||||
my $VERSION = '1.57';
|
my $VERSION = '1.58';
|
||||||
|
|
||||||
my %options;
|
my %options;
|
||||||
interpretCommandline();
|
interpretCommandline();
|
||||||
@ -91,11 +91,13 @@ sub interpretCommandline
|
|||||||
$options{curvestyle} = [];
|
$options{curvestyle} = [];
|
||||||
$options{style} = [];
|
$options{style} = [];
|
||||||
$options{every} = [];
|
$options{every} = [];
|
||||||
|
$options{using} = [];
|
||||||
$options{histogram} = [];
|
$options{histogram} = [];
|
||||||
$options{x1y2} = [];
|
$options{x1y2} = [];
|
||||||
$options{x2y1} = [];
|
$options{x2y1} = [];
|
||||||
$options{x2y2} = [];
|
$options{x2y2} = [];
|
||||||
$options{extracmds} = [];
|
$options{extracmds} = [];
|
||||||
|
$options{cmds} = [];
|
||||||
$options{set} = [];
|
$options{set} = [];
|
||||||
$options{unset} = [];
|
$options{unset} = [];
|
||||||
$options{equation} = [];
|
$options{equation} = [];
|
||||||
@ -119,8 +121,11 @@ sub interpretCommandline
|
|||||||
'ymin=f', 'ymax=f', 'y2min=f', 'y2max=f',
|
'ymin=f', 'ymax=f', 'y2min=f', 'y2max=f',
|
||||||
'zmin=f', 'zmax=f',
|
'zmin=f', 'zmax=f',
|
||||||
'x2=s@', 'y2=s@', 'x1y2=s@', 'x2y1=s@', 'x2y2=s@',
|
'x2=s@', 'y2=s@', 'x1y2=s@', 'x2y1=s@', 'x2y2=s@',
|
||||||
'style=s{2}', 'curvestyle=s{2}', 'curvestyleall=s', 'styleall=s', 'with=s', 'extracmds=s@', 'set=s@', 'unset=s@',
|
'style=s{2}', 'curvestyle=s{2}', 'curvestyleall=s', 'styleall=s', 'with=s',
|
||||||
|
'extracmds=s@', 'cmds=s@',
|
||||||
|
'set=s@', 'unset=s@',
|
||||||
'every=s{2}', 'everyall=s',
|
'every=s{2}', 'everyall=s',
|
||||||
|
'using=s{2}', 'usingall=s',
|
||||||
'square!', 'square_xy!', 'square-xy!', 'squarexy!', 'hardcopy=s', 'maxcurves=i', 'monotonic!', 'timefmt=s',
|
'square!', 'square_xy!', 'square-xy!', 'squarexy!', 'hardcopy=s', 'maxcurves=i', 'monotonic!', 'timefmt=s',
|
||||||
'equation=s@', 'equation-below=s@', 'equation-above=s@',
|
'equation=s@', 'equation-below=s@', 'equation-above=s@',
|
||||||
'image=s',
|
'image=s',
|
||||||
@ -158,6 +163,9 @@ sub interpretCommandline
|
|||||||
# various square-xy synonyms
|
# various square-xy synonyms
|
||||||
$options{'square_xy'} = 1 if $options{'square-xy'} || $options{'squarexy'};
|
$options{'square_xy'} = 1 if $options{'square-xy'} || $options{'squarexy'};
|
||||||
|
|
||||||
|
# --extracmds is a synonym for --cmds
|
||||||
|
push @{$options{extracmds}}, @{$options{cmds}};
|
||||||
|
$options{cmds} = [];
|
||||||
|
|
||||||
push @{$options{curvestyle}}, @{$options{style}};
|
push @{$options{curvestyle}}, @{$options{style}};
|
||||||
delete $options{style};
|
delete $options{style};
|
||||||
@ -185,7 +193,7 @@ sub interpretCommandline
|
|||||||
@{$options{$listkey}} = map split('\s*,\s*', $_), @{$options{$listkey}}
|
@{$options{$listkey}} = map split('\s*,\s*', $_), @{$options{$listkey}}
|
||||||
if defined $options{$listkey};
|
if defined $options{$listkey};
|
||||||
}
|
}
|
||||||
for my $listkey (qw(curvestyle rangesize tuplesize every))
|
for my $listkey (qw(curvestyle rangesize tuplesize every using))
|
||||||
{
|
{
|
||||||
next unless defined $options{$listkey};
|
next unless defined $options{$listkey};
|
||||||
my @in = @{$options{$listkey}};
|
my @in = @{$options{$listkey}};
|
||||||
@ -260,7 +268,7 @@ sub interpretCommandline
|
|||||||
# arrays in order to preserve the ordering. I parse both of these into hashes
|
# arrays in order to preserve the ordering. I parse both of these into hashes
|
||||||
# because those are useful to have later. After this I can access individual
|
# because those are useful to have later. After this I can access individual
|
||||||
# legends with $options{legend_hash}{curveid}
|
# legends with $options{legend_hash}{curveid}
|
||||||
for my $listkey (qw(legend curvestyle rangesize every))
|
for my $listkey (qw(legend curvestyle rangesize every using))
|
||||||
{
|
{
|
||||||
$options{"${listkey}_hash"} = {};
|
$options{"${listkey}_hash"} = {};
|
||||||
|
|
||||||
@ -808,48 +816,29 @@ sub mainThread
|
|||||||
print(PIPE "set view equal xy\n");
|
print(PIPE "set view equal xy\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
# For the specified values, set the legend entries to 'title "blah blah"'
|
for my $what_options_prefix_suffix ( ['curvestyle', 'extraoptions', '', ' ' ],
|
||||||
if(@{$options{legend}})
|
['every', 'everyoptions', 'every ', ' ' ],
|
||||||
|
['using', 'usingoptions', 'using ', ' ' ],
|
||||||
|
['legend', 'title', '', '' ])
|
||||||
{
|
{
|
||||||
# @{$options{legend}} is a list where consecutive pairs are (curveID,
|
my ($what, $options, $prefix, $suffix) = @$what_options_prefix_suffix;
|
||||||
# legend). I use $options{legend} here instead of $options{legend_hash}
|
|
||||||
# because I create a new curve when I see a new one, and the hash is
|
# @{$options{$what}} is a list where consecutive pairs are (curveID, style).
|
||||||
# unordered, thus messing up the ordering
|
if (@{$options{$what}})
|
||||||
my $n = scalar @{$options{legend}}/2;
|
{
|
||||||
|
my $n = scalar @{$options{$what}}/2;
|
||||||
foreach my $idx (0..$n-1)
|
foreach my $idx (0..$n-1)
|
||||||
{
|
{
|
||||||
setCurveLabel($options{legend}[$idx*2 ],
|
addOption($options{$what}[$idx*2 ],
|
||||||
$options{legend}[$idx*2 + 1]);
|
$options,
|
||||||
|
$prefix . $options{$what}[$idx*2 + 1] . $suffix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# add the extra curve options
|
addOption($_, 'extraoptions', 'axes x1y2 ') foreach (@{$options{x1y2}});
|
||||||
if(@{$options{curvestyle}})
|
addOption($_, 'extraoptions', 'axes x2y1 ') foreach (@{$options{x2y1}});
|
||||||
{
|
addOption($_, 'extraoptions', 'axes x2y2 ') foreach (@{$options{x2y2}});
|
||||||
# @{$options{curvestyle}} is a list where consecutive pairs are (curveID,
|
|
||||||
# style).
|
|
||||||
my $n = scalar @{$options{curvestyle}}/2;
|
|
||||||
foreach my $idx (0..$n-1)
|
|
||||||
{
|
|
||||||
addCurveOption($options{curvestyle}[$idx*2 ],
|
|
||||||
$options{curvestyle}[$idx*2 + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(@{$options{every}})
|
|
||||||
{
|
|
||||||
# @{$options{every}} is a list where consecutive pairs are (curveID,
|
|
||||||
# every).
|
|
||||||
my $n = scalar @{$options{every}}/2;
|
|
||||||
foreach my $idx (0..$n-1)
|
|
||||||
{
|
|
||||||
addEveryOption($options{every}[$idx*2 ],
|
|
||||||
$options{every}[$idx*2 + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addCurveOption($_, 'axes x1y2') foreach (@{$options{x1y2}});
|
|
||||||
addCurveOption($_, 'axes x2y1') foreach (@{$options{x2y1}});
|
|
||||||
addCurveOption($_, 'axes x2y2') foreach (@{$options{x2y2}});
|
|
||||||
|
|
||||||
# timefmt
|
# timefmt
|
||||||
if( $options{timefmt} )
|
if( $options{timefmt} )
|
||||||
@ -863,8 +852,16 @@ sub mainThread
|
|||||||
print PIPE
|
print PIPE
|
||||||
"set boxwidth $options{binwidth}\n" .
|
"set boxwidth $options{binwidth}\n" .
|
||||||
"histbin(x) = $options{binwidth} * floor(0.5 + x/$options{binwidth})\n";
|
"histbin(x) = $options{binwidth} * floor(0.5 + x/$options{binwidth})\n";
|
||||||
|
foreach my $id (@{$options{histogram}})
|
||||||
setCurveAsHistogram( $_ ) foreach (@{$options{histogram}});
|
{
|
||||||
|
# With histograms I have 2d plots with rangesize=1. I thus give gnuplot two
|
||||||
|
# values for each point: a domain and a range. For histograms I ignore the
|
||||||
|
# domain, so I get the statistics of the 2nd column: $2
|
||||||
|
addOption($id,
|
||||||
|
'usingoptions',
|
||||||
|
'using (histbin($2)):(1.0) smooth ' . $options{histstyle},
|
||||||
|
'do-not-override');
|
||||||
|
}
|
||||||
|
|
||||||
if(@{$options{x2y1}} || @{$options{x2y2}})
|
if(@{$options{x2y1}} || @{$options{x2y2}})
|
||||||
{
|
{
|
||||||
@ -1199,16 +1196,20 @@ sub updateCurveOptions
|
|||||||
# use the given title, unless we're generating a legend automatically. Given titles
|
# use the given title, unless we're generating a legend automatically. Given titles
|
||||||
# override autolegend
|
# override autolegend
|
||||||
my $title;
|
my $title;
|
||||||
if(defined $curve->{title})
|
if(defined $curve->{title} && length($curve->{title}))
|
||||||
{ $title = $curve->{title}; }
|
{ $title = $curve->{title}; }
|
||||||
elsif( $options{autolegend} )
|
elsif( $options{autolegend} )
|
||||||
{ $title = $id; }
|
{ $title = $id; }
|
||||||
|
|
||||||
my $titleoption = defined $title ? "title \"$title\"" : "notitle";
|
my $titleoption = defined $title ? "title \"$title\"" : "notitle";
|
||||||
my $histoptions = $curve->{histoptions} || '';
|
|
||||||
|
|
||||||
my $usingoptions = '';
|
my $usingoptions = $curve->{usingoptions};
|
||||||
if( $options{timefmt} && !$histoptions )
|
if( length($usingoptions) )
|
||||||
|
{
|
||||||
|
# user specified a 'using' option. I just do that, and don't look at
|
||||||
|
# anything else
|
||||||
|
}
|
||||||
|
elsif( $options{timefmt} )
|
||||||
{
|
{
|
||||||
# with --timefmt I need an explicit 'using' specification. I specify the
|
# with --timefmt I need an explicit 'using' specification. I specify the
|
||||||
# columns as 1:2:3..... I need the right number of columns (this is given
|
# columns as 1:2:3..... I need the right number of columns (this is given
|
||||||
@ -1234,7 +1235,7 @@ sub updateCurveOptions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$curve->{options} = "$curve->{everyoptions} $histoptions $usingoptions $titleoption $curve->{extraoptions}";
|
$curve->{options} = "$curve->{everyoptions} $usingoptions $titleoption $curve->{extraoptions}";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getCurve
|
sub getCurve
|
||||||
@ -1261,6 +1262,10 @@ sub getCurve
|
|||||||
everyoptions => (!exists $options{every_hash}{$id} &&
|
everyoptions => (!exists $options{every_hash}{$id} &&
|
||||||
exists $options{everyall}) ?
|
exists $options{everyall}) ?
|
||||||
"every $options{everyall} " : ' ',
|
"every $options{everyall} " : ' ',
|
||||||
|
usingoptions => (!exists $options{using_hash}{$id} &&
|
||||||
|
exists $options{usingall}) ?
|
||||||
|
"using $options{usingall} " : '',
|
||||||
|
title => '',
|
||||||
datastring => '',
|
datastring => '',
|
||||||
datastring_meta => [],
|
datastring_meta => [],
|
||||||
datastring_offset => 0}; # push a curve with no data and no options
|
datastring_offset => 0}; # push a curve with no data and no options
|
||||||
@ -1291,44 +1296,16 @@ sub getCurve
|
|||||||
return $curveFromID{$id};
|
return $curveFromID{$id};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub addCurveOption
|
sub addOption
|
||||||
{
|
{
|
||||||
my ($id, $str) = @_;
|
my ($id, $which, $str, $do_not_override) = @_;
|
||||||
|
|
||||||
my $curve = getCurve($id);
|
my $curve = getCurve($id);
|
||||||
$curve->{extraoptions} .= "$str ";
|
if(!$do_not_override || length($curve->{$which})==0)
|
||||||
|
{
|
||||||
|
$curve->{$which} .= $str;
|
||||||
updateCurveOptions($curve, $id);
|
updateCurveOptions($curve, $id);
|
||||||
}
|
}
|
||||||
sub addEveryOption
|
|
||||||
{
|
|
||||||
my ($id, $str) = @_;
|
|
||||||
|
|
||||||
my $curve = getCurve($id);
|
|
||||||
$curve->{everyoptions} .= "every $str ";
|
|
||||||
updateCurveOptions($curve, $id);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub setCurveLabel
|
|
||||||
{
|
|
||||||
my ($id, $str) = @_;
|
|
||||||
|
|
||||||
my $curve = getCurve($id);
|
|
||||||
$curve->{title} = $str;
|
|
||||||
updateCurveOptions($curve, $id);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub setCurveAsHistogram
|
|
||||||
{
|
|
||||||
my ($id, $str) = @_;
|
|
||||||
|
|
||||||
my $curve = getCurve($id);
|
|
||||||
|
|
||||||
# With histograms I have 2d plots with rangesize=1. I thus give gnuplot two
|
|
||||||
# values for each point: a domain and a range. For histograms I ignore the
|
|
||||||
# domain, so I get the statistics of the 2nd column: $2
|
|
||||||
$curve->{histoptions} = 'using (histbin($2)):(1.0) smooth ' . $options{histstyle};
|
|
||||||
|
|
||||||
updateCurveOptions($curve, $id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# remove all the curve data
|
# remove all the curve data
|
||||||
@ -1501,13 +1478,12 @@ points. New curves will be created as needed.
|
|||||||
|
|
||||||
The most commonly used functionality of gnuplot is supported directly by the
|
The most commonly used functionality of gnuplot is supported directly by the
|
||||||
script. Anything not directly supported can still be done with options such as
|
script. Anything not directly supported can still be done with options such as
|
||||||
C<--set>, C<--extracmds> C<--style>, etc. Arbitrary gnuplot commands can be
|
C<--set>, C<--cmds> C<--style>, etc. Arbitrary gnuplot commands can be passed in
|
||||||
passed in with C<--extracmds>. For example, to turn off the grid, you can pass
|
with C<--cmds>. For example, to turn off the grid, you can pass in C<--cmds
|
||||||
in C<--extracmds 'unset grid'>. Commands C<--set> and C<--unset> exists to
|
'unset grid'>. Commands C<--set> and C<--unset> exists to provide nicer syntax,
|
||||||
provide nicer syntax, so this is equivalent to passing C<--unset grid>. As many
|
so this is equivalent to passing C<--unset grid>. As many of these options as
|
||||||
of these options as needed can be passed in. To add arbitrary curve styles, use
|
needed can be passed in. To add arbitrary curve styles, use C<--style curveID
|
||||||
C<--style curveID extrastyle>. Pass these more than once to affect more than one
|
extrastyle>. Pass these more than once to affect more than one curve.
|
||||||
curve.
|
|
||||||
|
|
||||||
To apply an extra style to I<all> the curves that lack an explicit C<--style>,
|
To apply an extra style to I<all> the curves that lack an explicit C<--style>,
|
||||||
pass in C<--styleall extrastyle>. In the most common case, the extra style is
|
pass in C<--styleall extrastyle>. In the most common case, the extra style is
|
||||||
@ -1648,6 +1624,79 @@ Note that while gnuplot supports the time/date on any axis, I<feedgnuplot>
|
|||||||
currently supports it I<only> as the x-axis domain. This may change in the
|
currently supports it I<only> as the x-axis domain. This may change in the
|
||||||
future.
|
future.
|
||||||
|
|
||||||
|
=head3 'using' expressions
|
||||||
|
|
||||||
|
We just described how feedgnuplot parses its input data. When passing this data
|
||||||
|
to gnuplot, each curve is sent independently. The domain appears in the leading
|
||||||
|
columns followed by C<--rangesize> columns to complete each row. Without
|
||||||
|
C<--domain>, feedgnuplot explicitly writes out sequential integers. gnuplot then
|
||||||
|
knows how many values it has for each point, and it knows which style we're
|
||||||
|
using, so it's able to interpret the data appropriately, and to make the correct
|
||||||
|
plot.
|
||||||
|
|
||||||
|
As an example, if gnuplot is passed 2 columns of data, and it is plotting C<with
|
||||||
|
points>, it will use column 1 for the x coordinate and column 2 for the y
|
||||||
|
coordinate. This is the default behavior, but the meaning of each column can be
|
||||||
|
controlled via a C<using> expression in gnuplot (not feedgnuplot; keep reading).
|
||||||
|
The default is sequential integers, so this example uses C<using 1:2> by
|
||||||
|
default. We can flip the meaning of the columns by passing C<using 2:1>.
|
||||||
|
Arbitrary expressions may be specified by enclosing each field in C<()>, and
|
||||||
|
using C<$> to denote each data column. So to use the 2nd column as the x
|
||||||
|
coordinate and the sum of the two columns as the y coordinate, C<using
|
||||||
|
2:($1+$2)> is passed. Furthermore, the number of columns can vary. For instance
|
||||||
|
gnuplot can read the same two columns of data, but produce a plot with the extra
|
||||||
|
column encoding the sum as the color: C<using 1:2:($1+$2) with points palette>.
|
||||||
|
Please see the gnuplot documentation for lots of detail.
|
||||||
|
|
||||||
|
That's how I<gnuplot> works. Most of the time, I<feedgnuplot> doesn't pass any
|
||||||
|
C<using> expressions at all, and gnuplot does the default thing. But if we want
|
||||||
|
to do something fancy, feedgnuplot supports C<--using curveID expression> and
|
||||||
|
C<--usingall expression>. So we can plot a parabola:
|
||||||
|
|
||||||
|
seq 100 | feedgnuplot --lines --usingall '1:($2*$2)'
|
||||||
|
|
||||||
|
This is powerful, but there are some things to keep in mind:
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--using> overrides whatever C<using> expression feedgnuplot was going to pass.
|
||||||
|
feedgnuplot passes a C<using> expression only if C<--histogram> or C<--timefmt>
|
||||||
|
or C<--xticlabels> are given. So if C<--using> is given together with any of
|
||||||
|
these, the user must take care to do the right thing (whatever that means at
|
||||||
|
that time).
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
The C<--tuplesize> controls the data passed to feedgnuplot and the data then
|
||||||
|
passed to gnuplot. It does I<not> directly control how gnuplot eventually
|
||||||
|
interprets the data: C<--using> does that. So for instance we can plot
|
||||||
|
color-coded points:
|
||||||
|
|
||||||
|
seq 10 | feedgnuplot --with 'points pt 7 palette' --usingall '1:2:2'
|
||||||
|
|
||||||
|
Here feedgnuplot read 1 column of data. It defauled to C<--tuplesize 2>, so it
|
||||||
|
passed 2 columns of data to gnuplot. gnuplot then produced 3 values for each
|
||||||
|
point, and plotted them as indicated with the C<points palette> style.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
You I<always> need a column of data to generate a curve. You might want to use a
|
||||||
|
C<using> expression to plot a time series I<and> its cumulative integral. The
|
||||||
|
C<using> expression can compute the integral, but you I<must> pass in the data
|
||||||
|
twice; once for each curve to plot:
|
||||||
|
|
||||||
|
seq 100 | \
|
||||||
|
awk '{print $1,$1}' | \
|
||||||
|
feedgnuplot \
|
||||||
|
--cmds 'sum=0' \
|
||||||
|
--cmds 'accum(x) = (sum=sum+x)' \
|
||||||
|
--using 1 '1:(accum($2))' \
|
||||||
|
--lines --y2 1
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=head2 Real-time streaming data
|
=head2 Real-time streaming data
|
||||||
|
|
||||||
To plot real-time data, pass in the C<--stream [refreshperiod]> option. Data
|
To plot real-time data, pass in the C<--stream [refreshperiod]> option. Data
|
||||||
@ -1995,8 +2044,8 @@ C<--xticlabels>
|
|||||||
If given, the x-axis tic labels are not numerical, but are read from the data.
|
If given, the x-axis tic labels are not numerical, but are read from the data.
|
||||||
This changes the interpretation of the input data: with C<--domain>, each line
|
This changes the interpretation of the input data: with C<--domain>, each line
|
||||||
begins with C<x label ....>. Without C<--domain>, each line begins with C<label
|
begins with C<x label ....>. Without C<--domain>, each line begins with C<label
|
||||||
...>. This does I<not> affect the tuple size. This makes sense only without
|
...>. Clearly, the labels may not contain whitespace. This does I<not> affect
|
||||||
C<--3d>. Please see the guide
|
the tuple size. This makes sense only without C<--3d>. Please see the guide
|
||||||
(L<https://github.com/dkogan/feedgnuplot/blob/master/guide/guide.org>) for usage
|
(L<https://github.com/dkogan/feedgnuplot/blob/master/guide/guide.org>) for usage
|
||||||
examples.
|
examples.
|
||||||
|
|
||||||
@ -2080,13 +2129,35 @@ I<all> the curves.
|
|||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
C<--extracmds xxx>
|
C<--using curveID expression>
|
||||||
|
|
||||||
|
Specifies a C<using> expression to micromanage the plot. This is a powerful
|
||||||
|
option that allows gnuplot to interpret the input data in arbitrary ways. A
|
||||||
|
C<using> expression tells gnuplot how to map the input columns of data to tuples
|
||||||
|
expected by the plotting style. Please see the L</"'using' expressions"> section above for more detail.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--usingall expression>
|
||||||
|
|
||||||
|
Global "using" expressions. This works exactly like C<--using>, except it
|
||||||
|
applies to I<all> the curves.
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
|
C<--cmds xxx>
|
||||||
|
|
||||||
Additional commands to pass on to gnuplot verbatim. These could contain extra
|
Additional commands to pass on to gnuplot verbatim. These could contain extra
|
||||||
global styles for instance. Can be passed multiple times.
|
global styles for instance. Can be passed multiple times.
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
|
C<--extracmds xxx>
|
||||||
|
|
||||||
|
Synonym for C<--cmds xxx>
|
||||||
|
|
||||||
|
=item
|
||||||
|
|
||||||
C<--set xxx>
|
C<--set xxx>
|
||||||
|
|
||||||
Additional 'set' commands to pass on to gnuplot verbatim. C<--set 'a b c'> will
|
Additional 'set' commands to pass on to gnuplot verbatim. C<--set 'a b c'> will
|
||||||
|
@ -21,7 +21,7 @@ complete -W \
|
|||||||
--rangesize \
|
--rangesize \
|
||||||
--tuplesizeall \
|
--tuplesizeall \
|
||||||
--tuplesize \
|
--tuplesize \
|
||||||
--extracmds \
|
--cmds \
|
||||||
--set \
|
--set \
|
||||||
--unset \
|
--unset \
|
||||||
--equation \
|
--equation \
|
||||||
@ -67,4 +67,6 @@ complete -W \
|
|||||||
--zmax \
|
--zmax \
|
||||||
--zmin \
|
--zmin \
|
||||||
--xticlabels \
|
--xticlabels \
|
||||||
|
--using \
|
||||||
|
--usingall \
|
||||||
--vnlog ' feedgnuplot
|
--vnlog ' feedgnuplot
|
||||||
|
@ -35,7 +35,7 @@ _arguments -S
|
|||||||
'(--with)--curvestyleall[Additional styles for ALL curves]:style' \
|
'(--with)--curvestyleall[Additional styles for ALL curves]:style' \
|
||||||
'(--with)--styleall[Additional styles for ALL curves]:style' \
|
'(--with)--styleall[Additional styles for ALL curves]:style' \
|
||||||
'(--curvestyleall)--with[Additional styles for ALL curves]:style' \
|
'(--curvestyleall)--with[Additional styles for ALL curves]:style' \
|
||||||
'*--extracmds[Additional gnuplot commands]:command' \
|
'*--cmds[Additional gnuplot commands]:command' \
|
||||||
'*--set[Additional 'set' gnuplot commands]:set-option' \
|
'*--set[Additional 'set' gnuplot commands]:set-option' \
|
||||||
'*--unset[Additional 'unset' gnuplot commands]:unset-option' \
|
'*--unset[Additional 'unset' gnuplot commands]:unset-option' \
|
||||||
'*--equation[Raw symbolic equation]:equation' \
|
'*--equation[Raw symbolic equation]:equation' \
|
||||||
@ -58,6 +58,8 @@ _arguments -S
|
|||||||
'*--style[Additional styles for a curve]:curve id: :style:' \
|
'*--style[Additional styles for a curve]:curve id: :style:' \
|
||||||
'*--every[Decimation factor for a curve]:curve id: :decimation factor:' \
|
'*--every[Decimation factor for a curve]:curve id: :decimation factor:' \
|
||||||
'--everyall[Decimation factor for ALL curves]:decimation factor' \
|
'--everyall[Decimation factor for ALL curves]:decimation factor' \
|
||||||
|
'*--using[Column specification for a curve]:curve id: :column specification:' \
|
||||||
|
'--usingall[Column specification ALL curves]:column specification' \
|
||||||
'(--3d)*--histogram:plot to treat as a histogram:' \
|
'(--3d)*--histogram:plot to treat as a histogram:' \
|
||||||
'--binwidth:Histogram bin width:' \
|
'--binwidth:Histogram bin width:' \
|
||||||
'--histstyle:Style of histogram:(frequency fnormal unique cumulative cnormal)' \
|
'--histstyle:Style of histogram:(frequency fnormal unique cumulative cnormal)' \
|
||||||
|
@ -538,8 +538,8 @@ These aren't "histograms", where gnuplot bins the data for us, but rather the
|
|||||||
data is given to us, ready to plot. We pass =--xticlabels= to indicate that the
|
data is given to us, ready to plot. We pass =--xticlabels= to indicate that the
|
||||||
x-axis tic labels come from the data. This changes the interpretation of the
|
x-axis tic labels come from the data. This changes the interpretation of the
|
||||||
input: with =--domain=, each line begins with =x label ....=. Without
|
input: with =--domain=, each line begins with =x label ....=. Without
|
||||||
=--domain=, each line begins with =label ...=. This does /not/ affect the
|
=--domain=, each line begins with =label ...=. Clearly, the labels may not
|
||||||
tuple size.
|
contain whitespace. This does /not/ affect the tuple size.
|
||||||
|
|
||||||
Basic example without =--domain=:
|
Basic example without =--domain=:
|
||||||
|
|
||||||
|
39
t/every-individual.ref
Normal file
39
t/every-individual.ref
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
12 +------------------------------------------------------------------------------------------+
|
||||||
|
| + + + + + |
|
||||||
|
| |
|
||||||
|
| B A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
10 |-+ +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
8 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
6 |-+ +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| B A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
4 |-+ +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
2 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| + + + + + |
|
||||||
|
0 +------------------------------------------------------------------------------------------+
|
||||||
|
0 2 4 6 8 10 12
|
||||||
|
|
39
t/everyall.ref
Normal file
39
t/everyall.ref
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
12 +------------------------------------------------------------------------------------------+
|
||||||
|
| + + + + + |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
10 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
8 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
6 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
4 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
2 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| + + + + + |
|
||||||
|
0 +------------------------------------------------------------------------------------------+
|
||||||
|
0 2 4 6 8 10 12
|
||||||
|
|
27
t/plots.t
27
t/plots.t
@ -39,7 +39,7 @@ BEGIN {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use Test::More tests => 84;
|
use Test::More tests => 92;
|
||||||
use File::Temp 'tempfile';
|
use File::Temp 'tempfile';
|
||||||
use IPC::Run 'run';
|
use IPC::Run 'run';
|
||||||
use String::ShellQuote;
|
use String::ShellQuote;
|
||||||
@ -288,6 +288,31 @@ tryplot( testname => 'equations',
|
|||||||
'--ymin', '0'],
|
'--ymin', '0'],
|
||||||
refplot => 'equations.ref' );
|
refplot => 'equations.ref' );
|
||||||
|
|
||||||
|
tryplot( testname => 'everyall',
|
||||||
|
cmd => q{seq 12 | gawk '{print $1,$1+1}'},
|
||||||
|
options => [qw(--points --everyall 2)],
|
||||||
|
refplot => 'everyall.ref' );
|
||||||
|
|
||||||
|
tryplot( testname => 'every-individual',
|
||||||
|
cmd => q{seq 12 | gawk '{print $1,$1+1}'},
|
||||||
|
options => [qw(--points --every 0 2 --every 1 3)],
|
||||||
|
refplot => 'every-individual.ref' );
|
||||||
|
|
||||||
|
tryplot( testname => 'usingall',
|
||||||
|
cmd => q{seq 12 | gawk '{print $1,$1+1}'},
|
||||||
|
options => [qw(--style 0), 'with points pt variable',
|
||||||
|
qw(--style 1), 'with linespoints pt variable',
|
||||||
|
qw(--usingall 1:2:($2) --unset grid)],
|
||||||
|
refplot => 'usingall.ref' );
|
||||||
|
|
||||||
|
tryplot( testname => 'using-individual',
|
||||||
|
cmd => q{seq 12 | gawk '{print $1,$1+1}'},
|
||||||
|
options => [qw(--style 0), 'with points pt variable',
|
||||||
|
qw(--using 0 1:2:($2)),
|
||||||
|
qw(--using 1 1:(12-$2)),
|
||||||
|
qw(--unset grid)],
|
||||||
|
refplot => 'using-individual.ref' );
|
||||||
|
|
||||||
SKIP:
|
SKIP:
|
||||||
{
|
{
|
||||||
|
|
||||||
|
39
t/using-individual.ref
Normal file
39
t/using-individual.ref
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
12 +------------------------------------------------------------------------------------------+
|
||||||
|
| + + + + + |
|
||||||
|
| |
|
||||||
|
| K |
|
||||||
|
| |
|
||||||
|
10 |-+ B J +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| B I |
|
||||||
|
| |
|
||||||
|
8 |-+ B H +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| B G |
|
||||||
|
| |
|
||||||
|
6 |-+ B F +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| E B |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
4 |-+ D B +-|
|
||||||
|
| |
|
||||||
|
| C B |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
2 |-+ B B +-|
|
||||||
|
| |
|
||||||
|
| A B |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
0 |-+ B +-|
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| + + + + + |
|
||||||
|
-2 +------------------------------------------------------------------------------------------+
|
||||||
|
0 2 4 6 8 10 12
|
||||||
|
|
39
t/usingall.ref
Normal file
39
t/usingall.ref
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
14 +------------------------------------------------------------------------------------------+
|
||||||
|
| + + + + + |
|
||||||
|
| |
|
||||||
|
| ##|
|
||||||
|
| #### |
|
||||||
|
12 |-+ #L# +-|
|
||||||
|
| ## |
|
||||||
|
| ## |
|
||||||
|
| ##K# K |
|
||||||
|
| #### |
|
||||||
|
10 |-+ #J# J +-|
|
||||||
|
| ## |
|
||||||
|
| ## |
|
||||||
|
| ##I# I |
|
||||||
|
| #### |
|
||||||
|
8 |-+ #H# H +-|
|
||||||
|
| ## |
|
||||||
|
| ## |
|
||||||
|
| #G# G |
|
||||||
|
| ### |
|
||||||
|
| ## |
|
||||||
|
6 |-+ ##F# F +-|
|
||||||
|
| #### |
|
||||||
|
| #E# E |
|
||||||
|
| ## |
|
||||||
|
| ## |
|
||||||
|
4 |-+ ##D# D +-|
|
||||||
|
| #### |
|
||||||
|
| #C# C |
|
||||||
|
| ## |
|
||||||
|
| ## |
|
||||||
|
2 |-+ B# B +-|
|
||||||
|
| |
|
||||||
|
| A |
|
||||||
|
| |
|
||||||
|
| + + + + + |
|
||||||
|
0 +------------------------------------------------------------------------------------------+
|
||||||
|
0 2 4 6 8 10 12
|
||||||
|
|
Loading…
Reference in New Issue
Block a user