]> git.proxmox.com Git - mirror_novnc.git/blame - utils/json2graph.py
Change noVNC license to from LGPLv3 to MPL 2.0
[mirror_novnc.git] / utils / json2graph.py
CommitLineData
d3da7c4c 1#!/usr/bin/env python
1506a5ed
JM
2
3'''
4Use matplotlib to generate performance charts
5Copyright 2011 Joel Martin
1d728ace 6Licensed under MPL-2.0 (see docs/LICENSE.MPL-2.0)
1506a5ed
JM
7'''
8
d3da7c4c
JM
9# a bar plot with errorbars
10import sys, json, pprint
11import numpy as np
12import matplotlib.pyplot as plt
13from matplotlib.font_manager import FontProperties
14
15def usage():
303819ea 16 print "%s json_file level1 level2 level3 [legend_height]\n\n" % sys.argv[0]
d3da7c4c
JM
17 print "Description:\n"
18 print "level1, level2, and level3 are one each of the following:\n";
19 print " select=ITEM - select only ITEM at this level";
20 print " bar - each item on this level becomes a graph bar";
21 print " group - items on this level become groups of bars";
22 print "\n";
23 print "json_file is a file containing json data in the following format:\n"
24 print ' {';
25 print ' "conf": {';
26 print ' "order_l1": [';
27 print ' "level1_label1",';
28 print ' "level1_label2",';
29 print ' ...';
30 print ' ],';
31 print ' "order_l2": [';
32 print ' "level2_label1",';
33 print ' "level2_label2",';
34 print ' ...';
35 print ' ],';
36 print ' "order_l3": [';
37 print ' "level3_label1",';
38 print ' "level3_label2",';
39 print ' ...';
40 print ' ]';
41 print ' },';
42 print ' "stats": {';
43 print ' "level1_label1": {';
44 print ' "level2_label1": {';
45 print ' "level3_label1": [val1, val2, val3],';
46 print ' "level3_label2": [val1, val2, val3],';
47 print ' ...';
48 print ' },';
49 print ' "level2_label2": {';
50 print ' ...';
51 print ' },';
52 print ' },';
53 print ' "level1_label2": {';
54 print ' ...';
55 print ' },';
56 print ' ...';
57 print ' },';
58 print ' }';
59 sys.exit(2)
60
61def error(msg):
62 print msg
63 sys.exit(1)
64
65
66#colors = ['#ff0000', '#0863e9', '#00f200', '#ffa100',
67# '#800000', '#805100', '#013075', '#007900']
68colors = ['#ff0000', '#00ff00', '#0000ff',
69 '#dddd00', '#dd00dd', '#00dddd',
70 '#dd6622', '#dd2266', '#66dd22',
71 '#8844dd', '#44dd88', '#4488dd']
72
73if len(sys.argv) < 5:
74 usage()
75
76filename = sys.argv[1]
77L1 = sys.argv[2]
78L2 = sys.argv[3]
79L3 = sys.argv[4]
80if len(sys.argv) > 5:
81 legendHeight = float(sys.argv[5])
82else:
83 legendHeight = 0.75
84
85# Load the JSON data from the file
86data = json.loads(file(filename).read())
87conf = data['conf']
88stats = data['stats']
89
90# Sanity check data hierarchy
91if len(conf['order_l1']) != len(stats.keys()):
92 error("conf.order_l1 does not match stats level 1")
93for l1 in stats.keys():
94 if len(conf['order_l2']) != len(stats[l1].keys()):
95 error("conf.order_l2 does not match stats level 2 for %s" % l1)
96 if conf['order_l1'].count(l1) < 1:
97 error("%s not found in conf.order_l1" % l1)
98 for l2 in stats[l1].keys():
99 if len(conf['order_l3']) != len(stats[l1][l2].keys()):
100 error("conf.order_l3 does not match stats level 3")
101 if conf['order_l2'].count(l2) < 1:
102 error("%s not found in conf.order_l2" % l2)
103 for l3 in stats[l1][l2].keys():
104 if conf['order_l3'].count(l3) < 1:
105 error("%s not found in conf.order_l3" % l3)
106
107#
108# Generate the data based on the level specifications
109#
110bar_labels = None
111group_labels = None
112bar_vals = []
113bar_sdvs = []
114if L3.startswith("select="):
115 select_label = l3 = L3.split("=")[1]
116 bar_labels = conf['order_l1']
117 group_labels = conf['order_l2']
118 bar_vals = [[0]*len(group_labels) for i in bar_labels]
119 bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
120 for b in range(len(bar_labels)):
121 l1 = bar_labels[b]
122 for g in range(len(group_labels)):
123 l2 = group_labels[g]
124 bar_vals[b][g] = np.mean(stats[l1][l2][l3])
125 bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
126elif L2.startswith("select="):
127 select_label = l2 = L2.split("=")[1]
128 bar_labels = conf['order_l1']
129 group_labels = conf['order_l3']
130 bar_vals = [[0]*len(group_labels) for i in bar_labels]
131 bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
132 for b in range(len(bar_labels)):
133 l1 = bar_labels[b]
134 for g in range(len(group_labels)):
135 l3 = group_labels[g]
136 bar_vals[b][g] = np.mean(stats[l1][l2][l3])
137 bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
138elif L1.startswith("select="):
139 select_label = l1 = L1.split("=")[1]
140 bar_labels = conf['order_l2']
141 group_labels = conf['order_l3']
142 bar_vals = [[0]*len(group_labels) for i in bar_labels]
143 bar_sdvs = [[0]*len(group_labels) for i in bar_labels]
144 for b in range(len(bar_labels)):
145 l2 = bar_labels[b]
146 for g in range(len(group_labels)):
147 l3 = group_labels[g]
148 bar_vals[b][g] = np.mean(stats[l1][l2][l3])
149 bar_sdvs[b][g] = np.std(stats[l1][l2][l3])
150else:
151 usage()
152
153# If group is before bar then flip (zip) the data
154if [L1, L2, L3].index("group") < [L1, L2, L3].index("bar"):
155 bar_labels, group_labels = group_labels, bar_labels
156 bar_vals = zip(*bar_vals)
157 bar_sdvs = zip(*bar_sdvs)
158
159print "bar_vals:", bar_vals
160
161#
162# Now render the bar graph
163#
164ind = np.arange(len(group_labels)) # the x locations for the groups
165width = 0.8 * (1.0/len(bar_labels)) # the width of the bars
166
167fig = plt.figure(figsize=(10,6), dpi=80)
168plot = fig.add_subplot(1, 1, 1)
169
170rects = []
171for i in range(len(bar_vals)):
172 rects.append(plot.bar(ind+width*i, bar_vals[i], width, color=colors[i],
173 yerr=bar_sdvs[i], align='center'))
174
175# add some
176plot.set_ylabel('Milliseconds (less is better)')
177plot.set_title("Javascript array test: %s" % select_label)
178plot.set_xticks(ind+width)
179plot.set_xticklabels( group_labels )
180
181fontP = FontProperties()
182fontP.set_size('small')
183plot.legend( [r[0] for r in rects], bar_labels, prop=fontP,
184 loc = 'center right', bbox_to_anchor = (1.0, legendHeight))
185
186def autolabel(rects):
187 # attach some text labels
188 for rect in rects:
189 height = rect.get_height()
190 if np.isnan(height):
191 height = 0.0
192 plot.text(rect.get_x()+rect.get_width()/2., height+20, '%d'%int(height),
193 ha='center', va='bottom', size='7')
194
195for rect in rects:
196 autolabel(rect)
197
198# Adjust axis sizes
199axis = list(plot.axis())
200axis[0] = -width # Make sure left side has enough for bar
201#axis[1] = axis[1] * 1.20 # Add 20% to the right to make sure it fits
202axis[2] = 0 # Make y-axis start at 0
203axis[3] = axis[3] * 1.10 # Add 10% to the top
204plot.axis(axis)
205
206plt.show()