import gradio as gr from dataclasses import dataclass from datetime import date ANY = date.today().year # ----------------------------- # MODEL DE DADES # ----------------------------- @dataclass class Pacient: edat: int embaras: bool immuno: bool simptomes: str hsil: bool anys_lesio: int | None hister: str prev_adequat: bool prova: str any_prova: int | None citologia: str vph: str histologia: str marges: str # ----------------------------- # MOTOR DE DECISIÓ CLÍNICA # ----------------------------- def decidir(p: Pacient): # Símptomes d’alarma if p.simptomes != "Cap": return ("DERIVAR A COLPOSCÒPIA", "PRIORITARI", f"Símptoma d’alarma: {p.simptomes}") # Histerectomia sense coll if p.hister == "Sí, sense coll uterí": return ("NO CRIBRATGE", "INFORMATIU", "Histerectomia sense coll uterí") # Edat if p.edat < 25: return ("NO CRIBRATGE", "INFORMATIU", "Edat <25 anys") # 25–29 if 25 <= p.edat <= 29: if p.citologia == "Negativa": return ("REPETIR EN 3 ANYS", "INFORMATIU", "Citologia negativa") if p.citologia in ["ASC-US", "LSIL"]: return ("REPETIR EN 1 ANY", "RECOMANAT", "ASC-US/LSIL") if p.citologia in ["HSIL", "AGC", "AIS"]: return ("DERIVAR A COLPOSCÒPIA", "PRIORITARI", "Citologia d’alt grau") return ("FER CITOLOGIA", "RECOMANAT", "Cribratge 25–29") # 30–65 if 30 <= p.edat <= 65: if p.vph == "Negatiu": return ("REPETIR EN 5 ANYS", "INFORMATIU", "VPH negatiu") if p.vph in ["16", "18", "16/18"]: return ("DERIVAR A COLPOSCÒPIA", "PRIORITARI", "VPH16/18 positiu") if p.vph == "Altres": if p.citologia == "Negativa": return ("REPETIR VPH EN 1 ANY", "RECOMANAT", "Triage negatiu") return ("DERIVAR A COLPOSCÒPIA", "RECOMANAT", "Triage positiu") return ("FER PROVA VPH", "RECOMANAT", "Cribratge 30–65") # >65 if p.edat > 65: if p.prev_adequat: return ("FINALITZAR CRIBRATGE", "INFORMATIU", "Cribratge previ adequat") return ("FER CO-TEST", "RECOMANAT", "Sense cribratge adequat") return ("REVISAR", "ALERTA", "Cas no contemplat") # ----------------------------- # DECISIÓ AP (MANTINGUT) # ----------------------------- def decidir_ap(p: Pacient): if p.histologia == "Cap": return None if p.histologia == "LSIL": return ("SEGUIMENT", "RECOMANAT", "LSIL/CIN1") if p.histologia in ["HSIL2", "HSIL3"]: if p.marges == "Afectes": return ("CONTROL PRECOÇ", "PRIORITARI", "Marges afectes") return ("CO-TEST 3 ANYS", "RECOMANAT", "HSIL marges lliures") if p.histologia == "AIS": return ("SEGUIMENT PROLONGAT", "PRIORITARI", "AIS") if p.histologia == "Carcinoma": return ("DERIVACIÓ ONCOLÒGICA", "PRIORITARI", "Carcinoma invasiu") return None # ----------------------------- # COLOR PRIORITAT # ----------------------------- def color_prioritat(nivell: str) -> str: if nivell == "PRIORITARI": return "🔴 PRIORITARI" if nivell == "RECOMANAT": return "🟠 RECOMANAT" if nivell == "INFORMATIU": return "🟢 INFORMATIU" return nivell # ----------------------------- # FUNCIÓ PRINCIPAL # ----------------------------- def run_app( edat, embaras, immuno, simptomes, hsil, anys_lesio, hister, prev, prova, any_prova, citologia, vph, histologia, marges ): p = Pacient( edat=int(edat), embaras=embaras, immuno=immuno, simptomes=simptomes, hsil=hsil, anys_lesio=int(anys_lesio) if anys_lesio else None, hister=hister, prev_adequat=prev, prova=prova, any_prova=int(any_prova) if any_prova else None, citologia=citologia, vph=vph, histologia=histologia, marges=marges ) accio, nivell, rao = decidir(p) ap = decidir_ap(p) text_clinic = ( f"CRIBRATGE CÀNCER COLL UTERÍ.\n" f"ACCIÓ: {accio}.\n" f"MOTIU: {rao}.\n" f"EDAT: {p.edat} anys. HISTERECTOMIA: {p.hister}. " f"CRIBRATGE PREVI ADEQUAT: {'SÍ' if p.prev_adequat else 'NO'}." ) text_ap = "" if ap: text_ap = ( f"HISTOLOGIA: {p.histologia}. MARGES: {p.marges}. " f"ACCIÓ AP: {ap[0]}. MOTIU: {ap[2]}." ) nivell_col = color_prioritat(nivell) return accio, nivell_col, rao, text_clinic, text_ap # ----------------------------- # INTERFÍCIE GRADIO # ----------------------------- with gr.Blocks(title="Cribratge coll uterí – Catalunya 2023") as demo: gr.Markdown("## Algoritme de cribratge de càncer de coll uterí – Catalunya 2023") with gr.Row(): edat = gr.Number(label="Edat", value=35) embaras = gr.Checkbox(label="Embaràs actual") immuno = gr.Checkbox(label="Immunosupressió") simptomes = gr.Dropdown( label="Símptomes d’alarma", choices=[ "Cap", "Sagnat postcoital", "Sagnat intermenstrual", "Sagnat postmenopausa", "Fluix vaginal persistent", "Dolor pèlvic persistent", "Altres" ], value="Cap" ) hister = gr.Radio( label="Histerectomia", choices=[ "No", "Sí, amb coll uterí", "Sí, sense coll uterí" ], value="No" ) hsil = gr.Checkbox(label="Antecedent d’HSIL/CIN2+, AIS o càncer") anys_lesio = gr.Number(label="Anys des del tractament", value=0) prev = gr.Checkbox(label="Cribratge previ adequat") prova = gr.Radio( label="Tipus d’última prova", choices=["Cap / desconegut", "Citologia", "Prova VPH", "Co-test"], value="Cap / desconegut" ) any_prova = gr.Number( label="Any de l’última prova (opcional)", value=None, placeholder="Si no ho sap, deixar en blanc" ) citologia = gr.Radio( label="Resultat citologia", choices=["No aplica", "Negativa", "ASC-US", "LSIL", "HSIL", "AGC", "AIS"], value="No aplica" ) vph = gr.Radio( label="Resultat VPH", choices=["No aplica", "Negatiu", "Altres", "16", "18", "16/18"], value="No aplica" ) histologia = gr.Radio( label="Diagnòstic histològic", choices=["Cap", "LSIL", "HSIL2", "HSIL3", "AIS", "Carcinoma"], value="Cap" ) marges = gr.Radio( label="Marges quirúrgics", choices=["Cap", "Lliures", "Afectes"], value="Cap" ) boto = gr.Button("Calcular conducta") accio = gr.Textbox(label="Conducta recomanada") nivell = gr.Textbox(label="Prioritat") rao = gr.Textbox(label="Motiu") text_clinic = gr.Textbox(label="Text per història clínica") text_ap = gr.Textbox(label="Text per informe d’AP") boto.click( run_app, inputs=[ edat, embaras, immuno, simptomes, hsil, anys_lesio, hister, prev, prova, any_prova, citologia, vph, histologia, marges ], outputs=[accio, nivell, rao, text_clinic, text_ap] ) demo.launch()