diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2014-08-08 14:42:07 +0300 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2014-08-08 14:42:07 +0300 |
| commit | a6163888f3c56123b1db313743c6147ba498732c (patch) | |
| tree | ff7d15d991d1d09ba6cbc0cec80924f57445bfdd /third_party/ptpd-1.1.0/tools | |
| parent | c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 (diff) | |
Add third_party libs
Diffstat (limited to 'third_party/ptpd-1.1.0/tools')
| -rw-r--r-- | third_party/ptpd-1.1.0/tools/filter_response.m | 29 | ||||
| -rw-r--r-- | third_party/ptpd-1.1.0/tools/offset_stats.m | 102 | ||||
| -rw-r--r-- | third_party/ptpd-1.1.0/tools/ptp_plot.py | 170 | ||||
| -rw-r--r-- | third_party/ptpd-1.1.0/tools/quality_correlate.py | 190 |
4 files changed, 491 insertions, 0 deletions
diff --git a/third_party/ptpd-1.1.0/tools/filter_response.m b/third_party/ptpd-1.1.0/tools/filter_response.m new file mode 100644 index 0000000..5c20163 --- /dev/null +++ b/third_party/ptpd-1.1.0/tools/filter_response.m @@ -0,0 +1,29 @@ +#!/usr/bin/octave -qf
+
+# the IIR filter
+s = 2^4;
+a = [ s -(s-1) ];
+b = [ 1/2 1/2 ];
+
+[h w] = freqz(b, a, 100000);
+
+subplot(211);
+plot(w/pi,abs(h),";;");
+axis();
+#plot(w/pi,20*log(abs(h)));
+#axis([0 1 -120 0]);
+#semilogx(w/pi,20*log(abs(h)),";;");
+#axis([1e-3 1 -120 0]);
+ylabel("gain");
+
+subplot(212);
+plot(w/pi,unwrap(angle(h)),";;");
+axis([0 1 -pi 0]);
+#semilogx(w/pi,unwrap(angle(h)),";;");
+#axis([1e-3 1 -pi 0]);
+ylabel("phase (rad)");
+xlabel("frequency");
+replot;
+
+pause;
+
diff --git a/third_party/ptpd-1.1.0/tools/offset_stats.m b/third_party/ptpd-1.1.0/tools/offset_stats.m new file mode 100644 index 0000000..26af4c2 --- /dev/null +++ b/third_party/ptpd-1.1.0/tools/offset_stats.m @@ -0,0 +1,102 @@ +#!/usr/bin/octave -qf
+
+printf("start\n");
+
+load t;
+load tr;
+
+# time window to analyze
+t_beg = 1;
+t_fin = length(t);
+
+# parameters for synthetic reference time
+#start_time = round(t(t_beg));
+#sample_interval = 1;
+
+# parameters for histogram
+h_beg = -15e-6;
+h_fin = 15e-6;
+h_sz = 1e-6;
+
+# parameters for allan variance
+# tune for your computational power
+tau_beg = 1;
+tau_fin = length(t)/10;
+tau_maxsamps = 100;
+
+# ----------
+
+printf("data loaded\n");
+
+# create synthetic reference time
+#tr = t;
+#tr(t_beg) = start_time;
+#for k = (t_beg+1):t_fin
+#
+# tr(k) = tr(k-1) + sample_interval;
+#
+#endfor
+
+# time offset computation
+o = t - tr;
+
+o_min = min(o(t_beg:t_fin));
+o_max = max(o(t_beg:t_fin));
+o_mean = mean(o(t_beg:t_fin));
+
+# relative tick rate computation
+r = t;
+for k = (t_beg+1):t_fin
+
+ r(k) = o(k) - o(k-1);
+
+endfor
+
+r_min = min(r((t_beg+1):t_fin));
+r_max = max(r((t_beg+1):t_fin));
+r_mean = mean(r((t_beg+1):t_fin));
+
+figure;
+h_bins = h_beg:h_sz:h_fin;
+hist( o(t_beg:t_fin), h_bins, 1);
+
+printf("histogram plotted\n");
+
+figure;
+subplot(211);
+plot( t_beg:t_fin, o(t_beg:t_fin), "r;time offset;",
+ [t_beg t_fin], [o_min o_min], "g;;",
+ [t_beg t_fin], [o_max o_max], "g;;",
+ [t_beg t_fin], [o_mean o_mean], "b;;");
+subplot(212);
+plot( (t_beg+1):t_fin, r((t_beg+1):t_fin), "r;relative tick rate;",
+ [(t_beg+1) t_fin], [r_min r_min], "g;;",
+ [(t_beg+1) t_fin], [r_max r_max], "g;;",
+ [(t_beg+1) t_fin], [r_mean r_mean], "b;;")
+replot;
+
+printf("offset plotted\n");
+
+# the allan vaiance computation from the IEEE 1588 spec
+a = t;
+for tau = tau_beg:tau_fin
+
+ beg = t_beg;
+ if (t_fin-2*tau) > tau_maxsamps
+ fin = tau_maxsamps;
+ else
+ fin = (t_fin-2*tau);
+ end
+
+ a(tau) = sum((t(beg:fin) - 2*t((beg+tau):(fin+tau)) + t((beg+2*tau):(fin+2*tau))).^2);
+ a(tau) /= 2*(fin-beg)*(tau^2);
+
+endfor
+
+figure;
+loglog( tau_beg:tau_fin, a(tau_beg:tau_fin), ";allan variance;");
+replot;
+
+printf("variance plotted\n");
+input("done\n");
+
diff --git a/third_party/ptpd-1.1.0/tools/ptp_plot.py b/third_party/ptpd-1.1.0/tools/ptp_plot.py new file mode 100644 index 0000000..7c43dec --- /dev/null +++ b/third_party/ptpd-1.1.0/tools/ptp_plot.py @@ -0,0 +1,170 @@ +#! /usr/bin/env python2.6
+# Copyright (c) 2010, Neville-Neil Consulting
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 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.
+#
+# Neither the name of Neville-Neil Consulting nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 THE COPYRIGHT
+# OWNER OR CONTRIBUTORS 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.
+#
+# Author: George V. Neville-Neil
+#
+# Description:
+
+"""ptp_plot.py -- Plot PTP delays reported by the slave.
+
+This program takes a ptp log file generated by the slave
+and plots various times on a graph
+
+This program requires at least python2.6 as well as numpy
+and gnuplot support.
+
+"""
+
+import csv
+import datetime
+import subprocess
+import sys
+import tempfile
+
+from numpy import *
+
+import Gnuplot, Gnuplot.funcutils
+
+def usage():
+ sys.exit()
+
+def main():
+
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option("-a", "--all", dest="all", default=0,
+ help="show all entries")
+ parser.add_option("-t", "--type", dest="type", default="delay",
+ help="plot the delay or offset")
+ parser.add_option("-l", "--logfile", dest="logfile", default=None,
+ help="logfile to use")
+ parser.add_option("-s", "--start", dest="start", default="09:30:00",
+ help="start time")
+ parser.add_option("-e", "--end", dest="end", default="16:30:00",
+ help="end time")
+ parser.add_option("-r", "--roll", dest="roll", type=int, default=0,
+ help="number of days to roll at the start")
+ parser.add_option("-p", "--print", dest="png", default=None,
+ help="file to print the graph to")
+ parser.add_option("-y", "--ymin", dest="ymin", default="0.000000",
+ help="minimum y value")
+ parser.add_option("-Y", "--ymax", dest="ymax", default="0.001000",
+ help="maximum y value")
+ parser.add_option("-S", "--save", dest="save", default=None,
+ help="save file name")
+
+
+ (options, args) = parser.parse_args()
+
+ if ((options.type != "delay") and (options.type != "offset")):
+ print "You must choose either delay or offset."
+ usage()
+
+ try:
+ logfile = csv.reader(open(options.logfile, "rb"))
+ except:
+ print "Could not open %s" % options.logfile
+ sys.exit()
+
+ #
+ # This is an ugly hack, but it turns out that gnuplot
+ # is better able to plot time data if we write it out
+ # in the familiar format to a temporary file and
+ # then plot from the file rather than building up
+ # arrays of data.
+ #
+ tmpfile = tempfile.NamedTemporaryFile()
+
+ savefile = None
+
+ if (options.save != None):
+ savefile = open(options.save, "w")
+
+
+ first = True
+ for line in logfile:
+ # Split off the microseconds
+ try:
+ dt = line[0].rpartition(':')[0]
+ except:
+ continue
+ now = datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")
+ if (first == True):
+ if (options.all == 0):
+ start = datetime.datetime.strptime(options.start, "%H:%M:%S")
+ else:
+ start = now
+ start = start.replace(year=now.year, month=now.month,
+ day=now.day + options.roll)
+ end = datetime.datetime.strptime(options.end, "%H:%M:%S")
+ end = end.replace(year=now.year, month=now.month,
+ day=now.day + options.roll)
+ first = False
+ if ((now > end) and (options.all == 0)):
+ break
+ if ((now > start) or (options.all != 0)):
+ if (options.type == "delay"):
+ tmpfile.write("%s %f\n" % (dt, float(line[3])))
+ if (savefile != None):
+ savefile.write("%s %f\n" % (dt, float(line[3])))
+ else:
+ tmpfile.write("%s %f\n" % (dt, float(line[4])))
+ if (savefile != None):
+ savefile.write("%s %f\n" % (dt, float(line[4])))
+
+ plotter = Gnuplot.Gnuplot(debug=1)
+ plotter('set data style dots')
+ if (options.type == "delay"):
+ plotter.set_range('yrange', [options.ymin, options.ymax])
+ plotter.ylabel('Seconds\\nOne Way Delay')
+ else:
+ plotter.set_range('yrange', [options.ymin, options.ymax])
+ plotter.ylabel('Seconds\\nOffset')
+ if (options.all == 0):
+ plotter.xlabel(options.logfile + " " + options.start + " - " + options.end)
+ else:
+ plotter.xlabel(options.logfile + " " + str(start) + " - " + str(now))
+ plotter('set xdata time')
+ plotter('set timefmt "%Y-%m-%d %H:%M:%S"')
+
+ tmpfile.flush()
+ plotter.plot(Gnuplot.File(tmpfile.name, using='1:3'))
+
+ if (options.png != None):
+ plotter.hardcopy(options.logfile + "-" + options.type + ".png", terminal='png')
+ raw_input('Press return to exit')
+ else:
+ raw_input('Press return to exit')
+
+
+if __name__ == "__main__":
+ main()
diff --git a/third_party/ptpd-1.1.0/tools/quality_correlate.py b/third_party/ptpd-1.1.0/tools/quality_correlate.py new file mode 100644 index 0000000..cea5dd0 --- /dev/null +++ b/third_party/ptpd-1.1.0/tools/quality_correlate.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python2.6
+# Copyright (c) 2010, Neville-Neil Consulting
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 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.
+#
+# Neither the name of Neville-Neil Consulting nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 THE COPYRIGHT
+# OWNER OR CONTRIBUTORS 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.
+#
+# Author: George V. Neville-Neil
+#
+# Description: This program reads a pair of PTPd quality files,
+# generated with the -R option, correlates and graphs the differences
+# between the time each host saw a SYNC which is an easy way to
+# measure the quality of time synchronization between two clients
+# a timing service.
+
+import sys
+
+from numpy import *
+
+import Gnuplot, Gnuplot.funcutils
+
+import gzip
+import os
+
+def main():
+
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option("-y", "--ymin", dest="ymin", default=0,
+ help="minimum y value")
+ parser.add_option("-Y", "--ymax", dest="ymax", default=1000000,
+ help="maximum y value")
+ parser.add_option("-N", "--Names", dest="hosts", nargs=2, default=None,
+ help="host list for sync graph")
+ parser.add_option("-s", "--start", dest="start", type="int", default=0,
+ help="starting sequence number")
+ parser.add_option("-p", "--print", dest="png", default=None,
+ help="print the graph to a file")
+ parser.add_option("-o", "--output", dest="output", default=None,
+ help="save the correlated data to a file.")
+ parser.add_option("-d", "--debug", dest="debug", type="int", default=0,
+ help="print debugging info (verbose)")
+ (options, args) = parser.parse_args()
+
+ if (options.output != None):
+ try:
+ outfile = open(options.output, "w")
+ except:
+ print "cannot open %s for writing" % options.output
+
+ files = []
+ for filename in options.hosts:
+ if (os.path.splitext(filename)[1] == '.gz'):
+ file = gzip.open(filename)
+ else:
+ file = open(filename)
+
+ trace = {}
+ done = False
+ while not done:
+ try:
+ (seq, ts) = file.readline().split()
+ sequence = int(seq)
+ timestamp = long(ts)
+ except StopIteration:
+ done = True
+ except:
+ break
+
+ trace[sequence] = timestamp
+
+ files.append(trace)
+
+ sequences = []
+ sequences.append(sorted(files[0].keys()))
+ sequences.append(sorted(files[1].keys()))
+
+ if ((min(sequences[0]) > max(sequences[1])) or
+ (min(sequences[1]) > max(sequences[1]))):
+ print "sequences do not overlap"
+ sys.exit(1)
+
+ # Trim the dictionaries of non overlapping elements
+
+ index = 0
+ if ((min(sequences[0]) < min(sequences[1]))):
+ start = min(sequences[0])
+ end = min(sequences[1])
+ index = 0
+ else:
+ start = min(sequences[1])
+ end = min(sequences[0])
+ index = 1
+
+ for i in range(start, end):
+ del files[index][i]
+
+ if ((max(sequences[0]) > max(sequences[1]))):
+ start = max(sequences[1])
+ end = max(sequences[0])
+ index = 0
+ else:
+ start = max(sequences[0])
+ end = max(sequences[1])
+ index = 1
+
+ for i in range(start, end):
+ del files[index][i]
+
+ if options.start == 0:
+ options.start = min(files[0].keys())
+
+ graph = []
+
+ minimum = sys.maxint
+ maximum = -sys.maxint -1
+
+ for i in range(options.start,options.start + len(files[0])):
+ try:
+ delta = abs(files[1][i] - files[0][i])
+ except KeyError:
+ print "9:99:99.000900"
+ print "missing packet %d" % i
+ continue
+
+ if delta > maximum:
+ maximum = delta
+ if delta < minimum:
+ minimum = delta
+
+ if (options.output != None):
+ outfile.write(("%d %d\n" % (delta, (files[0][i] / 1000000000))))
+
+ graph.append(delta)
+
+ if (options.output != None):
+ outfile.close()
+
+ print "min %d, max %d" % (minimum, maximum)
+
+ # if (minimum.seconds > 1):
+ # print "Time difference exceeded one second maximum, " \
+ # "cannot graph differences"
+ # sys.exit(1)
+
+ plotter = Gnuplot.Gnuplot(debug=1)
+
+ if ((options.ymin != 0) or (options.ymax != 10)):
+ plotter.set_range('yrange', [options.ymin, options.ymax])
+
+ plotter.ylabel('Time Difference\\nNanoseconds')
+ plotter.xlabel('Sample Number')
+ plotter.plot(graph)
+
+ if (options.png != None):
+ plotter.hardcopy(options.png + ".png", terminal='png')
+ raw_input('Press return to exit')
+ else:
+ raw_input('Press return to exit')
+
+# The canonical way to make a python module into a script.
+# Remove if unnecessary.
+
+if __name__ == "__main__":
+ main()
|
