diff --git a/plotpipe/README b/plotpipe/README index d535157..7bdac30 100644 --- a/plotpipe/README +++ b/plotpipe/README @@ -32,8 +32,8 @@ Examples: printf "Column1\tColumn2\tColumn3"; paste <(seq 1 100) <(seq 1 100) <(seq 1 100 | shuf) ) | plotpipe -Copyright (C) 2020 Ole Tange, http://ole.tange.dk and Free Software -Foundation, Inc. +Copyright (C) 2020-2021 Ole Tange, http://ole.tange.dk and Free +Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. diff --git a/plotpipe/plotpipe b/plotpipe/plotpipe index 369a7fc..a3b78f5 100755 --- a/plotpipe/plotpipe +++ b/plotpipe/plotpipe @@ -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. +=item B<--smooth> I + +=item B<-s> I + +Smooth values. Take the average of I y-values. + + =item B<--version> =item B<-V> @@ -192,6 +199,7 @@ sub options_hash() { "null|0" => \$opt::null, "nox|n" => \$opt::nox, "header|H" => \$opt::header, + "smooth|s=i" => \$opt::smooth, ); } @@ -223,6 +231,9 @@ sub help() { '-0 Records separated by \0 instead of \n', '-C str Columns separator', '-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", "",); @@ -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(@) { # Returns: # Maximum value of array @@ -359,30 +382,63 @@ if($opt::header) { @header = (); } -# 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'); +# Convert input to perl table my $ncols = split /$opt::colsep/, $csv[0]; +my @tbl; if($ncols >= 2 and not $opt::nox) { # Column 1 = x-axis for(@csv) { chomp; - print $filehandle ((join "\001", split /$opt::colsep/, $_),"\n"); + my @row = split /$opt::colsep/, $_; + push @tbl,\@row; } } else { # All data = y-axis, invent x-axis my $x = 0; for(@csv) { 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 unshift(@header,""); $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 for(my $col = 2; $col <= $ncols; $col++) { my $legend; @@ -392,6 +448,7 @@ for(my $col = 2; $col <= $ncols; $col++) { push @plotscript, qq("$filename" using 1:$col with lines $legend,); } +# Add --logx/--logy/--logxy to Gnuplot script my @logscale; if($opt::logx or $opt::logxy) { push @logscale, "set logscale x 10;"; @@ -400,7 +457,6 @@ if($opt::logy or $opt::logxy) { push @logscale, "set logscale y 10;"; } - # Make full Gnuplot script my $plotscript=<<_EOS ; set title "@title";