-
Notifications
You must be signed in to change notification settings - Fork 0
SEIR Model Tutorial
Complete guide to understanding and using the SEIR (Susceptible-Exposed-Infected-Recovered) epidemic model.
- What is the SEIR Model?
- Why SEIR Instead of SIR?
- Mathematical Background
- Parameters Explained
- Incubation Period
- Code Examples
- Comparing SIR vs SEIR
- Advanced Usage
- Common Pitfalls
The SEIR model extends the classic SIR model by adding an Exposed compartment for individuals who have been infected but are not yet infectious.
| Compartment | Symbol | Description |
|---|---|---|
| Susceptible | S | Healthy individuals who can catch the disease |
| Exposed | E | Infected but not yet infectious (incubation period) |
| Infected | I | Infectious individuals who can transmit the disease |
| Recovered | R | Individuals who recovered and are immune |
Susceptible (S) β Exposed (E) β Infected (I) β Recovered (R)
β β β β
Healthy Incubating Sick/Fatal Immune
(not contagious) (contagious)
The SEIR model is more realistic for diseases with a significant incubation period.
| Disease | Incubation Period | SEIR Needed? |
|---|---|---|
| COVID-19 | 4-7 days | β Yes |
| Ebola | 2-21 days | β Yes |
| Measles | 10-14 days | β Yes |
| Seasonal Flu | 1-4 days | |
| Common Cold | 1-3 days | |
| Food Poisoning | 6-24 hours | β No |
| Scenario | Recommendation |
|---|---|
| Incubation period > 2 days | β Use SEIR |
| Quarantine of exposed individuals | β Use SEIR |
| Contact tracing is important | β Use SEIR |
| Quick onset disease | β SIR is sufficient |
The SEIR model is described by four differential equations:
dS/dt = -Ξ² Γ S Γ I / N
dE/dt = Ξ² Γ S Γ I / N - Ο Γ E
dI/dt = Ο Γ E - Ξ³ Γ I
dR/dt = Ξ³ Γ I
Where:
- N = Total population (S + E + I + R)
- Ξ² (beta) = Infection rate
- Ο (sigma) = Incubation rate (1/incubation period)
- Ξ³ (gamma) = Recovery rate
Total population remains constant:
S(t) + E(t) + I(t) + R(t) = N = constant
| Value | Meaning |
|---|---|
| 0.0 - 0.3 | Low transmission |
| 0.3 - 0.6 | Moderate transmission |
| 0.6 - 1.0 | High transmission |
Ο = 1 / (incubation period in days)
| Incubation Period | Ο Value |
|---|---|
| 1 day | 1.0 |
| 2 days | 0.5 |
| 5 days | 0.2 |
| 7 days | 0.143 |
| 10 days | 0.1 |
| 14 days | 0.071 |
Ξ³ = 1 / (infectious period in days)
| Infectious Period | Ξ³ Value |
|---|---|
| 2 days | 0.5 |
| 5 days | 0.2 |
| 7 days | 0.143 |
| 10 days | 0.1 |
| 14 days | 0.071 |
The time between infection and becoming infectious.
| Disease | Incubation Period | Ο Value |
|---|---|---|
| COVID-19 | 4-7 days | 0.14 - 0.25 |
| Ebola | 2-21 days | 0.05 - 0.5 |
| Measles | 10-14 days | 0.07 - 0.1 |
| Flu | 1-4 days | 0.25 - 1.0 |
| Common Cold | 1-3 days | 0.33 - 1.0 |
For SEIR, Rβ is calculated the same way:
Rβ = Ξ² / Ξ³
The exposed compartment affects dynamics, not the final Rβ.
from sir_simulator.core_models.seir_model import run_seir_simulation
# Parameters
beta = 0.5 # Infection rate
sigma = 0.2 # Incubation rate (5 days incubation)
gamma = 0.1 # Recovery rate (10 days infectious)
S0 = 990 # Initial susceptible
E0 = 5 # Initial exposed
I0 = 5 # Initial infected
R0 = 0 # Initial recovered
t_max = 100 # 100 days
# Run simulation
df = run_seir_simulation(beta, sigma, gamma, S0, E0, I0, R0, t_max)
print(df.tail())# Calculate Rβ
R0 = beta / gamma
print(f"Rβ = {R0:.2f}")
# Find peak metrics
peak_infected = df['Infected'].max()
peak_exposed = df['Exposed'].max()
peak_day = df[df['Infected'] == peak_infected]['time'].values[0]
print(f"Peak exposed: {int(peak_exposed)}")
print(f"Peak infected: {int(peak_infected)} on day {int(peak_day)}")
# Final outbreak size
final_susceptible = df['Susceptible'].iloc[-1]
total_infected = S0 - final_susceptible
print(f"Total infected: {int(total_infected)}")# Convert sigma to incubation period (days)
incubation_days = 1 / sigma
print(f"Incubation period: {incubation_days:.1f} days")import matplotlib.pyplot as plt
from sir_simulator.core_models.sir_model import run_sir_simulation
from sir_simulator.core_models.seir_model import run_seir_simulation
# Common parameters
beta = 0.5
gamma = 0.1
S0 = 990
I0 = 10
t_max = 150
# Run SIR
df_sir = run_sir_simulation(beta, gamma, S0, I0, 0, t_max)
# Run SEIR (with same parameters + exposure)
sigma = 0.2 # 5 days incubation
E0 = 5
df_seir = run_seir_simulation(beta, sigma, gamma, S0, E0, I0, 0, t_max)
# Plot comparison
plt.figure(figsize=(12, 6))
plt.plot(df_sir['time'], df_sir['Infected'], label='SIR - Infected',
color='red', linestyle='-', linewidth=2)
plt.plot(df_seir['time'], df_seir['Infected'], label='SEIR - Infected',
color='blue', linestyle='--', linewidth=2)
plt.plot(df_seir['time'], df_seir['Exposed'], label='SEIR - Exposed',
color='orange', linestyle=':', linewidth=2)
plt.xlabel('Time (days)', fontsize=12)
plt.ylabel('Population', fontsize=12)
plt.title('SIR vs SEIR Model Comparison', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()| Feature | SIR | SEIR |
|---|---|---|
| Compartments | 3 | 4 |
| Incubation period | β No | β Yes |
| Peak timing | Earlier | Later (due to incubation) |
| Peak magnitude | Higher | Lower (spread out) |
| Realism | Basic | More realistic |
| Complexity | Simple | Moderate |
βββββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ
β Metric β SIR β SEIR β
βββββββββββββββββββΌβββββββββββββββΌβββββββββββββββ€
β Peak Infected β Higher β Lower β
β Peak Day β Earlier β Later β
β Outbreak Length β Shorter β Longer β
β Rβ β Same Ξ²/Ξ³ β Same Ξ²/Ξ³ β
β Final Size β Slightly β Slightly β
β β higher β lower β
βββββββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ
import matplotlib.pyplot as plt
sigma_values = [0.5, 0.2, 0.1, 0.05] # 2, 5, 10, 20 days incubation
colors = ['blue', 'green', 'orange', 'red']
plt.figure(figsize=(12, 6))
for sigma, color in zip(sigma_values, colors):
df = run_seir_simulation(0.5, sigma, 0.1, 990, 5, 5, 0, 150)
incubation_days = 1/sigma
plt.plot(df['time'], df['Infected'],
label=f'Incubation: {incubation_days:.0f} days',
color=color)
plt.xlabel('Time (days)', fontsize=12)
plt.ylabel('Infected Population', fontsize=12)
plt.title('SEIR Model - Effect of Incubation Period', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()# Modify simulation to quarantine exposed individuals
# This would require custom code or using the scenario comparator
from sir_simulator.advanced_features.scenario_comparison import ScenarioComparator
comp = ScenarioComparator(population=1000, initial_infected=5, beta=0.3, gamma=0.1)
scenarios, metrics = comp.compare_all_scenarios(days=100)
print(metrics)import numpy as np
from sir_simulator.advanced_features.parameter_optimization import ParameterOptimizer
# Load your real data
# data = pd.read_csv('your_data.csv')
# observed = data['cases'].values
# t = data['day'].values
# For demo, use synthetic data
t = np.linspace(0, 100, 100)
observed = 100 * np.exp(-0.1 * t) + 5 * np.random.randn(len(t))
optimizer = ParameterOptimizer(model_type='seir')
results = optimizer.fit(observed, t, [990, 5, 5, 0])
print(f"Ξ² = {results['beta']:.3f}")
print(f"Ο = {results['sigma']:.3f}")
print(f"Ξ³ = {results['gamma']:.3f}")
print(f"Incubation period = {1/results['sigma']:.1f} days")| Incorrect | Correct |
|---|---|
| Ο = 5 (meaning 5 days) | Ο = 1/5 = 0.2 |
| Ο = incubation period | Ο = 1/incubation period |
Remember: Ο is a rate, not a duration.
If E0 = 0 and I0 > 0, the model works but misses the incubation effect.
SEIR has 3 parameters vs SIR's 2. More data needed for fitting.
# Good
df = run_seir_simulation(beta, sigma, gamma, S0, E0=5, I0=5, R0=0, t_max=100)
# Bad - missing E0
df = run_seir_simulation(beta, sigma, gamma, S0, I0=5, t_max=100)| Concept | Summary |
|---|---|
| SEIR | S β E β I β R (adds Exposed compartment) |
| Ο | Incubation rate = 1/incubation_days |
| Incubation | Time from infection to infectiousness |
| Peak | Later and lower than SIR |
| Best for | COVID-19, Ebola, Measles |
- Network Simulation Tutorial - Social network spread
- Parameter Optimization - Fit to real data
- Scenario Comparison - Intervention strategies