Spaces:
Sleeping
Sleeping
File size: 5,883 Bytes
bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d bf08742 bc1fb7d bf08742 b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d b46360a bc1fb7d bf08742 | 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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | """UI components for MelanoScope AI."""
import os
import logging
from typing import List
import gradio as gr
from ..config.settings import UIConfig
from ..core.utils import create_empty_dataframe
from .styles import get_custom_css, create_theme, get_header_html, get_footer_html, get_model_info_html
logger = logging.getLogger(__name__)
class MelanoScopeUI:
"""Handles UI components and layout."""
def __init__(self, model_instance, classes: List[str]):
self.model = model_instance
self.classes = classes
self.theme = create_theme()
self.css = get_custom_css()
logger.info("UI initialized")
def create_interface(self) -> gr.Blocks:
"""Create complete Gradio interface."""
with gr.Blocks(theme=self.theme, css=self.css) as interface:
self._create_header()
with gr.Row(equal_height=True):
self._create_input_column()
self._create_results_column()
self._create_footer()
self._setup_event_handlers()
return interface
def _create_header(self) -> None:
"""Create header section."""
with gr.Row():
with gr.Column(scale=6):
gr.Markdown(get_header_html())
with gr.Column(scale=1, min_width=UIConfig.THEME_TOGGLE_MIN_WIDTH):
try:
self.dark_toggle = gr.ThemeMode(label="Theme", value="system")
except Exception:
gr.Markdown("")
def _create_input_column(self) -> None:
"""Create input column with image upload and controls."""
with gr.Column(scale=UIConfig.LEFT_COLUMN_SCALE):
self.image_input = gr.Image(
type="numpy",
label="Lesion Image",
height=UIConfig.IMAGE_HEIGHT,
sources=["upload", "clipboard"]
)
with gr.Row():
self.analyze_btn = gr.Button("Analyze", variant="primary")
self.clear_btn = gr.Button("Clear")
self._create_examples_section()
self.latency_output = gr.Label(label="Inference Time")
def _create_examples_section(self) -> None:
"""Create examples section if files exist."""
example_files = [
"melanoma.jpg", "vascular_lesion.jpg"
]
existing_examples = [f for f in example_files if os.path.exists(f)]
if existing_examples:
gr.Examples(
examples=existing_examples,
inputs=self.image_input,
label="Quick Examples",
cache_examples=False
)
def _create_results_column(self) -> None:
"""Create results column with predictions and info."""
with gr.Column(scale=UIConfig.RIGHT_COLUMN_SCALE):
self._create_prediction_results()
self._create_information_tabs()
def _create_prediction_results(self) -> None:
"""Create prediction results section."""
with gr.Group():
with gr.Row():
self.prediction_output = gr.Label(label="Primary Prediction", elem_classes=["pred-card"])
self.confidence_output = gr.Label(label="Confidence")
self.probability_plot = gr.BarPlot(
value=create_empty_dataframe(self.classes),
x="item", y="probability",
title="Probability Distribution (Top-k)",
x_title="Class", y_title="Probability",
vertical=False, tooltip=["item", "probability"],
width=UIConfig.PLOT_WIDTH, height=UIConfig.PLOT_HEIGHT,
)
def _create_information_tabs(self) -> None:
"""Create information tabs."""
with gr.Tabs():
with gr.TabItem("Medical Details"):
self._create_medical_details()
with gr.TabItem("About Model"):
gr.Markdown(get_model_info_html())
def _create_medical_details(self) -> None:
"""Create medical details accordions."""
with gr.Accordion("Description", open=True):
self.description_output = gr.Textbox(lines=UIConfig.TEXTBOX_LINES, interactive=False)
with gr.Accordion("Symptoms", open=False):
self.symptoms_output = gr.Textbox(lines=UIConfig.TEXTBOX_LINES, interactive=False)
with gr.Accordion("Causes", open=False):
self.causes_output = gr.Textbox(lines=UIConfig.TEXTBOX_LINES, interactive=False)
with gr.Accordion("Treatment", open=False):
self.treatment_output = gr.Textbox(lines=UIConfig.TEXTBOX_LINES, interactive=False)
def _create_footer(self) -> None:
"""Create footer section."""
gr.Markdown(get_footer_html())
def _setup_event_handlers(self) -> None:
"""Set up event handlers."""
outputs = [
self.prediction_output, self.confidence_output, self.description_output,
self.symptoms_output, self.causes_output, self.treatment_output,
self.probability_plot, self.latency_output
]
self.analyze_btn.click(
fn=self.model.predict, inputs=[self.image_input],
outputs=outputs, show_progress="full"
)
self.clear_btn.click(
fn=self._clear_all, inputs=[],
outputs=[self.image_input] + outputs
)
def _clear_all(self) -> tuple:
"""Clear all inputs and outputs."""
empty_df = create_empty_dataframe(self.classes)
return (None, "", "", "", "", "", "", empty_df, "")
|