/contrib/ntp/scripts/plot_summary.in

https://bitbucket.org/freebsd/freebsd-head/ · Autoconf · 337 lines · 282 code · 19 blank · 36 comment · 29 complexity · 3b2ae587c00f80e5ba3166061eb83f4b MD5 · raw file

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