Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
import torch.nn as nn
|
| 4 |
+
import torch.nn.functional as F
|
| 5 |
+
from torchvision import models, transforms
|
| 6 |
+
import gradio as gr
|
| 7 |
+
import numpy as np
|
| 8 |
+
import cv2
|
| 9 |
+
from PIL import Image
|
| 10 |
+
|
| 11 |
+
# ==============================================================================
|
| 12 |
+
# 1. CORE CONFIGURATION & MODEL REGISTRY
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
IMG_SIZE = 128
|
| 15 |
+
LABELS = [
|
| 16 |
+
"Adenocarcinoma",
|
| 17 |
+
"Large Cell Carcinoma",
|
| 18 |
+
"Normal Tissue Profile",
|
| 19 |
+
"Squamous Cell Carcinoma"
|
| 20 |
+
]
|
| 21 |
+
|
| 22 |
+
class MedicalCLAHEEqualization(object):
|
| 23 |
+
"""
|
| 24 |
+
Applies Contrast Limited Adaptive Histogram Equalization to neutralize
|
| 25 |
+
scanner baseline variations, matching the front-end JS functionality exactly.
|
| 26 |
+
"""
|
| 27 |
+
def __call__(self, img):
|
| 28 |
+
img_np = np.array(img)
|
| 29 |
+
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
|
| 30 |
+
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
|
| 31 |
+
equalized = clahe.apply(gray)
|
| 32 |
+
return Image.fromarray(cv2.cvtColor(equalized, cv2.COLOR_GRAY2RGB))
|
| 33 |
+
|
| 34 |
+
# Re-establishing the exact validation transforms utilized during training
|
| 35 |
+
eval_transforms = transforms.Compose([
|
| 36 |
+
MedicalCLAHEEqualization(),
|
| 37 |
+
transforms.Resize((IMG_SIZE, IMG_SIZE)),
|
| 38 |
+
transforms.ToTensor(),
|
| 39 |
+
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
|
| 40 |
+
])
|
| 41 |
+
|
| 42 |
+
device = torch.device("cpu") # Hugging Face spaces run CPU pipelines by default
|
| 43 |
+
|
| 44 |
+
def load_bioset_cccm():
|
| 45 |
+
"""
|
| 46 |
+
Constructs the underlying EfficientNet-B0 blueprint structure
|
| 47 |
+
and binds the trained Bioset CCCM parameter weights.
|
| 48 |
+
"""
|
| 49 |
+
model = models.efficientnet_b0(weights=None)
|
| 50 |
+
in_features = model.classifier[1].in_features
|
| 51 |
+
model.classifier = nn.Sequential(
|
| 52 |
+
nn.Dropout(p=0.4, inplace=True),
|
| 53 |
+
nn.Linear(in_features, len(LABELS))
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
# Cascade verification checks to capture either weight file formatting variant
|
| 57 |
+
if os.path.exists('chestnet_efficientnet_weights.pth'):
|
| 58 |
+
model.load_state_dict(torch.load('chestnet_efficientnet_weights.pth', map_location=device))
|
| 59 |
+
elif os.path.exists('chestnet_efficientnet_full.pth'):
|
| 60 |
+
checkpoint = torch.load('chestnet_efficientnet_full.pth', map_location=device)
|
| 61 |
+
if hasattr(checkpoint, 'state_dict'):
|
| 62 |
+
model.load_state_dict(checkpoint.state_dict())
|
| 63 |
+
else:
|
| 64 |
+
model = checkpoint
|
| 65 |
+
|
| 66 |
+
model.eval()
|
| 67 |
+
return model
|
| 68 |
+
|
| 69 |
+
# Initialize the clinical architecture instance
|
| 70 |
+
model = load_bioset_cccm()
|
| 71 |
+
|
| 72 |
+
# ==============================================================================
|
| 73 |
+
# 2. RUNTIME INFERENCE FLOW PIPELINE
|
| 74 |
+
# ==============================================================================
|
| 75 |
+
def predict_chest_slice(input_image):
|
| 76 |
+
if input_image is None:
|
| 77 |
+
return "### Awaiting Ingestion Stream Vector...", {}
|
| 78 |
+
|
| 79 |
+
# Convert numpy array to PIL Image object context
|
| 80 |
+
pil_img = Image.fromarray(input_image.astype('uint8'), 'RGB')
|
| 81 |
+
tensor_input = eval_transforms(pil_img).unsqueeze(0).to(device)
|
| 82 |
+
|
| 83 |
+
with torch.no_grad():
|
| 84 |
+
logits = model(tensor_input)
|
| 85 |
+
probabilities = F.softmax(logits, dim=1).squeeze(0).numpy()
|
| 86 |
+
|
| 87 |
+
# Standardize result vectors into rank-ordered structures
|
| 88 |
+
indexed_results = [
|
| 89 |
+
{"label": LABELS[i], "prob": float(probabilities[i])}
|
| 90 |
+
for i in range(len(LABELS))
|
| 91 |
+
]
|
| 92 |
+
indexed_results.sort(key=lambda x: x["prob"], reverse=True)
|
| 93 |
+
|
| 94 |
+
# Compile premium Markdown summary readout for the UI header
|
| 95 |
+
top_winner = indexed_results[0]
|
| 96 |
+
output_summary = f"### Primary Classification: <span style='color:#22d3ee;font-weight:900;'>{top_winner['label']}</span> ({top_winner['prob']*100:.1f}%)"
|
| 97 |
+
|
| 98 |
+
# Return Top 3 classes for Gradio's responsive classification list
|
| 99 |
+
gradio_label_output = {item["label"]: item["prob"] for item in indexed_results[:3]}
|
| 100 |
+
|
| 101 |
+
return output_summary, gradio_label_output
|
| 102 |
+
|
| 103 |
+
# ==============================================================================
|
| 104 |
+
# 3. PREMIUM UI THEMING (DARK MODE SAAS AESTHETIC)
|
| 105 |
+
# ==============================================================================
|
| 106 |
+
saas_theme = gr.themes.Default(
|
| 107 |
+
primary_hue="cyan",
|
| 108 |
+
secondary_hue="slate",
|
| 109 |
+
neutral_hue="slate",
|
| 110 |
+
).set(
|
| 111 |
+
body_background_fill="#030712",
|
| 112 |
+
body_background_fill_dark="#030712",
|
| 113 |
+
block_background_fill="#0f172a",
|
| 114 |
+
block_background_fill_dark="#0f172a",
|
| 115 |
+
block_border_color="#1e293b",
|
| 116 |
+
block_border_width="1px",
|
| 117 |
+
panel_background_fill="#090d16",
|
| 118 |
+
container_radius="16px",
|
| 119 |
+
button_primary_background_fill="#06b6d4",
|
| 120 |
+
button_primary_text_color="#ffffff"
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
# ==============================================================================
|
| 124 |
+
# 4. COMPACT APP SURFACE DESIGN Layout
|
| 125 |
+
# ==============================================================================
|
| 126 |
+
with gr.Blocks(theme=saas_theme, title="Bioset CCCM Engine Deck") as demo:
|
| 127 |
+
|
| 128 |
+
# Top Identity Brand Layer
|
| 129 |
+
gr.Markdown(
|
| 130 |
+
"""
|
| 131 |
+
# <span style='color:#22d3ee;font-weight:900;letter-spacing:-0.025em;'>Bioset CCCM</span>
|
| 132 |
+
### Part of the **Bioset Model Collection** by **Infinitode** โข AI + Biology Initiative
|
| 133 |
+
---
|
| 134 |
+
"""
|
| 135 |
+
)
|
| 136 |
+
|
| 137 |
+
# Official Bioset Core Clinical Screening and Regulatory Disclaimers
|
| 138 |
+
gr.Markdown(
|
| 139 |
+
"""
|
| 140 |
+
<div style="background-color: rgba(239, 68, 68, 0.04); border: 1px solid rgba(239, 68, 68, 0.12); padding: 16px; border-radius: 14px; color: #fca5a5; font-size: 13px; line-height: 1.6; margin-bottom: 24px;">
|
| 141 |
+
<strong style="color: #fca5a5; text-transform: uppercase; letter-spacing: 0.05em; display: block; margin-bottom: 4px;">โ ๏ธ Bioset Model Registry Regulatory Notice</strong>
|
| 142 |
+
The Chest Cancer Classification Model (CCCM) is a regularized exploratory prototype engineered specifically for research evaluations inside computational biology domains. This architecture does not carry clinical validation certificates, is not cleared by the FDA or equivalent global healthcare oversight entities, and must never be deployed or relied upon as a primary proxy tool for human disease screening or medical case management.
|
| 143 |
+
</div>
|
| 144 |
+
"""
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
# Interactive Processing Grid Split
|
| 148 |
+
with gr.Row():
|
| 149 |
+
# Input Workspace Panel Area
|
| 150 |
+
with gr.Column(scale=5):
|
| 151 |
+
gr.Markdown("#### ๐ฅ Tissue Ingestion & Alignment")
|
| 152 |
+
|
| 153 |
+
input_image = gr.Image(
|
| 154 |
+
label="Axial Pulmonary CT Slice Matrix Input",
|
| 155 |
+
sources=["upload", "clipboard", "webcam"],
|
| 156 |
+
type="numpy",
|
| 157 |
+
tool="crop" # Enables high-fidelity crop, pan, and alignment controls on mobile + web
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
with gr.Row():
|
| 161 |
+
clear_btn = gr.Button("Clear Node", variant="secondary")
|
| 162 |
+
submit_btn = gr.Button("Evaluate Matrix Data", variant="primary")
|
| 163 |
+
|
| 164 |
+
# Ranked Diagnostics Output Panel Area
|
| 165 |
+
with gr.Column(scale=7):
|
| 166 |
+
gr.Markdown("#### ๐ Differential Analytics Report")
|
| 167 |
+
|
| 168 |
+
output_text = gr.Markdown("### Awaiting Ingestion Stream Vector...")
|
| 169 |
+
|
| 170 |
+
output_labels = gr.Label(
|
| 171 |
+
num_top_classes=3,
|
| 172 |
+
label="Rank-Ordered Softmax Probabilities"
|
| 173 |
+
)
|
| 174 |
+
|
| 175 |
+
gr.Markdown(
|
| 176 |
+
"""
|
| 177 |
+
<div style="background-color: rgba(15, 23, 42, 0.4); border: 1px solid #1e293b; padding: 12px; border-radius: 10px; font-size: 11px; color: #94a3b8; line-height: 1.5; margin-top: 12px;">
|
| 178 |
+
<strong>Pipeline Protocol:</strong> Input slices undergo local adaptive luminance leveling prior to network calculations. This mitigates hardware-specific baseline variance, focusing the model's extraction nodes entirely on tumor texture shapes.
|
| 179 |
+
</div>
|
| 180 |
+
"""
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
# Secondary Data Deck Layer: Compact Validation Profile Results
|
| 184 |
+
with gr.Accordion("๐ Model Profile & Performance Metrics Summary", open=True):
|
| 185 |
+
gr.Markdown(
|
| 186 |
+
"""
|
| 187 |
+
### Bioset Model Registry Evaluation Data (CCCM v1.4)
|
| 188 |
+
The following evaluation benchmarks were captured using an independent test set distribution following shape-equalization optimization:
|
| 189 |
+
|
| 190 |
+
<table style="width:100%; border-collapse: collapse; margin-top: 10px; font-size: 13px; color: #cbd5e1;">
|
| 191 |
+
<thead>
|
| 192 |
+
<tr style="border-b: 1px solid #334155; text-align: left; color: #94a3b8;">
|
| 193 |
+
<th style="padding: 10px 8px;">Target Validation Index</th>
|
| 194 |
+
<th style="padding: 10px 8px;">Metric Distribution</th>
|
| 195 |
+
<th style="padding: 10px 8px;">Infrastructure Scope</th>
|
| 196 |
+
</tr>
|
| 197 |
+
</thead>
|
| 198 |
+
<tbody>
|
| 199 |
+
<tr style="border-bottom: 1px solid #1e293b;">
|
| 200 |
+
<td style="padding: 10px 8px; font-weight: bold; color: #10b981;">Optimal Validation Accuracy</td>
|
| 201 |
+
<td style="padding: 10px 8px; font-family: monospace; font-weight: bold; color: #10b981;">93.06%</td>
|
| 202 |
+
<td style="padding: 10px 8px; color: #64748b;">Peak state convergence score</td>
|
| 203 |
+
</tr>
|
| 204 |
+
<tr style="border-bottom: 1px solid #1e293b;">
|
| 205 |
+
<td style="padding: 10px 8px; font-weight: bold;">Validation Loss Baseline</td>
|
| 206 |
+
<td style="padding: 10px 8px; font-family: monospace; color: #f43f5e;">0.1705</td>
|
| 207 |
+
<td style="padding: 10px 8px; color: #64748b;">Cross-Entropy loss ceiling</td>
|
| 208 |
+
</tr>
|
| 209 |
+
<tr style="border-bottom: 1px solid #1e293b;">
|
| 210 |
+
<td style="padding: 10px 8px; font-weight: bold; color: #22d3ee;">Highest Sample Confidence Target</td>
|
| 211 |
+
<td style="padding: 10px 8px; font-family: monospace; font-weight: bold; color: #22d3ee;">98.7%</td>
|
| 212 |
+
<td style="padding: 10px 8px; color: #64748b;">Verified on true positive test splits</td>
|
| 213 |
+
</tr>
|
| 214 |
+
<tr>
|
| 215 |
+
<td style="padding: 10px 8px; font-weight: bold;">Model footprint Volumetrics</td>
|
| 216 |
+
<td style="padding: 10px 8px; font-family: monospace;">16.6 MB</td>
|
| 217 |
+
<td style="padding: 10px 8px; color: #64748b;">Unified monolithic serialization array</td>
|
| 218 |
+
</tr>
|
| 219 |
+
</tbody>
|
| 220 |
+
</table>
|
| 221 |
+
"""
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
# Binding actionable runtime function sequences
|
| 225 |
+
submit_btn.click(
|
| 226 |
+
fn=predict_chest_slice,
|
| 227 |
+
inputs=[input_image],
|
| 228 |
+
outputs=[output_text, output_labels]
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
clear_btn.click(
|
| 232 |
+
fn=lambda: ("### Awaiting Ingestion Stream Vector...", {}),
|
| 233 |
+
inputs=None,
|
| 234 |
+
outputs=[output_text, output_labels]
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
if __name__ == "__main__":
|
| 238 |
+
demo.launch()
|