MagoPredator commited on
Commit
f06d618
·
verified ·
1 Parent(s): 229086c

chore: inject app.py to root for Streamlit Space

Browse files
Files changed (1) hide show
  1. app.py +99 -0
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Interfaz visual interactiva para pathogen-forecast (streamlit + folium)."""
3
+ # Copyright (C) 2026 Pedro Sordo Martínez <amurlaniakea@gmail.com>
4
+ # SPDX-License-Identifier: AGPL-3.0-or-later
5
+
6
+ from pathlib import Path
7
+
8
+ import folium
9
+ import streamlit as st
10
+ from streamlit_folium import st_folium
11
+
12
+ from data_loader import DataLoader
13
+ from epimodels import ModeloSEIR
14
+ from optimizer import OptimizadorSIR
15
+
16
+ st.set_page_config(page_title="pathogen-forecast", layout="wide")
17
+ st.title("pathogen-forecast — Predicción epidemiológica institucional")
18
+ st.markdown("**Autor:** Pedro Sordo Martínez <amurlaniakea@gmail.com> | **Licencia:** AGPL-3.0-or-later")
19
+
20
+ # Controles interactivos
21
+ col1, col2 = st.columns(2)
22
+ with col1:
23
+ r_contagiosidad = st.slider("R de contagiosidad (reproduction_rate aproximado)", 0.5, 10.0, 3.0, 0.1)
24
+ dias = st.slider("Días de simulación", 30, 730, 365, 30)
25
+ with col2:
26
+ pais = st.selectbox("País inicial (ejemplo del dataset)", ["Spain", "Afghanistan", "United States", "Global"])
27
+ poblacion = st.number_input("Población base (millones)", 1.0, 8000.0, 8.0, 1.0) * 1_000_000
28
+
29
+ import os
30
+
31
+ # Datos sintéticos por defecto (o dataset real si existe, vía env var)
32
+ ruta_env = os.getenv("COVID_DATASET_PATH", "")
33
+ ruta_dataset = Path(ruta_env) if ruta_env else Path(__file__).resolve().parent.parent / "tests" / "fixtures" / "synthetic_covid.csv"
34
+ if ruta_dataset.exists():
35
+ loader = DataLoader(ruta_dataset)
36
+ datos = loader.cargar_datos()
37
+ else:
38
+ loader = DataLoader(Path(__file__).resolve().parent.parent / "tests" / "fixtures" / "synthetic_covid.csv")
39
+ datos = loader.cargar_datos()
40
+
41
+ # Calibración (opcional, con datos sintéticos/reales)
42
+ if datos:
43
+ optimizador = OptimizadorSIR(datos)
44
+ try:
45
+ beta_cal, gamma_cal = optimizador.calibrar(N=poblacion)
46
+ st.success(f"Calibración real completada: beta={beta_cal:.3f}, gamma={gamma_cal:.3f}, R0={beta_cal/gamma_cal:.2f}")
47
+ except (ValueError, RuntimeError) as e:
48
+ beta_cal, gamma_cal = 0.3, 0.1
49
+ st.warning(f"Calibración con datos sintéticos de respaldo (error con datos reales: {e})")
50
+ else:
51
+ beta_cal, gamma_cal = 0.3, 0.1
52
+ st.info("Usando parámetros por defecto (sin datos disponibles).")
53
+
54
+ # Simulación SEIR (con latencia)
55
+ modelo = ModeloSEIR(beta=beta_cal, gamma=gamma_cal, sigma=0.2, N=poblacion)
56
+ t, y = modelo.simular(S0=poblacion - 100, E0=50, I0=100, R0=0, dias=dias)
57
+
58
+ # Métricas SEIR
59
+ S_final, E_final, I_final, R_final = y[:, -1]
60
+ col3, col4, col5, col6 = st.columns(4)
61
+ with col3:
62
+ st.metric("Susceptibles finales", f"{S_final:,.0f}")
63
+ with col4:
64
+ st.metric("Expuestos finales", f"{E_final:,.0f}")
65
+ with col5:
66
+ st.metric("Infectados finales", f"{I_final:,.0f}")
67
+ with col6:
68
+ st.metric("Recuperados finales", f"{R_final:,.0f}")
69
+
70
+ # Mapa interactivo (mapamundi básico con ubicación inicial)
71
+ m = folium.Map(location=[20.0, 0.0], zoom_start=2, tiles="cartodbpositron")
72
+ folium.CircleMarker(
73
+ location=[40.4168, -3.7038], # Ejemplo: Madrid (España)
74
+ radius=10,
75
+ popup=f"País inicial: {pais}\nR aproximado: {r_contagiosidad}\nSimulación: {dias} días",
76
+ color="red",
77
+ fill=True,
78
+ ).add_to(m)
79
+
80
+ # Añadir puntos simulados de expansión (simplificado: puntos aleatorios alrededor del mundo)
81
+ import random
82
+
83
+ random.seed(42)
84
+ for _ in range(20):
85
+ lat = random.uniform(-60, 60)
86
+ lon = random.uniform(-180, 180)
87
+ folium.CircleMarker(
88
+ location=[lat, lon],
89
+ radius=3,
90
+ color="orange",
91
+ fill=True,
92
+ fill_opacity=0.6,
93
+ ).add_to(m)
94
+
95
+ st.subheader("Mapa mundial interactivo de expansión simulada")
96
+ st_folium(m, width=1200, height=600)
97
+
98
+ # Nota de verificación
99
+ st.info("Nota: esta interfaz usa datos sintéticos por defecto o datos reales del dataset de Kaggle (`reproduction_rate` como referencia) para calibración. La expansión visual es una simulación teórica basada en el modelo SEIR básico.")