Tighten leaderboard sorting and colors
Browse files- app.py +118 -49
- assets/styles.css +1 -1
app.py
CHANGED
|
@@ -104,7 +104,6 @@ TABLE_LABELS = {
|
|
| 104 |
"method": "Method",
|
| 105 |
"family": "Family",
|
| 106 |
"hardware": "Hardware",
|
| 107 |
-
"metric": "Metric",
|
| 108 |
"task_score": "Task performance",
|
| 109 |
"score": "Task performance",
|
| 110 |
"robustness_auc": "Robustness AUC",
|
|
@@ -128,7 +127,6 @@ TABLE_LABELS = {
|
|
| 128 |
"n_train_trials": "Training trials",
|
| 129 |
"n_test_trials": "Test trials",
|
| 130 |
"n_neurons": "Neurons",
|
| 131 |
-
"notes": "Notes",
|
| 132 |
}
|
| 133 |
|
| 134 |
NUMERIC_COLUMNS = {
|
|
@@ -158,20 +156,57 @@ NUMERIC_COLUMNS = {
|
|
| 158 |
}
|
| 159 |
RIGHT_ALIGNED_COLUMNS = NUMERIC_COLUMNS | {"rank"}
|
| 160 |
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
CATEGORICAL_PALETTE = [
|
| 163 |
-
"#0072B2",
|
| 164 |
"#E69F00",
|
| 165 |
-
"#009E73",
|
| 166 |
-
"#CC79A7",
|
| 167 |
-
"#D55E00",
|
| 168 |
"#56B4E9",
|
|
|
|
| 169 |
"#F0E442",
|
| 170 |
-
"#
|
| 171 |
-
"#
|
| 172 |
-
"#
|
| 173 |
-
"#
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
]
|
| 176 |
|
| 177 |
|
|
@@ -354,6 +389,26 @@ def round_numeric(df: pd.DataFrame, columns: Iterable[str], digits: int = 3) ->
|
|
| 354 |
return out
|
| 355 |
|
| 356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
def records(df: pd.DataFrame) -> list[dict]:
|
| 358 |
clean = df.astype(object).where(pd.notna(df), None)
|
| 359 |
return clean.to_dict("records")
|
|
@@ -435,13 +490,15 @@ def dataframe_table(
|
|
| 435 |
*,
|
| 436 |
page_size: int = 8,
|
| 437 |
max_height: str = "520px",
|
|
|
|
| 438 |
) -> dash_table.DataTable:
|
| 439 |
return dash_table.DataTable(
|
| 440 |
id=table_id,
|
| 441 |
columns=[],
|
| 442 |
data=[],
|
| 443 |
page_size=page_size,
|
| 444 |
-
sort_action=
|
|
|
|
| 445 |
cell_selectable=True,
|
| 446 |
style_as_list_view=True,
|
| 447 |
fixed_rows={"headers": True},
|
|
@@ -531,8 +588,6 @@ def leaderboard_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 531 |
df = df.merge(rob, on="model", how="left")
|
| 532 |
df = df.merge(cons, on="model", how="left")
|
| 533 |
df = df.merge(scale, on="model", how="left")
|
| 534 |
-
df["notes"] = np.where(df["task_score"].isna(), "Not available", "")
|
| 535 |
-
|
| 536 |
available = df["task_score"].notna()
|
| 537 |
order = df.loc[available].sort_values(
|
| 538 |
["task_score", "model_order"], ascending=[False, True]
|
|
@@ -541,9 +596,6 @@ def leaderboard_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 541 |
for rank, idx in enumerate(order, start=1):
|
| 542 |
df.at[idx, "rank"] = rank
|
| 543 |
|
| 544 |
-
df = df.sort_values(
|
| 545 |
-
["task_score", "model_order"], ascending=[False, True], na_position="last"
|
| 546 |
-
)
|
| 547 |
df["id"] = df["model"]
|
| 548 |
return round_numeric(df, NUMERIC_COLUMNS)
|
| 549 |
|
|
@@ -551,7 +603,9 @@ def leaderboard_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 551 |
def leaderboard_summary(dataset: str, table_df: pd.DataFrame) -> list[html.Div]:
|
| 552 |
label = DATASET_LABELS.get(dataset, dataset)
|
| 553 |
metric = metric_text(table_df["metric"].dropna().iloc[0]) if table_df["metric"].notna().any() else "score"
|
| 554 |
-
available =
|
|
|
|
|
|
|
| 555 |
cards = [metric_card("Dataset", label, f"Primary metric: {metric}")]
|
| 556 |
for _, row in available.iterrows():
|
| 557 |
cards.append(
|
|
@@ -578,7 +632,11 @@ def performance_heatmap(dataset: str, models: list[str] | None) -> go.Figure:
|
|
| 578 |
)
|
| 579 |
|
| 580 |
selected_label = DATASET_LABELS.get(dataset, dataset)
|
| 581 |
-
order_df =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 582 |
method_order = [m for m in order_df["method"] if m in set(pivot.index)]
|
| 583 |
pivot = pivot.reindex(method_order)
|
| 584 |
dataset_order = [DATASET_LABELS.get(ds, ds) for ds in DATASETS]
|
|
@@ -615,7 +673,7 @@ def ranking_figure(dataset: str, table_df: pd.DataFrame) -> go.Figure:
|
|
| 615 |
x=rank_df["task_score"],
|
| 616 |
y=rank_df["method"],
|
| 617 |
orientation="h",
|
| 618 |
-
marker=dict(color=
|
| 619 |
hovertemplate="Method=%{y}<br>Score=%{x:.4f}<extra></extra>",
|
| 620 |
)
|
| 621 |
)
|
|
@@ -637,7 +695,6 @@ def consistency_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 637 |
cons = cons.rename(columns={"mean_r2": "alignment_score"})
|
| 638 |
|
| 639 |
df = base.merge(cons, on="model", how="left")
|
| 640 |
-
df["notes"] = np.where(df["alignment_score"].isna(), "Not available", "")
|
| 641 |
available = df["alignment_score"].notna()
|
| 642 |
order = df.loc[available].sort_values(
|
| 643 |
["alignment_score", "model_order"], ascending=[False, True]
|
|
@@ -645,9 +702,6 @@ def consistency_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 645 |
df["rank"] = None
|
| 646 |
for rank, idx in enumerate(order, start=1):
|
| 647 |
df.at[idx, "rank"] = rank
|
| 648 |
-
df = df.sort_values(
|
| 649 |
-
["alignment_score", "model_order"], ascending=[False, True], na_position="last"
|
| 650 |
-
)
|
| 651 |
df["id"] = df["model"]
|
| 652 |
return round_numeric(df, NUMERIC_COLUMNS)
|
| 653 |
|
|
@@ -655,7 +709,9 @@ def consistency_frame(dataset: str, models: list[str] | None) -> pd.DataFrame:
|
|
| 655 |
def selected_consistency_model(df: pd.DataFrame, active_cell: dict | None) -> str | None:
|
| 656 |
if active_cell and active_cell.get("row_id") in set(df["model"]):
|
| 657 |
return str(active_cell["row_id"])
|
| 658 |
-
available =
|
|
|
|
|
|
|
| 659 |
if available.empty:
|
| 660 |
return None
|
| 661 |
return str(available.iloc[0]["model"])
|
|
@@ -670,7 +726,7 @@ def consistency_bar_figure(dataset: str, df: pd.DataFrame) -> go.Figure:
|
|
| 670 |
x=bar_df["alignment_score"],
|
| 671 |
y=bar_df["method"],
|
| 672 |
orientation="h",
|
| 673 |
-
marker=dict(color=
|
| 674 |
hovertemplate="Method=%{y}<br>Alignment=%{x:.4f}<extra></extra>",
|
| 675 |
)
|
| 676 |
)
|
|
@@ -698,7 +754,7 @@ def consistency_heatmap(models: list[str] | None) -> go.Figure:
|
|
| 698 |
y=list(pivot.index),
|
| 699 |
text=text.values if not pivot.empty else [[]],
|
| 700 |
texttemplate="%{text}",
|
| 701 |
-
colorscale=
|
| 702 |
colorbar=dict(title="Score", thickness=12),
|
| 703 |
hovertemplate="Method=%{y}<br>Dataset=%{x}<br>Alignment=%{z:.4f}<extra></extra>",
|
| 704 |
)
|
|
@@ -757,10 +813,21 @@ def latent_space_figure(dataset: str, model: str | None) -> go.Figure:
|
|
| 757 |
|
| 758 |
condition_values = sorted(plot_df["condition"].astype(str).unique(), key=condition_sort_key)
|
| 759 |
use_categorical = len(condition_values) <= 12
|
| 760 |
-
|
| 761 |
-
|
| 762 |
-
|
| 763 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 764 |
condition_name = condition_axis_label(dataset)
|
| 765 |
|
| 766 |
for session_idx, session in enumerate(sessions):
|
|
@@ -847,7 +914,7 @@ def latent_space_figure(dataset: str, model: str | None) -> go.Figure:
|
|
| 847 |
size=2.8,
|
| 848 |
opacity=0.72,
|
| 849 |
color=session_df["condition_num"],
|
| 850 |
-
colorscale=
|
| 851 |
showscale=session_idx == 0,
|
| 852 |
colorbar=dict(title=condition_name, thickness=12),
|
| 853 |
),
|
|
@@ -948,7 +1015,7 @@ def robustness_table_frame(dataset: str, models: list[str] | None) -> pd.DataFra
|
|
| 948 |
df = filter_models(present_rows(robustness), models)
|
| 949 |
df = df[df["dataset"].astype(str) == str(dataset)].copy() if not df.empty else df
|
| 950 |
if df.empty:
|
| 951 |
-
return pd.DataFrame(columns=["method", "
|
| 952 |
df = add_method_columns(df)
|
| 953 |
df = df.rename(
|
| 954 |
columns={
|
|
@@ -958,7 +1025,7 @@ def robustness_table_frame(dataset: str, models: list[str] | None) -> pd.DataFra
|
|
| 958 |
"mean_score": "average_noisy_score",
|
| 959 |
}
|
| 960 |
)
|
| 961 |
-
cols = ["method", "
|
| 962 |
return round_numeric(df[cols].sort_values("robustness_auc", ascending=False), NUMERIC_COLUMNS)
|
| 963 |
|
| 964 |
|
|
@@ -988,7 +1055,7 @@ def compute_figures(dataset: str, models: list[str] | None) -> tuple[go.Figure,
|
|
| 988 |
text=df["method"],
|
| 989 |
marker=dict(
|
| 990 |
size=np.clip(df["peak_ram_gb"].fillna(1.0) * 4, 8, 26),
|
| 991 |
-
color=df["hardware"].map({"CPU": "#
|
| 992 |
opacity=0.82,
|
| 993 |
line=dict(color="#ffffff", width=1),
|
| 994 |
),
|
|
@@ -1035,7 +1102,7 @@ def influence_figures(dataset: str, models: list[str] | None) -> tuple[go.Figure
|
|
| 1035 |
nshap = nshap[nshap["dataset"].astype(str) == str(dataset)].copy() if not nshap.empty else nshap
|
| 1036 |
if nshap.empty:
|
| 1037 |
neuron_fig = empty_figure("No neuron-influence results are available for this dataset.")
|
| 1038 |
-
table = pd.DataFrame(columns=["method", "
|
| 1039 |
else:
|
| 1040 |
nshap = add_method_columns(nshap)
|
| 1041 |
nshap["auc"] = pd.to_numeric(nshap["auc"], errors="coerce")
|
|
@@ -1045,7 +1112,7 @@ def influence_figures(dataset: str, models: list[str] | None) -> tuple[go.Figure
|
|
| 1045 |
x=bar_df["auc"],
|
| 1046 |
y=bar_df["method"],
|
| 1047 |
orientation="h",
|
| 1048 |
-
marker=dict(color=
|
| 1049 |
hovertemplate="Method=%{y}<br>AUC=%{x:.4f}<extra></extra>",
|
| 1050 |
)
|
| 1051 |
)
|
|
@@ -1055,7 +1122,7 @@ def influence_figures(dataset: str, models: list[str] | None) -> tuple[go.Figure
|
|
| 1055 |
fig_layout(neuron_fig, height=max(420, 25 * len(bar_df) + 150))
|
| 1056 |
table = nshap.rename(columns={"auc": "neuron_influence_auc"})
|
| 1057 |
table = table[
|
| 1058 |
-
["method", "
|
| 1059 |
]
|
| 1060 |
|
| 1061 |
tshap = filter_models(active_rows(trial_shapley), models)
|
|
@@ -1071,7 +1138,7 @@ def influence_figures(dataset: str, models: list[str] | None) -> tuple[go.Figure
|
|
| 1071 |
x=trial_df["perturbation_auc"],
|
| 1072 |
y=trial_df["method"],
|
| 1073 |
orientation="h",
|
| 1074 |
-
marker=dict(color="#
|
| 1075 |
hovertemplate="Method=%{y}<br>AUC=%{x:.4f}<extra></extra>",
|
| 1076 |
)
|
| 1077 |
)
|
|
@@ -1173,7 +1240,7 @@ app.layout = html.Div(
|
|
| 1173 |
html.Div(
|
| 1174 |
[
|
| 1175 |
html.Div(
|
| 1176 |
-
dataframe_table("leaderboard-table", page_size=23, max_height="680px"),
|
| 1177 |
className="leaderboard-table-wrap",
|
| 1178 |
),
|
| 1179 |
dcc.Graph(id="dataset-ranking", config={"displayModeBar": False}),
|
|
@@ -1198,7 +1265,7 @@ app.layout = html.Div(
|
|
| 1198 |
[
|
| 1199 |
html.Div(
|
| 1200 |
[
|
| 1201 |
-
dataframe_table("consistency-table", page_size=23, max_height="520px"),
|
| 1202 |
html.P("Click a method to update the 3D latent view.", className="table-hint"),
|
| 1203 |
],
|
| 1204 |
className="consistency-table-wrap",
|
|
@@ -1312,21 +1379,21 @@ app.layout = html.Div(
|
|
| 1312 |
Output("performance-heatmap", "figure"),
|
| 1313 |
Input("dataset-filter", "value"),
|
| 1314 |
Input("model-filter", "value"),
|
|
|
|
| 1315 |
)
|
| 1316 |
-
def update_leaderboard(dataset: str, models: list[str] | None):
|
| 1317 |
df = leaderboard_frame(dataset, models)
|
| 1318 |
visible_cols = [
|
| 1319 |
"rank",
|
| 1320 |
"method",
|
| 1321 |
"task_score",
|
| 1322 |
-
"metric",
|
| 1323 |
"robustness_auc",
|
| 1324 |
"alignment_score",
|
| 1325 |
"training_time_sec",
|
| 1326 |
"peak_ram_gb",
|
| 1327 |
-
"notes",
|
| 1328 |
]
|
| 1329 |
-
|
|
|
|
| 1330 |
return (
|
| 1331 |
leaderboard_summary(dataset, df),
|
| 1332 |
column_defs([c for c in visible_cols if c in table_df.columns]),
|
|
@@ -1345,12 +1412,14 @@ def update_leaderboard(dataset: str, models: list[str] | None):
|
|
| 1345 |
Input("dataset-filter", "value"),
|
| 1346 |
Input("model-filter", "value"),
|
| 1347 |
Input("consistency-table", "active_cell"),
|
|
|
|
| 1348 |
)
|
| 1349 |
-
def update_consistency(dataset: str, models: list[str] | None, active_cell: dict | None):
|
| 1350 |
df = consistency_frame(dataset, models)
|
| 1351 |
model = selected_consistency_model(df, active_cell)
|
| 1352 |
-
visible_cols = ["rank", "method", "alignment_score", "n_sessions", "latent_dim", "n_pairwise"
|
| 1353 |
-
|
|
|
|
| 1354 |
return (
|
| 1355 |
column_defs([c for c in visible_cols if c in table_df.columns]),
|
| 1356 |
records(table_df),
|
|
|
|
| 104 |
"method": "Method",
|
| 105 |
"family": "Family",
|
| 106 |
"hardware": "Hardware",
|
|
|
|
| 107 |
"task_score": "Task performance",
|
| 108 |
"score": "Task performance",
|
| 109 |
"robustness_auc": "Robustness AUC",
|
|
|
|
| 127 |
"n_train_trials": "Training trials",
|
| 128 |
"n_test_trials": "Test trials",
|
| 129 |
"n_neurons": "Neurons",
|
|
|
|
| 130 |
}
|
| 131 |
|
| 132 |
NUMERIC_COLUMNS = {
|
|
|
|
| 156 |
}
|
| 157 |
RIGHT_ALIGNED_COLUMNS = NUMERIC_COLUMNS | {"rank"}
|
| 158 |
|
| 159 |
+
# Shared figure colors copied from the paper plotting scripts.
|
| 160 |
+
TASK_COLOR = "#1565C0"
|
| 161 |
+
ROBUSTNESS_COLOR = "#2E7D32"
|
| 162 |
+
COMPUTE_COLOR = "#E65100"
|
| 163 |
+
INFLUENCE_COLOR = "#CC79A7"
|
| 164 |
+
ALIGNMENT_COLOR = "#0072B2"
|
| 165 |
+
SCORE_SCALE = [[0.0, "#EFF6FF"], [1.0, TASK_COLOR]]
|
| 166 |
+
ALIGNMENT_SCALE = [[0.0, "#F7FBF7"], [1.0, ROBUSTNESS_COLOR]]
|
| 167 |
+
DATASET_COLORS = {
|
| 168 |
+
"monkey": "#0072B2",
|
| 169 |
+
"allen_neuropixels": "#E69F00",
|
| 170 |
+
"speech": "#009E73",
|
| 171 |
+
"mc_pacman": "#CC79A7",
|
| 172 |
+
"ratinabox": "#D55E00",
|
| 173 |
+
}
|
| 174 |
CATEGORICAL_PALETTE = [
|
|
|
|
| 175 |
"#E69F00",
|
|
|
|
|
|
|
|
|
|
| 176 |
"#56B4E9",
|
| 177 |
+
"#009E73",
|
| 178 |
"#F0E442",
|
| 179 |
+
"#0072B2",
|
| 180 |
+
"#D55E00",
|
| 181 |
+
"#CC79A7",
|
| 182 |
+
"#000000",
|
| 183 |
+
]
|
| 184 |
+
DIRECTION_PALETTE = [
|
| 185 |
+
"#B23AEE",
|
| 186 |
+
"#3B1C54",
|
| 187 |
+
"#2DD4F6",
|
| 188 |
+
"#289285",
|
| 189 |
+
"#E3D724",
|
| 190 |
+
"#00A65A",
|
| 191 |
+
"#5B8FF9",
|
| 192 |
+
"#F97316",
|
| 193 |
+
]
|
| 194 |
+
SPEECH_PALETTE = {
|
| 195 |
+
"3": "#E69F00",
|
| 196 |
+
"2": "#56B4E9",
|
| 197 |
+
"4": "#009E73",
|
| 198 |
+
"7": "#999933",
|
| 199 |
+
"6": "#0072B2",
|
| 200 |
+
"1": "#D55E00",
|
| 201 |
+
"5": "#CC79A7",
|
| 202 |
+
"0": "#000000",
|
| 203 |
+
}
|
| 204 |
+
RATINABOX_SCALE = [
|
| 205 |
+
[0.0, "#440154"],
|
| 206 |
+
[0.25, "#3B528B"],
|
| 207 |
+
[0.5, "#21918C"],
|
| 208 |
+
[0.75, "#5EC962"],
|
| 209 |
+
[1.0, "#FDE725"],
|
| 210 |
]
|
| 211 |
|
| 212 |
|
|
|
|
| 389 |
return out
|
| 390 |
|
| 391 |
|
| 392 |
+
def sort_table(df: pd.DataFrame, sort_by: list[dict] | None, default: list[tuple[str, bool]]) -> pd.DataFrame:
|
| 393 |
+
if sort_by:
|
| 394 |
+
sort_spec = []
|
| 395 |
+
for item in sort_by:
|
| 396 |
+
col = item.get("column_id")
|
| 397 |
+
if col in df.columns:
|
| 398 |
+
sort_spec.append((col, item.get("direction") == "asc"))
|
| 399 |
+
if sort_spec:
|
| 400 |
+
return df.sort_values(
|
| 401 |
+
[col for col, _ in sort_spec],
|
| 402 |
+
ascending=[ascending for _, ascending in sort_spec],
|
| 403 |
+
na_position="last",
|
| 404 |
+
)
|
| 405 |
+
return df.sort_values(
|
| 406 |
+
[col for col, _ in default],
|
| 407 |
+
ascending=[ascending for _, ascending in default],
|
| 408 |
+
na_position="last",
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
+
|
| 412 |
def records(df: pd.DataFrame) -> list[dict]:
|
| 413 |
clean = df.astype(object).where(pd.notna(df), None)
|
| 414 |
return clean.to_dict("records")
|
|
|
|
| 490 |
*,
|
| 491 |
page_size: int = 8,
|
| 492 |
max_height: str = "520px",
|
| 493 |
+
sort_action: str = "native",
|
| 494 |
) -> dash_table.DataTable:
|
| 495 |
return dash_table.DataTable(
|
| 496 |
id=table_id,
|
| 497 |
columns=[],
|
| 498 |
data=[],
|
| 499 |
page_size=page_size,
|
| 500 |
+
sort_action=sort_action,
|
| 501 |
+
sort_mode="single",
|
| 502 |
cell_selectable=True,
|
| 503 |
style_as_list_view=True,
|
| 504 |
fixed_rows={"headers": True},
|
|
|
|
| 588 |
df = df.merge(rob, on="model", how="left")
|
| 589 |
df = df.merge(cons, on="model", how="left")
|
| 590 |
df = df.merge(scale, on="model", how="left")
|
|
|
|
|
|
|
| 591 |
available = df["task_score"].notna()
|
| 592 |
order = df.loc[available].sort_values(
|
| 593 |
["task_score", "model_order"], ascending=[False, True]
|
|
|
|
| 596 |
for rank, idx in enumerate(order, start=1):
|
| 597 |
df.at[idx, "rank"] = rank
|
| 598 |
|
|
|
|
|
|
|
|
|
|
| 599 |
df["id"] = df["model"]
|
| 600 |
return round_numeric(df, NUMERIC_COLUMNS)
|
| 601 |
|
|
|
|
| 603 |
def leaderboard_summary(dataset: str, table_df: pd.DataFrame) -> list[html.Div]:
|
| 604 |
label = DATASET_LABELS.get(dataset, dataset)
|
| 605 |
metric = metric_text(table_df["metric"].dropna().iloc[0]) if table_df["metric"].notna().any() else "score"
|
| 606 |
+
available = sort_table(
|
| 607 |
+
table_df, None, [("task_score", False), ("model_order", True)]
|
| 608 |
+
).dropna(subset=["task_score"]).head(3)
|
| 609 |
cards = [metric_card("Dataset", label, f"Primary metric: {metric}")]
|
| 610 |
for _, row in available.iterrows():
|
| 611 |
cards.append(
|
|
|
|
| 632 |
)
|
| 633 |
|
| 634 |
selected_label = DATASET_LABELS.get(dataset, dataset)
|
| 635 |
+
order_df = sort_table(
|
| 636 |
+
leaderboard_frame(dataset, models),
|
| 637 |
+
None,
|
| 638 |
+
[("task_score", False), ("model_order", True)],
|
| 639 |
+
)
|
| 640 |
method_order = [m for m in order_df["method"] if m in set(pivot.index)]
|
| 641 |
pivot = pivot.reindex(method_order)
|
| 642 |
dataset_order = [DATASET_LABELS.get(ds, ds) for ds in DATASETS]
|
|
|
|
| 673 |
x=rank_df["task_score"],
|
| 674 |
y=rank_df["method"],
|
| 675 |
orientation="h",
|
| 676 |
+
marker=dict(color=TASK_COLOR),
|
| 677 |
hovertemplate="Method=%{y}<br>Score=%{x:.4f}<extra></extra>",
|
| 678 |
)
|
| 679 |
)
|
|
|
|
| 695 |
cons = cons.rename(columns={"mean_r2": "alignment_score"})
|
| 696 |
|
| 697 |
df = base.merge(cons, on="model", how="left")
|
|
|
|
| 698 |
available = df["alignment_score"].notna()
|
| 699 |
order = df.loc[available].sort_values(
|
| 700 |
["alignment_score", "model_order"], ascending=[False, True]
|
|
|
|
| 702 |
df["rank"] = None
|
| 703 |
for rank, idx in enumerate(order, start=1):
|
| 704 |
df.at[idx, "rank"] = rank
|
|
|
|
|
|
|
|
|
|
| 705 |
df["id"] = df["model"]
|
| 706 |
return round_numeric(df, NUMERIC_COLUMNS)
|
| 707 |
|
|
|
|
| 709 |
def selected_consistency_model(df: pd.DataFrame, active_cell: dict | None) -> str | None:
|
| 710 |
if active_cell and active_cell.get("row_id") in set(df["model"]):
|
| 711 |
return str(active_cell["row_id"])
|
| 712 |
+
available = sort_table(
|
| 713 |
+
df, None, [("alignment_score", False), ("model_order", True)]
|
| 714 |
+
).dropna(subset=["alignment_score"])
|
| 715 |
if available.empty:
|
| 716 |
return None
|
| 717 |
return str(available.iloc[0]["model"])
|
|
|
|
| 726 |
x=bar_df["alignment_score"],
|
| 727 |
y=bar_df["method"],
|
| 728 |
orientation="h",
|
| 729 |
+
marker=dict(color=ALIGNMENT_COLOR),
|
| 730 |
hovertemplate="Method=%{y}<br>Alignment=%{x:.4f}<extra></extra>",
|
| 731 |
)
|
| 732 |
)
|
|
|
|
| 754 |
y=list(pivot.index),
|
| 755 |
text=text.values if not pivot.empty else [[]],
|
| 756 |
texttemplate="%{text}",
|
| 757 |
+
colorscale=ALIGNMENT_SCALE,
|
| 758 |
colorbar=dict(title="Score", thickness=12),
|
| 759 |
hovertemplate="Method=%{y}<br>Dataset=%{x}<br>Alignment=%{z:.4f}<extra></extra>",
|
| 760 |
)
|
|
|
|
| 813 |
|
| 814 |
condition_values = sorted(plot_df["condition"].astype(str).unique(), key=condition_sort_key)
|
| 815 |
use_categorical = len(condition_values) <= 12
|
| 816 |
+
if dataset == "monkey":
|
| 817 |
+
condition_colors = {
|
| 818 |
+
condition: DIRECTION_PALETTE[int(float(condition)) % len(DIRECTION_PALETTE)]
|
| 819 |
+
for condition in condition_values
|
| 820 |
+
}
|
| 821 |
+
elif dataset == "speech":
|
| 822 |
+
condition_colors = {
|
| 823 |
+
condition: SPEECH_PALETTE.get(condition, CATEGORICAL_PALETTE[idx % len(CATEGORICAL_PALETTE)])
|
| 824 |
+
for idx, condition in enumerate(condition_values)
|
| 825 |
+
}
|
| 826 |
+
else:
|
| 827 |
+
condition_colors = {
|
| 828 |
+
condition: CATEGORICAL_PALETTE[idx % len(CATEGORICAL_PALETTE)]
|
| 829 |
+
for idx, condition in enumerate(condition_values)
|
| 830 |
+
}
|
| 831 |
condition_name = condition_axis_label(dataset)
|
| 832 |
|
| 833 |
for session_idx, session in enumerate(sessions):
|
|
|
|
| 914 |
size=2.8,
|
| 915 |
opacity=0.72,
|
| 916 |
color=session_df["condition_num"],
|
| 917 |
+
colorscale=RATINABOX_SCALE,
|
| 918 |
showscale=session_idx == 0,
|
| 919 |
colorbar=dict(title=condition_name, thickness=12),
|
| 920 |
),
|
|
|
|
| 1015 |
df = filter_models(present_rows(robustness), models)
|
| 1016 |
df = df[df["dataset"].astype(str) == str(dataset)].copy() if not df.empty else df
|
| 1017 |
if df.empty:
|
| 1018 |
+
return pd.DataFrame(columns=["method", "reference_score", "highest_noise_score", "robustness_auc", "average_noisy_score"])
|
| 1019 |
df = add_method_columns(df)
|
| 1020 |
df = df.rename(
|
| 1021 |
columns={
|
|
|
|
| 1025 |
"mean_score": "average_noisy_score",
|
| 1026 |
}
|
| 1027 |
)
|
| 1028 |
+
cols = ["method", "reference_score", "highest_noise_score", "robustness_auc", "average_noisy_score"]
|
| 1029 |
return round_numeric(df[cols].sort_values("robustness_auc", ascending=False), NUMERIC_COLUMNS)
|
| 1030 |
|
| 1031 |
|
|
|
|
| 1055 |
text=df["method"],
|
| 1056 |
marker=dict(
|
| 1057 |
size=np.clip(df["peak_ram_gb"].fillna(1.0) * 4, 8, 26),
|
| 1058 |
+
color=df["hardware"].map({"CPU": "#E69F00", "GPU": TASK_COLOR}).fillna("#637381"),
|
| 1059 |
opacity=0.82,
|
| 1060 |
line=dict(color="#ffffff", width=1),
|
| 1061 |
),
|
|
|
|
| 1102 |
nshap = nshap[nshap["dataset"].astype(str) == str(dataset)].copy() if not nshap.empty else nshap
|
| 1103 |
if nshap.empty:
|
| 1104 |
neuron_fig = empty_figure("No neuron-influence results are available for this dataset.")
|
| 1105 |
+
table = pd.DataFrame(columns=["method", "baseline_score", "full_model_score", "neuron_influence_auc", "shap_mean_value", "shap_fraction_positive"])
|
| 1106 |
else:
|
| 1107 |
nshap = add_method_columns(nshap)
|
| 1108 |
nshap["auc"] = pd.to_numeric(nshap["auc"], errors="coerce")
|
|
|
|
| 1112 |
x=bar_df["auc"],
|
| 1113 |
y=bar_df["method"],
|
| 1114 |
orientation="h",
|
| 1115 |
+
marker=dict(color=INFLUENCE_COLOR),
|
| 1116 |
hovertemplate="Method=%{y}<br>AUC=%{x:.4f}<extra></extra>",
|
| 1117 |
)
|
| 1118 |
)
|
|
|
|
| 1122 |
fig_layout(neuron_fig, height=max(420, 25 * len(bar_df) + 150))
|
| 1123 |
table = nshap.rename(columns={"auc": "neuron_influence_auc"})
|
| 1124 |
table = table[
|
| 1125 |
+
["method", "baseline_score", "full_model_score", "neuron_influence_auc", "shap_mean_value", "shap_fraction_positive"]
|
| 1126 |
]
|
| 1127 |
|
| 1128 |
tshap = filter_models(active_rows(trial_shapley), models)
|
|
|
|
| 1138 |
x=trial_df["perturbation_auc"],
|
| 1139 |
y=trial_df["method"],
|
| 1140 |
orientation="h",
|
| 1141 |
+
marker=dict(color="#009E73"),
|
| 1142 |
hovertemplate="Method=%{y}<br>AUC=%{x:.4f}<extra></extra>",
|
| 1143 |
)
|
| 1144 |
)
|
|
|
|
| 1240 |
html.Div(
|
| 1241 |
[
|
| 1242 |
html.Div(
|
| 1243 |
+
dataframe_table("leaderboard-table", page_size=23, max_height="680px", sort_action="custom"),
|
| 1244 |
className="leaderboard-table-wrap",
|
| 1245 |
),
|
| 1246 |
dcc.Graph(id="dataset-ranking", config={"displayModeBar": False}),
|
|
|
|
| 1265 |
[
|
| 1266 |
html.Div(
|
| 1267 |
[
|
| 1268 |
+
dataframe_table("consistency-table", page_size=23, max_height="520px", sort_action="custom"),
|
| 1269 |
html.P("Click a method to update the 3D latent view.", className="table-hint"),
|
| 1270 |
],
|
| 1271 |
className="consistency-table-wrap",
|
|
|
|
| 1379 |
Output("performance-heatmap", "figure"),
|
| 1380 |
Input("dataset-filter", "value"),
|
| 1381 |
Input("model-filter", "value"),
|
| 1382 |
+
Input("leaderboard-table", "sort_by"),
|
| 1383 |
)
|
| 1384 |
+
def update_leaderboard(dataset: str, models: list[str] | None, sort_by: list[dict] | None):
|
| 1385 |
df = leaderboard_frame(dataset, models)
|
| 1386 |
visible_cols = [
|
| 1387 |
"rank",
|
| 1388 |
"method",
|
| 1389 |
"task_score",
|
|
|
|
| 1390 |
"robustness_auc",
|
| 1391 |
"alignment_score",
|
| 1392 |
"training_time_sec",
|
| 1393 |
"peak_ram_gb",
|
|
|
|
| 1394 |
]
|
| 1395 |
+
sorted_df = sort_table(df, sort_by, [("task_score", False), ("model_order", True)])
|
| 1396 |
+
table_df = sorted_df[[c for c in visible_cols + ["id", "model"] if c in sorted_df.columns]]
|
| 1397 |
return (
|
| 1398 |
leaderboard_summary(dataset, df),
|
| 1399 |
column_defs([c for c in visible_cols if c in table_df.columns]),
|
|
|
|
| 1412 |
Input("dataset-filter", "value"),
|
| 1413 |
Input("model-filter", "value"),
|
| 1414 |
Input("consistency-table", "active_cell"),
|
| 1415 |
+
Input("consistency-table", "sort_by"),
|
| 1416 |
)
|
| 1417 |
+
def update_consistency(dataset: str, models: list[str] | None, active_cell: dict | None, sort_by: list[dict] | None):
|
| 1418 |
df = consistency_frame(dataset, models)
|
| 1419 |
model = selected_consistency_model(df, active_cell)
|
| 1420 |
+
visible_cols = ["rank", "method", "alignment_score", "n_sessions", "latent_dim", "n_pairwise"]
|
| 1421 |
+
sorted_df = sort_table(df, sort_by, [("alignment_score", False), ("model_order", True)])
|
| 1422 |
+
table_df = sorted_df[[c for c in visible_cols + ["id", "model"] if c in sorted_df.columns]]
|
| 1423 |
return (
|
| 1424 |
column_defs([c for c in visible_cols if c in table_df.columns]),
|
| 1425 |
records(table_df),
|
assets/styles.css
CHANGED
|
@@ -163,7 +163,7 @@ h2 {
|
|
| 163 |
|
| 164 |
.tab-selected {
|
| 165 |
color: #12302f !important;
|
| 166 |
-
border-bottom-color: #
|
| 167 |
background: #ffffff !important;
|
| 168 |
}
|
| 169 |
|
|
|
|
| 163 |
|
| 164 |
.tab-selected {
|
| 165 |
color: #12302f !important;
|
| 166 |
+
border-bottom-color: #1565C0 !important;
|
| 167 |
background: #ffffff !important;
|
| 168 |
}
|
| 169 |
|