crx / app.py
danieletx's picture
Upload app.py
070a601 verified
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()