wyctorfogos commited on
Commit
f2888df
Β·
1 Parent(s): d5ccf53

update: Add detalhes do paper

Browse files
Files changed (3) hide show
  1. Dockerfile +3 -1
  2. README.md +15 -2
  3. src/main.py +401 -61
Dockerfile CHANGED
@@ -9,7 +9,9 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
9
  PATH=/home/user/.local/bin:$PATH \
10
  HF_HOME=/tmp/.huggingface \
11
  TRANSFORMERS_CACHE=/tmp/.cache/huggingface/transformers \
12
- HUGGINGFACE_HUB_CACHE=/tmp/.cache/huggingface/hub
 
 
13
 
14
  RUN useradd -m -u 1000 user
15
 
 
9
  PATH=/home/user/.local/bin:$PATH \
10
  HF_HOME=/tmp/.huggingface \
11
  TRANSFORMERS_CACHE=/tmp/.cache/huggingface/transformers \
12
+ HUGGINGFACE_HUB_CACHE=/tmp/.cache/huggingface/hub\
13
+ PAPER_URL=https://ieeexplore.ieee.org/Xplore/home.jsp\
14
+ PAPER_TITLE="RG-DermNet: A Multimodal Attention-Based Model with Residual Block Usage for Skin Lesion Classification \n PAPER_DESCRIPTION=Skin cancer accounts for nearly one-third of all diag-\nnosed tumors worldwide, making early and accurate recognition\ncritical for improving patient outcomes. In this work, we pro-\npose RG-DermNet, a multimodal deep learning framework that\nintegrates skin lesion images with structured clinical metadata\nthrough a residual gated-attention (RG-ATT) fusion mechanism.\nThe architecture combines CNN- and Transformer-based visual\nbackbones with a lightweight one-hot encoding pipeline for meta-\ndata, enabling effective cross-modal interaction. The proposed\nmodel is evaluated using a patient-wise cross-validation protocol\nacross four dermatological datasets with heterogeneous metadata.\nOn PAD-UFES-20, using Caformer-B36 as the visual backbone,\nRG-DermNet achieves an accuracy of 0.75 Β± 0.05, balanced\naccuracy of 0.78 Β± 0.03, F1-score of 0.77 Β± 0.04, and AUC of\n0.95 Β± 0.01, outperforming existing multimodal baselines under\nthe same evaluation setting. In addition, a SHAP-based analysis\nprovides insights into the contribution of clinical metadata to\nthe model’s predictions, supporting both performance gains and\ninterpretability."
15
 
16
  RUN useradd -m -u 1000 user
17
 
README.md CHANGED
@@ -8,9 +8,12 @@ startup_duration_timeout: 1h
8
  license: mit
9
  ---
10
 
11
- # Multimodal Skin Lesion Explainability
12
 
13
  A Gradio-based web application for multimodal skin lesion analysis with **GradCAM++ visualization**. This tool enables clinicians and researchers to understand how deep learning models make predictions on dermoscopic images by combining image data with clinical metadata.
 
 
 
14
 
15
  ## 🎯 Features
16
 
@@ -171,7 +174,7 @@ GradCAMPlusPlus_SkinLesion/
171
  - **GPU Recommended**: Faster inference with CUDA. Falls back to CPU if unavailable.
172
 
173
  ## πŸ”— References & Acknowledgments
174
-
175
  - **Dataset**: PAD-UFES-20 (Universidade Federal do EspΓ­rito Santo)
