MTEST / app.py
zhang0319's picture
Upload 3 files
bb51627 verified
Raw
History Blame Contribute Delete
6.85 kB
from __future__ import annotations
import gradio as gr
from src.config import APP_TITLE, APP_MODE
from src.styles import APP_CSS
from src.inference import get_predictor
from src.imaging import nifti_preview
from src.ui_helpers import summary_html, interpretation_html, survival_figure
predictor = get_predictor()
HERO='''<section class="hero"><div class="eyebrow">AI-BEACON · Multimodal oncology research</div><h1>Individualized breast cancer prognosis</h1><p>Combine longitudinal MRI, segmentation, radiology text, and structured clinical variables in one transparent prognostic workflow.</p><div class="badge-row"><span class="badge">Research use only</span><span class="badge">Multimodal model</span><span class="badge">Mode: %s</span></div></section>''' % APP_MODE.title()
FLOW='''<div class="flow"><div class="flow-item"><b>01 · Eligibility</b>Confirm the intended cohort</div><div class="flow-item"><b>02 · Imaging</b>Upload MRI and mask data</div><div class="flow-item"><b>03 · Clinical profile</b>Review disease variables</div><div class="flow-item"><b>04 · Prognosis</b>Generate and interpret output</div></div>'''
def section(title, subtitle):
return f'<div class="section-title"><h3>{title}</h3><p>{subtitle}</p></div>'
def run_analysis(pre_mri, post_mri, mask, report, age, pre_stage, post_stage, family_history,
er, pr, her2, tumor_type, treatment, distant_metastasis):
try:
result=predictor.predict(pre_mri=pre_mri,post_mri=post_mri,mask=mask,report=report,age=age,
pre_stage=pre_stage,post_stage=post_stage,family_history=family_history,er=er,pr=pr,her2=her2,
tumor_type=tumor_type,treatment=treatment,distant_metastasis=distant_metastasis)
pre=nifti_preview(pre_mri,mask); post=nifti_preview(post_mri,mask)
return summary_html(result),survival_figure(result),pre,post,interpretation_html(result),"Analysis completed."
except Exception as exc:
raise gr.Error(str(exc))
def load_example(kind):
examples={
"Lower-risk example":["No","A small enhancing lesion with favorable treatment response and no suspicious nodal progression.",46,"I","0","No","Yes","Yes","No","Invasive ductal carcinoma","Neoadjuvant therapy completed"],
"Intermediate-risk example":["No","Residual enhancement and limited nodal disease are described after treatment.",58,"II","II","Yes","Yes","No","Yes","Invasive ductal carcinoma","Neoadjuvant therapy completed"],
"Higher-risk example":["No","Persistent extensive residual disease with nodal involvement and imaging features concerning for progression.",67,"III","III","No","No","No","No","Triple-negative breast cancer","Partial systemic treatment"],
}
return examples[kind]
with gr.Blocks(title=APP_TITLE, css=APP_CSS, theme=gr.themes.Base(primary_hue="slate",secondary_hue="blue",neutral_hue="slate",radius_size="lg",spacing_size="md")) as demo:
gr.HTML(HERO); gr.HTML(FLOW)
with gr.Row(equal_height=False):
with gr.Column(scale=5):
with gr.Group(elem_classes=["section-card"]):
gr.HTML(section("Eligibility","This workflow is designed for non-metastatic baseline assessment."))
distant_metastasis=gr.Radio(["No","Yes"],value="No",label="Distant metastasis at baseline")
with gr.Group(elem_classes=["section-card"]):
gr.HTML(section("Imaging and radiology report","Upload NIfTI volumes. A central-slice preview is generated after analysis."))
with gr.Row():
pre_mri=gr.File(label="Pre-treatment MRI",file_types=[".nii",".gz"],type="filepath",elem_classes=["upload-card"])
post_mri=gr.File(label="Post-treatment MRI",file_types=[".nii",".gz"],type="filepath",elem_classes=["upload-card"])
mask=gr.File(label="Segmentation mask",file_types=[".nii",".gz"],type="filepath",elem_classes=["upload-card"])
report=gr.Textbox(label="Radiology report",lines=7,placeholder="Paste the original radiology report...")
with gr.Column(scale=4):
with gr.Group(elem_classes=["section-card"]):
gr.HTML(section("Clinical profile","Provide the variables used by the prognostic model."))
with gr.Row(): age=gr.Number(label="Age",value=55,minimum=18,maximum=110); family_history=gr.Radio(["No","Yes"],value="No",label="Family history")
with gr.Row(): pre_stage=gr.Dropdown(["0","I","II","III","IV","Unknown"],value="II",label="Pre-treatment stage"); post_stage=gr.Dropdown(["0","I","II","III","IV","Unknown"],value="II",label="Post-treatment stage")
with gr.Row(): er=gr.Radio(["Yes","No"],value="Yes",label="ER positive"); pr=gr.Radio(["Yes","No"],value="Yes",label="PR positive"); her2=gr.Radio(["Yes","No"],value="No",label="HER2 positive")
tumor_type=gr.Dropdown(["Invasive ductal carcinoma","Invasive lobular carcinoma","Triple-negative breast cancer","Other"],value="Invasive ductal carcinoma",label="Tumor type")
treatment=gr.Dropdown(["Neoadjuvant therapy completed","Partial systemic treatment","Surgery first","Other"],value="Neoadjuvant therapy completed",label="Treatment")
with gr.Group(elem_classes=["section-card"]):
gr.HTML(section("Example profiles","Load clinical values for a fast interface test. Imaging files remain empty."))
example=gr.Dropdown(["Lower-risk example","Intermediate-risk example","Higher-risk example"],value="Intermediate-risk example",label="Example case")
load_btn=gr.Button("Load example",elem_classes=["secondary-action"])
run_btn=gr.Button("Generate prognostic assessment →",variant="primary",elem_classes=["primary-action"])
status=gr.Textbox(label="Status",interactive=False,value="Ready.")
gr.HTML('<div style="height:12px"></div>')
result_summary=gr.HTML()
with gr.Row():
with gr.Column(scale=6): curve=gr.Plot(label="Survival trajectory")
with gr.Column(scale=4):
with gr.Row(): pre_preview=gr.Image(label="Pre-treatment MRI",height=245); post_preview=gr.Image(label="Post-treatment MRI",height=245)
interpretation=gr.HTML()
gr.HTML('<div class="partner-strip"><span>Developed for translational research collaboration</span><div class="partner-names"><span>AI-BEACON</span><span>RUMC</span><span>NKI</span><span>BIG</span></div></div>')
example_outputs=[distant_metastasis,report,age,pre_stage,post_stage,family_history,er,pr,her2,tumor_type,treatment]
load_btn.click(load_example,inputs=example,outputs=example_outputs)
inputs=[pre_mri,post_mri,mask,report,age,pre_stage,post_stage,family_history,er,pr,her2,tumor_type,treatment,distant_metastasis]
run_btn.click(run_analysis,inputs=inputs,outputs=[result_summary,curve,pre_preview,post_preview,interpretation,status])
if __name__ == "__main__":
demo.queue(default_concurrency_limit=2).launch()