#!/usr/bin/python3 import numpy as np import re import sys, getopt import fileinput import argparse #-------------------------------------------------------------------------------- # Parse arguments parser = argparse.ArgumentParser(description='Produce a graph representing CPU activity over time.') parser.add_argument('-i', '--input' , dest='infile' , type=argparse.FileType('r'), default=sys.stdin, help='input file containing processor activity; if none specified then will use stdin.') parser.add_argument('-o', '--output', dest='outfile', type=argparse.FileType('w'), default=None, help='output file with any image format extension such as .png or .svg; if none specified then plt.show() will be used') args = parser.parse_args() print("----- Processing Halts Output -----") if not args.outfile: print("ERROR : no output file specified and interactive mode not supported", file=sys.stderr) sys.exit(1) #-------------------------------------------------------------------------------- # Process data class Proc: def __init__(self, id, name, address): self.name = name self.address = address self.id = id class Point: def __init__(self, time, on): self.time = time self.on = on processors = {} data = {} #-------------------------------------------------------------------------------- # Parse data for line in args.infile: match = re.match("Processor : ([0-9]+) - (.*) \((0x[0-9a-f]+)\)", line) if match : id = int(match.group(1)) processors[id] = Proc(id, match.group(2), match.group(3)) continue match = re.match("PH:([0-9]+) - ([0-9]+) ([0-9]+)", line) if match : id = int(match.group(1)) if not id in data: data[id] = [] data[id].append(Point(int(match.group(2)), int(match.group(3)))) continue print("WARNING : line '%s' filterred not matched" % line, file=sys.stderr) #-------------------------------------------------------------------------------- # Check data if not data: print("ERROR : no data extracted from '%s'" % args.infile, file=sys.stderr) for d in data: if not d in processors: print("WARNING : unkown processor '%s'" % d, file=sys.stderr) prevT = data[d][0].time prevO = data[d][0].on for p in data[d][1:]: if prevT > p.time: print("WARNING : Time is inconsistant for Proc '%s'" % d, file=sys.stderr) if prevO == p.on: print("WARNING : State is inconsistant for Proc '%s' at %s-%s" % (d, prevT, p.time), file=sys.stderr) prevT = p.time prevO = p.on #-------------------------------------------------------------------------------- # Convert data to series offset = min(data) series = dict() for d in data: series[d] = ([], [], []) for p in data[d]: series[d][0].append( p.time ) series[d][1].append(p.on + d - offset) series[d][2].append(d - offset) #-------------------------------------------------------------------------------- # setup matplotlib import matplotlib as mpl mpl.use('Agg') import matplotlib.pyplot as plt import matplotlib.ticker as ticker plt.style.use('dark_background') #-------------------------------------------------------------------------------- # setup plot dots_per_inch = 200 height_inches = 5 width_inches = 12 fig = plt.figure(figsize=(width_inches, height_inches), dpi=dots_per_inch) print('number of series={}'.format(len(series))) for s, xy in series.items(): if s in processors: name = '"{}" ({})'.format(processors[s].name, processors[s].address) else: name = s print( ' plotting series {} with {} points'.format(name, len(xy[0])) ) plt.fill_between(xy[0], xy[1], xy[2], step="post", alpha=0.4) plt.step(xy[0], xy[1], where='post') #-------------------------------------------------------------------------------- # y axis major, minor ax = plt.gca() ax.grid(which='major', axis='y', linestyle='-', color='lightgray') ax.yaxis.set_minor_locator(ticker.AutoMinorLocator()) ax.grid(which='minor', axis='y', linestyle='dotted', color='gray') #-------------------------------------------------------------------------------- # x axis major, minor ax.grid(which='major', axis='x', linestyle='-', color='lightgray') ax.xaxis.set_minor_locator(ticker.AutoMinorLocator()) ax.grid(which='minor', axis='x', linestyle='dotted', color='gray') #-------------------------------------------------------------------------------- # do the plot plt.tight_layout() print("saving figure image %s\n" % args.outfile.name) plt.savefig(args.outfile.name)