176
  - **GradCAM++**: [Paper](https://arxiv.org/abs/1710.11063) by Chattopadhyay et al.
177
  - **Framework**: [Gradio](https://gradio.app) for the web interface
@@ -189,6 +192,16 @@ Contributions are welcome! Please:
189
  4. Push to the branch (`git push origin feature/improvement`)
190
  5. Open a Pull Request
191
 
 
 
 
 
 
 
 
 
 
 
192
  ## πŸ“§ Support
193
 
194
  For issues, questions, or suggestions:
 
8
  license: mit
9
  ---
10
 
11
+ # πŸ”¬ RG-DermNet: Multimodal Skin Lesion Explainability
12
 
13
  A Gradio-based web application for multimodal skin lesion analysis with **GradCAM++ visualization**. This tool enables clinicians and researchers to understand how deep learning models make predictions on dermoscopic images by combining image data with clinical metadata.
14
+ ## πŸ“„ Abstract
15
+
16
+ Skin cancer accounts for nearly one-third of all diagnosed tumors worldwide, making early and accurate recognition critical for improving patient outcomes. In this work, we propose RG-DermNet, a multimodal deep learning framework that integrates skin lesion images with structured clinical metadata through a residual gated-attention (RG-ATT) fusion mechanism. The architecture combines CNN- and Transformer-based visual backbones with a lightweight one-hot encoding pipeline for metadata, enabling effective cross-modal interaction. The proposed model is evaluated using a patient-wise cross-validation protocol across four dermatological datasets with heterogeneous metadata. On PAD-UFES-20, using Caformer-B36 as the visual backbone, RG-DermNet achieves an accuracy of 0.75 Β± 0.05, balanced accuracy of 0.78 Β± 0.03, F1-score of 0.77 Β± 0.04, and AUC of 0.95 Β± 0.01, outperforming existing multimodal baselines under the same evaluation setting. In addition, a SHAP-based analysis provides insights into the contribution of clinical metadata to the model’s predictions, supporting both performance gains and interpretability.
17
 
18
  ## 🎯 Features
19
 
 
174
  - **GPU Recommended**: Faster inference with CUDA. Falls back to CPU if unavailable.
175
 
176
  ## πŸ”— References & Acknowledgments
177
+ - **Paper repository**: RG-DermNet (https://github.com/wyctorfogos/rg-dermnet)
178
  - **Dataset**: PAD-UFES-20 (Universidade Federal do EspΓ­rito Santo)
179
  - **GradCAM++**: [Paper](https://arxiv.org/abs/1710.11063) by Chattopadhyay et al.
180
  - **Framework**: [Gradio](https://gradio.app) for the web interface
 
192
  4. Push to the branch (`git push origin feature/improvement`)
193
  5. Open a Pull Request
194
 
195
+ ## πŸ“Ž Citation
196
+
197
+ @inproceedings{rocha2026rgdermnet,
198
+ title = {RG-DermNet: A Multimodal Attention-Based Model with Residual Block Usage for Skin Lesion Classification},
199
+ author = {Rocha, Wyctor F. and Bouzon, Pedro H. G. and Ramos, Lucas A. and Pacheco, Andre G. C. and Souza Jr., Luis A.},
200
+ booktitle = {International Joint Conference on Neural Networks (IJCNN)},
201
+ year = {2026},
202
+ note = {Accepted}
203
+ }
204
+
205
  ## πŸ“§ Support
206
 
207
  For issues, questions, or suggestions:
src/main.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import gradio as gr
2
  from models.inference import (
3
  run_inference,
@@ -16,26 +18,267 @@ GROUP_CHOICES = [
16
  DEFAULT_GROUPS = ["demographics", "symptoms", "lesion_geometry"]
17
  REGION_CHOICES = ["HEAD", "NECK", "BACK", "ARM", "LEG", "TORSO"]
18
  GENDER_CHOICES = ["MALE", "FEMALE"]
 
19
  MODEL_CHOICES = get_available_model_choices()
20
  DEFAULT_MODEL_KEY = get_default_model_key()
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  custom_css = """
23
- .gradio-container { background-color: #0b0f19 !important; }
24
- .input-panel { border: 1px solid #2d3748; padding: 15px; border-radius: 10px; background: #1a202c; }
25
- .predict-btn { background: #3182ce !important; color: white !important; font-weight: bold !important; }
26
- .predict-btn:hover { background: #4299e1 !important; }
27
- .status-msg { font-style: italic; color: #a0aec0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  """
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  def format_groups(enabled_groups):
31
  if not enabled_groups:
32
  return "No metadata group selected."
33
  label_map = dict(GROUP_CHOICES)
34
  return " | ".join([label_map.get(g, g) for g in enabled_groups])
35
 
 
36
  def safe_bool(value):
37
  return bool(value)
38
 
 
39
  def build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
40
  return {
41
  "age": age,
@@ -51,12 +294,14 @@ def build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hur
51
  "elevation": safe_bool(elevation),
52
  }
53
 
 
54
  def build_metadata_preview(enabled_groups, age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
55
  values = build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation)
56
  metadata_csv = build_metadata_csv(values, enabled_groups)
57
  groups_text = format_groups(enabled_groups)
58
  return metadata_csv, groups_text
59
 
 
60
  def validate_inputs(image, enabled_groups, age, diameter1, diameter2):
61
  if image is None:
62
  raise gr.Error("Please upload a dermoscopic image first.")
@@ -69,6 +314,7 @@ def validate_inputs(image, enabled_groups, age, diameter1, diameter2):
69
  if diameter2 is None or diameter2 < 0:
70
  raise gr.Error("Diameter 2 must be a valid non-negative number.")
71
 
 
72
  def gradio_predict(image, selected_model_key, enabled_groups, age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
73
  validate_inputs(image, enabled_groups, age, diameter1, diameter2)
74
  values = build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation)
@@ -89,6 +335,7 @@ def gradio_predict(image, selected_model_key, enabled_groups, age, gender, regio
89
  )
90
  return image, heatmap_img, pretty_prediction, metadata_csv, groups_text
91
 
 
92
  def clear_all():
93
  default_model = DEFAULT_MODEL_KEY
94
  if default_model is None and MODEL_CHOICES:
@@ -101,75 +348,168 @@ def clear_all():
101
  "", format_groups(DEFAULT_GROUPS)
102
  )
103
 
104
- with gr.Blocks(title="Skin Lesion Explainability", theme=gr.themes.Default(primary_hue="blue"), css=custom_css) as demo:
105
- gr.Markdown(
106
- """
107
- # πŸ”¬ Multimodal Skin Lesion Explainability
108
- Observe how metadata affects the model's focus using **GradCAM++**.
109
- """
110
- )
111
 
112
- with gr.Row():
113
- with gr.Column(scale=1, variant="panel"):
114
- gr.Markdown("### πŸ“₯ Input Data")
 
 
 
 
115
 
116
- image_input = gr.Image(type="pil", label="Dermoscopic Image", height=320)
 
 
 
 
 
 
 
 
117
 
118
- group_selector = gr.CheckboxGroup(
119
- choices=GROUP_CHOICES,
120
- value=DEFAULT_GROUPS,
121
- label="Enable Metadata Groups"
122
- )
123
 
124
- model_selector = gr.Dropdown(
125
- choices=MODEL_CHOICES,
126
- value=DEFAULT_MODEL_KEY if DEFAULT_MODEL_KEY is not None else None,
127
- label="Attention Mechanism Model",
128
- info="Choose which pretrained attention mechanism/model to run.",
129
- )
 
 
 
 
 
130
 
131
- with gr.Accordion("πŸ‘€ Demographics", open=True):
132
- age = gr.Number(label="Age", value=55, precision=0)
133
- with gr.Row():
134
- gender = gr.Dropdown(GENDER_CHOICES, value="FEMALE", label="Gender")
135
- region = gr.Dropdown(REGION_CHOICES, value="NECK", label="Region")
136
-
137
- with gr.Accordion("πŸ“ Lesion Geometry", open=False):
138
- with gr.Row():
139
- diameter1 = gr.Number(label="Diameter 1", value=6)
140
- diameter2 = gr.Number(label="Diameter 2", value=5)
141
-
142
- with gr.Accordion("🚩 Symptoms", open=False):
143
- with gr.Row():
144
- itch = gr.Checkbox(label="Itch")
145
- grew = gr.Checkbox(label="Grew")
146
- hurt = gr.Checkbox(label="Hurt")
147
- with gr.Row():
148
- changed = gr.Checkbox(label="Changed")
149
- bleed = gr.Checkbox(label="Bleed")
150
- elevation = gr.Checkbox(label="Elevation")
151
 
152
  with gr.Row():
153
- clear_btn = gr.Button("Clear", variant="secondary")
154
- run_btn = gr.Button("Generate GradCAM++", variant="primary", elem_classes="predict-btn")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
- with gr.Column(scale=2):
157
- gr.Markdown("### πŸ“Š Analysis Dashboard")
 
 
 
 
158
 
159
  with gr.Row():
160
- original_img_out = gr.Image(label="Original Lesion", interactive=False)
161
- heatmap_out = gr.Image(label="Attention Map (GradCAM++)", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
- with gr.Group():
164
- prediction_out = gr.Markdown(
165
- value="### Prediction Result\n\nRun the model to see the output here."
166
- )
 
 
 
 
 
167
 
168
- with gr.Accordion("πŸ“‹ System Metadata Details", open=False):
169
- active_groups_text = gr.Textbox(label="Active Groups", interactive=False)
170
- metadata_preview = gr.Textbox(label="Final CSV Input", lines=6, interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
- preview_inputs = [group_selector, age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation]
 
 
 
173
 
174
  for component in preview_inputs:
175
  component.change(
 
1
+ import os
2
+
3
  import gradio as gr
4
  from models.inference import (
5
  run_inference,
 
18
  DEFAULT_GROUPS = ["demographics", "symptoms", "lesion_geometry"]
19
  REGION_CHOICES = ["HEAD", "NECK", "BACK", "ARM", "LEG", "TORSO"]
20
  GENDER_CHOICES = ["MALE", "FEMALE"]
21
+
22
  MODEL_CHOICES = get_available_model_choices()
23
  DEFAULT_MODEL_KEY = get_default_model_key()
24
 
25
+ PAPER_URL = os.environ.get("PAPER_URL", "").strip()
26
+ PAPER_TITLE = os.environ.get(
27
+ "PAPER_TITLE",
28
+ "RG-DermNet: Multimodal Skin Lesion Explainability"
29
+ ).strip()
30
+ PAPER_DESCRIPTION = os.environ.get(
31
+ "PAPER_DESCRIPTION",
32
+ "This Space accompanies the proposed multimodal framework and allows real-time "
33
+ "inspection of how clinical metadata affects prediction behavior and GradCAM++ attention maps."
34
+ ).strip()
35
+
36
+ PAPER_FILE = os.environ.get("PAPER_FILE", "paper.pdf").strip()
37
+ PAPER_EXISTS = os.path.exists(PAPER_FILE)
38
+
39
  custom_css = """
40
+ .gradio-container {
41
+ background: linear-gradient(180deg, #08111f 0%, #0b0f19 100%) !important;
42
+ color: #e8eef8 !important;
43
+ }
44
+
45
+ .main-shell {
46
+ max-width: 1280px;
47
+ margin: 0 auto;
48
+ }
49
+
50
+ .hero {
51
+ padding: 28px 24px 18px 24px;
52
+ border: 1px solid #24364d;
53
+ border-radius: 18px;
54
+ background: linear-gradient(135deg, rgba(17, 28, 46, 0.95), rgba(8, 13, 24, 0.95));
55
+ margin-bottom: 18px;
56
+ }
57
+
58
+ .hero h1 {
59
+ margin: 0 0 10px 0;
60
+ font-size: 2.1rem;
61
+ line-height: 1.2;
62
+ }
63
+
64
+ .hero p {
65
+ margin: 0;
66
+ color: #d2dceb;
67
+ line-height: 1.65;
68
+ font-size: 1rem;
69
+ }
70
+
71
+ .badge-row {
72
+ display: flex;
73
+ flex-wrap: wrap;
74
+ gap: 8px;
75
+ margin-top: 14px;
76
+ }
77
+
78
+ .badge {
79
+ padding: 6px 10px;
80
+ border-radius: 999px;
81
+ background: #12253f;
82
+ border: 1px solid #2f527c;
83
+ color: #beddff;
84
+ font-size: 0.9rem;
85
+ }
86
+
87
+ .section-card {
88
+ border: 1px solid #24364d;
89
+ border-radius: 18px;
90
+ background: rgba(11, 18, 31, 0.92);
91
+ padding: 18px 20px;
92
+ margin-bottom: 18px;
93
+ }
94
+
95
+ .section-card h2,
96
+ .section-card h3 {
97
+ margin-top: 0;
98
+ }
99
+
100
+ .paper-card {
101
+ padding: 16px 18px;
102
+ border: 1px solid #2d4f7c;
103
+ border-radius: 14px;
104
+ background: linear-gradient(135deg, rgba(18, 34, 58, 0.95), rgba(10, 16, 28, 0.95));
105
+ }
106
+
107
+ .paper-card h3 {
108
+ margin: 0 0 8px 0;
109
+ font-size: 1.05rem;
110
+ }
111
+
112
+ .paper-card p {
113
+ margin: 0 0 8px 0;
114
+ color: #d3deee;
115
+ line-height: 1.55;
116
+ }
117
+
118
+ .paper-card a {
119
+ color: #8bc4ff;
120
+ text-decoration: none;
121
+ font-weight: 600;
122
+ }
123
+
124
+ .paper-card a:hover {
125
+ text-decoration: underline;
126
+ }
127
+
128
+ .pipeline-box {
129
+ padding: 14px;
130
+ border-radius: 14px;
131
+ border: 1px solid #2b405e;
132
+ background: #0d1727;
133
+ text-align: center;
134
+ min-height: 120px;
135
+ display: flex;
136
+ flex-direction: column;
137
+ justify-content: center;
138
+ }
139
+
140
+ .pipeline-box h3 {
141
+ margin-bottom: 8px;
142
+ }
143
+
144
+ .pipeline-box p {
145
+ margin: 0;
146
+ color: #ced9ea;
147
+ line-height: 1.5;
148
+ }
149
+
150
+ .pipeline-arrow {
151
+ text-align: center;
152
+ font-size: 1.6rem;
153
+ color: #8bc4ff;
154
+ padding-top: 38px;
155
+ font-weight: 700;
156
+ }
157
+
158
+ .demo-panel {
159
+ border: 1px solid #2d3748;
160
+ padding: 16px;
161
+ border-radius: 16px;
162
+ background: #111a29;
163
+ }
164
+
165
+ .predict-btn {
166
+ background: #3182ce !important;
167
+ color: white !important;
168
+ font-weight: bold !important;
169
+ border: none !important;
170
+ }
171
+
172
+ .predict-btn:hover {
173
+ background: #4299e1 !important;
174
+ }
175
+
176
+ .soft-text {
177
+ color: #b9c7da;
178
+ line-height: 1.6;
179
+ }
180
+
181
+ .footer-note {
182
+ font-size: 0.95rem;
183
+ color: #b7c6db;
184
+ line-height: 1.6;
185
+ }
186
+
187
+ .paper-frame-wrap {
188
+ border: 1px solid #2d4f7c;
189
+ border-radius: 14px;
190
+ overflow: hidden;
191
+ background: #0b1321;
192
+ }
193
+
194
+ .paper-frame {
195
+ width: 100%;
196
+ height: 900px;
197
+ border: none;
198
+ background: white;
199
+ }
200
+
201
+ .muted-divider {
202
+ opacity: 0.25;
203
+ margin: 10px 0 14px 0;
204
+ }
205
  """
206
 
207
+
208
+ def build_paper_card():
209
+ link_html = ""
210
+ if PAPER_URL:
211
+ link_html += (
212
+ f'<p><a href="{PAPER_URL}" target="_blank" rel="noopener noreferrer">'
213
+ f'Open paper link</a></p>'
214
+ )
215
+
216
+ if PAPER_EXISTS:
217
+ link_html += '<p><a href="/file=paper.pdf" target="_blank" rel="noopener noreferrer">Open embedded PDF in new tab</a></p>'
218
+
219
+ if not link_html:
220
+ link_html = "<p>No external paper link configured yet.</p>"
221
+
222
+ return f"""
223
+ <div class="paper-card">
224
+ <h3>πŸ“„ Associated Paper</h3>
225
+ <p><strong>{PAPER_TITLE}</strong></p>
226
+ <p>{PAPER_DESCRIPTION}</p>
227
+ {link_html}
228
+ </div>
229
+ """
230
+
231
+
232
+ def build_hero():
233
+ return """
234
+ <div class="hero">
235
+ <h1>πŸ”¬ Multimodal Skin Lesion Explainability</h1>
236
+ <p>
237
+ This interactive scientific demo presents a multimodal skin lesion analysis system that combines
238
+ clinical images and patient metadata to generate predictions and GradCAM++ explanations.
239
+ The interface allows real-time inspection of how metadata influences model attention and
240
+ diagnostic behavior.
241
+ </p>
242
+ <div class="badge-row">
243
+ <span class="badge">Clinical Image + Metadata</span>
244
+ <span class="badge">Multimodal Attention</span>
245
+ <span class="badge">GradCAM++ Explainability</span>
246
+ <span class="badge">Interactive Paper Demo</span>
247
+ </div>
248
+ </div>
249
+ """
250
+
251
+
252
+ def build_paper_embed():
253
+ if not PAPER_EXISTS:
254
+ return """
255
+ <div class="paper-card">
256
+ <h3>Paper preview unavailable</h3>
257
+ <p>
258
+ The file <strong>paper.pdf</strong> was not found in the repository root.
259
+ Add it to enable in-Space preview.
260
+ </p>
261
+ </div>
262
+ """
263
+
264
+ return """
265
+ <div class="paper-frame-wrap">
266
+ <iframe src="/file=paper.pdf" class="paper-frame"></iframe>
267
+ </div>
268
+ """
269
+
270
+
271
  def format_groups(enabled_groups):
272
  if not enabled_groups:
273
  return "No metadata group selected."
274
  label_map = dict(GROUP_CHOICES)
275
  return " | ".join([label_map.get(g, g) for g in enabled_groups])
276
 
277
+
278
  def safe_bool(value):
279
  return bool(value)
280
 
281
+
282
  def build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
283
  return {
284
  "age": age,
 
294
  "elevation": safe_bool(elevation),
295
  }
296
 
297
+
298
  def build_metadata_preview(enabled_groups, age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
299
  values = build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation)
300
  metadata_csv = build_metadata_csv(values, enabled_groups)
301
  groups_text = format_groups(enabled_groups)
302
  return metadata_csv, groups_text
303
 
304
+
305
  def validate_inputs(image, enabled_groups, age, diameter1, diameter2):
306
  if image is None:
307
  raise gr.Error("Please upload a dermoscopic image first.")
 
314
  if diameter2 is None or diameter2 < 0:
315
  raise gr.Error("Diameter 2 must be a valid non-negative number.")
316
 
317
+
318
  def gradio_predict(image, selected_model_key, enabled_groups, age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation):
319
  validate_inputs(image, enabled_groups, age, diameter1, diameter2)
320
  values = build_values_dict(age, gender, region, diameter1, diameter2, itch, grew, hurt, changed, bleed, elevation)
 
335
  )
336
  return image, heatmap_img, pretty_prediction, metadata_csv, groups_text
337
 
338
+
339
  def clear_all():
340
  default_model = DEFAULT_MODEL_KEY
341
  if default_model is None and MODEL_CHOICES:
 
348
  "", format_groups(DEFAULT_GROUPS)
349
  )
350
 
 
 
 
 
 
 
 
351
 
352
+ with gr.Blocks(
353
+ title="Skin Lesion Explainability",
354
+ theme=gr.themes.Default(primary_hue="blue"),
355
+ css=custom_css,
356
+ ) as demo:
357
+ with gr.Column(elem_classes="main-shell"):
358
+ gr.HTML(build_hero())
359
 
360
+ with gr.Group(elem_classes="section-card"):
361
+ gr.Markdown("## πŸ“„ Paper and Scientific Context")
362
+ with gr.Row():
363
+ with gr.Column(scale=1):
364
+ gr.HTML(build_paper_card())
365
+ with gr.Column(scale=1):
366
+ gr.Markdown(
367
+ """
368
+ ### Scientific Context
369
 
370
+ This Space accompanies a multimodal deep learning framework for skin lesion analysis.
371
+ It was designed as an interactive companion to the paper, enabling direct exploration of:
 
 
 
372
 
373
+ - metadata-aware prediction behavior
374
+ - qualitative GradCAM++ attention patterns
375
+ - differences across pretrained multimodal attention mechanisms
376
+
377
+ The goal is to make the proposed method easier to inspect, understand, and communicate.
378
+ """,
379
+ elem_classes="soft-text",
380
+ )
381
+
382
+ with gr.Accordion("πŸ“˜ Full Paper Preview", open=False):
383
+ gr.HTML(build_paper_embed())
384
 
385
+ with gr.Group(elem_classes="section-card"):
386
+ gr.Markdown("## 🧠 Method Pipeline")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  with gr.Row():
389
+ with gr.Column(scale=1):
390
+ gr.HTML(
391
+ """
392
+ <div class="pipeline-box">
393
+ <h3>Input</h3>
394
+ <p>Clinical image and structured patient metadata are jointly provided to the system.</p>
395
+ </div>
396
+ """
397
+ )
398
+ with gr.Column(scale=0):
399
+ gr.HTML('<div class="pipeline-arrow">β†’</div>')
400
+ with gr.Column(scale=1):
401
+ gr.HTML(
402
+ """
403
+ <div class="pipeline-box">
404
+ <h3>Multimodal Model</h3>
405
+ <p>Attention-based fusion integrates visual evidence with metadata-aware reasoning.</p>
406
+ </div>
407
+ """
408
+ )
409
+ with gr.Column(scale=0):
410
+ gr.HTML('<div class="pipeline-arrow">β†’</div>')
411
+ with gr.Column(scale=1):
412
+ gr.HTML(
413
+ """
414
+ <div class="pipeline-box">
415
+ <h3>Output</h3>
416
+ <p>The model returns a diagnosis, confidence information, and a GradCAM++ attention map.</p>
417
+ </div>
418
+ """
419
+ )
420
 
421
+ with gr.Group(elem_classes="section-card"):
422
+ gr.Markdown("## πŸ§ͺ Interactive Demonstration")
423
+ gr.Markdown(
424
+ "Modify the metadata, choose a model variant, and inspect how the attention map changes.",
425
+ elem_classes="soft-text",
426
+ )
427
 
428
  with gr.Row():
429
+ with gr.Column(scale=1, elem_classes="demo-panel"):
430
+ gr.Markdown("### πŸ“₯ Input Data")
431
+
432
+ image_input = gr.Image(type="pil", label="Dermoscopic Image", height=320)
433
+
434
+ group_selector = gr.CheckboxGroup(
435
+ choices=GROUP_CHOICES,
436
+ value=DEFAULT_GROUPS,
437
+ label="Enable Metadata Groups"
438
+ )
439
+
440
+ model_selector = gr.Dropdown(
441
+ choices=MODEL_CHOICES,
442
+ value=DEFAULT_MODEL_KEY if DEFAULT_MODEL_KEY is not None else None,
443
+ label="Attention Mechanism Model",
444
+ info="Choose which pretrained attention mechanism/model to run.",
445
+ )
446
+
447
+ with gr.Accordion("πŸ‘€ Demographics", open=True):
448
+ age = gr.Number(label="Age", value=55, precision=0)
449
+ with gr.Row():
450
+ gender = gr.Dropdown(GENDER_CHOICES, value="FEMALE", label="Gender")
451
+ region = gr.Dropdown(REGION_CHOICES, value="NECK", label="Region")
452
+
453
+ with gr.Accordion("πŸ“ Lesion Geometry", open=False):
454
+ with gr.Row():
455
+ diameter1 = gr.Number(label="Diameter 1", value=6)
456
+ diameter2 = gr.Number(label="Diameter 2", value=5)
457
 
458
+ with gr.Accordion("🚩 Symptoms", open=False):
459
+ with gr.Row():
460
+ itch = gr.Checkbox(label="Itch")
461
+ grew = gr.Checkbox(label="Grew")
462
+ hurt = gr.Checkbox(label="Hurt")
463
+ with gr.Row():
464
+ changed = gr.Checkbox(label="Changed")
465
+ bleed = gr.Checkbox(label="Bleed")
466
+ elevation = gr.Checkbox(label="Elevation")
467
 
468
+ with gr.Row():
469
+ clear_btn = gr.Button("Clear", variant="secondary")
470
+ run_btn = gr.Button("Generate GradCAM++", variant="primary", elem_classes="predict-btn")
471
+
472
+ with gr.Column(scale=2, elem_classes="demo-panel"):
473
+ gr.Markdown("### πŸ“Š Analysis Dashboard")
474
+
475
+ with gr.Row():
476
+ original_img_out = gr.Image(label="Original Lesion", interactive=False)
477
+ heatmap_out = gr.Image(label="Attention Map (GradCAM++)", interactive=False)
478
+
479
+ with gr.Group():
480
+ prediction_out = gr.Markdown(
481
+ value="### Prediction Result\n\nRun the model to see the output here."
482
+ )
483
+
484
+ with gr.Accordion("πŸ“‹ System Metadata Details", open=False):
485
+ active_groups_text = gr.Textbox(label="Active Groups", interactive=False)
486
+ metadata_preview = gr.Textbox(label="Final CSV Input", lines=6, interactive=False)
487
+
488
+ with gr.Group(elem_classes="section-card"):
489
+ gr.Markdown("## πŸ“š Notes for Readers")
490
+ gr.Markdown(
491
+ """
492
+ - This demo is intended as a qualitative companion to the paper.
493
+ - Users can inspect how metadata groups influence model behavior and attention maps.
494
+ - The available models correspond to pretrained multimodal attention-based variants.
495
+ - For best scientific use, this Space should be interpreted together with the associated manuscript.
496
+ """,
497
+ elem_classes="footer-note",
498
+ )
499
+
500
+ gr.Markdown("## πŸ“Ž Citation and Reproducibility")
501
+ gr.Markdown(
502
+ """
503
+ If you reference this demo in a paper, thesis, or presentation, cite the associated manuscript
504
+ and include the Hugging Face Space as supplementary interactive material.
505
+ """,
506
+ elem_classes="footer-note",
507
+ )
508
 
509
+ preview_inputs = [
510
+ group_selector, age, gender, region, diameter1, diameter2,
511
+ itch, grew, hurt, changed, bleed, elevation
512
+ ]
513
 
514
  for component in preview_inputs:
515
  component.change(