#!/usr/bin/perl -Tw # # $Id: trafgraph,v 1.8 2005/04/29 17:57:39 dgregor Exp $ # # Copyright (c) 1998 Daniel J. Gregor, Jr., All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by Daniel J. Gregor, Jr. # 4. The name of Daniel J. Gregor, Jr. may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY DANIEL J. GREGOR, JR. ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL DANIEL J. GREGOR, JR. BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. use Getopt::Std; require 'timelocal.pl'; $print_range = 1; $default_term = "png small color"; $default_plotstyle = "lines"; $usage = <] [-T ] [-t ] [-x <xaxislabel>] [-y <yaxislabel>] [-s <plot style>] [-a <seconds>] [<data file 1> <comment 1>] [<data file 2> <comment 2>] ... EOF $detailedusage = <<EOF; -h This help message. -m Read hours and minutes in input file and on graph print hours and minutes in tick labels. -b Break graph if we are missing input values for this number of seconds. Mutually exclusive with -B. -B Drag the graph down to the X axis if we are missing input values for this number of seconds. Mutually exclusive with -b. -e Input times are in seconds since epoch. -t Graph title. -T GNUplot terminal type. Defaults to "$default_term". -a Aggregate data over <seconds> interval -s Plot style, defaults to "$default_plotstyle". -x,-y X (or Y) axis comment. EOF Getopt::Std::getopts('a:t:x:y:b:B:T:s:hme', \%opts) || die $usage; if (defined($opts{'h'})) { print STDERR $usage; print STDERR $detailedusage; exit 1; } if (defined($opts{'b'}) && defined($opts{'B'})) { print STDERR "-b and -B are mutually exclusive\n"; print STDERR $usage; exit 1; } if ((@ARGV % 2) != 0) { die "$usage"; } $graphtitle = $opts{'t'}; $xaxislabel = $opts{'x'}; $yaxislabel = $opts{'y'}; $aggregate = $opts{'a'}; $termtype = defined($opts{'T'}) ? $opts{'T'} : $default_term; $plotstyle = defined($opts{'s'}) ? $opts{'s'} : $default_plotstyle; sub readdata { local($fh) = shift(@_); local($linetitle); local($lasttime); local($aggregateval); if (defined(@_)) { $linetitle = shift(@_); } local(%plot); while (<$fh>) { chomp(); if (m/^\s*$/) { defined($time = ${$plot{'datetimes'}}[$#{$plot{'datetimes'}}]) || next; $val = undef; } elsif (defined($opts{'e'})) { m/^\s*(\d+)\s+([0-9.]+)\s*$/ || die "syntax error: \"$_\""; $time = $1; $val = $2; } elsif (defined($opts{'m'})) { m/^\s*(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})\s+([0-9.]+)\s*$/ || die "syntax error: \"$_\""; $time = &timelocal(0, $5, $4, $3, $2 - 1, $1 - 1900); $val = $6; } else { m/^\s*(\d{4})(\d{2})(\d{2})\s+([0-9.]+)\s*$/ || die "syntax error: \"$_\""; $time = &timelocal(0, 0, 0, $3, $2 - 1, $1 - 1900); $val = $4; } if (defined($aggregate)) { if (defined($lasttime) && int($time / $aggregate) == $lasttime) { $aggregateval += $val; } else { if (defined($lasttime)) { $plottime = $lasttime * $aggregate; $plot{'vals'}{$plottime} = $aggregateval; push(@{$plot{'datetimes'}}, $plottime); } $lasttime = int($time / $aggregate); $aggregateval = $val; } } else { $plot{'vals'}{$time} = $val; push(@{$plot{'datetimes'}}, $time); } } if (defined($aggregate) && defined($lasttime)) { $plottime = $lasttime * $aggregate; $plot{'vals'}{$plottime} = $aggregateval; push(@{$plot{'datetimes'}}, $plottime); } $plot{'plotcommand'} = "'-' using 1:2 "; $plot{'plotcommand'} .= " title \"$linetitle\"" if defined($linetitle); $plot{'plotcommand'} .= " with $plotstyle"; return \%plot; } sub initgraph { print "set term $termtype\n\n"; print "set xlabel \"$xaxislabel\"\n" if defined($xaxislabel); print "set ylabel \"$yaxislabel\"\n" if defined($yaxislabel); print "\n"; print "set title \"$graphtitle\"\n" if defined($graphtitle); print "set xdata time\n\n"; print "set timefmt \"%Y%m%d%H%M%S\"\n\n"; if (defined($opts{'m'})) { print 'set format x "%m/%d/%y\n%H:%M"', "\n"; } else { print 'set format x "%m/%d/%y"', "\n"; } } if (@ARGV) { while (@ARGV) { local($datafile) = shift(@ARGV); local($comment) = shift(@ARGV); if ($datafile eq "-") { # read from STDIN push(@plots, readdata(\*STDIN, $comment)); } else { open(PLOTDATA, "<" . $datafile) || die "Could not open $datafile"; push(@plots, readdata(\*PLOTDATA, $comment)); } } } else { push(@plots, readdata(\*STDIN)); } initgraph(); foreach $plot (@plots) { push(@plotcommands, $$plot{'plotcommand'}); push(@datetimes, @{$$plot{'datetimes'}}); } @datetimes = sort( {$a <=> $b} @datetimes); @t = localtime($datetimes[0]); $begindatetime = sprintf("%04d%02d%02d%02d%02d%02d", $t[5] + 1900, $t[4] + 1, $t[3], $t[2], $t[1], $t[0]); @t = localtime($datetimes[$#datetimes]); $enddatetime = sprintf("%04d%02d%02d%02d%02d%02d", $t[5] + 1900, $t[4] + 1, $t[3], $t[2], $t[1], $t[0]); print "set xrange [\"$begindatetime\":\"$enddatetime\"]\n" if $print_range; print "plot " . join(", \\\n", @plotcommands). "\n"; foreach $plot (@plots) { foreach $i (@{$$plot{'datetimes'}}) { if (!defined($$plot{'vals'}{$i})) { print "\n"; } else { if (defined($opts{'b'}) && defined($lasttime) && $i > ($lasttime + $opts{'b'})) { print "\n"; } if (defined($opts{'B'}) && defined($lasttime) && $i > ($lasttime + $opts{'B'})) { @l = localtime($lasttime + $opts{'B'}); @c = localtime($i - $opts{'B'}); printf "%04d%02d%02d%02d%02d%02d %f\n", $l[5] + 1900, $l[4] + 1, $l[3], $l[2], $l[1], $l[0], 0; printf "%04d%02d%02d%02d%02d%02d %f\n", $c[5] + 1900, $c[4] + 1, $c[3], $c[2], $c[1], $c[0], 0; } @t = localtime($i); printf "%04d%02d%02d%02d%02d%02d %f\n", $t[5] + 1900, $t[4] + 1, $t[3], $t[2], $t[1], $t[0], $$plot{'vals'}{$i}; } $lasttime = $i; } print "e\n"; undef($lasttime); }