#! /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()