Merge branch 'master' into debian

This commit is contained in:
Dima Kogan 2018-02-24 12:55:45 -08:00
commit c2c327953d
2 changed files with 249 additions and 86 deletions

20
Changes
View File

@ -1,3 +1,23 @@
feedgnuplot (1.48)
* --vnlog works properly with --domain
-- Dima Kogan <dima@secretsauce.net> Sat, 24 Feb 2018 12:33:50 -0800
feedgnuplot (1.47)
* Fixed typo. Everything is un-broken now
-- Dima Kogan <dima@secretsauce.net> Fri, 23 Feb 2018 10:21:13 -0800
feedgnuplot (1.46)
* Added --tuplesize and --tuplesizeall as alternatives to --rangesize
and --rangesizeall. Both forms are supported.
* Vnlog integration
-- Dima Kogan <dima@secretsauce.net> Thu, 22 Feb 2018 23:37:54 -0800
feedgnuplot (1.45) feedgnuplot (1.45)
* zsh completion: --hardcopy, --image suggest filenames * zsh completion: --hardcopy, --image suggest filenames

View File

@ -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.45'; my $VERSION = '1.48';
my %options; my %options;
interpretCommandline(); interpretCommandline();
@ -102,8 +102,9 @@ sub interpretCommandline
$options{with} = ''; $options{with} = '';
$options{rangesize} = []; $options{rangesize} = [];
$options{tuplesize} = [];
GetOptions(\%options, 'stream:s', 'domain!', 'dataid!', '3d!', 'colormap!', 'lines!', 'points!', GetOptions(\%options, 'stream:s', 'domain!', 'dataid!', 'vnlog!', '3d!', 'colormap!', 'lines!', 'points!',
'circles', 'legend=s{2}', 'autolegend!', 'xlabel=s', 'ylabel=s', 'y2label=s', 'zlabel=s', 'circles', 'legend=s{2}', 'autolegend!', 'xlabel=s', 'ylabel=s', 'y2label=s', 'zlabel=s',
'title=s', 'xlen=f', 'ymin=f', 'ymax=f', 'xmin=s', 'xmax=s', 'y2min=f', 'y2max=f', 'title=s', 'xlen=f', 'ymin=f', 'ymax=f', 'xmin=s', 'xmax=s', 'y2min=f', 'y2max=f',
'zmin=f', 'zmax=f', 'y2=s@', 'zmin=f', 'zmax=f', 'y2=s@',
@ -113,7 +114,9 @@ sub interpretCommandline
'image=s', 'image=s',
'histogram=s@', 'binwidth=f', 'histstyle=s', 'histogram=s@', 'binwidth=f', 'histstyle=s',
'terminal=s', 'terminal=s',
'rangesize=s{2}', 'rangesizeall=i', 'extraValuesPerPoint=i', 'rangesize=s{2}', 'rangesizeall=i',
'tuplesize=s{2}', 'tuplesizeall=i',
'extraValuesPerPoint=i', # deprecated and undocumented
'help', 'dump', 'exit', 'version', 'help', 'dump', 'exit', 'version',
'geometry=s') or exit 1; 'geometry=s') or exit 1;
@ -154,6 +157,11 @@ sub interpretCommandline
delete $options{with}; delete $options{with};
} }
if( $options{dataid} && $options{vnlog} )
{
print STDERR "--dataid and --vnlog are mutually exclusive. Please just use one.\n";
exit -1;
}
# expand options that are given as comma-separated lists # expand options that are given as comma-separated lists
for my $listkey (qw(histogram y2)) for my $listkey (qw(histogram y2))
@ -161,7 +169,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)) for my $listkey (qw(curvestyle rangesize tuplesize))
{ {
next unless defined $options{$listkey}; next unless defined $options{$listkey};
my @in = @{$options{$listkey}}; my @in = @{$options{$listkey}};
@ -181,6 +189,35 @@ sub interpretCommandline
} }
# convert all tuplesize business to rangesize
my $domainsize = $options{'3d'} ? 2 : 1;
if (defined $options{tuplesizeall})
{
if (defined $options{rangesizeall} )
{
print STDERR "Only one of --rangesizeall and --tuplesizeall may be given\n";
exit -1;
}
$options{rangesizeall} = $options{tuplesizeall} - $domainsize;
delete $options{tuplesizeall};
}
if (defined $options{tuplesize})
{
$options{rangesize} //= [];
my $N = @{$options{tuplesize}} / 2;
for my $i (0..$N-1)
{
$options{tuplesize}[2*$i + 1] -= $domainsize;
}
push @{$options{rangesize}}, @{$options{tuplesize}};
delete $options{tuplesize};
}
# If we're plotting histograms, then set the default histogram options for # If we're plotting histograms, then set the default histogram options for
# each histogram curve # each histogram curve
# #
@ -756,6 +793,41 @@ sub mainThread
# The domain of the current point # The domain of the current point
my @domain; my @domain;
# column headers from vnlog
my @vnlog_headers;
if($options{vnlog})
{
require Vnlog::Parser;
require Vnlog::Util;
if ( !defined $pipe_in )
{
($pipe_in, $selector) = openNextFile();
}
my $parser = Vnlog::Parser->new();
while (defined ($_ = Vnlog::Util::get_unbuffered_line($pipe_in)))
{
if ( !$parser->parse($_) )
{
die "Error parsing vnlog: $parser->{error}; looking at line '$_'";
}
my $keys = $parser->getKeys();
if (defined $keys)
{
@vnlog_headers = @$keys;
last;
}
}
if(!@vnlog_headers)
{
die "Looked through all of the first file, and never saw a vnlog legend";
}
}
# The x-axis domain represented as a number. This is exactly the same as # The x-axis domain represented as a number. This is exactly the same as
# $domain[0] unless the x-axis domain uses a timefmt. Then this is the # $domain[0] unless the x-axis domain uses a timefmt. Then this is the
# number of seconds since the UNIX epoch. # number of seconds since the UNIX epoch.
@ -793,6 +865,7 @@ sub mainThread
# 3d plots require $options{domain}, and dictate "x y" for the domain instead of just "x" # 3d plots require $options{domain}, and dictate "x y" for the domain instead of just "x"
my @fields = split; my @fields = split;
my $i_column = 0;
if($options{domain}) if($options{domain})
{ {
@ -804,6 +877,7 @@ sub mainThread
$domain[0] = join (' ', splice( @fields, 0, $options{timefmt_Ncols}) ); $domain[0] = join (' ', splice( @fields, 0, $options{timefmt_Ncols}) );
$domain0_numeric = makeDomainNumeric( $domain[0] ); $domain0_numeric = makeDomainNumeric( $domain[0] );
$i_column += $options{timefmt_Ncols};
} }
elsif(!$options{'3d'}) elsif(!$options{'3d'})
{ {
@ -812,6 +886,7 @@ sub mainThread
next if @fields < 1+1; next if @fields < 1+1;
$domain[0] = $domain0_numeric = shift @fields; $domain[0] = $domain0_numeric = shift @fields;
$i_column += 1;
} }
else else
{ {
@ -820,6 +895,7 @@ sub mainThread
next if @fields < 2+1; next if @fields < 2+1;
@domain = splice(@fields, 0, 2); @domain = splice(@fields, 0, 2);
$i_column += 2;
} }
if( $options{monotonic} ) if( $options{monotonic} )
@ -844,11 +920,27 @@ sub mainThread
} }
my $id = -1; my $id = -1;
while(@fields) while(@fields)
{ {
if($options{dataid}) { $id = shift @fields; } if ($options{dataid})
else { $id++; } {
$id = shift @fields;
}
elsif($options{vnlog} )
{
if( $i_column >= @vnlog_headers )
{
# Got more columns than vnlog headers. The data is probably
# bogus, but I don't want to barf at the user, so I silently
# ignore the data
last;
}
$id = $vnlog_headers[$i_column];
}
else
{
$id++;
}
my $rangesize = getRangeSize($id); my $rangesize = getRangeSize($id);
last if @fields < $rangesize; last if @fields < $rangesize;
@ -858,6 +950,8 @@ sub mainThread
@domain, @domain,
splice( @fields, 0, $rangesize ) ) . "\n", splice( @fields, 0, $rangesize ) ) . "\n",
$domain0_numeric); $domain0_numeric);
$i_column++;
} }
} }
@ -1173,45 +1267,45 @@ Simple plotting of piped data:
$ seq 5 | awk '{print 2*$1, $1*$1}' | $ seq 5 | awk '{print 2*$1, $1*$1}' |
feedgnuplot --lines --points --legend 0 "data 0" --title "Test plot" --y2 1 feedgnuplot --lines --points --legend 0 "data 0" --title "Test plot" --y2 1
--terminal 'dumb 80,40' --exit --unset grid --terminal 'dumb 80,40' --exit
Test plot Test plot
10 ++------+--------+-------+-------+-------+--------+-------+------*A 25 10 +-----------------------------------------------------------------+ 25
+ + + + + + + + **#+ | + + + + + + + *##|
| : : : : : : data 0+**A*** | | data 0 ***A*#* |
| : : : : : : :** # | | ** # |
9 ++.......................................................**.##....| 9 |-+ ** ## |
| : : : : : : ** :# | | ** # |
| : : : : : : ** # | | ** # |
| : : : : : :** ##: ++ 20 | ** ## +-| 20
8 ++................................................A....#..........| 8 |-+ A # |
| : : : : : **: # : | | ** # |
| : : : : : ** : ## : | | ** ## |
| : : : : : ** :# : | | ** # |
| : : : : :** B : | | ** B |
7 ++......................................**......##................| 7 |-+ ** ## |
| : : : : ** : ## : : ++ 15 | ** ## +-| 15
| : : : : ** : # : : | | ** # |
| : : : :** : ## : : | | ** ## |
6 ++..............................*A.......##.......................| 6 |-+ *A ## |
| : : : ** : ##: : : | | ** ## |
| : : : ** : # : : : | | ** # |
| : : :** : ## : : : ++ 10 | ** ## +-| 10
5 ++......................**........##..............................| 5 |-+ ** ## |
| : : ** : #B : : : | | ** #B |
| : : ** : ## : : : : | | ** ## |
| : :** : ## : : : : | | ** ## |
4 ++...............A.......###......................................| 4 |-+ A ### |
| : **: ##: : : : : | | ** ## |
| : ** : ## : : : : : ++ 5 | ** ## +-| 5
| : ** : ## : : : : : | | ** ## |
| :** ##B# : : : : : | | ** ##B# |
3 ++.....**..####...................................................| 3 |-+ ** #### |
| **#### : : : : : : | | **#### |
| **## : : : : : : : | | #### |
B** + + + + + + + + |## + + + + + + + |
2 A+------+--------+-------+-------+-------+--------+-------+------++ 0 2 +-----------------------------------------------------------------+ 0
1 1.5 2 2.5 3 3.5 4 4.5 5 1 1.5 2 2.5 3 3.5 4 4.5 5
@ -1279,41 +1373,64 @@ with the I<X>-value at the start of that line.
=head3 Curve indexing =head3 Curve indexing
By default, each column represents a separate curve. This is fine unless sparse We index the curves in one of 3 ways: sequentially, explicitly with a
data is to be plotted. With the C<--dataid> option, each point is represented by C<--dataid> or by C<--vnlog> headers.
2 values: a string identifying the curve, and the value itself. If we add
C<--dataid> to the original example: By default, each column represents a separate curve. The first column (after any
domain) is curve C<0>. The next one is curve C<1> and so on. This is fine unless
sparse data is to be plotted. With the C<--dataid> option, each point is
represented by 2 values: a string identifying the curve, and the value itself.
If we add C<--dataid> to the original example:
$ seq 5 | awk '{print 2*$1, $1*$1}' | feedgnuplot --dataid --autolegend $ seq 5 | awk '{print 2*$1, $1*$1}' | feedgnuplot --dataid --autolegend
we get 5 different curves with one point in each. The first column, as produced we get 5 different curves with one point in each. The first column, as produced
by C<awk>, is B<2,4,6,8,10>. These are interpreted as the IDs of the curves to by C<awk>, is B<2,4,6,8,10>. These are interpreted as the IDs of the curves to
be plotted. The C<--autolegend> option adds a legend using the given IDs to be plotted.
If we're plotting C<vnlog> data (L<https://www.github.com/dkogan/vnlog>) then we
can get the curve IDs from the vnlog header. Vnlog is a trivial data format
where lines starting with C<#> are comments and the first comment contains
column labels. If we have such data, C<feedgnuplot --vnlog> can interpret these
column labels if the C<vnlog> perl modules are available.
The C<--autolegend> option adds a legend using the given IDs to
label the curves. The IDs need not be numbers; generic strings are accepted. As label the curves. The IDs need not be numbers; generic strings are accepted. As
many points as desired can appear on a single line. C<--domain> can be used in many points as desired can appear on a single line. C<--domain> can be used in
conjunction with C<--dataid>. conjunction with C<--dataid> or C<--vnlog>.
=head3 Multi-value style support =head3 Multi-value style support
Depending on how gnuplot is plotting the data, more than one value may be needed Depending on how gnuplot is plotting the data, more than one value may be needed
to represent the range of a single point. Basic 2D plots have 2 numbers to represent the range of a single point. Basic 2D plots have 2 numbers
representing each point: 1 domain and 1 range. But if plotting with representing each point: 1 domain and 1 range. But if plotting with
C<--circles>, for instance, then there's an extra range value: the radius. A C<--circles>, for instance, then there's an extra range value: the radius. Many
similar situation exists with C<--colormap> where each point contains the other gnuplot styles require more data: errorbars, variable colors (C<with
position I<and> the color. There are other gnuplot styles that require more data points palette>), variable sizes (C<with points ps variable>), labels and so on.
(such as error bars), but none of these are directly supported by the script. The feedgnuplot tool itself does not know about all these intricacies, but they
They can still be used, however, by specifying the specific style with can still be used, by specifying the specific style with C<--style>, and
C<--style>, and specifying how many values are needed for each point with specifying how many values are needed for each point with any of
C<--rangesizeall> or C<--rangesize> or C<--extraValuesPerPoint>. Those options C<--rangesizeall, C<--tuplesizeall>, C<--rangesize>, C<--tuplesize>. These
that specify the range size are required I<only> for styles not explicitly options are required I<only> for styles not explicitly supported by feedgnuplot;
supported by feedgnuplot; supported styles do the right thing automatically. supported styles do the right thing automatically.
More examples: if making a 2d plot of y error bars where gnuplot expects a Specific example: if making a 2d plot of y error bars, the exact format can be
(x,y,ydelta) tuple for each point, you want C<--rangesizeall 2> because you have queried by running C<gnuplot> and invoking C<help yerrorbars>. This tells us
one domain value (x) and 2 range values (y,ydelta). Gnuplot can also plot that there's a 3-column form: C<x y ydelta> and a 4-column form: C<x y ylow
lopsided y errorbars by giving a tuple (x,y,ylow,yhigh). This is similar as yhigh>. With 2d plots feedgnuplot will always output the 1-value domain C<x>, so
before, but you want C<--rangesizeall 3> instead. the rangesize is 2 and 3 respectively. Thus the following are equivalent:
$ echo '1 2 0.3
2 3 0.4
3 4 0.5' | feedgnuplot --domain --rangesizeall 2 --with 'yerrorbars'
$ echo '1 2 0.3
2 3 0.4
3 4 0.5' | feedgnuplot --domain --tuplesizeall 3 --with 'yerrorbars'
$ echo '1 2 1.7 2.3
2 3 2.6 3.4
3 4 3.5 4.5' | feedgnuplot --domain --rangesizeall 3 --with 'yerrorbars'
=head3 3D data =head3 3D data
@ -1547,6 +1664,19 @@ point in curve ID 20
=item =item
C<--vnlog>
Vnlog is a trivial data format where lines starting with C<#> are comments and
the first comment contains column labels. Some tools for working with such data
are available from the C<vnlog> project: L<https://www.github.com/dkogan/vnlog>.
With the C<vnlog> perl modules installed, we can read the vnlog column headers
with C<feedgnuplot --vnlog>. This replaces C<--dataid>, and we can do all the
normal things with these headers. For instance C<feedgnuplot --vnlog
--autolegend> will generate plot legends for each column in the vnlog, using the
vnlog column label in the legend.
=item
C<--[no]3d> C<--[no]3d>
Do [not] plot in 3D. This only makes sense with C<--domain>. Each domain here is Do [not] plot in 3D. This only makes sense with C<--domain>. Each domain here is
@ -1563,7 +1693,8 @@ Interpret the X data as a time/date, parsed with the given format
C<--colormap> C<--colormap>
Show a colormapped xy plot. Requires extra data for the color. zmin/zmax can be Show a colormapped xy plot. Requires extra data for the color. zmin/zmax can be
used to set the extents of the colors. Automatically sets the C<--rangesize>. used to set the extents of the colors. Automatically sets the
C<--rangesize>/C<--tuplesize>.
=item =item
@ -1591,7 +1722,8 @@ Do [not] draw points
C<--circles> C<--circles>
Plot with circles. This requires a radius be specified for each point. Plot with circles. This requires a radius be specified for each point.
Automatically sets the C<--rangesize>. C<Not> supported for 3d plots. Automatically sets the C<--rangesize>/C<--tuplesize>. C<Not> supported for 3d
plots.
=item =item
@ -1632,7 +1764,10 @@ C<--xmin/xmax/ymin/ymax/y2min/y2max/zmin/zmax xxx>
Set the range for the given axis. These x-axis bounds are ignored in a streaming Set the range for the given axis. These x-axis bounds are ignored in a streaming
plot. The y2-axis bound do not apply in 3d plots. The z-axis bounds apply plot. The y2-axis bound do not apply in 3d plots. The z-axis bounds apply
I<only> to 3d plots or colormaps. I<only> to 3d plots or colormaps. Note that there is no C<--xrange> to set both
sides at once or C<--xinv> to flip the axis around: anything more than the
basics supported in this option is clearly obtainable by talking to gnuplot, for
instance C<--set 'xrange [20:10]'> to set the given inverted bounds.
=item =item
@ -1774,9 +1909,9 @@ Gnuplot can plot both data and symbolic equations. C<feedgnuplot> generally
plots data, but with this option can plot symbolic equations I<also>. This is plots data, but with this option can plot symbolic equations I<also>. This is
generally intended to augment data plots, since for equation-only plots you generally intended to augment data plots, since for equation-only plots you
don't need C<feedgnuplot>. C<--equation> can be passed multiple times for don't need C<feedgnuplot>. C<--equation> can be passed multiple times for
multiple equations. The given strings are passed to gnuplot directly without any multiple equations. The given strings are passed to gnuplot directly without
thing added or removed, so styling and such should be applied in the string. A anything added or removed, so styling and such should be applied in the string.
basic example: A basic example:
seq 100 | awk '{print $1/10, $1/100}' | seq 100 | awk '{print $1/10, $1/100}' |
feedgnuplot --with 'lines lw 3' --domain --ymax 1 feedgnuplot --with 'lines lw 3' --domain --ymax 1
@ -1826,7 +1961,7 @@ file type is desired, use both C<--hardcopy> and C<--terminal>
=item =item
C<--maxcurves xxx> C<--maxcurves N>
The maximum allowed number of curves. This is 100 by default, but can be reset The maximum allowed number of curves. This is 100 by default, but can be reset
with this option. This exists purely to prevent perl from allocating all of the with this option. This exists purely to prevent perl from allocating all of the
@ -1839,17 +1974,19 @@ C<--monotonic>
If C<--domain> is given, checks to make sure that the x-coordinate in the input If C<--domain> is given, checks to make sure that the x-coordinate in the input
data is monotonically increasing. If a given x-variable is in the past, all data data is monotonically increasing. If a given x-variable is in the past, all data
currently cached for this curve is purged. Without C<--monotonic>, all data is currently cached for this curve is purged. Without C<--monotonic>, all data is
kept. Does not make sense with 3d plots. No C<--monotonic> by default. The data is kept. Does not make sense with 3d plots. No C<--monotonic> by default. The data
replotted before being purged is replotted before being purged. This is useful in streaming plots where the
incoming data represents multiple iterations of the same process (repeated
simulations of the same period in time, for instance).
=item =item
C<--rangesize curveID xxx> C<--rangesize curveID N>
The options C<--rangesizeall>, C<--rangesize> and C<--extraValuesPerPoint> set The options C<--rangesizeall> and C<--rangesize> set the number of values are
the number of values are needed to represent each point being plotted (see needed to represent each point being plotted (see L</"Multi-value style
L</"Multi-value style support"> above). These options are I<only> needed if support"> above). These options are I<only> needed if unknown styles are used,
unknown styles are used, with C<--styleall> or C<--with> for instance. with C<--styleall> or C<--with> for instance.
C<--rangesize> is used to set how many values are needed to represent the range C<--rangesize> is used to set how many values are needed to represent the range
of a point for a particular curve. This overrides any defaults that may exist of a point for a particular curve. This overrides any defaults that may exist
@ -1861,19 +1998,25 @@ rangesize should apply.
=item =item
C<--rangesizeall xxx> C<--tuplesize curveID N>
Very similar to C<--rangesize>, but instead of specifying the I<range> only,
this specifies the whole tuple. For instance if we're plotting circles, the
tuplesize is 3: C<x,y,radius>. In a 2D plot there's a 1-dimensional domain:
C<x>, so the rangesize is 2: C<y,radius>. This dimensionality can be given
either way.
=item
C<--rangesizeall N>
Like C<--rangesize>, but applies to I<all> the curves. Like C<--rangesize>, but applies to I<all> the curves.
C<--extraValuesPerPoint xxx> =item
Like C<--rangesizeall>, but instead of overriding the default, adds to it. For C<--tuplesizeall N>
example, if plotting non-lopsided y errorbars gnuplot wants (x,y,ydelta) tuples.
These can be specified both with C<--rangesizeall 2> (because there are 2 range
values) or C<--extraValuesPerPoint 1> (because there's 1 more value than usual).
This option is I<only> needed if unknown styles are used, with C<--styleall> or Like C<--tuplesize>, but applies to I<all> the curves.
C<--with> for instance.
=item =item