Home | History | Annotate | Line # | Download | only in scripts
      1 #! @PATH_PERL@ -w
      2 # @configure_input@
      3 # Id
      4 #
      5 # Use Gnuplot to display data in summary files produced by summary.pl.
      6 # This script requires GNUPLOT 3.7!
      7 #
      8 # Copyright (c) 1997, 1999 by Ulrich Windl <Ulrich.Windl (at] rz.uni-regensburg.de>
      9 #
     10 # This program is free software; you can redistribute it and/or modify
     11 # it under the terms of the GNU General Public License as published by
     12 # the Free Software Foundation; either version 2 of the License, or
     13 # (at your option) any later version.
     14 #
     15 # This program is distributed in the hope that it will be useful, but
     16 # WITHOUT ANY WARRANTY; without even the implied warranty of
     17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18 # General Public License for more details.
     19 #
     20 # You should have received a copy of the GNU General Public License
     21 # along with this program; if not, write to the Free Software
     22 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     23 package plot_summary;
     24 use 5.006_000;
     25 use strict;
     26 use Time::Local;
     27 
     28 my ($identifier, $offset_limit, $gnuplot_terminal, $wait_after_plot,
     29     $output_file, $output_file_number);
     30 
     31 exit run(@ARGV) unless caller;
     32 
     33 sub run {
     34     my $opts;
     35     if (!processOptions(\@_, $opts)) {
     36         usage(1);
     37     }
     38 
     39     $identifier  = $opts->{'identifier'};
     40     if (!$identifier) {
     41         $identifier = "host".`hostname`;
     42         chomp $identifier;
     43     }
     44     $offset_limit       = $opts->{'offset-limit'};
     45     $output_file        = $opts->{'output-file'};
     46     $output_file_number = 1;
     47     $gnuplot_terminal   = $opts->{'plot-terminal'}
     48     || ( $ENV{DISPLAY} ? "x11" : "dumb" );
     49     $wait_after_plot    = !$opts->{'dont-wait'};
     50 
     51     die "illegal offset-limit: $offset_limit" unless $offset_limit > 0.0;
     52     $offset_limit *= 1e6;			# scale to microseconds
     53 
     54     my $summary_dir = $opts->{'directory'};
     55 
     56     my $loop_summary ="$summary_dir/loop_summary";
     57     my $peer_summary ="$summary_dir/peer_summary";
     58     my $clock_summary="$summary_dir/clock_summary";
     59 
     60     my @peer_list   = @{$opts->{'peer'}};
     61 
     62     do_loop($loop_summary);
     63     do_peer($peer_summary, $_) for @peer_list;
     64 }
     65 
     66 # return the smallest value in the given list
     67 sub min
     68 {
     69     my ($result, @rest) = @_;
     70     map { $result = $_ if ($_ < $result) } @rest;
     71     return($result);
     72 }
     73 
     74 # return the largest value in the given list
     75 sub max
     76 {
     77     my ($result, @rest) = @_;
     78     map { $result = $_ if ($_ > $result) } @rest;
     79     return($result);
     80 }
     81 
     82 # maybe open alternate output file
     83 sub open_output
     84 {
     85     my $file;
     86     if ($output_file) {
     87 	while ( -r ($file = "$output_file$output_file_number") ) {
     88 	    ++$output_file_number;
     89 	}
     90 	open TOUCH, ">$file" and close TOUCH or die "$file: $!";
     91 	print "set output \"$file\"\n";
     92     }
     93 }
     94 
     95 # make Gnuplot wait
     96 sub maybe_add_pause
     97 {
     98     print "pause -1 \"Press key to continue...\"\n" if $wait_after_plot;
     99 }
    100 
    101 # plot data from loop summary
    102 sub do_loop
    103 {
    104     my $fname = shift;
    105     my $line;
    106     my $out_file = "/tmp/tempdata$$";
    107     my $cmd_file = "/tmp/tempcmd$$";
    108     my ($first_day, $day_out) = ("", 0);
    109     my ($lower_bound, $upper_bound, $rms);
    110     my ($min_offs, $max_offs) = (1e9, -1e9);
    111     my ($min_rms, $max_rms) = (1e9, -1e9);
    112     open INPUT, "$fname" or die "$fname: $!";
    113     open OUTPUT, ">$out_file" or die "$out_file: $!";
    114     my @Fld;
    115     while (<INPUT>) {
    116 	chop;	# strip record separator
    117 	@Fld = split;
    118 	if ($#Fld == 0) {
    119 # loops.19960405
    120 	    $_ = $Fld[0]; s/.*([12]\d{3}[01]\d[0-3]\d)$/$1/;
    121 	    m/(\d{4})(\d{2})(\d{2})/;
    122 	    $line = timegm(59, 59, 23, $3, $2 - 1, $1 - 1900, 0, 0, 0);
    123 	    $line = int $line / 86400;	# days relative to 1970
    124 	    $first_day = "$1-$2-$3 ($line)" unless $day_out;
    125 	    next;
    126 	}
    127 	if ($#Fld != 8) {
    128 	    warn "Illegal number of fields in file $fname, line $.";
    129 	    next;
    130 	}
    131 # loop 216, 856106+/-874041.5, rms 117239.8, freq 67.52+/-10.335, var 4.850
    132 	$_ = $Fld[1]; s/,/ /; $line .= " $_";
    133 	$_ = $Fld[2]; m:(.+?)\+/-(.+),:;
    134 	$lower_bound = $1 - $2;
    135 	$upper_bound = $1 + $2;
    136 	$line .= "$1 $lower_bound $upper_bound";
    137 	$min_offs = min($min_offs, $lower_bound);
    138 	$max_offs = max($max_offs, $upper_bound);
    139 	$_ = $Fld[4]; s/,/ /; $rms = $_;
    140 	$min_rms = min($min_rms, $rms);
    141 	$max_rms = max($max_rms, $rms);
    142 	$line .= " $rms";
    143 	$_ = $Fld[6]; m:(.+?)\+/-(.+),:;
    144 	$line .= " $1 " . ($1-$2) . " " . ($1+$2);
    145 	$line .= " $Fld[8]";
    146 	print OUTPUT "$line\n";
    147 	$day_out = 1;
    148 # 9621 216 856106 -17935.5 1730147.5 117239.8  67.52 57.185 77.855 4.850
    149     }
    150     close INPUT;
    151     close OUTPUT or die "close failed on $out_file: $!";
    152     my $ylimit = "[";
    153     if ($min_offs < -$offset_limit) {
    154 	$ylimit .= "-$offset_limit";
    155     }
    156     $ylimit .= ":";
    157     if ($max_offs > $offset_limit) {
    158 	$ylimit .= "$offset_limit";
    159     }
    160     if ( $ylimit eq "[:" ) {
    161 	$ylimit = "";
    162     } else {
    163 	$ylimit = "[] $ylimit]";
    164     }
    165 # build command file for GNUplot
    166     open OUTPUT, "> $cmd_file" or die "$cmd_file: $!";
    167     my $oldfh = select OUTPUT;
    168     print "set term $gnuplot_terminal\n";
    169     open_output;
    170     print "set grid\n";
    171     print "set title \"Loop Summary for $identifier: " .
    172 	"Daily mean values since $first_day\\n" .
    173 	"(Offset limit is $offset_limit microseconds)\"\n";
    174     print "set ylabel \"[us]\"\n";
    175     print "set style data yerrorbars\n";
    176     print "set multiplot\n";
    177     print "set size 1, 0.5\n";
    178     print "set lmargin 8\n";
    179     print "set origin 0, 0.5\n";
    180     print "plot $ylimit \"$out_file\"" .
    181 	" using 1:3:4:5 title \"mean offset\", ";
    182     print "\"$out_file\" using 1:(\$3-\$6/2) " .
    183 	"title \"(sigma low)\" with lines, ";
    184     print "\"$out_file\" using 1:3 smooth bezier " .
    185 	"title \"(Bezier med)\" with lines, ";
    186     print "\"$out_file\" using 1:(\$3+\$6/2) " .
    187 	"title \"(sigma high)\" with lines\n";
    188     print "set ylabel \"[ppm]\"\n";
    189     print "set origin 0, 0.0\n";
    190     print "set title\n";
    191     print "set xlabel \"Days relative to 1970\"\n";
    192     print "plot \"$out_file\" using 1:7:8:9 title \"mean frequency\", ";
    193     print "\"$out_file\" using 1:(\$7-\$10/2) " .
    194 	"title \"(sigma low)\" with lines, ";
    195     print "\"$out_file\" using 1:7 smooth bezier " .
    196 	"title \"(Bezier med)\" with lines, ";
    197     print "\"$out_file\" using 1:(\$7+\$10/2) " .
    198 	"title \"(sigma high)\" with lines\n";
    199     print "set nomultiplot\n";
    200     maybe_add_pause;
    201 
    202     $ylimit = "[";
    203     if ($min_rms < -$offset_limit) {
    204 	$ylimit .= "-$offset_limit";
    205     }
    206     $ylimit .= ":";
    207     if ($max_rms > $offset_limit) {
    208 	$ylimit .= "$offset_limit";
    209     }
    210     if ( $ylimit eq "[:" ) {
    211 	$ylimit ="";
    212     } else {
    213 	$ylimit = "[] $ylimit]";
    214     }
    215 
    216     open_output;
    217     print "set title \"Loop Summary for $identifier: " .
    218 	"Standard deviation since $first_day\\n" .
    219 	"(Offset limit is $offset_limit microseconds)\"\n";
    220     print "set xlabel\n";
    221     print "set ylabel \"[us]\"\n";
    222     print "set origin 0, 0.5\n";
    223     print "set style data linespoints\n";
    224     print "set multiplot\n";
    225     print "plot $ylimit \"$out_file\" using 1:6 title \"Offset\", ";
    226     print "\"$out_file\" using 1:6 smooth bezier " .
    227 	"title \"(Bezier)\" with lines\n";
    228     print "set title\n";
    229     print "set origin 0, 0.0\n";
    230     print "set xlabel \"Days relative to 1970\"\n";
    231     print "set ylabel \"[ppm]\"\n";
    232     print "plot \"$out_file\" using 1:10 title \"Frequency\", ";
    233     print "\"$out_file\" using 1:10 smooth bezier " .
    234 	"title \"(Bezier)\" with lines\n";
    235     print "set nomultiplot\n";
    236     maybe_add_pause;
    237 
    238     close OUTPUT or die "close failed on $cmd_file: $!";
    239     select $oldfh;
    240     print `gnuplot $cmd_file`;
    241     unlink $cmd_file;
    242     unlink $out_file;
    243 }
    244 
    245 # plot data form peer summary
    246 sub do_peer
    247 {
    248     my $fname = shift;
    249     my $peer = shift;
    250     my $out_file = "/tmp/tempdata$$";
    251     my $cmd_file = "/tmp/tempcmd$$";
    252     my $line;
    253     my ($first_day, $day_out) = ("", 0);
    254     open INPUT, "$fname" or die "$fname: $!";
    255     open OUTPUT, ">$out_file" or die "$out_file: $!";
    256     my @Fld;
    257     while (<INPUT>) {
    258 	chop;	# strip record separator
    259 	@Fld = split;
    260 	if ($#Fld == 0) {
    261 # peers.19960405
    262 	    $_ = $Fld[0]; s/.*([12]\d{3}[01]\d[0-3]\d)$/$1/;
    263 	    m/(\d{4})(\d{2})(\d{2})/ or next;
    264 	    $line = timegm(59, 59, 23, $3, $2 - 1, $1 - 1900, 0, 0, 0);
    265 	    $line = int $line / 86400;	# days relative to 1970
    266 	    $first_day = "$1-$2-$3 ($line)" unless $day_out;
    267 	    next;
    268 	}
    269 	if ($#Fld != 7) {
    270 	    warn "Illegal number of fields in file $fname, line $.";
    271 	    next;
    272 	}
    273 	next if ($Fld[0] ne $peer);
    274 #       ident     cnt     mean     rms      max     delay     dist     disp
    275 # 127.127.8.1       38   30.972  189.867 1154.607    0.000  879.760  111.037
    276 	$Fld[0] = $line;
    277 	print OUTPUT join(' ', @Fld) . "\n";
    278 # 9969 38 30.972 189.867 1154.607 0.000 879.760 111.037
    279 	$day_out = 1;
    280     }
    281     close INPUT;
    282     close OUTPUT or die "close failed on $out_file: $!";
    283     die "no data found for peer $peer" if !$day_out;
    284     open OUTPUT, "> $cmd_file" or die "$cmd_file: $!";
    285     my $oldfh = select OUTPUT;
    286     print "set term $gnuplot_terminal\n";
    287     open_output;
    288     print "set grid\n";
    289     print "set multiplot\n";
    290     print "set lmargin 8\n";
    291     print "set size 1, 0.34\n";
    292     print "set origin 0, 0.66\n";
    293     print "set title " .
    294 	"\"Peer Summary for $peer on $identifier since $first_day\"\n";
    295     print "set style data linespoints\n";
    296     print "set ylabel \"[us]\"\n";
    297     print "plot \"$out_file\" using 1:3 title \"mean offset\", ";
    298     print "\"$out_file\" using 1:3 smooth bezier " .
    299 	"title \"(Bezier)\" with lines, ";
    300     print "\"$out_file\" using 1:(\$3-\$7/2) " .
    301 	"title \"(sigma low)\" with lines, ";
    302     print "\"$out_file\" using 1:(\$3+\$7/2) " .
    303 	"title \"(sigma high)\" with lines\n";
    304     print "set title\n";
    305     print "set origin 0, 0.34\n";
    306     print "set size 1, 0.32\n";
    307     print "set ylabel\n";
    308     print "plot \"$out_file\" using 1:7 title \"dist\", ";
    309     print "\"$out_file\" using 1:7 smooth bezier " .
    310 	"title \"(Bezier)\" with lines\n";
    311     print "set origin 0, 0.00\n";
    312     print "set size 1, 0.35\n";
    313     print "set xlabel \"Days relative to 1970\"\n";
    314     print "plot \"$out_file\" using 1:8 title \"disp\", ";
    315     print "\"$out_file\" using 1:8 smooth bezier " .
    316 	"title \"(Bezier)\" with lines\n";
    317     print "set nomultiplot\n";
    318     maybe_add_pause;
    319 
    320     select $oldfh;
    321     close OUTPUT or die "close failed on $cmd_file: $!";
    322     print `gnuplot $cmd_file`;
    323     unlink $cmd_file;
    324     unlink $out_file;
    325 }
    326 
    327 @plot_summary_opts@
    328 
    329 1;
    330 __END__
    331