1 # Copyright (c) 2023 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 """The coverage data tables.
20 import dash_bootstrap_components as dbc
22 from dash import dash_table
23 from dash.dash_table.Format import Format, Scheme
25 from ..utils.constants import Constants as C
28 def select_coverage_data(
33 """Select coverage data for the tables and generate tables as pandas data
36 :param data: Coverage data.
37 :param selected: Dictionary with user selection.
38 :param csv: If True, pandas data frame with selected coverage data is
39 returned for "Download Data" feature.
40 :type data: pandas.DataFrame
43 :returns: List of tuples with suite name (str) and data (pandas dataframe)
44 or pandas dataframe if csv is True.
45 :rtype: list[tuple[str, pandas.DataFrame], ] or pandas.DataFrame
50 # Filter data selected by the user.
51 phy = selected["phy"].split("-")
53 topo, arch, nic, drv = phy
54 drv = "" if drv == "dpdk" else drv.replace("_", "-")
58 df = pd.DataFrame(data.loc[(
59 (data["passed"] == True) &
60 (data["dut_type"] == selected["dut"]) &
61 (data["dut_version"] == selected["dutver"]) &
62 (data["release"] == selected["rls"])
65 (df.job.str.endswith(f"{topo}-{arch}")) &
66 (df.test_id.str.contains(
67 f"^.*\.{selected['area']}\..*{nic}.*{drv}.*$",
72 for driver in C.DRIVERS:
74 df[df.test_id.str.contains(f"-{driver}-")].index,
78 # Prepare the coverage data
79 def _latency(hdrh_string: str, percentile: float) -> int:
80 """Get latency from HDRH string for given percentile.
82 :param hdrh_string: Encoded HDRH string.
83 :param percentile: Given percentile.
84 :type hdrh_string: str
85 :type percentile: float
86 :returns: The latency value for the given percentile from the encoded
91 hdr_lat = hdrh.histogram.HdrHistogram.decode(hdrh_string)
92 return hdr_lat.get_value_at_percentile(percentile)
93 except (hdrh.codec.HdrLengthException, TypeError):
96 def _get_suite(test_id: str) -> str:
97 """Get the suite name from the test ID.
99 return test_id.split(".")[-2].replace("2n1l-", "").\
100 replace("1n1l-", "").replace("2n-", "").replace("-ndrpdr", "")
102 def _get_test(test_id: str) -> str:
103 """Get the test name from the test ID.
105 return test_id.split(".")[-1].replace("-ndrpdr", "")
108 cov["suite"] = df.apply(lambda row: _get_suite(row["test_id"]), axis=1)
109 cov["Test Name"] = df.apply(lambda row: _get_test(row["test_id"]), axis=1)
110 cov["Throughput_Unit"] = df["result_pdr_lower_rate_unit"]
111 cov["Throughput_NDR"] = df.apply(
112 lambda row: row["result_ndr_lower_rate_value"] / 1e6, axis=1
114 cov["Throughput_NDR_Mbps"] = df.apply(
115 lambda row: row["result_ndr_lower_bandwidth_value"] /1e9, axis=1
117 cov["Throughput_PDR"] = \
118 df.apply(lambda row: row["result_pdr_lower_rate_value"] / 1e6, axis=1)
119 cov["Throughput_PDR_Mbps"] = df.apply(
120 lambda row: row["result_pdr_lower_bandwidth_value"] /1e9, axis=1
122 cov["Latency Forward [us]_10% PDR_P50"] = df.apply(
123 lambda row: _latency(row["result_latency_forward_pdr_10_hdrh"], 50.0),
126 cov["Latency Forward [us]_10% PDR_P90"] = df.apply(
127 lambda row: _latency(row["result_latency_forward_pdr_10_hdrh"], 90.0),
130 cov["Latency Forward [us]_10% PDR_P99"] = df.apply(
131 lambda row: _latency(row["result_latency_forward_pdr_10_hdrh"], 99.0),
134 cov["Latency Forward [us]_50% PDR_P50"] = df.apply(
135 lambda row: _latency(row["result_latency_forward_pdr_50_hdrh"], 50.0),
138 cov["Latency Forward [us]_50% PDR_P90"] = df.apply(
139 lambda row: _latency(row["result_latency_forward_pdr_50_hdrh"], 90.0),
142 cov["Latency Forward [us]_50% PDR_P99"] = df.apply(
143 lambda row: _latency(row["result_latency_forward_pdr_50_hdrh"], 99.0),
146 cov["Latency Forward [us]_90% PDR_P50"] = df.apply(
147 lambda row: _latency(row["result_latency_forward_pdr_90_hdrh"], 50.0),
150 cov["Latency Forward [us]_90% PDR_P90"] = df.apply(
151 lambda row: _latency(row["result_latency_forward_pdr_90_hdrh"], 90.0),
154 cov["Latency Forward [us]_90% PDR_P99"] = df.apply(
155 lambda row: _latency(row["result_latency_forward_pdr_90_hdrh"], 99.0),
158 cov["Latency Reverse [us]_10% PDR_P50"] = df.apply(
159 lambda row: _latency(row["result_latency_reverse_pdr_10_hdrh"], 50.0),
162 cov["Latency Reverse [us]_10% PDR_P90"] = df.apply(
163 lambda row: _latency(row["result_latency_reverse_pdr_10_hdrh"], 90.0),
166 cov["Latency Reverse [us]_10% PDR_P99"] = df.apply(
167 lambda row: _latency(row["result_latency_reverse_pdr_10_hdrh"], 99.0),
170 cov["Latency Reverse [us]_50% PDR_P50"] = df.apply(
171 lambda row: _latency(row["result_latency_reverse_pdr_50_hdrh"], 50.0),
174 cov["Latency Reverse [us]_50% PDR_P90"] = df.apply(
175 lambda row: _latency(row["result_latency_reverse_pdr_50_hdrh"], 90.0),
178 cov["Latency Reverse [us]_50% PDR_P99"] = df.apply(
179 lambda row: _latency(row["result_latency_reverse_pdr_50_hdrh"], 99.0),
182 cov["Latency Reverse [us]_90% PDR_P50"] = df.apply(
183 lambda row: _latency(row["result_latency_reverse_pdr_90_hdrh"], 50.0),
186 cov["Latency Reverse [us]_90% PDR_P90"] = df.apply(
187 lambda row: _latency(row["result_latency_reverse_pdr_90_hdrh"], 90.0),
190 cov["Latency Reverse [us]_90% PDR_P99"] = df.apply(
191 lambda row: _latency(row["result_latency_reverse_pdr_90_hdrh"], 99.0),
198 # Split data into tabels depending on the test suite.
199 for suite in cov["suite"].unique().tolist():
200 df_suite = pd.DataFrame(cov.loc[(cov["suite"] == suite)])
201 unit = df_suite["Throughput_Unit"].tolist()[0]
204 "Throughput_NDR": f"Throughput_NDR_M{unit}",
205 "Throughput_PDR": f"Throughput_PDR_M{unit}"
209 df_suite.drop(["suite", "Throughput_Unit"], axis=1, inplace=True)
210 l_data.append((suite, df_suite, ))
214 def coverage_tables(data: pd.DataFrame, selected: dict) -> list:
215 """Generate an accordion with coverage tables.
217 :param data: Coverage data.
218 :param selected: Dictionary with user selection.
219 :type data: pandas.DataFrame
221 :returns: Accordion with suite names (titles) and tables.
222 :rtype: dash_bootstrap_components.Accordion
225 accordion_items = list()
226 for suite, cov_data in select_coverage_data(data, selected):
228 for idx, col in enumerate(cov_data.columns):
231 "name": ["", "", col],
239 "name": col.split("_"),
244 "format": Format(precision=2, scheme=Scheme.fixed)
248 "name": col.split("_"),
253 "format": Format(precision=0, scheme=Scheme.fixed)
256 accordion_items.append(
259 children=dash_table.DataTable(
261 data=cov_data.to_dict("records"),
262 merge_duplicate_headers=True,
264 filter_action="none",
265 sort_action="native",
270 style_cell={"textAlign": "right"},
271 style_cell_conditional=[{
272 "if": {"column_id": "Test Name"},
279 return dbc.Accordion(
280 children=accordion_items,
281 class_name="gy-2 p-0",
282 start_collapsed=True,