summaryrefslogtreecommitdiff
path: root/utils/json2graph.py
diff options
context:
space:
mode:
authorJoel Martin <jmartin@sentryds.com>2011-08-25 12:24:52 -0500
committerJoel Martin <jmartin@sentryds.com>2011-08-25 12:24:52 -0500
commit65edee7696dc40dbc3e1a068c7767257be1f6bd1 (patch)
treeb7e54cd8a149b4ad3ceaeacc41987e51aeee2d5f /utils/json2graph.py
parent1d7af907209f3f1e3a7bad40ff9413b358d2c206 (diff)
downloadnovnc-html5-test.tar.gz
Fix menu. Add web-socket-js and websockify.html5-test
Diffstat (limited to 'utils/json2graph.py')
-rwxr-xr-xutils/json2graph.py206
1 files changed, 206 insertions, 0 deletions
diff --git a/utils/json2graph.py b/utils/json2graph.py
new file mode 100755
index 0000000..0f6a7ad
--- /dev/null
+++ b/utils/json2graph.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+
+'''
+Use matplotlib to generate performance charts
+Copyright 2011 Joel Martin
+Licensed under GPL version 3 (see docs/LICENSE.GPL-3)
+'''
+
+# a bar plot with errorbars
+import sys, json, pprint
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.font_manager import FontProperties
+
+def usage():
+ print "%s json_file level1 level2 level3 [legend_height]\n\n" % sys.argv[0]
+ print "Description:\n"
+ print "level1, level2, and level3 are one each of the following:\n";
+ print " select=ITEM - select only ITEM at this level";
+ print " bar - each item on this level becomes a graph bar";
+ print " group - items on this level become groups of bars";
+ print "\n";
+ print "json_file is a file containing json data in the following format:\n"
+ print ' {';
+ print ' "conf": {';
+ print ' "order_l1": [';
+ print ' "level1_label1",';
+ print ' "level1_label2",';
+ print ' ...';
+ print ' ],';
+ print ' "order_l2": [';
+ print ' "level2_label1",';
+ print ' "level2_label2",';
+ print ' ...';
+ print ' ],';
+ print ' "order_l3": [';
+ print ' "level3_label1",';
+ print ' "level3_label2",';
+ print ' ...';
+ print ' ]';
+ print ' },';
+ print ' "stats": {';
+ print ' "level1_label1": {';
+ print ' "level2_label1": {';
+ print ' "level3_label1": [val1, val2, val3],';
+ print ' "level3_label2": [val1, val2, val3],';
+ print ' ...';
+ print ' },';
+ print ' "level2_label2": {';
+ print ' ...';
+ print ' },';
+ print ' },';
+ print ' "level1_label2": {';
+ print ' ...';
+ print ' },';
+ print ' ...';
+ print ' },';
+ print ' }';
+ sys.exit(2)
+
+def error(msg):
+ print msg
+ sys.exit(1)
+
+
+#colors = ['#ff0000', '#0863e9', '#00f200', '#ffa100',
+# '#800000', '#805100', '#013075', '#007900']
+colors = ['#ff0000', '#00ff00', '#0000ff',
+ '#dddd00', '#dd00dd', '#00dddd',
+ '#dd6622', '#dd2266', '#66dd22',
+ '#8844dd', '#44dd88', '#4488dd']
+
+if len(sys.argv) < 5:
+ usage()
+
+filename = sys.argv[1]
+L1 = sys.argv[2]
+L2 = sys.argv[3]
+L3 = sys.argv[4]
+if len(sys.argv) > 5:
+ legendHeight = float(sys.argv[5])
+else:
+ legendHeight = 0.75
+
+# Load the JSON data from the file
+data = json.loads(file(filename).read())
+conf = data['conf']
+stats = data['stats']
+
+# Sanity check data hierarchy
+if len(conf['order_l1']) != len(stats.keys()):
+ error("conf.order_l1 does not match stats level 1")
+for l1 in stats.keys():
+ if len(conf['order_l2']) != len(stats[l1].keys()):
+ error("conf.order_l2 does not match stats level 2 for %s" % l1)
+ if conf['order_l1'].count(l1) < 1:
+ error("%s not found in conf.order_l1" % l1)
+ for l2 in stats[l1].keys():
+ if len(conf['order_l3']) != len(stats[l1][l2].keys()):
+ error("conf.order_l3 does not match stats level 3")
+ if conf['order_l2'].count(l2) < 1:
+ error("%s not found in conf.order_l2" % l2)
+ for l3 in stats[l1][l2].keys():
+ if conf['order_l3'].count(l3) < 1:
+ error("%s not found in conf.order_l3" % l3)
+
+#
+# Generate the data based on the level specifications
+#
+bar_labels = None
+group_labels = None
+bar_vals = []
+bar_sdvs = []
+if L3.startswith("select="):
+ select_label = l3 = L3.split("=")[1]
+ bar_labels = conf['order_l1']
+ group_labels = conf['order_l2']
+ bar_vals = [[0]*len(group_labels) for i in bar_labels]
+ bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
+ for b in range(len(bar_labels)):
+ l1 = bar_labels[b]
+ for g in range(len(group_labels)):
+ l2 = group_labels[g]
+ bar_vals[b][g] = np.mean(stats[l1][l2][l3])
+ bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
+elif L2.startswith("select="):
+ select_label = l2 = L2.split("=")[1]
+ bar_labels = conf['order_l1']
+ group_labels = conf['order_l3']
+ bar_vals = [[0]*len(group_labels) for i in bar_labels]
+ bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
+ for b in range(len(bar_labels)):
+ l1 = bar_labels[b]
+ for g in range(len(group_labels)):
+ l3 = group_labels[g]
+ bar_vals[b][g] = np.mean(stats[l1][l2][l3])
+ bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
+elif L1.startswith("select="):
+ select_label = l1 = L1.split("=")[1]
+ bar_labels = conf['order_l2']
+ group_labels = conf['order_l3']
+ bar_vals = [[0]*len(group_labels) for i in bar_labels]
+ bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
+ for b in range(len(bar_labels)):
+ l2 = bar_labels[b]
+ for g in range(len(group_labels)):
+ l3 = group_labels[g]
+ bar_vals[b][g] = np.mean(stats[l1][l2][l3])
+ bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
+else:
+ usage()
+
+# If group is before bar then flip (zip) the data
+if [L1, L2, L3].index("group") < [L1, L2, L3].index("bar"):
+ bar_labels, group_labels = group_labels, bar_labels
+ bar_vals = zip(*bar_vals)
+ bar_sdvs = zip(*bar_sdvs)
+
+print "bar_vals:", bar_vals
+
+#
+# Now render the bar graph
+#
+ind = np.arange(len(group_labels)) # the x locations for the groups
+width = 0.8 * (1.0/len(bar_labels)) # the width of the bars
+
+fig = plt.figure(figsize=(10,6), dpi=80)
+plot = fig.add_subplot(1, 1, 1)
+
+rects = []
+for i in range(len(bar_vals)):
+ rects.append(plot.bar(ind+width*i, bar_vals[i], width, color=colors[i],
+ yerr=bar_sdvs[i], align='center'))
+
+# add some
+plot.set_ylabel('Milliseconds (less is better)')
+plot.set_title("Javascript array test: %s" % select_label)
+plot.set_xticks(ind+width)
+plot.set_xticklabels( group_labels )
+
+fontP = FontProperties()
+fontP.set_size('small')
+plot.legend( [r[0] for r in rects], bar_labels, prop=fontP,
+ loc = 'center right', bbox_to_anchor = (1.0, legendHeight))
+
+def autolabel(rects):
+ # attach some text labels
+ for rect in rects:
+ height = rect.get_height()
+ if np.isnan(height):
+ height = 0.0
+ plot.text(rect.get_x()+rect.get_width()/2., height+20, '%d'%int(height),
+ ha='center', va='bottom', size='7')
+
+for rect in rects:
+ autolabel(rect)
+
+# Adjust axis sizes
+axis = list(plot.axis())
+axis[0] = -width # Make sure left side has enough for bar
+#axis[1] = axis[1] * 1.20 # Add 20% to the right to make sure it fits
+axis[2] = 0 # Make y-axis start at 0
+axis[3] = axis[3] * 1.10 # Add 10% to the top
+plot.axis(axis)
+
+plt.show()