richiam commited on
Commit
89f50ed
Β·
verified Β·
1 Parent(s): 913fa02

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +90 -30
app.py CHANGED
@@ -661,9 +661,9 @@ def proteins_tab():
661
  def clustering_tab():
662
  return dbc.Container([
663
  dbc.Row([
664
- make_dropdown("Model", "dd-model", MODELS, value="cambridgeltl__SapBERT-from-PubMedBERT-fulltext" if "cambridgeltl__SapBERT-from-PubMedBERT-fulltext" in MODELS else (MODELS[0] if MODELS else None)),
665
  make_dropdown("Min community size", "dd-min", MINS, value="2" if "2" in MINS else (MINS[0] if MINS else None)),
666
- make_dropdown("Threshold", "dd-threshold", THRESHOLDS, value="0.8" if "0.8" in THRESHOLDS else (THRESHOLDS[0] if THRESHOLDS else None)),
667
  make_dropdown("Field", "dd-field", CLUSTER_FIELDS, value="organism_source" if "organism_source" in CLUSTER_FIELDS else (CLUSTER_FIELDS[0] if CLUSTER_FIELDS else None)),
668
  ], className="mb-3 g-3"),
669
  dbc.Row([
@@ -766,17 +766,25 @@ _METRIC_LABELS = {
766
  }
767
 
768
 
769
- def _build_grid_summary_figure():
770
- """Heatmap of mean silhouette (all fields Γ— all min-sizes) per (model, threshold)."""
 
 
 
771
  if METRICS_DF.empty:
772
  return go.Figure()
773
 
774
  def _short(m):
775
  return m.split("__")[-1] if "__" in m else m
776
 
 
 
 
 
 
 
777
  agg = (
778
- METRICS_DF
779
- .dropna(subset=["silhouette_cosine"])
780
  .groupby(["model", "threshold"])["silhouette_cosine"]
781
  .mean()
782
  .reset_index()
@@ -823,10 +831,11 @@ def _build_grid_summary_figure():
823
  hovertemplate="Model: %{y}<br>Threshold: %{x}<br>Mean silhouette: %{z:.3f}<extra></extra>",
824
  ))
825
 
 
826
  n_models = len(pivot.index)
827
  fig.update_layout(
828
  title=dict(
829
- text="Grid Search Overview β€” Mean Silhouette (all fields & min-sizes) β˜… = best",
830
  font=dict(size=13),
831
  ),
832
  xaxis=dict(title="Threshold", type="category", tickfont=dict(size=11)),
@@ -839,21 +848,39 @@ def _build_grid_summary_figure():
839
  return fig
840
 
841
 
 
 
 
 
 
 
842
  def grid_metrics_tab():
843
  if METRICS_DF.empty:
844
  return dbc.Container([html.P("No metrics data found.", className="text-muted mt-3")])
845
 
846
- summary_fig = _build_grid_summary_figure()
847
-
848
  return dbc.Container([
849
- # ── Grid search overview (static, built at startup) ────────────────────
850
  dbc.Card([
851
  dbc.CardBody([
852
- dcc.Graph(
853
- figure=summary_fig,
854
- config={"displayModeBar": True,
855
- "toImageButtonOptions": {"format": "svg", "filename": "grid_search_summary"}},
856
- style={"height": f"{summary_fig.layout.height}px"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
857
  ),
858
  ], className="p-2"),
859
  ], className="mb-3 shadow-sm border-0"),
@@ -1379,19 +1406,24 @@ def readme_tab():
1379
 
1380
  # ── Clustering Explorer ───────────────────────��───────────────────
1381
  dbc.AccordionItem(title="Clustering Explorer", children=[
1382
- html.P(
1383
  "Explore semantic clusters of extracted field values. Embeddings are computed "
1384
  "with biomedical language models; community detection groups semantically similar "
1385
  "entries into clusters. All plots are rendered natively in Plotly β€” hover, zoom, "
1386
- "and pan are fully interactive.",
 
 
 
 
1387
  className="mb-3",
1388
  ),
1389
  html.H6("Parameter dropdowns", className="fw-bold"),
1390
  dbc.ListGroup([
1391
  dbc.ListGroupItem([
1392
  html.Span("Model ", className="fw-semibold"),
1393
- "Sentence-embedding model used to encode field values "
1394
- "(e.g. PubMedBERT, BioBERT, SapBERT).",
 
1395
  ]),
1396
  dbc.ListGroupItem([
1397
  html.Span("Min community size ", className="fw-semibold"),
@@ -1399,7 +1431,8 @@ def readme_tab():
1399
  ]),
1400
  dbc.ListGroupItem([
1401
  html.Span("Threshold ", className="fw-semibold"),
1402
- "Cosine similarity threshold for cluster membership. Higher = tighter clusters.",
 
1403
  ]),
1404
  dbc.ListGroupItem([
1405
  html.Span("Field ", className="fw-semibold"),
@@ -1426,6 +1459,15 @@ def readme_tab():
1426
  "common cluster labels for the selected cross-filter field and current "
1427
  "model / threshold settings.",
1428
  ]),
 
 
 
 
 
 
 
 
 
1429
  ], flush=True, className="mb-3"),
1430
  html.H6("UMAP cluster plot", className="fw-bold mt-2"),
1431
  dbc.ListGroup([
@@ -1466,11 +1508,22 @@ def readme_tab():
1466
  dbc.AccordionItem(title="Grid Metrics", children=[
1467
  html.P(
1468
  "Interactive charts comparing clustering quality across all combinations of "
1469
- "embedding model, similarity threshold, and min community size. "
 
1470
  "Loaded from the pre-computed metrics CSVs at startup.",
1471
  className="mb-3",
1472
  ),
1473
- html.H6("Controls", className="fw-bold"),
 
 
 
 
 
 
 
 
 
 
1474
  dbc.ListGroup([
1475
  dbc.ListGroupItem([
1476
  html.Span("Field ", className="fw-semibold"),
@@ -1488,21 +1541,20 @@ def readme_tab():
1488
  ], className="mb-0 mt-1"),
1489
  ]),
1490
  dbc.ListGroupItem([
1491
- html.Span("Model ", className="fw-semibold"),
1492
- "Filter the model-comparison bar chart to a single embedding model, "
1493
- "or select \"All\" to compare all models side by side.",
1494
  ]),
1495
  ], flush=True, className="mb-3"),
1496
- html.H6("Charts", className="fw-bold mt-2"),
1497
  dbc.ListGroup([
1498
  dbc.ListGroupItem([
1499
- html.Span("Heatmap ", className="fw-semibold"),
1500
- "Threshold (x) vs min community size (y) coloured by the selected metric. "
1501
- "Hover to see exact values.",
1502
  ]),
1503
  dbc.ListGroupItem([
1504
  html.Span("Model comparison bar chart ", className="fw-semibold"),
1505
- "Average metric value per model across all parameter combinations.",
1506
  ]),
1507
  dbc.ListGroupItem([
1508
  html.Span("Top-10 configurations table ", className="fw-semibold"),
@@ -2502,6 +2554,14 @@ def download_cluster_table(n_clicks, rows):
2502
  return dcc.send_data_frame(pd.DataFrame(rows).to_csv, "cluster_proteins.csv", index=False)
2503
 
2504
 
 
 
 
 
 
 
 
 
2505
  @app.callback(
2506
  Output("metrics-table-container", "children"),
2507
  Input("dd-model", "value"),
 
661
  def clustering_tab():
662
  return dbc.Container([
663
  dbc.Row([
664
+ make_dropdown("Model", "dd-model", MODELS, value="kamalkraj__BioSimCSE-BioLinkBERT-BASE" if "kamalkraj__BioSimCSE-BioLinkBERT-BASE" in MODELS else (MODELS[0] if MODELS else None)),
665
  make_dropdown("Min community size", "dd-min", MINS, value="2" if "2" in MINS else (MINS[0] if MINS else None)),
666
+ make_dropdown("Threshold", "dd-threshold", THRESHOLDS, value="0.9" if "0.9" in THRESHOLDS else (THRESHOLDS[0] if THRESHOLDS else None)),
667
  make_dropdown("Field", "dd-field", CLUSTER_FIELDS, value="organism_source" if "organism_source" in CLUSTER_FIELDS else (CLUSTER_FIELDS[0] if CLUSTER_FIELDS else None)),
668
  ], className="mb-3 g-3"),
669
  dbc.Row([
 
766
  }
767
 
768
 
769
+ def _build_grid_summary_figure(field=None):
770
+ """Heatmap of mean silhouette per (model, threshold).
771
+ field=None or '__global__' β†’ average over all fields and min-sizes.
772
+ field='elution_buffer' etc. β†’ restrict to that field only.
773
+ """
774
  if METRICS_DF.empty:
775
  return go.Figure()
776
 
777
  def _short(m):
778
  return m.split("__")[-1] if "__" in m else m
779
 
780
+ src = METRICS_DF.dropna(subset=["silhouette_cosine"])
781
+ if field and field != "__global__":
782
+ src = src[src["field"] == field]
783
+ if src.empty:
784
+ return go.Figure()
785
+
786
  agg = (
787
+ src
 
788
  .groupby(["model", "threshold"])["silhouette_cosine"]
789
  .mean()
790
  .reset_index()
 
831
  hovertemplate="Model: %{y}<br>Threshold: %{x}<br>Mean silhouette: %{z:.3f}<extra></extra>",
832
  ))
833
 
834
+ field_label = "Global (mean over all fields)" if (not field or field == "__global__") else field.replace("_", " ").title()
835
  n_models = len(pivot.index)
836
  fig.update_layout(
837
  title=dict(
838
+ text=f"Grid Search Overview β€” Mean Silhouette Β· {field_label} β˜… = best",
839
  font=dict(size=13),
840
  ),
841
  xaxis=dict(title="Threshold", type="category", tickfont=dict(size=11)),
 
848
  return fig
849
 
850
 
851
+ _SUMMARY_FIELD_OPTIONS = (
852
+ [{"label": "Global (mean over all fields)", "value": "__global__"}]
853
+ + [{"label": f.replace("_", " ").title(), "value": f} for f in sorted(METRIC_FIELDS)]
854
+ )
855
+
856
+
857
  def grid_metrics_tab():
858
  if METRICS_DF.empty:
859
  return dbc.Container([html.P("No metrics data found.", className="text-muted mt-3")])
860
 
 
 
861
  return dbc.Container([
862
+ # ── Grid search overview (callback-driven) ────────────────────────────
863
  dbc.Card([
864
  dbc.CardBody([
865
+ dbc.Row([
866
+ dbc.Col([
867
+ html.Label("View by field", className="fw-semibold small mb-1"),
868
+ dcc.Dropdown(
869
+ id="dd-summary-field",
870
+ options=_SUMMARY_FIELD_OPTIONS,
871
+ value="__global__",
872
+ clearable=False,
873
+ style={"fontSize": "13px"},
874
+ ),
875
+ ], width=4),
876
+ ], className="mb-2"),
877
+ dcc.Loading(
878
+ dcc.Graph(
879
+ id="metrics-summary-graph",
880
+ config={"displayModeBar": True,
881
+ "toImageButtonOptions": {"format": "svg", "filename": "grid_search_summary"}},
882
+ ),
883
+ type="circle", color="#1a73e8",
884
  ),
885
  ], className="p-2"),
886
  ], className="mb-3 shadow-sm border-0"),
 
1406
 
1407
  # ── Clustering Explorer ───────────────────────��───────────────────
1408
  dbc.AccordionItem(title="Clustering Explorer", children=[
1409
+ html.P([
1410
  "Explore semantic clusters of extracted field values. Embeddings are computed "
1411
  "with biomedical language models; community detection groups semantically similar "
1412
  "entries into clusters. All plots are rendered natively in Plotly β€” hover, zoom, "
1413
+ "and pan are fully interactive. ",
1414
+ html.Span("Recommended settings: ", className="fw-semibold"),
1415
+ "Model = BioSimCSE-BioLinkBERT-BASE, Threshold = 0.9, Min community size = 2 "
1416
+ "(best mean silhouette across all fields).",
1417
+ ],
1418
  className="mb-3",
1419
  ),
1420
  html.H6("Parameter dropdowns", className="fw-bold"),
1421
  dbc.ListGroup([
1422
  dbc.ListGroupItem([
1423
  html.Span("Model ", className="fw-semibold"),
1424
+ "Sentence-embedding model used to encode field values. "
1425
+ "BioSimCSE-BioLinkBERT-BASE achieves the highest mean silhouette (0.899) "
1426
+ "and is selected by default.",
1427
  ]),
1428
  dbc.ListGroupItem([
1429
  html.Span("Min community size ", className="fw-semibold"),
 
1431
  ]),
1432
  dbc.ListGroupItem([
1433
  html.Span("Threshold ", className="fw-semibold"),
1434
+ "Cosine similarity threshold for cluster membership. Higher = tighter clusters. "
1435
+ "0.9 is the recommended value for BioSimCSE.",
1436
  ]),
1437
  dbc.ListGroupItem([
1438
  html.Span("Field ", className="fw-semibold"),
 
1459
  "common cluster labels for the selected cross-filter field and current "
1460
  "model / threshold settings.",
1461
  ]),
1462
+ dbc.ListGroupItem([
1463
+ html.Span("Filter by publication era ", className="fw-semibold"),
1464
+ "Restrict all clusters to papers published in a specific time window "
1465
+ "(approximated from PMID ranges: pre-2001 through 2021–2023). "
1466
+ "Leave blank to include all time periods. "
1467
+ "Use this to explore how purification practices evolved over time β€” "
1468
+ "for example, set Field = Induction Temperature and step through eras "
1469
+ "to see the shift from 37 Β°C to low-temperature induction.",
1470
+ ]),
1471
  ], flush=True, className="mb-3"),
1472
  html.H6("UMAP cluster plot", className="fw-bold mt-2"),
1473
  dbc.ListGroup([
 
1508
  dbc.AccordionItem(title="Grid Metrics", children=[
1509
  html.P(
1510
  "Interactive charts comparing clustering quality across all combinations of "
1511
+ "embedding model, similarity threshold, and min community size "
1512
+ "(14 models Γ— 5 thresholds Γ— 5 min-sizes). "
1513
  "Loaded from the pre-computed metrics CSVs at startup.",
1514
  className="mb-3",
1515
  ),
1516
+ html.H6("Grid Search Overview heatmap", className="fw-bold"),
1517
+ html.P([
1518
+ "The top heatmap shows mean silhouette score for every (model, threshold) pair. "
1519
+ "Rows are sorted by best score; the best cell is marked β˜…. "
1520
+ "Use the ",
1521
+ html.Span("View by field ", className="fw-semibold"),
1522
+ "dropdown to switch between a global view (mean over all fields and min-sizes) "
1523
+ "and any individual extraction field (e.g. Elution Buffer, Induction Temperature). "
1524
+ "The figure can be downloaded as SVG via the camera icon.",
1525
+ ], className="mb-3"),
1526
+ html.H6("Detailed view controls", className="fw-bold"),
1527
  dbc.ListGroup([
1528
  dbc.ListGroupItem([
1529
  html.Span("Field ", className="fw-semibold"),
 
1541
  ], className="mb-0 mt-1"),
1542
  ]),
1543
  dbc.ListGroupItem([
1544
+ html.Span("Model (heatmap) ", className="fw-semibold"),
1545
+ "Select the embedding model shown in the threshold Γ— min-size heatmap below.",
 
1546
  ]),
1547
  ], flush=True, className="mb-3"),
1548
+ html.H6("Detailed charts", className="fw-bold mt-2"),
1549
  dbc.ListGroup([
1550
  dbc.ListGroupItem([
1551
+ html.Span("Threshold Γ— min-size heatmap ", className="fw-semibold"),
1552
+ "For the selected model and field: threshold (x) vs min community size (y) "
1553
+ "coloured by the chosen metric. Hover to see exact values.",
1554
  ]),
1555
  dbc.ListGroupItem([
1556
  html.Span("Model comparison bar chart ", className="fw-semibold"),
1557
+ "Best metric value per model for the selected field, across all parameter combos.",
1558
  ]),
1559
  dbc.ListGroupItem([
1560
  html.Span("Top-10 configurations table ", className="fw-semibold"),
 
2554
  return dcc.send_data_frame(pd.DataFrame(rows).to_csv, "cluster_proteins.csv", index=False)
2555
 
2556
 
2557
+ @app.callback(
2558
+ Output("metrics-summary-graph", "figure"),
2559
+ Input("dd-summary-field", "value"),
2560
+ )
2561
+ def update_summary_graph(field):
2562
+ return _build_grid_summary_figure(field)
2563
+
2564
+
2565
  @app.callback(
2566
  Output("metrics-table-container", "children"),
2567
  Input("dd-model", "value"),