Spaces:
Runtime error
Runtime error
Download ui.py from Gopal05/Report-Generatio-System-Radiology: direct link, hf CLI and curl.
- Browser
- Download file 27.5 kB
-
https://huggingface.co/spaces/Gopal05/Report-Generatio-System-Radiology/resolve/main/ui.py
- Command line
-
hf download hf://spaces/Gopal05/Report-Generatio-System-Radiology/ui.py
-
curl -L -o ui.py https://huggingface.co/spaces/Gopal05/Report-Generatio-System-Radiology/resolve/main/ui.py
27.5 kB
| """ | |
| ui.py - Gradio 6.x compatible UI - Extended timeout version | |
| """ | |
| import json | |
| import logging | |
| import os | |
| from pathlib import Path | |
| import gradio as gr | |
| import httpx | |
| logger = logging.getLogger(__name__) | |
| BACKEND_URL = "http://127.0.0.1:8000" | |
| REQUEST_TIMEOUT = 600 # 10 minutes β Phi-2 on CPU is slow | |
| CUSTOM_CSS = """ | |
| .gr-markdown h1 { font-size: 2rem !important; color: #1a4a8a !important; font-weight: 700; border-bottom: 3px solid #1a4a8a; padding-bottom: 8px; } | |
| .gr-markdown h3 { color: #1a4a8a !important; font-weight: 600; } | |
| #report-box textarea { font-family: 'Courier New', monospace !important; font-size: 13px !important; line-height: 1.7 !important; background: #1e1e2e !important; color: #e0e0e0 !important; border: 1.5px solid #1a4a8a !important; border-radius: 8px !important; } | |
| """ | |
| def _check_backend() -> bool: | |
| try: | |
| r = httpx.get(f"{BACKEND_URL}/api/health", timeout=5) | |
| return r.status_code == 200 | |
| except Exception: | |
| return False | |
| def _call_generate_report(image_path, patient_name, patient_age, patient_gender, | |
| symptoms, clinical_history, modality, body_region, view): | |
| with open(image_path, "rb") as f: | |
| image_bytes = f.read() | |
| filename = Path(image_path).name | |
| with httpx.Client(timeout=REQUEST_TIMEOUT) as client: | |
| response = client.post( | |
| f"{BACKEND_URL}/api/generate-report", | |
| files={"image": (filename, image_bytes, "application/octet-stream")}, | |
| data={ | |
| "patient_name": patient_name, | |
| "patient_age": str(patient_age), | |
| "patient_gender": patient_gender, | |
| "symptoms": symptoms, | |
| "clinical_history": clinical_history, | |
| "modality": modality, | |
| "body_region": body_region, | |
| "view": view, | |
| }, | |
| ) | |
| response.raise_for_status() | |
| return response.json() | |
| def generate_report(image_file, patient_name, patient_age, patient_gender, | |
| symptoms, clinical_history, modality, body_region, view): | |
| if image_file is None: | |
| return "", "", "β οΈ Please upload a radiology image.", "", "β No image uploaded." | |
| if not patient_name or not patient_name.strip(): | |
| return "", "", "β οΈ Please enter the patient name.", "", "β Patient name required." | |
| if not patient_age or int(patient_age) <= 0: | |
| return "", "", "β οΈ Please enter a valid patient age.", "", "β Invalid age." | |
| if not symptoms.strip(): | |
| return "", "", "β οΈ Please enter presenting symptoms.", "", "β Symptoms required." | |
| if not _check_backend(): | |
| return "", "", "β Backend offline. Run: uvicorn backend.main:app --reload", "", "β Backend offline." | |
| try: | |
| data = _call_generate_report( | |
| image_path=image_file, | |
| patient_name=patient_name.strip(), | |
| patient_age=int(patient_age), | |
| patient_gender=patient_gender, | |
| symptoms=symptoms, | |
| clinical_history=clinical_history, | |
| modality=modality, | |
| body_region=body_region, | |
| view=view, | |
| ) | |
| except httpx.ReadTimeout: | |
| err = "β Request timed out β model is still processing. Wait 2 min and try again, or restart backend." | |
| return "", "", err, "", err | |
| except httpx.HTTPStatusError as exc: | |
| err = f"β Server error {exc.response.status_code}: {exc.response.text[:200]}" | |
| return "", "", err, "", err | |
| except Exception as exc: | |
| err = f"β Request failed: {exc}" | |
| return "", "", err, "", err | |
| report = data.get("report", {}) | |
| validation = data.get("validation", {}) | |
| report_id = data.get("report_id", "") | |
| confidence = validation.get("confidence_score", 0.0) | |
| gen_time = report.get("generation_time_seconds", 0) | |
| report_text = data.get("report_text", "") | |
| if not report_text: | |
| r = data.get("report", {}) | |
| report_text = f"""RADIOLOGY REPORT | |
| {'='*60} | |
| EXAMINATION DETAILS: | |
| {r.get('examination_details','β')} | |
| CLINICAL INFORMATION: | |
| {r.get('clinical_information','β')} | |
| FINDINGS: | |
| {r.get('findings','β')} | |
| IMPRESSION: | |
| {r.get('impression','β')} | |
| RECOMMENDATIONS: | |
| {r.get('recommendations','β')} | |
| CONFIDENCE SCORE: {confidence:.2f} | |
| {'='*60} | |
| END OF REPORT""" | |
| if confidence >= 0.80: | |
| conf_label, conf_color = "HIGH", "#138808" | |
| elif confidence >= 0.60: | |
| conf_label, conf_color = "MODERATE", "#e67e00" | |
| else: | |
| conf_label, conf_color = "LOW", "#c0392b" | |
| confidence_html = f""" | |
| <div style="text-align:center;padding:16px;background:#f0f6ff; | |
| border:2px solid #1a4a8a;border-radius:12px;margin-top:8px;"> | |
| <div style="font-size:0.85rem;color:#555;margin-bottom:4px;">CONFIDENCE SCORE</div> | |
| <div style="font-size:1.5rem;font-weight:bold;color:{conf_color};"> | |
| {confidence:.2f} β {conf_label} | |
| </div> | |
| <div style="font-size:0.78rem;color:#888;margin-top:6px;"> | |
| Generated in {gen_time:.1f}s | |
| </div> | |
| </div>""" | |
| issues = validation.get("issues", []) | |
| warnings = validation.get("warnings", []) | |
| suggestions = validation.get("suggestions", []) | |
| section_scores = validation.get("section_scores", {}) | |
| val_lines = ["**Validation Results**\n"] | |
| val_lines.append(f"{'β VALID' if validation.get('is_valid') else 'β οΈ REVIEW NEEDED'}") | |
| if section_scores: | |
| val_lines.append("\n**Section Scores:**") | |
| for sec, score in section_scores.items(): | |
| bar = "β" * int(score * 10) + "β" * (10 - int(score * 10)) | |
| val_lines.append(f" {sec.replace('_',' ').title()}: {bar} {score:.2f}") | |
| if issues: | |
| val_lines.append("\n**Issues:**") | |
| val_lines.extend(f" β {i}" for i in issues) | |
| if warnings: | |
| val_lines.append("\n**Warnings:**") | |
| val_lines.extend(f" β οΈ {w}" for w in warnings) | |
| if suggestions: | |
| val_lines.append("\n**Suggestions:**") | |
| val_lines.extend(f" π‘ {s}" for s in suggestions) | |
| # Medical Coding Block | |
| coding = data.get("medical_coding", {}) | |
| val_lines.append("\n---") | |
| val_lines.append("## Medical Coding (UMLS / ICD-10 / SNOMED CT)") | |
| if coding and coding.get("total_findings", 0) > 0: | |
| primary = coding.get("primary_diagnosis", {}) | |
| val_lines.append(f"**Primary Diagnosis:** {primary.get('label','β')} | CUI: {primary.get('cui','β')}") | |
| val_lines.append(f"**Overall Severity:** {coding.get('overall_severity','β')}") | |
| icd_list = coding.get("icd10_codes", []) | |
| if icd_list: | |
| val_lines.append(f"**ICD-10 Codes:** {' | '.join(icd_list)}") | |
| val_lines.append(f"**All Concepts Found ({coding.get('total_findings',0)}):**") | |
| for mc in coding.get("medical_codes", []): | |
| val_lines.append(f" * {mc['label']} | CUI: {mc['cui']} | ICD-10: {mc['icd10']} | Severity: {mc['severity']}") | |
| else: | |
| val_lines.append("No significant pathological concepts detected (normal study).") | |
| validation_text = "\n".join(val_lines) | |
| status_final = f"β Report generated | ID: {report_id[:8]}" | |
| return report_text, confidence_html, validation_text, report_id, status_final | |
| def _downloads_dir() -> Path: | |
| """Returns a temp download folder that works on both Windows and Linux.""" | |
| d = Path(os.environ.get("TEMP", os.environ.get("TMP", "/tmp"))) / "radiology_reports" | |
| d.mkdir(parents=True, exist_ok=True) | |
| return d | |
| def export_pdf(report_id): | |
| if not report_id: | |
| return None | |
| try: | |
| r = httpx.get(f"{BACKEND_URL}/api/export/pdf/{report_id}", timeout=60) | |
| r.raise_for_status() | |
| path = _downloads_dir() / f"radiology_report_{report_id[:8]}.pdf" | |
| with open(path, "wb") as f: | |
| f.write(r.content) | |
| logger.info(f"PDF saved: {path}") | |
| return str(path) | |
| except Exception as exc: | |
| logger.error(f"PDF export error: {exc}") | |
| return None | |
| def export_json_file(report_id): | |
| if not report_id: | |
| return None | |
| try: | |
| r = httpx.get(f"{BACKEND_URL}/api/export/json/{report_id}", timeout=30) | |
| r.raise_for_status() | |
| path = _downloads_dir() / f"radiology_report_{report_id[:8]}.json" | |
| with open(path, "wb") as f: | |
| f.write(r.content) | |
| logger.info(f"JSON saved: {path}") | |
| return str(path) | |
| except Exception as exc: | |
| logger.error(f"JSON export error: {exc}") | |
| return None | |
| def fill_demo(): | |
| return ( | |
| 45, "Male", | |
| "Left abdominal pain, swelling of the abdominal wall, fever", | |
| "Suspected abdominal wall infection.", | |
| "CT", "Abdomen", "Axial", | |
| ) | |
| def check_backend_status(): | |
| if _check_backend(): | |
| return "π’ Backend online β ready to generate reports." | |
| return "π΄ Backend offline β run: uvicorn backend.main:app --reload" | |
| def fetch_report_history(): | |
| """Fetch all reports from DB for history tab.""" | |
| try: | |
| r = httpx.get(f"{BACKEND_URL}/api/reports?limit=50", timeout=10) | |
| r.raise_for_status() | |
| reports = r.json().get("reports", []) | |
| if not reports: | |
| return "No reports found in database yet." | |
| lines = ["| Patient Name | Age | Gender | Modality | Region | Confidence | Date |", | |
| "|---|---|---|---|---|---|---|"] | |
| for rep in reports: | |
| conf = rep.get("confidence_score", 0) or 0 | |
| lines.append( | |
| f"| {rep.get('patient_name','β')} " | |
| f"| {rep.get('age','β')} " | |
| f"| {rep.get('gender','β')} " | |
| f"| {rep.get('modality','β')} " | |
| f"| {rep.get('body_region','β')} " | |
| f"| {conf:.2f} " | |
| f"| {str(rep.get('created_at','β'))[:16]} |" | |
| ) | |
| return "\n".join(lines) | |
| except Exception as e: | |
| return f"β Could not load history: {e}" | |
| def fetch_db_stats(): | |
| """Fetch database statistics.""" | |
| try: | |
| r = httpx.get(f"{BACKEND_URL}/api/stats", timeout=10) | |
| r.raise_for_status() | |
| s = r.json() | |
| mod_counts = s.get("modality_counts", {}) | |
| mod_text = " | ".join(f"{k}: {v}" for k,v in mod_counts.items()) | |
| return ( | |
| f"**Total Reports:** {s.get('total_reports', 0)} \n" | |
| f"**Unique Patients:** {s.get('total_patients', 0)} \n" | |
| f"**Avg Confidence:** {s.get('avg_confidence', 0):.2f} \n" | |
| f"**By Modality:** {mod_text or 'None yet'}" | |
| ) | |
| except Exception as e: | |
| return f"β Could not load stats: {e}" | |
| def search_patient_reports(name: str): | |
| """Search reports by patient name.""" | |
| if not name.strip(): | |
| return "Enter a patient name to search." | |
| try: | |
| r = httpx.get( | |
| f"{BACKEND_URL}/api/reports/patient/{name.strip()}", | |
| timeout=10 | |
| ) | |
| r.raise_for_status() | |
| data = r.json() | |
| reports = data.get("reports", []) | |
| if not reports: | |
| return f"No reports found for patient: {name}" | |
| lines = [f"**{len(reports)} report(s) found for: {name}**\n", | |
| "| Date | Modality | Region | Confidence | Impression |", | |
| "|---|---|---|---|---|"] | |
| for rep in reports: | |
| conf = rep.get("confidence_score", 0) or 0 | |
| imp = str(rep.get("impression","β"))[:60] + "..." | |
| lines.append( | |
| f"| {str(rep.get('created_at','β'))[:16]} " | |
| f"| {rep.get('modality','β')} " | |
| f"| {rep.get('body_region','β')} " | |
| f"| {conf:.2f} " | |
| f"| {imp} |" | |
| ) | |
| return "\n".join(lines) | |
| except Exception as e: | |
| return f"β Search failed: {e}" | |
| def get_report_uuids_for_patient(name: str): | |
| """Returns list of (label, uuid) tuples for a patient's reports.""" | |
| if not name.strip(): | |
| return [] | |
| try: | |
| r = httpx.get( | |
| f"{BACKEND_URL}/api/reports/patient/{name.strip()}", timeout=10 | |
| ) | |
| r.raise_for_status() | |
| reports = r.json().get("reports", []) | |
| choices = [] | |
| for rep in reports: | |
| label = ( | |
| f"{str(rep.get('created_at',''))[:16]} | " | |
| f"{rep.get('modality','β')} {rep.get('body_region','β')} | " | |
| f"Conf: {rep.get('confidence_score',0):.2f}" | |
| ) | |
| choices.append((label, rep.get("report_uuid", ""))) | |
| return choices | |
| except Exception: | |
| return [] | |
| def load_patient_report_choices(name: str): | |
| """Populate the dropdown with patient's reports.""" | |
| choices = get_report_uuids_for_patient(name) | |
| if not choices: | |
| return gr.update(choices=[], value=None, | |
| label="No reports found for this patient") | |
| return gr.update(choices=choices, value=choices[0][1], | |
| label=f"{len(choices)} report(s) found β select one to download") | |
| def download_report_pdf(report_uuid: str): | |
| """Download PDF for a specific report UUID from DB.""" | |
| if not report_uuid: | |
| return None | |
| try: | |
| r = httpx.get( | |
| f"{BACKEND_URL}/api/export/pdf/{report_uuid}", timeout=60 | |
| ) | |
| r.raise_for_status() | |
| path = _downloads_dir() / f"report_{report_uuid[:8]}.pdf" | |
| with open(path, "wb") as f: | |
| f.write(r.content) | |
| return str(path) | |
| except Exception as exc: | |
| logger.error(f"PDF download failed: {exc}") | |
| return None | |
| def download_report_json(report_uuid: str): | |
| """Download JSON for a specific report UUID from DB.""" | |
| if not report_uuid: | |
| return None | |
| try: | |
| r = httpx.get( | |
| f"{BACKEND_URL}/api/export/json/{report_uuid}", timeout=30 | |
| ) | |
| r.raise_for_status() | |
| path = _downloads_dir() / f"report_{report_uuid[:8]}.json" | |
| with open(path, "wb") as f: | |
| f.write(r.content) | |
| return str(path) | |
| except Exception as exc: | |
| logger.error(f"JSON download failed: {exc}") | |
| return None | |
| def preview_selected_report(report_uuid: str): | |
| """Show full report text for selected report UUID.""" | |
| if not report_uuid: | |
| return "Select a report to preview." | |
| try: | |
| r = httpx.get( | |
| f"{BACKEND_URL}/api/report/{report_uuid}", timeout=10 | |
| ) | |
| r.raise_for_status() | |
| data = r.json() | |
| rep = data.get("report", {}) | |
| pat = data.get("patient", {}) | |
| img = data.get("imaging", {}) | |
| valid = data.get("validation", {}) | |
| conf = valid.get("confidence_score", rep.get("confidence_score", 0)) or 0 | |
| name = data.get("patient_name", pat.get("name", "Unknown")) | |
| return f"""RADIOLOGY REPORT | |
| {'='*60} | |
| Patient Name : {name} | |
| Age / Gender : {pat.get('age','β')} / {pat.get('gender','β')} | |
| Study : {img.get('modality','β')} {img.get('body_region','β')} {img.get('view','') or ''} | |
| Date : {str(data.get('timestamp',''))[:16]} | |
| {'='*60} | |
| EXAMINATION DETAILS: | |
| {rep.get('examination_details','β')} | |
| CLINICAL INFORMATION: | |
| {rep.get('clinical_information','β')} | |
| FINDINGS: | |
| {rep.get('findings','β')} | |
| IMPRESSION: | |
| {rep.get('impression','β')} | |
| RECOMMENDATIONS: | |
| {rep.get('recommendations','β')} | |
| CONFIDENCE SCORE: {conf:.2f} | |
| {'='*60} | |
| END OF REPORT""" | |
| except Exception as exc: | |
| return f"β Could not load report: {exc}" | |
| def build_interface() -> gr.Blocks: | |
| with gr.Blocks(title="Radiology AI β Report Generation System") as demo: | |
| report_id_state = gr.State("") | |
| gr.Markdown( | |
| "# π₯ Radiology AI β Report Generation System\n" | |
| "### AI-Based Structured Radiology Report Generation with Clinical Validation & Patient Database" | |
| ) | |
| backend_status = gr.Markdown("π΄ Checking backendβ¦") | |
| with gr.Tabs(): | |
| # ββ TAB 1: Generate Report βββββββββββββββββββββββββββββββββ | |
| with gr.Tab("π Generate Report"): | |
| gr.Markdown( | |
| "> β³ **Note:** First report generation takes **30β60 seconds on GPU**. " | |
| "Please click Generate Report and wait β do not click again." | |
| ) | |
| with gr.Row(equal_height=False): | |
| # LEFT: Inputs | |
| with gr.Column(scale=1, min_width=340): | |
| gr.Markdown("### π€ Step 1: Upload Radiology Image") | |
| image_input = gr.File( | |
| label="Upload Image (.dcm / .png / .jpg)", | |
| file_types=[".dcm", ".png", ".jpg", ".jpeg"], | |
| type="filepath", | |
| ) | |
| image_preview = gr.Image( | |
| label="Preview", | |
| interactive=False, | |
| height=220, | |
| ) | |
| gr.Markdown("### π€ Step 2: Patient Information") | |
| patient_name = gr.Textbox( | |
| label="Patient Name", | |
| placeholder="e.g. John Smith", | |
| lines=1, | |
| ) | |
| with gr.Row(): | |
| patient_age = gr.Number( | |
| label="Age (years)", minimum=0, maximum=130, step=1, value=50 | |
| ) | |
| patient_gender = gr.Dropdown( | |
| label="Gender", | |
| choices=["Male", "Female", "Other"], | |
| value="Male", | |
| ) | |
| symptoms = gr.Textbox( | |
| label="Presenting Symptoms", | |
| placeholder="e.g. abdominal pain, fever, swelling", | |
| lines=2, | |
| ) | |
| clinical_history = gr.Textbox( | |
| label="Clinical History", | |
| placeholder="e.g. suspected infection, prior surgeries", | |
| lines=2, | |
| ) | |
| gr.Markdown("### π¬ Step 3: Imaging Information") | |
| with gr.Row(): | |
| modality = gr.Dropdown( | |
| label="Modality", | |
| choices=[ | |
| "X-ray", "CT", "MRI", "Ultrasound", "PET", | |
| "Mammography", "Fluoroscopy", "Angiography", | |
| "Nuclear Medicine", | |
| ], | |
| value="X-ray", | |
| ) | |
| body_region = gr.Dropdown( | |
| label="Body Region", | |
| choices=[ | |
| "Chest", "Brain", "Abdomen", "Pelvis", | |
| "Spine", "Knee", "Hip", "Shoulder", "Neck", | |
| "Cardiac", "Breast", "Liver", "Kidney", | |
| "Thyroid", "Hand", "Wrist", "Foot", "Ankle", | |
| "Skull", "Prostate", "Obstetric", "Vascular", | |
| ], | |
| value="Chest", | |
| ) | |
| view = gr.Dropdown( | |
| label="View / Projection", | |
| choices=[ | |
| "PA", "AP", "Lateral", "Axial", "Coronal", | |
| "Sagittal", "Oblique", "Left Lateral", "Right Lateral", | |
| "Supine", "Prone", "Decubitus", "Cephalocaudal (CC)", | |
| "Mediolateral Oblique (MLO)", "T1", "T2", "FLAIR", | |
| "DWI", "STIR", "", | |
| ], | |
| value="PA", | |
| ) | |
| with gr.Row(): | |
| demo_btn = gr.Button("π Fill Demo", variant="secondary", size="sm") | |
| generate_btn = gr.Button("π Generate Report", variant="primary", size="lg") | |
| status_label = gr.Markdown("") | |
| # RIGHT: Outputs | |
| with gr.Column(scale=2, min_width=480): | |
| gr.Markdown("### π Generated Radiology Report") | |
| report_output = gr.Textbox( | |
| label="Structured Report", | |
| lines=22, | |
| interactive=False, | |
| elem_id="report-box", | |
| ) | |
| confidence_output = gr.HTML( | |
| value="<div style='text-align:center;color:#aaa;padding:16px;'>" | |
| "Confidence score will appear here after generation.</div>" | |
| ) | |
| with gr.Accordion("π Validation Details", open=False): | |
| validation_output = gr.Markdown("") | |
| gr.Markdown("### πΎ Export Report") | |
| with gr.Row(): | |
| export_pdf_btn = gr.Button("β¬οΈ Download PDF", variant="secondary") | |
| export_json_btn = gr.Button("β¬οΈ Download JSON", variant="secondary") | |
| pdf_file = gr.File(label="PDF Report", visible=False) | |
| json_file = gr.File(label="JSON Report", visible=False) | |
| # ββ TAB 2: Patient History βββββββββββββββββββββββββββββββββ | |
| with gr.Tab("π Patient History"): | |
| gr.Markdown("## π Report History Database") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Search by Patient Name") | |
| search_input = gr.Textbox( | |
| label="Patient Name", placeholder="e.g. John Smith" | |
| ) | |
| search_btn = gr.Button("π Search", variant="primary") | |
| search_output = gr.Markdown("") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Database Statistics") | |
| stats_output = gr.Markdown("") | |
| refresh_stats_btn = gr.Button("π Refresh Stats", variant="secondary") | |
| # ββ Download Previous Reports ββββββββββββββββββββββββββ | |
| gr.Markdown("---") | |
| gr.Markdown("### β¬οΈ Download Previous Reports") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| dl_patient_input = gr.Textbox( | |
| label="Enter Patient Name to Load Reports", | |
| placeholder="e.g. Gopalamanikandan A", | |
| ) | |
| dl_load_btn = gr.Button( | |
| "π Load Reports for This Patient", | |
| variant="primary" | |
| ) | |
| report_selector = gr.Dropdown( | |
| label="Select Report to Download", | |
| choices=[], | |
| value=None, | |
| interactive=True, | |
| ) | |
| with gr.Column(scale=2): | |
| gr.Markdown("#### ποΈ Report Preview") | |
| report_preview = gr.Textbox( | |
| label="Selected Report", | |
| lines=18, | |
| interactive=False, | |
| elem_id="report-box", | |
| ) | |
| with gr.Row(): | |
| dl_pdf_btn = gr.Button("β¬οΈ Download PDF", variant="secondary") | |
| dl_json_btn = gr.Button("β¬οΈ Download JSON", variant="secondary") | |
| dl_pdf_file = gr.File(label="PDF", visible=False) | |
| dl_json_file = gr.File(label="JSON", visible=False) | |
| # ββ All Reports Table ββββββββββββββββββββββββββββββββββ | |
| gr.Markdown("---") | |
| gr.Markdown("### π All Reports") | |
| history_btn = gr.Button("π Load All Reports", variant="secondary") | |
| history_output = gr.Markdown("") | |
| # ββ Events ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| image_input.change(fn=lambda f: f, inputs=image_input, outputs=image_preview) | |
| demo_btn.click( | |
| fn=fill_demo, inputs=[], | |
| outputs=[patient_age, patient_gender, symptoms, clinical_history, | |
| modality, body_region, view], | |
| ) | |
| generate_btn.click( | |
| fn=generate_report, | |
| inputs=[image_input, patient_name, patient_age, patient_gender, | |
| symptoms, clinical_history, modality, body_region, view], | |
| outputs=[report_output, confidence_output, validation_output, | |
| report_id_state, status_label], | |
| ) | |
| export_pdf_btn.click( | |
| fn=export_pdf, inputs=[report_id_state], outputs=[pdf_file], | |
| ).then( | |
| fn=lambda f: gr.update(visible=f is not None), | |
| inputs=[pdf_file], outputs=[pdf_file], | |
| ) | |
| export_json_btn.click( | |
| fn=export_json_file, inputs=[report_id_state], outputs=[json_file], | |
| ).then( | |
| fn=lambda f: gr.update(visible=f is not None), | |
| inputs=[json_file], outputs=[json_file], | |
| ) | |
| # History tab events | |
| history_btn.click( | |
| fn=fetch_report_history, inputs=[], outputs=[history_output] | |
| ) | |
| search_btn.click( | |
| fn=search_patient_reports, inputs=[search_input], outputs=[search_output] | |
| ) | |
| refresh_stats_btn.click( | |
| fn=fetch_db_stats, inputs=[], outputs=[stats_output] | |
| ) | |
| # Download previous report events | |
| dl_load_btn.click( | |
| fn=load_patient_report_choices, | |
| inputs=[dl_patient_input], | |
| outputs=[report_selector], | |
| ) | |
| report_selector.change( | |
| fn=preview_selected_report, | |
| inputs=[report_selector], | |
| outputs=[report_preview], | |
| ) | |
| dl_pdf_btn.click( | |
| fn=download_report_pdf, | |
| inputs=[report_selector], | |
| outputs=[dl_pdf_file], | |
| ).then( | |
| fn=lambda f: gr.update(visible=f is not None), | |
| inputs=[dl_pdf_file], outputs=[dl_pdf_file], | |
| ) | |
| dl_json_btn.click( | |
| fn=download_report_json, | |
| inputs=[report_selector], | |
| outputs=[dl_json_file], | |
| ).then( | |
| fn=lambda f: gr.update(visible=f is not None), | |
| inputs=[dl_json_file], outputs=[dl_json_file], | |
| ) | |
| demo.load(fn=check_backend_status, outputs=[backend_status]) | |
| demo.load(fn=fetch_db_stats, outputs=[stats_output]) | |
| return demo | |
| if __name__ == "__main__": | |
| logging.basicConfig(level=logging.INFO) | |
| interface = build_interface() | |
| interface.launch( | |
| server_name="0.0.0.0", | |
| server_port=int(os.getenv("GRADIO_PORT", "7860")), | |
| share=False, | |
| show_error=True, | |
| css=CUSTOM_CSS, | |
| theme=gr.themes.Soft(primary_hue="blue", neutral_hue="slate"), | |
| ) | |