Spaces:
Running
on
Zero
Running
on
Zero
Commit
·
805e5dd
1
Parent(s):
40c2708
fix: search tracks
Browse files
app.py
CHANGED
|
@@ -262,16 +262,44 @@ def _rank_search(query: str, names: list[str], limit: int) -> list[str]:
|
|
| 262 |
return out[:limit]
|
| 263 |
|
| 264 |
|
| 265 |
-
def search_bigwigs(species: str, query: str):
|
| 266 |
"""Search BigWig tracks and return formatted display names."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 267 |
names = _get_bigwig_names(species)
|
| 268 |
# Search in both track IDs and display names
|
| 269 |
metadata = _load_track_metadata()
|
| 270 |
-
query_lower =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
# Build list of (display_format, track_id) tuples for searching
|
| 273 |
track_display_pairs = []
|
| 274 |
for track_id in names:
|
|
|
|
|
|
|
|
|
|
| 275 |
display_name = metadata.get(track_id, track_id)
|
| 276 |
display_format = _format_track_for_display(track_id)
|
| 277 |
track_display_pairs.append((display_format, track_id, display_name))
|
|
@@ -284,9 +312,12 @@ def search_bigwigs(species: str, query: str):
|
|
| 284 |
query_lower in display_format.lower()):
|
| 285 |
matching.append(display_format)
|
| 286 |
|
| 287 |
-
# Limit results
|
| 288 |
results = matching[:SEARCH_MAX_RESULTS]
|
| 289 |
-
return
|
|
|
|
|
|
|
|
|
|
| 290 |
|
| 291 |
|
| 292 |
def add_selected(current_selected: list[str], to_add: list[str]):
|
|
@@ -304,13 +335,16 @@ def add_selected(current_selected: list[str], to_add: list[str]):
|
|
| 304 |
cur_ids.append(tid)
|
| 305 |
cur_display.append(_format_track_for_display(tid))
|
| 306 |
|
| 307 |
-
|
|
|
|
| 308 |
|
| 309 |
|
| 310 |
def remove_selected(current_selected: list[str], to_remove: list[str]):
|
| 311 |
"""Remove tracks from selected list."""
|
| 312 |
cur = [x for x in (current_selected or []) if x not in set(to_remove or [])]
|
| 313 |
-
|
|
|
|
|
|
|
| 314 |
|
| 315 |
|
| 316 |
def update_coords_on_species_change(species: str):
|
|
@@ -324,17 +358,25 @@ def reset_on_species_change(species: str):
|
|
| 324 |
track_ids = _get_bigwig_names(species) # warms cache if available
|
| 325 |
# Format available tracks for display
|
| 326 |
formatted_tracks = [_format_track_for_display(tid) for tid in track_ids]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
return (
|
| 328 |
gr.update(value=""), # query textbox
|
| 329 |
gr.update(choices=[], value=[]), # results list
|
| 330 |
-
gr.update(choices=formatted_tracks, value=
|
| 331 |
)
|
| 332 |
except (ValueError, AttributeError):
|
| 333 |
# Species doesn't have bigwigs, that's okay
|
| 334 |
return (
|
| 335 |
gr.update(value=""), # query textbox
|
| 336 |
gr.update(choices=[], value=[]), # results list
|
| 337 |
-
gr.update(choices=[], value=[]), # selected list
|
| 338 |
)
|
| 339 |
|
| 340 |
|
|
@@ -375,11 +417,11 @@ def predict(
|
|
| 375 |
if not seq or not seq.strip():
|
| 376 |
raise gr.Error("seq is required when use_coords=False")
|
| 377 |
inputs = {"seq": seq.strip(), "species": species}
|
| 378 |
-
|
| 379 |
# Verify species is in inputs before calling pipeline
|
| 380 |
if "species" not in inputs:
|
| 381 |
raise gr.Error(f"Internal error: species not found in inputs dict. Inputs: {list(inputs.keys())}")
|
| 382 |
-
|
| 383 |
out = pipe(inputs)
|
| 384 |
|
| 385 |
bw_names = out.bigwig_track_names or []
|
|
@@ -715,9 +757,9 @@ _init_bed_selected = [elem for elem in DEFAULT_BED_ELEMENTS if elem in _init_bed
|
|
| 715 |
# Default coordinates per species
|
| 716 |
DEFAULT_COORDS = {
|
| 717 |
"human": {"chrom": "chr19", "start": 6_700_000, "end": 6_831_072},
|
| 718 |
-
"mouse": {"chrom": "chr1", "start":
|
| 719 |
-
"drosophila_melanogaster": {"chrom": "chr2L", "start":
|
| 720 |
-
"arabidopsis_thaliana": {"chrom": "chr1", "start":
|
| 721 |
}
|
| 722 |
|
| 723 |
# Get default coordinates for default species
|
|
@@ -824,7 +866,7 @@ with gr.Blocks(title="NTv3 Tracks Demo") as demo:
|
|
| 824 |
|
| 825 |
# Get all available species from the pipeline
|
| 826 |
all_species = sorted(ASSEMBLY_TO_SPECIES.values())
|
| 827 |
-
|
| 828 |
with gr.Row():
|
| 829 |
species = gr.Dropdown(
|
| 830 |
choices=all_species,
|
|
@@ -909,6 +951,7 @@ with gr.Blocks(title="NTv3 Tracks Demo") as demo:
|
|
| 909 |
choices=_init_bigwig_selected,
|
| 910 |
value=_init_bigwig_selected,
|
| 911 |
label="Selected functional tracks (used for prediction)",
|
|
|
|
| 912 |
)
|
| 913 |
|
| 914 |
bigwig_query = gr.Textbox(
|
|
@@ -954,23 +997,132 @@ with gr.Blocks(title="NTv3 Tracks Demo") as demo:
|
|
| 954 |
|
| 955 |
# --- wiring (live search + auto-add) ---
|
| 956 |
|
| 957 |
-
# Live search on every keystroke
|
| 958 |
bigwig_query.input(
|
| 959 |
fn=search_bigwigs,
|
| 960 |
-
inputs=[species, bigwig_query],
|
| 961 |
-
outputs=[bigwig_results],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 962 |
)
|
| 963 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 964 |
# Auto-add: whenever user checks items in results, add them to Selected,
|
| 965 |
# then clear results selection (so it feels like "click to add")
|
| 966 |
-
def _auto_add(selected_now: list[str], results_checked: list[str]):
|
| 967 |
upd = add_selected(selected_now, results_checked) # reuses your function
|
| 968 |
-
#
|
| 969 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 970 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 971 |
bigwig_results.change(
|
| 972 |
-
fn=
|
| 973 |
-
inputs=[bigwig_selected, bigwig_results],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 974 |
outputs=[bigwig_selected, bigwig_results],
|
| 975 |
)
|
| 976 |
|
|
@@ -1011,10 +1163,19 @@ with gr.Blocks(title="NTv3 Tracks Demo") as demo:
|
|
| 1011 |
try:
|
| 1012 |
track_ids = _get_bigwig_names(species)
|
| 1013 |
formatted_tracks = [_format_track_for_display(tid) for tid in track_ids]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1014 |
except:
|
| 1015 |
formatted_tracks = []
|
|
|
|
|
|
|
| 1016 |
else:
|
| 1017 |
formatted_tracks = []
|
|
|
|
|
|
|
| 1018 |
|
| 1019 |
return (
|
| 1020 |
gr.update(visible=show_coords, value=coords["chrom"]),
|
|
@@ -1023,7 +1184,7 @@ with gr.Blocks(title="NTv3 Tracks Demo") as demo:
|
|
| 1023 |
gr.update(value=is_supported, visible=is_supported), # Show/hide and enable use_coords only if supported
|
| 1024 |
gr.update(visible=show_coords), # Show/hide the row
|
| 1025 |
gr.update(visible=not has_bigwigs), # Show "no tracks" message if no bigwigs
|
| 1026 |
-
gr.update(visible=
|
| 1027 |
gr.update(visible=has_bigwigs), # Show bigwig query if available
|
| 1028 |
gr.update(visible=has_bigwigs), # Show bigwig results if available
|
| 1029 |
gr.update(visible=has_bigwigs), # Show bigwig buttons if available
|
|
|
|
| 262 |
return out[:limit]
|
| 263 |
|
| 264 |
|
| 265 |
+
def search_bigwigs(species: str, query: str, current_selected: list[str]):
|
| 266 |
"""Search BigWig tracks and return formatted display names."""
|
| 267 |
+
# Handle None or empty query
|
| 268 |
+
if query is None:
|
| 269 |
+
query = ""
|
| 270 |
+
query_stripped = query.strip()
|
| 271 |
+
|
| 272 |
+
# If query is empty, return empty results immediately (don't show all tracks)
|
| 273 |
+
if not query_stripped:
|
| 274 |
+
displayed_selected = current_selected or []
|
| 275 |
+
show_selected = bool(displayed_selected)
|
| 276 |
+
return (
|
| 277 |
+
gr.update(choices=[], value=[], interactive=True), # empty results, explicitly clear checked state
|
| 278 |
+
gr.update(visible=show_selected, choices=displayed_selected, value=displayed_selected), # show ALL selected tracks
|
| 279 |
+
)
|
| 280 |
+
|
| 281 |
names = _get_bigwig_names(species)
|
| 282 |
# Search in both track IDs and display names
|
| 283 |
metadata = _load_track_metadata()
|
| 284 |
+
query_lower = query_stripped.lower()
|
| 285 |
+
|
| 286 |
+
# Show selected tracks section if user is typing or has selections
|
| 287 |
+
show_selected = bool(query_stripped) or bool(current_selected)
|
| 288 |
+
|
| 289 |
+
# Show ALL selected tracks (not limited to 20)
|
| 290 |
+
displayed_selected = current_selected or []
|
| 291 |
+
|
| 292 |
+
# Extract track IDs from already selected tracks (to exclude them from results)
|
| 293 |
+
selected_track_ids = set()
|
| 294 |
+
if current_selected:
|
| 295 |
+
selected_track_ids = {_extract_track_id(x) for x in current_selected}
|
| 296 |
|
| 297 |
# Build list of (display_format, track_id) tuples for searching
|
| 298 |
track_display_pairs = []
|
| 299 |
for track_id in names:
|
| 300 |
+
# Skip tracks that are already selected
|
| 301 |
+
if track_id in selected_track_ids:
|
| 302 |
+
continue
|
| 303 |
display_name = metadata.get(track_id, track_id)
|
| 304 |
display_format = _format_track_for_display(track_id)
|
| 305 |
track_display_pairs.append((display_format, track_id, display_name))
|
|
|
|
| 312 |
query_lower in display_format.lower()):
|
| 313 |
matching.append(display_format)
|
| 314 |
|
| 315 |
+
# Limit search results
|
| 316 |
results = matching[:SEARCH_MAX_RESULTS]
|
| 317 |
+
return (
|
| 318 |
+
gr.update(choices=results, value=[], interactive=True), # results - limited to SEARCH_MAX_RESULTS, explicitly clear checked state
|
| 319 |
+
gr.update(visible=show_selected, choices=displayed_selected, value=displayed_selected), # show ALL selected tracks
|
| 320 |
+
)
|
| 321 |
|
| 322 |
|
| 323 |
def add_selected(current_selected: list[str], to_add: list[str]):
|
|
|
|
| 335 |
cur_ids.append(tid)
|
| 336 |
cur_display.append(_format_track_for_display(tid))
|
| 337 |
|
| 338 |
+
# Show ALL selected tracks (no limit)
|
| 339 |
+
return gr.update(choices=cur_display, value=cur_display) # show all selected tracks
|
| 340 |
|
| 341 |
|
| 342 |
def remove_selected(current_selected: list[str], to_remove: list[str]):
|
| 343 |
"""Remove tracks from selected list."""
|
| 344 |
cur = [x for x in (current_selected or []) if x not in set(to_remove or [])]
|
| 345 |
+
# Show ALL remaining selected tracks (no limit)
|
| 346 |
+
show_selected = bool(cur)
|
| 347 |
+
return gr.update(choices=cur, value=cur, visible=show_selected)
|
| 348 |
|
| 349 |
|
| 350 |
def update_coords_on_species_change(species: str):
|
|
|
|
| 358 |
track_ids = _get_bigwig_names(species) # warms cache if available
|
| 359 |
# Format available tracks for display
|
| 360 |
formatted_tracks = [_format_track_for_display(tid) for tid in track_ids]
|
| 361 |
+
|
| 362 |
+
# Get default tracks for this species (filter to what's available)
|
| 363 |
+
default_track_ids = [tid for tid in DEFAULT_BIGWIG_TRACKS if tid in track_ids]
|
| 364 |
+
default_formatted = [_format_track_for_display(tid) for tid in default_track_ids]
|
| 365 |
+
|
| 366 |
+
# Show selected tracks section if there are default tracks
|
| 367 |
+
show_selected = bool(default_formatted)
|
| 368 |
+
|
| 369 |
return (
|
| 370 |
gr.update(value=""), # query textbox
|
| 371 |
gr.update(choices=[], value=[]), # results list
|
| 372 |
+
gr.update(choices=formatted_tracks, value=default_formatted, visible=show_selected), # selected list with defaults
|
| 373 |
)
|
| 374 |
except (ValueError, AttributeError):
|
| 375 |
# Species doesn't have bigwigs, that's okay
|
| 376 |
return (
|
| 377 |
gr.update(value=""), # query textbox
|
| 378 |
gr.update(choices=[], value=[]), # results list
|
| 379 |
+
gr.update(choices=[], value=[], visible=False), # selected list (hidden)
|
| 380 |
)
|
| 381 |
|
| 382 |
|
|
|
|
| 417 |
if not seq or not seq.strip():
|
| 418 |
raise gr.Error("seq is required when use_coords=False")
|
| 419 |
inputs = {"seq": seq.strip(), "species": species}
|
| 420 |
+
|
| 421 |
# Verify species is in inputs before calling pipeline
|
| 422 |
if "species" not in inputs:
|
| 423 |
raise gr.Error(f"Internal error: species not found in inputs dict. Inputs: {list(inputs.keys())}")
|
| 424 |
+
|
| 425 |
out = pipe(inputs)
|
| 426 |
|
| 427 |
bw_names = out.bigwig_track_names or []
|
|
|
|
| 757 |
# Default coordinates per species
|
| 758 |
DEFAULT_COORDS = {
|
| 759 |
"human": {"chrom": "chr19", "start": 6_700_000, "end": 6_831_072},
|
| 760 |
+
"mouse": {"chrom": "chr1", "start": 9_880_168, "end": 10_142_312},
|
| 761 |
+
"drosophila_melanogaster": {"chrom": "chr2L", "start": 6_700_000, "end": 6_831_072},
|
| 762 |
+
"arabidopsis_thaliana": {"chrom": "chr1", "start": 13_135_095, "end": 13_397_239},
|
| 763 |
}
|
| 764 |
|
| 765 |
# Get default coordinates for default species
|
|
|
|
| 866 |
|
| 867 |
# Get all available species from the pipeline
|
| 868 |
all_species = sorted(ASSEMBLY_TO_SPECIES.values())
|
| 869 |
+
|
| 870 |
with gr.Row():
|
| 871 |
species = gr.Dropdown(
|
| 872 |
choices=all_species,
|
|
|
|
| 951 |
choices=_init_bigwig_selected,
|
| 952 |
value=_init_bigwig_selected,
|
| 953 |
label="Selected functional tracks (used for prediction)",
|
| 954 |
+
visible=bool(_init_bigwig_selected), # Show if there are default tracks, otherwise hidden
|
| 955 |
)
|
| 956 |
|
| 957 |
bigwig_query = gr.Textbox(
|
|
|
|
| 997 |
|
| 998 |
# --- wiring (live search + auto-add) ---
|
| 999 |
|
| 1000 |
+
# Live search on every keystroke and when text changes (including deletion)
|
| 1001 |
bigwig_query.input(
|
| 1002 |
fn=search_bigwigs,
|
| 1003 |
+
inputs=[species, bigwig_query, bigwig_selected],
|
| 1004 |
+
outputs=[bigwig_results, bigwig_selected],
|
| 1005 |
+
)
|
| 1006 |
+
# Also trigger on change to catch deletions
|
| 1007 |
+
bigwig_query.change(
|
| 1008 |
+
fn=search_bigwigs,
|
| 1009 |
+
inputs=[species, bigwig_query, bigwig_selected],
|
| 1010 |
+
outputs=[bigwig_results, bigwig_selected],
|
| 1011 |
)
|
| 1012 |
|
| 1013 |
+
# Helper function to get search results choices directly (without gr.update wrapper)
|
| 1014 |
+
def _get_search_results_choices(species: str, query: str, current_selected: list[str]) -> list[str]:
|
| 1015 |
+
"""Get search results choices as a list, excluding selected tracks."""
|
| 1016 |
+
if query is None:
|
| 1017 |
+
query = ""
|
| 1018 |
+
query_stripped = query.strip()
|
| 1019 |
+
|
| 1020 |
+
if not query_stripped:
|
| 1021 |
+
return []
|
| 1022 |
+
|
| 1023 |
+
names = _get_bigwig_names(species)
|
| 1024 |
+
metadata = _load_track_metadata()
|
| 1025 |
+
query_lower = query_stripped.lower()
|
| 1026 |
+
|
| 1027 |
+
# Extract track IDs from already selected tracks
|
| 1028 |
+
selected_track_ids = set()
|
| 1029 |
+
if current_selected:
|
| 1030 |
+
selected_track_ids = {_extract_track_id(x) for x in current_selected}
|
| 1031 |
+
|
| 1032 |
+
# Build and filter results
|
| 1033 |
+
matching = []
|
| 1034 |
+
for track_id in names:
|
| 1035 |
+
if track_id in selected_track_ids:
|
| 1036 |
+
continue
|
| 1037 |
+
display_name = metadata.get(track_id, track_id)
|
| 1038 |
+
display_format = _format_track_for_display(track_id)
|
| 1039 |
+
if (query_lower in track_id.lower() or
|
| 1040 |
+
query_lower in display_name.lower() or
|
| 1041 |
+
query_lower in display_format.lower()):
|
| 1042 |
+
matching.append(display_format)
|
| 1043 |
+
|
| 1044 |
+
return matching[:SEARCH_MAX_RESULTS]
|
| 1045 |
+
|
| 1046 |
# Auto-add: whenever user checks items in results, add them to Selected,
|
| 1047 |
# then clear results selection (so it feels like "click to add")
|
| 1048 |
+
def _auto_add(selected_now: list[str], results_checked: list[str], current_query: str, current_results: list[str], current_species: str):
|
| 1049 |
upd = add_selected(selected_now, results_checked) # reuses your function
|
| 1050 |
+
# Show selected tracks section if there are selections
|
| 1051 |
+
show_selected = bool(upd["value"])
|
| 1052 |
+
|
| 1053 |
+
# Get the new search results choices directly (excluding all selected tracks)
|
| 1054 |
+
new_choices = _get_search_results_choices(current_species, current_query, upd["value"])
|
| 1055 |
+
|
| 1056 |
+
# Create a completely fresh update with explicit empty value to prevent any checked state
|
| 1057 |
+
# Force Gradio to clear checked state by explicitly setting value to empty list
|
| 1058 |
+
# Use a workaround: set choices to empty first, then to new_choices to force a complete refresh
|
| 1059 |
+
# But since we can only return one update, we'll ensure value is explicitly empty
|
| 1060 |
+
# and that we're not preserving any state from the previous update
|
| 1061 |
+
|
| 1062 |
+
# Ensure no items from results_checked are in new_choices (they should already be filtered, but double-check)
|
| 1063 |
+
checked_track_ids = {_extract_track_id(x) for x in results_checked}
|
| 1064 |
+
new_choices_filtered = [c for c in new_choices if _extract_track_id(c) not in checked_track_ids]
|
| 1065 |
+
|
| 1066 |
+
# Create update with explicit empty value - this should force Gradio to clear all checked items
|
| 1067 |
+
fresh_update = gr.update(
|
| 1068 |
+
choices=new_choices_filtered,
|
| 1069 |
+
value=[], # CRITICAL: Explicitly empty list to clear all checked state
|
| 1070 |
+
)
|
| 1071 |
+
|
| 1072 |
+
return gr.update(**upd, visible=show_selected), fresh_update
|
| 1073 |
|
| 1074 |
+
# Use a wrapper that ensures results are cleared before updating
|
| 1075 |
+
def _auto_add_wrapper(selected_now: list[str], results_checked: list[str], current_query: str, current_results: list[str], current_species: str):
|
| 1076 |
+
# First, get the updates
|
| 1077 |
+
selected_update, results_update = _auto_add(selected_now, results_checked, current_query, current_results, current_species)
|
| 1078 |
+
|
| 1079 |
+
# Force the results update to have an explicit empty value
|
| 1080 |
+
# Extract choices from results_update if it's a dict-like object
|
| 1081 |
+
if isinstance(results_update, dict):
|
| 1082 |
+
results_choices = results_update.get("choices", [])
|
| 1083 |
+
else:
|
| 1084 |
+
# If it's a gr.update object, we need to access it differently
|
| 1085 |
+
# Try to get choices from the update
|
| 1086 |
+
try:
|
| 1087 |
+
results_choices = results_update.choices if hasattr(results_update, 'choices') else []
|
| 1088 |
+
except:
|
| 1089 |
+
# Fallback: get choices from the search function directly
|
| 1090 |
+
results_choices = _get_search_results_choices(
|
| 1091 |
+
current_species,
|
| 1092 |
+
current_query,
|
| 1093 |
+
selected_now + results_checked if isinstance(selected_now, list) and isinstance(results_checked, list) else []
|
| 1094 |
+
)
|
| 1095 |
+
|
| 1096 |
+
# Create a completely fresh update with explicit empty value
|
| 1097 |
+
# This should force Gradio to clear all checked items
|
| 1098 |
+
fresh_results_update = gr.update(choices=results_choices, value=[])
|
| 1099 |
+
|
| 1100 |
+
return selected_update, fresh_results_update
|
| 1101 |
+
|
| 1102 |
bigwig_results.change(
|
| 1103 |
+
fn=_auto_add_wrapper,
|
| 1104 |
+
inputs=[bigwig_selected, bigwig_results, bigwig_query, bigwig_results, species],
|
| 1105 |
+
outputs=[bigwig_selected, bigwig_results],
|
| 1106 |
+
)
|
| 1107 |
+
|
| 1108 |
+
# Update selected tracks immediately when user unchecks items
|
| 1109 |
+
def _update_selected_tracks(selected_value: list[str], current_query: str, current_species: str):
|
| 1110 |
+
"""Update selected tracks when user checks/unchecks items directly."""
|
| 1111 |
+
# selected_value contains only the currently checked items
|
| 1112 |
+
# Update choices to match the current selections (so unchecked items are removed)
|
| 1113 |
+
show_selected = bool(selected_value)
|
| 1114 |
+
|
| 1115 |
+
# Also update search results to reflect the new selection (tracks that were unchecked can now appear in results)
|
| 1116 |
+
search_updates = search_bigwigs(current_species, current_query, selected_value)
|
| 1117 |
+
|
| 1118 |
+
return (
|
| 1119 |
+
gr.update(choices=selected_value, value=selected_value, visible=show_selected), # Update selected tracks
|
| 1120 |
+
search_updates[0], # Update search results
|
| 1121 |
+
)
|
| 1122 |
+
|
| 1123 |
+
bigwig_selected.change(
|
| 1124 |
+
fn=_update_selected_tracks,
|
| 1125 |
+
inputs=[bigwig_selected, bigwig_query, species],
|
| 1126 |
outputs=[bigwig_selected, bigwig_results],
|
| 1127 |
)
|
| 1128 |
|
|
|
|
| 1163 |
try:
|
| 1164 |
track_ids = _get_bigwig_names(species)
|
| 1165 |
formatted_tracks = [_format_track_for_display(tid) for tid in track_ids]
|
| 1166 |
+
# Get default tracks for this species (filter to what's available)
|
| 1167 |
+
default_track_ids = [tid for tid in DEFAULT_BIGWIG_TRACKS if tid in track_ids]
|
| 1168 |
+
default_formatted = [_format_track_for_display(tid) for tid in default_track_ids]
|
| 1169 |
+
# Show selected tracks section if there are default tracks
|
| 1170 |
+
show_selected_tracks = bool(default_formatted)
|
| 1171 |
except:
|
| 1172 |
formatted_tracks = []
|
| 1173 |
+
default_formatted = []
|
| 1174 |
+
show_selected_tracks = False
|
| 1175 |
else:
|
| 1176 |
formatted_tracks = []
|
| 1177 |
+
default_formatted = []
|
| 1178 |
+
show_selected_tracks = False
|
| 1179 |
|
| 1180 |
return (
|
| 1181 |
gr.update(visible=show_coords, value=coords["chrom"]),
|
|
|
|
| 1184 |
gr.update(value=is_supported, visible=is_supported), # Show/hide and enable use_coords only if supported
|
| 1185 |
gr.update(visible=show_coords), # Show/hide the row
|
| 1186 |
gr.update(visible=not has_bigwigs), # Show "no tracks" message if no bigwigs
|
| 1187 |
+
gr.update(visible=show_selected_tracks, choices=formatted_tracks, value=default_formatted), # Show bigwig selection with defaults if available
|
| 1188 |
gr.update(visible=has_bigwigs), # Show bigwig query if available
|
| 1189 |
gr.update(visible=has_bigwigs), # Show bigwig results if available
|
| 1190 |
gr.update(visible=has_bigwigs), # Show bigwig buttons if available
|