#!/usr/bin/python3 """ Python Script to plot values obtained by the rmit.py script Runs a R.I.P.L. ./plot.py -t trials -o option:values """ import argparse import itertools import json import math import numpy import re import statistics import sys import matplotlib.pyplot as plt from matplotlib.ticker import EngFormatter class Field: def __init__(self, unit, _min): self.unit = unit self.min = _min field_names = { "ns per ops" : Field('ns' , 0), "Number of processors" : Field('' , 1), "Ops per procs" : Field('Ops' , 0), "Ops per threads" : Field('Ops' , 0), "ns per ops/procs" : Field('ns' , 0), "Number of threads" : Field('thrd' , 1), "Total Operations(ops)": Field('Ops' , 0), "Ops/sec/procs" : Field('Ops' , 0), "Total blocks" : Field('Blocks', 0), "Ops per second" : Field('Ops' , 0), "Cycle size (# thrds)" : Field('thrd' , 1), "Duration (ms)" : Field('ms' , 0), } def plot(in_data, x, y, out): fig, ax = plt.subplots() colors = itertools.cycle(['#0095e3','#006cb4','#69df00','#0aa000','#fb0300','#e30002','#fd8f00','#ff7f00','#8f00d6','#4b009a','#ffff00','#b13f00']) series = {} # scatter data for each individual data point groups = {} # data points for x value for entry in in_data: name = entry[0] if not name in series: series[name] = {'x':[], 'y':[]} if not name in groups: groups[name] = {} if x in entry[2] and y in entry[2]: xval = entry[2][x] yval = entry[2][y] series[name]['x'].append(xval) series[name]['y'].append(yval) if not xval in groups[name]: groups[name][xval] = [] groups[name][xval].append(yval) lines = {} # lines from groups with min, max, median, etc. for name, data in groups.items(): if not name in lines: lines[name] = { 'x': [], 'min':[], 'max':[], 'med':[], 'avg':[] } for xkey in sorted(data): ys = data[xkey] lines[name]['x'] .append(xkey) lines[name]['min'].append(min(ys)) lines[name]['max'].append(max(ys)) lines[name]['med'].append(statistics.median(ys)) lines[name]['avg'].append(statistics.mean(ys)) for name, data in series.items(): _col = next(colors) plt.scatter(data['x'], data['y'], color=_col, label=name, marker='x') plt.plot(lines[name]['x'], lines[name]['min'], '--', color=_col) plt.plot(lines[name]['x'], lines[name]['max'], '--', color=_col) plt.plot(lines[name]['x'], lines[name]['med'], '-', color=_col) mx = max([max(s['x']) for s in series.values()]) my = max([max(s['y']) for s in series.values()]) plt.ylabel(y) plt.xlim(field_names[x].min, mx + 0.25) plt.xticks(range(1, math.ceil(mx) + 1)) plt.xlabel(x) plt.ylim(field_names[y].min, my*1.2) plt.grid(b = True) ax.xaxis.set_major_formatter( EngFormatter(unit=field_names[x].unit) ) ax.yaxis.set_major_formatter( EngFormatter(unit=field_names[y].unit) ) plt.legend(loc='upper left') if out: plt.savefig(out) else: plt.show() if __name__ == "__main__": # ================================================================================ # parse command line arguments parser = parser = argparse.ArgumentParser(description='Python Script to draw R.M.I.T. results') parser.add_argument('-f', '--file', nargs='?', type=argparse.FileType('r'), default=sys.stdin) parser.add_argument('-o', '--out', nargs='?', type=str, default=None) parser.add_argument('-y', nargs='?', type=str, default="") try: options = parser.parse_args() except: print('ERROR: invalid arguments', file=sys.stderr) parser.print_help(sys.stderr) sys.exit(1) # ================================================================================ # load data try : data = json.load(options.file) except : print('ERROR: could not read input', file=sys.stderr) parser.print_help(sys.stderr) sys.exit(1) # ================================================================================ # identify the keys series = set() fields = set() for entry in data: series.add(entry[0]) for label in entry[2].keys(): fields.add(label) if not options.out : print(series) print("fields") for f in fields: print("{}".format(f)) if options.y and options.y in field_names.keys(): plot(data, "Number of processors", options.y, options.out) else: if options.y: print("Could not find key '{}', defaulting to 'ns per ops'".format(options.y)) plot(data, "Number of processors", "ns per ops", options.out)