File size: 2,882 Bytes
d77e99f
 
 
 
 
 
a544a50
bfe80c5
d77e99f
 
bfe80c5
d77e99f
 
 
 
 
 
 
 
a544a50
 
 
d77e99f
 
 
a544a50
 
 
 
 
 
 
 
 
 
 
d77e99f
 
 
a544a50
d77e99f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a544a50
 
d77e99f
 
a544a50
d77e99f
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""Reusable UI components."""

from __future__ import annotations

import gradio as gr

from stroke_deepisles_demo.core.config import get_settings
from stroke_deepisles_demo.core.logging import get_logger
from stroke_deepisles_demo.data import list_case_ids

logger = get_logger(__name__)


def create_case_selector() -> gr.Dropdown:
    """
    Create a dropdown for selecting cases.

    Returns:
        Configured gr.Dropdown component

    Raises:
        RuntimeError: If case IDs cannot be loaded (no silent fallback)
    """
    try:
        case_ids = list_case_ids()
    except FileNotFoundError as e:
        # Data directory not found - fail loudly with helpful message
        logger.error("Data directory not found: %s", e)
        raise RuntimeError("ISLES24 data not found. Please run: uv run stroke-demo download") from e
    except Exception as e:
        # Unexpected error - fail loudly, don't mask with fake dropdown option
        logger.exception("Failed to load case IDs")
        raise RuntimeError(f"Failed to load case IDs: {e}") from e

    if not case_ids:
        raise RuntimeError("No cases found in dataset. Please verify data directory structure.")

    return gr.Dropdown(
        choices=case_ids,
        value=case_ids[0],
        label="Select Case",
        info="Choose a case from ISLES24-MR-Lite",
        filterable=True,
    )


def create_results_display() -> dict[str, gr.components.Component]:
    """
    Create results display components.

    Returns:
        Dictionary of component name -> gr.Component
    """
    # Using gr.Group to group them visually
    with gr.Group():
        # NiiVue visualization uses HTML
        niivue_viewer = gr.HTML(label="Interactive 3D Viewer")

        # Slice comparisons (Matplotlib)
        slice_plot = gr.Plot(label="Slice Comparison")

        metrics = gr.JSON(label="Metrics")
        download = gr.File(label="Download Prediction")

    return {
        "niivue_viewer": niivue_viewer,
        "slice_plot": slice_plot,
        "metrics": metrics,
        "download": download,
    }


def create_settings_accordion() -> dict[str, gr.components.Component]:
    """
    Create expandable settings section.

    Returns:
        Dictionary of setting name -> gr.Component
    """
    settings = get_settings()

    with gr.Accordion("Advanced Settings", open=False):
        fast_mode = gr.Checkbox(
            value=settings.deepisles_fast_mode,
            label="Fast Mode (SEALS)",
            info="Run SEALS only (ISLES'22 winner, requires DWI+ADC). Disable for full ensemble (requires FLAIR).",
        )
        show_ground_truth = gr.Checkbox(
            value=True,
            label="Show Ground Truth",
            info="Display ground truth mask if available",
        )

    return {
        "fast_mode": fast_mode,
        "show_ground_truth": show_ground_truth,
    }