Upload folder using huggingface_hub
Browse files
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="
|
| 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.
|
| 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
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 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
|
| 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 (
|
| 850 |
dbc.Card([
|
| 851 |
dbc.CardBody([
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
"
|
|
|
|
| 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("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
"
|
| 1493 |
-
"or select \"All\" to compare all models side by side.",
|
| 1494 |
]),
|
| 1495 |
], flush=True, className="mb-3"),
|
| 1496 |
-
html.H6("
|
| 1497 |
dbc.ListGroup([
|
| 1498 |
dbc.ListGroupItem([
|
| 1499 |
-
html.Span("
|
| 1500 |
-
"
|
| 1501 |
-
"Hover to see exact values.",
|
| 1502 |
]),
|
| 1503 |
dbc.ListGroupItem([
|
| 1504 |
html.Span("Model comparison bar chart ", className="fw-semibold"),
|
| 1505 |
-
"
|
| 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"),
|