From 808797d2d913eac7581a4e4cba3fb826ddbff775 Mon Sep 17 00:00:00 2001 From: Tibor Frank Date: Wed, 3 Aug 2022 15:00:51 +0200 Subject: UTI: Add Download for iterative data. Change-Id: I79bcfc2449310d4d186146ce79b2143a33ed2d1f Signed-off-by: Tibor Frank --- resources/tools/dash/app/pal/report/graphs.py | 122 +++++++++++++++++--------- resources/tools/dash/app/pal/report/layout.py | 38 +++++++- 2 files changed, 117 insertions(+), 43 deletions(-) (limited to 'resources/tools/dash/app/pal/report') diff --git a/resources/tools/dash/app/pal/report/graphs.py b/resources/tools/dash/app/pal/report/graphs.py index 4cd9287f0f..36f28d09e8 100644 --- a/resources/tools/dash/app/pal/report/graphs.py +++ b/resources/tools/dash/app/pal/report/graphs.py @@ -25,7 +25,14 @@ from ..utils.utils import get_color def get_short_version(version: str, dut_type: str="vpp") -> str: - """ + """Returns the short version of DUT without build number. + + :param version: Original version string. + :param dut_type: DUT type. + :type version: str + :type dut_type: str + :returns: Short verion string. + :rtype: str """ if dut_type in ("trex", "dpdk"): @@ -48,7 +55,15 @@ def get_short_version(version: str, dut_type: str="vpp") -> str: def select_iterative_data(data: pd.DataFrame, itm:dict) -> pd.DataFrame: - """ + """Select the data for graphs and tables from the provided data frame. + + :param data: Data frame with data for graphs and tables. + :param itm: Item (in this case job name) which data will be selected from + the input data frame. + :type data: pandas.DataFrame + :type itm: str + :returns: A data frame with selected data. + :rtype: pandas.DataFrame """ phy = itm["phy"].split("-") @@ -96,7 +111,20 @@ def select_iterative_data(data: pd.DataFrame, itm:dict) -> pd.DataFrame: def graph_iterative(data: pd.DataFrame, sel:dict, layout: dict, normalize: bool) -> tuple: - """ + """Generate the statistical box graph with iterative data (MRR, NDR and PDR, + for PDR also Latencies). + + :param data: Data frame with iterative data. + :param sel: Selected tests. + :param layout: Layout of plot.ly graph. + :param normalize: If True, the data is normalized to CPU frquency + Constants.NORM_FREQUENCY. + :param data: pandas.DataFrame + :param sel: dict + :param layout: dict + :param normalize: bool + :returns: Tuple of graphs - throughput and latency. + :rtype: tuple(plotly.graph_objects.Figure, plotly.graph_objects.Figure) """ fig_tput = None @@ -192,46 +220,56 @@ def graph_iterative(data: pd.DataFrame, sel:dict, layout: dict, def table_comparison(data: pd.DataFrame, sel:dict, normalize: bool) -> pd.DataFrame: - """ + """Generate the comparison table with selected tests. + + :param data: Data frame with iterative data. + :param sel: Selected tests. + :param normalize: If True, the data is normalized to CPU frquency + Constants.NORM_FREQUENCY. + :param data: pandas.DataFrame + :param sel: dict + :param normalize: bool + :returns: Comparison table. + :rtype: pandas.DataFrame """ table = pd.DataFrame( - { - "Test Case": [ - "64b-2t1c-avf-eth-l2xcbase-eth-2memif-1dcr", - "64b-2t1c-avf-eth-l2xcbase-eth-2vhostvr1024-1vm-vppl2xc", - "64b-2t1c-avf-ethip4udp-ip4base-iacl50sl-10kflows", - "78b-2t1c-avf-ethip6-ip6scale2m-rnd "], - "2106.0-8": [ - "14.45 +- 0.08", - "9.63 +- 0.05", - "9.7 +- 0.02", - "8.95 +- 0.06"], - "2110.0-8": [ - "14.45 +- 0.08", - "9.63 +- 0.05", - "9.7 +- 0.02", - "8.95 +- 0.06"], - "2110.0-9": [ - "14.45 +- 0.08", - "9.63 +- 0.05", - "9.7 +- 0.02", - "8.95 +- 0.06"], - "2202.0-9": [ - "14.45 +- 0.08", - "9.63 +- 0.05", - "9.7 +- 0.02", - "8.95 +- 0.06"], - "2110.0-9 vs 2110.0-8": [ - "-0.23 +- 0.62", - "-1.37 +- 1.3", - "+0.08 +- 0.2", - "-2.16 +- 0.83"], - "2202.0-9 vs 2110.0-9": [ - "+6.95 +- 0.72", - "+5.35 +- 1.26", - "+4.48 +- 1.48", - "+4.09 +- 0.95"] - } + # { + # "Test Case": [ + # "64b-2t1c-avf-eth-l2xcbase-eth-2memif-1dcr", + # "64b-2t1c-avf-eth-l2xcbase-eth-2vhostvr1024-1vm-vppl2xc", + # "64b-2t1c-avf-ethip4udp-ip4base-iacl50sl-10kflows", + # "78b-2t1c-avf-ethip6-ip6scale2m-rnd "], + # "2106.0-8": [ + # "14.45 +- 0.08", + # "9.63 +- 0.05", + # "9.7 +- 0.02", + # "8.95 +- 0.06"], + # "2110.0-8": [ + # "14.45 +- 0.08", + # "9.63 +- 0.05", + # "9.7 +- 0.02", + # "8.95 +- 0.06"], + # "2110.0-9": [ + # "14.45 +- 0.08", + # "9.63 +- 0.05", + # "9.7 +- 0.02", + # "8.95 +- 0.06"], + # "2202.0-9": [ + # "14.45 +- 0.08", + # "9.63 +- 0.05", + # "9.7 +- 0.02", + # "8.95 +- 0.06"], + # "2110.0-9 vs 2110.0-8": [ + # "-0.23 +- 0.62", + # "-1.37 +- 1.3", + # "+0.08 +- 0.2", + # "-2.16 +- 0.83"], + # "2202.0-9 vs 2110.0-9": [ + # "+6.95 +- 0.72", + # "+5.35 +- 1.26", + # "+4.48 +- 1.48", + # "+4.09 +- 0.95"] + # } ) - return pd.DataFrame() #table + return table diff --git a/resources/tools/dash/app/pal/report/layout.py b/resources/tools/dash/app/pal/report/layout.py index 0e8f32405c..978ab0de6c 100644 --- a/resources/tools/dash/app/pal/report/layout.py +++ b/resources/tools/dash/app/pal/report/layout.py @@ -23,6 +23,7 @@ from dash import dcc from dash import html from dash import callback_context, no_update, ALL from dash import Input, Output, State +from dash.exceptions import PreventUpdate from yaml import load, FullLoader, YAMLError from copy import deepcopy from ast import literal_eval @@ -32,7 +33,8 @@ from ..utils.utils import show_tooltip, label, sync_checklists, list_tests, \ gen_new_url from ..utils.url_processing import url_decode from ..data.data import Data -from .graphs import graph_iterative, table_comparison, get_short_version +from .graphs import graph_iterative, table_comparison, get_short_version, \ + select_iterative_data class Layout: @@ -1408,3 +1410,37 @@ class Layout: ] ret_val.extend(ctrl_panel.values()) return ret_val + + @app.callback( + Output("download-data", "data"), + State("selected-tests", "data"), + Input("btn-download-data", "n_clicks"), + prevent_initial_call=True + ) + def _download_data(store_sel, n_clicks): + """Download the data + + :param store_sel: List of tests selected by user stored in the + browser. + :param n_clicks: Number of clicks on the button "Download". + :type store_sel: list + :type n_clicks: int + :returns: dict of data frame content (base64 encoded) and meta data + used by the Download component. + :rtype: dict + """ + + if not n_clicks: + raise PreventUpdate + + if not store_sel: + raise PreventUpdate + + df = pd.DataFrame() + for itm in store_sel: + sel_data = select_iterative_data(self.data, itm) + if sel_data is None: + continue + df = pd.concat([df, sel_data], ignore_index=True) + + return dcc.send_data_frame(df.to_csv, C.REPORT_DOWNLOAD_FILE_NAME) -- cgit 1.2.3-korg