Skip to content

Commit 5e56a6f

Browse files
committed
Remove ranking from all tables
1 parent 7191482 commit 5e56a6f

File tree

8 files changed

+41
-103
lines changed

8 files changed

+41
-103
lines changed

docs/source/developer_guide/add_benchmarks.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,10 @@ For ``@build_table``, the value returned should be of the form:
262262
...
263263
}
264264
265-
This will generate a table with columns for each metric, as well as "MLIP", "Score",
266-
and "Rank" columns. Tooltips for each column header can also be set by the decorator,
267-
as well as the location to save the JSON file to be loaded when building the app,
268-
which typically would be placed in ``ml_peg/app/data/[category]/[benchmark_name]``.
265+
This will generate a table with columns for each metric, as well as "MLIP" and "Score"
266+
columns. Tooltips for each column header can also be set by the decorator, as well as
267+
the location to save the JSON file to be loaded when building the app, which typically
268+
would be placed in ``ml_peg/app/data/[category]/[benchmark_name]``.
269269

270270
Every benchmark should have at least one of these tables, which includes
271271
the score for each metric, and allowing the table to calculate an overall score for the

ml_peg/analysis/utils/decorators.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import numpy as np
1313
import plotly.graph_objects as go
1414

15-
from ml_peg.analysis.utils.utils import calc_ranks, calc_table_scores
15+
from ml_peg.analysis.utils.utils import calc_table_scores
1616
from ml_peg.app.utils.utils import Thresholds
1717

1818

@@ -274,8 +274,7 @@ def build_table(
274274
filename
275275
Filename to save table. Default is "table.json".
276276
metric_tooltips
277-
Tooltips for table metric headers. Defaults are set for "MLIP", "Score", and
278-
"Rank".
277+
Tooltips for table metric headers. Defaults are set for "MLIP" and "Score".
279278
normalize
280279
Whether to apply normalisation when calculating the score. Default is True.
281280
normalizer
@@ -365,10 +364,7 @@ def build_table_wrapper(*args, **kwargs) -> dict[str, Any]:
365364
| {"id": mlip},
366365
)
367366

