josephsoo commited on
Commit
a303a1e
·
1 Parent(s): 6554c13

Tighten leaderboard sorting and colors

Browse files
Files changed (2) hide show
  1. app.py +118 -49
  2. 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
- SCORE_SCALE = [[0.0, "#9f3a38"], [0.5, "#f3efe4"], [1.0, "#006d77"]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  CATEGORICAL_PALETTE = [
163
- "#0072B2",
164
  "#E69F00",
165
- "#009E73",
166
- "#CC79A7",
167
- "#D55E00",
168
  "#56B4E9",
 
169
  "#F0E442",
170
- "#6A3D9A",
171
- "#8C564B",
172
- "#4E79A7",
173
- "#59A14F",
174
- "#AF7AA1",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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="native",
 
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 = table_df.dropna(subset=["task_score"]).head(3)
 
 
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 = leaderboard_frame(dataset, models)
 
 
 
 
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="#006d77"),
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 = df.dropna(subset=["alignment_score"])
 
 
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="#4c908b"),
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=SCORE_SCALE,
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
- condition_colors = {
761
- condition: CATEGORICAL_PALETTE[idx % len(CATEGORICAL_PALETTE)]
762
- for idx, condition in enumerate(condition_values)
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="Viridis",
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", "metric", "reference_score", "highest_noise_score", "robustness_auc", "average_noisy_score"])
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", "metric", "reference_score", "highest_noise_score", "robustness_auc", "average_noisy_score"]
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": "#8a6f2a", "GPU": "#006d77"}).fillna("#637381"),
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", "metric", "baseline_score", "full_model_score", "neuron_influence_auc", "shap_mean_value", "shap_fraction_positive"])
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="#006d77"),
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", "metric", "baseline_score", "full_model_score", "neuron_influence_auc", "shap_mean_value", "shap_fraction_positive"]
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="#8a6f2a"),
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
- table_df = df[[c for c in visible_cols + ["id", "model"] if c in df.columns]]
 
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", "notes"]
1353
- table_df = df[[c for c in visible_cols + ["id", "model"] if c in df.columns]]
 
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: #006d77 !important;
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