Arviano's picture
update: update presentation view button
5b27f23
Raw History Blame Contribute Delete
27.1 kB
import json
from pathlib import Path
from typing import Any
import gradio as gr
from src.inference import (
CASE_OPTIONS,
DEFAULT_CASE_NAME,
DEFAULT_GRADCAM_TARGET_LAYER,
DEVICE,
GRADCAM_TARGET_LAYER_OPTIONS,
batch_predict_with_xdl_stream,
)
from src.utils import clean_drive_downloads, normalize_uploaded_paths
UI_DEFAULTS_PATH = Path(__file__).resolve().parent.parent / "config" / "ui_defaults.json"
UI_DEFAULTS_FALLBACK = {
"selected_case": DEFAULT_CASE_NAME,
"confidence_threshold": 0.60,
"smoothgrad_samples": 50,
"smoothgrad_noise": 0.05,
"gradcam_target_layer": DEFAULT_GRADCAM_TARGET_LAYER,
"save_xdl_results": False,
"save_xdl_dir": "xdl_results",
}
GRADCAM_TARGET_LAYER_DROPDOWN_CHOICES = [
("DenseBlock 3 (Default, balanced)", "denseblock3"),
("Transition 2 (Broad, stable)", "transition2"),
("Transition 1 (Earlier, detailed/noisier)", "transition1"),
("DenseBlock 4 (Late, center-heavy)", "denseblock4"),
("Transition 3 (Late, center-heavy)", "transition3"),
("Norm5 Last (Legacy behavior)", "norm5_last"),
]
CUSTOM_CSS = """
.app-shell {
--xdl-bg: #ffffff;
--xdl-surface: #f8fafc;
--xdl-text: #0f172a;
--xdl-muted: #475569;
--xdl-border: #d1d5db;
--xdl-primary: #0f766e;
--xdl-primary-strong: #0f4f4a;
--xdl-accent: #0ea5e9;
--xdl-success-bg: #dcfce7;
--xdl-success-text: #166534;
--xdl-warning-bg: #fef3c7;
--xdl-warning-text: #92400e;
max-width: 1120px;
margin: 0 auto;
color: var(--xdl-text);
}
.hero {
border: 1px solid var(--xdl-border);
background: linear-gradient(135deg, #f0fdfa 0%, #ecfeff 44%, #ffffff 100%);
border-radius: 18px;
padding: 20px 22px;
margin-bottom: 12px;
color: var(--xdl-text);
box-shadow: 0 18px 45px rgba(15, 23, 42, 0.08);
}
.hero-top {
display: flex;
justify-content: space-between;
gap: 18px;
align-items: flex-start;
}
.hero-kicker {
color: var(--xdl-primary);
font-size: 12px;
font-weight: 900;
letter-spacing: 0.12em;
margin-bottom: 6px;
text-transform: uppercase;
}
.hero h1 {
margin: 0;
font-size: 30px;
line-height: 1.1;
color: var(--xdl-text);
}
.hero p {
margin: 8px 0 0 0;
color: #334155;
font-size: 15px;
line-height: 1.5;
max-width: 720px;
}
.hero-pills {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
min-width: 220px;
}
.hero-pill {
border: 1px solid #99f6e4;
border-radius: 999px;
background: #ffffff;
color: var(--xdl-primary-strong);
font-size: 12px;
font-weight: 900;
padding: 7px 10px;
white-space: nowrap;
}
.panel {
border: 1px solid #e2e8f0;
border-radius: 12px;
background: var(--xdl-bg);
color: var(--xdl-text);
padding: 12px;
}
.dashboard-shell {
align-items: flex-start;
flex-direction: row-reverse;
gap: 16px;
}
.sidebar-panel {
border-radius: 20px;
padding: 16px;
position: sticky;
top: 12px;
}
.workspace-panel {
border-radius: 20px;
padding: 18px;
min-height: 680px;
}
.control-section {
border: 1px solid #e2e8f0;
border-radius: 15px;
background: #f8fafc;
margin-bottom: 12px;
padding: 12px;
}
.control-section-title {
color: var(--xdl-primary-strong);
font-size: 12px;
font-weight: 900;
letter-spacing: 0.08em;
margin-bottom: 10px;
text-transform: uppercase;
}
.workspace-title {
display: flex;
align-items: center !important;
justify-content: space-between;
gap: 14px;
margin-bottom: 14px;
}
.workspace-title-copy {
display: flex;
align-items: center;
flex: 1 1 auto;
min-height: 36px;
min-width: 0;
}
.workspace-title h2 {
color: var(--xdl-text);
font-size: 20px;
line-height: 1.2;
margin: 0;
}
.presentation-toggle {
align-self: center !important;
flex: 0 0 auto !important;
min-width: fit-content;
}
.presentation-toggle button {
align-items: center !important;
border: 1px solid #99f6e4 !important;
border-radius: 999px !important;
background: linear-gradient(135deg, #ffffff, #f0fdfa) !important;
color: var(--xdl-primary-strong) !important;
display: inline-flex !important;
font-size: 12px !important;
font-weight: 900 !important;
justify-content: center !important;
line-height: 1 !important;
margin: 0 !important;
min-height: 36px !important;
padding: 0 14px !important;
white-space: nowrap;
}
.presentation-toggle button:hover {
border-color: var(--xdl-primary) !important;
box-shadow: 0 8px 20px rgba(15, 118, 110, 0.16) !important;
}
.empty-state {
border: 1px dashed #cbd5e1;
border-radius: 18px;
background: linear-gradient(135deg, #ffffff, #f8fafc);
color: var(--xdl-muted);
padding: 28px;
text-align: center;
}
.empty-state-title {
color: var(--xdl-text);
font-size: 18px;
font-weight: 900;
margin-bottom: 8px;
}
.empty-state-copy {
font-size: 14px;
line-height: 1.5;
margin: 0 auto;
max-width: 520px;
}
.summary-card {
border: 1px solid #d1d5db;
border-radius: 18px;
background: #ffffff;
color: var(--xdl-text);
padding: 16px;
box-shadow: 0 14px 35px rgba(15, 23, 42, 0.06);
}
.summary-title {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-bottom: 14px;
}
.summary-title h3 {
color: var(--xdl-text);
font-size: 18px;
margin: 0;
}
.summary-title span {
border-radius: 999px;
background: #ecfeff;
color: var(--xdl-primary-strong);
font-size: 12px;
font-weight: 900;
padding: 6px 10px;
}
.metric-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
margin-bottom: 12px;
}
.metric-card {
border: 1px solid #e2e8f0;
border-radius: 14px;
background: #f8fafc;
padding: 12px;
}
.metric-label {
color: #64748b;
font-size: 12px;
font-weight: 800;
margin-bottom: 6px;
}
.metric-value {
color: var(--xdl-text);
font-size: 20px;
font-weight: 900;
line-height: 1.15;
word-break: break-word;
}
.metric-value.small {
font-size: 16px;
}
.summary-details {
border-top: 1px solid #e5e7eb;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px 16px;
padding-top: 12px;
}
.summary-detail {
color: #334155;
font-size: 13px;
line-height: 1.4;
}
.summary-detail b {
color: var(--xdl-text);
}
.panel :is(h1, h2, h3, h4, h5, h6, p, label, span, th, td) {
color: inherit;
}
.panel .secondary-wrap,
.panel .prose,
.panel .markdown {
color: var(--xdl-text);
}
.xdl-report {
display: flex;
flex-direction: column;
gap: 14px;
color: var(--xdl-text);
}
.processing-status {
border: 1px solid #dbeafe;
background: #eff6ff;
border-radius: 14px;
color: var(--xdl-text);
padding: 14px;
margin: 12px 0;
}
.processing-status-title {
font-size: 16px;
font-weight: 800;
margin-bottom: 10px;
}
.processing-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.progress-card {
border: 1px solid #bfdbfe;
border-radius: 12px;
background: #ffffff;
color: var(--xdl-text);
padding: 12px;
}
.progress-card-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: center;
font-size: 14px;
margin-bottom: 8px;
}
.progress-card-head span {
color: #075985;
font-weight: 800;
}
.progress-message {
color: #334155;
font-size: 13px;
line-height: 1.4;
margin-bottom: 10px;
}
.progress-track {
height: 10px;
border-radius: 999px;
background: #dbeafe;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, var(--xdl-primary), var(--xdl-accent));
transition: width 180ms ease;
}
.xdl-guide {
border: 1px solid #bae6fd;
background: #f0f9ff;
border-radius: 12px;
padding: 14px;
color: var(--xdl-text);
}
.xdl-guide-title {
font-size: 16px;
font-weight: 700;
color: var(--xdl-text);
margin-bottom: 10px;
}
.xdl-guide-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 10px;
}
.xdl-guide-grid div {
border: 1px solid #dbeafe;
background: var(--xdl-bg);
color: var(--xdl-text);
border-radius: 10px;
padding: 10px;
}
.xdl-guide-grid b {
display: block;
color: #075985;
font-size: 14px;
margin-bottom: 4px;
}
.xdl-guide-grid span {
display: block;
color: #334155;
font-size: 13px;
line-height: 1.4;
}
.xdl-report-heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
color: var(--xdl-text);
font-size: 17px;
font-weight: 700;
}
.xdl-report-heading span {
border-radius: 999px;
background: #e0f2fe;
color: #075985;
font-size: 12px;
font-weight: 700;
padding: 5px 10px;
}
.xdl-scroll {
max-height: 820px;
overflow-y: auto;
padding: 2px 8px 2px 2px;
}
.xdl-card {
border: 1px solid #cbd5e1;
border-radius: 18px;
background: linear-gradient(180deg, #ffffff 0%, #fbfdff 100%);
color: var(--xdl-text);
box-shadow: 0 16px 36px rgba(15, 23, 42, 0.09);
margin-bottom: 18px;
padding: 18px;
}
.xdl-card-header {
display: flex;
justify-content: space-between;
gap: 14px;
align-items: flex-start;
margin-bottom: 14px;
}
.xdl-filename {
color: var(--xdl-text);
font-size: 18px;
font-weight: 800;
word-break: break-word;
}
.xdl-card-subtitle {
color: #64748b;
font-size: 13px;
margin-top: 3px;
}
.xdl-meta {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
}
.xdl-badge,
.xdl-confidence {
border-radius: 999px;
font-size: 13px;
font-weight: 800;
padding: 7px 11px;
white-space: nowrap;
}
.xdl-badge {
background: var(--xdl-success-bg);
color: var(--xdl-success-text);
}
.xdl-confidence {
background: var(--xdl-warning-bg);
color: var(--xdl-warning-text);
}
.xdl-index {
color: var(--xdl-primary);
font-size: 12px;
font-weight: 900;
letter-spacing: 0.08em;
margin-bottom: 5px;
text-transform: uppercase;
}
.xdl-acceptance-note {
border-left: 3px solid var(--xdl-primary);
background: #f0fdfa;
border-radius: 10px;
color: #334155;
font-size: 13px;
line-height: 1.4;
margin: 12px 0 14px 0;
padding: 9px 11px;
}
.xdl-panel-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.xdl-panel {
border: 1px solid #e2e8f0;
border-radius: 14px;
background: var(--xdl-surface);
color: var(--xdl-text);
overflow: hidden;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75);
}
.xdl-panel-title {
background: #0f172a;
color: #ffffff;
font-size: 13px;
font-weight: 800;
letter-spacing: 0.02em;
padding: 8px 10px;
text-align: center;
}
.xdl-panel img {
display: block;
width: 100%;
height: auto;
background: #ffffff;
transition: transform 160ms ease, filter 160ms ease;
}
.xdl-image-link {
color: inherit;
display: block;
position: relative;
text-decoration: none;
}
.xdl-image-link:hover img {
filter: saturate(1.05) contrast(1.03);
transform: scale(1.01);
}
.xdl-image-hint {
border: 1px solid rgba(255, 255, 255, 0.45);
border-radius: 999px;
background: rgba(15, 23, 42, 0.78);
bottom: 9px;
color: #ffffff !important;
font-size: 11px;
font-weight: 900;
opacity: 0;
padding: 5px 8px;
pointer-events: none;
position: absolute;
right: 9px;
transform: translateY(4px);
transition: opacity 160ms ease, transform 160ms ease;
}
.xdl-image-link:hover .xdl-image-hint {
opacity: 1;
transform: translateY(0);
}
.xdl-empty {
border: 1px dashed #cbd5e1;
border-radius: 14px;
background: var(--xdl-surface);
color: var(--xdl-muted);
padding: 24px;
text-align: center;
}
.xdl-empty-title {
color: var(--xdl-text);
font-size: 16px;
font-weight: 800;
margin-bottom: 6px;
}
.xdl-status {
color: var(--xdl-muted);
font-size: 13px;
text-align: right;
}
@media (max-width: 900px) {
.sidebar-panel {
position: static;
}
.metric-grid,
.summary-details {
grid-template-columns: 1fr;
}
.hero-top {
flex-direction: column;
}
.hero-pills {
justify-content: flex-start;
}
.processing-grid,
.xdl-guide-grid,
.xdl-panel-grid {
grid-template-columns: 1fr;
}
.xdl-card-header {
flex-direction: column;
}
.xdl-meta {
justify-content: flex-start;
}
}
.action-stack {
display: flex;
flex-direction: column;
gap: 8px;
}
.action-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 8px;
align-items: stretch;
}
.run-action button {
font-weight: 900 !important;
min-height: 44px;
}
.clean-action button {
min-height: 44px;
}
.action-note {
border: 1px solid #ccfbf1;
border-radius: 10px;
background: #f0fdfa;
color: #0f4f4a;
font-size: 12px;
font-weight: 700;
line-height: 1.35;
padding: 9px 10px;
}
"""
def _as_float(value: Any, fallback: float) -> float:
try:
return float(value)
except (TypeError, ValueError):
return float(fallback)
def _as_int(value: Any, fallback: int) -> int:
try:
return int(value)
except (TypeError, ValueError):
return int(fallback)
def _as_bool(value: Any, fallback: bool) -> bool:
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.strip().lower() in {"1", "true", "yes", "y", "on"}
if value is None:
return fallback
return bool(value)
def _load_ui_defaults() -> dict[str, Any]:
defaults = dict(UI_DEFAULTS_FALLBACK)
try:
raw_text = UI_DEFAULTS_PATH.read_text(encoding="utf-8")
raw = json.loads(raw_text)
if isinstance(raw, dict):
for key in defaults:
if key in raw:
defaults[key] = raw[key]
except Exception:
pass
selected_case = str(defaults.get("selected_case", DEFAULT_CASE_NAME))
defaults["selected_case"] = selected_case if selected_case in CASE_OPTIONS else DEFAULT_CASE_NAME
defaults["confidence_threshold"] = min(
1.0,
max(0.0, _as_float(defaults.get("confidence_threshold"), UI_DEFAULTS_FALLBACK["confidence_threshold"])),
)
defaults["smoothgrad_samples"] = max(
1,
_as_int(defaults.get("smoothgrad_samples"), UI_DEFAULTS_FALLBACK["smoothgrad_samples"]),
)
defaults["smoothgrad_noise"] = min(
1.0,
max(0.0, _as_float(defaults.get("smoothgrad_noise"), UI_DEFAULTS_FALLBACK["smoothgrad_noise"])),
)
gradcam_target_layer = str(defaults.get("gradcam_target_layer", DEFAULT_GRADCAM_TARGET_LAYER)).strip().lower()
defaults["gradcam_target_layer"] = (
gradcam_target_layer if gradcam_target_layer in GRADCAM_TARGET_LAYER_OPTIONS else DEFAULT_GRADCAM_TARGET_LAYER
)
defaults["save_xdl_results"] = _as_bool(defaults.get("save_xdl_results"), UI_DEFAULTS_FALLBACK["save_xdl_results"])
defaults["save_xdl_dir"] = str(defaults.get("save_xdl_dir") or UI_DEFAULTS_FALLBACK["save_xdl_dir"])
return defaults
def _toggle_save_dir(enabled: bool):
is_enabled = bool(enabled)
return gr.update(visible=is_enabled, interactive=is_enabled)
def _toggle_presentation_view(enabled: bool):
next_enabled = not bool(enabled)
label = "Exit Presentation View" if next_enabled else "Enter Presentation View"
variant = "primary" if next_enabled else "secondary"
return next_enabled, gr.update(visible=not next_enabled), gr.update(value=label, variant=variant)
def _loaded_images_from_upload(uploaded_files):
image_paths = normalize_uploaded_paths(uploaded_files)
names = [path.name for path in image_paths]
stored_paths = [str(path) for path in image_paths]
return gr.update(choices=names, value=names[0] if names else None, interactive=bool(names)), stored_paths
def _empty_summary_html() -> str:
return (
"<div class='empty-state'>"
"<div class='empty-state-title'>No Results Yet</div>"
"<div class='empty-state-copy'>Upload an image folder or enter a public Google Drive folder link, "
"then run inference to see the batch diagnosis summary.</div>"
"</div>"
)
def _empty_processing_html() -> str:
return (
"<div class='empty-state'>"
"<div class='empty-state-title'>Processing Status Will Appear Here</div>"
"<div class='empty-state-copy'>Input preparation, Drive download progress, and XDL generation progress "
"will stream here while the model runs.</div>"
"</div>"
)
def _empty_xdl_html() -> str:
return (
"<div class='empty-state'>"
"<div class='empty-state-title'>XDL Cards Not Generated Yet</div>"
"<div class='empty-state-copy'>Classified images will appear as presentation-ready Original, GradCAM, "
"and SmoothGrad cards after inference completes.</div>"
"</div>"
)
def _reset_demo():
clean_drive_downloads()
ui_defaults = _load_ui_defaults()
save_enabled = bool(ui_defaults["save_xdl_results"])
return (
ui_defaults["selected_case"],
None,
[],
"",
gr.update(choices=[], value=None, interactive=False),
ui_defaults["confidence_threshold"],
ui_defaults["smoothgrad_samples"],
ui_defaults["smoothgrad_noise"],
ui_defaults["gradcam_target_layer"],
ui_defaults["save_xdl_results"],
gr.update(
value=ui_defaults["save_xdl_dir"],
visible=save_enabled,
interactive=save_enabled,
),
_empty_summary_html(),
_empty_processing_html(),
_empty_xdl_html(),
[],
)
def build_demo() -> gr.Blocks:
ui_defaults = _load_ui_defaults()
with gr.Blocks(title="XDL Colitis Demo") as demo:
gr.HTML(
f"""
<style>{CUSTOM_CSS}</style>
<div class="app-shell">
<div class="hero">
<div class="hero-top">
<div class="hero-copy">
<div class="hero-kicker">Medical AI Explanation Demo</div>
<h1>XDL Colitis Workbench</h1>
<p>DenseNet-based colitis classification with GradCAM and SmoothGrad explanations. Upload a directory or use a public Google Drive folder link, then run batch inference.</p>
</div>
<div class="hero-pills">
<span class="hero-pill">Device: {DEVICE.type}</span>
<span class="hero-pill">3 Case Modes</span>
<span class="hero-pill">Folder / Drive Input</span>
</div>
</div>
</div>
</div>
"""
)
with gr.Row(elem_classes=["app-shell", "dashboard-shell"]):
with gr.Column(scale=1, min_width=330, elem_classes=["panel", "sidebar-panel"]) as sidebar_panel:
gr.HTML("<div class='control-section-title'>Data Source</div>")
with gr.Group(elem_classes=["control-section"]):
upload_input = gr.UploadButton(
label="Select Image Folder",
variant="secondary",
file_count="directory",
type="filepath",
)
google_drive_link = gr.Textbox(
label="Google Drive Link (Optional)",
placeholder="Public Google Drive folder link",
)
loaded_images = gr.Dropdown(
choices=[],
label="Loaded Images",
info="Filenames detected from upload or Google Drive after processing starts.",
interactive=False,
)
uploaded_files_state = gr.State([])
folder_path = gr.State("")
gr.HTML("<div class='control-section-title'>Model Case</div>")
with gr.Group(elem_classes=["control-section"]):
selected_case = gr.Dropdown(
choices=CASE_OPTIONS,
value=ui_defaults["selected_case"],
label="Problem Case",
info="Choose the model group that matches your diagnosis scenario.",
)
gr.HTML("<div class='control-section-title'>Inference Settings</div>")
with gr.Group(elem_classes=["control-section"]):
threshold = gr.Number(
value=ui_defaults["confidence_threshold"],
minimum=0.0,
maximum=1.0,
step=0.01,
precision=2,
label="Confidence Threshold",
info="Range: 0.00 to 1.00",
)
gradcam_target_layer = gr.Dropdown(
choices=GRADCAM_TARGET_LAYER_DROPDOWN_CHOICES,
value=ui_defaults["gradcam_target_layer"],
label="GradCAM Target Layer",
info="Try `transition2` or `denseblock3` if CAM looks too centered.",
)
smoothgrad_samples = gr.Number(
value=ui_defaults["smoothgrad_samples"],
minimum=1,
maximum=1000,
step=1,
precision=0,
label="SmoothGrad Samples",
info="Higher values improve stability but increase runtime.",
)
smoothgrad_noise = gr.Number(
value=ui_defaults["smoothgrad_noise"],
minimum=0.0,
maximum=1.0,
step=0.01,
precision=2,
label="SmoothGrad Noise Level",
info="Typical range: 0.01 to 0.20",
)
gr.HTML("<div class='control-section-title'>Export</div>")
with gr.Group(elem_classes=["control-section"]):
save_xdl_results = gr.Checkbox(
label="Save XDL Results Locally",
value=ui_defaults["save_xdl_results"],
)
save_xdl_dir = gr.Textbox(
label="Save Folder",
value=ui_defaults["save_xdl_dir"],
placeholder="xdl_results",
visible=bool(ui_defaults["save_xdl_results"]),
interactive=bool(ui_defaults["save_xdl_results"]),
)
with gr.Column(elem_classes=["action-stack"]):
with gr.Row(elem_classes=["action-row"]):
run_btn = gr.Button(
"Run / Rerun Inference",
variant="primary",
elem_classes=["run-action"],
)
clean_btn = gr.Button("Clean", variant="secondary", elem_classes=["clean-action"])
gr.HTML(
"<div class='action-note'>Runs classification first, then streams XDL overlays as each image finishes.</div>"
)
with gr.Column(scale=3, elem_classes=["panel", "workspace-panel"]):
with gr.Row(elem_classes=["workspace-title"]):
gr.HTML(
"<div class='workspace-title-copy'><h2>Results Workspace</h2></div>"
)
presentation_state = gr.State(False)
presentation_btn = gr.Button(
"Enter Presentation View",
variant="secondary",
elem_classes=["presentation-toggle"],
scale=0,
min_width=178,
)
summary_out = gr.HTML(value=_empty_summary_html(), label="Summary")
processing_status_out = gr.HTML(value=_empty_processing_html(), label="Processing Status")
xdl_report_out = gr.HTML(value=_empty_xdl_html(), label="Classified XDL Results")
with gr.Accordion("Detailed Per-Image Table", open=False):
table_out = gr.Dataframe(
headers=["filename", "status", "predicted_label", "confidence_or_error"],
datatype=["str", "str", "str", "str"],
interactive=False,
label="Per-image Results",
)
save_xdl_results.change(
fn=_toggle_save_dir,
inputs=[save_xdl_results],
outputs=[save_xdl_dir],
)
upload_input.upload(
fn=_loaded_images_from_upload,
inputs=[upload_input],
outputs=[loaded_images, uploaded_files_state],
)
presentation_btn.click(
fn=_toggle_presentation_view,
inputs=[presentation_state],
outputs=[presentation_state, sidebar_panel, presentation_btn],
)
run_btn.click(
fn=batch_predict_with_xdl_stream,
inputs=[
uploaded_files_state,
selected_case,
folder_path,
threshold,
smoothgrad_samples,
smoothgrad_noise,
save_xdl_results,
save_xdl_dir,
gradcam_target_layer,
google_drive_link,
],
outputs=[summary_out, processing_status_out, xdl_report_out, loaded_images, table_out],
)
clean_btn.click(
fn=_reset_demo,
inputs=[],
outputs=[
selected_case,
upload_input,
uploaded_files_state,
google_drive_link,
loaded_images,
threshold,
smoothgrad_samples,
smoothgrad_noise,
gradcam_target_layer,
save_xdl_results,
save_xdl_dir,
summary_out,
processing_status_out,
xdl_report_out,
table_out,
],
)
return demo.queue()