368-
summary_tooltips = {
369-
"MLIP": "Name of the model",
370-
"Rank": "Model rank based on score (lower is better)",
371-
}
367+
summary_tooltips = {"MLIP": "Name of the model"}
372368
if normalize:
373369
summary_tooltips["Score"] = (
374370
"Average of normalised metrics (higher is better)"
@@ -391,8 +387,7 @@ def build_table_wrapper(*args, **kwargs) -> dict[str, Any]:
391387
else:
392388
metrics_data = calc_table_scores(metrics_data)
393389

394-
metrics_data = calc_ranks(metrics_data)
395-
metrics_columns += ("Score", "Rank")
390+
metrics_columns += ("Score",)
396391

397392
metric_weights = weights if weights else {}
398393
for column in results:

ml_peg/analysis/utils/utils.py

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from matplotlib import cm
99
from matplotlib.colors import Colormap
1010
import numpy as np
11-
from scipy.stats import rankdata
1211
from sklearn.metrics import mean_absolute_error, mean_squared_error
1312
from yaml import safe_load
1413

@@ -145,7 +144,7 @@ def calc_metric_scores(
145144
for row in metrics_scores:
146145
for key, value in row.items():
147146
# Value may be ``None`` if missing for a benchmark
148-
if key not in {"MLIP", "Score", "Rank", "id"} and value is not None:
147+
if key not in {"MLIP", "Score", "id"} and value is not None:
149148
if cleaned_thresholds is None or key not in cleaned_thresholds:
150149
row[key] = value
151150
continue
@@ -194,7 +193,7 @@ def calc_table_scores(
194193
weights_list = []
195194
for key, value in metrics_row.items():
196195
# Value may be ``None`` if missing for a benchmark
197-
if key not in {"MLIP", "Score", "Rank", "id"} and value is not None:
196+
if key not in {"MLIP", "Score", "id"} and value is not None:
198197
scores_list.append(scores_row[key])
199198
weights_list.append(weights.get(key, 1.0))
200199

@@ -210,36 +209,6 @@ def calc_table_scores(
210209
return metrics_data
211210

212211

213-
def calc_ranks(metrics_data: list[dict]) -> list[dict]:
214-
"""
215-
Calculate rank for each model and add to table data.
216-
217-
Parameters
218-
----------
219-
metrics_data
220-
Rows data containing model name, metric values, and Score.
221-
The "Score" column is used to calculate the rank, with the highest score ranked
222-
1.
223-
224-
Returns
225-
-------
226-
list[dict]
227-
Rows of data with rank for each model added.
228-
"""
229-
# If a score is None, set to NaN for ranking purposes, but do not rank
230-
ranked_scores = rankdata(
231-
[x["Score"] if x.get("Score") is not None else np.nan for x in metrics_data],
232-
nan_policy="omit",
233-
method="max",
234-
)
235-
for i, row in enumerate(metrics_data):
236-
if np.isnan(ranked_scores[i]):
237-
row["Rank"] = None
238-
else:
239-
row["Rank"] = len(ranked_scores) - int(ranked_scores[i]) + 1
240-
return metrics_data
241-
242-
243212
def get_table_style(
244213
data: list[TableRow],
245214
*,
@@ -339,10 +308,7 @@ def rgba_from_val(val: float, vmin: float, vmax: float, cmap: Colormap) -> str:
339308

340309
# Use thresholds
341310
if normalized:
342-
if col != "Rank":
343-
min_value, max_value = 1, 0
344-
else:
345-
min_value, max_value = 1, len(numeric_values)
311+
min_value, max_value = 1, 0
346312
else:
347313
min_value = min(numeric_values)
348314
max_value = max(numeric_values)
@@ -370,13 +336,13 @@ def rgba_from_val(val: float, vmin: float, vmax: float, cmap: Colormap) -> str:
370336
return style_data_conditional
371337

372338

373-
def update_score_rank_style(
339+
def update_score_style(
374340
data: list[MetricRow],
375341
weights: dict[str, float] | None = None,
376342
thresholds: Thresholds | None = None,
377343
) -> tuple[list[MetricRow], list[TableRow]]:
378344
"""
379-
Update table scores, ranks, and table styles.
345+
Update table scores and table styles.
380346
381347
Parameters
382348
----------
@@ -395,7 +361,6 @@ def update_score_rank_style(
395361
"""
396362
weights = clean_weights(weights)
397363
data = calc_table_scores(data, weights, thresholds)
398-
data = calc_ranks(data)
399364
scored_data = calc_metric_scores(data, thresholds)
400365
style = get_table_style(data, scored_data=scored_data)
401366
return data, style

ml_peg/app/build_app.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
from dash.html import H1, H3, Div
1212
from yaml import safe_load
1313

14-
from ml_peg.analysis.utils.utils import calc_ranks, calc_table_scores, get_table_style
14+
from ml_peg.analysis.utils.utils import calc_table_scores, get_table_style
1515
from ml_peg.app import APP_ROOT
1616
from ml_peg.app.utils.build_components import build_weight_components
1717
from ml_peg.app.utils.register_callbacks import register_benchmark_to_category_callback
18-
from ml_peg.app.utils.utils import calculate_column_widths, rank_format, sig_fig_format
18+
from ml_peg.app.utils.utils import calculate_column_widths, sig_fig_format
1919
from ml_peg.models.get_models import get_model_names
2020
from ml_peg.models.models import current_models
2121

@@ -194,17 +194,13 @@ def build_summary_table(
194194
data.append({"MLIP": mlip} | summary_data[mlip])
195195

196196
data = calc_table_scores(data)
197-
data = calc_ranks(data)
198197

199-
columns_headers = ("MLIP",) + tuple(tables.keys()) + ("Score", "Rank")
198+
columns_headers = ("MLIP",) + tuple(tables.keys()) + ("Score",)
200199

201200
columns = [{"name": headers, "id": headers} for headers in columns_headers]
202201
for column in columns:
203202
column_id = column["id"]
204-
if column_id == "Rank":
205-
column["type"] = "numeric"
206-
column["format"] = rank_format()
207-
elif column_id != "MLIP":
203+
if column_id != "MLIP":
208204
column["type"] = "numeric"
209205
column["format"] = sig_fig_format()
210206

ml_peg/app/utils/build_components.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def grid_template_from_widths(
3131
widths
3232
Mapping of column names to pixel widths.
3333
column_order
34-
Ordered metric column names to render between the MLIP, Score, and Rank columns.
34+
Ordered metric column names to render between the MLIP and Score columns.
3535
3636
Returns
3737
-------
@@ -41,7 +41,6 @@ def grid_template_from_widths(
4141
tracks: list[tuple[str, int]] = [("MLIP", widths["MLIP"])]
4242
tracks.extend((col, widths[col]) for col in column_order)
4343
tracks.append(("Score", widths["Score"]))
44-
tracks.append(("Rank", widths["Rank"]))
4544

4645
template_parts: list[str] = []
4746
for _, width in tracks:
@@ -146,7 +145,7 @@ def build_weight_components(
146145
"Threshold metadata must be provided when use_thresholds=True."
147146
)
148147
# Identify metric columns (exclude reserved columns)
149-
reserved = {"MLIP", "Score", "Rank", "id"}
148+
reserved = {"MLIP", "Score", "id"}
150149
columns = [col["id"] for col in table.columns if col.get("id") not in reserved]
151150

152151
if not columns:
@@ -367,7 +366,7 @@ def build_test_layout(
367366

368367
# Inline normalization thresholds when metadata is supplied
369368
if thresholds is not None:
370-
reserved = {"MLIP", "Score", "Rank", "id"}
369+
reserved = {"MLIP", "Score", "id"}
371370
metric_columns = [
372371
col["id"] for col in table.columns if col.get("id") not in reserved
373372
]
@@ -663,19 +662,19 @@ def build_threshold_inputs(
663662
)
664663
)
665664

666-
for _ in ("Score", "Rank"):
667-
cells.append(
668-
Div(
669-
"",
670-
style={
671-
"width": "100%",
672-
"minWidth": "0",
673-
"maxWidth": "100%",
674-
"boxSizing": "border-box",
675-
"border": "1px solid transparent",
676-
},
677-
)
665+
# Score
666+
cells.append(
667+
Div(
668+
"",
669+
style={
670+
"width": "100%",
671+
"minWidth": "0",
672+
"maxWidth": "100%",
673+
"boxSizing": "border-box",
674+
"border": "1px solid transparent",
675+
},
678676
)
677+
)
679678

680679
store = Store(
681680
id=f"{table_id}-thresholds-store",

ml_peg/app/utils/load.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
clean_thresholds,
1616
clean_weights,
1717
is_numeric_column,
18-
rank_format,
1918
sig_fig_format,
2019
)
2120

@@ -65,10 +64,7 @@ def rebuild_table(filename: str | Path, id: str) -> DataTable:
6564
width_labels.append(label_source)
6665
if column_id is None:
6766
continue
68-
if column_id == "Rank":
69-
column["type"] = "numeric"
70-
column.setdefault("format", rank_format())
71-
elif column.get("type") == "numeric" or is_numeric_column(data, column_id):
67+
if column.get("type") == "numeric" or is_numeric_column(data, column_id):
7268
column["type"] = "numeric"
7369
column.setdefault("format", sig_fig_format())
7470
if column_name is not None and not isinstance(column_name, str):

ml_peg/app/utils/register_callbacks.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
calc_metric_scores,
1313
calc_table_scores,
1414
get_table_style,
15-
update_score_rank_style,
15+
update_score_style,
1616
)
1717
from ml_peg.app.utils.utils import (
1818
Thresholds,
@@ -67,14 +67,14 @@ def update_summary_table(
6767
row[tab] = values[row["MLIP"]]
6868

6969
# Update table contents
70-
return update_score_rank_style(summary_data, stored_weights)
70+
return update_score_style(summary_data, stored_weights)
7171

7272

7373
def register_category_table_callbacks(
7474
table_id: str, use_thresholds: bool = False
7575
) -> None:
7676
"""
77-
Register callback to update table scores/rankings when stored values change.
77+
Register callback to update table scores when stored values change.
7878
7979
Parameters
8080
----------
@@ -218,7 +218,7 @@ def update_table_scores(
218218
if not table_data:
219219
raise PreventUpdate
220220

221-
scored_rows, style = update_score_rank_style(table_data, stored_weights)
221+
scored_rows, style = update_score_style(table_data, stored_weights)
222222
return scored_rows, style, scored_rows
223223

224224
@callback(
@@ -337,7 +337,7 @@ def update_category_from_benchmark(
337337
if mlip in benchmark_scores:
338338
row[benchmark_column] = benchmark_scores[mlip]
339339

340-
category_rows, style = update_score_rank_style(category_rows, category_weights)
340+
category_rows, style = update_score_style(category_rows, category_weights)
341341
return category_rows, style, category_rows
342342

343343

ml_peg/app/utils/utils.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ def calculate_column_widths(
5252
# Fixed widths for static columns
5353
widths.setdefault("MLIP", 150)
5454
widths.setdefault("Score", 100)
55-
widths.setdefault("Rank", 100)
5655

5756
for col in columns:
58-
if col not in ("MLIP", "Score", "Rank"):
57+
if col not in ("MLIP", "Score"):
5958
# Calculate width based on column title length
6059
calculated_width = len(col) * char_width + padding
6160
# Enforce minimum width
@@ -109,18 +108,6 @@ def sig_fig_format() -> TableFormat.Format:
109108
)
110109

111110

112-
def rank_format() -> TableFormat.Format:
113-
"""
114-
Build a formatter that displays integer ranks.
115-
116-
Returns
117-
-------
118-
TableFormat.Format
119-
Dash table format configured for integer values.
120-
"""
121-
return TableFormat.Format().scheme(TableFormat.Scheme.decimal_integer)
122-
123-
124111
def clean_thresholds(
125112
raw_thresholds: Mapping[str, Mapping[str, object]] | None,
126113
) -> Thresholds:
@@ -271,7 +258,7 @@ def format_metric_columns(
271258
return None
272259

273260
thresholds = thresholds or {}
274-
reserved = {"MLIP", "Score", "Rank", "id"}
261+
reserved = {"MLIP", "Score", "id"}
275262
updated_columns: list[dict[str, object]] = []
276263

277264
for column in columns:
@@ -352,7 +339,7 @@ def format_tooltip_headers(
352339
return None
353340

354341
thresholds = thresholds or {}
355-
reserved = {"MLIP", "Score", "Rank", "id"}
342+
reserved = {"MLIP", "Score", "id"}
356343

357344
updated: dict[str, str] = {}
358345
for key, text in tooltip_header.items():

0 commit comments

Comments
 (0)