plotpipe: --smooth implemented.

This commit is contained in:
Ole Tange 2021-01-20 22:55:31 +01:00
parent 0d01eb1ea2
commit 3b0b378249
2 changed files with 66 additions and 10 deletions

View file

@ -32,8 +32,8 @@ Examples:
printf "Column1\tColumn2\tColumn3"; printf "Column1\tColumn2\tColumn3";
paste <(seq 1 100) <(seq 1 100) <(seq 1 100 | shuf) ) | plotpipe paste <(seq 1 100) <(seq 1 100) <(seq 1 100 | shuf) ) | plotpipe
Copyright (C) 2020 Ole Tange, http://ole.tange.dk and Free Software Copyright (C) 2020-2021 Ole Tange, http://ole.tange.dk and Free
Foundation, Inc. Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. This is free software: you are free to change and redistribute it.

View file

@ -72,6 +72,13 @@ used as x-value. B<--nox> will use line number as x-value.
Use \0 (NUL) instead of newline (\n) as record separator. Use \0 (NUL) instead of newline (\n) as record separator.
=item B<--smooth> I<width>
=item B<-s> I<width>
Smooth values. Take the average of I<width> y-values.
=item B<--version> =item B<--version>
=item B<-V> =item B<-V>
@ -192,6 +199,7 @@ sub options_hash() {
"null|0" => \$opt::null, "null|0" => \$opt::null,
"nox|n" => \$opt::nox, "nox|n" => \$opt::nox,
"header|H" => \$opt::header, "header|H" => \$opt::header,
"smooth|s=i" => \$opt::smooth,
); );
} }
@ -223,6 +231,9 @@ sub help() {
'-0 Records separated by \0 instead of \n', '-0 Records separated by \0 instead of \n',
'-C str Columns separator', '-C str Columns separator',
'-V Show version', '-V Show version',
'--logx/logy/logxy Log x/y/x&y',
'-n No X value',
'-s num Smooth num Y-values',
"", "",
"See 'man $Global::progname' for details", "See 'man $Global::progname' for details",
"",); "",);
@ -279,6 +290,18 @@ sub my_dump(@) {
} }
} }
sub sum(@) {
# Returns:
# Sum of values of array
my @args = @_;
my $sum = 0;
for (@args) {
# Skip undefs
$_ and do { $sum += $_; }
}
return $sum;
}
sub max(@) { sub max(@) {
# Returns: # Returns:
# Maximum value of array # Maximum value of array
@ -359,30 +382,63 @@ if($opt::header) {
@header = (); @header = ();
} }
# Save data to tmpfile that will be read by Gnuplot # Convert input to perl table
use File::Temp qw(tempfile);
$ENV{'TMPDIR'} ||= "/tmp";
my($filehandle,$filename) =
tempfile(DIR=>$ENV{'TMPDIR'}, TEMPLATE => 'plotXXXXX');
my $ncols = split /$opt::colsep/, $csv[0]; my $ncols = split /$opt::colsep/, $csv[0];
my @tbl;
if($ncols >= 2 and not $opt::nox) { if($ncols >= 2 and not $opt::nox) {
# Column 1 = x-axis # Column 1 = x-axis
for(@csv) { for(@csv) {
chomp; chomp;
print $filehandle ((join "\001", split /$opt::colsep/, $_),"\n"); my @row = split /$opt::colsep/, $_;
push @tbl,\@row;
} }
} else { } else {
# All data = y-axis, invent x-axis # All data = y-axis, invent x-axis
my $x = 0; my $x = 0;
for(@csv) { for(@csv) {
chomp; chomp;
print $filehandle ((join "\001", $x++, split /$opt::colsep/, $_),"\n"); my @row = ($x++, split /$opt::colsep/, $_);
push @tbl,\@row;
} }
# Prepend dummy header for x-axis # Prepend dummy header for x-axis
unshift(@header,""); unshift(@header,"");
$ncols += 1; $ncols += 1;
} }
# Smooth data
if($opt::smooth) {
my (@sum,@new);
if($#tbl < $opt::smooth) {
print STDERR "plotpipe: --smooth must be lower than the ",
"number of rows (",1+$#tbl,")\n";
exit(255);
}
my $smooth = $opt::smooth-1;
for(my $x = 0; $x < $smooth; $x++) {
for (my $y = 0; $y <= $#{$tbl[$x]}; $y++) {
$sum[$y] += $tbl[$x][$y] / $opt::smooth;
}
}
for(my $x = $smooth; $x <= $#tbl; $x++) {
for (my $y = 0; $y <= $#{$tbl[$x]}; $y++) {
$sum[$y] += $tbl[$x][$y] / $opt::smooth;
$new[$x-$smooth][$y] = $sum[$y];
$sum[$y] -= $tbl[$x-$smooth][$y] / $opt::smooth;
}
}
@tbl = @new;
}
# Save data to tmpfile that will be read by Gnuplot
use File::Temp qw(tempfile);
$ENV{'TMPDIR'} ||= "/tmp";
my($filehandle,$filename) =
tempfile(DIR=>$ENV{'TMPDIR'}, TEMPLATE => 'plotXXXXX');
for(@tbl) {
print $filehandle (join "\001", @$_)."\n";
}
close $filehandle;
# Generate the variant part of Gnuplot script # Generate the variant part of Gnuplot script
for(my $col = 2; $col <= $ncols; $col++) { for(my $col = 2; $col <= $ncols; $col++) {
my $legend; my $legend;
@ -392,6 +448,7 @@ for(my $col = 2; $col <= $ncols; $col++) {
push @plotscript, qq("$filename" using 1:$col with lines $legend,); push @plotscript, qq("$filename" using 1:$col with lines $legend,);
} }
# Add --logx/--logy/--logxy to Gnuplot script
my @logscale; my @logscale;
if($opt::logx or $opt::logxy) { if($opt::logx or $opt::logxy) {
push @logscale, "set logscale x 10;"; push @logscale, "set logscale x 10;";
@ -400,7 +457,6 @@ if($opt::logy or $opt::logxy) {
push @logscale, "set logscale y 10;"; push @logscale, "set logscale y 10;";
} }
# Make full Gnuplot script # Make full Gnuplot script
my $plotscript=<<_EOS ; my $plotscript=<<_EOS ;
set title "@title"; set title "@title";