Spaces:
Sleeping
Sleeping
Marlin Lee commited on
Commit Β·
f84765f
1
Parent(s): f7be737
Sync explorer_app.py and clip_utils.py from main repo
Browse files- scripts/explorer_app.py +67 -8
scripts/explorer_app.py
CHANGED
|
@@ -557,6 +557,57 @@ def make_image_grid_html(images_info, title, cols=9):
|
|
| 557 |
return html
|
| 558 |
|
| 559 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
# ---------- UMAP data source ----------
|
| 561 |
# live_mask / live_indices / freq / mean_act / log_freq / umap_backup are all
|
| 562 |
# already set by _apply_dataset_globals(0) above β just build the source from them.
|
|
@@ -699,6 +750,7 @@ mean_heatmap_div = Div(text="", width=900)
|
|
| 699 |
mean_zoom_div = Div(text="", width=900)
|
| 700 |
p75_heatmap_div = Div(text="", width=900)
|
| 701 |
p75_zoom_div = Div(text="", width=900)
|
|
|
|
| 702 |
|
| 703 |
# Name editing widget (defined here so update_feature_display can reference it)
|
| 704 |
name_input = TextInput(
|
|
@@ -786,7 +838,8 @@ def update_feature_display(feature_idx):
|
|
| 786 |
'dead', f'Feature {feat} is dead β it never activated on the precompute set.')
|
| 787 |
for div in [top_heatmap_div, top_zoom_div,
|
| 788 |
mean_heatmap_div, mean_zoom_div,
|
| 789 |
-
p75_heatmap_div, p75_zoom_div
|
|
|
|
| 790 |
div.text = ""
|
| 791 |
return
|
| 792 |
|
|
@@ -879,6 +932,10 @@ def update_feature_display(feature_idx):
|
|
| 879 |
p75_zoom_div.text = make_image_grid_html(
|
| 880 |
p75_zm_infos, f"75th Percentile β Zoomed to peak patch (feature {feat})")
|
| 881 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 882 |
status_div.text = _status_html('ok', f'✓ Feature {feat} ready.')
|
| 883 |
_update_view_visibility()
|
| 884 |
|
|
@@ -888,13 +945,14 @@ def update_feature_display(feature_idx):
|
|
| 888 |
# ---------- View visibility ----------
|
| 889 |
def _update_view_visibility():
|
| 890 |
v = view_select.value
|
| 891 |
-
|
| 892 |
-
top_heatmap_div.visible
|
| 893 |
-
top_zoom_div.visible
|
| 894 |
-
mean_heatmap_div.visible =
|
| 895 |
-
mean_zoom_div.visible =
|
| 896 |
-
p75_heatmap_div.visible =
|
| 897 |
-
p75_zoom_div.visible =
|
|
|
|
| 898 |
|
| 899 |
view_select.on_change('value', lambda attr, old, new: _update_view_visibility())
|
| 900 |
_update_view_visibility() # set initial state
|
|
@@ -1727,6 +1785,7 @@ middle_panel = column(
|
|
| 1727 |
stats_div,
|
| 1728 |
name_panel,
|
| 1729 |
row(view_select, zoom_slider, heatmap_alpha_slider),
|
|
|
|
| 1730 |
top_heatmap_div, top_zoom_div,
|
| 1731 |
mean_heatmap_div, mean_zoom_div,
|
| 1732 |
p75_heatmap_div, p75_zoom_div,
|
|
|
|
| 557 |
return html
|
| 558 |
|
| 559 |
|
| 560 |
+
def make_compare_aggregations_html(top_infos, mean_infos, p75_infos, feat, n_each=5):
|
| 561 |
+
"""Paper-ready side-by-side comparison of Top / Mean / 75th-percentile aggregations.
|
| 562 |
+
|
| 563 |
+
Each method gets its own column with a styled header. Images are shown at a
|
| 564 |
+
reduced size so all three columns fit comfortably for a screenshot.
|
| 565 |
+
"""
|
| 566 |
+
col_thumb = min(THUMB, 160)
|
| 567 |
+
|
| 568 |
+
sections = [
|
| 569 |
+
("Top (Max Activation)", "#2563a8", top_infos),
|
| 570 |
+
("Mean Activation", "#1a7a4a", mean_infos),
|
| 571 |
+
("75th Percentile", "#7a3a9a", p75_infos),
|
| 572 |
+
]
|
| 573 |
+
|
| 574 |
+
html = (
|
| 575 |
+
'<div style="font-family:Arial,Helvetica,sans-serif;background:#ffffff;'
|
| 576 |
+
'padding:14px 16px 10px 16px;border:1px solid #d0d0d0;border-radius:6px;'
|
| 577 |
+
'display:inline-block;box-shadow:0 1px 4px rgba(0,0,0,0.08)">'
|
| 578 |
+
f'<div style="font-size:12px;color:#666;margin-bottom:10px;letter-spacing:0.2px">'
|
| 579 |
+
f'<b>Feature {feat}</b> β aggregation method comparison</div>'
|
| 580 |
+
'<div style="display:flex;gap:20px;align-items:flex-start">'
|
| 581 |
+
)
|
| 582 |
+
|
| 583 |
+
for method_name, color, infos in sections:
|
| 584 |
+
html += (
|
| 585 |
+
'<div style="min-width:0">'
|
| 586 |
+
f'<div style="background:{color};color:#ffffff;font-size:12px;font-weight:bold;'
|
| 587 |
+
f'text-align:center;padding:5px 14px;border-radius:4px;margin-bottom:8px;'
|
| 588 |
+
f'letter-spacing:0.5px">{method_name}</div>'
|
| 589 |
+
'<div style="display:flex;gap:6px;flex-wrap:wrap">'
|
| 590 |
+
)
|
| 591 |
+
shown = (infos or [])[:n_each]
|
| 592 |
+
if not shown:
|
| 593 |
+
html += '<div style="color:#aaa;font-style:italic;font-size:11px;padding:8px">No images</div>'
|
| 594 |
+
for img, caption in shown:
|
| 595 |
+
url = pil_to_data_url(img)
|
| 596 |
+
parts = caption.split('<br>')
|
| 597 |
+
cap_html = '<br>'.join(parts)
|
| 598 |
+
html += (
|
| 599 |
+
f'<div style="text-align:center">'
|
| 600 |
+
f'<img src="{url}" width="{col_thumb}" height="{col_thumb}"'
|
| 601 |
+
f' style="border:1px solid #ccc;border-radius:3px;display:block"/>'
|
| 602 |
+
f'<div style="font-size:9px;color:#555;margin-top:2px;line-height:1.35">'
|
| 603 |
+
f'{cap_html}</div></div>'
|
| 604 |
+
)
|
| 605 |
+
html += '</div></div>'
|
| 606 |
+
|
| 607 |
+
html += '</div></div>'
|
| 608 |
+
return html
|
| 609 |
+
|
| 610 |
+
|
| 611 |
# ---------- UMAP data source ----------
|
| 612 |
# live_mask / live_indices / freq / mean_act / log_freq / umap_backup are all
|
| 613 |
# already set by _apply_dataset_globals(0) above β just build the source from them.
|
|
|
|
| 750 |
mean_zoom_div = Div(text="", width=900)
|
| 751 |
p75_heatmap_div = Div(text="", width=900)
|
| 752 |
p75_zoom_div = Div(text="", width=900)
|
| 753 |
+
compare_agg_div = Div(text="", width=1400) # side-by-side aggregation comparison
|
| 754 |
|
| 755 |
# Name editing widget (defined here so update_feature_display can reference it)
|
| 756 |
name_input = TextInput(
|
|
|
|
| 838 |
'dead', f'Feature {feat} is dead β it never activated on the precompute set.')
|
| 839 |
for div in [top_heatmap_div, top_zoom_div,
|
| 840 |
mean_heatmap_div, mean_zoom_div,
|
| 841 |
+
p75_heatmap_div, p75_zoom_div,
|
| 842 |
+
compare_agg_div]:
|
| 843 |
div.text = ""
|
| 844 |
return
|
| 845 |
|
|
|
|
| 932 |
p75_zoom_div.text = make_image_grid_html(
|
| 933 |
p75_zm_infos, f"75th Percentile β Zoomed to peak patch (feature {feat})")
|
| 934 |
|
| 935 |
+
# Side-by-side aggregation comparison (paper-ready screenshot view)
|
| 936 |
+
compare_agg_div.text = make_compare_aggregations_html(
|
| 937 |
+
heatmap_infos, mean_hm_infos, p75_hm_infos, feat)
|
| 938 |
+
|
| 939 |
status_div.text = _status_html('ok', f'✓ Feature {feat} ready.')
|
| 940 |
_update_view_visibility()
|
| 941 |
|
|
|
|
| 945 |
# ---------- View visibility ----------
|
| 946 |
def _update_view_visibility():
|
| 947 |
v = view_select.value
|
| 948 |
+
is_compare = (v == "Compare aggregations")
|
| 949 |
+
top_heatmap_div.visible = (v == "Top (max activation)")
|
| 950 |
+
top_zoom_div.visible = (v == "Top (max activation)")
|
| 951 |
+
mean_heatmap_div.visible = (v == "Mean activation")
|
| 952 |
+
mean_zoom_div.visible = (v == "Mean activation")
|
| 953 |
+
p75_heatmap_div.visible = (v == "75th percentile")
|
| 954 |
+
p75_zoom_div.visible = (v == "75th percentile")
|
| 955 |
+
compare_agg_div.visible = is_compare
|
| 956 |
|
| 957 |
view_select.on_change('value', lambda attr, old, new: _update_view_visibility())
|
| 958 |
_update_view_visibility() # set initial state
|
|
|
|
| 1785 |
stats_div,
|
| 1786 |
name_panel,
|
| 1787 |
row(view_select, zoom_slider, heatmap_alpha_slider),
|
| 1788 |
+
compare_agg_div,
|
| 1789 |
top_heatmap_div, top_zoom_div,
|
| 1790 |
mean_heatmap_div, mean_zoom_div,
|
| 1791 |
p75_heatmap_div, p75_zoom_div,
|