Parte I — Datos reales

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import ipywidgets as widgets
from ipywidgets import interact
import pandas as pd

import plotly.graph_objects as go

%matplotlib inline
def sir_model(y, t, beta, gamma):
    S, I, R = y
    N = S + I + R
    
    dSdt = -beta * S * I / N
    dIdt = beta * S * I / N - gamma * I
    dRdt = gamma * I
    
    return [dSdt, dIdt, dRdt]


def simulate_sir(beta=0.3, gamma=0.1, S0=990, I0=10, R0=0, days=160):
    t = np.linspace(0, days, days)
    y0 = [S0, I0, R0]
    
    solution = odeint(sir_model, y0, t, args=(beta, gamma))
    S, I, R = solution.T
    
    return t, S, I, R
def plot_sir_plotly(beta=0.3, gamma=0.1, S0=990, I0=10, R0=0, days=160):
    t, S, I, R = simulate_sir(beta, gamma, S0, I0, R0, days)
    
    fig = go.Figure()
    
    fig.add_trace(go.Scatter(x=t, y=S, mode='lines', name='Susceptible'))
    fig.add_trace(go.Scatter(x=t, y=I, mode='lines', name='Infected'))
    fig.add_trace(go.Scatter(x=t, y=R, mode='lines', name='Recovered'))
    
    fig.update_layout(
        title=f"SIR Model (R₀ = {beta/gamma:.2f})",
        xaxis_title="Time",
        yaxis_title="Population",
        template="plotly_white"
    )
    
    fig.show()

Trabajamos con datos de casos en España.


Ejercicio 1

Carga los datos agregados y representa la evolución temporal.

Preguntas:

  • ¿Qué forma tiene la curva?
  • ¿Dónde está el pico?

Parte II — Modelo SIR

El modelo SIR describe la evolución de:

  • S → susceptibles
  • I → infectados
  • R → recuperados

Ejercicio 2

Ejecuta el modelo SIR básico.

interact(
    plot_sir_plotly,
    beta=widgets.FloatSlider(value=0.3, min=0.0, max=1.0, step=0.01, description='beta'),
    gamma=widgets.FloatSlider(value=0.1, min=0.01, max=1.0, step=0.01, description='gamma'),
    S0=widgets.IntSlider(value=990, min=0, max=1000, step=10, description='S0'),
    I0=widgets.IntSlider(value=10, min=1, max=500, step=1, description='I0'),
    R0=widgets.IntSlider(value=0, min=0, max=500, step=1, description='R0'),
    days=widgets.IntSlider(value=160, min=10, max=365, step=10, description='days')
);

Ejercicio 3 — Ajuste de parámetros

Modifica:

  • el tamaño de la población (S0+I0+R0)
  • la condición inicial (I0)
  • beta (tasa de infección)
  • gamma (recuperación)

para aproximar la curva real.


Preguntas:

  • ¿qué parámetro cambia el pico?
  • ¿qué parámetro cambia la duración?
Hint

beta controla la velocidad de contagio
gamma controla la duración de la infección

covid_df = pd.read_parquet("data/processed/cnig_provincias_covid_cases.parquet")
pop_df   = pd.read_parquet("data/processed/cnig_provincias_zone_movements.parquet")
N = pop_df.loc['2020-02-14', 'total_population'].sum()

I_real = covid_df.groupby('date')['new_cases'].sum().rolling(window=10, min_periods=1).sum()
I_real = I_real.values[:180] * 20
plt.plot(I_real)
I_real.shape
beta=0.15
gamma=0.115
I0=500
S0=N - I0

R0=0
days=1800

t, S, I, R = simulate_sir(beta, gamma, S0, I0, R0, days)

figure = plt.figure(figsize=(6,3))
#plt.plot(t, S, label='S', color='purple')
plt.plot(t, I, label='I (sim)', color='firebrick')
plt.plot(I_real, '--', label='I (real)', color='purple')
#plt.plot(t, R, label='R', color='k')
plt.legend(frameon=False, loc='center right')
plt.xlabel("time")
plt.ylabel("compartment")
plt.show()

Ejercicio 4 — Ajustar el modelo a los datos de España

Modifica:

  • el tamaño de la población (S0+I0+R0)
  • la condición inicial (I0)
  • beta (tasa de infección)
  • gamma (recuperación)
  1. Representar las curvas de infectados simuladas y reales apara diferente parametros
  2. Calcular alguna métrica de error entre las curvas de forma manual

Limitaciones del modelo SIR

El modelo SIR:

  • asume población homogénea
  • no incluye estructura espacial
  • no incluye movilidad

Pregunta

¿Qué falta para modelar mejor una epidemia real?

Parte III — Movilidad

En la práctica anterior calculamos:

risk(i → j)


Esto sugiere:

  • las regiones están conectadas
  • los infectados viajan
  • la epidemia se propaga entre regiones

necesitamos modelos espaciales

Instrucciones para instalar EpiCommute

  1. Abrimos la terminar y nos conectamos al servidor
  2. Entramos en la carpetta del curso (cd mini-course-scicomp)
  3. Activamos el venv
  4. Instalar EpiCommute:
    1. Descargamos Epicommute:
      git clone https://github.com/franksh/EpiCommute.git
    2. Acedemos a la carpeta del paquete:
      cd EpiCommute
    3. Instalamos el paquete en el venv:
      python setupy.py install
    4. Probamos que se instaló de forma correcta:
      python -c "import EpiCommute"
    5. Si no hay mensajes de erro es que fue todo OK!

¿Que es EpiCommute?

Es un paquete en python que implemta un modelo simple de metapoblaciones y que fue usado en el sigueinte artículo: - COVID-19 lockdown induces disease-mitigating structural changes in mobility networks

Las idas orginales está desarrolladas en este otro artículo:

Ejercicio 1 — Simulación básica

Ejecuta el modelo básico.

Preguntas:

  • ¿cómo evoluciona la epidemia?
  • ¿qué regiones se infectan primero?

ejecutar 04_1_basic_example.ipynb

Ejercicio 2 — Efecto de la movilidad

Ejecuta la simulación:

  • sin movilidad
  • con movilidad

Preguntas:

  • ¿qué cambia?
  • ¿la epidemia se propaga más rápido?

ejecutar 2_lattice_mobility.ipynb

Ejercicio 3 — Efecto de la reducción de movilidad.

Simular los distintos tipos de cuarentenas y observar las diferencias

Preguntas:

  • ¿se reduce el pico?
  • ¿se retrasa la epidemia?