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
22 from plotly.exceptions import PlotlyError
24 from utils import mean
27 def generate_plots(spec, data):
28 """Generate all plots specified in the specification file.
30 :param spec: Specification read from the specification file.
31 :param data: Data to process.
32 :type spec: Specification
36 logging.info("Generating the plots ...")
37 for index, plot in enumerate(spec.plots):
39 logging.info(" Plot nr {0}:".format(index + 1))
40 eval(plot["algorithm"])(plot, data)
42 logging.error("The algorithm '{0}' is not defined.".
43 format(plot["algorithm"]))
47 def plot_performance_box(plot, input_data):
48 """Generate the plot(s) with algorithm: table_detailed_test_results
49 specified in the specification file.
51 :param plot: Plot to generate.
52 :param input_data: Data to process.
53 :type plot: pandas.Series
54 :type input_data: InputData
57 logging.info(" Generating the plot {0} ...".
58 format(plot.get("title", "")))
61 data = input_data.filter_data(plot)
63 logging.error("No data.")
66 # Prepare the data for the plot
71 if y_vals.get(test["parent"], None) is None:
72 y_vals[test["parent"]] = list()
74 y_vals[test["parent"]].append(test["throughput"]["value"])
75 except (KeyError, TypeError):
76 y_vals[test["parent"]].append(None)
78 # Add None to the lists with missing data
80 for val in y_vals.values():
81 if len(val) > max_len:
83 for key, val in y_vals.items():
84 if len(val) < max_len:
85 val.extend([None for _ in range(max_len - len(val))])
89 df = pd.DataFrame(y_vals)
91 for i, col in enumerate(df.columns):
92 name = "{0}. {1}".format(i + 1, col.lower().replace('-ndrpdrdisc', ''))
93 traces.append(plgo.Box(x=[str(i + 1) + '.'] * len(df[col]),
100 plpl = plgo.Figure(data=traces, layout=plot["layout"])
103 logging.info(" Writing file '{0}{1}'.".
104 format(plot["output-file"], plot["output-file-type"]))
106 show_link=False, auto_open=False,
107 filename='{0}{1}'.format(plot["output-file"],
108 plot["output-file-type"]))
109 except PlotlyError as err:
110 logging.error(" Finished with error: {}".
111 format(str(err).replace("\n", " ")))
114 logging.info(" Done.")
117 def plot_latency_box(plot, input_data):
118 """Generate the plot(s) with algorithm: plot_latency_box
119 specified in the specification file.
121 :param plot: Plot to generate.
122 :param input_data: Data to process.
123 :type plot: pandas.Series
124 :type input_data: InputData
127 logging.info(" Generating the plot {0} ...".
128 format(plot.get("title", "")))
131 data = input_data.filter_data(plot)
133 logging.error("No data.")
136 # Prepare the data for the plot
141 if y_tmp_vals.get(test["parent"], None) is None:
142 y_tmp_vals[test["parent"]] = [
143 list(), # direction1, min
144 list(), # direction1, avg
145 list(), # direction1, max
146 list(), # direction2, min
147 list(), # direction2, avg
148 list() # direction2, max
151 y_tmp_vals[test["parent"]][0].append(
152 test["latency"]["direction1"]["50"]["min"])
153 y_tmp_vals[test["parent"]][1].append(
154 test["latency"]["direction1"]["50"]["avg"])
155 y_tmp_vals[test["parent"]][2].append(
156 test["latency"]["direction1"]["50"]["max"])
157 y_tmp_vals[test["parent"]][3].append(
158 test["latency"]["direction2"]["50"]["min"])
159 y_tmp_vals[test["parent"]][4].append(
160 test["latency"]["direction2"]["50"]["avg"])
161 y_tmp_vals[test["parent"]][5].append(
162 test["latency"]["direction2"]["50"]["max"])
163 except (KeyError, TypeError):
167 for key, values in y_tmp_vals.items():
174 y_vals[key].append(average)
175 y_vals[key].append(average) # Twice for plot.ly
180 df = pd.DataFrame(y_vals)
182 except ValueError as err:
183 logging.error(" Finished with error: {}".
184 format(str(err).replace("\n", " ")))
187 for i, col in enumerate(df.columns):
188 name = "{0}. {1}".format(i + 1, col.lower().replace('-ndrpdrdisc', ''))
189 traces.append(plgo.Box(x=['TGint1-to-SUT1-to-SUT2-to-TGint2',
190 '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 'TGint2-to-SUT2-to-SUT1-to-TGint1',
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'],
207 logging.info(" Writing file '{0}{1}'.".
208 format(plot["output-file"], plot["output-file-type"]))
209 plpl = plgo.Figure(data=traces, layout=plot["layout"])
213 show_link=False, auto_open=False,
214 filename='{0}{1}'.format(plot["output-file"],
215 plot["output-file-type"]))
216 except PlotlyError as err:
217 logging.error(" Finished with error: {}".
218 format(str(err).replace("\n", " ")))
221 logging.info(" Done.")
224 def plot_throughput_speedup_analysis(plot, input_data):
225 """Generate the plot(s) with algorithm: plot_throughput_speedup_analysis
226 specified in the specification file.
228 :param plot: Plot to generate.
229 :param input_data: Data to process.
230 :type plot: pandas.Series
231 :type input_data: InputData
234 logging.info(" Generating the plot {0} ...".
235 format(plot.get("title", "")))
238 data = input_data.filter_data(plot)
240 logging.error("No data.")
247 if throughput.get(test["parent"], None) is None:
248 throughput[test["parent"]] = {"1": list(),
252 if "1T1C" in test["tags"]:
253 throughput[test["parent"]]["1"].\
254 append(test["throughput"]["value"])
255 elif "2T2C" in test["tags"]:
256 throughput[test["parent"]]["2"]. \
257 append(test["throughput"]["value"])
258 elif "4T4C" in test["tags"]:
259 throughput[test["parent"]]["4"]. \
260 append(test["throughput"]["value"])
261 except (KeyError, TypeError):
265 logging.warning("No data for the plot '{}'".
266 format(plot.get("title", "")))
269 for test_name, test_vals in throughput.items():
270 for key, test_val in test_vals.items():
272 throughput[test_name][key] = sum(test_val) / len(test_val)
274 names = ['1 core', '2 cores', '4 cores']
280 for test_name, test_vals in throughput.items():
282 x_vals.append("-".join(test_name.split('-')[1:-1]))
286 round(float(test_vals["2"]) / float(test_vals["1"]), 2))
288 y_vals_2.append(None)
291 round(float(test_vals["4"]) / float(test_vals["1"]), 2))
293 y_vals_4.append(None)
295 y_vals = [y_vals_1, y_vals_2, y_vals_4]
297 y_vals_zipped = zip(names, y_vals)
299 for val in y_vals_zipped:
300 traces.append(plgo.Bar(x=x_vals,
306 logging.info(" Writing file '{0}{1}'.".
307 format(plot["output-file"], plot["output-file-type"]))
308 plpl = plgo.Figure(data=traces, layout=plot["layout"])
312 show_link=False, auto_open=False,
313 filename='{0}{1}'.format(plot["output-file"],
314 plot["output-file-type"]))
315 except PlotlyError as err:
316 logging.error(" Finished with error: {}".
317 format(str(err).replace("\n", " ")))
320 logging.info(" Done.")