1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Algorithms to generate plots.
20 import plotly.offline as ploff
21 import plotly.graph_objs as plgo
23 from plotly.exceptions import PlotlyError
25 from utils import mean
28 def generate_plots(spec, data):
29 """Generate all plots specified in the specification file.
31 :param spec: Specification read from the specification file.
32 :param data: Data to process.
33 :type spec: Specification
37 logging.info("Generating the plots ...")
38 for index, plot in enumerate(spec.plots):
40 logging.info(" Plot nr {0}:".format(index + 1))
41 eval(plot["algorithm"])(plot, data)
43 logging.error("The algorithm '{0}' is not defined.".
44 format(plot["algorithm"]))
48 def plot_performance_box(plot, input_data):
49 """Generate the plot(s) with algorithm: plot_performance_box
50 specified in the specification file.
52 :param plot: Plot to generate.
53 :param input_data: Data to process.
54 :type plot: pandas.Series
55 :type input_data: InputData
58 logging.info(" Generating the plot {0} ...".
59 format(plot.get("title", "")))
62 data = input_data.filter_data(plot)
64 logging.error("No data.")
67 # Prepare the data for the plot
72 if y_vals.get(test["parent"], None) is None:
73 y_vals[test["parent"]] = list()
75 y_vals[test["parent"]].append(test["throughput"]["value"])
76 except (KeyError, TypeError):
77 y_vals[test["parent"]].append(None)
79 # Add None to the lists with missing data
81 for val in y_vals.values():
82 if len(val) > max_len:
84 for key, val in y_vals.items():
85 if len(val) < max_len:
86 val.extend([None for _ in range(max_len - len(val))])
90 df = pd.DataFrame(y_vals)
92 for i, col in enumerate(df.columns):
93 name = "{0}. {1}".format(i + 1, col.lower().replace('-ndrpdrdisc', ''))
94 traces.append(plgo.Box(x=[str(i + 1) + '.'] * len(df[col]),
101 plpl = plgo.Figure(data=traces, layout=plot["layout"])
104 logging.info(" Writing file '{0}{1}'.".
105 format(plot["output-file"], plot["output-file-type"]))
107 show_link=False, auto_open=False,
108 filename='{0}{1}'.format(plot["output-file"],
109 plot["output-file-type"]))
110 except PlotlyError as err:
111 logging.error(" Finished with error: {}".
112 format(str(err).replace("\n", " ")))
115 logging.info(" Done.")
118 def plot_latency_box(plot, input_data):
119 """Generate the plot(s) with algorithm: plot_latency_box
120 specified in the specification file.
122 :param plot: Plot to generate.
123 :param input_data: Data to process.
124 :type plot: pandas.Series
125 :type input_data: InputData
128 logging.info(" Generating the plot {0} ...".
129 format(plot.get("title", "")))
132 data = input_data.filter_data(plot)
134 logging.error("No data.")
137 # Prepare the data for the plot
142 if y_tmp_vals.get(test["parent"], None) is None:
143 y_tmp_vals[test["parent"]] = [
144 list(), # direction1, min
145 list(), # direction1, avg
146 list(), # direction1, max
147 list(), # direction2, min
148 list(), # direction2, avg
149 list() # direction2, max
152 y_tmp_vals[test["parent"]][0].append(
153 test["latency"]["direction1"]["50"]["min"])
154 y_tmp_vals[test["parent"]][1].append(
155 test["latency"]["direction1"]["50"]["avg"])
156 y_tmp_vals[test["parent"]][2].append(
157 test["latency"]["direction1"]["50"]["max"])
158 y_tmp_vals[test["parent"]][3].append(
159 test["latency"]["direction2"]["50"]["min"])
160 y_tmp_vals[test["parent"]][4].append(
161 test["latency"]["direction2"]["50"]["avg"])
162 y_tmp_vals[test["parent"]][5].append(
163 test["latency"]["direction2"]["50"]["max"])
164 except (KeyError, TypeError):
168 for key, values in y_tmp_vals.items():
175 y_vals[key].append(average)
176 y_vals[key].append(average) # Twice for plot.ly
181 df = pd.DataFrame(y_vals)
183 except ValueError as err:
184 logging.error(" Finished with error: {}".
185 format(str(err).replace("\n", " ")))
188 for i, col in enumerate(df.columns):
189 name = "{0}. {1}".format(i + 1, col.lower().replace('-ndrpdrdisc', ''))
190 traces.append(plgo.Box(x=['TGint1-to-SUT1-to-SUT2-to-TGint2',
191 'TGint1-to-SUT1-to-SUT2-to-TGint2',
192 'TGint1-to-SUT1-to-SUT2-to-TGint2',
193 'TGint1-to-SUT1-to-SUT2-to-TGint2',
194 'TGint1-to-SUT1-to-SUT2-to-TGint2',
195 'TGint1-to-SUT1-to-SUT2-to-TGint2',
196 'TGint2-to-SUT2-to-SUT1-to-TGint1',
197 'TGint2-to-SUT2-to-SUT1-to-TGint1',
198 'TGint2-to-SUT2-to-SUT1-to-TGint1',
199 'TGint2-to-SUT2-to-SUT1-to-TGint1',
200 'TGint2-to-SUT2-to-SUT1-to-TGint1',
201 'TGint2-to-SUT2-to-SUT1-to-TGint1'],
208 logging.info(" Writing file '{0}{1}'.".
209 format(plot["output-file"], plot["output-file-type"]))
210 plpl = plgo.Figure(data=traces, layout=plot["layout"])
214 show_link=False, auto_open=False,
215 filename='{0}{1}'.format(plot["output-file"],
216 plot["output-file-type"]))
217 except PlotlyError as err:
218 logging.error(" Finished with error: {}".
219 format(str(err).replace("\n", " ")))
222 logging.info(" Done.")
225 def plot_throughput_speedup_analysis(plot, input_data):
226 """Generate the plot(s) with algorithm: plot_throughput_speedup_analysis
227 specified in the specification file.
229 :param plot: Plot to generate.
230 :param input_data: Data to process.
231 :type plot: pandas.Series
232 :type input_data: InputData
235 logging.info(" Generating the plot {0} ...".
236 format(plot.get("title", "")))
239 data = input_data.filter_data(plot)
241 logging.error("No data.")
248 if throughput.get(test["parent"], None) is None:
249 throughput[test["parent"]] = {"1": list(),
253 if "1T1C" in test["tags"]:
254 throughput[test["parent"]]["1"].\
255 append(test["throughput"]["value"])
256 elif "2T2C" in test["tags"]:
257 throughput[test["parent"]]["2"]. \
258 append(test["throughput"]["value"])
259 elif "4T4C" in test["tags"]:
260 throughput[test["parent"]]["4"]. \
261 append(test["throughput"]["value"])
262 except (KeyError, TypeError):
266 logging.warning("No data for the plot '{}'".
267 format(plot.get("title", "")))
270 for test_name, test_vals in throughput.items():
271 for key, test_val in test_vals.items():
273 throughput[test_name][key] = sum(test_val) / len(test_val)
275 names = ['1 core', '2 cores', '4 cores']
281 for test_name, test_vals in throughput.items():
283 x_vals.append("-".join(test_name.split('-')[1:-1]))
287 round(float(test_vals["2"]) / float(test_vals["1"]), 2))
289 y_vals_2.append(None)
292 round(float(test_vals["4"]) / float(test_vals["1"]), 2))
294 y_vals_4.append(None)
296 y_vals = [y_vals_1, y_vals_2, y_vals_4]
298 y_vals_zipped = zip(names, y_vals)
300 for val in y_vals_zipped:
301 traces.append(plgo.Bar(x=x_vals,
307 logging.info(" Writing file '{0}{1}'.".
308 format(plot["output-file"], plot["output-file-type"]))
309 plpl = plgo.Figure(data=traces, layout=plot["layout"])
313 show_link=False, auto_open=False,
314 filename='{0}{1}'.format(plot["output-file"],
315 plot["output-file-type"]))
316 except PlotlyError as err:
317 logging.error(" Finished with error: {}".
318 format(str(err).replace("\n", " ")))
321 logging.info(" Done.")
324 def plot_http_server_performance_box(plot, input_data):
325 """Generate the plot(s) with algorithm: plot_http_server_performance_box
326 specified in the specification file.
328 :param plot: Plot to generate.
329 :param input_data: Data to process.
330 :type plot: pandas.Series
331 :type input_data: InputData
334 logging.info(" Generating the plot {0} ...".
335 format(plot.get("title", "")))
338 data = input_data.filter_data(plot)
340 logging.error("No data.")
343 # Prepare the data for the plot
348 if y_vals.get(test["name"], None) is None:
349 y_vals[test["name"]] = list()
351 y_vals[test["name"]].append(test["result"]["value"])
352 except (KeyError, TypeError):
353 y_vals[test["name"]].append(None)
355 # Add None to the lists with missing data
357 for val in y_vals.values():
358 if len(val) > max_len:
360 for key, val in y_vals.items():
361 if len(val) < max_len:
362 val.extend([None for _ in range(max_len - len(val))])
366 df = pd.DataFrame(y_vals)
368 for i, col in enumerate(df.columns):
369 name = "{0}. {1}".format(i + 1, col.lower().replace('-cps', '').
371 traces.append(plgo.Box(x=[str(i + 1) + '.'] * len(df[col]),
377 plpl = plgo.Figure(data=traces, layout=plot["layout"])
380 logging.info(" Writing file '{0}{1}'.".
381 format(plot["output-file"], plot["output-file-type"]))
383 show_link=False, auto_open=False,
384 filename='{0}{1}'.format(plot["output-file"],
385 plot["output-file-type"]))
386 except PlotlyError as err:
387 logging.error(" Finished with error: {}".
388 format(str(err).replace("\n", " ")))
391 logging.info(" Done.")