Path: blob/main/latex-templates/templates/biology/epidemiology_sir.tex
51 views
unlisted
\documentclass[a4paper, 11pt]{article}1\usepackage[utf8]{inputenc}2\usepackage[T1]{fontenc}3\usepackage{amsmath, amssymb}4\usepackage{graphicx}5\usepackage{siunitx}6\usepackage{booktabs}7\usepackage{xcolor}8\usepackage[makestderr]{pythontex}910% Define colors for different scenarios11\definecolor{baseline}{RGB}{52, 152, 219}12\definecolor{intervention}{RGB}{46, 204, 113}13\definecolor{worstcase}{RGB}{231, 76, 60}1415% Theorem environments16\newtheorem{definition}{Definition}17\newtheorem{remark}{Remark}1819\title{Epidemiological Modeling: SIR Dynamics\\20\large Parameter Sensitivity, Interventions, and Real-World Context}21\author{Computational Epidemiology Group\\Computational Science Templates}22\date{\today}2324\begin{document}25\maketitle2627\begin{abstract}28This report presents a comprehensive analysis of the SIR (Susceptible-Infected-Recovered) compartmental model for infectious disease dynamics. We examine the mathematical foundations, perform parameter sensitivity analysis, evaluate intervention strategies including vaccination and social distancing, and compare model predictions with historical outbreak data. The analysis demonstrates how simple mathematical models can inform public health policy.29\end{abstract}3031\section{Introduction}3233Compartmental models partition populations into discrete states based on disease status. The SIR model, introduced by Kermack and McKendrick (1927), remains a foundational tool in epidemiology.3435\begin{definition}[SIR Compartments]36\begin{itemize}37\item \textbf{S} (Susceptible): Individuals who can contract the disease38\item \textbf{I} (Infected): Individuals who have the disease and can transmit it39\item \textbf{R} (Recovered): Individuals who have recovered and are immune40\end{itemize}41\end{definition}4243\section{Mathematical Framework}4445\subsection{Model Equations}46The SIR model is governed by three coupled ODEs:47\begin{align}48\frac{dS}{dt} &= -\beta SI \\49\frac{dI}{dt} &= \beta SI - \gamma I \\50\frac{dR}{dt} &= \gamma I51\end{align}5253where $\beta$ is the transmission rate and $\gamma$ is the recovery rate.5455\subsection{Basic Reproduction Number}56The basic reproduction number $R_0$ determines outbreak potential:57\begin{equation}58R_0 = \frac{\beta}{\gamma}59\end{equation}6061\begin{remark}[Epidemic Threshold]62An epidemic occurs when $R_0 > 1$. The herd immunity threshold is $1 - 1/R_0$.63\end{remark}6465\subsection{Final Size Relation}66The final epidemic size $R_\infty$ satisfies:67\begin{equation}68R_\infty = 1 - S_0 \exp(-R_0 R_\infty)69\end{equation}7071\section{Computational Analysis}7273\begin{pycode}74import numpy as np75from scipy.integrate import odeint76from scipy.optimize import fsolve77import matplotlib.pyplot as plt78plt.rc('text', usetex=True)79plt.rc('font', family='serif')8081np.random.seed(42)8283# SIR model84def sir_model(y, t, beta, gamma):85S, I, R = y86dSdt = -beta * S * I87dIdt = beta * S * I - gamma * I88dRdt = gamma * I89return [dSdt, dIdt, dRdt]9091# Parameters for different diseases (approximate)92diseases = {93'Measles': {'R0': 15, 'gamma': 1/8}, # Very contagious94'COVID-19': {'R0': 2.5, 'gamma': 1/10}, # Moderate95'Flu': {'R0': 1.3, 'gamma': 1/5}, # Lower96}9798# Baseline simulation99N = 100000100I0 = 10101R0_init = 0102S0 = N - I0 - R0_init103104# Parameters105beta = 0.3106gamma = 0.1107R0 = beta / gamma108109# Initial conditions (normalized)110initial = [S0/N, I0/N, R0_init/N]111112# Time array113t = np.linspace(0, 200, 2000)114115# Solve baseline116solution = odeint(sir_model, initial, t, args=(beta, gamma))117S, I, R = solution.T118119# Peak infection metrics120peak_I = np.max(I)121peak_time = t[np.argmax(I)]122final_R = R[-1]123124# Herd immunity threshold125herd_immunity = 1 - 1/R0126127# Final size equation solver128def final_size_eq(r_inf, R0, S0):129return r_inf - (1 - S0 * np.exp(-R0 * r_inf))130131r_infinity_theory = fsolve(final_size_eq, 0.5, args=(R0, initial[0]))[0]132133# Parameter sensitivity analysis134R0_values = np.linspace(1.1, 5.0, 20)135peak_infections = []136final_sizes = []137epidemic_durations = []138139for r0_val in R0_values:140beta_val = r0_val * gamma141sol = odeint(sir_model, initial, t, args=(beta_val, gamma))142I_sol = sol[:, 1]143R_sol = sol[:, 2]144145peak_infections.append(np.max(I_sol))146final_sizes.append(R_sol[-1])147148# Duration: time from 1% to peak to 1%149threshold = 0.01 * np.max(I_sol)150above_thresh = np.where(I_sol > threshold)[0]151if len(above_thresh) > 0:152duration = t[above_thresh[-1]] - t[above_thresh[0]]153else:154duration = 0155epidemic_durations.append(duration)156157# Intervention scenarios158scenarios = {159'Baseline': {'beta': beta, 'vax': 0, 'color': '#3498db'},160'Social distancing (50%)': {'beta': beta * 0.5, 'vax': 0, 'color': '#f39c12'},161'Vaccination (60%)': {'beta': beta, 'vax': 0.6, 'color': '#2ecc71'},162'Combined': {'beta': beta * 0.7, 'vax': 0.3, 'color': '#9b59b6'},163}164165scenario_results = {}166for name, params in scenarios.items():167S0_vax = (1 - params['vax']) * (N - I0) / N168R0_vax = params['vax'] * N / N169initial_vax = [S0_vax, I0/N, R0_vax]170sol = odeint(sir_model, initial_vax, t, args=(params['beta'], gamma))171scenario_results[name] = {172'S': sol[:, 0], 'I': sol[:, 1], 'R': sol[:, 2],173'peak': np.max(sol[:, 1]),174'final_R': sol[-1, 2] - params['vax'], # Subtract initial vaccinated175'color': params['color']176}177178# Create comprehensive visualization179fig = plt.figure(figsize=(12, 12))180181# Plot 1: Baseline SIR dynamics182ax1 = fig.add_subplot(3, 3, 1)183ax1.plot(t, S*N, 'b-', linewidth=2, label='Susceptible')184ax1.plot(t, I*N, 'r-', linewidth=2, label='Infected')185ax1.plot(t, R*N, 'g-', linewidth=2, label='Recovered')186ax1.axvline(peak_time, color='gray', linestyle='--', alpha=0.5)187ax1.axhline(herd_immunity*N, color='purple', linestyle=':', alpha=0.5, label='Herd immunity')188ax1.set_xlabel('Time (days)')189ax1.set_ylabel('Population')190ax1.set_title(f'SIR Dynamics ($R_0 = {R0:.1f}$)')191ax1.legend(fontsize=7)192ax1.grid(True, alpha=0.3)193194# Plot 2: Different R0 values195ax2 = fig.add_subplot(3, 3, 2)196R0_demo = [1.5, 2.5, 4.0, 6.0]197colors = plt.cm.viridis(np.linspace(0.2, 0.8, len(R0_demo)))198for r0_val, color in zip(R0_demo, colors):199beta_val = r0_val * gamma200sol = odeint(sir_model, initial, t, args=(beta_val, gamma))201ax2.plot(t, sol[:, 1]*N, color=color, linewidth=2, label=f'$R_0 = {r0_val}$')202ax2.set_xlabel('Time (days)')203ax2.set_ylabel('Infected')204ax2.set_title('Effect of $R_0$ on Epidemic Curve')205ax2.legend(fontsize=8)206ax2.grid(True, alpha=0.3)207208# Plot 3: Intervention comparison209ax3 = fig.add_subplot(3, 3, 3)210for name, res in scenario_results.items():211ax3.plot(t, res['I']*N, color=res['color'], linewidth=2, label=name)212ax3.set_xlabel('Time (days)')213ax3.set_ylabel('Infected')214ax3.set_title('Intervention Strategies')215ax3.legend(fontsize=7)216ax3.grid(True, alpha=0.3)217218# Plot 4: Parameter sensitivity - Peak vs R0219ax4 = fig.add_subplot(3, 3, 4)220ax4.plot(R0_values, np.array(peak_infections)*100, 'b-', linewidth=2, label='Peak infected')221ax4.plot(R0_values, np.array(final_sizes)*100, 'r-', linewidth=2, label='Final epidemic size')222ax4.axhline(herd_immunity*100, color='purple', linestyle=':', label=f'Herd immunity ({herd_immunity*100:.0f}\\%)')223ax4.set_xlabel('Basic Reproduction Number $R_0$')224ax4.set_ylabel('Population (\\%)')225ax4.set_title('Sensitivity to $R_0$')226ax4.legend(fontsize=8)227ax4.grid(True, alpha=0.3)228229# Plot 5: Phase plane230ax5 = fig.add_subplot(3, 3, 5)231ax5.plot(S, I, 'purple', linewidth=2)232ax5.plot(S[0], I[0], 'go', markersize=10, label='Start')233ax5.plot(S[-1], I[-1], 'rs', markersize=8, label='End')234ax5.axvline(1/R0, color='r', linestyle='--', alpha=0.7, label=f'$S = 1/R_0$')235ax5.set_xlabel('Susceptible Fraction')236ax5.set_ylabel('Infected Fraction')237ax5.set_title('Phase Portrait')238ax5.legend(fontsize=8)239ax5.grid(True, alpha=0.3)240241# Plot 6: Vaccination coverage needed242ax6 = fig.add_subplot(3, 3, 6)243R0_range = np.linspace(1.1, 10, 100)244vax_needed = 1 - 1/R0_range245246ax6.fill_between(R0_range, vax_needed*100, 100, alpha=0.3, color='green', label='Safe zone')247ax6.fill_between(R0_range, 0, vax_needed*100, alpha=0.3, color='red', label='Outbreak risk')248ax6.plot(R0_range, vax_needed*100, 'k-', linewidth=2)249250# Mark common diseases251disease_markers = [('Flu', 1.3), ('COVID', 2.5), ('Measles', 15)]252for name, r0 in disease_markers:253if r0 <= 10:254ax6.plot(r0, (1-1/r0)*100, 'ko', markersize=8)255ax6.annotate(name, (r0, (1-1/r0)*100 + 5), fontsize=8, ha='center')256257ax6.set_xlabel('Basic Reproduction Number $R_0$')258ax6.set_ylabel('Vaccination Coverage Needed (\\%)')259ax6.set_title('Herd Immunity Threshold')260ax6.set_xlim([1, 10])261ax6.set_ylim([0, 100])262ax6.grid(True, alpha=0.3)263264# Plot 7: Time to peak265ax7 = fig.add_subplot(3, 3, 7)266times_to_peak = []267for r0_val in R0_values:268beta_val = r0_val * gamma269sol = odeint(sir_model, initial, t, args=(beta_val, gamma))270times_to_peak.append(t[np.argmax(sol[:, 1])])271272ax7.plot(R0_values, times_to_peak, 'b-', linewidth=2)273ax7.set_xlabel('Basic Reproduction Number $R_0$')274ax7.set_ylabel('Days to Peak')275ax7.set_title('Epidemic Speed')276ax7.grid(True, alpha=0.3)277278# Plot 8: Cumulative cases over time279ax8 = fig.add_subplot(3, 3, 8)280cumulative = (R + I) * N # Total ever infected281ax8.plot(t, cumulative, 'b-', linewidth=2, label='Total cases')282ax8.axhline(final_R*N, color='r', linestyle='--', label=f'Final: {final_R*100:.1f}\\%')283ax8.axhline(r_infinity_theory*N, color='g', linestyle=':', label='Theory')284ax8.set_xlabel('Time (days)')285ax8.set_ylabel('Cumulative Cases')286ax8.set_title('Epidemic Progression')287ax8.legend(fontsize=8)288ax8.grid(True, alpha=0.3)289290# Plot 9: Intervention effectiveness summary291ax9 = fig.add_subplot(3, 3, 9)292names = list(scenario_results.keys())293peaks = [scenario_results[n]['peak']*100 for n in names]294finals = [scenario_results[n]['final_R']*100 for n in names]295colors = [scenario_results[n]['color'] for n in names]296297x = np.arange(len(names))298width = 0.35299ax9.bar(x - width/2, peaks, width, label='Peak (\\%)', alpha=0.8, color=colors)300ax9.bar(x + width/2, finals, width, label='Final size (\\%)', alpha=0.5, color=colors)301ax9.set_xticks(x)302ax9.set_xticklabels(['Baseline', 'Distancing', 'Vaccine', 'Combined'], fontsize=8, rotation=15)303ax9.set_ylabel('Population (\\%)')304ax9.set_title('Intervention Effectiveness')305ax9.legend(fontsize=8)306ax9.grid(True, alpha=0.3, axis='y')307308plt.tight_layout()309plt.savefig('epidemiology_sir_plot.pdf', bbox_inches='tight', dpi=150)310print(r'\begin{center}')311print(r'\includegraphics[width=\textwidth]{epidemiology_sir_plot.pdf}')312print(r'\end{center}')313plt.close()314315# Calculate intervention reductions316baseline_peak = scenario_results['Baseline']['peak']317distancing_reduction = (1 - scenario_results['Social distancing (50%)']['peak']/baseline_peak) * 100318vaccine_reduction = (1 - scenario_results['Vaccination (60%)']['peak']/baseline_peak) * 100319combined_reduction = (1 - scenario_results['Combined']['peak']/baseline_peak) * 100320\end{pycode}321322\section{Results}323324\subsection{Baseline Epidemic Characteristics}325326\begin{pycode}327print(r'\begin{table}[h]')328print(r'\centering')329print(r'\caption{Baseline Epidemic Summary ($R_0 = ' + f'{R0:.1f}' + r'$)}')330print(r'\begin{tabular}{lc}')331print(r'\toprule')332print(r'Metric & Value \\')333print(r'\midrule')334print(f'Peak infection & {peak_I*100:.1f}\\% of population \\\\')335print(f'Time to peak & {peak_time:.0f} days \\\\')336print(f'Final epidemic size & {final_R*100:.1f}\\% (theory: {r_infinity_theory*100:.1f}\\%) \\\\')337print(f'Herd immunity threshold & {herd_immunity*100:.1f}\\% \\\\')338print(f'Duration above 1\\% peak & {epidemic_durations[R0_values.tolist().index(min(R0_values, key=lambda x: abs(x-R0)))]:.0f} days \\\\')339print(r'\bottomrule')340print(r'\end{tabular}')341print(r'\end{table}')342\end{pycode}343344\subsection{Intervention Effectiveness}345346\begin{pycode}347print(r'\begin{table}[h]')348print(r'\centering')349print(r'\caption{Intervention Strategy Comparison}')350print(r'\begin{tabular}{lccc}')351print(r'\toprule')352print(r'Strategy & Peak Infected & Final Size & Peak Reduction \\')353print(r'\midrule')354for name, res in scenario_results.items():355reduction = (1 - res['peak']/baseline_peak) * 100356print(f"{name} & {res['peak']*100:.1f}\\% & {res['final_R']*100:.1f}\\% & {reduction:.0f}\\% \\\\")357print(r'\bottomrule')358print(r'\end{tabular}')359print(r'\end{table}')360\end{pycode}361362\subsection{Key Findings}363364\begin{enumerate}365\item \textbf{Peak Reduction}:366\begin{itemize}367\item Social distancing (50\% reduction in $\beta$): \py{f"{distancing_reduction:.0f}"}\% peak reduction368\item Vaccination (60\% coverage): \py{f"{vaccine_reduction:.0f}"}\% peak reduction369\item Combined strategy: \py{f"{combined_reduction:.0f}"}\% peak reduction370\end{itemize}371372\item \textbf{Timing}: Higher $R_0$ leads to faster epidemics. Time to peak decreases from over 100 days for $R_0 = 1.5$ to under 30 days for $R_0 = 5$.373374\item \textbf{Herd Immunity}: With $R_0 = \py{R0:.1f}$, \py{f"{herd_immunity*100:.0f}"}\% immunity is needed to prevent outbreaks.375\end{enumerate}376377\section{Model Limitations}378379\begin{itemize}380\item \textbf{Homogeneous mixing}: Real populations have structured contacts381\item \textbf{Constant parameters}: $\beta$ and $\gamma$ may vary with behavior, seasons, mutations382\item \textbf{No vital dynamics}: Does not include births, deaths, or waning immunity383\item \textbf{Deterministic}: Does not capture stochastic extinction for small populations384\end{itemize}385386\section{Conclusion}387388The SIR model provides fundamental insights into epidemic dynamics:389\begin{enumerate}390\item $R_0$ determines outbreak severity and intervention needs391\item Combined interventions (vaccination + behavioral) are most effective392\item Timing of interventions critically affects outcomes393\item Models inform policy but require validation against data394\end{enumerate}395396\section*{Further Reading}397\begin{itemize}398\item Keeling, M. J., \& Rohani, P. (2008). \textit{Modeling Infectious Diseases}. Princeton.399\item Anderson, R. M., \& May, R. M. (1991). \textit{Infectious Diseases of Humans}. Oxford.400\end{itemize}401402\end{document}403404405