1 # Copyright (c) 2022 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 """Plotly Dash HTML layout override.
19 import dash_bootstrap_components as dbc
21 from flask import Flask
24 from dash import callback_context, no_update, ALL
25 from dash import Input, Output, State
26 from yaml import load, FullLoader, YAMLError
27 from copy import deepcopy
28 from ast import literal_eval
30 from ..data.data import Data
31 from ..data.url_processing import url_decode, url_encode
32 from .graphs import graph_iterative, table_comparison, get_short_version
39 # If True, clear all inputs in control panel when button "ADD SELECTED" is
41 CLEAR_ALL_INPUTS = False
43 STYLE_DISABLED = {"display": "none"}
44 STYLE_ENABLED = {"display": "inherit"}
57 PLACEHOLDER = html.Nobr("")
59 DRIVERS = ("avf", "af-xdp", "rdma", "dpdk")
63 "container_memif": "LXC/DRC Container Memif",
64 "crypto": "IPSec IPv4 Routing",
65 "ip4": "IPv4 Routing",
66 "ip6": "IPv6 Routing",
67 "ip4_tunnels": "IPv4 Tunnels",
68 "l2": "L2 Ethernet Switching",
69 "srv6": "SRv6 Routing",
70 "vm_vhost": "VMs vhost-user",
71 "nfv_density-dcr_memif-chain_ipsec": "CNF Service Chains Routing IPSec",
72 "nfv_density-vm_vhost-chain_dot1qip4vxlan":"VNF Service Chains Tunnels",
73 "nfv_density-vm_vhost-chain": "VNF Service Chains Routing",
74 "nfv_density-dcr_memif-pipeline": "CNF Service Pipelines Routing",
75 "nfv_density-dcr_memif-chain": "CNF Service Chains Routing",
79 "background-color": "#d2ebf5",
80 "border-color": "#bce1f1",
84 def __init__(self, app: Flask, releases: list, html_layout_file: str,
85 graph_layout_file: str, data_spec_file: str, tooltip_file: str) -> None:
91 self.releases = releases
92 self._html_layout_file = html_layout_file
93 self._graph_layout_file = graph_layout_file
94 self._data_spec_file = data_spec_file
95 self._tooltip_file = tooltip_file
98 self._data = pd.DataFrame()
100 data_mrr = Data(self._data_spec_file, True).\
101 read_iterative_mrr(release=rls.replace("csit", "rls"))
102 data_mrr["release"] = rls
103 data_ndrpdr = Data(self._data_spec_file, True).\
104 read_iterative_ndrpdr(release=rls.replace("csit", "rls"))
105 data_ndrpdr["release"] = rls
106 self._data = pd.concat(
107 [self._data, data_mrr, data_ndrpdr], ignore_index=True)
109 # Get structure of tests:
111 cols = ["job", "test_id", "test_type", "dut_version", "release"]
112 for _, row in self._data[cols].drop_duplicates().iterrows():
114 ttype = row["test_type"]
115 lst_job = row["job"].split("-")
117 d_ver = get_short_version(row["dut_version"], dut)
118 tbed = "-".join(lst_job[-2:])
119 lst_test_id = row["test_id"].split(".")
123 area = "-".join(lst_test_id[3:-2])
124 suite = lst_test_id[-2].replace("2n1l-", "").replace("1n1l-", "").\
126 test = lst_test_id[-1]
127 nic = suite.split("-")[0]
128 for drv in self.DRIVERS:
130 driver = drv.replace("-", "_")
131 test = test.replace(f"{drv}-", "")
135 infra = "-".join((tbed, nic, driver))
136 lst_test = test.split("-")
137 framesize = lst_test[0]
138 core = lst_test[1] if lst_test[1] else "8C"
139 test = "-".join(lst_test[2: -1])
141 if tbs.get(rls, None) is None:
143 if tbs[rls].get(dut, None) is None:
144 tbs[rls][dut] = dict()
145 if tbs[rls][dut].get(d_ver, None) is None:
146 tbs[rls][dut][d_ver] = dict()
147 if tbs[rls][dut][d_ver].get(infra, None) is None:
148 tbs[rls][dut][d_ver][infra] = dict()
149 if tbs[rls][dut][d_ver][infra].get(area, None) is None:
150 tbs[rls][dut][d_ver][infra][area] = dict()
151 if tbs[rls][dut][d_ver][infra][area].get(test, None) is None:
152 tbs[rls][dut][d_ver][infra][area][test] = dict()
153 tbs[rls][dut][d_ver][infra][area][test]["core"] = list()
154 tbs[rls][dut][d_ver][infra][area][test]["frame-size"] = list()
155 tbs[rls][dut][d_ver][infra][area][test]["test-type"] = list()
156 if core.upper() not in \
157 tbs[rls][dut][d_ver][infra][area][test]["core"]:
158 tbs[rls][dut][d_ver][infra][area][test]["core"].append(
160 if framesize.upper() not in \
161 tbs[rls][dut][d_ver][infra][area][test]["frame-size"]:
162 tbs[rls][dut][d_ver][infra][area][test]["frame-size"].append(
166 tbs[rls][dut][d_ver][infra][area][test]["test-type"]:
167 tbs[rls][dut][d_ver][infra][area][test]["test-type"].append(
169 elif ttype == "ndrpdr":
171 tbs[rls][dut][d_ver][infra][area][test]["test-type"]:
172 tbs[rls][dut][d_ver][infra][area][test]["test-type"].extend(
177 self._html_layout = ""
178 self._graph_layout = None
179 self._tooltips = dict()
182 with open(self._html_layout_file, "r") as file_read:
183 self._html_layout = file_read.read()
184 except IOError as err:
186 f"Not possible to open the file {self._html_layout_file}\n{err}"
190 with open(self._graph_layout_file, "r") as file_read:
191 self._graph_layout = load(file_read, Loader=FullLoader)
192 except IOError as err:
194 f"Not possible to open the file {self._graph_layout_file}\n"
197 except YAMLError as err:
199 f"An error occurred while parsing the specification file "
200 f"{self._graph_layout_file}\n{err}"
204 with open(self._tooltip_file, "r") as file_read:
205 self._tooltips = load(file_read, Loader=FullLoader)
206 except IOError as err:
208 f"Not possible to open the file {self._tooltip_file}\n{err}"
210 except YAMLError as err:
212 f"An error occurred while parsing the specification file "
213 f"{self._tooltip_file}\n{err}"
217 if self._app is not None and hasattr(self, 'callbacks'):
218 self.callbacks(self._app)
221 def html_layout(self):
222 return self._html_layout
226 return self._spec_tbs
234 return self._graph_layout
236 def label(self, key: str) -> str:
237 return self.LABELS.get(key, key)
239 def _show_tooltip(self, id: str, title: str,
240 clipboard_id: str=None) -> list:
244 dcc.Clipboard(target_id=clipboard_id, title="Copy URL") \
245 if clipboard_id else str(),
253 class_name="border ms-1",
256 children=self._tooltips.get(id, str()),
262 def add_content(self):
265 if self.html_layout and self.spec_tbs:
279 id="offcanvas-metadata",
280 title="Throughput And Latency",
284 dbc.Row(id="metadata-tput-lat"),
285 dbc.Row(id="metadata-hdrh-graph"),
293 dcc.Store(id="selected-tests"),
294 dcc.Store(id="control-panel"),
295 dcc.Location(id="url", refresh=False),
296 self._add_ctrl_col(),
297 self._add_plotting_col(),
315 def _add_navbar(self):
316 """Add nav element with navigation panel. It is placed on the top.
318 return dbc.NavbarSimple(
319 id="navbarsimple-main",
323 "Iterative Test Runs",
332 brand_external_link=True,
337 def _add_ctrl_col(self) -> dbc.Col:
338 """Add column with controls. It is placed on the left side.
343 self._add_ctrl_panel(),
347 def _add_plotting_col(self) -> dbc.Col:
348 """Add column with plots and tables. It is placed on the right side.
351 id="col-plotting-area",
356 class_name="g-0 p-2",
359 dbc.Row( # Throughput
361 class_name="g-0 p-2",
371 class_name="g-0 p-2",
382 class_name="g-0 p-2",
388 id="row-btn-download",
389 class_name="g-0 p-2",
400 def _add_ctrl_panel(self) -> dbc.Row:
405 class_name="g-0 p-2",
413 children=self._show_tooltip(
414 "help-release", "CSIT Release")
418 placeholder=("Select a Release..."),
421 {"label": k, "value": k} \
422 for k in self.spec_tbs.keys()
424 key=lambda d: d["label"]
439 children=self._show_tooltip(
445 "Select a Device under Test..."
460 children=self._show_tooltip(
461 "help-dut-ver", "DUT Version")
466 "Select a Version of "
467 "Device under Test..."
482 children=self._show_tooltip(
483 "help-infra", "Infra")
488 "Select a Physical Test Bed "
504 children=self._show_tooltip(
509 placeholder="Select an Area...",
524 children=self._show_tooltip(
529 placeholder="Select a Test...",
539 id="row-ctrl-framesize",
543 children=self._show_tooltip(
544 "help-framesize", "Frame Size"),
550 id="cl-ctrl-framesize-all",
551 options=self.CL_ALL_DISABLED,
561 id="cl-ctrl-framesize",
574 children=self._show_tooltip(
575 "help-cores", "Number of Cores"),
581 id="cl-ctrl-core-all",
582 options=self.CL_ALL_DISABLED,
601 id="row-ctrl-testtype",
605 children=self._show_tooltip(
606 "help-ttype", "Test Type"),
612 id="cl-ctrl-testtype-all",
613 options=self.CL_ALL_DISABLED,
623 id="cl-ctrl-testtype",
632 id="row-ctrl-normalize",
636 children=self._show_tooltip(
637 "help-normalize", "Normalize"),
643 id="cl-ctrl-normalize",
645 "value": "normalize",
647 "Normalize results to CPU"
660 class_name="gy-1 p-0",
666 children="Add Selected",
676 id="row-card-sel-tests",
678 style=self.STYLE_DISABLED,
685 class_name="overflow-auto",
689 style={"max-height": "20em"},
694 id="row-btns-sel-tests",
695 style=self.STYLE_DISABLED,
702 children="Remove Selected",
703 class_name="w-100 me-1",
708 id="btn-sel-remove-all",
709 children="Remove All",
710 class_name="w-100 me-1",
723 def __init__(self, panel: dict) -> None:
731 # Defines also the order of keys
733 "dd-rls-value": str(),
734 "dd-dut-options": list(),
735 "dd-dut-disabled": True,
736 "dd-dut-value": str(),
737 "dd-dutver-options": list(),
738 "dd-dutver-disabled": True,
739 "dd-dutver-value": str(),
740 "dd-phy-options": list(),
741 "dd-phy-disabled": True,
742 "dd-phy-value": str(),
743 "dd-area-options": list(),
744 "dd-area-disabled": True,
745 "dd-area-value": str(),
746 "dd-test-options": list(),
747 "dd-test-disabled": True,
748 "dd-test-value": str(),
749 "cl-core-options": list(),
750 "cl-core-value": list(),
751 "cl-core-all-value": list(),
752 "cl-core-all-options": CL_ALL_DISABLED,
753 "cl-framesize-options": list(),
754 "cl-framesize-value": list(),
755 "cl-framesize-all-value": list(),
756 "cl-framesize-all-options": CL_ALL_DISABLED,
757 "cl-testtype-options": list(),
758 "cl-testtype-value": list(),
759 "cl-testtype-all-value": list(),
760 "cl-testtype-all-options": CL_ALL_DISABLED,
761 "btn-add-disabled": True,
762 "cl-normalize-value": list(),
763 "cl-selected-options": list()
766 self._panel = deepcopy(self._defaults)
768 for key in self._defaults:
769 self._panel[key] = panel[key]
772 def defaults(self) -> dict:
773 return self._defaults
776 def panel(self) -> dict:
779 def set(self, kwargs: dict) -> None:
780 for key, val in kwargs.items():
781 if key in self._panel:
782 self._panel[key] = val
784 raise KeyError(f"The key {key} is not defined.")
786 def get(self, key: str) -> any:
787 return self._panel[key]
789 def values(self) -> tuple:
790 return tuple(self._panel.values())
793 def _sync_checklists(opt: list, sel: list, all: list, id: str) -> tuple:
796 options = {v["value"] for v in opt}
798 sel = list(options) if all else list()
800 all = ["all", ] if set(sel) == options else list()
804 def _list_tests(selection: dict) -> list:
805 """Display selected tests with checkboxes
808 return [{"label": v["id"], "value": v["id"]} for v in selection]
812 def callbacks(self, app):
814 def _generate_plotting_area(figs: tuple, table: pd.DataFrame,
819 (fig_tput, fig_lat) = figs
821 row_fig_tput = self.PLACEHOLDER
822 row_fig_lat = self.PLACEHOLDER
823 row_table = self.PLACEHOLDER
824 row_btn_dwnld = self.PLACEHOLDER
829 id={"type": "graph", "index": "tput"},
837 dcc.Loading(children=[
839 id="btn-download-data",
840 children=self._show_tooltip(
841 "help-download", "Download Data"),
845 dcc.Download(id="download-data")
856 style=self.URL_STYLE,
857 children=self._show_tooltip(
858 "help-url", "URL", "input-url")
864 style=self.URL_STYLE,
875 id={"type": "graph", "index": "lat"},
881 dbc.Table.from_dataframe(
883 id={"type": "table", "index": "compare"},
890 return row_fig_tput, row_fig_lat, row_table, row_btn_dwnld
893 Output("control-panel", "data"), # Store
894 Output("selected-tests", "data"), # Store
895 Output("row-graph-tput", "children"),
896 Output("row-graph-lat", "children"),
897 Output("row-table", "children"),
898 Output("row-btn-download", "children"),
899 Output("row-card-sel-tests", "style"),
900 Output("row-btns-sel-tests", "style"),
901 Output("dd-ctrl-rls", "value"),
902 Output("dd-ctrl-dut", "options"),
903 Output("dd-ctrl-dut", "disabled"),
904 Output("dd-ctrl-dut", "value"),
905 Output("dd-ctrl-dutver", "options"),
906 Output("dd-ctrl-dutver", "disabled"),
907 Output("dd-ctrl-dutver", "value"),
908 Output("dd-ctrl-phy", "options"),
909 Output("dd-ctrl-phy", "disabled"),
910 Output("dd-ctrl-phy", "value"),
911 Output("dd-ctrl-area", "options"),
912 Output("dd-ctrl-area", "disabled"),
913 Output("dd-ctrl-area", "value"),
914 Output("dd-ctrl-test", "options"),
915 Output("dd-ctrl-test", "disabled"),
916 Output("dd-ctrl-test", "value"),
917 Output("cl-ctrl-core", "options"),
918 Output("cl-ctrl-core", "value"),
919 Output("cl-ctrl-core-all", "value"),
920 Output("cl-ctrl-core-all", "options"),
921 Output("cl-ctrl-framesize", "options"),
922 Output("cl-ctrl-framesize", "value"),
923 Output("cl-ctrl-framesize-all", "value"),
924 Output("cl-ctrl-framesize-all", "options"),
925 Output("cl-ctrl-testtype", "options"),
926 Output("cl-ctrl-testtype", "value"),
927 Output("cl-ctrl-testtype-all", "value"),
928 Output("cl-ctrl-testtype-all", "options"),
929 Output("btn-ctrl-add", "disabled"),
930 Output("cl-ctrl-normalize", "value"),
931 Output("cl-selected", "options"), # User selection
932 State("control-panel", "data"), # Store
933 State("selected-tests", "data"), # Store
934 State("cl-selected", "value"), # User selection
935 Input("dd-ctrl-rls", "value"),
936 Input("dd-ctrl-dut", "value"),
937 Input("dd-ctrl-dutver", "value"),
938 Input("dd-ctrl-phy", "value"),
939 Input("dd-ctrl-area", "value"),
940 Input("dd-ctrl-test", "value"),
941 Input("cl-ctrl-core", "value"),
942 Input("cl-ctrl-core-all", "value"),
943 Input("cl-ctrl-framesize", "value"),
944 Input("cl-ctrl-framesize-all", "value"),
945 Input("cl-ctrl-testtype", "value"),
946 Input("cl-ctrl-testtype-all", "value"),
947 Input("cl-ctrl-normalize", "value"),
948 Input("btn-ctrl-add", "n_clicks"),
949 Input("btn-sel-remove", "n_clicks"),
950 Input("btn-sel-remove-all", "n_clicks"),
953 def _update_ctrl_panel(cp_data: dict, store_sel: list, list_sel: list,
954 dd_rls: str, dd_dut: str, dd_dutver: str, dd_phy: str, dd_area: str,
955 dd_test: str, cl_core: list, cl_core_all: list, cl_framesize: list,
956 cl_framesize_all: list, cl_testtype: list, cl_testtype_all: list,
957 cl_normalize: list, btn_add: int, btn_remove: int,
958 btn_remove_all: int, href: str) -> tuple:
962 def _gen_new_url(parsed_url: dict, store_sel: list) -> str:
965 new_url = url_encode({
966 "scheme": parsed_url["scheme"],
967 "netloc": parsed_url["netloc"],
968 "path": parsed_url["path"],
970 "store_sel": store_sel,
977 ctrl_panel = self.ControlPanel(cp_data)
980 parsed_url = url_decode(href)
982 row_fig_tput = no_update
983 row_fig_lat = no_update
984 row_table = no_update
985 row_btn_dwnld = no_update
986 row_card_sel_tests = no_update
987 row_btns_sel_tests = no_update
989 trigger_id = callback_context.triggered[0]["prop_id"].split(".")[0]
991 if trigger_id == "dd-ctrl-rls":
993 rls = self.spec_tbs[dd_rls]
995 [{"label": v, "value": v} for v in rls.keys()],
996 key=lambda d: d["label"]
1003 "dd-rls-value": dd_rls,
1004 "dd-dut-value": str(),
1005 "dd-dut-options": options,
1006 "dd-dut-disabled": disabled,
1007 "dd-dutver-value": str(),
1008 "dd-dutver-options": list(),
1009 "dd-dutver-disabled": True,
1010 "dd-phy-value": str(),
1011 "dd-phy-options": list(),
1012 "dd-phy-disabled": True,
1013 "dd-area-value": str(),
1014 "dd-area-options": list(),
1015 "dd-area-disabled": True,
1016 "dd-test-value": str(),
1017 "dd-test-options": list(),
1018 "dd-test-disabled": True,
1019 "cl-core-options": list(),
1020 "cl-core-value": list(),
1021 "cl-core-all-value": list(),
1022 "cl-core-all-options": self.CL_ALL_DISABLED,
1023 "cl-framesize-options": list(),
1024 "cl-framesize-value": list(),
1025 "cl-framesize-all-value": list(),
1026 "cl-framesize-all-options": self.CL_ALL_DISABLED,
1027 "cl-testtype-options": list(),
1028 "cl-testtype-value": list(),
1029 "cl-testtype-all-value": list(),
1030 "cl-testtype-all-options": self.CL_ALL_DISABLED
1032 elif trigger_id == "dd-ctrl-dut":
1034 rls = ctrl_panel.get("dd-rls-value")
1035 dut = self.spec_tbs[rls][dd_dut]
1037 [{"label": v, "value": v} for v in dut.keys()],
1038 key=lambda d: d["label"]
1045 "dd-dut-value": dd_dut,
1046 "dd-dutver-value": str(),
1047 "dd-dutver-options": options,
1048 "dd-dutver-disabled": disabled,
1049 "dd-phy-value": str(),
1050 "dd-phy-options": list(),
1051 "dd-phy-disabled": True,
1052 "dd-area-value": str(),
1053 "dd-area-options": list(),
1054 "dd-area-disabled": True,
1055 "dd-test-value": str(),
1056 "dd-test-options": list(),
1057 "dd-test-disabled": True,
1058 "cl-core-options": list(),
1059 "cl-core-value": list(),
1060 "cl-core-all-value": list(),
1061 "cl-core-all-options": self.CL_ALL_DISABLED,
1062 "cl-framesize-options": list(),
1063 "cl-framesize-value": list(),
1064 "cl-framesize-all-value": list(),
1065 "cl-framesize-all-options": self.CL_ALL_DISABLED,
1066 "cl-testtype-options": list(),
1067 "cl-testtype-value": list(),
1068 "cl-testtype-all-value": list(),
1069 "cl-testtype-all-options": self.CL_ALL_DISABLED
1071 elif trigger_id == "dd-ctrl-dutver":
1073 rls = ctrl_panel.get("dd-rls-value")
1074 dut = ctrl_panel.get("dd-dut-value")
1075 dutver = self.spec_tbs[rls][dut][dd_dutver]
1077 [{"label": v, "value": v} for v in dutver.keys()],
1078 key=lambda d: d["label"]
1085 "dd-dutver-value": dd_dutver,
1086 "dd-phy-value": str(),
1087 "dd-phy-options": options,
1088 "dd-phy-disabled": disabled,
1089 "dd-area-value": str(),
1090 "dd-area-options": list(),
1091 "dd-area-disabled": True,
1092 "dd-test-value": str(),
1093 "dd-test-options": list(),
1094 "dd-test-disabled": True,
1095 "cl-core-options": list(),
1096 "cl-core-value": list(),
1097 "cl-core-all-value": list(),
1098 "cl-core-all-options": self.CL_ALL_DISABLED,
1099 "cl-framesize-options": list(),
1100 "cl-framesize-value": list(),
1101 "cl-framesize-all-value": list(),
1102 "cl-framesize-all-options": self.CL_ALL_DISABLED,
1103 "cl-testtype-options": list(),
1104 "cl-testtype-value": list(),
1105 "cl-testtype-all-value": list(),
1106 "cl-testtype-all-options": self.CL_ALL_DISABLED
1108 elif trigger_id == "dd-ctrl-phy":
1110 rls = ctrl_panel.get("dd-rls-value")
1111 dut = ctrl_panel.get("dd-dut-value")
1112 dutver = ctrl_panel.get("dd-dutver-value")
1113 phy = self.spec_tbs[rls][dut][dutver][dd_phy]
1115 [{"label": self.label(v), "value": v}
1116 for v in phy.keys()],
1117 key=lambda d: d["label"]
1124 "dd-phy-value": dd_phy,
1125 "dd-area-value": str(),
1126 "dd-area-options": options,
1127 "dd-area-disabled": disabled,
1128 "dd-test-value": str(),
1129 "dd-test-options": list(),
1130 "dd-test-disabled": True,
1131 "cl-core-options": list(),
1132 "cl-core-value": list(),
1133 "cl-core-all-value": list(),
1134 "cl-core-all-options": self.CL_ALL_DISABLED,
1135 "cl-framesize-options": list(),
1136 "cl-framesize-value": list(),
1137 "cl-framesize-all-value": list(),
1138 "cl-framesize-all-options": self.CL_ALL_DISABLED,
1139 "cl-testtype-options": list(),
1140 "cl-testtype-value": list(),
1141 "cl-testtype-all-value": list(),
1142 "cl-testtype-all-options": self.CL_ALL_DISABLED
1144 elif trigger_id == "dd-ctrl-area":
1146 rls = ctrl_panel.get("dd-rls-value")
1147 dut = ctrl_panel.get("dd-dut-value")
1148 dutver = ctrl_panel.get("dd-dutver-value")
1149 phy = ctrl_panel.get("dd-phy-value")
1150 area = self.spec_tbs[rls][dut][dutver][phy][dd_area]
1152 [{"label": v, "value": v} for v in area.keys()],
1153 key=lambda d: d["label"]
1160 "dd-area-value": dd_area,
1161 "dd-test-value": str(),
1162 "dd-test-options": options,
1163 "dd-test-disabled": disabled,
1164 "cl-core-options": list(),
1165 "cl-core-value": list(),
1166 "cl-core-all-value": list(),
1167 "cl-core-all-options": self.CL_ALL_DISABLED,
1168 "cl-framesize-options": list(),
1169 "cl-framesize-value": list(),
1170 "cl-framesize-all-value": list(),
1171 "cl-framesize-all-options": self.CL_ALL_DISABLED,
1172 "cl-testtype-options": list(),
1173 "cl-testtype-value": list(),
1174 "cl-testtype-all-value": list(),
1175 "cl-testtype-all-options": self.CL_ALL_DISABLED
1177 elif trigger_id == "dd-ctrl-test":
1178 rls = ctrl_panel.get("dd-rls-value")
1179 dut = ctrl_panel.get("dd-dut-value")
1180 dutver = ctrl_panel.get("dd-dutver-value")
1181 phy = ctrl_panel.get("dd-phy-value")
1182 area = ctrl_panel.get("dd-area-value")
1183 test = self.spec_tbs[rls][dut][dutver][phy][area][dd_test]
1184 if dut and phy and area and dd_test:
1186 "dd-test-value": dd_test,
1187 "cl-core-options": [{"label": v, "value": v}
1188 for v in sorted(test["core"])],
1189 "cl-core-value": list(),
1190 "cl-core-all-value": list(),
1191 "cl-core-all-options": self.CL_ALL_ENABLED,
1192 "cl-framesize-options": [{"label": v, "value": v}
1193 for v in sorted(test["frame-size"])],
1194 "cl-framesize-value": list(),
1195 "cl-framesize-all-value": list(),
1196 "cl-framesize-all-options": self.CL_ALL_ENABLED,
1197 "cl-testtype-options": [{"label": v, "value": v}
1198 for v in sorted(test["test-type"])],
1199 "cl-testtype-value": list(),
1200 "cl-testtype-all-value": list(),
1201 "cl-testtype-all-options": self.CL_ALL_ENABLED,
1203 elif trigger_id == "cl-ctrl-core":
1204 val_sel, val_all = self._sync_checklists(
1205 opt=ctrl_panel.get("cl-core-options"),
1211 "cl-core-value": val_sel,
1212 "cl-core-all-value": val_all,
1214 elif trigger_id == "cl-ctrl-core-all":
1215 val_sel, val_all = self._sync_checklists(
1216 opt = ctrl_panel.get("cl-core-options"),
1222 "cl-core-value": val_sel,
1223 "cl-core-all-value": val_all,
1225 elif trigger_id == "cl-ctrl-framesize":
1226 val_sel, val_all = self._sync_checklists(
1227 opt = ctrl_panel.get("cl-framesize-options"),
1233 "cl-framesize-value": val_sel,
1234 "cl-framesize-all-value": val_all,
1236 elif trigger_id == "cl-ctrl-framesize-all":
1237 val_sel, val_all = self._sync_checklists(
1238 opt = ctrl_panel.get("cl-framesize-options"),
1240 all=cl_framesize_all,
1244 "cl-framesize-value": val_sel,
1245 "cl-framesize-all-value": val_all,
1247 elif trigger_id == "cl-ctrl-testtype":
1248 val_sel, val_all = self._sync_checklists(
1249 opt = ctrl_panel.get("cl-testtype-options"),
1255 "cl-testtype-value": val_sel,
1256 "cl-testtype-all-value": val_all,
1258 elif trigger_id == "cl-ctrl-testtype-all":
1259 val_sel, val_all = self._sync_checklists(
1260 opt = ctrl_panel.get("cl-testtype-options"),
1262 all=cl_testtype_all,
1266 "cl-testtype-value": val_sel,
1267 "cl-testtype-all-value": val_all,
1269 elif trigger_id == "btn-ctrl-add":
1271 rls = ctrl_panel.get("dd-rls-value")
1272 dut = ctrl_panel.get("dd-dut-value")
1273 dutver = ctrl_panel.get("dd-dutver-value")
1274 phy = ctrl_panel.get("dd-phy-value")
1275 area = ctrl_panel.get("dd-area-value")
1276 test = ctrl_panel.get("dd-test-value")
1277 cores = ctrl_panel.get("cl-core-value")
1278 framesizes = ctrl_panel.get("cl-framesize-value")
1279 testtypes = ctrl_panel.get("cl-testtype-value")
1280 # Add selected test to the list of tests in store:
1281 if all((rls, dut, dutver, phy, area, test, cores, framesizes,
1283 if store_sel is None:
1286 for framesize in framesizes:
1287 for ttype in testtypes:
1290 tid = "-".join((rls, dut, dutver,
1291 phy.replace('af_xdp', 'af-xdp'), area,
1292 framesize.lower(), core.lower(), test,
1294 if tid not in [itm["id"] for itm in store_sel]:
1303 "framesize": framesize.lower(),
1304 "core": core.lower(),
1305 "testtype": ttype.lower()
1307 store_sel = sorted(store_sel, key=lambda d: d["id"])
1308 row_card_sel_tests = self.STYLE_ENABLED
1309 row_btns_sel_tests = self.STYLE_ENABLED
1310 if self.CLEAR_ALL_INPUTS:
1311 ctrl_panel.set(ctrl_panel.defaults)
1313 "cl-selected-options": self._list_tests(store_sel)
1315 elif trigger_id == "btn-sel-remove-all":
1317 row_fig_tput = self.PLACEHOLDER
1318 row_fig_lat = self.PLACEHOLDER
1319 row_table = self.PLACEHOLDER
1320 row_btn_dwnld = self.PLACEHOLDER
1321 row_card_sel_tests = self.STYLE_DISABLED
1322 row_btns_sel_tests = self.STYLE_DISABLED
1324 ctrl_panel.set({"cl-selected-options": list()})
1325 elif trigger_id == "btn-sel-remove":
1328 new_store_sel = list()
1329 for item in store_sel:
1330 if item["id"] not in list_sel:
1331 new_store_sel.append(item)
1332 store_sel = new_store_sel
1333 elif trigger_id == "url":
1334 # TODO: Add verification
1335 url_params = parsed_url["params"]
1337 store_sel = literal_eval(
1338 url_params.get("store_sel", list())[0])
1340 row_card_sel_tests = self.STYLE_ENABLED
1341 row_btns_sel_tests = self.STYLE_ENABLED
1343 if trigger_id in ("btn-ctrl-add", "url", "btn-sel-remove-all",
1344 "btn-sel-remove", "cl-ctrl-normalize"):
1346 row_fig_tput, row_fig_lat, row_table, row_btn_dwnld = \
1347 _generate_plotting_area(
1349 self.data, store_sel, self.layout,
1353 self.data, store_sel, bool(cl_normalize)
1355 _gen_new_url(parsed_url, store_sel)
1358 "cl-selected-options": self._list_tests(store_sel)
1361 row_fig_tput = self.PLACEHOLDER
1362 row_fig_lat = self.PLACEHOLDER
1363 row_table = self.PLACEHOLDER
1364 row_btn_dwnld = self.PLACEHOLDER
1365 row_card_sel_tests = self.STYLE_DISABLED
1366 row_btns_sel_tests = self.STYLE_DISABLED
1368 ctrl_panel.set({"cl-selected-options": list()})
1370 if ctrl_panel.get("cl-core-value") and \
1371 ctrl_panel.get("cl-framesize-value") and \
1372 ctrl_panel.get("cl-testtype-value"):
1377 "btn-add-disabled": disabled,
1378 "cl-normalize-value": cl_normalize
1382 ctrl_panel.panel, store_sel,
1383 row_fig_tput, row_fig_lat, row_table, row_btn_dwnld,
1384 row_card_sel_tests, row_btns_sel_tests
1386 ret_val.extend(ctrl_panel.values())
1390 # Output("download-data", "data"),
1391 # State("selected-tests", "data"),
1392 # Input("btn-download-data", "n_clicks"),
1393 # prevent_initial_call=True
1395 # def _download_data(store_sel, n_clicks):
1400 # raise PreventUpdate
1403 # raise PreventUpdate
1405 # df = pd.DataFrame()
1406 # for itm in store_sel:
1407 # sel_data = select_trending_data(self.data, itm)
1408 # if sel_data is None:
1410 # df = pd.concat([df, sel_data], ignore_index=True)
1412 # return dcc.send_data_frame(df.to_csv, "trending_data.csv")