Siyad798's picture
Update app.py
3419cfb verified
Raw History Blame Contribute Delete
6.1 kB
import os
import shutil
import zipfile
import gradio as gr
import nibabel as nib
import numpy as np
import matplotlib.pyplot as plt
import tempfile
import subprocess
# ==========================================
# 1. DEEPISLES SETUP (Environment Trickery)
# ==========================================
os.environ['nnUNet_raw_data_base'] = '/tmp/nnUNet_raw_data_base'
os.environ['nnUNet_preprocessed'] = '/tmp/nnUNet_preprocessed'
os.environ['RESULTS_FOLDER'] = '/tmp/nnUNet_trained_models'
TASK_NAME = "Task012_Ischemic_Stroke_TM_Fullset"
TRAINER = "nnUNetTrainerV2_DDP__nnUNetPlansv2.1"
MODEL_PATH_INTERNAL = os.path.join(os.environ['RESULTS_FOLDER'], "nnUNet", "3d_fullres", TASK_NAME, TRAINER, "fold_0")
print("--- 🧠 Initializing DeepISLES Engine ---")
UPLOADED_WEIGHTS = "fold_0.zip"
if os.path.exists(UPLOADED_WEIGHTS):
if not os.path.exists(MODEL_PATH_INTERNAL):
print(f"📦 Installing {UPLOADED_WEIGHTS}...")
os.makedirs(MODEL_PATH_INTERNAL, exist_ok=True)
try:
with zipfile.ZipFile(UPLOADED_WEIGHTS, 'r') as zip_ref:
zip_ref.extractall(MODEL_PATH_INTERNAL)
print("✅ DeepISLES Weights Installed.")
except Exception as e:
print(f"❌ Error extracting weights: {e}")
else:
print(f"⚠️ CRITICAL: '{UPLOADED_WEIGHTS}' not found. Please upload it to the Files tab.")
# ==========================================
# 2. FILE HANDLING
# ==========================================
def find_sequences(extract_dir):
dwi = None
adc = None
for root, _, files in os.walk(extract_dir):
for f in files:
name = f.lower()
if "dwi" in name and ".nii" in name: dwi = os.path.join(root, f)
elif "adc" in name and ".nii" in name: adc = os.path.join(root, f)
return dwi, adc
def generate_overlay(dwi_path, mask_path):
try:
img = nib.load(dwi_path)
mask = nib.load(mask_path)
dwi = img.get_fdata()
seg = mask.get_fdata()
dwi = np.rot90(dwi, k=1, axes=(0, 1))
seg = np.rot90(seg, k=1, axes=(0, 1))
sums = np.sum(seg, axis=(0, 1))
idx = np.argmax(sums) if np.max(sums) > 0 else dwi.shape[2]//2
fig, ax = plt.subplots(figsize=(5, 5))
ax.imshow(dwi[:, :, idx], cmap="gray")
if np.max(seg) > 0:
overlay = np.zeros((*seg.shape[:2], 4))
overlay[seg[:, :, idx] > 0] = [1, 0, 0, 0.6]
ax.imshow(overlay)
ax.axis("off")
out_path = "/tmp/overlay.png"
plt.savefig(out_path, bbox_inches='tight')
plt.close()
return out_path
except:
return None
# ==========================================
# 3. INFERENCE ENGINE (nnU-Net Wrapper)
# ==========================================
def segment_stroke(zip_file):
if not zip_file: return {"error": "No file uploaded"}, None
work_dir = tempfile.mkdtemp()
input_dir = os.path.join(work_dir, "input")
output_dir = os.path.join(work_dir, "output")
os.makedirs(input_dir, exist_ok=True)
os.makedirs(output_dir, exist_ok=True)
try:
# Handle Gradio 5 file path string
file_path = zip_file.name if hasattr(zip_file, 'name') else zip_file
with zipfile.ZipFile(file_path, 'r') as z:
z.extractall(work_dir)
dwi, adc = find_sequences(work_dir)
if not dwi or not adc:
return {"status": "FAILED", "error": "DWI or ADC missing in zip"}, None
# Format for nnU-Net: 0000=DWI, 0001=ADC
shutil.copy(dwi, os.path.join(input_dir, "patient_0000.nii.gz"))
shutil.copy(adc, os.path.join(input_dir, "patient_0001.nii.gz"))
print("🚀 Running DeepISLES Inference...")
cmd = [
"nnUNet_predict",
"-i", input_dir,
"-o", output_dir,
"-t", "012",
"-m", "3d_fullres",
"-f", "0",
"--save_npz"
]
process = subprocess.run(cmd, capture_output=True, text=True)
if process.returncode != 0:
print("NNUNET ERROR:", process.stderr)
return {"status": "FAILED", "error": "Model inference failed. See logs."}, None
result_file = os.path.join(output_dir, "patient.nii.gz")
if os.path.exists(result_file):
mask_img = nib.load(result_file)
mask_data = mask_img.get_fdata()
zooms = mask_img.header.get_zooms()
vol_ml = (np.sum(mask_data > 0) * np.prod(zooms)) / 1000.0
risk = "LOW"
if vol_ml > 70: risk = "HIGH (Futile Recanalization?)"
elif vol_ml > 50: risk = "MODERATE"
report = {
"status": "SUCCESS",
"core_volume_ml": round(vol_ml, 2),
"risk_assessment": risk,
"model_used": "DeepISLES (nnU-Net Ensembled)"
}
overlay = generate_overlay(dwi, result_file)
return report, overlay
else:
return {"status": "FAILED", "error": "No output mask generated"}, None
except Exception as e:
return {"status": "CRASHED", "error": str(e)}, None
finally:
shutil.rmtree(work_dir, ignore_errors=True)
# ==========================================
# 4. UI
# ==========================================
with gr.Blocks() as demo:
gr.Markdown("# 👁️ Neuro-Triage: Vision Agent")
gr.Markdown("Upload Patient ZIP (DWI + ADC). Calculates Infarct Core Volume.")
with gr.Row():
with gr.Column():
inp = gr.File(label="Patient Data (.zip)", type="filepath")
btn = gr.Button("Calculate Core Volume", variant="primary")
with gr.Column():
out_json = gr.JSON(label="Clinical Report")
out_img = gr.Image(label="Lesion Map")
btn.click(segment_stroke, inputs=inp, outputs=[out_json, out_img])
if __name__ == "__main__":
demo.launch()