Compare commits
3 Commits
6d6400d3eb
...
d3af2e6a5b
Author | SHA1 | Date |
---|---|---|
|
d3af2e6a5b | |
|
4a529d40d3 | |
|
1f4b6f1a91 |
108
tsplotsql
108
tsplotsql
|
@ -1,30 +1,42 @@
|
||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl
|
||||||
|
use v5.24;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Getopt::Long;
|
||||||
|
use Pod::Usage;
|
||||||
|
|
||||||
|
use DBIx::SimpleConnect;
|
||||||
|
use TimeSeries;
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
tsplotv - plot time series given in vertical format
|
tsplot - plot time series in column format
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
tsplotv
|
tsplot
|
||||||
[--dbname dbname]
|
[--dbname dbname]
|
||||||
[--finalresolution dpi]
|
[--finalresolution dpi]
|
||||||
[--legend-position pos]
|
[--legend-position pos]
|
||||||
[--log-y]
|
|
||||||
[--output-format format ]
|
[--output-format format ]
|
||||||
[--stacked]
|
[--stacked]
|
||||||
[--style style]
|
[--style style]
|
||||||
|
[--time_t]
|
||||||
|
[--yrange min max]
|
||||||
[query ...]
|
[query ...]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
This program expects time series data in vertical format, I.e.,
|
This program expects time series data in column format, I.e.,
|
||||||
each line contains a tab-separated tripel <time, series, value>.
|
each line contains a timestamp and the values for each series, except
|
||||||
|
the first one which contains the column headers, which are used for the
|
||||||
|
legend. Columns are separated by any amount of whitespace unless the
|
||||||
|
--tsv option is given which enables tab-separated columns.
|
||||||
|
|
||||||
The default legend position is "top right", same as with gnuplot.
|
The default legend position is "top right", same as with gnuplot.
|
||||||
Another frequently useful position (especially if you have lots of series)
|
Another frequently useful position (especially if you have lots of series)
|
||||||
is "below". Note that positions which consist of several words (such as
|
is "below". Note that positions which consist of several words (such as
|
||||||
"top right" need to be passed to tsplotv as a single argument, so the
|
"top right") need to be passed to tsplotv as a single argument, so the
|
||||||
space needs to be hidden from the shell by use of quotes or a backslash.
|
space needs to be hidden from the shell by use of quotes or a backslash.
|
||||||
|
|
||||||
The default output format is "png", the default style is "lines".
|
The default output format is "png", the default style is "lines".
|
||||||
|
@ -35,76 +47,62 @@ output formats, and styles.
|
||||||
The --stacked option causes the time series to be stacked on top of each
|
The --stacked option causes the time series to be stacked on top of each
|
||||||
other.
|
other.
|
||||||
|
|
||||||
|
The --time_t option specifies that the timestamps are in seconds since
|
||||||
|
the epoch. Otherwise they are parsed by add_timestring function (which
|
||||||
|
in turn uses the parse_date function of the HTTP::Date module).
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
use strict;
|
|
||||||
use TimeSeries;
|
|
||||||
use Getopt::Long;
|
|
||||||
use Pod::Usage;
|
|
||||||
use DBIx::SimpleConnect;
|
|
||||||
|
|
||||||
my $help;
|
|
||||||
my $legend_position = 'top right';
|
|
||||||
my $output_format ='png';
|
my $output_format ='png';
|
||||||
my $stacked = 0;
|
|
||||||
my $style = "lines";
|
|
||||||
my $log_y =0;
|
my $log_y =0;
|
||||||
my $finalresolution;
|
|
||||||
my $time_t =0;
|
my $time_t =0;
|
||||||
my $colors;
|
my $style = "lines";
|
||||||
|
my $tsv = 0;
|
||||||
|
my $stacked = 0;
|
||||||
|
my @yrange;
|
||||||
|
my $keeptempfiles;
|
||||||
|
my $finalresolution;
|
||||||
my $dbname;
|
my $dbname;
|
||||||
|
|
||||||
GetOptions('help|?' => \$help,
|
GetOptions('output_format|output-format=s' => \$output_format,
|
||||||
'legend_position|legend-position=s' => \$legend_position,
|
|
||||||
'output_format|output-format=s' => \$output_format,
|
|
||||||
'stacked' => \$stacked,
|
|
||||||
'style:s' => \$style,
|
|
||||||
'log_y|log-y' => \$log_y,
|
'log_y|log-y' => \$log_y,
|
||||||
'finalresolution=i' => \$finalresolution,
|
|
||||||
'time_t' => \$time_t,
|
'time_t' => \$time_t,
|
||||||
'colors=s' => \$colors,
|
'style=s' => \$style,
|
||||||
|
'tsv' => \$tsv,
|
||||||
|
'stacked' => \$stacked,
|
||||||
|
'yrange=s{2}' => \@yrange,
|
||||||
|
'keeptempfiles' => \$keeptempfiles,
|
||||||
|
'finalresolution=i' => \$finalresolution,
|
||||||
'dbname=s' => \$dbname,
|
'dbname=s' => \$dbname,
|
||||||
) or pod2usage(2);
|
)
|
||||||
pod2usage(1) if $help;
|
or pod2usage(verbose => 0);
|
||||||
|
|
||||||
|
my $sep = $tsv ? qr/\t/ : ' ';
|
||||||
|
|
||||||
binmode STDOUT, ':raw';
|
binmode STDOUT, ':raw';
|
||||||
|
|
||||||
my %series;
|
|
||||||
my $ns;
|
|
||||||
my %data;
|
|
||||||
|
|
||||||
my $ts = TimeSeries->new(output_format => $output_format);
|
my $ts = TimeSeries->new(output_format => $output_format);
|
||||||
|
$ts->{keeptempfiles} = 1 if $keeptempfiles;
|
||||||
|
|
||||||
my $dbh = DBIx::SimpleConnect->connect($dbname);
|
my $dbh = DBIx::SimpleConnect->connect($dbname);
|
||||||
|
my $sth = $dbh->prepare($ARGV[0]);
|
||||||
|
$sth->execute();
|
||||||
|
my @legend = $sth->{NAME}->@*;
|
||||||
|
shift @legend;
|
||||||
|
$ts->legend(@legend);
|
||||||
|
|
||||||
for my $q (@ARGV) {
|
while (my (@r) = $sth->fetchrow_array) {
|
||||||
my $qdata = $dbh->selectall_arrayref($q);
|
my ($timestamp, @values) = @r;
|
||||||
for my $r (@$qdata) {
|
|
||||||
my ($timestamp, $series, $value) = @$r;
|
|
||||||
$series{$series} = ++$ns unless ($series{$series});
|
|
||||||
$data{$timestamp}{$series} = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
my @series = sort { $series{$a} <=> $series{$b} } keys %series;
|
|
||||||
$ts->legend(@series);
|
|
||||||
$ts->legend_position($legend_position);
|
|
||||||
$ts->stacked($stacked);
|
|
||||||
$ts->style($style);
|
|
||||||
$ts->log_y($log_y);
|
|
||||||
$ts->finalresolution($finalresolution) if $finalresolution;
|
|
||||||
if ($colors) {
|
|
||||||
$ts->colors(split(/,/, $colors));
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $timestamp (sort keys %data) {
|
|
||||||
my %d = %{$data{$timestamp}};
|
|
||||||
my @values = @d{@series};
|
|
||||||
if ($time_t) {
|
if ($time_t) {
|
||||||
$ts->add($timestamp, @values);
|
$ts->add($timestamp, @values);
|
||||||
} else {
|
} else {
|
||||||
$ts->add_timestring($timestamp, @values);
|
$ts->add_timestring($timestamp, @values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$ts->log_y($log_y);
|
||||||
|
$ts->style($style);
|
||||||
|
$ts->stacked($stacked);
|
||||||
|
$ts->yrange(@yrange);
|
||||||
|
$ts->finalresolution($finalresolution) if $finalresolution;
|
||||||
|
|
||||||
my $g = $ts->plot();
|
my $g = $ts->plot();
|
||||||
print $g
|
print $g
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
tsplotv - plot time series given in vertical format
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
tsplotv
|
||||||
|
[--dbname dbname]
|
||||||
|
[--finalresolution dpi]
|
||||||
|
[--legend-position pos]
|
||||||
|
[--log-y]
|
||||||
|
[--output-format format ]
|
||||||
|
[--stacked]
|
||||||
|
[--style style]
|
||||||
|
[--time_t]
|
||||||
|
[--colors rgb-list]
|
||||||
|
[--configfile yaml]
|
||||||
|
[--yrange min:max]
|
||||||
|
[query ...]
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This program expects time series data in vertical format, I.e.,
|
||||||
|
each line contains a tab-separated tripel <time, series, value>.
|
||||||
|
|
||||||
|
The default legend position is "top right", same as with gnuplot.
|
||||||
|
Another frequently useful position (especially if you have lots of series)
|
||||||
|
is "below". Note that positions which consist of several words (such as
|
||||||
|
"top right" need to be passed to tsplotv as a single argument, so the
|
||||||
|
space needs to be hidden from the shell by use of quotes or a backslash.
|
||||||
|
|
||||||
|
The default output format is "png", the default style is "lines".
|
||||||
|
|
||||||
|
See L<TimeSeries> for a description of possible legend positions,
|
||||||
|
output formats, and styles.
|
||||||
|
|
||||||
|
The --stacked option causes the time series to be stacked on top of each
|
||||||
|
other.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
use v5.24;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Getopt::Long;
|
||||||
|
use Pod::Usage;
|
||||||
|
use YAML qw(LoadFile);
|
||||||
|
|
||||||
|
use DBIx::SimpleConnect;
|
||||||
|
use TimeSeries;
|
||||||
|
|
||||||
|
my $help;
|
||||||
|
my $legend_position = 'top right';
|
||||||
|
my $output_format = 'png';
|
||||||
|
my $stacked = 0;
|
||||||
|
my $style = "lines";
|
||||||
|
my $log_y = 0;
|
||||||
|
my $finalresolution;
|
||||||
|
my $time_t = 0;
|
||||||
|
my $colors;
|
||||||
|
my $dbname;
|
||||||
|
my $configfile;
|
||||||
|
my $yrange;
|
||||||
|
|
||||||
|
GetOptions('help|?' => \$help,
|
||||||
|
'legend_position|legend-position=s' => \$legend_position,
|
||||||
|
'output_format|output-format=s' => \$output_format,
|
||||||
|
'stacked' => \$stacked,
|
||||||
|
'style:s' => \$style,
|
||||||
|
'log_y|log-y' => \$log_y,
|
||||||
|
'finalresolution=i' => \$finalresolution,
|
||||||
|
'time_t' => \$time_t,
|
||||||
|
'colors=s' => \$colors,
|
||||||
|
'dbname=s' => \$dbname,
|
||||||
|
'configfile=s' => \$configfile,
|
||||||
|
'yrange=s' => \$yrange,
|
||||||
|
) or pod2usage(2);
|
||||||
|
pod2usage(1) if $help;
|
||||||
|
|
||||||
|
my $config = LoadFile($configfile) if $configfile;
|
||||||
|
|
||||||
|
binmode STDOUT, ':raw';
|
||||||
|
|
||||||
|
my $ns = 0;
|
||||||
|
my %data;
|
||||||
|
|
||||||
|
$config->{timeseries} //= {};
|
||||||
|
for (keys $config->{timeseries}->%*) {
|
||||||
|
$ns = $config->{timeseries}{$_}{order} if ($config->{timeseries}{$_}{order} // 0) > $ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $dbh = DBIx::SimpleConnect->connect($dbname);
|
||||||
|
|
||||||
|
for my $q (@ARGV) {
|
||||||
|
my $qdata = $dbh->selectall_arrayref($q);
|
||||||
|
for my $r (@$qdata) {
|
||||||
|
my ($timestamp, $series, $value) = @$r;
|
||||||
|
$config->{timeseries}{$series}{order} = ++$ns unless ($config->{timeseries}{$series}{order});
|
||||||
|
$data{$timestamp}{$series} = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my @series = sort { $config->{timeseries}{$a}{order} <=> $config->{timeseries}{$b}{order} }
|
||||||
|
keys $config->{timeseries}->%*;
|
||||||
|
if ($colors) {
|
||||||
|
my @colors = split(/,/, $colors);
|
||||||
|
while (my ($i, $c) = each(@colors)) {
|
||||||
|
$config->{timeseries}{$series[$i]}{color} = $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $ts = TimeSeries->new(output_format => $output_format);
|
||||||
|
$ts->legend(@series);
|
||||||
|
$ts->legend_position($legend_position);
|
||||||
|
$ts->stacked($stacked);
|
||||||
|
$ts->style($style);
|
||||||
|
$ts->log_y($log_y);
|
||||||
|
$ts->finalresolution($finalresolution) if $finalresolution;
|
||||||
|
$ts->colors(map $config->{timeseries}{$_}{color}, @series);
|
||||||
|
|
||||||
|
if ($yrange) {
|
||||||
|
$yrange =~s /^\[(.*)\]$/$1/; # remove optional brackets
|
||||||
|
my ($min, $max) = $yrange =~ /^(\*|[-+0-9E.]+):(\*|[-+0-9E.]+)$/;
|
||||||
|
$ts->yrange($min, $max);
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $timestamp (sort keys %data) {
|
||||||
|
my %d = %{$data{$timestamp}};
|
||||||
|
my @values = @d{@series};
|
||||||
|
if ($time_t) {
|
||||||
|
$ts->add($timestamp, @values);
|
||||||
|
} else {
|
||||||
|
$ts->add_timestring($timestamp, @values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $g = $ts->plot();
|
||||||
|
print $g
|
Loading…
Reference in New Issue