-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
1,002 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "7a646367", | ||
"metadata": {}, | ||
"source": [ | ||
"### Step a-b: create the base model\n", | ||
"Questions: You want to implement a masking intervention in a simple compartmental model and simulate epidemic trajectories under different compliance scenarios. You found an existing model that incorporates masking as a time-dependent modification to the β parameter (https://doi.org/10.3390/ijerph18179027 plus accompanying code), and you want to ensure that the model is working as expected by reproducing plots in the publication. \n", | ||
"\n", | ||
"Replicate an analysis from the paper.\n", | ||
"- (TA1 Model Extraction Workflow, TA2 Model Representation) Extract the SEIRD model (equations 1-5, with time-varying β as defined in equations 8-9) and load into the workbench. In equation 8, let kappa = γR0, R0 = 5. In equation 9, let k = 5.\n", | ||
"\n", | ||
"- (TA3 Simulation Workflow, Unit Test): Replicate Figure 3 from the paper, which maps to the first scenario in the paper- implementing a masking intervention at several different timepoints (delays of 0 days, 50 days, 100 days, and control case, from the date of first infection) in the pandemic, with 100% compliance. Recreate the Fig. 3 curves (including peak infection times and levels), up to some reasonable margin of error. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"id": "56172b31", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import sympy\n", | ||
"from mira.metamodel import *\n", | ||
"from mira.modeling import Model\n", | ||
"from mira.modeling.askenet.petrinet import AskeNetPetriNetModel" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"id": "f07383fb", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"person_units = Unit(expression=sympy.Symbol('person'))\n", | ||
"day_units = Unit(expression=sympy.Symbol('day'))\n", | ||
"per_day_units = Unit(expression=1/sympy.Symbol('day'))\n", | ||
"dimensionless_units = Unit(expression=sympy.Integer('1'))\n", | ||
"\n", | ||
"c = {\n", | ||
" 'S': Concept(name='S', units=dimensionless_units),\n", | ||
" 'E': Concept(name='E', units=dimensionless_units),\n", | ||
" 'I': Concept(name='I', units=dimensionless_units),\n", | ||
" 'R': Concept(name='R', units=dimensionless_units),\n", | ||
" 'D': Concept(name='D', units=dimensionless_units)\n", | ||
"}\n", | ||
"\n", | ||
"\n", | ||
"parameters = {\n", | ||
" 'gamma': Parameter(name='gamma', value=1/11, units=per_day_units),\n", | ||
" 'delta': Parameter(name='delta', value=1/5, units=per_day_units),\n", | ||
" 'alpha': Parameter(name='alpha', value=0.000064, units=dimensionless_units),\n", | ||
" 'rho': Parameter(name='rho', value=1/9, units=per_day_units),\n", | ||
" 'N': Parameter(name='N', value=5_600_000, units=person_units),\n", | ||
" 'beta_s': Parameter(name='beta_s', value=1),\n", | ||
" 'beta_c': Parameter(name='beta_c', value=0.4),\n", | ||
" 't_0': Parameter(name='t_0', value=89),\n", | ||
" # D=11, gamma = 1/D, R_0 = 5 and\n", | ||
" # beta = R_0 * gamma * mask(t) so kappa = 5/11\n", | ||
" 'kappa': Parameter(name='kappa', value=5/11),\n", | ||
"}\n", | ||
"\n", | ||
"initials = {\n", | ||
" 'S': Initial(concept=Concept(name='S'), value=5_600_000-1),\n", | ||
" 'E': Initial(concept=Concept(name='E'), value=1),\n", | ||
" 'I': Initial(concept=Concept(name='I'), value=0),\n", | ||
" 'R': Initial(concept=Concept(name='R'), value=0),\n", | ||
" 'D': Initial(concept=Concept(name='D'), value=0),\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"id": "bdf70b6a", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"S, E, I, R, D, N, kappa, beta_s, beta_c, k, t_0, t, alpha, delta, rho, gamma = \\\n", | ||
" sympy.symbols('S E I R D N kappa beta_s beta_c k t_0 t alpha delta rho gamma')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"id": "d1b732b3", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"m_1 = (beta_s - beta_c) / (1 + sympy.exp(-k*(t_0-t))) + beta_c\n", | ||
"beta = kappa*m_1\n", | ||
"\n", | ||
"t1 = ControlledConversion(subject=c['S'],\n", | ||
" outcome=c['E'],\n", | ||
" controller=c['E'],\n", | ||
" rate_law=S*I*beta / N)\n", | ||
"t2 = NaturalConversion(subject=c['E'],\n", | ||
" outcome=c['I'],\n", | ||
" rate_law=delta*E)\n", | ||
"t3 = NaturalConversion(subject=c['I'],\n", | ||
" outcome=c['R'],\n", | ||
" rate_law=(1-alpha)*gamma*I)\n", | ||
"t4 = NaturalConversion(subject=c['I'],\n", | ||
" outcome=c['D'],\n", | ||
" rate_law=alpha*rho*I)\n", | ||
"templates = [t1, t2, t3, t4]\n", | ||
"tm = TemplateModel(\n", | ||
" templates=templates,\n", | ||
" parameters=parameters,\n", | ||
" initials=initials,\n", | ||
" time=Time(name='t', units=day_units)\n", | ||
")\n", | ||
"AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_a.json')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "4c29d51a", | ||
"metadata": {}, | ||
"source": [ | ||
"### Step c: update beta\n", | ||
"\n", | ||
"(TA2 Model Modification Workflow, TA3 Simulation Workflow): Update the β(t) function to be defined as equations 8 and 10, with k1 = 5, and k2 = 1. This reflects the paper’s second scenario, gradual noncompliance with the masking policy over time. Rerun the simulation with several different delays in enforcing a mask policy (ranging from 0 to 140 days), and replicate Fig. 5, up to some reasonable margin of error." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"id": "3413db92", | ||
"metadata": { | ||
"scrolled": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"k_1, k_2, t_1, beta_nc = sympy.symbols('k_1 k_2 t_1 beta_nc')\n", | ||
"parameters['k_1'] = Parameter(name='k_1')\n", | ||
"parameters['k_2'] = Parameter(name='k_2')\n", | ||
"parameters['t_1'] = Parameter(name='t_1', value=154)\n", | ||
"parameters['beta_nc'] = Parameter(name='beta_nc', value=0.5)\n", | ||
"m_2 = (beta_s - beta_c) / (1 + sympy.exp(-k_1*(t_0-t))) + (beta_c - beta_nc) / (1 + sympy.exp(-k_2*(t_1-t))) + beta_nc" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"id": "f487b47f", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"t1.rate_law = SympyExprStr(kappa*m_2)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"id": "30a47395", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/latex": [ | ||
"$\\displaystyle \\kappa \\left(\\beta_{nc} + \\frac{\\beta_{c} - \\beta_{nc}}{1 + e^{- k_{2} \\left(- t + t_{1}\\right)}} + \\frac{- \\beta_{c} + \\beta_{s}}{1 + e^{- k_{1} \\left(- t + t_{0}\\right)}}\\right)$" | ||
], | ||
"text/plain": [ | ||
"kappa*(beta_nc + (beta_c - beta_nc)/(1 + exp(-k_2*(-t + t_1))) + (-beta_c + beta_s)/(1 + exp(-k_1*(-t + t_0))))" | ||
] | ||
}, | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"t1.rate_law.args[0]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"id": "0791ae2d", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_c.json')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "5f67f2e9", | ||
"metadata": {}, | ||
"source": [ | ||
"### Step d: update for reinfection\n", | ||
"(TA2 Model Modification Workflow, TA3 Simulation Workflow): Update the system of equations to include equations 6 and 7. This adds the potential for reinfection. Compare with the outcomes from 1c. What impact does immunity loss and potential for reinfection have?" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 9, | ||
"id": "38b6002e", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"epsilon = sympy.Symbol('epsilon')\n", | ||
"parameters['epsilon'] = Parameter(name='epsilon', value=1/90)\n", | ||
"t5 = NaturalConversion(subject=c['R'],\n", | ||
" outcome=c['S'],\n", | ||
" rate_law=epsilon*R)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"id": "3aed70ad", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_d.json')" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.12" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.