timefmt plots now work with streaming and with --xlen

This commit is contained in:
Dima Kogan 2013-09-20 22:06:18 -07:00
parent d76f163be4
commit c169330fca

View File

@ -11,6 +11,7 @@ use threads;
use threads::shared; use threads::shared;
use Thread::Queue; use Thread::Queue;
use Pod::Usage; use Pod::Usage;
use Time::Piece;
my $VERSION = 1.24; my $VERSION = 1.24;
@ -355,6 +356,21 @@ sub sendRangeCommand
print PIPE $cmd; print PIPE $cmd;
} }
sub makeDomainNumeric
{
my ($domain0) = @_;
if ( $options{timefmt} )
{
my $timepiece = Time::Piece->strptime( $domain0, $options{timefmt} )
or die "Couldn't parse time format. String '$domain0' doesn't fit format '$options{timefmt}'";
return $timepiece->epoch();
}
return $domain0;
}
sub mainThread sub mainThread
{ {
my $valuesPerPoint = 1; my $valuesPerPoint = 1;
@ -406,18 +422,6 @@ sub mainThread
print PIPE "set terminal $options{terminal}\n" if $options{terminal}; print PIPE "set terminal $options{terminal}\n" if $options{terminal};
print PIPE "set output \"$outputfile\"\n" if $outputfile; print PIPE "set output \"$outputfile\"\n" if $outputfile;
# If a bound isn't given I want to set it to the empty string, so I can communicate it simply to
# gnuplot
print PIPE "set xtics\n";
if($options{y2})
{
print PIPE "set ytics nomirror\n";
print PIPE "set y2tics\n";
# if any of the ranges are given, set the range
sendRangeCommand( "y2range", $options{y2min}, $options{y2max} );
}
# set up plotting style # set up plotting style
my $style = ''; my $style = '';
if($options{lines}) { $style .= 'lines';} if($options{lines}) { $style .= 'lines';}
@ -427,11 +431,6 @@ sub mainThread
$options{curvestyleall} = "with circles $options{curvestyleall}"; $options{curvestyleall} = "with circles $options{curvestyleall}";
} }
# if any of the ranges are given, set the range
sendRangeCommand( "xrange", $options{xmin}, $options{xmax} );
sendRangeCommand( "yrange", $options{ymin}, $options{ymax} );
sendRangeCommand( "zrange", $options{zmin}, $options{zmax} );
print PIPE "set style data $style\n" if $style; print PIPE "set style data $style\n" if $style;
print PIPE "set grid\n"; print PIPE "set grid\n";
@ -459,13 +458,8 @@ sub mainThread
print(PIPE "set view equal xy\n"); print(PIPE "set view equal xy\n");
} }
if($options{colormap})
{
sendRangeCommand( "cbrange", $options{zmin}, $options{zmax} );
}
# For the specified values, set the legend entries to 'title "blah blah"' # For the specified values, set the legend entries to 'title "blah blah"'
if(@{$options{legend}}) if(defined $options{legend} && @{$options{legend}})
{ {
# @{$options{legend}} is a list where consecutive pairs are (curveID, # @{$options{legend}} is a list where consecutive pairs are (curveID,
# legend). I use $options{legend} here instead of $options{legend_hash} # legend). I use $options{legend} here instead of $options{legend_hash}
@ -480,7 +474,7 @@ sub mainThread
} }
# add the extra curve options # add the extra curve options
if(@{$options{curvestyle}}) if(defined $options{curvestyle} && @{$options{curvestyle}})
{ {
# @{$options{curvestyle}} is a list where consecutive pairs are (curveID, # @{$options{curvestyle}} is a list where consecutive pairs are (curveID,
# style). I use $options{curvestyle} here instead of # style). I use $options{curvestyle} here instead of
@ -495,10 +489,13 @@ sub mainThread
} }
# For the values requested to be printed on the y2 axis, set that # For the values requested to be printed on the y2 axis, set that
if( defined $options{y2} )
{
foreach (@{$options{y2}}) foreach (@{$options{y2}})
{ {
addCurveOption($_, 'axes x1y2 linewidth 3'); addCurveOption($_, 'axes x1y2 linewidth 3');
} }
}
# timefmt # timefmt
if( $options{timefmt} ) if( $options{timefmt} )
@ -508,7 +505,7 @@ sub mainThread
} }
# add the extra global options # add the extra global options
if($options{extracmds}) if(defined $options{extracmds})
{ {
foreach (@{$options{extracmds}}) foreach (@{$options{extracmds}})
{ {
@ -517,6 +514,8 @@ sub mainThread
} }
# set up histograms # set up histograms
if( defined $options{histogram} )
{
$options{binwidth} ||= 1; # if no binwidth given, set it to 1 $options{binwidth} ||= 1; # if no binwidth given, set it to 1
print PIPE print PIPE
"set boxwidth $options{binwidth}\n" . "set boxwidth $options{binwidth}\n" .
@ -525,6 +524,7 @@ sub mainThread
{ {
setCurveAsHistogram( $_ ); setCurveAsHistogram( $_ );
} }
}
# regexp for a possibly floating point, possibly scientific notation number # regexp for a possibly floating point, possibly scientific notation number
my $numRE = '-?\d*\.?\d+(?:[Ee][-+]?\d+)?'; my $numRE = '-?\d*\.?\d+(?:[Ee][-+]?\d+)?';
@ -536,6 +536,26 @@ sub mainThread
$pointRE .= '(' . join('\s+', ($numRE) x $valuesPerPoint) . ')'; $pointRE .= '(' . join('\s+', ($numRE) x $valuesPerPoint) . ')';
$pointRE = qr/$pointRE/; $pointRE = qr/$pointRE/;
# set all the axis ranges
# If a bound isn't given I want to set it to the empty string, so I can communicate it simply to
# gnuplot
print PIPE "set xtics\n";
if($options{y2})
{
print PIPE "set ytics nomirror\n";
print PIPE "set y2tics\n";
# if any of the ranges are given, set the range
sendRangeCommand( "y2range", $options{y2min}, $options{y2max} );
}
# if any of the ranges are given, set the range
sendRangeCommand( "xrange", $options{xmin}, $options{xmax} );
sendRangeCommand( "yrange", $options{ymin}, $options{ymax} );
sendRangeCommand( "zrange", $options{zmin}, $options{zmax} );
sendRangeCommand( "cbrange", $options{zmin}, $options{zmax} ) if($options{colormap});
# latest domain variable present in our data # latest domain variable present in our data
@ -544,6 +564,10 @@ sub mainThread
# The domain of the current point # The domain of the current point
my @domain; my @domain;
# 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
# number of seconds since the UNIX epoch.
my $domain0_numeric;
# I should be using the // operator, but I'd like to be compatible with perl 5.8 # I should be using the // operator, but I'd like to be compatible with perl 5.8
while( $_ = (defined $dataQueue ? $dataQueue->dequeue() : <>)) while( $_ = (defined $dataQueue ? $dataQueue->dequeue() : <>))
@ -556,7 +580,7 @@ sub mainThread
elsif( $options{stream} && /^replot/o ) elsif( $options{stream} && /^replot/o )
{ {
# /timertick/ determines if the timer was the source of the replot # /timertick/ determines if the timer was the source of the replot
replot( $domain[0], /timertick/ ); replot( $domain0_numeric, /timertick/ );
} }
elsif(! /^replot/o) elsif(! /^replot/o)
{ {
@ -574,6 +598,8 @@ sub mainThread
{ {
/($domainRE)/go or next; /($domainRE)/go or next;
$domain[0] = $1; $domain[0] = $1;
$domain0_numeric = makeDomainNumeric( $domain[0] );
if($options{'3d'}) if($options{'3d'})
{ {
/($numRE)/go or next; /($numRE)/go or next;
@ -581,17 +607,17 @@ sub mainThread
} }
elsif( $options{monotonic} ) elsif( $options{monotonic} )
{ {
if( defined $latestX && $domain[0] < $latestX ) if( defined $latestX && $domain0_numeric < $latestX )
{ {
# the x-coordinate of the new point is in the past, so I wipe out # the x-coordinate of the new point is in the past, so I wipe out
# all the data and start anew. Before I wipe the old data, I # all the data and start anew. Before I wipe the old data, I
# replot the old data # replot the old data
replot( $domain[0] ); replot( $domain0_numeric );
clearCurves(); clearCurves();
$latestX = undef; $latestX = undef;
} }
else else
{ $latestX = $domain[0]; } { $latestX = $domain0_numeric; }
} }
} }
@ -608,6 +634,7 @@ sub mainThread
{ {
$domain[0] = $.; $domain[0] = $.;
} }
$domain0_numeric = makeDomainNumeric( $domain[0] );
} }
my $id = -1; my $id = -1;
@ -617,7 +644,7 @@ sub mainThread
else {$id++; } else {$id++; }
pushPoint(getCurve($id), pushPoint(getCurve($id),
"@domain $2\n", $domain[0]); "@domain $2\n", $domain0_numeric);
} }
} }
} }
@ -645,8 +672,7 @@ sub mainThread
sub pruneOldData sub pruneOldData
{ {
my ($x, $xlen) = @_; my ($oldestx) = @_;
my $oldestx = $x - $xlen;
foreach my $curve (@curves) foreach my $curve (@curves)
{ {
@ -815,7 +841,7 @@ sub replot
# } # }
my ($domain0, $replot_is_from_timer) = @_; my ($domain0_numeric, $replot_is_from_timer) = @_;
my $now = [gettimeofday]; my $now = [gettimeofday];
@ -834,9 +860,15 @@ sub replot
if ( defined $options{xlen} ) if ( defined $options{xlen} )
{ {
# we have an --xlen, so we need to clean out the old data # we have an --xlen, so we need to clean out the old data
pruneOldData( $domain0, $options{xlen} ); pruneOldData( $domain0_numeric - $options{xlen} );
my ($xmin, $xmax) = ($domain0 - $options{xlen}, $domain0); my ($xmin, $xmax) = ($domain0_numeric - $options{xlen}, $domain0_numeric);
if ( defined $options{timefmt} )
{
# if we're using a timefmt, I need to convert my xmin range from
# seconds-since-the-epoch BACK to the timefmt. Sheesh
($xmin, $xmax) = map {Time::Piece->strptime( $_, '%s' )->strftime( $options{timefmt} ) } ($xmin, $xmax);
}
sendRangeCommand( "xrange", $xmin, $xmax ); sendRangeCommand( "xrange", $xmin, $xmax );
} }
@ -852,10 +884,10 @@ sub replot
# function to add a point to the plot. Assumes that the curve indexed by $idx already exists # function to add a point to the plot. Assumes that the curve indexed by $idx already exists
sub pushPoint sub pushPoint
{ {
my ($curve, $datastring, $domain0) = @_; my ($curve, $datastring, $domain0_numeric) = @_;
push @{$curve->{datastring_meta}}, { offset_start => length( $curve->{datastring} ) + $curve->{datastring_offset}, push @{$curve->{datastring_meta}}, { offset_start => length( $curve->{datastring} ) + $curve->{datastring_offset},
domain => $domain0 }; domain => $domain0_numeric };
$curve->{datastring} .= $datastring; $curve->{datastring} .= $datastring;
$haveNewData = 1; $haveNewData = 1;