From 4691e72e2cb161928377e6c6665b7f7fdcec6bc5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 11:06:15 -0400 Subject: [PATCH 001/117] Add support for recording last time tested, as well as giving priority in random testing to people for which more time passed before they were last tested --- seirsplus/models.py | 3 +++ seirsplus/sim_loops.py | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index c4ddd40..127abac 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1880,6 +1880,7 @@ def __init__(self, G, beta, sigma, lamda, gamma, # Initialize other node metadata: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.tested = numpy.array([False]*self.numNodes).reshape((self.numNodes,1)) + self.testedTime = numpy.array([-1] * self.numNodes).reshape((self.numNodes, 1)) # the time that the node was last tested: negative means it was not tested self.positive = numpy.array([False]*self.numNodes).reshape((self.numNodes,1)) self.numTested = numpy.zeros(6*self.numNodes) self.numPositive = numpy.zeros(6*self.numNodes) @@ -2470,6 +2471,8 @@ def set_isolation(self, node, isolate): def set_tested(self, node, tested): self.tested[node] = tested + if tested: + self.testedTime[node] = self.t # set time that the node was tested to current time self.testedInCurrentState[node] = tested #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 1202512..339aa5d 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -3,7 +3,7 @@ import numpy import time - +import random def run_tti_sim(model, T, @@ -17,7 +17,11 @@ def run_tti_sim(model, T, isolation_compliance_positive_individual=[None], isolation_compliance_positive_groupmate=[None], isolation_compliance_positive_contact=[None], isolation_compliance_positive_contactgroupmate=[None], isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, - cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None + cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, + test_priority = 'random' + # test_priority: how to to choose which nodes to test: + # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) + # A suffix of "degree_oblivious" means that we ignore degrees (i.e., assume we don't know social networks for testing policy) ): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -255,10 +259,17 @@ def run_tti_sim(model, T, numRandomTests = max(min(tests_per_day-len(tracingSelection)-len(symptomaticSelection), len(testingPool)), 0) testingPool_degrees = model.degree.flatten()[testingPool] - testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) + if "degree_oblivious" in test_priority: + testingPool_degreeWeights = numpy.ones(len(testingPool)) + else: + testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) if(len(testingPool) > 0): - randomSelection = testingPool[numpy.random.choice(len(testingPool), numRandomTests, p=testingPool_degreeWeights, replace=False)] + if 'last_tested' in test_priority: + # sort the pool according to the time they were last tested, breaking ties randomly + randomSelection = sort(testingPool,key = lambda i: model.testedTime[i], cmp = lambda x,y: x-y if x-y else random.randint(0, 1) * 2 - 1 )[:numRandomTests] + else: + randomSelection = testingPool[numpy.random.choice(len(testingPool), numRandomTests, p=testingPool_degreeWeights, replace=False)] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 4159e1bc69425f1f74698a1be3e018d2c88fd700 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 11:12:20 -0400 Subject: [PATCH 002/117] Notebook with priority testing --- ...EIRS_Workplace_TTI_Demo_timePriority.ipynb | 853 ++++++++++++++++++ 1 file changed, 853 insertions(+) create mode 100644 examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb new file mode 100644 index 0000000..45a2eec --- /dev/null +++ b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb @@ -0,0 +1,853 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extended SEIRS Workplace TTI Demo\n", + "\n", + "**In this demonstration we will explore the effect of testing, tracing, and isolation interventions on disease transmission in a workplace setting with a realistic contact network.**\n", + "\n", + "This notebook provides a demonstration of the functionality of the [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description) and the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). This notebook also offers a sandbox for starting to explore TTI scenarios of your own. \n", + "For a more thorough walkthrough of the model, simulation loop, and use of this package, refer to the [SEIRS+ Wiki](https://github.com/ryansmcgee/seirsplus/wiki)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Installing and importing the model code\n", + "\n", + "All of the code needed to run the model is imported from the ```models``` module of this package.\n", + "\n", + "In this demo we will also use features from the `networks`, `sim_loops`, and `utilities` modules.\n", + "\n", + "#### Install the package using ```pip```\n", + "The package can be installed on your machine by entering this in the command line:\n", + "\n", + "```pip install seirsplus```\n", + "\n", + "Then, the ```models```, `networks`, `sim_loops`, and `utilities` modules can be imported as shown here:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from seirsplus.models import *\n", + "from seirsplus.networks import *\n", + "from seirsplus.sim_loops import *\n", + "from seirsplus.utilities import *\n", + "import networkx\n", + "import matplotlib.pyplot as pyplot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### *Alternatively, manually copy the code to your machine*\n", + "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", + "```python\n", + "from models import *\n", + "from networks import *\n", + "from sim_loops import *\n", + "from utilities import *\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set basic parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the workplace size and structure" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "NUM_COHORTS = 4\n", + "NUM_NODES_PER_COHORT = 200\n", + "NUM_TEAMS_PER_COHORT = 10\n", + "\n", + "MEAN_INTRACOHORT_DEGREE = 6\n", + "PCT_CONTACTS_INTERCOHORT = 0.1" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "N = NUM_NODES_PER_COHORT*NUM_COHORTS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we set the initial prevalence to be a single case" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "INIT_EXPOSED = 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------\n", + "\n", + "## Specifying contact networks\n", + "\n", + "This package implements models epidemic dynamics for populations with a structured [contact network](Extended-SEIRS-Model-Description#contact-networks). Individuals are represented as nodes in a network, and parameters, contacts, and interventions can be specified on a targeted individual basis. A graph specifying the contact network must be specified, where each node represents an individual in the population and edges connect individuals who have regular interactions.\n", + "\n", + "This model also supports scenarios where individuals enter quarantine states in which their parameters and interactions may be different from baseline, and a separate graph defining the interactions for individuals in quarantine can be specified (i.e., the [quarantine contact network](Extended-SEIRS-Model-Description#quarantine-contacts)).\n", + "\n", + "### Workplace Contact Network\n", + "\n", + "Here we use the [**demographic community network generator**](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#workplace-network) defined in the SEIRS+ package. This function generates a contact network that resembles workplaces and other multi-level modular populations.\n", + "\n", + "[FARZ](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#farz-networks) network layers are generated to represent cohorts of employees (e.g., departments, floors, shifts). FARZ networks have a tunable community structure, so each cohort includes some number of communities, which can be thought to represent teams (i.e., groups of employees that work closely with each other). Employees may belong to more than one team (specified by a FARZ parameter), but employees belong to only one cohort. An employee's intra-team and intra-cohort contacts are defined by the FARZ cohort network they belong to. A specified percentage of each employee's total number of workplace contacts can be with individuals from other cohorts. An employee's inter-cohort contacts are drawn randomly from the pool of individuals outside their own cohort. \n", + "\n", + "The number of cohorts, number of employees per cohort, number of teams per cohort, number of teams employees belong to, mean intra-cohort degree, percent of within- and between-team connections, and percent of intra- and inter-cohort connections can be controlled with the arguments to the `generate_demographic_contact_network()` function (some of which are passed as [parameters to the FARZ generator](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#FARZ-parameters)).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Baseline:\n", + "Degree: mean = 11.11, std = 8.41, 95% CI = (1.00, 29.00)\n", + " coeff var = 0.76\n", + "Assortativity: 0.28\n", + "Clustering coeff: 0.24\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "G_baseline, cohorts, teams = generate_workplace_contact_network(\n", + " num_cohorts=NUM_COHORTS, num_nodes_per_cohort=NUM_NODES_PER_COHORT, \n", + " num_teams_per_cohort=NUM_TEAMS_PER_COHORT,\n", + " mean_intracohort_degree=MEAN_INTRACOHORT_DEGREE, \n", + " pct_contacts_intercohort=PCT_CONTACTS_INTERCOHORT,\n", + " farz_params={'alpha':5.0, 'gamma':5.0, 'beta':0.5, 'r':1, 'q':0.0, 'phi':10, \n", + " 'b':0, 'epsilon':1e-6, 'directed': False, 'weighted': False})\n", + "\n", + "network_info(G_baseline, \"Baseline\", plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we define the quarantine contact network to be an empty network (i.e., no connections). This represents an assumption that an employee that is in a quarantine state makes no contact with anyone from their workplace." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "G_quarantine = networkx.classes.function.create_empty_copy(G_baseline)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Specifying parameters\n", + "\n", + "**_The parameter values used in this notebook reflect rough estimates of parameter values for the COVID-19 epidemic (as of 9 Aug 2020)._**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set disease progression rate parameters:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Parameter values are assigned to members of the population on an individual basis. Parameter values can be [specified to the `ExtSEIRSNetworkModel`](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#specifying-parameters) by providing a list of values that gives the *N* values to assign to each individual. The population may be either homogeneous or heterogeneous for a given parameter at the user's discretion. \n", + "\n", + "**Here we generate distributions of values for each parameter, thus specifying a realistically heterogeneous population.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected latent periods (time in Exposed state) and presymptomatic periods (time in Pre-symptomatic infectious state). The `sigma` and `lamda` rates are calculated as the inverse of the expected exposed and pre-symptomatic periods assigned to each individual, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "latent period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", + "\n", + "pre-symptomatic period: mean = 2.94, std = 1.72, 95% CI = (0.64, 7.12)\n", + "\n", + "total incubation period: mean = 5.14, std = 2.03, 95% CI = (2.17, 10.02)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAD4CAYAAAAD6PrjAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3xU5bX/8c8iIBcDVK4FuYT6QwETCDQEEETwUrVFEEULBxWsgkjV1vZwRHz1lMMR669QaHts/R2sGGwBQUWk6rGISiEV5RouAgocAkaoQCoKGBDC+v0xk90ASZhAdiaX7/v1mldm9uy9n7WHMCv72c9ej7k7IiIiADXiHYCIiFQcSgoiIhJQUhARkYCSgoiIBJQUREQkUDPeAZyPJk2aeFJSUrzDEBGpVNasWXPA3ZsW9V6lTgpJSUmsXr063mGIiFQqZraruPfUfSQiIgElBRERCSgpiIhIoFJfUxCprI4fP05OTg5Hjx6NdyhShdWpU4dWrVpRq1atmLdRUhCJg5ycHOrXr09SUhJmFu9wpApyd3Jzc8nJyaFdu3Yxb6fuI5E4OHr0KI0bN1ZCkNCYGY0bNy712aiSgkicKCFI2M7ld0xJQUREAkoKIhVBfi58vavsHvm5Z20yMTGxxPcPHjzI73//+/M6rIyMDPbs2XNe+yjOnj17GDJkSKm26devn254PQtdaA5bfi7kHw63jYRESGgcbhsSrvzD8I8nym5/jSac9+9EQVIYO3bsOe8jIyOD5ORkWrZseV6xnO7EiRO0bNmSl156qUz3K0oK4Svr/+xFKYMvAKm+Dh8+zKBBg/j88885fvw4jz/+OIMGDWL8+PHs2LGD1NRUrrvuOqZMmcKUKVOYP38+x44dY/DgwfzHf/wH2dnZ3HjjjfTp04f33nuPiy++mFdffZXXX3+d1atXM3z4cOrWrcuKFSuoW7du0G6/fv1ITU1l5cqVfPnll8ycOZP09HSOHDnCgw8+yMaNGzlx4gQTJ05k0KBBZGRk8Prrr3P06FGOHDnCzJkzGTBgAJs2beLo0aPcf//9rF69mpo1azJt2jT69+9PXl4ed999N5s3b6Zjx47k5eXF8ZOuHEJLCmZWB1gG1I6285K7/9zMGgHzgCQgG7jd3T+PbvMocA+QDzzk7n8JKz4RiahTpw6vvPIKDRo04MCBA/Ts2ZOBAwfy5JNPsmnTJrKysgBYvHgx27ZtY+XKlbg7AwcOZNmyZbRp04Zt27Yxd+5cnnnmGW6//XZefvll7rjjDp566immTp1KWlpakW0fOXKE9957j2XLlvGDH/yATZs2MXnyZK6++mpmzpzJwYMHSU9P59prrwVgxYoVbNiwgUaNGpGdnR3s53e/+x0AGzduZOvWrXznO9/h448/5umnn6ZevXps2LCBDRs20K1bt3A/zCogzDOFY8DV7n7YzGoBmWb2P8AtwNvu/qSZjQfGA4+YWSdgKHA50BJYYmaXunt+iDGKVHvuzoQJE1i2bBk1atTg008/5bPPPjtjvcWLF7N48WK6du0KRM4wtm3bRps2bWjXrh2pqakAfPvb3z7lC7skw4YNA6Bv3758+eWXHDx4kMWLF7No0SKmTp0KRIbv7t69G4DrrruORo0anbGfzMxMHnzwQQA6dOhA27Zt+fjjj1m2bBkPPfQQAJ07d6Zz586l+GSqp9CSgrs7UNCZXiv6cGAQ0C+6fBawFHgkuvwFdz8G7DSz7UA6sCKsGEUEZs+ezf79+1mzZg21atUiKSmpyLHt7s6jjz7Kfffdd8ry7OxsateuHbxOSEiIuZvm9CGTZoa78/LLL3PZZZed8t4HH3zAhRdeWOR+Il83sbUhJQt19JGZJZhZFrAPeMvdPwCau/tegOjPZtHVLwY+KbR5TnTZ6fscbWarzWz1/v37wwxfpFr44osvaNasGbVq1eLdd99l165IVeX69etz6NChYL3rr7+emTNncvhw5G+9Tz/9lH379pW479P3cbp58+YBkb/0GzZsSMOGDbn++uv5r//6r+CLft26dWc9hr59+zJ79mwAPv74Y3bv3s1ll112yvJNmzaxYcOGs+6rugv1QnO06yfVzL4BvGJmySWsXlQ6PyP9u/sMYAZAWlpa8X8eiFQmCYmRAQNlub8YDR8+nJtuuom0tDRSU1Pp0KEDAI0bN6Z3794kJydz4403MmXKFLZs2UKvXr2AyJDWP/3pTyQkJBS775EjRzJmzJgiLzQDXHTRRVxxxRXBhWaAn/3sZ/z4xz+mc+fOuDtJSUm89tprJR7D2LFjGTNmDCkpKdSsWZOMjAxq167N/fffz913303nzp1JTU0lPT095s+lurKSTrvKtCGznwNHgFFAP3ffa2YtgKXufln0IjPu/ovo+n8BJrp7sd1HaWlpXuHHHH+9q3xGH13QNtw2pExt2bKFjh07xjuMuOrXr1+JF6GlbBT1u2Zma9y9yA8+tO4jM2saPUPAzOoC1wJbgUXAiOhqI4BXo88XAUPNrLaZtQPaAyvDik9ERM4UZvdRC2CWmSUQST7z3f01M1sBzDeze4DdwG0A7v6hmc0HNgMngB9q5JFI1bV06dJ4hyBFCHP00QagaxHLc4FritlmMjA5rJhERKRkqn0kIiIBJQUREQkoKYiISEBJQaQiyMuFL3aV3SPv7KWzK6vs7GzmzJkTejsLFy5k8+bNwet///d/Z8mSJaG3e67tLV26lAEDBpx3u6qSKlIRfH0YVpbh/SzpE6Du+VfOzc/PL/HmtHgoSAr/8i//Emo7CxcuZMCAAXTq1AmASZMmhdpeYfn5+eXaXmE6UxCphrKzs+nQoQMjRoygc+fODBkyhK+++gqApKQkJk2aRJ8+fXjxxRdZvHgxvXr1olu3btx2221BmYvC9u7dS9++fUlNTSU5OZnly5fz7LPP8vDDDwfrPPPMM/zkJz8J2r733ntJTk5m+PDhLFmyhN69e9O+fXtWrozcnjRx4kTuvPNOrr76atq3b88zzzwDwPjx41m+fDmpqalMnz6do0ePcvfdd5OSkkLXrl159913gchcDjfffDM33XQT7dq146mnnmLatGl07dqVnj178o9//COIq3v37nTp0oVbb72Vr776ivfee49FixYxbtw4UlNT2bFjByNHjgzmb1i1ahVXXHEFXbp0IT09/YxSHkuXLqVv374MHjyYTp06MWbMGE6ePAlQ7Od5+udeuL23336brl27kpKSwg9+8AOOHTsGwJtvvkmHDh3o06cPCxYsKIPfDCUFkWrro48+YvTo0WzYsIEGDRqcMstanTp1yMzM5Nprr+Xxxx9nyZIlrF27lrS0NKZNm3bGvubMmcP1119PVlYW69evJzU1laFDh7Jo0SKOHz8OwHPPPcfdd98NwPbt2/nRj37Ehg0b2Lp1K3PmzCEzM5OpU6fyxBP/PGPasGEDr7/+OitWrGDSpEns2bOHJ598kiuvvJKsrCwefvjhU8pmz507lxEjRgQF/TZt2sScOXNYuXIljz32GPXq1WPdunX06tWL559/HoBbbrmFVatWsX79ejp27Mizzz7LFVdcwcCBA5kyZQpZWVlccsklQUxff/013//+9/nNb37D+vXrWbJkyRnlOwBWrlzJr371KzZu3MiOHTtYsGABBw4cKPHzLPjchw4dGiw7evQoI0eOZN68ecEcE08//TRHjx5l1KhR/PnPf2b58uX8/e9/L/0vQRGUFESqqdatW9O7d28A7rjjDjIzM4P3vv/97wPw/vvvs3nzZnr37k1qaiqzZs0KCuYV1r17d5577jkmTpzIxo0bqV+/PhdeeCFXX301r732Glu3buX48eOkpKQA0K5dO1JSUqhRowaXX34511xzDWZGSkrKKWW3Bw0aRN26dWnSpAn9+/cPziIKy8zM5M477wROLZsN0L9/f+rXr0/Tpk1p2LAhN910E8Ap7WzatIkrr7ySlJQUZs+ezYcfflji5/bRRx/RokULunfvDkCDBg2oWfPMnvj09HS+9a1vkZCQwLBhw8jMzDzr51nwuZ/eXrt27bj00ksBGDFiBMuWLWPr1q20a9eO9u3bY2bccccdJcYdK11TEKmmiipbXaCgRLW7c9111zF37txT1v3ggw+CEtqTJk0KJtx5/fXXufPOOxk3bhx33XUX9957L0888QQdOnQIzhKAU0pt16hRI3hdo0YNTpw4EVOMBUqq3xZLOyNHjmThwoV06dKFjIyMs95p7e4xleMurix4UZ9ngaJKg5d3WXCdKYhUU7t372bFiki9yblz59KnT58z1unZsyd/+9vf2L59OwBfffUVH3/8MT169CArK4usrCwGDhzIrl27aNasGaNGjeKee+5h7dq1APTo0YNPPvmEOXPmBBPqlMarr77K0aNHyc3NZenSpXTv3v2MctzFlc2O1aFDh2jRogXHjx8P9gPFl/3u0KEDe/bsYdWqVcH2hRNZgZUrV7Jz505OnjzJvHnz6NOnT7GfZ0k6dOhAdnZ2sM0f//hHrrrqKjp06MDOnTvZsWMHQLGJprR0piBSEVyQGBkxVJb7O4uOHTsya9Ys7rvvPtq3b8/9999/xjpNmzYlIyODYcOGBRc3H3/88aAro8DSpUuZMmUKtWrVIjExMeivB7j99tvJysrioosuKvVhpKen873vfY/du3fzs5/9jJYtW9K0aVNq1qxJly5dGDlyZLFls2P1n//5n/To0YO2bduSkpISJIKhQ4cyatQofvvb3wYXfAEuuOAC5s2bx4MPPkheXh5169ZlyZIlJCae+pn36tWL8ePHs3HjxuCic40aNWL6PAurU6cOzz33HLfddhsnTpyge/fujBkzhtq1azNjxgy+973v0aRJE/r06cOmTZtK8/EWqdxKZ4dBpbOjVDq70ol36ezs7Oxg0vuwDRgwgIcffphrrimy5FmxJk6cSGJiIv/6r/8aUmThWbp0KVOnTj3rPBDlocKUzhaR6u3gwYNceuml1K1bt9QJQeJH3Uci1VBSUlLoZwnf+MY3ztpfXpKJEyeWXTDlrF+/fvTr1y/eYZwTnSmIiEhASUFERAJKCiIiElBSEBGRgJKCSAWQm5vLrl27yuyRm1ty6eyDBw+eUuuoOLGWqc7OziY5OfmM5Xv27GHIkCFn3b40imurJBkZGezZsyd4fe+9955SFjuevvvd73Lw4MGY1584cSJTp04NLR6NPhKpAA4fPnxKIbjzNWHCBBo3Lr50dkFSGDt2bIn7Od8y1S1btjzlxq94ycjIIDk5mZYtWwLwhz/8Ic4RRcpXuDtvvPFGvEM5hc4URKqh8ePHs2PHDlJTUxk3bhzuzrhx40hOTiYlJYV58+YF6xUuU52dnc2VV15Jt27d6NatG++9916J7RT+qz4jI4NbbrmFG264gfbt2/Nv//ZvwXpvvvkm3bp1o0uXLsE9Daf/RZycnBwUsTtx4kSRZb8nTZpE9+7dSU5OZvTo0bg7L730EqtXr2b48OGkpqaSl5dHv379KLjxde7cuaSkpJCcnMwjjzwStJeYmMhjjz1Gly5d6NmzJ5999tkZx1dceW+AKVOm0L17dzp37szPf/7z4PPo2LEjY8eOpVu3bnzyySckJSVx4MABAKZNm0ZycjLJycn8+te/DvY1efJkLrvsMq699lo++uijEj/z86WkIFINPfnkk1xyySVkZWUxZcoUFixYEJS9XrJkCePGjWPv3r1nlKlu1qwZb731FmvXrmXevHk89NBDpWo3KysrKAE9b948PvnkE/bv38+oUaN4+eWXWb9+PS+++OJZ91Nc2e8HHniAVatWsWnTJvLy8njttdcYMmQIaWlpzJ49m6ysrFPKXO/Zs4dHHnmEd955h6ysLFatWsXChQsBOHLkCD179mT9+vX07dv3lC/8wooq77148WK2bdvGypUrycrKYs2aNSxbtiyI/a677mLdunW0bfvPSgRr1qzhueee44MPPuD999/nmWeeYd26daxZs4YXXniBdevWsWDBgqDmUliUFESEzMxMhg0bRkJCAs2bN+eqq64q8svn+PHjjBo1ipSUFG677bZS98tfc801NGzYkDp16tCpUyd27drF+++/T9++fWnXrh0AjRo1Out+iiv7/e6779KjRw9SUlJ45513zloGe9WqVfTr1y+opzR8+PDgy/uCCy4Iprf89re/fUpJ78KKKu+9ePFiFi9eTNeuXenWrRtbt25l27ZtALRt25aePXuesZ/MzEwGDx7MhRdeSGJiIrfccgvLly9n+fLlDB48mHr16tGgQQMGDhx41s/nfOiagoiUWJ65sOnTp9O8eXPWr1/PyZMnqVOnTqnaKVyoLiEhgRMnThRbirpmzZrBbGVAMHEOFF2W+ujRo4wdO5bVq1fTunVrJk6ceMo2RSnpuGvVqhW0UxBrUYorkf3oo48G5cULZGdnF1ke+2yxhFEiuzg6U6gqvt4V/iO/6k4GX90UVX563rx55Ofns3//fpYtW0Z6evoZ633xxRe0aNGCGjVq8Mc//pH8/PzzjqVXr1789a9/ZefOnQDBNJlJSUlBCe61a9cG70PRZb8LEkCTJk04fPjwKRe4iyuD3aNHD/76179y4MAB8vPzmTt3LldddVWp4i+qvPf111/PzJkzg6k2P/30U/bt21fifvr27cvChQv56quvOHLkCK+88gpXXnklffv25ZVXXiEvL49Dhw7x5z//uVTxlVZoZwpm1hp4HvgmcBKY4e6/MbOJwChgf3TVCe7+RnSbR4F7gHzgIXf/S1jxVSmeB59PD7+dRhMg4fwng5czJSYmMmFC2ZXOPr2M8+kaN25M7969SU5O5sYbb+SXv/wlK1asoEuXLpgZv/zlL/nmN79J48aNzyhTfeutt/Liiy/Sv3//Yv/qLY2mTZsyY8YMbrnlFk6ePBlct7j11lt5/vnnSU1NpXv37qeUly6q7He9evWCrq2kpKRgZjSITKQzZswY6tatGyQTgBYtWvCLX/yC/v374+5897vfZdCgQaWKv6jy3i1btmTLli306tULiPx7/OlPfyIhIaHY/XTr1o2RI0eSnp4ORIbNdu3aFYjMyJaamkrbtm258sorSxVfaYVWOtvMWgAt3H2tmdUH1gA3A7cDh9196mnrdwLmAulAS2AJcKm7F/uniEpnR130cPklBZXoLhPxLp0tZaMy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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "latentPeriod_mean, latentPeriod_coeffvar = 3.0, 0.6\n", + "SIGMA = 1 / gamma_dist(latentPeriod_mean, latentPeriod_coeffvar, N)\n", + "\n", + "presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar = 2.2, 0.5\n", + "LAMDA = 1 / gamma_dist(presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar, N)\n", + "\n", + "dist_info([1/LAMDA, 1/SIGMA, 1/LAMDA+1/SIGMA], [\"latent period\", \"pre-symptomatic period\", \"total incubation period\"], plot=True, colors=['gold', 'darkorange', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected (a)symptomatic periods (time in symptomatic or asymptomatic state). The `gamma` rates are calculated as the inverse of the expected (a)symptomatic periods assigned to each individual. \n", + "\n", + "The expected total infectious period for each individual is the sum of their expected pre-symptomatic and (a)symptomatic periods." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pre-symptomatic period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", + "\n", + "(a)symptomatic period: mean = 4.01, std = 1.54, 95% CI = (1.64, 7.36)\n", + "\n", + "total infectious period: mean = 6.20, std = 1.87, 95% CI = (3.09, 10.45)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "symptomaticPeriod_mean, symptomaticPeriod_coeffvar = 4.0, 0.4\n", + "GAMMA = 1 / gamma_dist(symptomaticPeriod_mean, symptomaticPeriod_coeffvar, N)\n", + "\n", + "infectiousPeriod = 1/LAMDA + 1/GAMMA\n", + "\n", + "dist_info([1/LAMDA, 1/GAMMA, 1/LAMDA+1/GAMMA], [\"pre-symptomatic period\", \"(a)symptomatic period\", \"total infectious period\"], plot=True, colors=['darkorange', 'crimson', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected onset-to-hospitalization periods (time in symptomatic state before entering hospitalized state for those with severe cases) and hospitalization-to-discharge periods (time in hospitalized state for those with non-fatal cases). The `eta` and `gamma_H` rates are calculated as the inverse of the expected onset-to-hospitalization periods and hospitalization-to-discharge periods assigned to each individual, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", + "\n", + "hospitalization-to-discharge period: mean = 11.38, std = 5.29, 95% CI = (3.49, 23.54)\n", + "\n", + "onset-to-discharge period: mean = 22.51, std = 7.16, 95% CI = (10.62, 39.43)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3wU5bnA8d+TEAzITQE9QYTIOVzEEAOGqxQIVFChXBRQDigXIdADUmiLUKyCqICtRyPWUwpYpGopiHIR23ojiFyEgERALFo0UCRyCUIJIeSy7/ljN+smOxs2Ibub3Xm+n08+yc7szDwZwpPJM+88rxhjUEopZR9RoQ5AKaVUcGniV0opm9HEr5RSNqOJXymlbEYTv1JK2UyNUAfgj0aNGpn4+PhQh6GUUmFlz549p40xjcsuD4vEHx8fz+7du0MdhlJKhRUROWK1XEs9SillM5r4lVLKZjTxK6WUzYRFjV9FtsLCQo4dO0Z+fn6oQ1EqLMXGxtK0aVNiYmL8er8mfhVyx44do27dusTHxyMioQ5HqbBijCEnJ4djx45x0003+bWNlnpUyOXn59OwYUNN+kpVgojQsGHDCv3FrIlfVQua9JWqvIr+/9HEr5RSNqOJX1U7xd+fo/Bf31XZR/H350L6/WRmZvLXv/7V5/q0tDTy8vIqtM/NmzczYMCAKw3Np927dzN16lT3sbZv337ZbV555RWmTJkCwOLFi/nTn/5U4eOWPVZl9xMIjz/+OB988IHf7w/0v9GV0Ju71Vzx9+dw5F70Wi4xNTCFRZbbRNWpRfQ19QMdWsA4ci9yNu3VKttfg2kPhPR8ZGZmsnv3bu6++27L9WlpaYwaNYratWsHOTLfkpOTSU5OBpwJrE6dOnTr1s3v7SdNmlSp45Y9VmX3U9WKi4uZN29eqMOoMnrFX82VJMGyH8XnL1guP5v2quUvClW+5557joSEBBISEkhLSwMgKyuLm2++mQkTJnDLLbfQt29fLl50nttFixbRtm1bEhMTuf/++wG4cOEC48aNo2PHjrRv357169dTUFDA448/zqpVq0hKSmLVqlWljrto0SKOHz9OSkoKKSkpAKxcuZJ27dqRkJDAzJkzfcacm5vL0KFDadOmDSNHjqRkNr0PP/yQ9u3b065dO8aNG8elS5cAmDVrljvmX/7ylwCMGTOGSZMm8aMf/YhWrVqxceNG4Ier1aysLBYvXszzzz9PUlISH3/8MW+//TadO3emffv2/PjHP+bEiRNesc2dO5dnn32W48ePk5SU5P6Ijo7myJEjlvuwOlbJfsD5C7RLly4kJiYyZMgQvv/+ewB69erFzJkz6dSpE61ateLjjz/2imfz5s306NGDIUOG0LZtWyZNmoTD4QDgvffeo2vXrnTo0IFhw4aRm5sLOFvFzJs3j+7du/PGG28wZswY1qxZU+45/vvf/06bNm3o3r07b731ls9/u1DTxK9sb8+ePSxfvpydO3fyySefsHTpUvbu3QvAV199xeTJk/n8889p0KABb775JgALFy5k79697Nu3j8WLFwPw9NNP07t3bzIyMkhPT2fGjBkUFhYyb9487rvvPjIzM7nvvvtKHXvq1Kk0adKE9PR00tPTOX78ODNnzmTTpk1kZmaSkZHBunXrLOPeu3cvaWlpHDx4kK+//ppt27aRn5/PmDFjWLVqFfv376eoqIjf//73nDlzhrVr1/L555+zb98+fv3rX7v3k5WVxUcffcQ777zDpEmTSo0OiY+PZ9KkSUyfPp3MzEx+9KMf0b17dz755BP27t3L/fffz29+8xuf57ZJkyZkZmaSmZnJhAkTuPfee2nevLnlPqyO5enBBx/kmWeeYd++fbRr144nnnjCva6oqIhdu3aRlpZWarmnXbt28b//+7/s37+fw4cP89Zbb3H69GmeeuopPvjgAz799FOSk5N57rnn3NvExsaydetW9y93wOc5zs/PZ8KECbz99tt8/PHHfPfddz7PS6hpqcdmfJWOIPxLRJW1detWhgwZwtVXXw3APffcw8cff8zAgQO56aabSEpKAuC2224jKysLgMTEREaOHMngwYMZPHgw4Lxy3LBhg/sKNT8/n6NHj1YoloyMDHr16kXjxs6GiiNHjmTLli3uY3jq1KkTTZs2BSApKYmsrCzq1q3LTTfdRKtWrQAYPXo0L730ElOmTCE2Npbx48fTv3//UrXn4cOHExUVRcuWLWnRogX/+Mc/yo3x2LFj3HfffWRnZ1NQUODX2PFt27axbNky99V4Rfdx7tw5zp49S8+ePd3f17Bhw9zr77nnHqD0v1FZnTp1okWLFgCMGDGCrVu3Ehsby8GDB7n99tsBKCgooGvXru5tyv6iBjh06JDl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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar = 11.0, 0.45\n", + "ETA = 1 / gamma_dist(onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar, N)\n", + "\n", + "hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar = 11.0, 0.45\n", + "GAMMA_H = 1 / gamma_dist(hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar, N)\n", + "\n", + "dist_info([1/ETA, 1/GAMMA_H, 1/ETA+1/GAMMA_H], [\"onset-to-hospitalization period\", \"hospitalization-to-discharge period\", \"onset-to-discharge period\"], plot=True, colors=['crimson', 'violet', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of hospitalization-to-death periods (time in hospitalized state for those with fatal cases). The `mu_H` rates are calculated as the inverse of the expected hospitalization-to-death periods." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", + "\n", + "hospitalization-to-death period: mean = 6.87, std = 3.10, 95% CI = (2.01, 13.61)\n", + "\n", + "onset-to-death period: mean = 17.99, std = 6.08, 95% CI = (8.34, 31.59)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar = 7.0, 0.45\n", + "MU_H = 1 / gamma_dist(hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar, N)\n", + "\n", + "dist_info([1/ETA, 1/MU_H, 1/ETA+1/MU_H], [\"onset-to-hospitalization period\", \"hospitalization-to-death period\", \"onset-to-death period\"], plot=True, colors=['crimson', 'darkgray', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set severity parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the percentage of cases that are asymptomatic. This percentage of case will progress from the pre-symptomatic state to the asymptomatic state, rather than to the symptomatic state." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_ASYMPTOMATIC = 0.25" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the case hospitalization rate. The value used here is approximately the age-frequency-weighted average of age-stratified hospitalization rates for working age adults using data from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_HOSPITALIZED = 0.035" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the case fatality rate for hospitalized cases. The value used here is approximately the age-frequency-weighted average of age stratified hospitalization fatality rates for working age adults, again using figures from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_FATALITY = 0.08" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set transmission parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#stochastic-network-model-implementation) model considers two modes of disease transmission: a well-mixed mode of [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) and a contact network based mode of [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The propensity for a given individual to become exposed due to global transmission depends on the mean transmissibility of all infectious individuals in the population; the propensity for a given individual to become exposed due to local transmission depends on the pairwise transmissibilities between the focal node and its infectious contacts in the network (see [Transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#transmission) and [Model Equations](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#model-equations) for more information about these calculations). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The transmissibility parameter *β* can be related to the basic reproduction number *R0* (i.e., the expected number of new infections generated by a single infectious individual in a completely susceptible population) by the standard formula: *β = R0𝛾*. *R0* is a more interpretable parameter, so we specify transmissibility in terms of *R0* and then calculate the corresponding *β* values.\n", + "\n", + "First, we generate a distribution of individual *R0* values (i.e., the expected number of new infections generated by a single *particular* infectious individual in a completely susceptible population). Of course, this means that transmissibility is heterogeneous in this population. The coefficient of variation is an important parameter for the individual *R0* distribution in that it tunes the degree of superspreading in the heterogeneous transmissibility. The distribution used in this example has a relatively low coefficient of variation, so most individuals have around the same degree of transmissibility. But a higher coefficient of variation (e.g., 2.0) would give a long right tail in idividual transmissibility representing a small number of individuals contributing many cases while the majority cases contribute less than 1 on average when they are infectious." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Individual R0: mean = 1.98, std = 0.41, 95% CI = (1.32, 2.89)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "R0_mean = 2.0\n", + "R0_coeffvar = 0.2\n", + "\n", + "R0 = gamma_dist(R0_mean, R0_coeffvar, N)\n", + "\n", + "dist_info(R0, \"Individual R0\", bin_size=0.1, plot=True, colors='crimson')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Individuals are ultimately assigned an [*Individual Transmissibility Value*](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#transmissibility-parameters) (*βi*), which are stored in the `beta` attribute of the model object. \n", + "\n", + "The means of the Individual Transmissibility Values for infectious subpopulations are used to calculate the [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) terms. Individual Transmissibility Values may also be used to generate the Pairwise Transmissibility Values used for [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission) terms, as we will specify in a few steps." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "BETA = 1/infectiousPeriod * R0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the stochastic network model, an individual comes into contact with a random individual from the population at large (e.g., in a public space) with probability *p* or with an individual from their set of close contacts with probability *(1-p)*. Transmission that occurs between an individual and the population at large is referred to as [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission), and transmission between an individual and one of their close contacts (network neighbors) is referred to as [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The parameter *p* defines the locality of the network: for *p=0* an individual only interacts with their close contacts, while *p=1* represents a uniformly mixed population.\n", + "\n", + "Here we set *p* to reflect 40% of interactions being with incidental or casual contacts outside their set of close contacts." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "P_GLOBALINTXN = 0.4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Testing, Tracing, & Isolation (TTI) intervention protocol parameters:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the parameters that govern the Testing, Tracing, and Isolation protocol that is implemented by the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). The implementation of this TTI protocol and the interpretation of these parameters is desribed in detail on the [TTI Simulation Loop wiki page](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) (but these parameters are briefly explained as code comments below).\n", + "\n", + "**The scenario set up in the steps that follow involves the entire workforce being tested on a weekly basis, a 2-day test turn around time, 50% of symptomatic individuals self-reporting and getting tested within 1 day of onset, 30% of symptomatics self-isolating even without a positive test, and teams of detected positive cases being proactively isolated. A new exogenous exposures comes into the workplace about once a week.**" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "INTERVENTION_START_PCT_INFECTED = 0/100\n", + "AVERAGE_INTRODUCTIONS_PER_DAY = 1/14 # expected number of new exogenous exposures per day\n", + "\n", + "TESTING_CADENCE = 'weekly' # how often to do testing (other than self-reporting symptomatics who can get tested any day)\n", + "PCT_TESTED_PER_DAY = 1.0 # max daily test allotment defined as a percent of population size\n", + "TEST_FALSENEG_RATE = 'temporal' # test false negative rate, will use FN rate that varies with disease time\n", + "MAX_PCT_TESTS_FOR_SYMPTOMATICS = 1.0 # max percent of daily test allotment to use on self-reporting symptomatics\n", + "MAX_PCT_TESTS_FOR_TRACES = 0.0 # max percent of daily test allotment to use on contact traces\n", + "RANDOM_TESTING_DEGREE_BIAS = 0 # magnitude of degree bias in random selections for testing, none here\n", + "\n", + "PCT_CONTACTS_TO_TRACE = 0.0 # percentage of primary cases' contacts that are traced\n", + "TRACING_LAG = 2 # number of cadence testing days between primary tests and tracing tests\n", + "\n", + "ISOLATION_LAG_SYMPTOMATIC = 1 # number of days between onset of symptoms and self-isolation of symptomatics\n", + "ISOLATION_LAG_POSITIVE = 2 # test turn-around time (TAT): number of days between administration of test and isolation of positive cases\n", + "ISOLATION_LAG_CONTACT = 0 # number of days between a contact being traced and that contact self-isolating\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set intervention compliance parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, we specify the compliance rates (i.e., the percentage of individuals who are compliant) for each intervention type. See the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) documentation for more information about compliance." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "TESTING_COMPLIANCE_RATE_SYMPTOMATIC = 0.5 \n", + "TESTING_COMPLIANCE_RATE_TRACED = 0.0\n", + "TESTING_COMPLIANCE_RATE_RANDOM = 1.0 # Assume employee testing is mandatory, so 100% compliance\n", + "\n", + "TRACING_COMPLIANCE_RATE = 0.0\n", + "\n", + "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL = 0.3\n", + "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE = 0.8 # Isolate teams with a positive member, but suppose 20% of employees are essential workforce\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE = 0.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we randomly assign a `True/False` compliance to each individual according to the rates set above. Individuals whose compliance is set to `True` for a given intervention will participate in that intervention, individuals set to `False` will not." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "TESTING_COMPLIANCE_RANDOM = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_RANDOM)\n", + "TESTING_COMPLIANCE_TRACED = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_TRACED)\n", + "TESTING_COMPLIANCE_SYMPTOMATIC = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_SYMPTOMATIC)\n", + "\n", + "TRACING_COMPLIANCE = (numpy.random.rand(N) < TRACING_COMPLIANCE_RATE)\n", + "\n", + "ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL)\n", + "ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE)\n", + "ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL)\n", + "ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE)\n", + "ISOLATION_COMPLIANCE_POSITIVE_CONTACT = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT)\n", + "ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initializing the model" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\boaz\\PycharmProjects\\seirsplus\\seirsplus\\models.py:2143: RuntimeWarning: invalid value encountered in true_divide\n", + " self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1))\n" + ] + } + ], + "source": [ + "model = ExtSEIRSNetworkModel(G=G_baseline, p=P_GLOBALINTXN,\n", + " beta=BETA, sigma=SIGMA, lamda=LAMDA, gamma=GAMMA, \n", + " gamma_asym=GAMMA, eta=ETA, gamma_H=GAMMA_H, mu_H=MU_H, \n", + " a=PCT_ASYMPTOMATIC, h=PCT_HOSPITALIZED, f=PCT_FATALITY, \n", + " G_Q=G_quarantine, isolation_time=14,\n", + " initE=INIT_EXPOSED)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running the model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set the max simulation time to 300 days." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "T = 300" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Execute the TTI simulation scenario by calling the `run_tti_sim()` function, which runs a custom simulation loop that implements the [TTI Simulation Protocol](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop)." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[INTERVENTIONS @ t = 0.64 (4 (0.50%) infected)]\n" + ] + }, + { + "ename": "NameError", + "evalue": "name 'sort' is not defined", + "output_type": "error", + "traceback": [ + "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[1;31mNameError\u001B[0m Traceback (most recent call last)", + "\u001B[1;32m\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[1;32m----> 1\u001B[1;33m run_tti_sim(model, T, \n\u001B[0m\u001B[0;32m 2\u001B[0m \u001B[0mintervention_start_pct_infected\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mINTERVENTION_START_PCT_INFECTED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maverage_introductions_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mAVERAGE_INTRODUCTIONS_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3\u001B[0m \u001B[0mtesting_cadence\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_CADENCE\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpct_tested_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mPCT_TESTED_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtest_falseneg_rate\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTEST_FALSENEG_RATE\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[0mtesting_compliance_symptomatic\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_SYMPTOMATIC\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_symptomatics\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_SYMPTOMATICS\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m \u001B[0mtesting_compliance_traced\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_TRACED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_traces\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_TRACES\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", + "\u001B[1;32m~\\PycharmProjects\\seirsplus\\seirsplus\\sim_loops.py\u001B[0m in \u001B[0;36mrun_tti_sim\u001B[1;34m(model, T, intervention_start_pct_infected, average_introductions_per_day, testing_cadence, pct_tested_per_day, test_falseneg_rate, testing_compliance_symptomatic, max_pct_tests_for_symptomatics, testing_compliance_traced, max_pct_tests_for_traces, testing_compliance_random, random_testing_degree_bias, tracing_compliance, num_contacts_to_trace, pct_contacts_to_trace, tracing_lag, isolation_compliance_symptomatic_individual, isolation_compliance_symptomatic_groupmate, isolation_compliance_positive_individual, isolation_compliance_positive_groupmate, isolation_compliance_positive_contact, isolation_compliance_positive_contactgroupmate, isolation_lag_symptomatic, isolation_lag_positive, isolation_lag_contact, isolation_groups, cadence_testing_days, cadence_cycle_length, temporal_falseneg_rates, test_priority)\u001B[0m\n\u001B[0;32m 268\u001B[0m \u001B[1;32mif\u001B[0m \u001B[1;34m'last_tested'\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mtest_priority\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 269\u001B[0m \u001B[1;31m# sort the pool according to the time they were last tested, breaking ties randomly\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 270\u001B[1;33m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0msort\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mkey\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mi\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mmodel\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtestedTime\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mi\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcmp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0my\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m*\u001B[0m \u001B[1;36m2\u001B[0m \u001B[1;33m-\u001B[0m \u001B[1;36m1\u001B[0m \u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[0mnumRandomTests\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 271\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 272\u001B[0m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtestingPool\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnumpy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mchoice\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnumRandomTests\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mp\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mtestingPool_degreeWeights\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreplace\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", + "\u001B[1;31mNameError\u001B[0m: name 'sort' is not defined" + ] + } + ], + "source": [ + "run_tti_sim(model, T, \n", + " intervention_start_pct_infected=INTERVENTION_START_PCT_INFECTED, average_introductions_per_day=AVERAGE_INTRODUCTIONS_PER_DAY,\n", + " testing_cadence=TESTING_CADENCE, pct_tested_per_day=PCT_TESTED_PER_DAY, test_falseneg_rate=TEST_FALSENEG_RATE, \n", + " testing_compliance_symptomatic=TESTING_COMPLIANCE_SYMPTOMATIC, max_pct_tests_for_symptomatics=MAX_PCT_TESTS_FOR_SYMPTOMATICS,\n", + " testing_compliance_traced=TESTING_COMPLIANCE_TRACED, max_pct_tests_for_traces=MAX_PCT_TESTS_FOR_TRACES,\n", + " testing_compliance_random=TESTING_COMPLIANCE_RANDOM, random_testing_degree_bias=RANDOM_TESTING_DEGREE_BIAS,\n", + " tracing_compliance=TRACING_COMPLIANCE, pct_contacts_to_trace=PCT_CONTACTS_TO_TRACE, tracing_lag=TRACING_LAG,\n", + " isolation_compliance_symptomatic_individual=ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL, isolation_compliance_symptomatic_groupmate=ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE, \n", + " isolation_compliance_positive_individual=ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL, isolation_compliance_positive_groupmate=ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE,\n", + " isolation_compliance_positive_contact=ISOLATION_COMPLIANCE_POSITIVE_CONTACT, isolation_compliance_positive_contactgroupmate=ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE,\n", + " isolation_lag_symptomatic=ISOLATION_LAG_SYMPTOMATIC, isolation_lag_positive=ISOLATION_LAG_POSITIVE, \n", + " isolation_groups=list(teams.values()),\n", + " test_priority = 'last_tested')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "total percent infected: 0.88%\n", + "total percent fatality: 0.00%\n", + "peak pct hospitalized: 0.00%\n" + ] + } + ], + "source": [ + "results_summary(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualizing the results" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = model.figure_infections(combine_Q_infected=False, plot_Q_R='stacked', plot_Q_S='stacked')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file From fd46ae2edb912c15fc2b36200c722d422db16a17 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 11:21:23 -0400 Subject: [PATCH 003/117] Fixed bug with sorting --- seirsplus/sim_loops.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 339aa5d..ae9006d 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -264,10 +264,11 @@ def run_tti_sim(model, T, else: testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) - if(len(testingPool) > 0): + poolSize = len(testingPool) + if(poolSize > 0): if 'last_tested' in test_priority: # sort the pool according to the time they were last tested, breaking ties randomly - randomSelection = sort(testingPool,key = lambda i: model.testedTime[i], cmp = lambda x,y: x-y if x-y else random.randint(0, 1) * 2 - 1 )[:numRandomTests] + randomSelection = sorted(testingPool,key = lambda i: (model.testedTime[i], random.randint(0,poolSize*poolSize)))[:numRandomTests] else: randomSelection = testingPool[numpy.random.choice(len(testingPool), numRandomTests, p=testingPool_degreeWeights, replace=False)] From 51d3ad00c0c53b03d9c727a3d6ffd70014962538 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 11:26:52 -0400 Subject: [PATCH 004/117] Remove testing notebook from git tracking --- .gitignore | 1 + .../Extended_SEIRS_Workplace_TTI_Demo.ipynb | 20 +- ...EIRS_Workplace_TTI_Demo_timePriority.ipynb | 853 ------------------ 3 files changed, 3 insertions(+), 871 deletions(-) delete mode 100644 examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb diff --git a/.gitignore b/.gitignore index 76386e1..2cff9c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # ignore temporary swap files *.swp +examples/Testing*.ipynb # ignore notebooks used for testing features .DS_Store diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb index be4bb46..f7a63ec 100644 --- a/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb +++ b/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb @@ -31,10 +31,8 @@ ] }, { - "cell_type": "code", - "execution_count": 1, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ "from seirsplus.models import *\n", "from seirsplus.networks import *\n", @@ -44,20 +42,6 @@ "import matplotlib.pyplot as pyplot" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### *Alternatively, manually copy the code to your machine*\n", - "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", - "```python\n", - "from models import *\n", - "from networks import *\n", - "from sim_loops import *\n", - "from utilities import *\n", - "```" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -3279,4 +3263,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb deleted file mode 100644 index 45a2eec..0000000 --- a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb +++ /dev/null @@ -1,853 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Extended SEIRS Workplace TTI Demo\n", - "\n", - "**In this demonstration we will explore the effect of testing, tracing, and isolation interventions on disease transmission in a workplace setting with a realistic contact network.**\n", - "\n", - "This notebook provides a demonstration of the functionality of the [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description) and the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). This notebook also offers a sandbox for starting to explore TTI scenarios of your own. \n", - "For a more thorough walkthrough of the model, simulation loop, and use of this package, refer to the [SEIRS+ Wiki](https://github.com/ryansmcgee/seirsplus/wiki)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Installing and importing the model code\n", - "\n", - "All of the code needed to run the model is imported from the ```models``` module of this package.\n", - "\n", - "In this demo we will also use features from the `networks`, `sim_loops`, and `utilities` modules.\n", - "\n", - "#### Install the package using ```pip```\n", - "The package can be installed on your machine by entering this in the command line:\n", - "\n", - "```pip install seirsplus```\n", - "\n", - "Then, the ```models```, `networks`, `sim_loops`, and `utilities` modules can be imported as shown here:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from seirsplus.models import *\n", - "from seirsplus.networks import *\n", - "from seirsplus.sim_loops import *\n", - "from seirsplus.utilities import *\n", - "import networkx\n", - "import matplotlib.pyplot as pyplot" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### *Alternatively, manually copy the code to your machine*\n", - "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", - "```python\n", - "from models import *\n", - "from networks import *\n", - "from sim_loops import *\n", - "from utilities import *\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Set basic parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the workplace size and structure" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "NUM_COHORTS = 4\n", - "NUM_NODES_PER_COHORT = 200\n", - "NUM_TEAMS_PER_COHORT = 10\n", - "\n", - "MEAN_INTRACOHORT_DEGREE = 6\n", - "PCT_CONTACTS_INTERCOHORT = 0.1" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "N = NUM_NODES_PER_COHORT*NUM_COHORTS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we set the initial prevalence to be a single case" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "INIT_EXPOSED = 4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------\n", - "\n", - "## Specifying contact networks\n", - "\n", - "This package implements models epidemic dynamics for populations with a structured [contact network](Extended-SEIRS-Model-Description#contact-networks). Individuals are represented as nodes in a network, and parameters, contacts, and interventions can be specified on a targeted individual basis. A graph specifying the contact network must be specified, where each node represents an individual in the population and edges connect individuals who have regular interactions.\n", - "\n", - "This model also supports scenarios where individuals enter quarantine states in which their parameters and interactions may be different from baseline, and a separate graph defining the interactions for individuals in quarantine can be specified (i.e., the [quarantine contact network](Extended-SEIRS-Model-Description#quarantine-contacts)).\n", - "\n", - "### Workplace Contact Network\n", - "\n", - "Here we use the [**demographic community network generator**](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#workplace-network) defined in the SEIRS+ package. This function generates a contact network that resembles workplaces and other multi-level modular populations.\n", - "\n", - "[FARZ](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#farz-networks) network layers are generated to represent cohorts of employees (e.g., departments, floors, shifts). FARZ networks have a tunable community structure, so each cohort includes some number of communities, which can be thought to represent teams (i.e., groups of employees that work closely with each other). Employees may belong to more than one team (specified by a FARZ parameter), but employees belong to only one cohort. An employee's intra-team and intra-cohort contacts are defined by the FARZ cohort network they belong to. A specified percentage of each employee's total number of workplace contacts can be with individuals from other cohorts. An employee's inter-cohort contacts are drawn randomly from the pool of individuals outside their own cohort. \n", - "\n", - "The number of cohorts, number of employees per cohort, number of teams per cohort, number of teams employees belong to, mean intra-cohort degree, percent of within- and between-team connections, and percent of intra- and inter-cohort connections can be controlled with the arguments to the `generate_demographic_contact_network()` function (some of which are passed as [parameters to the FARZ generator](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#FARZ-parameters)).\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Baseline:\n", - "Degree: mean = 11.11, std = 8.41, 95% CI = (1.00, 29.00)\n", - " coeff var = 0.76\n", - "Assortativity: 0.28\n", - "Clustering coeff: 0.24\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "G_baseline, cohorts, teams = generate_workplace_contact_network(\n", - " num_cohorts=NUM_COHORTS, num_nodes_per_cohort=NUM_NODES_PER_COHORT, \n", - " num_teams_per_cohort=NUM_TEAMS_PER_COHORT,\n", - " mean_intracohort_degree=MEAN_INTRACOHORT_DEGREE, \n", - " pct_contacts_intercohort=PCT_CONTACTS_INTERCOHORT,\n", - " farz_params={'alpha':5.0, 'gamma':5.0, 'beta':0.5, 'r':1, 'q':0.0, 'phi':10, \n", - " 'b':0, 'epsilon':1e-6, 'directed': False, 'weighted': False})\n", - "\n", - "network_info(G_baseline, \"Baseline\", plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we define the quarantine contact network to be an empty network (i.e., no connections). This represents an assumption that an employee that is in a quarantine state makes no contact with anyone from their workplace." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "G_quarantine = networkx.classes.function.create_empty_copy(G_baseline)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Specifying parameters\n", - "\n", - "**_The parameter values used in this notebook reflect rough estimates of parameter values for the COVID-19 epidemic (as of 9 Aug 2020)._**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set disease progression rate parameters:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Parameter values are assigned to members of the population on an individual basis. Parameter values can be [specified to the `ExtSEIRSNetworkModel`](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#specifying-parameters) by providing a list of values that gives the *N* values to assign to each individual. The population may be either homogeneous or heterogeneous for a given parameter at the user's discretion. \n", - "\n", - "**Here we generate distributions of values for each parameter, thus specifying a realistically heterogeneous population.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected latent periods (time in Exposed state) and presymptomatic periods (time in Pre-symptomatic infectious state). The `sigma` and `lamda` rates are calculated as the inverse of the expected exposed and pre-symptomatic periods assigned to each individual, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "latent period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", - "\n", - "pre-symptomatic period: mean = 2.94, std = 1.72, 95% CI = (0.64, 7.12)\n", - "\n", - "total incubation period: mean = 5.14, std = 2.03, 95% CI = (2.17, 10.02)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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WVlccsklQUxff/013//+9/nNb37D+vXrWbJkyRnlOwBWrlzJr371KzZu3MiOHTtYsGABBw4cKPHzLPjchw4dGiw7evQoI0eOZN68ecEcE08//TRHjx5l1KhR/PnPf2b58uX8/e9/L/0vQRGUFESqqdatW9O7d28A7rjjDjIzM4P3vv/97wPw/vvvs3nzZnr37k1qaiqzZs0KCuYV1r17d5577jkmTpzIxo0bqV+/PhdeeCFXX301r732Glu3buX48eOkpKQA0K5dO1JSUqhRowaXX34511xzDWZGSkrKKWW3Bw0aRN26dWnSpAn9+/cPziIKy8zM5M477wROLZsN0L9/f+rXr0/Tpk1p2LAhN910E8Ap7WzatIkrr7ySlJQUZs+ezYcfflji5/bRRx/RokULunfvDkCDBg2oWfPMnvj09HS+9a1vkZCQwLBhw8jMzDzr51nwuZ/eXrt27bj00ksBGDFiBMuWLWPr1q20a9eO9u3bY2bccccdJcYdK11TEKmmiipbXaCgRLW7c9111zF37txT1v3ggw+CEtqTJk0KJtx5/fXXufPOOxk3bhx33XUX9957L0888QQdOnQIzhKAU0pt16hRI3hdo0YNTpw4EVOMBUqq3xZLOyNHjmThwoV06dKFjIyMs95p7e4xleMurix4UZ9ngaJKg5d3WXCdKYhUU7t372bFiki9yblz59KnT58z1unZsyd/+9vf2L59OwBfffUVH3/8MT169CArK4usrCwGDhzIrl27aNasGaNGjeKee+5h7dq1APTo0YNPPvmEOXPmBBPqlMarr77K0aNHyc3NZenSpXTv3v2MctzFlc2O1aFDh2jRogXHjx8P9gPFl/3u0KEDe/bsYdWqVcH2hRNZgZUrV7Jz505OnjzJvHnz6NOnT7GfZ0k6dOhAdnZ2sM0f//hHrrrqKjp06MDOnTvZsWMHQLGJprR0piBSEVyQGBkxVJb7O4uOHTsya9Ys7rvvPtq3b8/9999/xjpNmzYlIyODYcOGBRc3H3/88aAro8DSpUuZMmUKtWrVIjExMeivB7j99tvJysrioosuKvVhpKen873vfY/du3fzs5/9jJYtW9K0aVNq1qxJly5dGDlyZLFls2P1n//5n/To0YO2bduSkpISJIKhQ4cyatQofvvb3wYXfAEuuOAC5s2bx4MPPkheXh5169ZlyZIlJCae+pn36tWL8ePHs3HjxuCic40aNWL6PAurU6cOzz33HLfddhsnTpyge/fujBkzhtq1azNjxgy+973v0aRJE/r06cOmTZtK8/EWqdxKZ4dBpbOjVDq70ol36ezs7Oxg0vuwDRgwgIcffphrrimy5FmxJk6cSGJiIv/6r/8aUmThWbp0KVOnTj3rPBDlocKUzhaR6u3gwYNceuml1K1bt9QJQeJH3Uci1VBSUlLoZwnf+MY3ztpfXpKJEyeWXTDlrF+/fvTr1y/eYZwTnSmIiEhASUFERAJKCiIiElBSEBGRgJKCSAWQm5vLrl27yuyRm1ty6eyDBw+eUuuoOLGWqc7OziY5OfmM5Xv27GHIkCFn3b40imurJBkZGezZsyd4fe+9955SFjuevvvd73Lw4MGY1584cSJTp04NLR6NPhKpAA4fPnxKIbjzNWHCBBo3Lr50dkFSGDt2bIn7Od8y1S1btjzlxq94ycjIIDk5mZYtWwLwhz/8Ic4RRcpXuDtvvPFGvEM5hc4URKqh8ePHs2PHDlJTUxk3bhzuzrhx40hOTiYlJYV58+YF6xUuU52dnc2VV15Jt27d6NatG++9916J7RT+qz4jI4NbbrmFG264gfbt2/Nv//ZvwXpvvvkm3bp1o0uXLsE9Daf/RZycnBwUsTtx4kSRZb8nTZpE9+7dSU5OZvTo0bg7L730EqtXr2b48OGkpqaSl5dHv379KLjxde7cuaSkpJCcnMwjjzwStJeYmMhjjz1Gly5d6NmzJ5999tkZx1dceW+AKVOm0L17dzp37szPf/7z4PPo2LEjY8eOpVu3bnzyySckJSVx4MABAKZNm0ZycjLJycn8+te/DvY1efJkLrvsMq699lo++uijEj/z86WkIFINPfnkk1xyySVkZWUxZcoUFixYEJS9XrJkCePGjWPv3r1nlKlu1qwZb731FmvXrmXevHk89NBDpWo3KysrKAE9b948PvnkE/bv38+oUaN4+eWXWb9+PS+++OJZ91Nc2e8HHniAVatWsWnTJvLy8njttdcYMmQIaWlpzJ49m6ysrFPKXO/Zs4dHHnmEd955h6ysLFatWsXChQsBOHLkCD179mT9+vX07dv3lC/8wooq77148WK2bdvGypUrycrKYs2aNSxbtiyI/a677mLdunW0bfvPSgRr1qzhueee44MPPuD999/nmWeeYd26daxZs4YXXniBdevWsWDBgqDmUliUFESEzMxMhg0bRkJCAs2bN+eqq64q8svn+PHjjBo1ipSUFG677bZS98tfc801NGzYkDp16tCpUyd27drF+++/T9++fWnXrh0AjRo1Out+iiv7/e6779KjRw9SUlJ45513zloGe9WqVfTr1y+opzR8+PDgy/uCCy4Iprf89re/fUpJ78KKKu+9ePFiFi9eTNeuXenWrRtbt25l27ZtALRt25aePXuesZ/MzEwGDx7MhRdeSGJiIrfccgvLly9n+fLlDB48mHr16tGgQQMGDhx41s/nfOiagoiUWJ65sOnTp9O8eXPWr1/PyZMnqVOnTqnaKVyoLiEhgRMnThRbirpmzZrBbGVAMHEOFF2W+ujRo4wdO5bVq1fTunVrJk6ceMo2RSnpuGvVqhW0UxBrUYorkf3oo48G5cULZGdnF1ke+2yxhFEiuzg6U6gqvt4V/iO/6k4GX90UVX563rx55Ofns3//fpYtW0Z6evoZ633xxRe0aNGCGjVq8Mc//pH8/PzzjqVXr1789a9/ZefOnQDBNJlJSUlBCe61a9cG70PRZb8LEkCTJk04fPjwKRe4iyuD3aNHD/76179y4MAB8vPzmTt3LldddVWp4i+qvPf111/PzJkzg6k2P/30U/bt21fifvr27cvChQv56quvOHLkCK+88gpXXnklffv25ZVXXiEvL49Dhw7x5z//uVTxlVZoZwpm1hp4HvgmcBKY4e6/MbOJwChgf3TVCe7+RnSbR4F7gHzgIXf/S1jxVSmeB59PD7+dRhMg4fwng5czJSYmMmFC2ZXOPr2M8+kaN25M7969SU5O5sYbb+SXv/wlK1asoEuXLpgZv/zlL/nmN79J48aNzyhTfeutt/Liiy/Sv3//Yv/qLY2mTZsyY8YMbrnlFk6ePBlct7j11lt5/vnnSU1NpXv37qeUly6q7He9evWCrq2kpKRgZjSITKQzZswY6tatGyQTgBYtWvCLX/yC/v374+5897vfZdCgQaWKv6jy3i1btmTLli306tULiPx7/OlPfyIhIaHY/XTr1o2RI0eSnp4ORIbNdu3aFYjMyJaamkrbtm258sorSxVfaYVWOtvMWgAt3H2tmdUH1gA3A7cDh9196mnrdwLmAulAS2AJcKm7F/uniEpnR130cPklBZXoLhPxLp0tZaMy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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "latentPeriod_mean, latentPeriod_coeffvar = 3.0, 0.6\n", - "SIGMA = 1 / gamma_dist(latentPeriod_mean, latentPeriod_coeffvar, N)\n", - "\n", - "presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar = 2.2, 0.5\n", - "LAMDA = 1 / gamma_dist(presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar, N)\n", - "\n", - "dist_info([1/LAMDA, 1/SIGMA, 1/LAMDA+1/SIGMA], [\"latent period\", \"pre-symptomatic period\", \"total incubation period\"], plot=True, colors=['gold', 'darkorange', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected (a)symptomatic periods (time in symptomatic or asymptomatic state). The `gamma` rates are calculated as the inverse of the expected (a)symptomatic periods assigned to each individual. \n", - "\n", - "The expected total infectious period for each individual is the sum of their expected pre-symptomatic and (a)symptomatic periods." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pre-symptomatic period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", - "\n", - "(a)symptomatic period: mean = 4.01, std = 1.54, 95% CI = (1.64, 7.36)\n", - "\n", - "total infectious period: mean = 6.20, std = 1.87, 95% CI = (3.09, 10.45)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "symptomaticPeriod_mean, symptomaticPeriod_coeffvar = 4.0, 0.4\n", - "GAMMA = 1 / gamma_dist(symptomaticPeriod_mean, symptomaticPeriod_coeffvar, N)\n", - "\n", - "infectiousPeriod = 1/LAMDA + 1/GAMMA\n", - "\n", - "dist_info([1/LAMDA, 1/GAMMA, 1/LAMDA+1/GAMMA], [\"pre-symptomatic period\", \"(a)symptomatic period\", \"total infectious period\"], plot=True, colors=['darkorange', 'crimson', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected onset-to-hospitalization periods (time in symptomatic state before entering hospitalized state for those with severe cases) and hospitalization-to-discharge periods (time in hospitalized state for those with non-fatal cases). The `eta` and `gamma_H` rates are calculated as the inverse of the expected onset-to-hospitalization periods and hospitalization-to-discharge periods assigned to each individual, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", - "\n", - "hospitalization-to-discharge period: mean = 11.38, std = 5.29, 95% CI = (3.49, 23.54)\n", - "\n", - "onset-to-discharge period: mean = 22.51, std = 7.16, 95% CI = (10.62, 39.43)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3wU5bnA8d+TEAzITQE9QYTIOVzEEAOGqxQIVFChXBRQDigXIdADUmiLUKyCqICtRyPWUwpYpGopiHIR23ojiFyEgERALFo0UCRyCUIJIeSy7/ljN+smOxs2Ibub3Xm+n08+yc7szDwZwpPJM+88rxhjUEopZR9RoQ5AKaVUcGniV0opm9HEr5RSNqOJXymlbEYTv1JK2UyNUAfgj0aNGpn4+PhQh6GUUmFlz549p40xjcsuD4vEHx8fz+7du0MdhlJKhRUROWK1XEs9SillM5r4lVLKZjTxK6WUzYRFjV9FtsLCQo4dO0Z+fn6oQ1EqLMXGxtK0aVNiYmL8er8mfhVyx44do27dusTHxyMioQ5HqbBijCEnJ4djx45x0003+bWNlnpUyOXn59OwYUNN+kpVgojQsGHDCv3FrIlfVQua9JWqvIr+/9HEr5RSNqOJX1U7xd+fo/Bf31XZR/H350L6/WRmZvLXv/7V5/q0tDTy8vIqtM/NmzczYMCAKw3Np927dzN16lT3sbZv337ZbV555RWmTJkCwOLFi/nTn/5U4eOWPVZl9xMIjz/+OB988IHf7w/0v9GV0Ju71Vzx9+dw5F70Wi4xNTCFRZbbRNWpRfQ19QMdWsA4ci9yNu3VKttfg2kPhPR8ZGZmsnv3bu6++27L9WlpaYwaNYratWsHOTLfkpOTSU5OBpwJrE6dOnTr1s3v7SdNmlSp45Y9VmX3U9WKi4uZN29eqMOoMnrFX82VJMGyH8XnL1guP5v2quUvClW+5557joSEBBISEkhLSwMgKyuLm2++mQkTJnDLLbfQt29fLl50nttFixbRtm1bEhMTuf/++wG4cOEC48aNo2PHjrRv357169dTUFDA448/zqpVq0hKSmLVqlWljrto0SKOHz9OSkoKKSkpAKxcuZJ27dqRkJDAzJkzfcacm5vL0KFDadOmDSNHjqRkNr0PP/yQ9u3b065dO8aNG8elS5cAmDVrljvmX/7ylwCMGTOGSZMm8aMf/YhWrVqxceNG4Ier1aysLBYvXszzzz9PUlISH3/8MW+//TadO3emffv2/PjHP+bEiRNesc2dO5dnn32W48ePk5SU5P6Ijo7myJEjlvuwOlbJfsD5C7RLly4kJiYyZMgQvv/+ewB69erFzJkz6dSpE61ateLjjz/2imfz5s306NGDIUOG0LZtWyZNmoTD4QDgvffeo2vXrnTo0IFhw4aRm5sLOFvFzJs3j+7du/PGG28wZswY1qxZU+45/vvf/06bNm3o3r07b731ls9/u1DTxK9sb8+ePSxfvpydO3fyySefsHTpUvbu3QvAV199xeTJk/n8889p0KABb775JgALFy5k79697Nu3j8WLFwPw9NNP07t3bzIyMkhPT2fGjBkUFhYyb9487rvvPjIzM7nvvvtKHXvq1Kk0adKE9PR00tPTOX78ODNnzmTTpk1kZmaSkZHBunXrLOPeu3cvaWlpHDx4kK+//ppt27aRn5/PmDFjWLVqFfv376eoqIjf//73nDlzhrVr1/L555+zb98+fv3rX7v3k5WVxUcffcQ777zDpEmTSo0OiY+PZ9KkSUyfPp3MzEx+9KMf0b17dz755BP27t3L/fffz29+8xuf57ZJkyZkZmaSmZnJhAkTuPfee2nevLnlPqyO5enBBx/kmWeeYd++fbRr144nnnjCva6oqIhdu3aRlpZWarmnXbt28b//+7/s37+fw4cP89Zbb3H69GmeeuopPvjgAz799FOSk5N57rnn3NvExsaydetW9y93wOc5zs/PZ8KECbz99tt8/PHHfPfddz7PS6hpqcdmfJWOIPxLRJW1detWhgwZwtVXXw3APffcw8cff8zAgQO56aabSEpKAuC2224jKysLgMTEREaOHMngwYMZPHgw4Lxy3LBhg/sKNT8/n6NHj1YoloyMDHr16kXjxs6GiiNHjmTLli3uY3jq1KkTTZs2BSApKYmsrCzq1q3LTTfdRKtWrQAYPXo0L730ElOmTCE2Npbx48fTv3//UrXn4cOHExUVRcuWLWnRogX/+Mc/yo3x2LFj3HfffWRnZ1NQUODX2PFt27axbNky99V4Rfdx7tw5zp49S8+ePd3f17Bhw9zr77nnHqD0v1FZnTp1okWLFgCMGDGCrVu3Ehsby8GDB7n99tsBKCgooGvXru5tyv6iBjh06JDl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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar = 11.0, 0.45\n", - "ETA = 1 / gamma_dist(onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar, N)\n", - "\n", - "hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar = 11.0, 0.45\n", - "GAMMA_H = 1 / gamma_dist(hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar, N)\n", - "\n", - "dist_info([1/ETA, 1/GAMMA_H, 1/ETA+1/GAMMA_H], [\"onset-to-hospitalization period\", \"hospitalization-to-discharge period\", \"onset-to-discharge period\"], plot=True, colors=['crimson', 'violet', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of hospitalization-to-death periods (time in hospitalized state for those with fatal cases). The `mu_H` rates are calculated as the inverse of the expected hospitalization-to-death periods." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", - "\n", - "hospitalization-to-death period: mean = 6.87, std = 3.10, 95% CI = (2.01, 13.61)\n", - "\n", - "onset-to-death period: mean = 17.99, std = 6.08, 95% CI = (8.34, 31.59)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAD4CAYAAAAD6PrjAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3hU1b3/8ffiIkGDl4K2INWE/ggXAbmEqxES0aJCQUAQDlAiCocqIrQq1IpSREsVMWJ9SkEK1GMRAbmIHi8okZtCQCIIFBUJyuGioKAJhGSS9ftjJttc9oRJyMwkmc/refIks9fM3t9ZhHxnr732dxlrLSIiIgA1wh2AiIhUHkoKIiLiUFIQERGHkoKIiDiUFERExFEr3AGcjwYNGtiYmJhwhyEiUqVs3779uLX2cre2Kp0UYmJi2LZtW7jDEBGpUowxB/21afhIREQcSgoiIuJQUhAREUeVvqYgUha5ubkcOnSI7OzscIciEhJRUVE0btyY2rVrB/waJQWJGIcOHaJevXrExMRgjAl3OCJBZa3lxIkTHDp0iNjY2IBfp+EjiRjZ2dnUr19fCUEigjGG+vXrl/nMWElBIooSgkSS8vy+KymIiIhDSUEiVt73p8j9+miFfeV9fyqs7yc9PZ0333zTb3tKSgqnT58u0z5TU1Pp06fP+Ybm17Zt2xg/frxzrM2bN5/zNQsXLmTcuHEAzJkzh3/9619lPm7xY5V3P8Hw6KOPsnbt2oCfX9H/RrrQHGZnz57F4/G4ttWqVYs6deqEOKLIkZ95hpMpL1XY/i6dMIKal11SYfsrq/T0dLZt28att97q2p6SksLw4cO58MILQxyZf/Hx8cTHxwPeP27R0dF069Yt4NePHTu2XMctfqzy7qei5eXlMW3atLDGoDOFMPN4POzdu9f1y1+ykKpr1qxZtGrVilatWpGSkgJARkYGLVq0YPTo0VxzzTX8+te/5syZMwDMnj2bli1b0qZNG4YMGQJAVlYWo0aNomPHjrRr145Vq1aRk5PDo48+ypIlS2jbti1LliwpctzZs2dz+PBhkpKSSEpKAmDx4sW0bt2aVq1aMWnSJL8xZ2Zmcvvtt9O8eXOGDRtGwWqN7733Hu3ataN169aMGjWKs2fPAjB58mQn5gceeACA5ORkxo4dy/XXX09cXBxr1qwBfvqUm5GRwZw5c3j22Wdp27YtGzZs4PXXX6dz5860a9eOG2+8kWPHjpWIberUqcycOZPDhw/Ttm1b56tmzZocPHjQdR9uxyrYD3iTa5cuXWjTpg39+/fn+++/ByAxMZFJkybRqVMn4uLi2LBhQ4l4UlNT6d69O/3796dly5aMHTuW/Px8AN555x26du1K+/btGTRoEJmZmYC3XM+0adNISEhg6dKlJCcns2zZslL7+K233qJ58+YkJCTw2muv+f23Kw8lhRA5e/YsWVlZJb4KfmGk+tu+fTsLFixgy5YtfPTRR8ybN48dO3YA8Pnnn3Pvvfeye/duLr30UpYvXw7AjBkz2LFjBzt37mTOnDkAPPHEE9xwww2kpaWxbt06HnzwQXJzc5k2bRp33HEH6enp3HHHHUWOPX78eBo1asS6detYt24dhw8fZtKkSbz//vukp6eTlpbGypUrXePesWMHKSkp7Nmzhy+//JJNmzaRnZ1NcnIyS5YsYdeuXXg8Hv7+97/z3XffsWLFCnbv3s3OnTt55JFHnP1kZGTwwQcf8MYbbzB27Ngis2JiYmIYO3YsEydOJD09neuvv56EhAQ++ugjduzYwZAhQ3jqqaf89m2jRo1IT08nPT2d0aNHM3DgQK6++mrXfbgdq7Df/va3/PWvf2Xnzp20bt2aP//5z06bx+Nh69atpKSkFNle2NatW3nmmWfYtWsX+/fv57XXXuP48eNMnz6dtWvX8vHHHxMfH8+sWbOc10RFRbFx40Yn8QN++zg7O5vRo0fz+uuvs2HDBo4ePeq3X8pDw0chUnBGUFxcXFwYopFw2LhxI/379+eiiy4CYMCAAWzYsIG+ffsSGxtL27ZtAejQoQMZGRkAtGnThmHDhnHbbbdx2223Ad5PnKtXr3Y+2WZnZ/PVV1+VKZa0tDQSExO5/HJvocxhw4axfv165xiFderUicaNGwPQtm1bMjIyqFevHrGxsc7v78iRI3nhhRcYN24cUVFR3H333fTu3bvIWPfgwYOpUaMGTZs2pUmTJvznP/8pNcZDhw5xxx13cOTIEXJycgKaa79p0yZefPFF51N8Wfdx6tQpTp48SY8ePZz3NWjQIKd9wIABQNF/o+I6depEkyZNABg6dCgbN24kKiqKPXv2cN111wGQk5ND165dndcUT+IA+/btc+3jxMREYmNjadq0KQDDhw9n7ty55+ybQOlMQSRECoZd3BS+dlSzZk1n6PCNN97g3nvvZfv27XTo0AGPx4O1luXLlzufjL/66itatGhRYp+9evWibdu23H333QHHsmXLFmcIZvXq1X5j8/f6WrVqsXXrVgYOHMjKlSu5+eabnbbi0yPPNV3yvvvuY9y4cezatYt//OMf55xvf+TIEe666y6WLFlCdHR0ufZxLgV9UfjfqDi392mt5aabbnL+zfbs2cP8+fOd5xR8UCistN+XYE6tVlIQCZHu3buzcuVKTp8+TVZWFitWrCgxdFFYfn4+X3/9NUlJSTz11FOcPHmSzMxMevXqxfPPP+/80SgYgqpXrx4//vij8/q3336b9PR0XnzxxRLtnTt35oMPPuD48ePk5eWxePFievToQefOnZ0/XH379vUbW/PmzcnIyOCLL74A4KWXXqJHjx5kZmZy6tQpbr31VlJSUkhPT3des3TpUvLz89m/fz9ffvklzZo1K7LP4vGfOnWKK6+8EoBFixaV2re5ubkMHjyYv/71r0XOvv3to/ixClxyySVcdtllzplGwfsqi61bt3LgwAHy8/NZsmQJCQkJdOnShU2bNjn9dfr0aT777LNS9+Ovj5s3b86BAwfYv38/4L02VJGCNnxkjPkn0Af4xlrbyrftZ8ASIAbIAAZba7/3tf0RuAvIA8Zba98OVmwiADWi63LphBEVur/StG/fnuTkZDp16gTA3XffTbt27fwOQ+Tl5TF8+HBOnTqFtZaJEydy6aWXMmXKFCZMmECbNm2w1hITE8OaNWtISkpixowZtG3blj/+8Y8lhiTGjBnDLbfcQsOGDVm3bh1/+ctfSEpKwlrLrbfeSr9+/QJ+r1FRUSxYsIBBgwbh8Xjo2LEjY8eO5bvvvqNfv35kZ2djreXZZ591XtOsWTN69OjBsWPHmDNnDlFRUUX2+Zvf/Ibbb7+dVatW8fzzzzN16lQGDRrElVdeSZcuXThw4IDfeDZv3kxaWhqPPfYYjz32GABvvvmm330UP1ZhixYtYuzYsZw+fZomTZqwYMGCgPsFoGvXrkyePJldu3Y5F51r1KjBwoULGTp0qHOxePr06aUOH/vr4zp16jB37lx69+5NgwYNSEhI4NNPPy1TjKUxpZ2inNeOjekOZAL/KpQUngK+s9bOMMZMBi6z1k4yxrQEFgOdgEbAWiDOWptX2jHi4+NtVVlkJysry+81BX+fGFq0aOF6Winls3fvXtdhFgm+5ORk+vTpw+233x7uUIIqNTWVmTNnOrOrKgO333tjzHZrbbzb84N2pmCtXW+MiSm2uR+Q6Pt5EZAKTPJtf8VaexY4YIz5Am+C+DBY8VUVWVlZrtt1D4OIBEOoZx/93Fp7BMBae8QYc4Vv+5XAR4Wed8i3LaLl5eWVehahpCBVxcKFC8MdQkgkJiaSmJgY7jDOS2W50Ox2Kd11XMsYM8YYs80Ys+3bb78NclgiIpEl1EnhmDGmIYDv+ze+7YeAXxZ6XmPgsNsOrLVzrbXx1tr4gjnWIiJSMUKdFFYDI30/jwRWFdo+xBhTxxgTCzQFtoY4NhGRiBfMKamL8V5UbmCMOQQ8BswAXjXG3AV8BQwCsNbuNsa8CuwBPMC955p5JCIiFS9oZwrW2qHW2obW2trW2sbW2vnW2hPW2p7W2qa+798Vev4T1tpfWWubWWv/N1hxiRTwV4+qvF8F88/9ycjIoFWrVkF7P4cPH3amfJ6rjHaBwmWXV69ezYwZM8p83OLHKu9+3KxcuZI9e/ac1z4Kl9ouq+LvrXDhvGAqTx8W3MV9vlT7SCKWv3pU5RXuGWGNGjVyqmueq4y2m759+5Z6F7M/xY9V3v24WblyJX369KFly5YVsr+yKk8/ni+Px1OhfVhWlWX2kUhEyMvLcy2R7a9cs1vp7KlTpzJixAhuuOEGmjZtyrx584CfzkTcymhv3bqVbt260a5dO7p168a+fftKxFb4E3XhMtR169blgw8+cN2H27EK7+fgwYP07NmTNm3a0LNnT6dwX3JyMuPHj6dbt240adLESWaFbd68mdWrV/Pggw/Stm1b9u/f77efiluwYAFxcXH06NGDTZs2Odu//fZbBg4cSMeOHenYsaPTFuh7A9izZw+JiYk0adKE2bNnux4/OjqaP/zhD7Rv356ePXtSMFNy//793HzzzXTo0IHrr7/eKQqYnJzM73//e5KSkpg0aVJAfXjgwAG6du1Kx44dmTJlimsc5aGkIBJC/kpk+yvX7FY6G2Dnzp288cYbfPjhh0ybNo3Dh3+arHfBBReUKKPdvHlz1q9fz44dO5g2bRoPP/xwqXEW1D96/PHHiY+Pp1u3bq77cDtWYePGjeO3v/0tO3fuZNiwYc4qa+AtYLdx40bWrFnD5MmTS8TQrVs3+vbty9NPP016ejq/+tWvSi1rXXi/jz32GJs2beLdd98tMvx0//33M3HiRNLS0li+fLlTLLAs7+0///kPb7/9Nlu3buXPf/4zubm5JWLIysqiffv2fPzxx/To0cOJc8yYMTz//PNs376dmTNncs899ziv+eyzz1i7di3PPPNMQH14//3387vf/Y60tDR+8YtflPrvWRYaPhIJIbcS2aWVa3YrnQ3Qr18/6tatS926dUlKSmLr1q3Oft2cOnWKkSNH8vnnn2OMcf1DVtznn3/Ogw8+yPvvv0/t2rU5evRomffx4YcfOovAjBgxgoceeshpu+2226hRowYtW7Z0XUDH7T2UVta6wJYtW4qUBb/jjjucm0DXrl1bJEn88MMP/Pjjj2Xqn969e1OnTh3q1KnDFVdcwbFjx5zS4gVq1KjhJJHhw4czYMAAMjMz2bx5c5GYC1+HGjRoEDVr1ixxPH99uGnTJudDxYgRI0pdKKkslBSqMJXAqHqKl6EuGD7y54033mD9+vWsXr2axx9/nN27dwNlL0M9ZcoUkpKSWLFiBRkZGee86zYrK4vBgwczb948GjVqVK59uCkcZ+G+KKjB9qc//Yk33ngDoEiF1dLk5eXRoUMHwHs9o3379n77Iz8/nw8//JC6dYsWL7zvvvsCfm/+ypyXxhhDfn4+l156qd/3FWids8LvLRgltDV8VEXl5eVpGc9qwl+5Zn+lswFWrVpFdnY2J06cIDU1lY4dOxbZZ2llqAMpOXHnnXdy5513Fint7W8f/spQg3cI6JVXXgHg5ZdfJiEhodTjPvHEE87QVfF9++unmjVrOq+ZNm0anTt3JjU1lRMnTpCbm8vSpUud/f/617/mb3/7m/O44DjleW+lyc/Pd66T/Pvf/yYhIYGLL76Y2NhYJx5rLZ988sk59+WvD6+77roi2yuKzhQkYtWqVatCq6bWqlX+/05u5Zr9lc4G7+pevXv35quvvmLKlCk0atSoSAnu4mW0H3roIUaOHMmsWbO44YYbSo3l4MGDLFu2jM8++4x//vOfALz44ot+91H8WIXNnj2bUaNG8fTTT3P55ZeXuQz1kCFDGD16NLNnz2bZsmUBlbVu2LAhU6dOpWvXrjRs2JD27duTl5fnxHPvvffSpk0bPB4P3bt3Z86cOeV6b6W56KKL2L17Nx06dOCSSy5xLlK//PLL/O53v2P69Onk5uYyZMgQrr322lL35a8Pn3vuOf7rv/6L5557joEDBwYc27kErXR2KFT30tnlbVPJbXfVpXT21KlTiY6O5oEHHgh3KOJHdHS0c1YXbmUtna3hIxERcWj4SKSKmTp1arhDkHOoLGcJ5aEzBRERcSgpiIiIQ0lBREQcSgoiIuLQhWaJWCdOnKjQC4LR0dHUr1+/wvZXVunp6Rw+fNhvRc+UlBTGjBnDhRdeWO5jJCcn06dPH6dEd1msXLmSuLg4p+JpYmIiM2fOJD7edWZkhXn00Ufp3r07N954Y0DPT01NZebMmaxZsyaocVVWSgoSsTIzM3nyyScrbH8PP/xw2JNCaWWeU1JSGD58+HklhfMRjjLYeXl5TJs2LWTHqw40fCQSQrNmzaJVq1a0atWKlJQUwFvyukWLFq4ltd1KZ2dlZTFq1Cg6duxIu3btWLVqld8yzwVmz57N4cOHSUpKIikpCYDFixfTunVrWrVq5beYmrWWcePG0bJlS3r37s0333zjtG3fvp0ePXrQoUMHevXqxZEjRwCYN28eHTt25Nprr2XgwIGcPn3atQw2wNKlS+nUqRNxcXFO+YrCUlNT6d69O/3796dly5aMHTuW/Px8AN555x26du1K+/btGTRokHPWFxMTw7Rp00hISGDp0qUkJyc7JSfee+892rVrR+vWrRk1apRTkO6tt96iefPmJCQkOMXnIpWSgkiIbN++nQULFrBlyxY++ugj5s2bx44dOwD/JbXdSmc/8cQT3HDDDaSlpbFu3ToefPBBcnNzSy1hPX78eBo1asS6detYt24dhw8fZtKkSbz//vukp6eTlpbGypUrS8S8YsUK9u3bx65du5g3bx6bN28GIDc3l/vuu49ly5axfft2Ro0axZ/+9CcABgwYQFpaGp988gktWrRg/vz5rmWwwbugzNatW0lJSXEtgw3etQ6eeeYZdu3axf79+3nttdc4fvw406dPZ+3atXz88cfEx8cza9Ys5zVRUVFs3LjRSaQA2dnZJCcns2TJEnbt2oXH4+Hvf/872dnZjB49mtdff50NGzZw9OjRcv37VhcaPhIJkY0bN9K/f3+nBMmAAQPYsGEDffv2dS2pDe6ls9955x1Wr17tLAuZnZ3tLLwSqLS0tCLlpYcNG8b69euLlOcGWL9+PUOHDqVmzZo0atTIqQu0b98+Pv30U2666SbAO0zTsGFDAD799FMeeeQRp4Bfr169/MYxYMCAEu+5uE6dOtGkSRMAhg4dysaNG4mKimLPnj1cd911AOTk5NC1a1fnNcWTYkHMsbGxxMXFAd7S2y+88AKJiYnExsbStGlTwFvqeu7cuaX0XvWmpCASIqXVGfNXUtutdLa1luXLl9OsWbMi+9iyZUuRx7169eLYsWPEx8fz4osvBhTLli1b+O///m8AZyzerTyztZZrrrmGDz/8sERbcnIyK1eu5Nprr2XhwoWkpqae832XVoLarUy4tZabbrqJxYsXu77GrfZXaf0fjBLUVZWGj0RCpHv37qxcuZLTp0+TlZXFihUripSmLs5f6exevXrx/PPPO3/kCoagipd5fvvtt0lPT3cSQuH2zp0788EHH3D8+HHy8vJYvHgxPXr0oHPnzk4Z6r59+9K9e3deeeUV8vLyOHLkCOvWrQOgWbNmfPvtt05SyM3NddZ6+PHHH2nYsCG5ublFSjqXtwz11q1bOXDgAPn5+SxZsoSEhAS6dOnCpk2b+OKLLwA4ffq03wKRBZo3b05GRobzmoLS282bN+fAgQPOdQ5/iSZS6ExBIlZ0dPQ5l6Us6/5K0759e5KTk+nUqRMAd999N+3atfM7bOKvdPaUKVOYMGECbdq0wVpLTEwMa9asKVHmufgQypgxY7jlllto2LAh69at4y9/+QtJSUlYa7n11lvp169fiRj69+/P+++/T+vWrZ01j8G75OeyZcsYP348p06dwuPxMGHCBK655hoef/xxOnfuzNVXX03r1q2dRFC8DHagunbtyuTJk9m1a5dz0blGjRosXLiQoUOHOheLp0+f7gwNuYmKimLBggUMGjQIj8dDx44dGTt2LHXq1GHu3Ln07t2bBg0akJCQwKeffhpwfNWNSmeHiEpnh191KZ0dSSL9noGKoNLZIiJSbho+EpFKKzExsVxrQUv56UxBIkpVHi4VKavy/L4rKUjEiIqK4sSJE0oMEhGstZw4cYKoqKgyvU7DRxIxGjduzKFDh/j222/DHYpISERFRdG4ceMyvUZJQSJG7dq1iY2NDXcYIpWaho9ERMShpCAiIo6wJAVjzERjzG5jzKfGmMXGmChjzM+MMe8aYz73fb8sHLGJiESykCcFY8yVwHgg3lrbCqgJDAEmA+9Za5sC7/kei4hICIVr+KgWUNcYUwu4EDgM9AMW+doXAbf5ea2IiARJyJOCtfb/gJnAV8AR4JS19h3g59baI77nHAGucHu9MWaMMWabMWabphaKiFSscAwfXYb3rCAWaARcZIwZHujrrbVzrbXx1tr4ggVCRESkYoRj+OhG4IC19ltrbS7wGtANOGaMaQjg+/5NKfsQEZEgCEdS+AroYoy50HiXO+oJ7AVWAyN9zxkJrApDbCIiES3kdzRba7cYY5YBHwMeYAcwF4gGXjXG3IU3cQwKdWwiIpEuLGUurLWPAY8V23wW71mDiIiEie5oFhERh5KCiIg4lBRERMShpCAiIg4lBRERcSgpiIiIQyuvVVG1z+QQG1XPta3WqSxyv/uxxPYa0XWpedklwQ5NRKowJYWq6nQ2x56a79oU/cg9nPzH0hLbL50wQklBREqlpCAA5H1/ivzMM65tOsMQiRxKCgJAfuYZTqa85NqmMwyRyKGkUE3l5uaW2Jafnx+GSESkKlFSqKZOnjxZYtvPrA1DJCJSlSgpVKCzZ8/i8Xhc2/QpXUSqAiWFCuTxeNi7d69rW1xcXIijEREpO928JiIiDiUFERFxKCmIiIijTEnBGFPDGHNxsIIREZHwOmdSMMb82xhzsTHmImAPsM8Y82DwQxMRkVAL5EyhpbX2B+A24E3gKmBEUKMSEZGwCGRKam1jTG28SeFv1tpcY4zugqqCTA1D7tdHXdusyx3QIhJ5AkkK/wAygE+A9caYq4EfghmUBEl2jmv1VICLxw4OcTAiUhmdMylYa2cDswttOmiMSQpeSCIiEi6BXGj+uTFmvjHmf32PWwIjgx6ZiIiEXCAXmhcCbwONfI8/AyYEKyAREQmfQJJCA2vtq0A+gLXWA+QFNSoREQmLQJJCljGmPmABjDFdgFNBjUpERMIikNlHvwdWA78yxmwCLgduD2pUIiISFoHMPvrYGNMDaAYYYJ+1VpPaRUSqIb9JwRgzwE9TnDEGa+1rQYpJRETCpLQzhd/4vl8BdAPe9z1OAlKBcicFY8ylwItAK7zXKkYB+4AlQAzem+UGW2u/L+8xJLxOnDhBZmama1t0dDT169cPcUQiEgi/ScFaeyeAMWYN3vpHR3yPGwIvnOdxnwPestbeboy5ALgQeBh4z1o7wxgzGZgMTDrP40iYZGZm8uSTT7q2Pfzww0oKIpVUILOPYgoSgs8xoNxrS/pKb3cH5gNYa3OstSeBfsAi39MW4a21JCIiIRTI7KNUY8zbwGK8Qz1DgHXnccwmwLfAAmPMtcB24H7g5wXJx1p7xBhzhduLjTFjgDEAV1111XmEISIixZ3zTMFaOw6YA1wLtAXmWmvvO49j1gLaA3+31rYDsvAOFQXEWjvXWhtvrY2//PLLzyMMEREpLpAzBYDNgAfvmcLW8zzmIeCQtXaL7/EyvEnhmDGmoe8soSHwzXkeR0REyiiQgniD8SaC24HBwBZjTLlvXrPWHgW+NsY0823qiXdFt9X8VGhvJLCqvMcQEZHyCeRM4U9AR2vtNwDGmMuBtXg/4ZfXfcDLvplHXwJ34k1Qrxpj7gK+Agadx/6lGtI0V5HgCyQp1ChICD4nCGzWkl/W2nQg3qWp5/nsV6o3TXMVCb5AksJbhWYfAdyBd61mCbLaZ3KIjarn2lYjPz/E0bjL+/4U+ZlnSmy/xAR6uUpEKpNAah89aIwZCFyHt/bRXGvtiqBHJnA6m2NPzXdtin7knhAH4y4/8wwnU14qsb3Of6tmokhVFNDHOWvtcmB5kGOREMjN9VPL0IY2DhGpnM6ZFHyF8f6KtwaS8X1Za+3FQY5NguDkyZOu2+srK4gIgZ0pPAX8xlq7N9jBiJQ2wygnJyfE0YhEnkCSwjElBAmV0mYYTZw4McTRiESeQJLCNmPMEmAlcLZgo9ZTiCy5Xx913W79XaMQkSopkKRwMXAa+HWhbZbzWE9Bqpb87LP8MOdV17aLxw4OcTQiEkyBTEm9MxSBiIhI+J3XnckiIlK9KCmIiIhDSUFERByB3Lx2KfBbIKbw862144MXllR3Bw8edN2uexFEwiuQ2UdvAh8Bu4DKUYVNqrQzZ87w7LPPurbpXgSR8AokKURZa38f9EiqiLNnz+LxeFzb8itJ5VIRkfIKJCm8ZIwZDayh6M1r3wUtqkrM4/Gwd6/7Dd5xcXEhjkZEpGIFkhRygKfxrsBWUDXNAk2CFZRIebhdp6hVq5bfMzut1iZSUiBJ4ffA/7PWHg92MCLl5e86xcSJE/1ev9BqbSIlBTIldTfeMhciIlLNBXKmkAekG2PWUfSagqakiohUM4EkhZW+LxERqeYCKYi3KBSBiIhI+AVyR/MBXFbwtdZq9pFUW6WtAKdZS1KdBTJ8FF/o5yhgEPCz4IQjUjmUtgKcZi1JdXbO2UfW2hOFvv7PWpsC3BCC2EREJMQCGT5qX+hhDbxnDvWCFpGIiIRNIMNHzxT62QNkAFqDUaoFVWsVKSqQ2UdJoQhEJNRUrVWkpECGj+oAAym5nsK04IUVOWqfySE2yn00rkaIq67m5ua6N5SYe1aoKT+fH3/8scT2C6wqxopURYEMH60CTgHbKXRHs1SQ09kce2q+a1P0I/eENJSTJ0+6bq9fSlawFnbs2FFie087ssLiEpHQCSQpNLbW3hz0SEREJOwCKYi32RjTuqIPbIypaYzZYYxZ43v8M2PMu8aYz33fL6voY4qISOkCSdLHj2UAAAo1SURBVAoJwHZjzD5jzE5jzC5jzM4KOPb9QOHVaiYD71lrmwLv+R6LiEgIBTJ8dEtFH9QY0xjoDTyBd70GgH5Aou/nRUAqMKmijy0iIv4FMiXVfSL3+UkBHqLoTXA/t9Ye8R3ziDHmCrcXGmPGAGMArrrqqiCEJsHW4IK6/K6/+60uDS6oG+JoRKSwQM4UKpQxpg/wjbV2uzEmsayvt9bOBeYCxMfHlzJZUiqrWjke9k9JcW2Lecl9u4iERsiTAnAd0NcYcyveAnsXG2P+BzhmjGnoO0toCHwThtiCxt/9CKG+F0GCR5VVpToIeVKw1v4R+COA70zhAWvtcGPM08BIYIbv+6pQxxZUfu5HCPW9CBI8qqwq1UEgs49CZQZwkzHmc+Am32MREQmhcAwfOay1qXhnGWGtPQH0DGc8IiKRLqxJQaSqcquuqsqqUh0oKYiUkb/qqqqsKtVBZbqmICIiYaakICIiDg0fyTlZa13XTACILm2xBRGpcpQUJCBuayYANCQ5tIGISFBp+EhERBxKCiIi4tDwkQTFBRdc4LcSam2jzyIilZWSggSFycn1Wwm12UvPhTgaEQmUkoJ4WUtubm64oxCRMFNSEAAscPz4cde2ZqENRUTCSElBzskAzZs3d28zJrTBiEhQKSnIOVng6NGjrm2/Cm0oIhJkSgpSqZQ2a0nrN4sEn5KCVCqlzVrS+s0iwacJ4yIi4lBSEBERh5KCiIg4lBRERMShpCAiIg4lBRERcWhKqlQZuodBJPiUFKTKqOr3MBw8eNB1e3R0NPXr1w9xNCLulBREQuDMmTM8++yzrm0PP/ywkoJUGrqmICIiDiUFERFxaPgokmghnSIaXFBXF65FilFSiCBaSKeoWjmeKn3hWiQYlBSkWvA3XVWf+EXKJuRJwRjzS+BfwC+AfGCutfY5Y8zPgCVADJABDLbWfh/q+KRq8jddVZ/4RcomHGcKHuAP1tqPjTH1gO3GmHeBZOA9a+0MY8xkYDIwKQzxlVvtMznERtVzbauRnx/iaKQq0T0MUlmEPClYa48AR3w//2iM2QtcCfQDEn1PWwSkUsWSAqezOfbUfNem6EfuCXEwUlXoHgapTMJ6TcEYEwO0A7YAP/clDKy1R4wxV/h5zRhgDMBVV10VlLjOnj2Lx+NxbcvXJ34RqcbClhSMMdHAcmCCtfYHY0xAr7PWzgXmAsTHx9tgxObxeNi7d69rW1xcXDAOKSJSKYTl5jVjTG28CeFla+1rvs3HjDENfe0NgW/CEZuISCQLeVIw3lOC+cBea+2sQk2rgZG+n0cCq0Idm4hIpAvH8NF1wAhglzEm3bftYWAG8Kox5i7gK2BQGGKTMjJA8+bNS2yvYYzrdoBAhwrFvxMnTpCZmenaphlLcj7CMftoI96/JW56hjIWOX8WOHr0aIntv/KzvaBNzk9mZiZPPvmka5tmLMn5UEE8ERFxKCmIiIhDtY+qI1VDrVbc7nbOyckp82tA1xvk3JQUqiF/1VAjsRJqVefvbueJEyeW+TWg6w1ybho+EhERh5KCiIg4NHwk1Zq/dRYAaht9JhIpTklBqjV/6ywANHvpuRBHI1L56aOSiIg4lBRERMShpCAiIg4lBRERcehCs4Scv8qqUHkqqJY2a6nBBXVDHI1I6CgpSMj5q6wKlaeCammzlmJect8uUh0oKYgI4H+NBtVLiixKCiIC+F+jQfWSIouSgkiE8VdB9VyVV91oBbjqR0lBJIKUVkG1tMqr/mgFuOpHSUGkjPzNTPpl3XqasSRVnpKCSBn5m5nU7KXnNGNJqjwlhapKq6uJSBAoKVRR/lZXA62wJiLlp6RQmelsQERCTEmhEtPZgIiEmpJCGdU+k0NsVD3Xthr5+SGORkSkYikplNXpbI49Nd+1KfqRe0IcjIhIxVJSEKmCGlxQN6T3RFTkXdDBoDurK46SgkgVVCvHE7J7Iir6Luhg0J3VFUdJQSTMSvvU7+8u6dqm+q6P5e9Tf61atfB4PK6vqSxnLNWBkoJImJX2qd/fXdLNXnou2GGFjb9P/RMnTqz0ZyzVgZKCi5pZ2ZphVMUYY1xXc6sKK7mF8lN/KK9FXGJq8cNnB9wbL6zD93nu9+DoU394VbqkYIy5GXgOqAm8aK2dEfIgNMOoSnJbza0qrOQWyk/9obwWwels3h0xwbWp50spPPnsU65t+tQfXpUqKRhjagIvADcBh4A0Y8xqa+2e8EZWAfzcnWx113LA/J0NVJY4qutZSahnOgWDv9lT/mYmlTabqbRrG9VhplOlSgpAJ+ALa+2XAMaYV4B+QJVPCv7uTm7mZ3tBmxRVWdZ2jqSzkpCeXQRBabOn/M1MKm02U2nXNqrDTCdjrQ13DA5jzO3Azdbau32PRwCdrbXjCj1nDDDG97AZsO88DtkAcP+LHHnUF0WpP36iviiqOvTH1dbay90aKtuZgtv5d5GsZa2dC8ytkIMZs81aG18R+6rq1BdFqT9+or4oqrr3R2Wb7HwI+GWhx42Bw2GKRUQk4lS2pJAGNDXGxBpjLgCGAKvDHJOISMSoVMNH1lqPMWYc8DbeKan/tNbuDuIhK2QYqppQXxSl/viJ+qKoat0flepCs4iIhFdlGz4SEZEwUlIQERFHRCYFY8zNxph9xpgvjDGTwx1PqBlj/mmM+cYY82mhbT8zxrxrjPnc9/2ycMYYKsaYXxpj1hlj9hpjdhtj7vdtj9T+iDLGbDXGfOLrjz/7tkdkf4C30oIxZocxZo3vcbXui4hLCoVKadwCtASGGmNahjeqkFsI3Fxs22TgPWttU+A93+NI4AH+YK1tAXQB7vX9PkRqf5wFbrDWXgu0BW42xnQhcvsD4H5gb6HH1bovIi4pUKiUhrU2BygopRExrLXrge+Kbe4HLPL9vAi4LaRBhYm19oi19mPfzz/i/c9/JZHbH9ZaW1D0p7bvyxKh/WGMaQz0Bl4stLla90UkJoUrga8LPT7k2xbpfm6tPQLeP5TAFWGOJ+SMMTFAO2ALEdwfvuGSdOAb4F1rbST3RwrwEFC4Zn617otITArnLKUhkccYEw0sByZYa38IdzzhZK3Ns9a2xVtRoJMxplW4YwoHY0wf4Btr7fZwxxJKkZgUVErD3TFjTEMA3/dvwhxPyBhjauNNCC9ba1/zbY7Y/ihgrT0JpOK9/hSJ/XEd0NcYk4F3mPkGY8z/UM37IhKTgkppuFsNjPT9PBJYFcZYQsZ4F0GYD+y11s4q1BSp/XG5MeZS3891gRuB/xCB/WGt/aO1trG1Ngbv34n3rbXDqeZ9EZF3NBtjbsU7VlhQSuOJMIcUUsaYxUAi3hLAx4DHgJXAq8BVwFfAIGtt8YvR1Y4xJgHYAOzip3Hjh/FeV4jE/miD9+JpTbwfGl+11k4zxtQnAvujgDEmEXjAWtunuvdFRCYFERFxF4nDRyIi4oeSgoiIOJQURETEoaQgIiIOJQUREXEoKYiIiENJQUREHP8f9f1g7w11M8sAAAAASUVORK5CYII=\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar = 7.0, 0.45\n", - "MU_H = 1 / gamma_dist(hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar, N)\n", - "\n", - "dist_info([1/ETA, 1/MU_H, 1/ETA+1/MU_H], [\"onset-to-hospitalization period\", \"hospitalization-to-death period\", \"onset-to-death period\"], plot=True, colors=['crimson', 'darkgray', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set severity parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the percentage of cases that are asymptomatic. This percentage of case will progress from the pre-symptomatic state to the asymptomatic state, rather than to the symptomatic state." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_ASYMPTOMATIC = 0.25" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the case hospitalization rate. The value used here is approximately the age-frequency-weighted average of age-stratified hospitalization rates for working age adults using data from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_HOSPITALIZED = 0.035" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the case fatality rate for hospitalized cases. The value used here is approximately the age-frequency-weighted average of age stratified hospitalization fatality rates for working age adults, again using figures from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_FATALITY = 0.08" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set transmission parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#stochastic-network-model-implementation) model considers two modes of disease transmission: a well-mixed mode of [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) and a contact network based mode of [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The propensity for a given individual to become exposed due to global transmission depends on the mean transmissibility of all infectious individuals in the population; the propensity for a given individual to become exposed due to local transmission depends on the pairwise transmissibilities between the focal node and its infectious contacts in the network (see [Transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#transmission) and [Model Equations](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#model-equations) for more information about these calculations). " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The transmissibility parameter *β* can be related to the basic reproduction number *R0* (i.e., the expected number of new infections generated by a single infectious individual in a completely susceptible population) by the standard formula: *β = R0𝛾*. *R0* is a more interpretable parameter, so we specify transmissibility in terms of *R0* and then calculate the corresponding *β* values.\n", - "\n", - "First, we generate a distribution of individual *R0* values (i.e., the expected number of new infections generated by a single *particular* infectious individual in a completely susceptible population). Of course, this means that transmissibility is heterogeneous in this population. The coefficient of variation is an important parameter for the individual *R0* distribution in that it tunes the degree of superspreading in the heterogeneous transmissibility. The distribution used in this example has a relatively low coefficient of variation, so most individuals have around the same degree of transmissibility. But a higher coefficient of variation (e.g., 2.0) would give a long right tail in idividual transmissibility representing a small number of individuals contributing many cases while the majority cases contribute less than 1 on average when they are infectious." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Individual R0: mean = 1.98, std = 0.41, 95% CI = (1.32, 2.89)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "R0_mean = 2.0\n", - "R0_coeffvar = 0.2\n", - "\n", - "R0 = gamma_dist(R0_mean, R0_coeffvar, N)\n", - "\n", - "dist_info(R0, \"Individual R0\", bin_size=0.1, plot=True, colors='crimson')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Individuals are ultimately assigned an [*Individual Transmissibility Value*](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#transmissibility-parameters) (*βi*), which are stored in the `beta` attribute of the model object. \n", - "\n", - "The means of the Individual Transmissibility Values for infectious subpopulations are used to calculate the [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) terms. Individual Transmissibility Values may also be used to generate the Pairwise Transmissibility Values used for [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission) terms, as we will specify in a few steps." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "BETA = 1/infectiousPeriod * R0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the stochastic network model, an individual comes into contact with a random individual from the population at large (e.g., in a public space) with probability *p* or with an individual from their set of close contacts with probability *(1-p)*. Transmission that occurs between an individual and the population at large is referred to as [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission), and transmission between an individual and one of their close contacts (network neighbors) is referred to as [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The parameter *p* defines the locality of the network: for *p=0* an individual only interacts with their close contacts, while *p=1* represents a uniformly mixed population.\n", - "\n", - "Here we set *p* to reflect 40% of interactions being with incidental or casual contacts outside their set of close contacts." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "P_GLOBALINTXN = 0.4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set Testing, Tracing, & Isolation (TTI) intervention protocol parameters:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the parameters that govern the Testing, Tracing, and Isolation protocol that is implemented by the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). The implementation of this TTI protocol and the interpretation of these parameters is desribed in detail on the [TTI Simulation Loop wiki page](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) (but these parameters are briefly explained as code comments below).\n", - "\n", - "**The scenario set up in the steps that follow involves the entire workforce being tested on a weekly basis, a 2-day test turn around time, 50% of symptomatic individuals self-reporting and getting tested within 1 day of onset, 30% of symptomatics self-isolating even without a positive test, and teams of detected positive cases being proactively isolated. A new exogenous exposures comes into the workplace about once a week.**" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "INTERVENTION_START_PCT_INFECTED = 0/100\n", - "AVERAGE_INTRODUCTIONS_PER_DAY = 1/14 # expected number of new exogenous exposures per day\n", - "\n", - "TESTING_CADENCE = 'weekly' # how often to do testing (other than self-reporting symptomatics who can get tested any day)\n", - "PCT_TESTED_PER_DAY = 1.0 # max daily test allotment defined as a percent of population size\n", - "TEST_FALSENEG_RATE = 'temporal' # test false negative rate, will use FN rate that varies with disease time\n", - "MAX_PCT_TESTS_FOR_SYMPTOMATICS = 1.0 # max percent of daily test allotment to use on self-reporting symptomatics\n", - "MAX_PCT_TESTS_FOR_TRACES = 0.0 # max percent of daily test allotment to use on contact traces\n", - "RANDOM_TESTING_DEGREE_BIAS = 0 # magnitude of degree bias in random selections for testing, none here\n", - "\n", - "PCT_CONTACTS_TO_TRACE = 0.0 # percentage of primary cases' contacts that are traced\n", - "TRACING_LAG = 2 # number of cadence testing days between primary tests and tracing tests\n", - "\n", - "ISOLATION_LAG_SYMPTOMATIC = 1 # number of days between onset of symptoms and self-isolation of symptomatics\n", - "ISOLATION_LAG_POSITIVE = 2 # test turn-around time (TAT): number of days between administration of test and isolation of positive cases\n", - "ISOLATION_LAG_CONTACT = 0 # number of days between a contact being traced and that contact self-isolating\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set intervention compliance parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First, we specify the compliance rates (i.e., the percentage of individuals who are compliant) for each intervention type. See the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) documentation for more information about compliance." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "TESTING_COMPLIANCE_RATE_SYMPTOMATIC = 0.5 \n", - "TESTING_COMPLIANCE_RATE_TRACED = 0.0\n", - "TESTING_COMPLIANCE_RATE_RANDOM = 1.0 # Assume employee testing is mandatory, so 100% compliance\n", - "\n", - "TRACING_COMPLIANCE_RATE = 0.0\n", - "\n", - "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL = 0.3\n", - "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE = 0.8 # Isolate teams with a positive member, but suppose 20% of employees are essential workforce\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE = 0.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we randomly assign a `True/False` compliance to each individual according to the rates set above. Individuals whose compliance is set to `True` for a given intervention will participate in that intervention, individuals set to `False` will not." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "TESTING_COMPLIANCE_RANDOM = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_RANDOM)\n", - "TESTING_COMPLIANCE_TRACED = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_TRACED)\n", - "TESTING_COMPLIANCE_SYMPTOMATIC = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_SYMPTOMATIC)\n", - "\n", - "TRACING_COMPLIANCE = (numpy.random.rand(N) < TRACING_COMPLIANCE_RATE)\n", - "\n", - "ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL)\n", - "ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE)\n", - "ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL)\n", - "ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE)\n", - "ISOLATION_COMPLIANCE_POSITIVE_CONTACT = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT)\n", - "ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initializing the model" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\boaz\\PycharmProjects\\seirsplus\\seirsplus\\models.py:2143: RuntimeWarning: invalid value encountered in true_divide\n", - " self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1))\n" - ] - } - ], - "source": [ - "model = ExtSEIRSNetworkModel(G=G_baseline, p=P_GLOBALINTXN,\n", - " beta=BETA, sigma=SIGMA, lamda=LAMDA, gamma=GAMMA, \n", - " gamma_asym=GAMMA, eta=ETA, gamma_H=GAMMA_H, mu_H=MU_H, \n", - " a=PCT_ASYMPTOMATIC, h=PCT_HOSPITALIZED, f=PCT_FATALITY, \n", - " G_Q=G_quarantine, isolation_time=14,\n", - " initE=INIT_EXPOSED)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Running the model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set the max simulation time to 300 days." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "T = 300" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Execute the TTI simulation scenario by calling the `run_tti_sim()` function, which runs a custom simulation loop that implements the [TTI Simulation Protocol](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop)." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[INTERVENTIONS @ t = 0.64 (4 (0.50%) infected)]\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'sort' is not defined", - "output_type": "error", - "traceback": [ - "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[1;31mNameError\u001B[0m Traceback (most recent call last)", - "\u001B[1;32m\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[1;32m----> 1\u001B[1;33m run_tti_sim(model, T, \n\u001B[0m\u001B[0;32m 2\u001B[0m \u001B[0mintervention_start_pct_infected\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mINTERVENTION_START_PCT_INFECTED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maverage_introductions_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mAVERAGE_INTRODUCTIONS_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3\u001B[0m \u001B[0mtesting_cadence\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_CADENCE\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpct_tested_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mPCT_TESTED_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtest_falseneg_rate\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTEST_FALSENEG_RATE\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[0mtesting_compliance_symptomatic\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_SYMPTOMATIC\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_symptomatics\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_SYMPTOMATICS\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m \u001B[0mtesting_compliance_traced\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_TRACED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_traces\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_TRACES\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\PycharmProjects\\seirsplus\\seirsplus\\sim_loops.py\u001B[0m in \u001B[0;36mrun_tti_sim\u001B[1;34m(model, T, intervention_start_pct_infected, average_introductions_per_day, testing_cadence, pct_tested_per_day, test_falseneg_rate, testing_compliance_symptomatic, max_pct_tests_for_symptomatics, testing_compliance_traced, max_pct_tests_for_traces, testing_compliance_random, random_testing_degree_bias, tracing_compliance, num_contacts_to_trace, pct_contacts_to_trace, tracing_lag, isolation_compliance_symptomatic_individual, isolation_compliance_symptomatic_groupmate, isolation_compliance_positive_individual, isolation_compliance_positive_groupmate, isolation_compliance_positive_contact, isolation_compliance_positive_contactgroupmate, isolation_lag_symptomatic, isolation_lag_positive, isolation_lag_contact, isolation_groups, cadence_testing_days, cadence_cycle_length, temporal_falseneg_rates, test_priority)\u001B[0m\n\u001B[0;32m 268\u001B[0m \u001B[1;32mif\u001B[0m \u001B[1;34m'last_tested'\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mtest_priority\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 269\u001B[0m \u001B[1;31m# sort the pool according to the time they were last tested, breaking ties randomly\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 270\u001B[1;33m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0msort\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mkey\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mi\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mmodel\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtestedTime\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mi\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcmp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0my\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m*\u001B[0m \u001B[1;36m2\u001B[0m \u001B[1;33m-\u001B[0m \u001B[1;36m1\u001B[0m \u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[0mnumRandomTests\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 271\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 272\u001B[0m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtestingPool\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnumpy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mchoice\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnumRandomTests\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mp\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mtestingPool_degreeWeights\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreplace\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;31mNameError\u001B[0m: name 'sort' is not defined" - ] - } - ], - "source": [ - "run_tti_sim(model, T, \n", - " intervention_start_pct_infected=INTERVENTION_START_PCT_INFECTED, average_introductions_per_day=AVERAGE_INTRODUCTIONS_PER_DAY,\n", - " testing_cadence=TESTING_CADENCE, pct_tested_per_day=PCT_TESTED_PER_DAY, test_falseneg_rate=TEST_FALSENEG_RATE, \n", - " testing_compliance_symptomatic=TESTING_COMPLIANCE_SYMPTOMATIC, max_pct_tests_for_symptomatics=MAX_PCT_TESTS_FOR_SYMPTOMATICS,\n", - " testing_compliance_traced=TESTING_COMPLIANCE_TRACED, max_pct_tests_for_traces=MAX_PCT_TESTS_FOR_TRACES,\n", - " testing_compliance_random=TESTING_COMPLIANCE_RANDOM, random_testing_degree_bias=RANDOM_TESTING_DEGREE_BIAS,\n", - " tracing_compliance=TRACING_COMPLIANCE, pct_contacts_to_trace=PCT_CONTACTS_TO_TRACE, tracing_lag=TRACING_LAG,\n", - " isolation_compliance_symptomatic_individual=ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL, isolation_compliance_symptomatic_groupmate=ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE, \n", - " isolation_compliance_positive_individual=ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL, isolation_compliance_positive_groupmate=ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE,\n", - " isolation_compliance_positive_contact=ISOLATION_COMPLIANCE_POSITIVE_CONTACT, isolation_compliance_positive_contactgroupmate=ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE,\n", - " isolation_lag_symptomatic=ISOLATION_LAG_SYMPTOMATIC, isolation_lag_positive=ISOLATION_LAG_POSITIVE, \n", - " isolation_groups=list(teams.values()),\n", - " test_priority = 'last_tested')" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "total percent infected: 0.88%\n", - "total percent fatality: 0.00%\n", - "peak pct hospitalized: 0.00%\n" - ] - } - ], - "source": [ - "results_summary(model)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualizing the results" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = model.figure_infections(combine_Q_infected=False, plot_Q_R='stacked', plot_Q_S='stacked')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.8.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} \ No newline at end of file From 7da545a6eb4f356eaf5b3d7dfc0c9ffc30dbce5d Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 13:18:34 -0400 Subject: [PATCH 005/117] Revert "Remove testing notebook from git tracking" This reverts commit 51d3ad00 --- .gitignore | 1 - .../Extended_SEIRS_Workplace_TTI_Demo.ipynb | 18 +- ...EIRS_Workplace_TTI_Demo_timePriority.ipynb | 853 ++++++++++++++++++ 3 files changed, 870 insertions(+), 2 deletions(-) create mode 100644 examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb diff --git a/.gitignore b/.gitignore index 2cff9c4..76386e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ # ignore temporary swap files *.swp -examples/Testing*.ipynb # ignore notebooks used for testing features .DS_Store diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb index f7a63ec..6e04b19 100644 --- a/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb +++ b/examples/Extended_SEIRS_Workplace_TTI_Demo.ipynb @@ -31,8 +31,10 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 1, "metadata": {}, + "outputs": [], "source": [ "from seirsplus.models import *\n", "from seirsplus.networks import *\n", @@ -42,6 +44,20 @@ "import matplotlib.pyplot as pyplot" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### *Alternatively, manually copy the code to your machine*\n", + "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", + "```python\n", + "from models import *\n", + "from networks import *\n", + "from sim_loops import *\n", + "from utilities import *\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb new file mode 100644 index 0000000..45a2eec --- /dev/null +++ b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb @@ -0,0 +1,853 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extended SEIRS Workplace TTI Demo\n", + "\n", + "**In this demonstration we will explore the effect of testing, tracing, and isolation interventions on disease transmission in a workplace setting with a realistic contact network.**\n", + "\n", + "This notebook provides a demonstration of the functionality of the [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description) and the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). This notebook also offers a sandbox for starting to explore TTI scenarios of your own. \n", + "For a more thorough walkthrough of the model, simulation loop, and use of this package, refer to the [SEIRS+ Wiki](https://github.com/ryansmcgee/seirsplus/wiki)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Installing and importing the model code\n", + "\n", + "All of the code needed to run the model is imported from the ```models``` module of this package.\n", + "\n", + "In this demo we will also use features from the `networks`, `sim_loops`, and `utilities` modules.\n", + "\n", + "#### Install the package using ```pip```\n", + "The package can be installed on your machine by entering this in the command line:\n", + "\n", + "```pip install seirsplus```\n", + "\n", + "Then, the ```models```, `networks`, `sim_loops`, and `utilities` modules can be imported as shown here:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from seirsplus.models import *\n", + "from seirsplus.networks import *\n", + "from seirsplus.sim_loops import *\n", + "from seirsplus.utilities import *\n", + "import networkx\n", + "import matplotlib.pyplot as pyplot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### *Alternatively, manually copy the code to your machine*\n", + "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", + "```python\n", + "from models import *\n", + "from networks import *\n", + "from sim_loops import *\n", + "from utilities import *\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set basic parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the workplace size and structure" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "NUM_COHORTS = 4\n", + "NUM_NODES_PER_COHORT = 200\n", + "NUM_TEAMS_PER_COHORT = 10\n", + "\n", + "MEAN_INTRACOHORT_DEGREE = 6\n", + "PCT_CONTACTS_INTERCOHORT = 0.1" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "N = NUM_NODES_PER_COHORT*NUM_COHORTS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we set the initial prevalence to be a single case" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "INIT_EXPOSED = 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------\n", + "\n", + "## Specifying contact networks\n", + "\n", + "This package implements models epidemic dynamics for populations with a structured [contact network](Extended-SEIRS-Model-Description#contact-networks). Individuals are represented as nodes in a network, and parameters, contacts, and interventions can be specified on a targeted individual basis. A graph specifying the contact network must be specified, where each node represents an individual in the population and edges connect individuals who have regular interactions.\n", + "\n", + "This model also supports scenarios where individuals enter quarantine states in which their parameters and interactions may be different from baseline, and a separate graph defining the interactions for individuals in quarantine can be specified (i.e., the [quarantine contact network](Extended-SEIRS-Model-Description#quarantine-contacts)).\n", + "\n", + "### Workplace Contact Network\n", + "\n", + "Here we use the [**demographic community network generator**](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#workplace-network) defined in the SEIRS+ package. This function generates a contact network that resembles workplaces and other multi-level modular populations.\n", + "\n", + "[FARZ](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#farz-networks) network layers are generated to represent cohorts of employees (e.g., departments, floors, shifts). FARZ networks have a tunable community structure, so each cohort includes some number of communities, which can be thought to represent teams (i.e., groups of employees that work closely with each other). Employees may belong to more than one team (specified by a FARZ parameter), but employees belong to only one cohort. An employee's intra-team and intra-cohort contacts are defined by the FARZ cohort network they belong to. A specified percentage of each employee's total number of workplace contacts can be with individuals from other cohorts. An employee's inter-cohort contacts are drawn randomly from the pool of individuals outside their own cohort. \n", + "\n", + "The number of cohorts, number of employees per cohort, number of teams per cohort, number of teams employees belong to, mean intra-cohort degree, percent of within- and between-team connections, and percent of intra- and inter-cohort connections can be controlled with the arguments to the `generate_demographic_contact_network()` function (some of which are passed as [parameters to the FARZ generator](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#FARZ-parameters)).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Baseline:\n", + "Degree: mean = 11.11, std = 8.41, 95% CI = (1.00, 29.00)\n", + " coeff var = 0.76\n", + "Assortativity: 0.28\n", + "Clustering coeff: 0.24\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "G_baseline, cohorts, teams = generate_workplace_contact_network(\n", + " num_cohorts=NUM_COHORTS, num_nodes_per_cohort=NUM_NODES_PER_COHORT, \n", + " num_teams_per_cohort=NUM_TEAMS_PER_COHORT,\n", + " mean_intracohort_degree=MEAN_INTRACOHORT_DEGREE, \n", + " pct_contacts_intercohort=PCT_CONTACTS_INTERCOHORT,\n", + " farz_params={'alpha':5.0, 'gamma':5.0, 'beta':0.5, 'r':1, 'q':0.0, 'phi':10, \n", + " 'b':0, 'epsilon':1e-6, 'directed': False, 'weighted': False})\n", + "\n", + "network_info(G_baseline, \"Baseline\", plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we define the quarantine contact network to be an empty network (i.e., no connections). This represents an assumption that an employee that is in a quarantine state makes no contact with anyone from their workplace." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "G_quarantine = networkx.classes.function.create_empty_copy(G_baseline)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Specifying parameters\n", + "\n", + "**_The parameter values used in this notebook reflect rough estimates of parameter values for the COVID-19 epidemic (as of 9 Aug 2020)._**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set disease progression rate parameters:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Parameter values are assigned to members of the population on an individual basis. Parameter values can be [specified to the `ExtSEIRSNetworkModel`](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#specifying-parameters) by providing a list of values that gives the *N* values to assign to each individual. The population may be either homogeneous or heterogeneous for a given parameter at the user's discretion. \n", + "\n", + "**Here we generate distributions of values for each parameter, thus specifying a realistically heterogeneous population.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected latent periods (time in Exposed state) and presymptomatic periods (time in Pre-symptomatic infectious state). The `sigma` and `lamda` rates are calculated as the inverse of the expected exposed and pre-symptomatic periods assigned to each individual, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "latent period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", + "\n", + "pre-symptomatic period: mean = 2.94, std = 1.72, 95% CI = (0.64, 7.12)\n", + "\n", + "total incubation period: mean = 5.14, std = 2.03, 95% CI = (2.17, 10.02)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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WVlccsklQUxff/013//+9/nNb37D+vXrWbJkyRnlOwBWrlzJr371KzZu3MiOHTtYsGABBw4cKPHzLPjchw4dGiw7evQoI0eOZN68ecEcE08//TRHjx5l1KhR/PnPf2b58uX8/e9/L/0vQRGUFESqqdatW9O7d28A7rjjDjIzM4P3vv/97wPw/vvvs3nzZnr37k1qaiqzZs0KCuYV1r17d5577jkmTpzIxo0bqV+/PhdeeCFXX301r732Glu3buX48eOkpKQA0K5dO1JSUqhRowaXX34511xzDWZGSkrKKWW3Bw0aRN26dWnSpAn9+/cPziIKy8zM5M477wROLZsN0L9/f+rXr0/Tpk1p2LAhN910E8Ap7WzatIkrr7ySlJQUZs+ezYcfflji5/bRRx/RokULunfvDkCDBg2oWfPMnvj09HS+9a1vkZCQwLBhw8jMzDzr51nwuZ/eXrt27bj00ksBGDFiBMuWLWPr1q20a9eO9u3bY2bccccdJcYdK11TEKmmiipbXaCgRLW7c9111zF37txT1v3ggw+CEtqTJk0KJtx5/fXXufPOOxk3bhx33XUX9957L0888QQdOnQIzhKAU0pt16hRI3hdo0YNTpw4EVOMBUqq3xZLOyNHjmThwoV06dKFjIyMs95p7e4xleMurix4UZ9ngaJKg5d3WXCdKYhUU7t372bFiki9yblz59KnT58z1unZsyd/+9vf2L59OwBfffUVH3/8MT169CArK4usrCwGDhzIrl27aNasGaNGjeKee+5h7dq1APTo0YNPPvmEOXPmBBPqlMarr77K0aNHyc3NZenSpXTv3v2MctzFlc2O1aFDh2jRogXHjx8P9gPFl/3u0KEDe/bsYdWqVcH2hRNZgZUrV7Jz505OnjzJvHnz6NOnT7GfZ0k6dOhAdnZ2sM0f//hHrrrqKjp06MDOnTvZsWMHQLGJprR0piBSEVyQGBkxVJb7O4uOHTsya9Ys7rvvPtq3b8/9999/xjpNmzYlIyODYcOGBRc3H3/88aAro8DSpUuZMmUKtWrVIjExMeivB7j99tvJysrioosuKvVhpKen873vfY/du3fzs5/9jJYtW9K0aVNq1qxJly5dGDlyZLFls2P1n//5n/To0YO2bduSkpISJIKhQ4cyatQofvvb3wYXfAEuuOAC5s2bx4MPPkheXh5169ZlyZIlJCae+pn36tWL8ePHs3HjxuCic40aNWL6PAurU6cOzz33HLfddhsnTpyge/fujBkzhtq1azNjxgy+973v0aRJE/r06cOmTZtK8/EWqdxKZ4dBpbOjVDq70ol36ezs7Oxg0vuwDRgwgIcffphrrimy5FmxJk6cSGJiIv/6r/8aUmThWbp0KVOnTj3rPBDlocKUzhaR6u3gwYNceuml1K1bt9QJQeJH3Uci1VBSUlLoZwnf+MY3ztpfXpKJEyeWXTDlrF+/fvTr1y/eYZwTnSmIiEhASUFERAJKCiIiElBSEBGRgJKCSAWQm5vLrl27yuyRm1ty6eyDBw+eUuuoOLGWqc7OziY5OfmM5Xv27GHIkCFn3b40imurJBkZGezZsyd4fe+9955SFjuevvvd73Lw4MGY1584cSJTp04NLR6NPhKpAA4fPnxKIbjzNWHCBBo3Lr50dkFSGDt2bIn7Od8y1S1btjzlxq94ycjIIDk5mZYtWwLwhz/8Ic4RRcpXuDtvvPFGvEM5hc4URKqh8ePHs2PHDlJTUxk3bhzuzrhx40hOTiYlJYV58+YF6xUuU52dnc2VV15Jt27d6NatG++9916J7RT+qz4jI4NbbrmFG264gfbt2/Nv//ZvwXpvvvkm3bp1o0uXLsE9Daf/RZycnBwUsTtx4kSRZb8nTZpE9+7dSU5OZvTo0bg7L730EqtXr2b48OGkpqaSl5dHv379KLjxde7cuaSkpJCcnMwjjzwStJeYmMhjjz1Gly5d6NmzJ5999tkZx1dceW+AKVOm0L17dzp37szPf/7z4PPo2LEjY8eOpVu3bnzyySckJSVx4MABAKZNm0ZycjLJycn8+te/DvY1efJkLrvsMq699lo++uijEj/z86WkIFINPfnkk1xyySVkZWUxZcoUFixYEJS9XrJkCePGjWPv3r1nlKlu1qwZb731FmvXrmXevHk89NBDpWo3KysrKAE9b948PvnkE/bv38+oUaN4+eWXWb9+PS+++OJZ91Nc2e8HHniAVatWsWnTJvLy8njttdcYMmQIaWlpzJ49m6ysrFPKXO/Zs4dHHnmEd955h6ysLFatWsXChQsBOHLkCD179mT9+vX07dv3lC/8wooq77148WK2bdvGypUrycrKYs2aNSxbtiyI/a677mLdunW0bfvPSgRr1qzhueee44MPPuD999/nmWeeYd26daxZs4YXXniBdevWsWDBgqDmUliUFESEzMxMhg0bRkJCAs2bN+eqq64q8svn+PHjjBo1ipSUFG677bZS98tfc801NGzYkDp16tCpUyd27drF+++/T9++fWnXrh0AjRo1Out+iiv7/e6779KjRw9SUlJ45513zloGe9WqVfTr1y+opzR8+PDgy/uCCy4Iprf89re/fUpJ78KKKu+9ePFiFi9eTNeuXenWrRtbt25l27ZtALRt25aePXuesZ/MzEwGDx7MhRdeSGJiIrfccgvLly9n+fLlDB48mHr16tGgQQMGDhx41s/nfOiagoiUWJ65sOnTp9O8eXPWr1/PyZMnqVOnTqnaKVyoLiEhgRMnThRbirpmzZrBbGVAMHEOFF2W+ujRo4wdO5bVq1fTunVrJk6ceMo2RSnpuGvVqhW0UxBrUYorkf3oo48G5cULZGdnF1ke+2yxhFEiuzg6U6gqvt4V/iO/6k4GX90UVX563rx55Ofns3//fpYtW0Z6evoZ633xxRe0aNGCGjVq8Mc//pH8/PzzjqVXr1789a9/ZefOnQDBNJlJSUlBCe61a9cG70PRZb8LEkCTJk04fPjwKRe4iyuD3aNHD/76179y4MAB8vPzmTt3LldddVWp4i+qvPf111/PzJkzg6k2P/30U/bt21fifvr27cvChQv56quvOHLkCK+88gpXXnklffv25ZVXXiEvL49Dhw7x5z//uVTxlVZoZwpm1hp4HvgmcBKY4e6/MbOJwChgf3TVCe7+RnSbR4F7gHzgIXf/S1jxVSmeB59PD7+dRhMg4fwng5czJSYmMmFC2ZXOPr2M8+kaN25M7969SU5O5sYbb+SXv/wlK1asoEuXLpgZv/zlL/nmN79J48aNzyhTfeutt/Liiy/Sv3//Yv/qLY2mTZsyY8YMbrnlFk6ePBlct7j11lt5/vnnSU1NpXv37qeUly6q7He9evWCrq2kpKRgZjSITKQzZswY6tatGyQTgBYtWvCLX/yC/v374+5897vfZdCgQaWKv6jy3i1btmTLli306tULiPx7/OlPfyIhIaHY/XTr1o2RI0eSnp4ORIbNdu3aFYjMyJaamkrbtm258sorSxVfaYVWOtvMWgAt3H2tmdUH1gA3A7cDh9196mnrdwLmAulAS2AJcKm7F/uniEpnR130cPklBZXoLhPxLp0tZaMy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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "latentPeriod_mean, latentPeriod_coeffvar = 3.0, 0.6\n", + "SIGMA = 1 / gamma_dist(latentPeriod_mean, latentPeriod_coeffvar, N)\n", + "\n", + "presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar = 2.2, 0.5\n", + "LAMDA = 1 / gamma_dist(presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar, N)\n", + "\n", + "dist_info([1/LAMDA, 1/SIGMA, 1/LAMDA+1/SIGMA], [\"latent period\", \"pre-symptomatic period\", \"total incubation period\"], plot=True, colors=['gold', 'darkorange', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected (a)symptomatic periods (time in symptomatic or asymptomatic state). The `gamma` rates are calculated as the inverse of the expected (a)symptomatic periods assigned to each individual. \n", + "\n", + "The expected total infectious period for each individual is the sum of their expected pre-symptomatic and (a)symptomatic periods." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pre-symptomatic period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", + "\n", + "(a)symptomatic period: mean = 4.01, std = 1.54, 95% CI = (1.64, 7.36)\n", + "\n", + "total infectious period: mean = 6.20, std = 1.87, 95% CI = (3.09, 10.45)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "symptomaticPeriod_mean, symptomaticPeriod_coeffvar = 4.0, 0.4\n", + "GAMMA = 1 / gamma_dist(symptomaticPeriod_mean, symptomaticPeriod_coeffvar, N)\n", + "\n", + "infectiousPeriod = 1/LAMDA + 1/GAMMA\n", + "\n", + "dist_info([1/LAMDA, 1/GAMMA, 1/LAMDA+1/GAMMA], [\"pre-symptomatic period\", \"(a)symptomatic period\", \"total infectious period\"], plot=True, colors=['darkorange', 'crimson', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of expected onset-to-hospitalization periods (time in symptomatic state before entering hospitalized state for those with severe cases) and hospitalization-to-discharge periods (time in hospitalized state for those with non-fatal cases). The `eta` and `gamma_H` rates are calculated as the inverse of the expected onset-to-hospitalization periods and hospitalization-to-discharge periods assigned to each individual, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", + "\n", + "hospitalization-to-discharge period: mean = 11.38, std = 5.29, 95% CI = (3.49, 23.54)\n", + "\n", + "onset-to-discharge period: mean = 22.51, std = 7.16, 95% CI = (10.62, 39.43)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3wU5bnA8d+TEAzITQE9QYTIOVzEEAOGqxQIVFChXBRQDigXIdADUmiLUKyCqICtRyPWUwpYpGopiHIR23ojiFyEgERALFo0UCRyCUIJIeSy7/ljN+smOxs2Ibub3Xm+n08+yc7szDwZwpPJM+88rxhjUEopZR9RoQ5AKaVUcGniV0opm9HEr5RSNqOJXymlbEYTv1JK2UyNUAfgj0aNGpn4+PhQh6GUUmFlz549p40xjcsuD4vEHx8fz+7du0MdhlJKhRUROWK1XEs9SillM5r4lVLKZjTxK6WUzYRFjV9FtsLCQo4dO0Z+fn6oQ1EqLMXGxtK0aVNiYmL8er8mfhVyx44do27dusTHxyMioQ5HqbBijCEnJ4djx45x0003+bWNlnpUyOXn59OwYUNN+kpVgojQsGHDCv3FrIlfVQua9JWqvIr+/9HEr5RSNqOJX1U7xd+fo/Bf31XZR/H350L6/WRmZvLXv/7V5/q0tDTy8vIqtM/NmzczYMCAKw3Np927dzN16lT3sbZv337ZbV555RWmTJkCwOLFi/nTn/5U4eOWPVZl9xMIjz/+OB988IHf7w/0v9GV0Ju71Vzx9+dw5F70Wi4xNTCFRZbbRNWpRfQ19QMdWsA4ci9yNu3VKttfg2kPhPR8ZGZmsnv3bu6++27L9WlpaYwaNYratWsHOTLfkpOTSU5OBpwJrE6dOnTr1s3v7SdNmlSp45Y9VmX3U9WKi4uZN29eqMOoMnrFX82VJMGyH8XnL1guP5v2quUvClW+5557joSEBBISEkhLSwMgKyuLm2++mQkTJnDLLbfQt29fLl50nttFixbRtm1bEhMTuf/++wG4cOEC48aNo2PHjrRv357169dTUFDA448/zqpVq0hKSmLVqlWljrto0SKOHz9OSkoKKSkpAKxcuZJ27dqRkJDAzJkzfcacm5vL0KFDadOmDSNHjqRkNr0PP/yQ9u3b065dO8aNG8elS5cAmDVrljvmX/7ylwCMGTOGSZMm8aMf/YhWrVqxceNG4Ier1aysLBYvXszzzz9PUlISH3/8MW+//TadO3emffv2/PjHP+bEiRNesc2dO5dnn32W48ePk5SU5P6Ijo7myJEjlvuwOlbJfsD5C7RLly4kJiYyZMgQvv/+ewB69erFzJkz6dSpE61ateLjjz/2imfz5s306NGDIUOG0LZtWyZNmoTD4QDgvffeo2vXrnTo0IFhw4aRm5sLOFvFzJs3j+7du/PGG28wZswY1qxZU+45/vvf/06bNm3o3r07b731ls9/u1DTxK9sb8+ePSxfvpydO3fyySefsHTpUvbu3QvAV199xeTJk/n8889p0KABb775JgALFy5k79697Nu3j8WLFwPw9NNP07t3bzIyMkhPT2fGjBkUFhYyb9487rvvPjIzM7nvvvtKHXvq1Kk0adKE9PR00tPTOX78ODNnzmTTpk1kZmaSkZHBunXrLOPeu3cvaWlpHDx4kK+//ppt27aRn5/PmDFjWLVqFfv376eoqIjf//73nDlzhrVr1/L555+zb98+fv3rX7v3k5WVxUcffcQ777zDpEmTSo0OiY+PZ9KkSUyfPp3MzEx+9KMf0b17dz755BP27t3L/fffz29+8xuf57ZJkyZkZmaSmZnJhAkTuPfee2nevLnlPqyO5enBBx/kmWeeYd++fbRr144nnnjCva6oqIhdu3aRlpZWarmnXbt28b//+7/s37+fw4cP89Zbb3H69GmeeuopPvjgAz799FOSk5N57rnn3NvExsaydetW9y93wOc5zs/PZ8KECbz99tt8/PHHfPfddz7PS6hpqcdmfJWOIPxLRJW1detWhgwZwtVXXw3APffcw8cff8zAgQO56aabSEpKAuC2224jKysLgMTEREaOHMngwYMZPHgw4Lxy3LBhg/sKNT8/n6NHj1YoloyMDHr16kXjxs6GiiNHjmTLli3uY3jq1KkTTZs2BSApKYmsrCzq1q3LTTfdRKtWrQAYPXo0L730ElOmTCE2Npbx48fTv3//UrXn4cOHExUVRcuWLWnRogX/+Mc/yo3x2LFj3HfffWRnZ1NQUODX2PFt27axbNky99V4Rfdx7tw5zp49S8+ePd3f17Bhw9zr77nnHqD0v1FZnTp1okWLFgCMGDGCrVu3Ehsby8GDB7n99tsBKCgooGvXru5tyv6iBjh06JDl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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar = 11.0, 0.45\n", + "ETA = 1 / gamma_dist(onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar, N)\n", + "\n", + "hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar = 11.0, 0.45\n", + "GAMMA_H = 1 / gamma_dist(hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar, N)\n", + "\n", + "dist_info([1/ETA, 1/GAMMA_H, 1/ETA+1/GAMMA_H], [\"onset-to-hospitalization period\", \"hospitalization-to-discharge period\", \"onset-to-discharge period\"], plot=True, colors=['crimson', 'violet', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a distribution of hospitalization-to-death periods (time in hospitalized state for those with fatal cases). The `mu_H` rates are calculated as the inverse of the expected hospitalization-to-death periods." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", + "\n", + "hospitalization-to-death period: mean = 6.87, std = 3.10, 95% CI = (2.01, 13.61)\n", + "\n", + "onset-to-death period: mean = 17.99, std = 6.08, 95% CI = (8.34, 31.59)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar = 7.0, 0.45\n", + "MU_H = 1 / gamma_dist(hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar, N)\n", + "\n", + "dist_info([1/ETA, 1/MU_H, 1/ETA+1/MU_H], [\"onset-to-hospitalization period\", \"hospitalization-to-death period\", \"onset-to-death period\"], plot=True, colors=['crimson', 'darkgray', 'black'], reverse_plot=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set severity parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the percentage of cases that are asymptomatic. This percentage of case will progress from the pre-symptomatic state to the asymptomatic state, rather than to the symptomatic state." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_ASYMPTOMATIC = 0.25" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the case hospitalization rate. The value used here is approximately the age-frequency-weighted average of age-stratified hospitalization rates for working age adults using data from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_HOSPITALIZED = 0.035" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the case fatality rate for hospitalized cases. The value used here is approximately the age-frequency-weighted average of age stratified hospitalization fatality rates for working age adults, again using figures from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "PCT_FATALITY = 0.08" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set transmission parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#stochastic-network-model-implementation) model considers two modes of disease transmission: a well-mixed mode of [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) and a contact network based mode of [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The propensity for a given individual to become exposed due to global transmission depends on the mean transmissibility of all infectious individuals in the population; the propensity for a given individual to become exposed due to local transmission depends on the pairwise transmissibilities between the focal node and its infectious contacts in the network (see [Transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#transmission) and [Model Equations](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#model-equations) for more information about these calculations). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The transmissibility parameter *β* can be related to the basic reproduction number *R0* (i.e., the expected number of new infections generated by a single infectious individual in a completely susceptible population) by the standard formula: *β = R0𝛾*. *R0* is a more interpretable parameter, so we specify transmissibility in terms of *R0* and then calculate the corresponding *β* values.\n", + "\n", + "First, we generate a distribution of individual *R0* values (i.e., the expected number of new infections generated by a single *particular* infectious individual in a completely susceptible population). Of course, this means that transmissibility is heterogeneous in this population. The coefficient of variation is an important parameter for the individual *R0* distribution in that it tunes the degree of superspreading in the heterogeneous transmissibility. The distribution used in this example has a relatively low coefficient of variation, so most individuals have around the same degree of transmissibility. But a higher coefficient of variation (e.g., 2.0) would give a long right tail in idividual transmissibility representing a small number of individuals contributing many cases while the majority cases contribute less than 1 on average when they are infectious." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Individual R0: mean = 1.98, std = 0.41, 95% CI = (1.32, 2.89)\n", + "\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "R0_mean = 2.0\n", + "R0_coeffvar = 0.2\n", + "\n", + "R0 = gamma_dist(R0_mean, R0_coeffvar, N)\n", + "\n", + "dist_info(R0, \"Individual R0\", bin_size=0.1, plot=True, colors='crimson')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Individuals are ultimately assigned an [*Individual Transmissibility Value*](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#transmissibility-parameters) (*βi*), which are stored in the `beta` attribute of the model object. \n", + "\n", + "The means of the Individual Transmissibility Values for infectious subpopulations are used to calculate the [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) terms. Individual Transmissibility Values may also be used to generate the Pairwise Transmissibility Values used for [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission) terms, as we will specify in a few steps." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "BETA = 1/infectiousPeriod * R0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the stochastic network model, an individual comes into contact with a random individual from the population at large (e.g., in a public space) with probability *p* or with an individual from their set of close contacts with probability *(1-p)*. Transmission that occurs between an individual and the population at large is referred to as [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission), and transmission between an individual and one of their close contacts (network neighbors) is referred to as [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The parameter *p* defines the locality of the network: for *p=0* an individual only interacts with their close contacts, while *p=1* represents a uniformly mixed population.\n", + "\n", + "Here we set *p* to reflect 40% of interactions being with incidental or casual contacts outside their set of close contacts." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "P_GLOBALINTXN = 0.4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Testing, Tracing, & Isolation (TTI) intervention protocol parameters:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we specify the parameters that govern the Testing, Tracing, and Isolation protocol that is implemented by the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). The implementation of this TTI protocol and the interpretation of these parameters is desribed in detail on the [TTI Simulation Loop wiki page](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) (but these parameters are briefly explained as code comments below).\n", + "\n", + "**The scenario set up in the steps that follow involves the entire workforce being tested on a weekly basis, a 2-day test turn around time, 50% of symptomatic individuals self-reporting and getting tested within 1 day of onset, 30% of symptomatics self-isolating even without a positive test, and teams of detected positive cases being proactively isolated. A new exogenous exposures comes into the workplace about once a week.**" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "INTERVENTION_START_PCT_INFECTED = 0/100\n", + "AVERAGE_INTRODUCTIONS_PER_DAY = 1/14 # expected number of new exogenous exposures per day\n", + "\n", + "TESTING_CADENCE = 'weekly' # how often to do testing (other than self-reporting symptomatics who can get tested any day)\n", + "PCT_TESTED_PER_DAY = 1.0 # max daily test allotment defined as a percent of population size\n", + "TEST_FALSENEG_RATE = 'temporal' # test false negative rate, will use FN rate that varies with disease time\n", + "MAX_PCT_TESTS_FOR_SYMPTOMATICS = 1.0 # max percent of daily test allotment to use on self-reporting symptomatics\n", + "MAX_PCT_TESTS_FOR_TRACES = 0.0 # max percent of daily test allotment to use on contact traces\n", + "RANDOM_TESTING_DEGREE_BIAS = 0 # magnitude of degree bias in random selections for testing, none here\n", + "\n", + "PCT_CONTACTS_TO_TRACE = 0.0 # percentage of primary cases' contacts that are traced\n", + "TRACING_LAG = 2 # number of cadence testing days between primary tests and tracing tests\n", + "\n", + "ISOLATION_LAG_SYMPTOMATIC = 1 # number of days between onset of symptoms and self-isolation of symptomatics\n", + "ISOLATION_LAG_POSITIVE = 2 # test turn-around time (TAT): number of days between administration of test and isolation of positive cases\n", + "ISOLATION_LAG_CONTACT = 0 # number of days between a contact being traced and that contact self-isolating\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set intervention compliance parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, we specify the compliance rates (i.e., the percentage of individuals who are compliant) for each intervention type. See the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) documentation for more information about compliance." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "TESTING_COMPLIANCE_RATE_SYMPTOMATIC = 0.5 \n", + "TESTING_COMPLIANCE_RATE_TRACED = 0.0\n", + "TESTING_COMPLIANCE_RATE_RANDOM = 1.0 # Assume employee testing is mandatory, so 100% compliance\n", + "\n", + "TRACING_COMPLIANCE_RATE = 0.0\n", + "\n", + "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL = 0.3\n", + "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE = 0.8 # Isolate teams with a positive member, but suppose 20% of employees are essential workforce\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT = 0.0\n", + "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE = 0.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we randomly assign a `True/False` compliance to each individual according to the rates set above. Individuals whose compliance is set to `True` for a given intervention will participate in that intervention, individuals set to `False` will not." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "TESTING_COMPLIANCE_RANDOM = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_RANDOM)\n", + "TESTING_COMPLIANCE_TRACED = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_TRACED)\n", + "TESTING_COMPLIANCE_SYMPTOMATIC = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_SYMPTOMATIC)\n", + "\n", + "TRACING_COMPLIANCE = (numpy.random.rand(N) < TRACING_COMPLIANCE_RATE)\n", + "\n", + "ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL)\n", + "ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE)\n", + "ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL)\n", + "ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE)\n", + "ISOLATION_COMPLIANCE_POSITIVE_CONTACT = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT)\n", + "ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initializing the model" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\boaz\\PycharmProjects\\seirsplus\\seirsplus\\models.py:2143: RuntimeWarning: invalid value encountered in true_divide\n", + " self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1))\n" + ] + } + ], + "source": [ + "model = ExtSEIRSNetworkModel(G=G_baseline, p=P_GLOBALINTXN,\n", + " beta=BETA, sigma=SIGMA, lamda=LAMDA, gamma=GAMMA, \n", + " gamma_asym=GAMMA, eta=ETA, gamma_H=GAMMA_H, mu_H=MU_H, \n", + " a=PCT_ASYMPTOMATIC, h=PCT_HOSPITALIZED, f=PCT_FATALITY, \n", + " G_Q=G_quarantine, isolation_time=14,\n", + " initE=INIT_EXPOSED)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running the model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set the max simulation time to 300 days." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "T = 300" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Execute the TTI simulation scenario by calling the `run_tti_sim()` function, which runs a custom simulation loop that implements the [TTI Simulation Protocol](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop)." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[INTERVENTIONS @ t = 0.64 (4 (0.50%) infected)]\n" + ] + }, + { + "ename": "NameError", + "evalue": "name 'sort' is not defined", + "output_type": "error", + "traceback": [ + "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[1;31mNameError\u001B[0m Traceback (most recent call last)", + "\u001B[1;32m\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[1;32m----> 1\u001B[1;33m run_tti_sim(model, T, \n\u001B[0m\u001B[0;32m 2\u001B[0m \u001B[0mintervention_start_pct_infected\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mINTERVENTION_START_PCT_INFECTED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maverage_introductions_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mAVERAGE_INTRODUCTIONS_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3\u001B[0m \u001B[0mtesting_cadence\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_CADENCE\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpct_tested_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mPCT_TESTED_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtest_falseneg_rate\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTEST_FALSENEG_RATE\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[0mtesting_compliance_symptomatic\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_SYMPTOMATIC\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_symptomatics\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_SYMPTOMATICS\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m \u001B[0mtesting_compliance_traced\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_TRACED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_traces\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_TRACES\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", + "\u001B[1;32m~\\PycharmProjects\\seirsplus\\seirsplus\\sim_loops.py\u001B[0m in \u001B[0;36mrun_tti_sim\u001B[1;34m(model, T, intervention_start_pct_infected, average_introductions_per_day, testing_cadence, pct_tested_per_day, test_falseneg_rate, testing_compliance_symptomatic, max_pct_tests_for_symptomatics, testing_compliance_traced, max_pct_tests_for_traces, testing_compliance_random, random_testing_degree_bias, tracing_compliance, num_contacts_to_trace, pct_contacts_to_trace, tracing_lag, isolation_compliance_symptomatic_individual, isolation_compliance_symptomatic_groupmate, isolation_compliance_positive_individual, isolation_compliance_positive_groupmate, isolation_compliance_positive_contact, isolation_compliance_positive_contactgroupmate, isolation_lag_symptomatic, isolation_lag_positive, isolation_lag_contact, isolation_groups, cadence_testing_days, cadence_cycle_length, temporal_falseneg_rates, test_priority)\u001B[0m\n\u001B[0;32m 268\u001B[0m \u001B[1;32mif\u001B[0m \u001B[1;34m'last_tested'\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mtest_priority\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 269\u001B[0m \u001B[1;31m# sort the pool according to the time they were last tested, breaking ties randomly\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 270\u001B[1;33m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0msort\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mkey\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mi\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mmodel\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtestedTime\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mi\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcmp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0my\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m*\u001B[0m \u001B[1;36m2\u001B[0m \u001B[1;33m-\u001B[0m \u001B[1;36m1\u001B[0m \u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[0mnumRandomTests\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 271\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 272\u001B[0m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtestingPool\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnumpy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mchoice\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnumRandomTests\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mp\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mtestingPool_degreeWeights\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreplace\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", + "\u001B[1;31mNameError\u001B[0m: name 'sort' is not defined" + ] + } + ], + "source": [ + "run_tti_sim(model, T, \n", + " intervention_start_pct_infected=INTERVENTION_START_PCT_INFECTED, average_introductions_per_day=AVERAGE_INTRODUCTIONS_PER_DAY,\n", + " testing_cadence=TESTING_CADENCE, pct_tested_per_day=PCT_TESTED_PER_DAY, test_falseneg_rate=TEST_FALSENEG_RATE, \n", + " testing_compliance_symptomatic=TESTING_COMPLIANCE_SYMPTOMATIC, max_pct_tests_for_symptomatics=MAX_PCT_TESTS_FOR_SYMPTOMATICS,\n", + " testing_compliance_traced=TESTING_COMPLIANCE_TRACED, max_pct_tests_for_traces=MAX_PCT_TESTS_FOR_TRACES,\n", + " testing_compliance_random=TESTING_COMPLIANCE_RANDOM, random_testing_degree_bias=RANDOM_TESTING_DEGREE_BIAS,\n", + " tracing_compliance=TRACING_COMPLIANCE, pct_contacts_to_trace=PCT_CONTACTS_TO_TRACE, tracing_lag=TRACING_LAG,\n", + " isolation_compliance_symptomatic_individual=ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL, isolation_compliance_symptomatic_groupmate=ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE, \n", + " isolation_compliance_positive_individual=ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL, isolation_compliance_positive_groupmate=ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE,\n", + " isolation_compliance_positive_contact=ISOLATION_COMPLIANCE_POSITIVE_CONTACT, isolation_compliance_positive_contactgroupmate=ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE,\n", + " isolation_lag_symptomatic=ISOLATION_LAG_SYMPTOMATIC, isolation_lag_positive=ISOLATION_LAG_POSITIVE, \n", + " isolation_groups=list(teams.values()),\n", + " test_priority = 'last_tested')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "total percent infected: 0.88%\n", + "total percent fatality: 0.00%\n", + "peak pct hospitalized: 0.00%\n" + ] + } + ], + "source": [ + "results_summary(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualizing the results" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = model.figure_infections(combine_Q_infected=False, plot_Q_R='stacked', plot_Q_S='stacked')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file From 9800f6f3001f72d60471b2ce3faa9f75c1752921 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 18 Aug 2020 13:19:25 -0400 Subject: [PATCH 006/117] Remove testing notebook from git tracking --- ...EIRS_Workplace_TTI_Demo_timePriority.ipynb | 853 ------------------ 1 file changed, 853 deletions(-) delete mode 100644 examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb diff --git a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb b/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb deleted file mode 100644 index 45a2eec..0000000 --- a/examples/Extended_SEIRS_Workplace_TTI_Demo_timePriority.ipynb +++ /dev/null @@ -1,853 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Extended SEIRS Workplace TTI Demo\n", - "\n", - "**In this demonstration we will explore the effect of testing, tracing, and isolation interventions on disease transmission in a workplace setting with a realistic contact network.**\n", - "\n", - "This notebook provides a demonstration of the functionality of the [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description) and the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). This notebook also offers a sandbox for starting to explore TTI scenarios of your own. \n", - "For a more thorough walkthrough of the model, simulation loop, and use of this package, refer to the [SEIRS+ Wiki](https://github.com/ryansmcgee/seirsplus/wiki)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Installing and importing the model code\n", - "\n", - "All of the code needed to run the model is imported from the ```models``` module of this package.\n", - "\n", - "In this demo we will also use features from the `networks`, `sim_loops`, and `utilities` modules.\n", - "\n", - "#### Install the package using ```pip```\n", - "The package can be installed on your machine by entering this in the command line:\n", - "\n", - "```pip install seirsplus```\n", - "\n", - "Then, the ```models```, `networks`, `sim_loops`, and `utilities` modules can be imported as shown here:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from seirsplus.models import *\n", - "from seirsplus.networks import *\n", - "from seirsplus.sim_loops import *\n", - "from seirsplus.utilities import *\n", - "import networkx\n", - "import matplotlib.pyplot as pyplot" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### *Alternatively, manually copy the code to your machine*\n", - "*You can use the model code without installing a package by copying the ```models.py``` module file to a directory on your machine. For some of the features used in this demo you will also need the `networks`, `sim_loops`, and `utilities` modules. In this case, the easiest way to use the modules is to place your scripts in the same directory as the modules, and import the modules as shown here:*\n", - "```python\n", - "from models import *\n", - "from networks import *\n", - "from sim_loops import *\n", - "from utilities import *\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Set basic parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the workplace size and structure" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "NUM_COHORTS = 4\n", - "NUM_NODES_PER_COHORT = 200\n", - "NUM_TEAMS_PER_COHORT = 10\n", - "\n", - "MEAN_INTRACOHORT_DEGREE = 6\n", - "PCT_CONTACTS_INTERCOHORT = 0.1" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "N = NUM_NODES_PER_COHORT*NUM_COHORTS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we set the initial prevalence to be a single case" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "INIT_EXPOSED = 4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------\n", - "\n", - "## Specifying contact networks\n", - "\n", - "This package implements models epidemic dynamics for populations with a structured [contact network](Extended-SEIRS-Model-Description#contact-networks). Individuals are represented as nodes in a network, and parameters, contacts, and interventions can be specified on a targeted individual basis. A graph specifying the contact network must be specified, where each node represents an individual in the population and edges connect individuals who have regular interactions.\n", - "\n", - "This model also supports scenarios where individuals enter quarantine states in which their parameters and interactions may be different from baseline, and a separate graph defining the interactions for individuals in quarantine can be specified (i.e., the [quarantine contact network](Extended-SEIRS-Model-Description#quarantine-contacts)).\n", - "\n", - "### Workplace Contact Network\n", - "\n", - "Here we use the [**demographic community network generator**](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#workplace-network) defined in the SEIRS+ package. This function generates a contact network that resembles workplaces and other multi-level modular populations.\n", - "\n", - "[FARZ](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#farz-networks) network layers are generated to represent cohorts of employees (e.g., departments, floors, shifts). FARZ networks have a tunable community structure, so each cohort includes some number of communities, which can be thought to represent teams (i.e., groups of employees that work closely with each other). Employees may belong to more than one team (specified by a FARZ parameter), but employees belong to only one cohort. An employee's intra-team and intra-cohort contacts are defined by the FARZ cohort network they belong to. A specified percentage of each employee's total number of workplace contacts can be with individuals from other cohorts. An employee's inter-cohort contacts are drawn randomly from the pool of individuals outside their own cohort. \n", - "\n", - "The number of cohorts, number of employees per cohort, number of teams per cohort, number of teams employees belong to, mean intra-cohort degree, percent of within- and between-team connections, and percent of intra- and inter-cohort connections can be controlled with the arguments to the `generate_demographic_contact_network()` function (some of which are passed as [parameters to the FARZ generator](https://github.com/ryansmcgee/seirsplus/wiki/Network-Generation#FARZ-parameters)).\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Baseline:\n", - "Degree: mean = 11.11, std = 8.41, 95% CI = (1.00, 29.00)\n", - " coeff var = 0.76\n", - "Assortativity: 0.28\n", - "Clustering coeff: 0.24\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "G_baseline, cohorts, teams = generate_workplace_contact_network(\n", - " num_cohorts=NUM_COHORTS, num_nodes_per_cohort=NUM_NODES_PER_COHORT, \n", - " num_teams_per_cohort=NUM_TEAMS_PER_COHORT,\n", - " mean_intracohort_degree=MEAN_INTRACOHORT_DEGREE, \n", - " pct_contacts_intercohort=PCT_CONTACTS_INTERCOHORT,\n", - " farz_params={'alpha':5.0, 'gamma':5.0, 'beta':0.5, 'r':1, 'q':0.0, 'phi':10, \n", - " 'b':0, 'epsilon':1e-6, 'directed': False, 'weighted': False})\n", - "\n", - "network_info(G_baseline, \"Baseline\", plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we define the quarantine contact network to be an empty network (i.e., no connections). This represents an assumption that an employee that is in a quarantine state makes no contact with anyone from their workplace." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "G_quarantine = networkx.classes.function.create_empty_copy(G_baseline)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Specifying parameters\n", - "\n", - "**_The parameter values used in this notebook reflect rough estimates of parameter values for the COVID-19 epidemic (as of 9 Aug 2020)._**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set disease progression rate parameters:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Parameter values are assigned to members of the population on an individual basis. Parameter values can be [specified to the `ExtSEIRSNetworkModel`](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#specifying-parameters) by providing a list of values that gives the *N* values to assign to each individual. The population may be either homogeneous or heterogeneous for a given parameter at the user's discretion. \n", - "\n", - "**Here we generate distributions of values for each parameter, thus specifying a realistically heterogeneous population.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected latent periods (time in Exposed state) and presymptomatic periods (time in Pre-symptomatic infectious state). The `sigma` and `lamda` rates are calculated as the inverse of the expected exposed and pre-symptomatic periods assigned to each individual, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "latent period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", - "\n", - "pre-symptomatic period: mean = 2.94, std = 1.72, 95% CI = (0.64, 7.12)\n", - "\n", - "total incubation period: mean = 5.14, std = 2.03, 95% CI = (2.17, 10.02)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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WVlccsklQUxff/013//+9/nNb37D+vXrWbJkyRnlOwBWrlzJr371KzZu3MiOHTtYsGABBw4cKPHzLPjchw4dGiw7evQoI0eOZN68ecEcE08//TRHjx5l1KhR/PnPf2b58uX8/e9/L/0vQRGUFESqqdatW9O7d28A7rjjDjIzM4P3vv/97wPw/vvvs3nzZnr37k1qaiqzZs0KCuYV1r17d5577jkmTpzIxo0bqV+/PhdeeCFXX301r732Glu3buX48eOkpKQA0K5dO1JSUqhRowaXX34511xzDWZGSkrKKWW3Bw0aRN26dWnSpAn9+/cPziIKy8zM5M477wROLZsN0L9/f+rXr0/Tpk1p2LAhN910E8Ap7WzatIkrr7ySlJQUZs+ezYcfflji5/bRRx/RokULunfvDkCDBg2oWfPMnvj09HS+9a1vkZCQwLBhw8jMzDzr51nwuZ/eXrt27bj00ksBGDFiBMuWLWPr1q20a9eO9u3bY2bccccdJcYdK11TEKmmiipbXaCgRLW7c9111zF37txT1v3ggw+CEtqTJk0KJtx5/fXXufPOOxk3bhx33XUX9957L0888QQdOnQIzhKAU0pt16hRI3hdo0YNTpw4EVOMBUqq3xZLOyNHjmThwoV06dKFjIyMs95p7e4xleMurix4UZ9ngaJKg5d3WXCdKYhUU7t372bFiki9yblz59KnT58z1unZsyd/+9vf2L59OwBfffUVH3/8MT169CArK4usrCwGDhzIrl27aNasGaNGjeKee+5h7dq1APTo0YNPPvmEOXPmBBPqlMarr77K0aNHyc3NZenSpXTv3v2MctzFlc2O1aFDh2jRogXHjx8P9gPFl/3u0KEDe/bsYdWqVcH2hRNZgZUrV7Jz505OnjzJvHnz6NOnT7GfZ0k6dOhAdnZ2sM0f//hHrrrqKjp06MDOnTvZsWMHQLGJprR0piBSEVyQGBkxVJb7O4uOHTsya9Ys7rvvPtq3b8/9999/xjpNmzYlIyODYcOGBRc3H3/88aAro8DSpUuZMmUKtWrVIjExMeivB7j99tvJysrioosuKvVhpKen873vfY/du3fzs5/9jJYtW9K0aVNq1qxJly5dGDlyZLFls2P1n//5n/To0YO2bduSkpISJIKhQ4cyatQofvvb3wYXfAEuuOAC5s2bx4MPPkheXh5169ZlyZIlJCae+pn36tWL8ePHs3HjxuCic40aNWL6PAurU6cOzz33HLfddhsnTpyge/fujBkzhtq1azNjxgy+973v0aRJE/r06cOmTZtK8/EWqdxKZ4dBpbOjVDq70ol36ezs7Oxg0vuwDRgwgIcffphrrimy5FmxJk6cSGJiIv/6r/8aUmThWbp0KVOnTj3rPBDlocKUzhaR6u3gwYNceuml1K1bt9QJQeJH3Uci1VBSUlLoZwnf+MY3ztpfXpKJEyeWXTDlrF+/fvTr1y/eYZwTnSmIiEhASUFERAJKCiIiElBSEBGRgJKCSAWQm5vLrl27yuyRm1ty6eyDBw+eUuuoOLGWqc7OziY5OfmM5Xv27GHIkCFn3b40imurJBkZGezZsyd4fe+9955SFjuevvvd73Lw4MGY1584cSJTp04NLR6NPhKpAA4fPnxKIbjzNWHCBBo3Lr50dkFSGDt2bIn7Od8y1S1btjzlxq94ycjIIDk5mZYtWwLwhz/8Ic4RRcpXuDtvvPFGvEM5hc4URKqh8ePHs2PHDlJTUxk3bhzuzrhx40hOTiYlJYV58+YF6xUuU52dnc2VV15Jt27d6NatG++9916J7RT+qz4jI4NbbrmFG264gfbt2/Nv//ZvwXpvvvkm3bp1o0uXLsE9Daf/RZycnBwUsTtx4kSRZb8nTZpE9+7dSU5OZvTo0bg7L730EqtXr2b48OGkpqaSl5dHv379KLjxde7cuaSkpJCcnMwjjzwStJeYmMhjjz1Gly5d6NmzJ5999tkZx1dceW+AKVOm0L17dzp37szPf/7z4PPo2LEjY8eOpVu3bnzyySckJSVx4MABAKZNm0ZycjLJycn8+te/DvY1efJkLrvsMq699lo++uijEj/z86WkIFINPfnkk1xyySVkZWUxZcoUFixYEJS9XrJkCePGjWPv3r1nlKlu1qwZb731FmvXrmXevHk89NBDpWo3KysrKAE9b948PvnkE/bv38+oUaN4+eWXWb9+PS+++OJZ91Nc2e8HHniAVatWsWnTJvLy8njttdcYMmQIaWlpzJ49m6ysrFPKXO/Zs4dHHnmEd955h6ysLFatWsXChQsBOHLkCD179mT9+vX07dv3lC/8wooq77148WK2bdvGypUrycrKYs2aNSxbtiyI/a677mLdunW0bfvPSgRr1qzhueee44MPPuD999/nmWeeYd26daxZs4YXXniBdevWsWDBgqDmUliUFESEzMxMhg0bRkJCAs2bN+eqq64q8svn+PHjjBo1ipSUFG677bZS98tfc801NGzYkDp16tCpUyd27drF+++/T9++fWnXrh0AjRo1Out+iiv7/e6779KjRw9SUlJ45513zloGe9WqVfTr1y+opzR8+PDgy/uCCy4Iprf89re/fUpJ78KKKu+9ePFiFi9eTNeuXenWrRtbt25l27ZtALRt25aePXuesZ/MzEwGDx7MhRdeSGJiIrfccgvLly9n+fLlDB48mHr16tGgQQMGDhx41s/nfOiagoiUWJ65sOnTp9O8eXPWr1/PyZMnqVOnTqnaKVyoLiEhgRMnThRbirpmzZrBbGVAMHEOFF2W+ujRo4wdO5bVq1fTunVrJk6ceMo2RSnpuGvVqhW0UxBrUYorkf3oo48G5cULZGdnF1ke+2yxhFEiuzg6U6gqvt4V/iO/6k4GX90UVX563rx55Ofns3//fpYtW0Z6evoZ633xxRe0aNGCGjVq8Mc//pH8/PzzjqVXr1789a9/ZefOnQDBNJlJSUlBCe61a9cG70PRZb8LEkCTJk04fPjwKRe4iyuD3aNHD/76179y4MAB8vPzmTt3LldddVWp4i+qvPf111/PzJkzg6k2P/30U/bt21fifvr27cvChQv56quvOHLkCK+88gpXXnklffv25ZVXXiEvL49Dhw7x5z//uVTxlVZoZwpm1hp4HvgmcBKY4e6/MbOJwChgf3TVCe7+RnSbR4F7gHzgIXf/S1jxVSmeB59PD7+dRhMg4fwng5czJSYmMmFC2ZXOPr2M8+kaN25M7969SU5O5sYbb+SXv/wlK1asoEuXLpgZv/zlL/nmN79J48aNzyhTfeutt/Liiy/Sv3//Yv/qLY2mTZsyY8YMbrnlFk6ePBlct7j11lt5/vnnSU1NpXv37qeUly6q7He9evWCrq2kpKRgZjSITKQzZswY6tatGyQTgBYtWvCLX/yC/v374+5897vfZdCgQaWKv6jy3i1btmTLli306tULiPx7/OlPfyIhIaHY/XTr1o2RI0eSnp4ORIbNdu3aFYjMyJaamkrbtm258sorSxVfaYVWOtvMWgAt3H2tmdUH1gA3A7cDh9196mnrdwLmAulAS2AJcKm7F/uniEpnR130cPklBZXoLhPxLp0tZaMy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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "latentPeriod_mean, latentPeriod_coeffvar = 3.0, 0.6\n", - "SIGMA = 1 / gamma_dist(latentPeriod_mean, latentPeriod_coeffvar, N)\n", - "\n", - "presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar = 2.2, 0.5\n", - "LAMDA = 1 / gamma_dist(presymptomaticPeriod_mean, presymptomaticPeriod_coeffvar, N)\n", - "\n", - "dist_info([1/LAMDA, 1/SIGMA, 1/LAMDA+1/SIGMA], [\"latent period\", \"pre-symptomatic period\", \"total incubation period\"], plot=True, colors=['gold', 'darkorange', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected (a)symptomatic periods (time in symptomatic or asymptomatic state). The `gamma` rates are calculated as the inverse of the expected (a)symptomatic periods assigned to each individual. \n", - "\n", - "The expected total infectious period for each individual is the sum of their expected pre-symptomatic and (a)symptomatic periods." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pre-symptomatic period: mean = 2.19, std = 1.01, 95% CI = (0.71, 4.51)\n", - "\n", - "(a)symptomatic period: mean = 4.01, std = 1.54, 95% CI = (1.64, 7.36)\n", - "\n", - "total infectious period: mean = 6.20, std = 1.87, 95% CI = (3.09, 10.45)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "symptomaticPeriod_mean, symptomaticPeriod_coeffvar = 4.0, 0.4\n", - "GAMMA = 1 / gamma_dist(symptomaticPeriod_mean, symptomaticPeriod_coeffvar, N)\n", - "\n", - "infectiousPeriod = 1/LAMDA + 1/GAMMA\n", - "\n", - "dist_info([1/LAMDA, 1/GAMMA, 1/LAMDA+1/GAMMA], [\"pre-symptomatic period\", \"(a)symptomatic period\", \"total infectious period\"], plot=True, colors=['darkorange', 'crimson', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of expected onset-to-hospitalization periods (time in symptomatic state before entering hospitalized state for those with severe cases) and hospitalization-to-discharge periods (time in hospitalized state for those with non-fatal cases). The `eta` and `gamma_H` rates are calculated as the inverse of the expected onset-to-hospitalization periods and hospitalization-to-discharge periods assigned to each individual, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", - "\n", - "hospitalization-to-discharge period: mean = 11.38, std = 5.29, 95% CI = (3.49, 23.54)\n", - "\n", - "onset-to-discharge period: mean = 22.51, std = 7.16, 95% CI = (10.62, 39.43)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3de3wU5bnA8d+TEAzITQE9QYTIOVzEEAOGqxQIVFChXBRQDigXIdADUmiLUKyCqICtRyPWUwpYpGopiHIR23ojiFyEgERALFo0UCRyCUIJIeSy7/ljN+smOxs2Ibub3Xm+n08+yc7szDwZwpPJM+88rxhjUEopZR9RoQ5AKaVUcGniV0opm9HEr5RSNqOJXymlbEYTv1JK2UyNUAfgj0aNGpn4+PhQh6GUUmFlz549p40xjcsuD4vEHx8fz+7du0MdhlJKhRUROWK1XEs9SillM5r4lVLKZjTxK6WUzYRFjV9FtsLCQo4dO0Z+fn6oQ1EqLMXGxtK0aVNiYmL8er8mfhVyx44do27dusTHxyMioQ5HqbBijCEnJ4djx45x0003+bWNlnpUyOXn59OwYUNN+kpVgojQsGHDCv3FrIlfVQua9JWqvIr+/9HEr5RSNqOJX1U7xd+fo/Bf31XZR/H350L6/WRmZvLXv/7V5/q0tDTy8vIqtM/NmzczYMCAKw3Np927dzN16lT3sbZv337ZbV555RWmTJkCwOLFi/nTn/5U4eOWPVZl9xMIjz/+OB988IHf7w/0v9GV0Ju71Vzx9+dw5F70Wi4xNTCFRZbbRNWpRfQ19QMdWsA4ci9yNu3VKttfg2kPhPR8ZGZmsnv3bu6++27L9WlpaYwaNYratWsHOTLfkpOTSU5OBpwJrE6dOnTr1s3v7SdNmlSp45Y9VmX3U9WKi4uZN29eqMOoMnrFX82VJMGyH8XnL1guP5v2quUvClW+5557joSEBBISEkhLSwMgKyuLm2++mQkTJnDLLbfQt29fLl50nttFixbRtm1bEhMTuf/++wG4cOEC48aNo2PHjrRv357169dTUFDA448/zqpVq0hKSmLVqlWljrto0SKOHz9OSkoKKSkpAKxcuZJ27dqRkJDAzJkzfcacm5vL0KFDadOmDSNHjqRkNr0PP/yQ9u3b065dO8aNG8elS5cAmDVrljvmX/7ylwCMGTOGSZMm8aMf/YhWrVqxceNG4Ier1aysLBYvXszzzz9PUlISH3/8MW+//TadO3emffv2/PjHP+bEiRNesc2dO5dnn32W48ePk5SU5P6Ijo7myJEjlvuwOlbJfsD5C7RLly4kJiYyZMgQvv/+ewB69erFzJkz6dSpE61ateLjjz/2imfz5s306NGDIUOG0LZtWyZNmoTD4QDgvffeo2vXrnTo0IFhw4aRm5sLOFvFzJs3j+7du/PGG28wZswY1qxZU+45/vvf/06bNm3o3r07b731ls9/u1DTxK9sb8+ePSxfvpydO3fyySefsHTpUvbu3QvAV199xeTJk/n8889p0KABb775JgALFy5k79697Nu3j8WLFwPw9NNP07t3bzIyMkhPT2fGjBkUFhYyb9487rvvPjIzM7nvvvtKHXvq1Kk0adKE9PR00tPTOX78ODNnzmTTpk1kZmaSkZHBunXrLOPeu3cvaWlpHDx4kK+//ppt27aRn5/PmDFjWLVqFfv376eoqIjf//73nDlzhrVr1/L555+zb98+fv3rX7v3k5WVxUcffcQ777zDpEmTSo0OiY+PZ9KkSUyfPp3MzEx+9KMf0b17dz755BP27t3L/fffz29+8xuf57ZJkyZkZmaSmZnJhAkTuPfee2nevLnlPqyO5enBBx/kmWeeYd++fbRr144nnnjCva6oqIhdu3aRlpZWarmnXbt28b//+7/s37+fw4cP89Zbb3H69GmeeuopPvjgAz799FOSk5N57rnn3NvExsaydetW9y93wOc5zs/PZ8KECbz99tt8/PHHfPfddz7PS6hpqcdmfJWOIPxLRJW1detWhgwZwtVXXw3APffcw8cff8zAgQO56aabSEpKAuC2224jKysLgMTEREaOHMngwYMZPHgw4Lxy3LBhg/sKNT8/n6NHj1YoloyMDHr16kXjxs6GiiNHjmTLli3uY3jq1KkTTZs2BSApKYmsrCzq1q3LTTfdRKtWrQAYPXo0L730ElOmTCE2Npbx48fTv3//UrXn4cOHExUVRcuWLWnRogX/+Mc/yo3x2LFj3HfffWRnZ1NQUODX2PFt27axbNky99V4Rfdx7tw5zp49S8+ePd3f17Bhw9zr77nnHqD0v1FZnTp1okWLFgCMGDGCrVu3Ehsby8GDB7n99tsBKCgooGvXru5tyv6iBjh06JDl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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar = 11.0, 0.45\n", - "ETA = 1 / gamma_dist(onsetToHospitalizationPeriod_mean, onsetToHospitalizationPeriod_coeffvar, N)\n", - "\n", - "hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar = 11.0, 0.45\n", - "GAMMA_H = 1 / gamma_dist(hospitalizationToDischargePeriod_mean, hospitalizationToDischargePeriod_coeffvar, N)\n", - "\n", - "dist_info([1/ETA, 1/GAMMA_H, 1/ETA+1/GAMMA_H], [\"onset-to-hospitalization period\", \"hospitalization-to-discharge period\", \"onset-to-discharge period\"], plot=True, colors=['crimson', 'violet', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate a distribution of hospitalization-to-death periods (time in hospitalized state for those with fatal cases). The `mu_H` rates are calculated as the inverse of the expected hospitalization-to-death periods." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "onset-to-hospitalization period: mean = 11.12, std = 5.10, 95% CI = (3.72, 22.73)\n", - "\n", - "hospitalization-to-death period: mean = 6.87, std = 3.10, 95% CI = (2.01, 13.61)\n", - "\n", - "onset-to-death period: mean = 17.99, std = 6.08, 95% CI = (8.34, 31.59)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar = 7.0, 0.45\n", - "MU_H = 1 / gamma_dist(hospitalizationToDeathPeriod_mean, hospitalizationToDeathPeriod_coeffvar, N)\n", - "\n", - "dist_info([1/ETA, 1/MU_H, 1/ETA+1/MU_H], [\"onset-to-hospitalization period\", \"hospitalization-to-death period\", \"onset-to-death period\"], plot=True, colors=['crimson', 'darkgray', 'black'], reverse_plot=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set severity parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the percentage of cases that are asymptomatic. This percentage of case will progress from the pre-symptomatic state to the asymptomatic state, rather than to the symptomatic state." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_ASYMPTOMATIC = 0.25" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the case hospitalization rate. The value used here is approximately the age-frequency-weighted average of age-stratified hospitalization rates for working age adults using data from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_HOSPITALIZED = 0.035" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the case fatality rate for hospitalized cases. The value used here is approximately the age-frequency-weighted average of age stratified hospitalization fatality rates for working age adults, again using figures from [Verity et al. (2020)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext)." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "PCT_FATALITY = 0.08" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set transmission parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The [Extended SEIRS Network Model](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#stochastic-network-model-implementation) model considers two modes of disease transmission: a well-mixed mode of [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) and a contact network based mode of [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The propensity for a given individual to become exposed due to global transmission depends on the mean transmissibility of all infectious individuals in the population; the propensity for a given individual to become exposed due to local transmission depends on the pairwise transmissibilities between the focal node and its infectious contacts in the network (see [Transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#transmission) and [Model Equations](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#model-equations) for more information about these calculations). " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The transmissibility parameter *β* can be related to the basic reproduction number *R0* (i.e., the expected number of new infections generated by a single infectious individual in a completely susceptible population) by the standard formula: *β = R0𝛾*. *R0* is a more interpretable parameter, so we specify transmissibility in terms of *R0* and then calculate the corresponding *β* values.\n", - "\n", - "First, we generate a distribution of individual *R0* values (i.e., the expected number of new infections generated by a single *particular* infectious individual in a completely susceptible population). Of course, this means that transmissibility is heterogeneous in this population. The coefficient of variation is an important parameter for the individual *R0* distribution in that it tunes the degree of superspreading in the heterogeneous transmissibility. The distribution used in this example has a relatively low coefficient of variation, so most individuals have around the same degree of transmissibility. But a higher coefficient of variation (e.g., 2.0) would give a long right tail in idividual transmissibility representing a small number of individuals contributing many cases while the majority cases contribute less than 1 on average when they are infectious." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Individual R0: mean = 1.98, std = 0.41, 95% CI = (1.32, 2.89)\n", - "\n" - ] - }, - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "R0_mean = 2.0\n", - "R0_coeffvar = 0.2\n", - "\n", - "R0 = gamma_dist(R0_mean, R0_coeffvar, N)\n", - "\n", - "dist_info(R0, \"Individual R0\", bin_size=0.1, plot=True, colors='crimson')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Individuals are ultimately assigned an [*Individual Transmissibility Value*](https://github.com/ryansmcgee/seirsplus/wiki/ExtSEIRSNetworkModel-Class#transmissibility-parameters) (*βi*), which are stored in the `beta` attribute of the model object. \n", - "\n", - "The means of the Individual Transmissibility Values for infectious subpopulations are used to calculate the [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission) terms. Individual Transmissibility Values may also be used to generate the Pairwise Transmissibility Values used for [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission) terms, as we will specify in a few steps." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "BETA = 1/infectiousPeriod * R0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the stochastic network model, an individual comes into contact with a random individual from the population at large (e.g., in a public space) with probability *p* or with an individual from their set of close contacts with probability *(1-p)*. Transmission that occurs between an individual and the population at large is referred to as [global transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#global-transmission), and transmission between an individual and one of their close contacts (network neighbors) is referred to as [local transmission](https://github.com/ryansmcgee/seirsplus/wiki/Extended-SEIRS-Model-Description#local-transmission). The parameter *p* defines the locality of the network: for *p=0* an individual only interacts with their close contacts, while *p=1* represents a uniformly mixed population.\n", - "\n", - "Here we set *p* to reflect 40% of interactions being with incidental or casual contacts outside their set of close contacts." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "P_GLOBALINTXN = 0.4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set Testing, Tracing, & Isolation (TTI) intervention protocol parameters:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we specify the parameters that govern the Testing, Tracing, and Isolation protocol that is implemented by the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop). The implementation of this TTI protocol and the interpretation of these parameters is desribed in detail on the [TTI Simulation Loop wiki page](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) (but these parameters are briefly explained as code comments below).\n", - "\n", - "**The scenario set up in the steps that follow involves the entire workforce being tested on a weekly basis, a 2-day test turn around time, 50% of symptomatic individuals self-reporting and getting tested within 1 day of onset, 30% of symptomatics self-isolating even without a positive test, and teams of detected positive cases being proactively isolated. A new exogenous exposures comes into the workplace about once a week.**" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "INTERVENTION_START_PCT_INFECTED = 0/100\n", - "AVERAGE_INTRODUCTIONS_PER_DAY = 1/14 # expected number of new exogenous exposures per day\n", - "\n", - "TESTING_CADENCE = 'weekly' # how often to do testing (other than self-reporting symptomatics who can get tested any day)\n", - "PCT_TESTED_PER_DAY = 1.0 # max daily test allotment defined as a percent of population size\n", - "TEST_FALSENEG_RATE = 'temporal' # test false negative rate, will use FN rate that varies with disease time\n", - "MAX_PCT_TESTS_FOR_SYMPTOMATICS = 1.0 # max percent of daily test allotment to use on self-reporting symptomatics\n", - "MAX_PCT_TESTS_FOR_TRACES = 0.0 # max percent of daily test allotment to use on contact traces\n", - "RANDOM_TESTING_DEGREE_BIAS = 0 # magnitude of degree bias in random selections for testing, none here\n", - "\n", - "PCT_CONTACTS_TO_TRACE = 0.0 # percentage of primary cases' contacts that are traced\n", - "TRACING_LAG = 2 # number of cadence testing days between primary tests and tracing tests\n", - "\n", - "ISOLATION_LAG_SYMPTOMATIC = 1 # number of days between onset of symptoms and self-isolation of symptomatics\n", - "ISOLATION_LAG_POSITIVE = 2 # test turn-around time (TAT): number of days between administration of test and isolation of positive cases\n", - "ISOLATION_LAG_CONTACT = 0 # number of days between a contact being traced and that contact self-isolating\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Set intervention compliance parameters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First, we specify the compliance rates (i.e., the percentage of individuals who are compliant) for each intervention type. See the [TTI Simulation Loop](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop) documentation for more information about compliance." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "TESTING_COMPLIANCE_RATE_SYMPTOMATIC = 0.5 \n", - "TESTING_COMPLIANCE_RATE_TRACED = 0.0\n", - "TESTING_COMPLIANCE_RATE_RANDOM = 1.0 # Assume employee testing is mandatory, so 100% compliance\n", - "\n", - "TRACING_COMPLIANCE_RATE = 0.0\n", - "\n", - "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL = 0.3\n", - "ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE = 0.8 # Isolate teams with a positive member, but suppose 20% of employees are essential workforce\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT = 0.0\n", - "ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE = 0.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we randomly assign a `True/False` compliance to each individual according to the rates set above. Individuals whose compliance is set to `True` for a given intervention will participate in that intervention, individuals set to `False` will not." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "TESTING_COMPLIANCE_RANDOM = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_RANDOM)\n", - "TESTING_COMPLIANCE_TRACED = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_TRACED)\n", - "TESTING_COMPLIANCE_SYMPTOMATIC = (numpy.random.rand(N) < TESTING_COMPLIANCE_RATE_SYMPTOMATIC)\n", - "\n", - "TRACING_COMPLIANCE = (numpy.random.rand(N) < TRACING_COMPLIANCE_RATE)\n", - "\n", - "ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_INDIVIDUAL)\n", - "ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_SYMPTOMATIC_GROUPMATE)\n", - "ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_INDIVIDUAL)\n", - "ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_GROUPMATE)\n", - "ISOLATION_COMPLIANCE_POSITIVE_CONTACT = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACT)\n", - "ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE = (numpy.random.rand(N) < ISOLATION_COMPLIANCE_RATE_POSITIVE_CONTACTGROUPMATE)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initializing the model" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\boaz\\PycharmProjects\\seirsplus\\seirsplus\\models.py:2143: RuntimeWarning: invalid value encountered in true_divide\n", - " self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1))\n" - ] - } - ], - "source": [ - "model = ExtSEIRSNetworkModel(G=G_baseline, p=P_GLOBALINTXN,\n", - " beta=BETA, sigma=SIGMA, lamda=LAMDA, gamma=GAMMA, \n", - " gamma_asym=GAMMA, eta=ETA, gamma_H=GAMMA_H, mu_H=MU_H, \n", - " a=PCT_ASYMPTOMATIC, h=PCT_HOSPITALIZED, f=PCT_FATALITY, \n", - " G_Q=G_quarantine, isolation_time=14,\n", - " initE=INIT_EXPOSED)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Running the model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set the max simulation time to 300 days." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "T = 300" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Execute the TTI simulation scenario by calling the `run_tti_sim()` function, which runs a custom simulation loop that implements the [TTI Simulation Protocol](https://github.com/ryansmcgee/seirsplus/wiki/TTI-Simulation-Loop)." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[INTERVENTIONS @ t = 0.64 (4 (0.50%) infected)]\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'sort' is not defined", - "output_type": "error", - "traceback": [ - "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[1;31mNameError\u001B[0m Traceback (most recent call last)", - "\u001B[1;32m\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[1;32m----> 1\u001B[1;33m run_tti_sim(model, T, \n\u001B[0m\u001B[0;32m 2\u001B[0m \u001B[0mintervention_start_pct_infected\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mINTERVENTION_START_PCT_INFECTED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maverage_introductions_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mAVERAGE_INTRODUCTIONS_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 3\u001B[0m \u001B[0mtesting_cadence\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_CADENCE\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpct_tested_per_day\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mPCT_TESTED_PER_DAY\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtest_falseneg_rate\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTEST_FALSENEG_RATE\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[0mtesting_compliance_symptomatic\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_SYMPTOMATIC\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_symptomatics\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_SYMPTOMATICS\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m \u001B[0mtesting_compliance_traced\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mTESTING_COMPLIANCE_TRACED\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_pct_tests_for_traces\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mMAX_PCT_TESTS_FOR_TRACES\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\PycharmProjects\\seirsplus\\seirsplus\\sim_loops.py\u001B[0m in \u001B[0;36mrun_tti_sim\u001B[1;34m(model, T, intervention_start_pct_infected, average_introductions_per_day, testing_cadence, pct_tested_per_day, test_falseneg_rate, testing_compliance_symptomatic, max_pct_tests_for_symptomatics, testing_compliance_traced, max_pct_tests_for_traces, testing_compliance_random, random_testing_degree_bias, tracing_compliance, num_contacts_to_trace, pct_contacts_to_trace, tracing_lag, isolation_compliance_symptomatic_individual, isolation_compliance_symptomatic_groupmate, isolation_compliance_positive_individual, isolation_compliance_positive_groupmate, isolation_compliance_positive_contact, isolation_compliance_positive_contactgroupmate, isolation_lag_symptomatic, isolation_lag_positive, isolation_lag_contact, isolation_groups, cadence_testing_days, cadence_cycle_length, temporal_falseneg_rates, test_priority)\u001B[0m\n\u001B[0;32m 268\u001B[0m \u001B[1;32mif\u001B[0m \u001B[1;34m'last_tested'\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mtest_priority\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 269\u001B[0m \u001B[1;31m# sort the pool according to the time they were last tested, breaking ties randomly\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 270\u001B[1;33m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0msort\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mkey\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mi\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mmodel\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtestedTime\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mi\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcmp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mlambda\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0my\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mx\u001B[0m\u001B[1;33m-\u001B[0m\u001B[0my\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m*\u001B[0m \u001B[1;36m2\u001B[0m \u001B[1;33m-\u001B[0m \u001B[1;36m1\u001B[0m \u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[0mnumRandomTests\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 271\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 272\u001B[0m \u001B[0mrandomSelection\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtestingPool\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnumpy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mrandom\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mchoice\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtestingPool\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnumRandomTests\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mp\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mtestingPool_degreeWeights\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreplace\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;31mNameError\u001B[0m: name 'sort' is not defined" - ] - } - ], - "source": [ - "run_tti_sim(model, T, \n", - " intervention_start_pct_infected=INTERVENTION_START_PCT_INFECTED, average_introductions_per_day=AVERAGE_INTRODUCTIONS_PER_DAY,\n", - " testing_cadence=TESTING_CADENCE, pct_tested_per_day=PCT_TESTED_PER_DAY, test_falseneg_rate=TEST_FALSENEG_RATE, \n", - " testing_compliance_symptomatic=TESTING_COMPLIANCE_SYMPTOMATIC, max_pct_tests_for_symptomatics=MAX_PCT_TESTS_FOR_SYMPTOMATICS,\n", - " testing_compliance_traced=TESTING_COMPLIANCE_TRACED, max_pct_tests_for_traces=MAX_PCT_TESTS_FOR_TRACES,\n", - " testing_compliance_random=TESTING_COMPLIANCE_RANDOM, random_testing_degree_bias=RANDOM_TESTING_DEGREE_BIAS,\n", - " tracing_compliance=TRACING_COMPLIANCE, pct_contacts_to_trace=PCT_CONTACTS_TO_TRACE, tracing_lag=TRACING_LAG,\n", - " isolation_compliance_symptomatic_individual=ISOLATION_COMPLIANCE_SYMPTOMATIC_INDIVIDUAL, isolation_compliance_symptomatic_groupmate=ISOLATION_COMPLIANCE_SYMPTOMATIC_GROUPMATE, \n", - " isolation_compliance_positive_individual=ISOLATION_COMPLIANCE_POSITIVE_INDIVIDUAL, isolation_compliance_positive_groupmate=ISOLATION_COMPLIANCE_POSITIVE_GROUPMATE,\n", - " isolation_compliance_positive_contact=ISOLATION_COMPLIANCE_POSITIVE_CONTACT, isolation_compliance_positive_contactgroupmate=ISOLATION_COMPLIANCE_POSITIVE_CONTACTGROUPMATE,\n", - " isolation_lag_symptomatic=ISOLATION_LAG_SYMPTOMATIC, isolation_lag_positive=ISOLATION_LAG_POSITIVE, \n", - " isolation_groups=list(teams.values()),\n", - " test_priority = 'last_tested')" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "total percent infected: 0.88%\n", - "total percent fatality: 0.00%\n", - "peak pct hospitalized: 0.00%\n" - ] - } - ], - "source": [ - "results_summary(model)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-------" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualizing the results" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": "
", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = model.figure_infections(combine_Q_infected=False, plot_Q_R='stacked', plot_Q_S='stacked')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.8.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} \ No newline at end of file From c974004e161a2c50dfc610b4c4ac3d0e5d996276 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 14:00:03 -0400 Subject: [PATCH 007/117] Add support for logging history, as well as as policy to stop simulation if a certain condition is met, and ability to supress print statements. --- seirsplus/sim_loops.py | 77 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index ae9006d..5131cea 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -18,10 +18,16 @@ def run_tti_sim(model, T, isolation_compliance_positive_contact=[None], isolation_compliance_positive_contactgroupmate=[None], isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, - test_priority = 'random' + test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) # A suffix of "degree_oblivious" means that we ignore degrees (i.e., assume we don't know social networks for testing policy) + history = None, + # history is a dictonary that, if provided, will be updated with history and summary information for logging + stopping_policy=None, + # stopping_policy: function that takes as input the model and decides whether to stop execution + # it also takes as a additional two inputs the history and summary to record data on why execution was stopped + verbose = True, # suppress printing if verbose is false - useful for running many simulations in parallel ): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -79,10 +85,44 @@ def run_tti_sim(model, T, model.tmax = T running = True + + + def log(d): + # log values in dictionary d into history dict + nonlocal history + nonlocal model + if not history: return + if model.t in history: + history[model.t].update(d) + else: + history[model.t] = dict(d) + + def vprint(s): + # print s if verbose is true + if verbose: print(s) + + while running: running = model.run_iteration() + if history: # log current state of the model + d = {} + for att in ["numS","numE","numI","numR","numF","numQ_E","numQ_I"]: + d[att] = getattr(model,att)[model.tidx] + if (model.nodeGroupData): + for groupName, groupData in enumerate(model.nodeGroupData): + d[groupName+"/"+att] = groupData[att][model.tidx] + log(d) + + + if running and stopping_policy: + running = stopping_policy(model) + if not running: + self.finalize_data_series() + + + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Introduce exogenous exposures randomly: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -93,9 +133,10 @@ def run_tti_sim(model, T, numNewExposures = numpy.random.poisson(lam=average_introductions_per_day) model.introduce_exposures(num_new_exposures=numNewExposures) + log({"numNewExposures": numNewExposures}) if(numNewExposures > 0): - print("[NEW EXPOSURE @ t = %.2f (%d exposed)]" % (model.t, numNewExposures)) + vprint("[NEW EXPOSURE @ t = %.2f (%d exposed)]" % (model.t, numNewExposures)) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Execute testing policy at designated intervals: @@ -109,6 +150,7 @@ def run_tti_sim(model, T, currentNumInfected = model.total_num_infected()[model.tidx] currentPctInfected = model.total_num_infected()[model.tidx]/model.numNodes + log({"currentNumInfected": currentNumInfected}) if(currentPctInfected >= intervention_start_pct_infected and not interventionOn): interventionOn = True @@ -116,7 +158,7 @@ def run_tti_sim(model, T, if(interventionOn): - print("[INTERVENTIONS @ t = %.2f (%d (%.2f%%) infected)]" % (model.t, currentNumInfected, currentPctInfected*100)) + vprint("[INTERVENTIONS @ t = %.2f (%d (%.2f%%) infected)]" % (model.t, currentNumInfected, currentPctInfected*100)) nodeStates = model.X.flatten() nodeTestedStatuses = model.tested.flatten() @@ -384,14 +426,14 @@ def run_tti_sim(model, T, tracingPoolQueue.append(newTracingPool) - print("\t"+str(numTested_symptomatic) +"\ttested due to symptoms [+ "+str(numPositive_symptomatic)+" positive (%.2f %%) +]" % (numPositive_symptomatic/numTested_symptomatic*100 if numTested_symptomatic>0 else 0)) - print("\t"+str(numTested_tracing) +"\ttested as traces [+ "+str(numPositive_tracing)+" positive (%.2f %%) +]" % (numPositive_tracing/numTested_tracing*100 if numTested_tracing>0 else 0)) - print("\t"+str(numTested_random) +"\ttested randomly [+ "+str(numPositive_random)+" positive (%.2f %%) +]" % (numPositive_random/numTested_random*100 if numTested_random>0 else 0)) - print("\t"+str(numTested) +"\ttested TOTAL [+ "+str(numPositive)+" positive (%.2f %%) +]" % (numPositive/numTested*100 if numTested>0 else 0)) + vprint("\t"+str(numTested_symptomatic) +"\ttested due to symptoms [+ "+str(numPositive_symptomatic)+" positive (%.2f %%) +]" % (numPositive_symptomatic/numTested_symptomatic*100 if numTested_symptomatic>0 else 0)) + vprint("\t"+str(numTested_tracing) +"\ttested as traces [+ "+str(numPositive_tracing)+" positive (%.2f %%) +]" % (numPositive_tracing/numTested_tracing*100 if numTested_tracing>0 else 0)) + vprint("\t"+str(numTested_random) +"\ttested randomly [+ "+str(numPositive_random)+" positive (%.2f %%) +]" % (numPositive_random/numTested_random*100 if numTested_random>0 else 0)) + vprint("\t"+str(numTested) +"\ttested TOTAL [+ "+str(numPositive)+" positive (%.2f %%) +]" % (numPositive/numTested*100 if numTested>0 else 0)) - print("\t"+str(numSelfIsolated_symptoms) +" will isolate due to symptoms ("+str(numSelfIsolated_symptomaticGroupmate)+" as groupmates of symptomatic)") - print("\t"+str(numPositive) +" will isolate due to positive test ("+str(numIsolated_positiveGroupmate)+" as groupmates of positive)") - print("\t"+str(numSelfIsolated_positiveContact) +" will isolate due to positive contact ("+str(numSelfIsolated_positiveContactGroupmate)+" as groupmates of contact)") + vprint("\t"+str(numSelfIsolated_symptoms) +" will isolate due to symptoms ("+str(numSelfIsolated_symptomaticGroupmate)+" as groupmates of symptomatic)") + vprint("\t"+str(numPositive) +" will isolate due to positive test ("+str(numIsolated_positiveGroupmate)+" as groupmates of positive)") + vprint("\t"+str(numSelfIsolated_positiveContact) +" will isolate due to positive contact ("+str(numSelfIsolated_positiveContactGroupmate)+" as groupmates of contact)") #---------------------------------------- # Update the status of nodes who are to be isolated: @@ -414,7 +456,20 @@ def run_tti_sim(model, T, model.set_isolation(isolationNode, True) numIsolated += 1 - print("\t"+str(numIsolated)+" entered isolation") + vprint("\t"+str(numIsolated)+" entered isolation") + log({"numTested_symptomatic": numTested_symptomatic, + "numPositive_symptomatic" : numPositive_symptomatic, + "numTested_tracing" : numTested_tracing, + "numPositive_tracing" : numPositive_tracing, + "numTested" : numTested, + "numSelfIsolated_symptoms": numSelfIsolated_symptoms, + "numSelfIsolated_symptomaticGroupmate": numSelfIsolated_symptomaticGroupmate + "numPositive" : numPositive, + "numIsolated_positiveGroupmate" : numIsolated_positiveGroupmate, + "numSelfIsolated_positiveContact" : numSelfIsolated_positiveContact, + "numIsolated" : numIsolated + }) + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 44353823e04b3c5805a51191e7846f0368da69b9 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 14:02:11 -0400 Subject: [PATCH 008/117] Realized that "obvious testing" can already be realized using the `random_testing_degree_bias` parameter. --- seirsplus/sim_loops.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index ae9006d..8488881 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -21,7 +21,6 @@ def run_tti_sim(model, T, test_priority = 'random' # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) - # A suffix of "degree_oblivious" means that we ignore degrees (i.e., assume we don't know social networks for testing policy) ): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -259,10 +258,7 @@ def run_tti_sim(model, T, numRandomTests = max(min(tests_per_day-len(tracingSelection)-len(symptomaticSelection), len(testingPool)), 0) testingPool_degrees = model.degree.flatten()[testingPool] - if "degree_oblivious" in test_priority: - testingPool_degreeWeights = numpy.ones(len(testingPool)) - else: - testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) + testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) poolSize = len(testingPool) if(poolSize > 0): From 309f7890adba715869bf277254bf33fab1f64906 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 14:08:57 -0400 Subject: [PATCH 009/117] Realized that "obvious testing" can already be realized using the `random_testing_degree_bias` parameter. --- seirsplus/sim_loops.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 5131cea..d986621 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -21,7 +21,6 @@ def run_tti_sim(model, T, test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) - # A suffix of "degree_oblivious" means that we ignore degrees (i.e., assume we don't know social networks for testing policy) history = None, # history is a dictonary that, if provided, will be updated with history and summary information for logging stopping_policy=None, @@ -301,10 +300,7 @@ def vprint(s): numRandomTests = max(min(tests_per_day-len(tracingSelection)-len(symptomaticSelection), len(testingPool)), 0) testingPool_degrees = model.degree.flatten()[testingPool] - if "degree_oblivious" in test_priority: - testingPool_degreeWeights = numpy.ones(len(testingPool)) - else: - testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) + testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) poolSize = len(testingPool) if(poolSize > 0): From b686d5f1fcd3e1dda045dac3a336be902bc32cb0 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 19:11:31 -0400 Subject: [PATCH 010/117] fix bug --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index d986621..6ceb9e2 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -459,7 +459,7 @@ def vprint(s): "numPositive_tracing" : numPositive_tracing, "numTested" : numTested, "numSelfIsolated_symptoms": numSelfIsolated_symptoms, - "numSelfIsolated_symptomaticGroupmate": numSelfIsolated_symptomaticGroupmate + "numSelfIsolated_symptomaticGroupmate": numSelfIsolated_symptomaticGroupmate, "numPositive" : numPositive, "numIsolated_positiveGroupmate" : numIsolated_positiveGroupmate, "numSelfIsolated_positiveContact" : numSelfIsolated_positiveContact, From 581e48c9dc451ad8511060f79db2a16f9e913911 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 19:33:00 -0400 Subject: [PATCH 011/117] adding correct attributes, giving stopping policy access to history --- seirsplus/sim_loops.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 6ceb9e2..b7480a0 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -24,8 +24,7 @@ def run_tti_sim(model, T, history = None, # history is a dictonary that, if provided, will be updated with history and summary information for logging stopping_policy=None, - # stopping_policy: function that takes as input the model and decides whether to stop execution - # it also takes as a additional two inputs the history and summary to record data on why execution was stopped + # stopping_policy: function that takes as input the model and current history and decides whether to stop execution verbose = True, # suppress printing if verbose is false - useful for running many simulations in parallel ): @@ -107,7 +106,10 @@ def vprint(s): if history: # log current state of the model d = {} - for att in ["numS","numE","numI","numR","numF","numQ_E","numQ_I"]: + + + statistics = ["numS","numE","numI_pre","numI_sym","numI_asym","numH","numR","numF","numQ_S","numQ_E","numQ_pre","numQ_sym","numQ_asym","numQ_R"] + for att in statistics: d[att] = getattr(model,att)[model.tidx] if (model.nodeGroupData): for groupName, groupData in enumerate(model.nodeGroupData): @@ -116,7 +118,7 @@ def vprint(s): if running and stopping_policy: - running = stopping_policy(model) + running = stopping_policy(model,history) if not running: self.finalize_data_series() From 50b4f515fda47ded203aa2eb6a626bf2c5bd36f1 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 19:36:06 -0400 Subject: [PATCH 012/117] stopping policy returns True to stop --- seirsplus/sim_loops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index b7480a0..68d8d6c 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -25,6 +25,7 @@ def run_tti_sim(model, T, # history is a dictonary that, if provided, will be updated with history and summary information for logging stopping_policy=None, # stopping_policy: function that takes as input the model and current history and decides whether to stop execution + # returns True to stop, False to continue running verbose = True, # suppress printing if verbose is false - useful for running many simulations in parallel ): @@ -118,7 +119,7 @@ def vprint(s): if running and stopping_policy: - running = stopping_policy(model,history) + running = not stopping_policy(model,history) if not running: self.finalize_data_series() From f7823ae64cf92e6f2efbfb8c0538c5ea4b5a0d4a Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 19:42:49 -0400 Subject: [PATCH 013/117] fix indent bug --- seirsplus/sim_loops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 68d8d6c..0ce44fe 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -23,6 +23,7 @@ def run_tti_sim(model, T, # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) history = None, # history is a dictonary that, if provided, will be updated with history and summary information for logging + # OrderedDict is optional but may be better for efficiency in some stopping policies stopping_policy=None, # stopping_policy: function that takes as input the model and current history and decides whether to stop execution # returns True to stop, False to continue running @@ -115,7 +116,7 @@ def vprint(s): if (model.nodeGroupData): for groupName, groupData in enumerate(model.nodeGroupData): d[groupName+"/"+att] = groupData[att][model.tidx] - log(d) + log(d) if running and stopping_policy: From d4b60d78a96482c0fe9b097ebde3bc7c46c6cc27 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 19:54:57 -0400 Subject: [PATCH 014/117] fix bug --- seirsplus/sim_loops.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 0ce44fe..7ba7e3b 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -89,8 +89,8 @@ def run_tti_sim(model, T, def log(d): # log values in dictionary d into history dict - nonlocal history - nonlocal model + #nonlocal history # uncomment for Python 3.x + #nonlocal model # uncomment for Python 3.x if not history: return if model.t in history: history[model.t].update(d) @@ -106,23 +106,22 @@ def vprint(s): running = model.run_iteration() - if history: # log current state of the model + if not (history is None): # log current state of the model d = {} - - - statistics = ["numS","numE","numI_pre","numI_sym","numI_asym","numH","numR","numF","numQ_S","numQ_E","numQ_pre","numQ_sym","numQ_asym","numQ_R"] - for att in statistics: - d[att] = getattr(model,att)[model.tidx] - if (model.nodeGroupData): - for groupName, groupData in enumerate(model.nodeGroupData): - d[groupName+"/"+att] = groupData[att][model.tidx] - log(d) + statistics = ["numS","numE","numI_pre","numI_sym","numI_asym","numH","numR","numF","numQ_S","numQ_E","numQ_pre","numQ_sym","numQ_asym","numQ_R"] + for att in statistics: + d[att] = getattr(model,att)[model.tidx] + if (model.nodeGroupData): + for groupName in model.nodeGroupData: + groupData = model.nodeGroupData[groupName] + d[groupName+"/"+att] = groupData[att][model.tidx] + log(d) if running and stopping_policy: running = not stopping_policy(model,history) if not running: - self.finalize_data_series() + model.finalize_data_series() From b38d2444779b9f3043730f44575f97804a2c4db1 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 20:04:12 -0400 Subject: [PATCH 015/117] fix bug --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 7ba7e3b..7de796e 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -91,7 +91,7 @@ def log(d): # log values in dictionary d into history dict #nonlocal history # uncomment for Python 3.x #nonlocal model # uncomment for Python 3.x - if not history: return + if history is None: return #o/w assume it's a dictionary if model.t in history: history[model.t].update(d) else: From 7411f1b38d31521e068347276915881def1aca3f Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 20:22:37 -0400 Subject: [PATCH 016/117] wip --- seirsplus/__pycache__/FARZ.cpython-37.pyc | Bin 0 -> 19005 bytes seirsplus/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 164 bytes seirsplus/__pycache__/models.cpython-37.pyc | Bin 0 -> 93587 bytes seirsplus/__pycache__/networks.cpython-37.pyc | Bin 0 -> 17654 bytes seirsplus/__pycache__/sim_loops.cpython-37.pyc | Bin 0 -> 10039 bytes seirsplus/__pycache__/utilities.cpython-37.pyc | Bin 0 -> 2947 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 seirsplus/__pycache__/FARZ.cpython-37.pyc create mode 100644 seirsplus/__pycache__/__init__.cpython-37.pyc create mode 100644 seirsplus/__pycache__/models.cpython-37.pyc create mode 100644 seirsplus/__pycache__/networks.cpython-37.pyc create mode 100644 seirsplus/__pycache__/sim_loops.cpython-37.pyc create mode 100644 seirsplus/__pycache__/utilities.cpython-37.pyc diff --git a/seirsplus/__pycache__/FARZ.cpython-37.pyc b/seirsplus/__pycache__/FARZ.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba90e0b15223fa019801c39b0dd30e8435a2343d GIT binary patch literal 19005 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 literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/models.cpython-37.pyc b/seirsplus/__pycache__/models.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b6146b135f10f1b1905f7a661f0d9b4b94bb23d GIT binary patch literal 93587 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 literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/networks.cpython-37.pyc b/seirsplus/__pycache__/networks.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a846de9436fcdf796d020e78ecc52c58b3a67c52 GIT binary patch literal 17654 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 WpNf8veHXdh@up;dV}XOA?*9YtB!1KY literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/sim_loops.cpython-37.pyc b/seirsplus/__pycache__/sim_loops.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b29afa9b4cf2caeb503a320734bbb53c59eeafd6 GIT binary patch literal 10039 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 literal 0 HcmV?d00001 From 977b9e5c15e6688c8091e4a2946bf3334cb5adc2 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 19 Aug 2020 20:25:21 -0400 Subject: [PATCH 017/117] ignore temp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 76386e1..a856bd4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.swp .DS_Store +/seirsplus/.ipynb_checkpoints/ From ae6d27036d898d66faed9a22360b4bfa87b12c43 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 20 Aug 2020 17:59:30 -0400 Subject: [PATCH 018/117] Added ability to introduce different number of exposures per group, and allow the priority of testing to be an arbitrary function --- seirsplus/models.py | 32 ++++++++++++++++++++++++++------ seirsplus/sim_loops.py | 12 ++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 127abac..4a408f2 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1934,6 +1934,21 @@ def __init__(self, G, beta, sigma, lamda, gamma, #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # Two helper functions to get the node list and mask for a group + # If groupName is `all` then returns this for all vertices, + # even if nodeGroups were not set. + def get_nodes(self,groupName='all'): + if groupName=='all': + return range(self.numNodes) + return self.nodeGroupData[groupName]['nodes'] + + def get_mask(self,groupName='all'): + if groupName=='all': + return numpy.ones(shape=(self.numNodes,1)) + return self.nodeGroupData[groupName]['mask'] + +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ def update_parameters(self): @@ -2483,12 +2498,17 @@ def set_positive(self, node, positive): #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ def introduce_exposures(self, num_new_exposures): - exposedNodes = numpy.random.choice(range(self.numNodes), size=num_new_exposures, replace=False) - for exposedNode in exposedNodes: - if(self.X[exposedNode]==self.S): - self.X[exposedNode] = self.E - elif(self.X[exposedNode]==self.Q_S): - self.X[exposedNode] = self.Q_E + # If num_new_exposure is dictionary of the form {"group_1": num_1, "group_2": num_2 , ... } + # then introduce num_i exposures to group_i + if not isinstance(num_new_exposures,dict): + num_new_exposures = {"all": num_new_exposures } + for group,num in num_new_exposures.items(): + exposedNodes = numpy.random.choice(self.get_nodes(group), size=num, replace=False) + for exposedNode in exposedNodes: + if(self.X[exposedNode]==self.S): + self.X[exposedNode] = self.E + elif(self.X[exposedNode]==self.Q_S): + self.X[exposedNode] = self.Q_E #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 7de796e..0070634 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -21,6 +21,7 @@ def run_tti_sim(model, T, test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) + # if test_priority is callable then use as a key to sort nodes (lower value is higher priority) history = None, # history is a dictonary that, if provided, will be updated with history and summary information for logging # OrderedDict is optional but may be better for efficiency in some stopping policies @@ -132,7 +133,12 @@ def vprint(s): timeOfLastIntroduction = model.t - numNewExposures = numpy.random.poisson(lam=average_introductions_per_day) + if isinstance(average_introductions_per_day,dict): + numNewExposures = {} + for group,num in average_introductions_per_day.items(): + numNewExposures[group] = numpy.random.poisson(lam=num) + else: + numNewExposures = numpy.random.poisson(lam=average_introductions_per_day) model.introduce_exposures(num_new_exposures=numNewExposures) log({"numNewExposures": numNewExposures}) @@ -307,7 +313,9 @@ def vprint(s): poolSize = len(testingPool) if(poolSize > 0): - if 'last_tested' in test_priority: + if callable(test_priority): + randomSelection = sorted(testingPool, key=test_priority)[:numRandomTests] + elif test_priority == 'last_tested': # sort the pool according to the time they were last tested, breaking ties randomly randomSelection = sorted(testingPool,key = lambda i: (model.testedTime[i], random.randint(0,poolSize*poolSize)))[:numRandomTests] else: From 5921093c5587c2f51c0a9b6084ee38f64c98a3e5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 15:48:03 -0400 Subject: [PATCH 019/117] comment typos --- seirsplus/sim_loops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 0070634..c90cd2f 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -23,8 +23,8 @@ def run_tti_sim(model, T, # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) # if test_priority is callable then use as a key to sort nodes (lower value is higher priority) history = None, - # history is a dictonary that, if provided, will be updated with history and summary information for logging - # OrderedDict is optional but may be better for efficiency in some stopping policies + # history is a dictionary that, if provided, will be updated with history and summary information for logging + # it preferably should be OrderedDict if we want to preserve ordering of logs stopping_policy=None, # stopping_policy: function that takes as input the model and current history and decides whether to stop execution # returns True to stop, False to continue running From fb69f6e7e3dd855e2dbc79ab0493e32048a3156b Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 15:56:16 -0400 Subject: [PATCH 020/117] Added functions to map dictionary of history into pandas DataFrame and Series of the summary --- seirsplus/utilities.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index b8e9720..f16acc1 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -1,3 +1,4 @@ +import sys import numpy import matplotlib.pyplot as pyplot @@ -61,6 +62,43 @@ def results_summary(model): print("peak pct hospitalized: %0.2f%%" % (numpy.max(model.numH)/model.numNodes * 100) ) +######################################################################################################################################### +# Logging packages - requires pandas + +try: + import pandas as pd + + def last(x): + """Return last element of a pandas Series""" + return x.iloc[-1] + + + def hist2df(history): + """Take history dictionary and return: + pandas DataFrame of all history + pandas Series of the summary of history, taking the last value and the sum, as well average over time (sum of scaled)""" + L = [{'time': t, **d} for t, d in history.items()] + tmax = L[-1]['time'] + n = len(L) + df = pd.DataFrame(L) + df['interval_length'] = (df['time'] - df['time'].shift(1)).fillna(0) + temp = df.copy().fillna(0) + for col in df.columns: + if col == 'time': continue + temp[col + "/scaled"] = temp[col] * temp['interval_length'] / tmax + summary = temp.agg([last, numpy.sum]) + summary = summary.stack() + summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] + return df, summary + +except ImportError: + print("Warning: pandas missing - some logging functions will not work", file=sys.stderr) + def last(x): + raise NotImplementedError("This function requires pandas to work") + + def hist2df(history): + raise NotImplementedError("This function requires pandas to work") + From 66baff0c9914e24c800d920f0965e0d4f92bb670 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 16:10:36 -0400 Subject: [PATCH 021/117] Keep track of number of nodes, add more fields in logging --- seirsplus/sim_loops.py | 3 ++- seirsplus/utilities.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index c90cd2f..cb46d79 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -33,6 +33,7 @@ def run_tti_sim(model, T, #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Testing cadences involve a repeating 28 day cycle starting on a Monday # (0:Mon, 1:Tue, 2:Wed, 3:Thu, 4:Fri, 5:Sat, 6:Sun, 7:Mon, 8:Tues, ...) # For each cadence, testing is done on the day numbers included in the associated list. @@ -109,7 +110,7 @@ def vprint(s): if not (history is None): # log current state of the model d = {} - statistics = ["numS","numE","numI_pre","numI_sym","numI_asym","numH","numR","numF","numQ_S","numQ_E","numQ_pre","numQ_sym","numQ_asym","numQ_R"] + statistics = ["N","numS","numE","numI_pre","numI_sym","numI_asym","numH","numR","numF","numQ_S","numQ_E","numQ_pre","numQ_sym","numQ_asym","numQ_R"] for att in statistics: d[att] = getattr(model,att)[model.tidx] if (model.nodeGroupData): diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index f16acc1..a40b227 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -73,10 +73,12 @@ def last(x): return x.iloc[-1] - def hist2df(history): + def hist2df(history , **kwargs): """Take history dictionary and return: pandas DataFrame of all history - pandas Series of the summary of history, taking the last value and the sum, as well average over time (sum of scaled)""" + pandas Series of the summary of history, taking the last value and the sum, as well average over time (sum of scaled) + Optional kwargs argument - if given then add them to the dataFrame and DataSeries - helpful when merging many logs from different runs. + """ L = [{'time': t, **d} for t, d in history.items()] tmax = L[-1]['time'] n = len(L) @@ -89,6 +91,10 @@ def hist2df(history): summary = temp.agg([last, numpy.sum]) summary = summary.stack() summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] + if kwargs: + for key,val in kwargs.items(): + df[key] = val + summary[key] = val return df, summary except ImportError: From cb78cc961c279cff199db9d7e1395f3a7f6198de Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 17:04:44 -0400 Subject: [PATCH 022/117] Support for running many executions in parallel --- seirsplus/parallel_run.py | 104 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 seirsplus/parallel_run.py diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py new file mode 100644 index 0000000..f0bdab5 --- /dev/null +++ b/seirsplus/parallel_run.py @@ -0,0 +1,104 @@ +## Support to run + +import sys +import os + +import os +p = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(p) + + +from models import * +from networks import * +from sim_loops import * +from utilities import * +import collections + +import multiprocessing as mp +import pickle +import os + +def pack(f,*args,**kwds): + """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ + return ("eval",f.__name__, args,kwds) + +def unpack(O): + """Unpack and evaluate expression""" + if isinstance(O,tuple) and (len(O)>1) and (O[0]=="eval"): + f = globals()[O[1]] + return f(*O[2],**O[3]) + return O + +def run(model_params,run_params, keep_model = False): + """Run an execution with given parameters""" + MP = { key: pack(val) for key,val in model_params.items() } + RP = { key: pack(val) for key,val in run_params.items() } + desc= {key : str(val) for key,val in model_params.items() } + desc.update({key : str(val) for key,val in run_params.items() }) + model = ExtSEIRSNetworkModel(**MP) + hist = collections.OrderedDict() + run_tti_sim(model, hist=hist, **RP) + df, sum = hist2df(hist,desc) + return df,sum, model if keep_model else None + +def run_(T): + # single parameter version of run - returns only summary with an additional "model" + df, sum,model = run(T[0],T[1],T[2]) + T[1]["verbose"] = False # no printouts when running in parallel + sum["model"] = model + return sum + +def parallel_run(to_do, realizations= 1, keep_in = 0): + """Get list of triples (MP,RP) of model parameters to run, run each given number of realizations in parallel + Among all realizations we keep""" + print("Preparing list to run", flush=True) + run_list = [(T[0],T[1], r < keep_in) for r in range(realizations) for T in to_do] + print(f"We have {mp.cpu_count()} CPUs") + pool = mp.Pool(mp.cpu_count()) + print(f"Starting execution of {len(run_list)} runs", flush=True) + # rows = list(map(single_exec, run_list)) + rows = list(pool.map(run_, run_list)) + print("done", flush=True) + pool.close() + df = pd.DataFrame(rows) + return df + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--torun", default = "torun.pickle", help="File name of list to run") + parser.add_argument("--realizations", default = 5, help="Number of realizations") + parser.add_argument("--savename", default="data", help="File name to save resulting data (with csv and zip extensions)") + args = parser.parse_args() + print("Loading torun", flush=True) + with open(args.torun, 'rb') as handle: + torun = pickle.load(handle) + print("Loaded", flush=True) + data = parallel_run(torun, args.realizations) + print("Saving csv", flush=True) + data.to_csv(args.savename+'.csv') + chunk_size = 100000 + if data.shape[0] > chunk_size: + print("Saving split parts", flush=True) + i = 1 + for start in range(0, data.shape[0], chunk_size): + print(f"Saving pickle {i}", flush = True) + temp = data.iloc[start:start + chunk_size] + fname = args.savename+"_"+str(i)+".zip" + temp.to_pickle(fname) + i += 1 + fname = args.savename + "_" + str(i) + ".zip" + if os.path.exists(fname): # so there is no confusion that this was the last part + os.remove(fname) + else: + print("Saving data") + data.to_pickle(args.savename+".zip") + print("Done", flush=True) + + + + +if __name__ == "__main__": + # execute only if run as a script + main() + From 5695582338ead378230d86b5c43db8bca282c538 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 17:31:17 -0400 Subject: [PATCH 023/117] Added support for "tracing out" parameters to `run_tti_sim` so don't need to specify long parameters - useful to save on communication when running it in parallel --- seirsplus/sim_loops.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index cb46d79..68de7e1 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -33,6 +33,25 @@ def run_tti_sim(model, T, #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + def trace(param): + """ + if var is a single number between 0 and 1 then convert it to an arrau of NumNodes True/False randomly chosen with this probability: + if var is a dictionary of form { group_name: prob } then use the above separately for each group + This allows parameters to be more compactly described (useful when running many executions in parallel) + """ + if isinstance(param,(float,int)): + return (numpy.random.rand(model.numNodes) < param) + if isinstance(param,dict): + arr = numpy.full(model.numNodes,False, dtype=bool) + for group, p in param.items(): + mask = model.nodeGroupData[group]['mask'] + arr[mask] = (numpy.random.rand(model.numNodes) < p)[mask] + return arr + return param + + + + # Testing cadences involve a repeating 28 day cycle starting on a Monday # (0:Mon, 1:Tue, 2:Wed, 3:Thu, 4:Fri, 5:Sat, 6:Sun, 7:Mon, 8:Tues, ...) From f6b59849d0727799c48cb1a1fd2cbbe4f1d9e307 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 18:09:26 -0400 Subject: [PATCH 024/117] Added support for "tracing out" parameters to `run_tti_sim` so don't need to specify long parameters - useful to save on communication when running it in parallel --- seirsplus/parallel_run.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index f0bdab5..dbc2e42 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -1,7 +1,6 @@ ## Support to run import sys -import os import os p = os.path.dirname(os.path.abspath(__file__)) @@ -16,7 +15,10 @@ import multiprocessing as mp import pickle -import os + +import networkx + + def pack(f,*args,**kwds): """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ @@ -31,8 +33,11 @@ def unpack(O): def run(model_params,run_params, keep_model = False): """Run an execution with given parameters""" - MP = { key: pack(val) for key,val in model_params.items() } - RP = { key: pack(val) for key,val in run_params.items() } + MP = { key: unpack(val) for key,val in model_params.items() } + RP = { key: unpack(val) for key,val in run_params.items() } + if not MP['G_Q']: + MP['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty + desc= {key : str(val) for key,val in model_params.items() } desc.update({key : str(val) for key,val in run_params.items() }) model = ExtSEIRSNetworkModel(**MP) From da5eebb53b58a99fab0b58cebaa10e8b16d5017c Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 18:15:39 -0400 Subject: [PATCH 025/117] wip --- .DS_Store | Bin 8196 -> 0 bytes examples/.DS_Store | Bin 6148 -> 0 bytes images/.DS_Store | Bin 6148 -> 0 bytes seirsplus/.DS_Store | Bin 6148 -> 0 bytes seirsplus/__pycache__/FARZ.cpython-38.pyc | Bin 0 -> 19025 bytes seirsplus/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 156 bytes seirsplus/__pycache__/models.cpython-38.pyc | Bin 0 -> 92208 bytes seirsplus/__pycache__/networks.cpython-38.pyc | Bin 0 -> 17540 bytes seirsplus/__pycache__/sim_loops.cpython-38.pyc | Bin 0 -> 10997 bytes seirsplus/__pycache__/utilities.cpython-38.pyc | Bin 0 -> 4682 bytes 10 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 examples/.DS_Store delete mode 100644 images/.DS_Store delete mode 100644 seirsplus/.DS_Store create mode 100644 seirsplus/__pycache__/FARZ.cpython-38.pyc create mode 100644 seirsplus/__pycache__/__init__.cpython-38.pyc create mode 100644 seirsplus/__pycache__/models.cpython-38.pyc create mode 100644 seirsplus/__pycache__/networks.cpython-38.pyc create mode 100644 seirsplus/__pycache__/sim_loops.cpython-38.pyc create mode 100644 seirsplus/__pycache__/utilities.cpython-38.pyc diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 599dff412581124f1df64b802f4aae3d765b0b6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMPfrs;6n_JV+ZvP@5^KEd#TyAM7W87Qr5;R-Az8(P8rY=`6uUc{-K_;nO^s*2 zfPM%QZ{F0SUcC7YOuYI5jKBFq%hJUd4u-^;WZs*Z_h;Vz-gK8Y5D}}k>kd(gh%9u$ zr_X@oG$9v#q>bs7^WY5jL=m;9K}l=VaYwYxf$)}D=uFhAhHAipTM$g7^4o5Hn!#!&HIW=Q}|TX1JkBVml#Z$ zLv9Oo@QUVr#g#cRWll`*%yfmqS;)WUo3<9GFh}zvk&Avk(1qbW*4IV^N zed^WwJe`2oYJQ9RLiX}k>BWcAryfyk)W6eC(ipO3a%qK5=UD zv}F~G#i`&dDZq^%6 zdGw$e)_JGO+hIMCeq1H6tU{r%Hhr<%br!D9+Kbnm-mHzWvp8#)%S*jp!MbqSxqf>+ z*nQUB>pg!hl7m;QeihR>H6PG77-gPP+y@PEtJE^`gJxs}z=s+7vt}kwWAeA2<1dpfMt#ILJap#!FX1r6AaHC1#+7AB)c?1RzW+bA ze`9D6FbJG{1lUB)tyK}{{vULQLl(8RjlPa9n$YVjE=@pWISww%aqz)E3^BH$Dr_p6 U_Z7zqnz;y&Fc@MG_@@Z`24@8<5C8xG diff --git a/examples/.DS_Store b/examples/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0@Se`4;qAni7`Z?SA;?uRIs)s(OZAIZ)PV%f*vtqW|G;r zJD==p(`5mK{$_p&bOCgzf~`{y--!4{_oQVO!JsuVj4{MD?uahOz<@lv3-mEXg(bc| zzX=w2!-k%ko>#0HF~OYHnp$E->zZ1rKci3VakWOyss;UdQO|BRRb8^r72k>vjaV?d zhX+=DVTYCG^)S$0Q+n&^Gdy$5t)|pj zYNbMZNz~zYd}}*CD6_}#diig32AqLE$^g%7k>Hpf|?Hig-}E?I1*6Mxyvu`3w$NaK0r2xmI8L8 z-MQP_@x@bk?*Pc+X>$h50Zi$N*lQS@uB(siATo+#&)DJ-SNxq~H>&5qwzx;1 z|9sK3H|wTdvqJygEB)lnj3eL(cWAM}EgC%7j$aw)ta|A&jFur4NCi@XR3H`j=L)cA zt4(K)8B>8&AQkvjK)(-#u2=&*NBeXz=*(dQ*B1IU{li#mS?oukp2H##v70;)?|D)1W$ FyaP+9DFgrj diff --git a/seirsplus/__pycache__/FARZ.cpython-38.pyc b/seirsplus/__pycache__/FARZ.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc8d37dd6a0fd42b2e6f3865e694febf80c6bfcd GIT binary patch literal 19025 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 XxqIBP3EShTV|)L@c<0O3Si%0kXFYL& literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/__init__.cpython-38.pyc b/seirsplus/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64bc0538d6565c5cf9048850c0e17cb01efd909a GIT binary patch literal 156 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%0Avk>7T|rmD_-NTo5$^&*B>&vN(CA~xF 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 IP_Xm=0w|PGmjD0& literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/sim_loops.cpython-38.pyc b/seirsplus/__pycache__/sim_loops.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b398a52b3e5a197bd8e7dd7f3c920525f17fab69 GIT binary patch literal 10997 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 AqW}N^ literal 0 HcmV?d00001 diff --git a/seirsplus/__pycache__/utilities.cpython-38.pyc b/seirsplus/__pycache__/utilities.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e692d641114edc0161f75b89b9a39bf970d888df GIT binary patch literal 4682 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 literal 0 HcmV?d00001 From f659e77913cffcd42d5b14b0fcbcf12a62ee02c4 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 18:17:17 -0400 Subject: [PATCH 026/117] add gitignore --- .idea/.gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..edd5a13 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../:\Users\boaz\PycharmProjects\seirsplus\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ From aa328a0eaa0842efa2b8df3ecce15b839a5c31d4 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 18:20:37 -0400 Subject: [PATCH 027/117] ignore cached files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a856bd4..7459c23 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ *.swp .DS_Store + /seirsplus/.ipynb_checkpoints/ +*.pyc \ No newline at end of file From e5cd79508033c16c1213bf90650e9a201ce075a7 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 24 Aug 2020 18:21:55 -0400 Subject: [PATCH 028/117] ignore cached files --- seirsplus/.ipynb_checkpoints/Untitled-checkpoint.ipynb | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 seirsplus/.ipynb_checkpoints/Untitled-checkpoint.ipynb diff --git a/seirsplus/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/seirsplus/.ipynb_checkpoints/Untitled-checkpoint.ipynb deleted file mode 100644 index 2fd6442..0000000 --- a/seirsplus/.ipynb_checkpoints/Untitled-checkpoint.ipynb +++ /dev/null @@ -1,6 +0,0 @@ -{ - "cells": [], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 2 -} From 6b9bfe6f87edcf94bfb42741ba45dbedfebc7676 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 10:49:46 -0400 Subject: [PATCH 029/117] wip --- seirsplus/__pycache__/FARZ.cpython-37.pyc | Bin 19005 -> 0 bytes seirsplus/__pycache__/FARZ.cpython-38.pyc | Bin 19025 -> 0 bytes seirsplus/__pycache__/__init__.cpython-37.pyc | Bin 164 -> 0 bytes seirsplus/__pycache__/__init__.cpython-38.pyc | Bin 156 -> 0 bytes seirsplus/__pycache__/models.cpython-37.pyc | Bin 93587 -> 0 bytes seirsplus/__pycache__/models.cpython-38.pyc | Bin 92208 -> 0 bytes seirsplus/__pycache__/networks.cpython-37.pyc | Bin 17654 -> 0 bytes seirsplus/__pycache__/networks.cpython-38.pyc | Bin 17540 -> 0 bytes seirsplus/__pycache__/sim_loops.cpython-37.pyc | Bin 10039 -> 0 bytes seirsplus/__pycache__/sim_loops.cpython-38.pyc | Bin 10997 -> 0 bytes seirsplus/__pycache__/utilities.cpython-37.pyc | Bin 2947 -> 0 bytes seirsplus/__pycache__/utilities.cpython-38.pyc | Bin 4682 -> 0 bytes 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 seirsplus/__pycache__/FARZ.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/FARZ.cpython-38.pyc delete mode 100644 seirsplus/__pycache__/__init__.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/__init__.cpython-38.pyc delete mode 100644 seirsplus/__pycache__/models.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/models.cpython-38.pyc delete mode 100644 seirsplus/__pycache__/networks.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/networks.cpython-38.pyc delete mode 100644 seirsplus/__pycache__/sim_loops.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/sim_loops.cpython-38.pyc delete mode 100644 seirsplus/__pycache__/utilities.cpython-37.pyc delete mode 100644 seirsplus/__pycache__/utilities.cpython-38.pyc diff --git a/seirsplus/__pycache__/FARZ.cpython-37.pyc b/seirsplus/__pycache__/FARZ.cpython-37.pyc deleted file mode 100644 index ba90e0b15223fa019801c39b0dd30e8435a2343d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19005 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 XxqIBP3EShTV|)L@c<0O3Si%0kXFYL& diff --git a/seirsplus/__pycache__/__init__.cpython-37.pyc b/seirsplus/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 4ad56ebb0ec72910c4448ffe8095a2e6ef8de482..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164 zcmZ?b<>g`kg0>Lbco6*lIYq;;_lhPbtkwwF6o68HgDG16V6* diff --git a/seirsplus/__pycache__/__init__.cpython-38.pyc b/seirsplus/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 64bc0538d6565c5cf9048850c0e17cb01efd909a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156 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 diff --git a/seirsplus/__pycache__/models.cpython-38.pyc b/seirsplus/__pycache__/models.cpython-38.pyc deleted file mode 100644 index 9e32a67d83f90e0a91d790289409d20b74a4ef02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92208 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%0Avk>7T|rmD_-NTo5$^&*B>&vN(CA~xF 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 WpNf8veHXdh@up;dV}XOA?*9YtB!1KY diff --git a/seirsplus/__pycache__/networks.cpython-38.pyc b/seirsplus/__pycache__/networks.cpython-38.pyc deleted file mode 100644 index 2088319b85ae3a8de5723d5d65c8b765221d304e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17540 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 IP_Xm=0w|PGmjD0& diff --git a/seirsplus/__pycache__/sim_loops.cpython-37.pyc b/seirsplus/__pycache__/sim_loops.cpython-37.pyc deleted file mode 100644 index b29afa9b4cf2caeb503a320734bbb53c59eeafd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10039 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 AqW}N^ diff --git a/seirsplus/__pycache__/utilities.cpython-37.pyc b/seirsplus/__pycache__/utilities.cpython-37.pyc deleted file mode 100644 index 49d7476edaefa947f7f3395bbeb9bb7ab616e65d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2947 zcmb7GOLN@D5uO3CSS+}FQ>17q5}cTd*HIWniCqaJD~hRNDUVvKVkJ(oXm7xs;Sv-U zSPzC0xdoo6%E_v7E;-~x=HRN_^K0hn6aPRCy2M}4f@_+#51B1|XmroJ`|IBKCMQFN z_O~bRcD9;~eL)}Rtp?!%p5h)rFu_x{IePQHv*~aq9O1rTo33aIU({dlO;1dUKr|rL zL?|X;^9BEawWiK618a9(dZE$G^sM74ZUIVGa>3`>0y}acyVux}r`aCgb4s`LN=G;^ zUCiUQ&m8n_xu#Zh<5c3c8xN%MiexBBo9*`phsIZNCi1?i_2Pa%ZqZf`wQ`CvOg*!uAOKmLAeJr{DTn?Fm0 zmW58T-c}(KRSeSo;)1lVlQhwZELO3J&@SE)Nug<(!Ur(kPLYN z%0PWy2EtupnIk+=(~Xm`te5nX-P&MT2^kt_WYcW$+nS%`(6$6NmwSnIX<5%Nn$|#8l}oVExh;(=Y3s zee&stm=l&iYxiVU%$(9n?%tf36>~4Gd@_HEbp=Bd&9{fs@d0@WF79*>yA(*>Jk8b6 zS&IxC-iat)qIaW})w?^lqe6?Z{L8mjR-*Oa;`_~!k+9W+=g_aSrH_@{9GuyuS_1XW>TE6kNldLecG~Sk}n#KszkfJB;hDoVi1!HNHJ(VVX)l1Nmgf+IeC; z8fH8iWeGY0zk>!(1eEN(Z1eX}~ zUt$xU;HW_ydcn%zBsgUc5&cJD*-)SBM%fU4#hHev>k#Y;!LksX8oejWPy}FEctTRc zO6NA)_Zr)&En3!<{>fAsobsay-4J0pG1g97Z4=swvN_V~M#azrFleR>b+|VxxSrGV zWeA2gD~3*jp$#zZ57_6F%>~n7X&o$`5wn)1J7TV^Tb9F3XMi^DiR;CE0sY*28Oen*}-xNizbgYwSi9TGTfs}iOi|Z&tT7tE`$WF6n^;Pas zvpB}E9tpd_4K+tsbe@6KJic1KqI*+U2q^uiMS>*)V%B%(9JLH{Ysm!F6&c8)T>jepOflWq~iGJ(7hBl zrgx#7$qA2qqh-{7y=oJ4tva@3Ra9Q7Xhk0Y8Qd;H&M7atl~ zs$?g8RGlF?BWVedzK4HG!d+k$bD8j<^Qek{i>;<>CqDG3)t9ZdF8b}^O`YpFjjC)P zA;rqBmI5Jl2eG!YVk72EU{{yB?!*{q1GDNnyg88Z(8qUPuuTDD1x;<%;{whO)FXKr@H7A z`}jMk4#~&W-?6v&b*_Gg?^dn7VJXwzxG2``B4)N9YpP3WvW>rXB#i=`>WQr|id<+X gy0AD^8f6Psa1R^XPvw1bZb3yW;7up+!@2OrmuE=XKL7v# diff --git a/seirsplus/__pycache__/utilities.cpython-38.pyc b/seirsplus/__pycache__/utilities.cpython-38.pyc deleted file mode 100644 index e692d641114edc0161f75b89b9a39bf970d888df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4682 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 From c6424c4b3a5891944bec29ae492d87a2bfa07917 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 11:38:26 -0400 Subject: [PATCH 030/117] Ability to express functions that output first element (useful for graph generation) --- seirsplus/parallel_run.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index dbc2e42..e2f88f5 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -20,15 +20,23 @@ -def pack(f,*args,**kwds): +def pack(f,*args,**kwds, getelement = ""): """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ - return ("eval",f.__name__, args,kwds) + return ("eval"+str(getelement),f.__name__, args,kwds) + +def packfirst(f,*args,**kwds): + return pack(f,*args,**kwds,getelement=0) def unpack(O): """Unpack and evaluate expression""" - if isinstance(O,tuple) and (len(O)>1) and (O[0]=="eval"): + K = len("eval") # this is four of course but just in case we change things later + if isinstance(O,tuple) and (len(O)>1) and (O[0][:K]=="eval"): f = globals()[O[1]] - return f(*O[2],**O[3]) + res = f(*O[2],**O[3]) + if len(O[0]) > K: + i = int(O[K:]) + return res[i] + return res return O def run(model_params,run_params, keep_model = False): From ac3e99dd8b8d3d1b089de6072f5fec7c63d35645 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 11:47:15 -0400 Subject: [PATCH 031/117] Ability to express functions that output first element (useful for graph generation) --- seirsplus/parallel_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index e2f88f5..608429d 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -20,12 +20,12 @@ -def pack(f,*args,**kwds, getelement = ""): +def pack(f,*args,getelement = "", **kwds): """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ return ("eval"+str(getelement),f.__name__, args,kwds) def packfirst(f,*args,**kwds): - return pack(f,*args,**kwds,getelement=0) + return pack(f,*args,getelement=0,**kwds) def unpack(O): """Unpack and evaluate expression""" From 54351d6d1e5ae9cff7bc53998746766cf3442a57 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 16:46:15 +0000 Subject: [PATCH 032/117] fix bugs in parallel run --- seirsplus/parallel_run.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 608429d..4c6f235 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -8,7 +8,7 @@ from models import * -from networks import * +from .networks import * from sim_loops import * from utilities import * import collections @@ -17,7 +17,7 @@ import pickle import networkx - +import argparse def pack(f,*args,getelement = "", **kwds): @@ -34,7 +34,7 @@ def unpack(O): f = globals()[O[1]] res = f(*O[2],**O[3]) if len(O[0]) > K: - i = int(O[K:]) + i = int(O[0][K:]) return res[i] return res return O @@ -50,8 +50,8 @@ def run(model_params,run_params, keep_model = False): desc.update({key : str(val) for key,val in run_params.items() }) model = ExtSEIRSNetworkModel(**MP) hist = collections.OrderedDict() - run_tti_sim(model, hist=hist, **RP) - df, sum = hist2df(hist,desc) + run_tti_sim(model, history=hist, **RP) + df, sum = hist2df(hist,**desc) return df,sum, model if keep_model else None def run_(T): @@ -62,7 +62,7 @@ def run_(T): return sum def parallel_run(to_do, realizations= 1, keep_in = 0): - """Get list of triples (MP,RP) of model parameters to run, run each given number of realizations in parallel + """Get list of pairs (MP,RP) of model parameters to run, run each given number of realizations in parallel Among all realizations we keep""" print("Preparing list to run", flush=True) run_list = [(T[0],T[1], r < keep_in) for r in range(realizations) for T in to_do] @@ -76,11 +76,17 @@ def parallel_run(to_do, realizations= 1, keep_in = 0): df = pd.DataFrame(rows) return df +def save_to_file(L,filename = 'torun.pickle'): + """Save list of (MP,RP) pairs to run""" + with open(filename, 'wb') as handle: + pickle.dump(L, handle, protocol=pickle.HIGHEST_PROTOCOL) + + def main(): parser = argparse.ArgumentParser() parser.add_argument("--torun", default = "torun.pickle", help="File name of list to run") - parser.add_argument("--realizations", default = 5, help="Number of realizations") + parser.add_argument("--realizations", default = 5, type=int, help="Number of realizations") parser.add_argument("--savename", default="data", help="File name to save resulting data (with csv and zip extensions)") args = parser.parse_args() print("Loading torun", flush=True) From 3d98f8291fe56562b6d5e4bf6d3598e2774b0358 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 17:54:33 -0400 Subject: [PATCH 033/117] Suppress warning --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 4a408f2..8f46989 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2153,7 +2153,7 @@ def update_parameters(self): # Degree-based transmission scaling parameters: #---------------------------------------- self.delta_pairwise_mode = self.parameters['delta_pairwise_mode'] - with numpy.errstate(divide='ignore'): # ignore log(0) warning, then convert log(0) = -inf -> 0.0 + with numpy.errstate(divide='ignore',invalid='ignore'): # ignore log(0) warning, then convert log(0) = -inf -> 0.0 self.delta = numpy.log(self.degree)/numpy.log(numpy.mean(self.degree)) if self.parameters['delta'] is None else numpy.array(self.parameters['delta']) if isinstance(self.parameters['delta'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta'], shape=(self.numNodes,1)) self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1)) self.delta[numpy.isneginf(self.delta)] = 0.0 From ad9dcc71a2185ba191088952b888c677c9a463ce Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 22:03:20 +0000 Subject: [PATCH 034/117] wip --- seirsplus/parallel_run.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 4c6f235..91d44a0 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -89,6 +89,9 @@ def main(): parser.add_argument("--realizations", default = 5, type=int, help="Number of realizations") parser.add_argument("--savename", default="data", help="File name to save resulting data (with csv and zip extensions)") args = parser.parse_args() + print("Arguments:") + for arg in vars(args): + print(arg,":", getattr(args, arg)) print("Loading torun", flush=True) with open(args.torun, 'rb') as handle: torun = pickle.load(handle) @@ -97,21 +100,17 @@ def main(): print("Saving csv", flush=True) data.to_csv(args.savename+'.csv') chunk_size = 100000 - if data.shape[0] > chunk_size: - print("Saving split parts", flush=True) - i = 1 - for start in range(0, data.shape[0], chunk_size): - print(f"Saving pickle {i}", flush = True) - temp = data.iloc[start:start + chunk_size] - fname = args.savename+"_"+str(i)+".zip" - temp.to_pickle(fname) - i += 1 - fname = args.savename + "_" + str(i) + ".zip" - if os.path.exists(fname): # so there is no confusion that this was the last part - os.remove(fname) - else: - print("Saving data") - data.to_pickle(args.savename+".zip") + print("Saving split parts", flush=True) + i = 1 + for start in range(0, data.shape[0], chunk_size): + print(f"Saving pickle {i}", flush = True) + temp = data.iloc[start:start + chunk_size] + fname = args.savename+"_"+str(i)+".zip" + temp.to_pickle(fname) + i += 1 + fname = args.savename + "_" + str(i) + ".zip" + if os.path.exists(fname): # so there is no confusion that this was the last part + os.remove(fname) print("Done", flush=True) From 24a06edd55e9f41540ea4f0dd5e3194244a7c917 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 25 Aug 2020 22:55:02 +0000 Subject: [PATCH 035/117] wip --- seirsplus/models.py | 2 +- seirsplus/parallel_run.py | 37 +++++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 4a408f2..c89c340 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2153,7 +2153,7 @@ def update_parameters(self): # Degree-based transmission scaling parameters: #---------------------------------------- self.delta_pairwise_mode = self.parameters['delta_pairwise_mode'] - with numpy.errstate(divide='ignore'): # ignore log(0) warning, then convert log(0) = -inf -> 0.0 + with numpy.errstate(divide='ignore', invalid='ignore'): # ignore log(0) warning, then convert log(0) = -inf -> 0.0 self.delta = numpy.log(self.degree)/numpy.log(numpy.mean(self.degree)) if self.parameters['delta'] is None else numpy.array(self.parameters['delta']) if isinstance(self.parameters['delta'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta'], shape=(self.numNodes,1)) self.delta_Q = numpy.log(self.degree_Q)/numpy.log(numpy.mean(self.degree_Q)) if self.parameters['delta_Q'] is None else numpy.array(self.parameters['delta_Q']) if isinstance(self.parameters['delta_Q'], (list, numpy.ndarray)) else numpy.full(fill_value=self.parameters['delta_Q'], shape=(self.numNodes,1)) self.delta[numpy.isneginf(self.delta)] = 0.0 diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 91d44a0..99151a0 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -19,7 +19,6 @@ import networkx import argparse - def pack(f,*args,getelement = "", **kwds): """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ return ("eval"+str(getelement),f.__name__, args,kwds) @@ -39,33 +38,35 @@ def unpack(O): return res return O -def run(model_params,run_params, keep_model = False): +def run(model_params,run_params, extra, keep_model = False): """Run an execution with given parameters""" MP = { key: unpack(val) for key,val in model_params.items() } RP = { key: unpack(val) for key,val in run_params.items() } if not MP['G_Q']: - MP['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty - - desc= {key : str(val) for key,val in model_params.items() } + MP['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty + desc= dict(extra) + desc.update({key : str(val) for key,val in model_params.items() }) desc.update({key : str(val) for key,val in run_params.items() }) model = ExtSEIRSNetworkModel(**MP) hist = collections.OrderedDict() run_tti_sim(model, history=hist, **RP) - df, sum = hist2df(hist,**desc) - return df,sum, model if keep_model else None + df, summary = hist2df(hist,**desc) + m = model if keep_model else None + return df,summary, m def run_(T): # single parameter version of run - returns only summary with an additional "model" - df, sum,model = run(T[0],T[1],T[2]) T[1]["verbose"] = False # no printouts when running in parallel - sum["model"] = model - return sum + df, summary,model = run(T[0],T[1],T[2],T[3]) + summary["model"] = model + return summary def parallel_run(to_do, realizations= 1, keep_in = 0): - """Get list of pairs (MP,RP) of model parameters to run, run each given number of realizations in parallel - Among all realizations we keep""" + """Get list of pairs (MP,RP, extra) of model parameters to run, run each given number of realizations in parallel + Among all realizations we keep. + Extra is extra fields for logging and grouping purposes""" print("Preparing list to run", flush=True) - run_list = [(T[0],T[1], r < keep_in) for r in range(realizations) for T in to_do] + run_list = [(M,R,E, r < keep_in) for r in range(realizations) for M,R,E in to_do] print(f"We have {mp.cpu_count()} CPUs") pool = mp.Pool(mp.cpu_count()) print(f"Starting execution of {len(run_list)} runs", flush=True) @@ -81,7 +82,15 @@ def save_to_file(L,filename = 'torun.pickle'): with open(filename, 'wb') as handle: pickle.dump(L, handle, protocol=pickle.HIGHEST_PROTOCOL) - +def read_from_file(prefix= 'data'): + i = 1 + chunks = [] + while os.path.exists(prefix+"_"+str(i)+".zip"): + print("Loading chunk "+ str(i), flush=True) + chunks.append(pd.read_pickle(prefix+"_"+str(i)+".zip")) + i += 1 + return pd.concat(chunks) + def main(): parser = argparse.ArgumentParser() From f08f89eed2b8c3c919d3e9258b8ad0422c1d0475 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 11:35:02 -0400 Subject: [PATCH 036/117] Log numTested_random --- seirsplus/sim_loops.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 68de7e1..a4bbe54 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -489,6 +489,7 @@ def vprint(s): "numTested_tracing" : numTested_tracing, "numPositive_tracing" : numPositive_tracing, "numTested" : numTested, + "numTested_random" : numTested_random, "numSelfIsolated_symptoms": numSelfIsolated_symptoms, "numSelfIsolated_symptomaticGroupmate": numSelfIsolated_symptomaticGroupmate, "numPositive" : numPositive, From 9fb502cad47270c3e8eb8390a2cf9dc35e6547db Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 12:42:55 -0400 Subject: [PATCH 037/117] move stopping policy check --- seirsplus/sim_loops.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index a4bbe54..f19e70a 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -126,6 +126,10 @@ def vprint(s): while running: running = model.run_iteration() + if running and stopping_policy: + running = not stopping_policy(model, history) + if not running: + model.finalize_data_series() if not (history is None): # log current state of the model d = {} @@ -139,10 +143,7 @@ def vprint(s): log(d) - if running and stopping_policy: - running = not stopping_policy(model,history) - if not running: - model.finalize_data_series() + @@ -498,7 +499,6 @@ def vprint(s): "numIsolated" : numIsolated }) - #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From d2a0280bcb69812033229de09ada763c1b22fe26 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 12:45:14 -0400 Subject: [PATCH 038/117] make time the log of the index --- seirsplus/utilities.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index a40b227..6be3de6 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -95,6 +95,8 @@ def hist2df(history , **kwargs): for key,val in kwargs.items(): df[key] = val summary[key] = val + df.set_index('time',inplace=True) + df.sort_index(inplace=True) return df, summary except ImportError: From 74b0b9d29728c89ca9b85d32c36c88a19030f1a9 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 12:46:06 -0400 Subject: [PATCH 039/117] make time the log of the index --- seirsplus/utilities.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 6be3de6..376e4bc 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -99,6 +99,7 @@ def hist2df(history , **kwargs): df.sort_index(inplace=True) return df, summary + except ImportError: print("Warning: pandas missing - some logging functions will not work", file=sys.stderr) def last(x): From 272f002b07ac5bc8dda488251bac6e11cbf71e91 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 15:07:01 -0400 Subject: [PATCH 040/117] ensured there is an event every day, added option to continue simulation even when there are no infected people, added some logging fields --- seirsplus/models.py | 37 +++++++++++++++++++++++++++++++------ seirsplus/sim_loops.py | 16 ++++++++++++---- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index c89c340..d05a36e 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1791,11 +1791,17 @@ def __init__(self, G, beta, sigma, lamda, gamma, self.tidx = 0 self.tseries[0] = 0 + self.blankEvent = False # if blankEvent = True then we run a blank event until we reach "wait_until_t" + # this ensures that we don't skip a day of doing randomized testing or any other intervention + self.wait_until_t = 0 + + self.runTillEnd = False # if True then don't stop when infetions = 0 - makes sense if external infections may be introduced later + # Vectors holding the time that each node has been in a given state or in isolation: self.timer_state = numpy.zeros((self.numNodes,1)) self.timer_isolation = numpy.zeros(self.numNodes) self.isolationTime = isolation_time - + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Initialize Counts of inidividuals with each state: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2625,7 +2631,7 @@ def run_iteration(self): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ propensities, transitionTypes = self.calc_propensities() - if(propensities.sum() > 0): + if (not self.blankEvent) and (propensities.sum() > 0): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Calculate alpha @@ -2638,8 +2644,17 @@ def run_iteration(self): # Compute the time until the next event takes place #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tau = (1/alpha)*numpy.log(float(1/r1)) - self.t += tau - self.timer_state += tau + if int(self.t + tau) > int(self.t)+1: + # if next event will skip a day + delta = int(self.t) + 1.0 + self.wait_until_t = self.t + tau + self.blankEvent = True + self.t += delta + self.timer_state += delta + else: + self.blankEvent = False + self.t += tau + self.timer_state += tau #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Compute which event takes place @@ -2682,7 +2697,16 @@ def run_iteration(self): else: - tau = 0.01 + if self.blankEvent: + # if this is a blank event then either go to the time we're waiting for or the next day + # the goal is to verify we have at least one event every day + if int(self.t) >= int( self.wait_until_t)-1: + tau = self.wait_until_t - self.t + self.blankEvent = False + else: + tau = int(self.t)+1 - self.t + else: + tau = 0.01 self.t += tau self.timer_state += tau @@ -2750,7 +2774,8 @@ def run_iteration(self): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Terminate if tmax reached or num infections is 0: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if(self.t >= self.tmax or (self.total_num_infected(self.tidx) < 1 and self.total_num_isolated(self.tidx) < 1)): + # if self.runTillEnd is true then only terminate when tmax is reached + if(self.t >= self.tmax) or ((not self.runTillEnd) and (self.total_num_infected(self.tidx) < 1 and self.total_num_isolated(self.tidx) < 1)): self.finalize_data_series() return False diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index f19e70a..c8005e0 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -18,6 +18,7 @@ def run_tti_sim(model, T, isolation_compliance_positive_contact=[None], isolation_compliance_positive_contactgroupmate=[None], isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, + runTillEnd = False, # True: don't stop simulation if number of infected & isolated is zero, since more external infections may be introduced later test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) @@ -105,6 +106,7 @@ def trace(param): isolationQueue_contact = [[] for i in range(isolation_lag_contact)] model.tmax = T + model.runTillEnd = runTillEnd running = True @@ -179,12 +181,13 @@ def vprint(s): currentNumInfected = model.total_num_infected()[model.tidx] currentPctInfected = model.total_num_infected()[model.tidx]/model.numNodes - log({"currentNumInfected": currentNumInfected}) + log({"currentNumInfected": currentNumInfected , "cadenceDayNumber": cadenceDayNumber }) if(currentPctInfected >= intervention_start_pct_infected and not interventionOn): interventionOn = True interventionStartTime = model.t - + + log({"interventionOn": interventionOn}) if(interventionOn): vprint("[INTERVENTIONS @ t = %.2f (%d (%.2f%%) infected)]" % (model.t, currentNumInfected, currentPctInfected*100)) @@ -277,6 +280,8 @@ def vprint(s): ).flatten() numSymptomaticTests = min(len(symptomaticPool), max_symptomatic_tests_per_day) + + log({"symptomaticPool": len(symptomaticPool), "numSymptomaticTests": numSymptomaticTests }) if(len(symptomaticPool) > 0): symptomaticSelection = symptomaticPool[numpy.random.choice(len(symptomaticPool), min(numSymptomaticTests, len(symptomaticPool)), replace=False)] @@ -298,10 +303,12 @@ def vprint(s): #---------------------------------------- tracingPool = tracingPoolQueue.pop(0) + log({"currentTracingPool" : len(tracingPool)}) if(any(testing_compliance_traced)): numTracingTests = min(len(tracingPool), min(tests_per_day-len(symptomaticSelection), max_tracing_tests_per_day)) + log({"numTracingTests" : numTracingTests}) for trace in range(numTracingTests): traceNode = tracingPool.pop() @@ -326,9 +333,9 @@ def vprint(s): & (nodeStates != model.H) & (nodeStates != model.F) ).flatten() - + log({"testingPool" : len(testingPool)}) numRandomTests = max(min(tests_per_day-len(tracingSelection)-len(symptomaticSelection), len(testingPool)), 0) - + log({"numRandomTests": numRandomTests}) testingPool_degrees = model.degree.flatten()[testingPool] testingPool_degreeWeights = numpy.power(testingPool_degrees,random_testing_degree_bias)/numpy.sum(numpy.power(testingPool_degrees,random_testing_degree_bias)) @@ -451,6 +458,7 @@ def vprint(s): isolationQueue_contact.append(newIsolationGroup_contact) # Add the nodes to be traced to the tracing queue: + log({"newTracingPool" : len(newTracingPool)}) tracingPoolQueue.append(newTracingPool) From f9073c1ccb288b47bd272ce4d806fcac79546afb Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 27 Aug 2020 19:44:51 -0400 Subject: [PATCH 041/117] fix bug in time --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index d05a36e..13ece33 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2646,7 +2646,7 @@ def run_iteration(self): tau = (1/alpha)*numpy.log(float(1/r1)) if int(self.t + tau) > int(self.t)+1: # if next event will skip a day - delta = int(self.t) + 1.0 + delta = int(self.t) - self.t + 1.0 self.wait_until_t = self.t + tau self.blankEvent = True self.t += delta From 76a7c20d508418de8e9c1eeadbc232f61967c2dc Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 31 Aug 2020 18:28:42 -0400 Subject: [PATCH 042/117] Log results at first detection --- seirsplus/sim_loops.py | 3 ++- seirsplus/utilities.py | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index c8005e0..81067b6 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -504,7 +504,8 @@ def vprint(s): "numPositive" : numPositive, "numIsolated_positiveGroupmate" : numIsolated_positiveGroupmate, "numSelfIsolated_positiveContact" : numSelfIsolated_positiveContact, - "numIsolated" : numIsolated + "numIsolated" : numIsolated, + "positiveTestResults": len(isolationGroup_positive) }) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 376e4bc..29ee257 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -83,10 +83,13 @@ def hist2df(history , **kwargs): tmax = L[-1]['time'] n = len(L) df = pd.DataFrame(L) + df = df.fillna(0) df['interval_length'] = (df['time'] - df['time'].shift(1)).fillna(0) - temp = df.copy().fillna(0) - for col in df.columns: - if col == 'time': continue + df.set_index('time',inplace=True) + df.sort_index(inplace=True) + temp = df.copy() + orig_cols = list(df.columns) + for col in orig_cols: temp[col + "/scaled"] = temp[col] * temp['interval_length'] / tmax summary = temp.agg([last, numpy.sum]) summary = summary.stack() @@ -95,8 +98,16 @@ def hist2df(history , **kwargs): for key,val in kwargs.items(): df[key] = val summary[key] = val - df.set_index('time',inplace=True) - df.sort_index(inplace=True) + if "positiveTestResults" in df.columns: + # add summary statistics for when first positive test results are detected + temp = df[df.positiveTestResults > 0] + row = temp.iloc[0] if len(temp) else None + vals = [] + labels = [] + for col in orig_cols: + labels.append(col+"/1st") + vals.append(row[col] if row else 0) + summary = summary.append(pd.Series(vals,index=labels)) return df, summary From 53ac0150cc0b9b91045b700ddbe726b783035c91 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 31 Aug 2020 19:43:00 -0400 Subject: [PATCH 043/117] Allow float parameters --- seirsplus/sim_loops.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 81067b6..b03642a 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -34,10 +34,10 @@ def run_tti_sim(model, T, #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - def trace(param): + def sample(param): """ - if var is a single number between 0 and 1 then convert it to an arrau of NumNodes True/False randomly chosen with this probability: - if var is a dictionary of form { group_name: prob } then use the above separately for each group + if param is a single number between 0 and 1 then convert it to an arrau of NumNodes True/False randomly chosen with this probability: + if param is a dictionary of form { group_name: prob } then use the above separately for each group This allows parameters to be more compactly described (useful when running many executions in parallel) """ if isinstance(param,(float,int)): @@ -50,6 +50,17 @@ def trace(param): return arr return param + testing_compliance_random = sample(testing_compliance_random) + testing_compliance_traced = sample(testing_compliance_traced) + testing_compliance_symptomatic = sample(testing_compliance_symptomatic) + tracing_compliance = sample(testing_compliance_symptomatic) + isolation_compliance_symptomatic_individual = sample(isolation_compliance_symptomatic_individual) + isolation_compliance_symptomatic_groupmate = sample(isolation_compliance_symptomatic_groupmate) + isolation_compliance_positive_individual = sample(isolation_compliance_positive_individual) + isolation_compliance_positive_groupmate = sample(isolation_compliance_positive_groupmate) + isolation_compliance_positive_contact = sample(isolation_compliance_positive_contact) + isolation_compliance_positive_contactgroupmate = sample(isolation_compliance_positive_contactgroupmate) + From 438a123779029763d2dee28ebf9d7ac69e121ec3 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 08:54:27 -0400 Subject: [PATCH 044/117] Logging positive tests --- seirsplus/sim_loops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index b03642a..c3e3a02 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -499,6 +499,7 @@ def vprint(s): numIsolated += 1 isolationGroup_positive = isolationQueue_positive.pop(0) + positiveTestResults = len(isolationGroup_positive) for isolationNode in isolationGroup_positive: model.set_isolation(isolationNode, True) numIsolated += 1 @@ -516,7 +517,7 @@ def vprint(s): "numIsolated_positiveGroupmate" : numIsolated_positiveGroupmate, "numSelfIsolated_positiveContact" : numSelfIsolated_positiveContact, "numIsolated" : numIsolated, - "positiveTestResults": len(isolationGroup_positive) + "positiveTestResults": positiveTestResults }) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9668554745e3900911a30f838fd4ae43755fb2a3 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 10:43:03 -0400 Subject: [PATCH 045/117] Deferring execution for parallel runs, generate graph with isolation groups --- seirsplus/parallel_run.py | 64 ++++++++++++++++++++++++++++++--------- seirsplus/utilities.py | 2 +- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 99151a0..8788d6b 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -19,30 +19,64 @@ import networkx import argparse -def pack(f,*args,getelement = "", **kwds): - """"Pack a function evaluation into a symbolic representations we can easily 'pickle' """ - return ("eval"+str(getelement),f.__name__, args,kwds) -def packfirst(f,*args,**kwds): - return pack(f,*args,getelement=0,**kwds) -def unpack(O): - """Unpack and evaluate expression""" - K = len("eval") # this is four of course but just in case we change things later - if isinstance(O,tuple) and (len(O)>1) and (O[0][:K]=="eval"): - f = globals()[O[1]] - res = f(*O[2],**O[3]) - if len(O[0]) > K: - i = int(O[0][K:]) - return res[i] +class Defer: + """Class for deferring computation + Defer(f,positional and keyword arguments) stores f's name and the arguments for later evaluation""" + def __init__(self,f,*args,**kwds): + self.f_name = f.__name__ + self.args = args + self.kwds = kwds + + def __str__(self): + res = self.f_name+"(" + res += ", ".join([str(a) for a in self.args]) + if args and kwds: + res+=", " + if kwds: + res += ", ".join([str(k)+"="+str(v) for k,v in kwds.items()]) return res + + def eval(self): + f = globals()[self.f_name] + args_ = [unpack(a) for a in self.args] + kwds_ = {k:unpack(v) for k,v in self.kwds.items()} + return f(*args_,**kwds_) + +def unpack(O): + if isinstance(O,Defer): + return O.eval() return O + +def generate_workplace_contact_network_(*args,**kwds): + """Helper function to produce graph + isolation groups""" + G, cohorts, teams = generate_workplace_contact_network(*args,**kwds) + return G, teams.values() + +def generate_workplace_contact_network_deferred(*args,**kwds): + """Returns deferred execution of functoin to generate return graph and isolation groups""" + return Defer(generate_workplace_contact_network_,*args,**kwds) + + def run(model_params,run_params, extra, keep_model = False): """Run an execution with given parameters""" MP = { key: unpack(val) for key,val in model_params.items() } RP = { key: unpack(val) for key,val in run_params.items() } - if not MP['G_Q']: + for D in [MP,RP]: + # replace key a value pair of form (k1,k2,k3):(v1,v2,v3) with k1:v1,k2:v2,k3:v3 etc.. + # useful if several keys depend on the same deferred computation + for key in list(D.keys()): + if isinstance((key,tuple)): + L = D[key] + if len(L) != len(key): + raise Exception("Key" + str(key) + "should have same length as value" + str(L)) + for i,subkey in enumerate(key): + D[subkey] = L[i] + del D[key] + + if ('G_Q' not in MP) or (not MP['G_Q']): MP['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty desc= dict(extra) desc.update({key : str(val) for key,val in model_params.items() }) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 29ee257..2481922 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -106,7 +106,7 @@ def hist2df(history , **kwargs): labels = [] for col in orig_cols: labels.append(col+"/1st") - vals.append(row[col] if row else 0) + vals.append(0 if row is None else row[col]) summary = summary.append(pd.Series(vals,index=labels)) return df, summary From 038031372afd98c98eeed7741a8efc666bcf84a7 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:09:43 -0400 Subject: [PATCH 046/117] Progress bar for parallel run --- seirsplus/parallel_run.py | 74 +++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 8788d6b..bc15439 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -13,12 +13,20 @@ from utilities import * import collections -import multiprocessing as mp -import pickle +import pickle +import inspect import networkx import argparse +try: + from p_tqdm import p_umap # https://github.com/swansonk14/p_tqdm +except ImportError: + print("Please install p_tqdm package via pip install p_tqdm") + print("Preparing code for parallel run will work, but running the script will not") + def p_umap(*L): + raise Exception("Package p_tqdm not found") + class Defer: @@ -60,38 +68,45 @@ def generate_workplace_contact_network_deferred(*args,**kwds): return Defer(generate_workplace_contact_network_,*args,**kwds) -def run(model_params,run_params, extra, keep_model = False): +def run(params, keep_model = False): """Run an execution with given parameters""" - MP = { key: unpack(val) for key,val in model_params.items() } - RP = { key: unpack(val) for key,val in run_params.items() } - for D in [MP,RP]: - # replace key a value pair of form (k1,k2,k3):(v1,v2,v3) with k1:v1,k2:v2,k3:v3 etc.. - # useful if several keys depend on the same deferred computation - for key in list(D.keys()): - if isinstance((key,tuple)): - L = D[key] - if len(L) != len(key): - raise Exception("Key" + str(key) + "should have same length as value" + str(L)) - for i,subkey in enumerate(key): - D[subkey] = L[i] - del D[key] - - if ('G_Q' not in MP) or (not MP['G_Q']): - MP['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty - desc= dict(extra) + params = { key: unpack(val) for key,val in model_params.items() } + # replace key a value pair of form (k1,k2,k3):(v1,v2,v3) with k1:v1,k2:v2,k3:v3 etc.. + # useful if several keys depend on the same deferred computation + for key in list(params.keys()): + if isinstance((key,tuple)): + L = params[key] + if len(L) != len(key): + raise Exception("Key" + str(key) + "should have same length as value" + str(L)) + for i,subkey in enumerate(key): + params[subkey] = L[i] + del params[key] + + if ('G_Q' not in params) or (not params['G_Q']): + params['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty + desc= {} + model_params = {} + run_params = {} + for k, v in params.items(): + if k in inspect.signature(ExtSEIRSNetworkModel).parameters: + model_params[k] = v + elif k in inspect.signature(run_tti_sim).parameters: + run_params[k] = v + else: + desc[k] = v desc.update({key : str(val) for key,val in model_params.items() }) desc.update({key : str(val) for key,val in run_params.items() }) - model = ExtSEIRSNetworkModel(**MP) + model = ExtSEIRSNetworkModel(**model_params) hist = collections.OrderedDict() - run_tti_sim(model, history=hist, **RP) + run_tti_sim(model, history=hist, **run_params) df, summary = hist2df(hist,**desc) m = model if keep_model else None return df,summary, m def run_(T): # single parameter version of run - returns only summary with an additional "model" - T[1]["verbose"] = False # no printouts when running in parallel - df, summary,model = run(T[0],T[1],T[2],T[3]) + T[0]["verbose"] = False # no printouts when running in parallel + df, summary,model = run(T[0],T[1]) summary["model"] = model return summary @@ -100,14 +115,13 @@ def parallel_run(to_do, realizations= 1, keep_in = 0): Among all realizations we keep. Extra is extra fields for logging and grouping purposes""" print("Preparing list to run", flush=True) - run_list = [(M,R,E, r < keep_in) for r in range(realizations) for M,R,E in to_do] - print(f"We have {mp.cpu_count()} CPUs") - pool = mp.Pool(mp.cpu_count()) + run_list = [(D, r < keep_in) for r in range(realizations) for D in to_do] + #print(f"We have {mp.cpu_count()} CPUs") + #pool = mp.Pool(mp.cpu_count()) print(f"Starting execution of {len(run_list)} runs", flush=True) - # rows = list(map(single_exec, run_list)) - rows = list(pool.map(run_, run_list)) + rows = list(p_umap(run,run_list)) + #rows = list(pool.map(run_, run_list)) print("done", flush=True) - pool.close() df = pd.DataFrame(rows) return df From e253b9993944108767b766a138958e7e60917cd5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:20:33 -0400 Subject: [PATCH 047/117] Fix bug --- seirsplus/parallel_run.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index bc15439..65bdcac 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -70,11 +70,11 @@ def generate_workplace_contact_network_deferred(*args,**kwds): def run(params, keep_model = False): """Run an execution with given parameters""" - params = { key: unpack(val) for key,val in model_params.items() } + params = { key: unpack(val) for key,val in params.items() } # replace key a value pair of form (k1,k2,k3):(v1,v2,v3) with k1:v1,k2:v2,k3:v3 etc.. # useful if several keys depend on the same deferred computation for key in list(params.keys()): - if isinstance((key,tuple)): + if isinstance(key,tuple): L = params[key] if len(L) != len(key): raise Exception("Key" + str(key) + "should have same length as value" + str(L)) @@ -118,7 +118,7 @@ def parallel_run(to_do, realizations= 1, keep_in = 0): run_list = [(D, r < keep_in) for r in range(realizations) for D in to_do] #print(f"We have {mp.cpu_count()} CPUs") #pool = mp.Pool(mp.cpu_count()) - print(f"Starting execution of {len(run_list)} runs", flush=True) + print("Starting execution of " +str(len(run_list)) +" runs", flush=True) rows = list(p_umap(run,run_list)) #rows = list(pool.map(run_, run_list)) print("done", flush=True) @@ -160,7 +160,7 @@ def main(): print("Saving split parts", flush=True) i = 1 for start in range(0, data.shape[0], chunk_size): - print(f"Saving pickle {i}", flush = True) + print("Saving pickle " + str(i), flush = True) temp = data.iloc[start:start + chunk_size] fname = args.savename+"_"+str(i)+".zip" temp.to_pickle(fname) From 27c57037de3e3d2d86ab55d1a8ac05ecbd1c24d5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:23:41 -0400 Subject: [PATCH 048/117] Fix bug --- seirsplus/parallel_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 65bdcac..74050a1 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -119,7 +119,7 @@ def parallel_run(to_do, realizations= 1, keep_in = 0): #print(f"We have {mp.cpu_count()} CPUs") #pool = mp.Pool(mp.cpu_count()) print("Starting execution of " +str(len(run_list)) +" runs", flush=True) - rows = list(p_umap(run,run_list)) + rows = list(p_umap(run_,run_list)) #rows = list(pool.map(run_, run_list)) print("done", flush=True) df = pd.DataFrame(rows) From 38c6ae44272a6a9ff044ffd7dd7a38ddb18edefc Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:27:58 -0400 Subject: [PATCH 049/117] Test --- seirsplus/parallel_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 74050a1..c3847d1 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -68,9 +68,9 @@ def generate_workplace_contact_network_deferred(*args,**kwds): return Defer(generate_workplace_contact_network_,*args,**kwds) -def run(params, keep_model = False): +def run(params_, keep_model = False): """Run an execution with given parameters""" - params = { key: unpack(val) for key,val in params.items() } + params = { key: unpack(val) for key,val in params_.items() } # replace key a value pair of form (k1,k2,k3):(v1,v2,v3) with k1:v1,k2:v2,k3:v3 etc.. # useful if several keys depend on the same deferred computation for key in list(params.keys()): From 705078c76d623a50560a67c380dfb0a60be5129d Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:31:07 -0400 Subject: [PATCH 050/117] For debugging --- seirsplus/parallel_run.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index c3847d1..4d860cd 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -76,6 +76,9 @@ def run(params_, keep_model = False): for key in list(params.keys()): if isinstance(key,tuple): L = params[key] + if not isinstance(L,(list,tuple)): + U = unpack(L) + raise Exception("L is of type " +str(type(L)) + f" and not tuple, L = {L}, U={U}") if len(L) != len(key): raise Exception("Key" + str(key) + "should have same length as value" + str(L)) for i,subkey in enumerate(key): From 26f5acefcfb15379c44a67488bc1b6de0beaa1bd Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:33:44 -0400 Subject: [PATCH 051/117] For debugging --- seirsplus/parallel_run.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 4d860cd..59ce9b3 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -40,10 +40,10 @@ def __init__(self,f,*args,**kwds): def __str__(self): res = self.f_name+"(" res += ", ".join([str(a) for a in self.args]) - if args and kwds: + if self.args and self.kwds: res+=", " - if kwds: - res += ", ".join([str(k)+"="+str(v) for k,v in kwds.items()]) + if self.kwds: + res += ", ".join([str(k)+"="+str(v) for k,v in self.kwds.items()]) return res def eval(self): From f5670d1f9699cc66246f45ec9ec8c8b44d372f0e Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:34:13 -0400 Subject: [PATCH 052/117] For debugging --- seirsplus/parallel_run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 59ce9b3..3f7023e 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -68,6 +68,7 @@ def generate_workplace_contact_network_deferred(*args,**kwds): return Defer(generate_workplace_contact_network_,*args,**kwds) + def run(params_, keep_model = False): """Run an execution with given parameters""" params = { key: unpack(val) for key,val in params_.items() } From 977874bec522265e0ded2029748608def0f40855 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:36:05 -0400 Subject: [PATCH 053/117] More robust type check for pickling --- seirsplus/parallel_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 3f7023e..271eead 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -53,7 +53,7 @@ def eval(self): return f(*args_,**kwds_) def unpack(O): - if isinstance(O,Defer): + if "Defer" in type(O).__name__: return O.eval() return O From 37b923da1f044a75a50c48f7cd79781ff99c64f1 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:39:19 -0400 Subject: [PATCH 054/117] fix bug --- seirsplus/parallel_run.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 271eead..6713bb7 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -78,8 +78,7 @@ def run(params_, keep_model = False): if isinstance(key,tuple): L = params[key] if not isinstance(L,(list,tuple)): - U = unpack(L) - raise Exception("L is of type " +str(type(L)) + f" and not tuple, L = {L}, U={U}") + raise Exception("L is of type " +str(type(L)) + " and not tuple (L= " + str(L) +")") if len(L) != len(key): raise Exception("Key" + str(key) + "should have same length as value" + str(L)) for i,subkey in enumerate(key): @@ -87,7 +86,7 @@ def run(params_, keep_model = False): del params[key] if ('G_Q' not in params) or (not params['G_Q']): - params['G_Q'] = networkx.classes.function.create_empty_copy(MP["G"]) # default quarantine graph is empty + params['G_Q'] = networkx.classes.function.create_empty_copy(params["G"]) # default quarantine graph is empty desc= {} model_params = {} run_params = {} @@ -115,9 +114,8 @@ def run_(T): return summary def parallel_run(to_do, realizations= 1, keep_in = 0): - """Get list of pairs (MP,RP, extra) of model parameters to run, run each given number of realizations in parallel - Among all realizations we keep. - Extra is extra fields for logging and grouping purposes""" + """Get list of dictionaries of model and run parameters to run, run each given number of realizations in parallel + Among all realizations we keep.""" print("Preparing list to run", flush=True) run_list = [(D, r < keep_in) for r in range(realizations) for D in to_do] #print(f"We have {mp.cpu_count()} CPUs") @@ -130,7 +128,7 @@ def parallel_run(to_do, realizations= 1, keep_in = 0): return df def save_to_file(L,filename = 'torun.pickle'): - """Save list of (MP,RP) pairs to run""" + """Save list of parameter dictionaries to run""" with open(filename, 'wb') as handle: pickle.dump(L, handle, protocol=pickle.HIGHEST_PROTOCOL) From 18a8e81c3b445c4bb22261b742cb19f9cde483cd Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:50:22 -0400 Subject: [PATCH 055/117] allow non disjoint isolation groups --- seirsplus/parallel_run.py | 2 +- seirsplus/sim_loops.py | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 6713bb7..55b931f 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -61,7 +61,7 @@ def unpack(O): def generate_workplace_contact_network_(*args,**kwds): """Helper function to produce graph + isolation groups""" G, cohorts, teams = generate_workplace_contact_network(*args,**kwds) - return G, teams.values() + return G, list(teams.values()) def generate_workplace_contact_network_deferred(*args,**kwds): """Returns deferred execution of functoin to generate return graph and isolation groups""" diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index c3e3a02..023a1bb 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -234,13 +234,15 @@ def vprint(s): #---------------------------------------- # Isolate the GROUPMATES of this SYMPTOMATIC node without a test: #---------------------------------------- - if(isolation_groups is not None and any(isolation_compliance_symptomatic_groupmate)): - isolationGroupmates = next((group for group in isolation_groups if symptomaticNode in group), None) - for isolationGroupmate in isolationGroupmates: - if(isolationGroupmate != symptomaticNode): - if(isolation_compliance_symptomatic_groupmate[isolationGroupmate]): - numSelfIsolated_symptomaticGroupmate += 1 - newIsolationGroup_symptomatic.append(isolationGroupmate) + if(isolation_groups is not None) and any(isolation_compliance_symptomatic_groupmate): + for group in isolation_groups: # allow non disjoint groups + if not symptomaticNode in group: + continue + for isolationGroupmate in group: + if(isolationGroupmate != symptomaticNode): + if(isolation_compliance_symptomatic_groupmate[isolationGroupmate]): + numSelfIsolated_symptomaticGroupmate += 1 + newIsolationGroup_symptomatic.append(isolationGroupmate) #---------------------------------------- From 647e12b889a3ae93bd1f8106c7a3dadc9246b344 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 11:58:40 -0400 Subject: [PATCH 056/117] allow non disjoint isolation groups --- seirsplus/sim_loops.py | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 023a1bb..2d47a49 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -240,11 +240,10 @@ def vprint(s): continue for isolationGroupmate in group: if(isolationGroupmate != symptomaticNode): - if(isolation_compliance_symptomatic_groupmate[isolationGroupmate]): + if (isolation_compliance_symptomatic_groupmate[isolationGroupmate]): numSelfIsolated_symptomaticGroupmate += 1 newIsolationGroup_symptomatic.append(isolationGroupmate) - #---------------------------------------- # Isolate the CONTACTS of detected POSITIVE cases without a test: #---------------------------------------- @@ -260,14 +259,16 @@ def vprint(s): #---------------------------------------- # Isolate the GROUPMATES of this self-isolating CONTACT without a test: #---------------------------------------- - if(isolation_groups is not None and any(isolation_compliance_positive_contactgroupmate)): - isolationGroupmates = next((group for group in isolation_groups if contactNode in group), None) - for isolationGroupmate in isolationGroupmates: - # if(isolationGroupmate != contactNode): - if(isolation_compliance_positive_contactgroupmate[isolationGroupmate]): - newIsolationGroup_contact.append(isolationGroupmate) - numSelfIsolated_positiveContactGroupmate += 1 - + if (isolation_groups is not None) and any(isolation_compliance_positive_contactgroupmate): + for group in isolation_groups: # allow non disjoint groups + if not contactNode in group: + continue + for isolationGroupmate in group: + if (isolationGroupmate != contactNode): # do not include node itself + if (isolation_compliance_positive_contactgroupmate[isolationGroupmate]): + newIsolationGroup_contact.append(isolationGroupmate) + numSelfIsolated_positiveContactGroupmate += 1 + #---------------------------------------- # Update the nodeStates list after self-isolation updates to model.X: @@ -442,14 +443,17 @@ def vprint(s): #---------------------------------------- # Add the groupmates of this positive node to the isolation group: - #---------------------------------------- - if(isolation_groups is not None and any(isolation_compliance_positive_groupmate)): - isolationGroupmates = next((group for group in isolation_groups if testNode in group), None) - for isolationGroupmate in isolationGroupmates: - if(isolationGroupmate != testNode): - if(isolation_compliance_positive_groupmate[isolationGroupmate]): - numIsolated_positiveGroupmate += 1 - newIsolationGroup_positive.append(isolationGroupmate) + #---------------------------------------- + if (isolation_groups is not None) and any(isolation_compliance_symptomatic_groupmate): + for group in isolation_groups: # allow non disjoint groups + if not testNode in group: + continue + for isolationGroupmate in group: + if (isolationGroupmate != testNode): + if (isolation_compliance_symptomatic_groupmate[isolationGroupmate]): + numSelfIsolated_symptomaticGroupmate += 1 + newIsolationGroup_symptomatic.append(isolationGroupmate) + #---------------------------------------- # Add this node's neighbors to the contact tracing pool: From 0989ce6c951d9c3313dacaff5bd2c9300c34d980 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 12:37:10 -0400 Subject: [PATCH 057/117] log first detection time, separate out from isolation logic --- seirsplus/sim_loops.py | 4 ++-- seirsplus/utilities.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 2d47a49..daa73ff 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -505,7 +505,7 @@ def vprint(s): numIsolated += 1 isolationGroup_positive = isolationQueue_positive.pop(0) - positiveTestResults = len(isolationGroup_positive) + enterIsolationPositive = len(isolationGroup_positive) for isolationNode in isolationGroup_positive: model.set_isolation(isolationNode, True) numIsolated += 1 @@ -523,7 +523,7 @@ def vprint(s): "numIsolated_positiveGroupmate" : numIsolated_positiveGroupmate, "numSelfIsolated_positiveContact" : numSelfIsolated_positiveContact, "numIsolated" : numIsolated, - "positiveTestResults": positiveTestResults + "numEnterIsolationPositiveNow": enterIsolationPositive }) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 2481922..852d5c4 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -79,6 +79,14 @@ def hist2df(history , **kwargs): pandas Series of the summary of history, taking the last value and the sum, as well average over time (sum of scaled) Optional kwargs argument - if given then add them to the dataFrame and DataSeries - helpful when merging many logs from different runs. """ + test_lag = 0 + if 'test_lag' in kwargs: + test_lag = kwargs['test_lag'] + else: + for t,d in history.items(): + if 'isolation_lag_positive' in d: + test_lag = d['isolation_lag_positive'] + break L = [{'time': t, **d} for t, d in history.items()] tmax = L[-1]['time'] n = len(L) @@ -98,16 +106,23 @@ def hist2df(history , **kwargs): for key,val in kwargs.items(): df[key] = val summary[key] = val - if "positiveTestResults" in df.columns: - # add summary statistics for when first positive test results are detected - temp = df[df.positiveTestResults > 0] + + detectionTime = -1 + firstPositiveTestTime = -1 + temp = df[df.numPositive>0] + row = None + if len(temp)>0: + firstPositiveTestTime = temp.iloc[0].index + detectionTime = firstPositiveTestTime + test_lag + temp = temp[temp.index> detectionTime] row = temp.iloc[0] if len(temp) else None - vals = [] - labels = [] - for col in orig_cols: - labels.append(col+"/1st") - vals.append(0 if row is None else row[col]) - summary = summary.append(pd.Series(vals,index=labels)) + vals = [firstPositiveTestTime, test_lag, detectionTime] + labels = ['firstPositiveTestTime', 'test_lag', 'detectionTime'] + for col in orig_cols: + labels.append(col+"/1st") + vals.append(0 if row is None else row[col]) + + summary = summary.append(pd.Series(vals,index=labels)) return df, summary @@ -131,3 +146,4 @@ def hist2df(history): + From e4315d5f1315fa9c283428e3e28f567e8a9f5286 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 12:45:05 -0400 Subject: [PATCH 058/117] debugging --- seirsplus/utilities.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 852d5c4..7b53e05 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -113,6 +113,8 @@ def hist2df(history , **kwargs): row = None if len(temp)>0: firstPositiveTestTime = temp.iloc[0].index + print(firstPositiveTestTime, type(firstPositiveTestTime)) + print(test_lag, type(test_lag)) detectionTime = firstPositiveTestTime + test_lag temp = temp[temp.index> detectionTime] row = temp.iloc[0] if len(temp) else None From 8d738cef6ccc745784144201a45ffe84905c9a12 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 12:51:22 -0400 Subject: [PATCH 059/117] fix bug --- seirsplus/utilities.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 7b53e05..d08bb61 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -112,9 +112,7 @@ def hist2df(history , **kwargs): temp = df[df.numPositive>0] row = None if len(temp)>0: - firstPositiveTestTime = temp.iloc[0].index - print(firstPositiveTestTime, type(firstPositiveTestTime)) - print(test_lag, type(test_lag)) + firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag temp = temp[temp.index> detectionTime] row = temp.iloc[0] if len(temp) else None From e51d13fdc52ee4e5d310544d1103dfddfcff3042 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:31:35 -0400 Subject: [PATCH 060/117] improved logging --- seirsplus/utilities.py | 72 +++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index d08bb61..0168111 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -72,6 +72,27 @@ def last(x): """Return last element of a pandas Series""" return x.iloc[-1] + def summarize(df): + """Return a Series with last value, sum of values, and weighted average of values""" + temp = df.copy() + tmax = df['interval_length'].sum() + orig_cols = list(df.columns) + todrop = [] + for col in orig_cols: + temp[col + "/scaled"] = temp[col] * temp['interval_length'] / tmax + todrop.append(col+"/scaled/last") + summary = temp.agg([last, numpy.sum]) + summary = summary.stack() + summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] + summary.drop(todrop,inplace=True) + summary.rename({col+"/scaled/sum": col+"/average" for col in orig_cols},inplace=True) + return summary + + + + + + def hist2df(history , **kwargs): """Take history dictionary and return: @@ -79,34 +100,25 @@ def hist2df(history , **kwargs): pandas Series of the summary of history, taking the last value and the sum, as well average over time (sum of scaled) Optional kwargs argument - if given then add them to the dataFrame and DataSeries - helpful when merging many logs from different runs. """ - test_lag = 0 - if 'test_lag' in kwargs: - test_lag = kwargs['test_lag'] - else: - for t,d in history.items(): - if 'isolation_lag_positive' in d: - test_lag = d['isolation_lag_positive'] - break L = [{'time': t, **d} for t, d in history.items()] - tmax = L[-1]['time'] n = len(L) df = pd.DataFrame(L) df = df.fillna(0) df['interval_length'] = (df['time'] - df['time'].shift(1)).fillna(0) df.set_index('time',inplace=True) df.sort_index(inplace=True) - temp = df.copy() - orig_cols = list(df.columns) - for col in orig_cols: - temp[col + "/scaled"] = temp[col] * temp['interval_length'] / tmax - summary = temp.agg([last, numpy.sum]) - summary = summary.stack() - summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] - if kwargs: - for key,val in kwargs.items(): - df[key] = val - summary[key] = val + summary = summarize(df) + + # add to summary statistics up to first detection + test_lag = 0 + if 'test_lag' in kwargs: + test_lag = kwargs['test_lag'] + else: + for t,d in history.items(): + if 'isolation_lag_positive' in d: + test_lag = d['isolation_lag_positive'] + break detectionTime = -1 firstPositiveTestTime = -1 temp = df[df.numPositive>0] @@ -114,15 +126,17 @@ def hist2df(history , **kwargs): if len(temp)>0: firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag - temp = temp[temp.index> detectionTime] - row = temp.iloc[0] if len(temp) else None - vals = [firstPositiveTestTime, test_lag, detectionTime] - labels = ['firstPositiveTestTime', 'test_lag', 'detectionTime'] - for col in orig_cols: - labels.append(col+"/1st") - vals.append(0 if row is None else row[col]) - - summary = summary.append(pd.Series(vals,index=labels)) + summary2 = summarize(df[df.index<= detectionTime]) + summary.aappend(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) + summary = summary.append(summary2) + if kwargs: + for key,val in kwargs.items(): + if isinstance(val,numpy.ndarray): + val = val.mean() + elif isinstance(val,list) and val and isinstance(val[0],(int,float)): + val = sum(val)/len(val) + df[key] = val + summary[key] = val return df, summary From 0450223dffbd7b395c32add30a3a6db95384688a Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:33:10 -0400 Subject: [PATCH 061/117] fix typo --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 0168111..a26f1df 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -127,7 +127,7 @@ def hist2df(history , **kwargs): firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag summary2 = summarize(df[df.index<= detectionTime]) - summary.aappend(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) + summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) summary = summary.append(summary2) if kwargs: for key,val in kwargs.items(): From 913dad163e7c79c02112707d3aa98ae1d08b50ae Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:36:52 -0400 Subject: [PATCH 062/117] fix div by zero error --- seirsplus/utilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index a26f1df..045a495 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -79,7 +79,7 @@ def summarize(df): orig_cols = list(df.columns) todrop = [] for col in orig_cols: - temp[col + "/scaled"] = temp[col] * temp['interval_length'] / tmax + temp[col + "/scaled"] = (temp[col] * temp['interval_length'] / tmax) if tmax else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) summary = summary.stack() @@ -127,7 +127,7 @@ def hist2df(history , **kwargs): firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag summary2 = summarize(df[df.index<= detectionTime]) - summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) + summary.append(pd.Series([tmax,firstPositiveTestTime, test_lag, detectionTime], index= ['tmax','firstPositiveTestTime', 'test_lag', 'detectionTime')) summary = summary.append(summary2) if kwargs: for key,val in kwargs.items(): From 1622d2877188529628ac4341a19633a79692ba11 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:38:47 -0400 Subject: [PATCH 063/117] fix bug --- seirsplus/utilities.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 045a495..82fcea2 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -127,7 +127,8 @@ def hist2df(history , **kwargs): firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag summary2 = summarize(df[df.index<= detectionTime]) - summary.append(pd.Series([tmax,firstPositiveTestTime, test_lag, detectionTime], index= ['tmax','firstPositiveTestTime', 'test_lag', 'detectionTime')) + summary.append(pd.Series([tmax,firstPositiveTestTime, test_lag, detectionTime], + index= ['tmax','firstPositiveTestTime', 'test_lag', 'detectionTime'])) summary = summary.append(summary2) if kwargs: for key,val in kwargs.items(): @@ -156,8 +157,3 @@ def hist2df(history): - - - - - From a58ccee374be11f71db198c7aa2153da99e160be Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:39:57 -0400 Subject: [PATCH 064/117] fix bug --- seirsplus/utilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 82fcea2..e429414 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -127,8 +127,8 @@ def hist2df(history , **kwargs): firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag summary2 = summarize(df[df.index<= detectionTime]) - summary.append(pd.Series([tmax,firstPositiveTestTime, test_lag, detectionTime], - index= ['tmax','firstPositiveTestTime', 'test_lag', 'detectionTime'])) + summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], + index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) summary = summary.append(summary2) if kwargs: for key,val in kwargs.items(): From ce1c16dcc603a9fb28c83e1022ad6cccda7b3d97 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:47:55 -0400 Subject: [PATCH 065/117] fix bug --- seirsplus/utilities.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index e429414..dd942f9 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -126,10 +126,14 @@ def hist2df(history , **kwargs): if len(temp)>0: firstPositiveTestTime = temp.index[0] detectionTime = firstPositiveTestTime + test_lag - summary2 = summarize(df[df.index<= detectionTime]) + temp = df[df.index<= detectionTime] + if len(temp): + summary2 = summarize(temp) + summary2.rename({col: col+"/1st" for col in summary2.index }) + summary = summary.append(summary2) summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) - summary = summary.append(summary2) + if kwargs: for key,val in kwargs.items(): if isinstance(val,numpy.ndarray): From da7a9b6b4b0ca081c3aca6ea65c011484ced8590 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 13:53:30 -0400 Subject: [PATCH 066/117] make list of dictionaries --- seirsplus/parallel_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 55b931f..389ca99 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -111,7 +111,7 @@ def run_(T): T[0]["verbose"] = False # no printouts when running in parallel df, summary,model = run(T[0],T[1]) summary["model"] = model - return summary + return summary.to_dict() def parallel_run(to_do, realizations= 1, keep_in = 0): """Get list of dictionaries of model and run parameters to run, run each given number of realizations in parallel From 5a7094ae3ca835b592d298371caf089479a543a7 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 14:00:52 -0400 Subject: [PATCH 067/117] make list of dictionaries --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index dd942f9..e1850cf 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -129,7 +129,7 @@ def hist2df(history , **kwargs): temp = df[df.index<= detectionTime] if len(temp): summary2 = summarize(temp) - summary2.rename({col: col+"/1st" for col in summary2.index }) + summary2.rename({col: col+"/1st" for col in summary2.index }, inplace=True) summary = summary.append(summary2) summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) From f9ca71b9bfb2836a2abfea7c00971c555b96993c Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 16:40:55 -0400 Subject: [PATCH 068/117] make list of dictionaries --- seirsplus/utilities.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index e1850cf..57899d9 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -145,6 +145,45 @@ def hist2df(history , **kwargs): return df, summary + def violin_plot(lists, labels, title="", ylabel=""): + sns.set() + fig, ax = plt.subplots(figsize=(16, 8)) + + vp = ax.violinplot(lists, showmeans=True) + i = 1 + for pc in vp['bodies']: + pc.set_color(f'C{i}') + + for partname in ('cbars', 'cmins', 'cmaxes', 'cmeans'): + pc = vp[partname] + pc.set_edgecolor("black") + pc.set_linewidth(1) + + ax.get_xaxis().set_tick_params(direction='out') + ax.xaxis.set_ticks_position('bottom') + ax.set_xticks(np.arange(1, len(labels) + 1)) + ax.set_xticklabels(labels) + ax.set_xlim(0.25, len(labels) + 0.75) + ax.set_ylabel(ylabel) + if title: + ax.set_title(title) + for tick in ax.get_xticklabels(): + tick.set_rotation(45) + plt.show() + + + def show_violins(data, field, groupby = 'variant', ylabel=None,title=""): + """Show 'violin graphs' of a certain field according to different variants""" + plots = [] + labels = [] + if ylabel is None: + ylabel = field + for v in sorted(data[groupby].unique()): + plots.append(data[data[groupby] == v][field]) + labels.append(v) + violin_plot(plots, labels, ylabel=ylabel, title=title) + + except ImportError: print("Warning: pandas missing - some logging functions will not work", file=sys.stderr) def last(x): From 6ed10c3028248d0f39702eba227c0d6155d13031 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 17:33:44 -0400 Subject: [PATCH 069/117] make list of dictionaries --- seirsplus/utilities.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 57899d9..b7f8cff 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -67,6 +67,7 @@ def results_summary(model): try: import pandas as pd + import seaborn as sns def last(x): """Return last element of a pandas Series""" From 7826dced76e7686bbf75272e15e01a18c9ed099f Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 17:35:45 -0400 Subject: [PATCH 070/117] import sns plt --- seirsplus/utilities.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index b7f8cff..4db9c62 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -68,6 +68,8 @@ def results_summary(model): try: import pandas as pd import seaborn as sns + import matplotlib.pyplot as plt + def last(x): """Return last element of a pandas Series""" From 28dff91134f28e0d0c6d5193520c8221b94481ac Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 1 Sep 2020 17:37:03 -0400 Subject: [PATCH 071/117] typo --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 4db9c62..7826158 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -164,7 +164,7 @@ def violin_plot(lists, labels, title="", ylabel=""): ax.get_xaxis().set_tick_params(direction='out') ax.xaxis.set_ticks_position('bottom') - ax.set_xticks(np.arange(1, len(labels) + 1)) + ax.set_xticks(numpy.arange(1, len(labels) + 1)) ax.set_xticklabels(labels) ax.set_xlim(0.25, len(labels) + 0.75) ax.set_ylabel(ylabel) From c55ba6be7faf536dc53d3760a582d3d5f902b422 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 13:18:20 -0400 Subject: [PATCH 072/117] track overallInfected --- seirsplus/sim_loops.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index daa73ff..d850237 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -153,6 +153,11 @@ def vprint(s): for groupName in model.nodeGroupData: groupData = model.nodeGroupData[groupName] d[groupName+"/"+att] = groupData[att][model.tidx] + d["overallInfected"] = model.numNodes - model.numS[model.tidx] # total number of people infect (initial - susceptible) + if (model.nodeGroupData): + for groupName in model.nodeGroupData: + groupData = model.nodeGroupData[groupName] + d[groupName + "/overallInfected"] = len(groupData['nodes']) - groupData['numS'][model.tidx] log(d) From 0ce715e1cf498d70224e96ac4e0a34e8759e1609 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 13:37:37 -0400 Subject: [PATCH 073/117] log number unquaranteened infectious --- seirsplus/sim_loops.py | 2 ++ seirsplus/utilities.py | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index d850237..8a0d93f 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -153,10 +153,12 @@ def vprint(s): for groupName in model.nodeGroupData: groupData = model.nodeGroupData[groupName] d[groupName+"/"+att] = groupData[att][model.tidx] + d["numInfectious"] = sum( getattr(model,att)[model.tidx] for att in ["numI_pre","numI_sym","numI_asym"]) # number of infectionus non quaranteened people d["overallInfected"] = model.numNodes - model.numS[model.tidx] # total number of people infect (initial - susceptible) if (model.nodeGroupData): for groupName in model.nodeGroupData: groupData = model.nodeGroupData[groupName] + d[groupName+"/numInfectious"] = sum(groupData[att][model.tidx] for att in ["numI_pre","numI_sym","numI_asym"]) d[groupName + "/overallInfected"] = len(groupData['nodes']) - groupData['numS'][model.tidx] log(d) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 7826158..e4a70f2 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -106,8 +106,10 @@ def hist2df(history , **kwargs): L = [{'time': t, **d} for t, d in history.items()] n = len(L) df = pd.DataFrame(L) - df = df.fillna(0) df['interval_length'] = (df['time'] - df['time'].shift(1)).fillna(0) + if 'numPositive' in df.columns: + df['overallPositive'] = df['numPositive'].cumsum() + df = df.fillna(0) df.set_index('time',inplace=True) df.sort_index(inplace=True) summary = summarize(df) @@ -134,15 +136,17 @@ def hist2df(history , **kwargs): summary2 = summarize(temp) summary2.rename({col: col+"/1st" for col in summary2.index }, inplace=True) summary = summary.append(summary2) - summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], + summary = summary.append(pd.Series([firstPositiveTestTime, test_lag, detectionTime], index= ['firstPositiveTestTime', 'test_lag', 'detectionTime'])) if kwargs: for key,val in kwargs.items(): if isinstance(val,numpy.ndarray): val = val.mean() - elif isinstance(val,list) and val and isinstance(val[0],(int,float)): + elif isinstance(val,(list,tuple)) and (len(val)>5) and isinstance(val[0], (int, float, numpy.number)): val = sum(val)/len(val) + elif isinstance(val,str): + val = val[:30] df[key] = val summary[key] = val return df, summary From 5c6878e3615c0a9b1b3b1c589eeba31a4890cccb Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 16:54:18 -0400 Subject: [PATCH 074/117] Don't make parameters to strings --- seirsplus/parallel_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 389ca99..5abf720 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -97,8 +97,8 @@ def run(params_, keep_model = False): run_params[k] = v else: desc[k] = v - desc.update({key : str(val) for key,val in model_params.items() }) - desc.update({key : str(val) for key,val in run_params.items() }) + desc.update({key : val for key,val in model_params.items() }) + desc.update({key : val for key,val in run_params.items() }) model = ExtSEIRSNetworkModel(**model_params) hist = collections.OrderedDict() run_tti_sim(model, history=hist, **run_params) From 5c550019815cc7056495a40e441c11a95912cd21 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 17:08:50 -0400 Subject: [PATCH 075/117] Improved logging --- seirsplus/parallel_run.py | 8 ++++---- seirsplus/utilities.py | 26 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 5abf720..4b327fc 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -12,7 +12,7 @@ from sim_loops import * from utilities import * import collections - +import random import pickle import inspect @@ -87,7 +87,7 @@ def run(params_, keep_model = False): if ('G_Q' not in params) or (not params['G_Q']): params['G_Q'] = networkx.classes.function.create_empty_copy(params["G"]) # default quarantine graph is empty - desc= {} + desc= { "run_id" : random.choice(string.ascii_lowercase,8) } # unique id to help in aggregating model_params = {} run_params = {} for k, v in params.items(): @@ -97,8 +97,8 @@ def run(params_, keep_model = False): run_params[k] = v else: desc[k] = v - desc.update({key : val for key,val in model_params.items() }) - desc.update({key : val for key,val in run_params.items() }) + desc.update({key : make_compact(val) for key,val in model_params.items() }) + desc.update({key : make_compact(val) for key,val in run_params.items() }) model = ExtSEIRSNetworkModel(**model_params) hist = collections.OrderedDict() run_tti_sim(model, history=hist, **run_params) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index e4a70f2..685cec2 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -93,8 +93,23 @@ def summarize(df): - - + def make_compact(val): + """Take a potentially object and reduce it to smaller for logging. + If the object is number - return it + If the object is a long list or ndarray of numbers - return its average + Otherwise, stringify it + If the object is a string - return its first 30 characters + """ + if isinstance(val, (int, float, numpy.number)): + return val + if isinstance(val, numpy.ndarray): + return val.flatten().mean() + if isinstance(val, (list, tuple)): + if len(val)<5: + return val + if isinstance(val[0], (int, float, numpy.number)): + return sum(val) / len(val) + return str(val)[:30] def hist2df(history , **kwargs): @@ -141,12 +156,7 @@ def hist2df(history , **kwargs): if kwargs: for key,val in kwargs.items(): - if isinstance(val,numpy.ndarray): - val = val.mean() - elif isinstance(val,(list,tuple)) and (len(val)>5) and isinstance(val[0], (int, float, numpy.number)): - val = sum(val)/len(val) - elif isinstance(val,str): - val = val[:30] + val = make_compact(val) df[key] = val summary[key] = val return df, summary From 59a75c4330edcb3cbaa9493993a3650475958891 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 17:14:20 -0400 Subject: [PATCH 076/117] missing import --- seirsplus/parallel_run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 4b327fc..b987de1 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -18,6 +18,7 @@ import inspect import networkx import argparse +import string try: from p_tqdm import p_umap # https://github.com/swansonk14/p_tqdm From 8368f0cd8476dbb1b3ca0eaa2d89236a68458aad Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 17:17:04 -0400 Subject: [PATCH 077/117] missing import --- seirsplus/parallel_run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index b987de1..ef9afcb 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -20,6 +20,7 @@ import argparse import string + try: from p_tqdm import p_umap # https://github.com/swansonk14/p_tqdm except ImportError: @@ -88,7 +89,7 @@ def run(params_, keep_model = False): if ('G_Q' not in params) or (not params['G_Q']): params['G_Q'] = networkx.classes.function.create_empty_copy(params["G"]) # default quarantine graph is empty - desc= { "run_id" : random.choice(string.ascii_lowercase,8) } # unique id to help in aggregating + desc= { "run_id" : random.choices(string.ascii_lowercase,k=8) } # unique id to help in aggregating model_params = {} run_params = {} for k, v in params.items(): From 1a9992f59b16aa696d942feca322b39194f3ba4b Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 17:42:19 -0400 Subject: [PATCH 078/117] added support for decreasing budget as pool of people to be tested decreases --- seirsplus/sim_loops.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 8a0d93f..7b8fb54 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -19,6 +19,9 @@ def run_tti_sim(model, T, isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, runTillEnd = False, # True: don't stop simulation if number of infected & isolated is zero, since more external infections may be introduced later + fraction_of_pool = False, + # True: number of daily tests is measured as fraction of eligible pool + # False (default): - measured as fraction of original number of nodes test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) @@ -215,6 +218,23 @@ def vprint(s): nodeTestedInCurrentStateStatuses = model.testedInCurrentState.flatten() nodePositiveStatuses = model.positive.flatten() + log({"PositveStatuses" : sum(nodePositiveStatuses), + "TestedStatuses" : sum(nodeTestedStatuses), + "TestedInCurrentStateStatuses" : sum(nodeTestedInCurrentStateStatuses) + }) + + # number of people that can be tested + poolSize = numpy.sum((nodePositiveStatuses==False) + & (nodeStates != model.R) + & (nodeStates != model.Q_R) + & (nodeStates != model.H) + & (nodeStates != model.F)) + log({"poolSize": poolSize}) + if fraction_of_pool: + tests_per_day = int(model.numNodes * poolSize) + max_tracing_tests_per_day = int(tests_per_day * max_pct_tests_for_traces) + max_symptomatic_tests_per_day = int(tests_per_day * max_pct_tests_for_symptomatics) + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # tracingPoolQueue[0] = tracingPoolQueue[0]Queue.pop(0) From abf3ebd6b3a55fa5782a5ef556b27652c1151c2a Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 3 Sep 2020 17:48:50 -0400 Subject: [PATCH 079/117] fix bug --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 7b8fb54..579b6ce 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -231,7 +231,7 @@ def vprint(s): & (nodeStates != model.F)) log({"poolSize": poolSize}) if fraction_of_pool: - tests_per_day = int(model.numNodes * poolSize) + tests_per_day = int(poolSize * pct_tested_per_day) max_tracing_tests_per_day = int(tests_per_day * max_pct_tests_for_traces) max_symptomatic_tests_per_day = int(tests_per_day * max_pct_tests_for_symptomatics) From 9e1624ed214caffef0ddd84e1256e35de297199b Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 12:24:40 -0400 Subject: [PATCH 080/117] Fix scaled average in logging --- seirsplus/utilities.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 685cec2..ae336b8 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -78,11 +78,12 @@ def last(x): def summarize(df): """Return a Series with last value, sum of values, and weighted average of values""" temp = df.copy() - tmax = df['interval_length'].sum() orig_cols = list(df.columns) todrop = [] for col in orig_cols: - temp[col + "/scaled"] = (temp[col] * temp['interval_length'] / tmax) if tmax else 0 + lengths = (temp[col].dropna().index - temp[col].dropna().index.shift(1)).fillna(0) + total = lengths.sum() + temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) summary = summary.stack() @@ -121,10 +122,8 @@ def hist2df(history , **kwargs): L = [{'time': t, **d} for t, d in history.items()] n = len(L) df = pd.DataFrame(L) - df['interval_length'] = (df['time'] - df['time'].shift(1)).fillna(0) if 'numPositive' in df.columns: - df['overallPositive'] = df['numPositive'].cumsum() - df = df.fillna(0) + df['overallPositive'] = df['numPositive'].fillna(0).cumsum() df.set_index('time',inplace=True) df.sort_index(inplace=True) summary = summarize(df) From 87c572044507356d876b8bebb9e95f7bbb12ee50 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:17:13 -0400 Subject: [PATCH 081/117] Support for policies to stop after detection or to test everyone after detection --- seirsplus/sim_loops.py | 58 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 579b6ce..b7c2b02 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -19,9 +19,8 @@ def run_tti_sim(model, T, isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, runTillEnd = False, # True: don't stop simulation if number of infected & isolated is zero, since more external infections may be introduced later - fraction_of_pool = False, - # True: number of daily tests is measured as fraction of eligible pool - # False (default): - measured as fraction of original number of nodes + budget_policy = None, + # policy to adjust number of daily tests based on initial values and current circumstances test_priority = 'random', # test_priority: how to to choose which nodes to test: # 'random' - use test budget for random fraction of eligible population, 'last_tested' - sort according to the time passed since testing (breaking ties randomly) @@ -121,6 +120,8 @@ def sample(param): model.tmax = T model.runTillEnd = runTillEnd + if not hasattr(model,"lastPositive"): + model.lastPositive = -1 running = True @@ -230,10 +231,18 @@ def vprint(s): & (nodeStates != model.H) & (nodeStates != model.F)) log({"poolSize": poolSize}) - if fraction_of_pool: - tests_per_day = int(poolSize * pct_tested_per_day) - max_tracing_tests_per_day = int(tests_per_day * max_pct_tests_for_traces) - max_symptomatic_tests_per_day = int(tests_per_day * max_pct_tests_for_symptomatics) + if budget_policy: + tests_per_day, max_tracing_tests_per_day, max_symptomatic_tests_per_day = budget_policy( + model, + hist, + poolSize=poolSize, + pct_tested_per_day = pct_tested_per_day, + max_pct_tests_for_traces = max_pct_tests_for_traces, + max_pct_tests_for_symptomatics = max_pct_tests_for_symptomatics) + log({"tests_per_day": tests_per_day, + "max_tracing_tests_per_day" : max_tracing_tests_per_day, + "max_symptomatic_tests_per_day" : max_symptomatic_tests_per_day + }) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -505,6 +514,8 @@ def vprint(s): log({"newTracingPool" : len(newTracingPool)}) tracingPoolQueue.append(newTracingPool) + if numPositive: + model.lastPositive = model.t vprint("\t"+str(numTested_symptomatic) +"\ttested due to symptoms [+ "+str(numPositive_symptomatic)+" positive (%.2f %%) +]" % (numPositive_symptomatic/numTested_symptomatic*100 if numTested_symptomatic>0 else 0)) vprint("\t"+str(numTested_tracing) +"\ttested as traces [+ "+str(numPositive_tracing)+" positive (%.2f %%) +]" % (numPositive_tracing/numTested_tracing*100 if numTested_tracing>0 else 0)) @@ -565,3 +576,36 @@ def vprint(s): #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# Policy generation functions + +def hammer_and_dance(lag=1,hammer_wait = 7, test_schedule = [0], frac_of_pool=True): + """Returns a budget policy function that will test everyone if there is a positive test result. + Otherwise go by the other budget parameters - if frac_of_pool=True then testing budget depends on eligible pool and + not on original number of nodes""" + def test_policy(model, hist, poolSize, pct_tested_per_day, max_pct_tests_for_symptomatics): + if not hasattr(model,"lastHammer"): + model.lastHammer = -hammer_wait + if (model.lastPositive>=0): + detectionTime = model.lastPositive + lag + if model.lastHammer < detectionTime - hammer_wait: + model.lastHammer = detectionTime + model.lastSchedule = [detectionTime + offset for offset in test_schedule] + for i,t in enumerate(model.lastSchedule): + if int(model.t) == int(t): + model.lastSchedule[i] = -1 + # test everyone + return model.numNodes,model.numNodes,model.numNodes + + N = poolSize if frac_of_pool else model.numNodes + tests_per_day = int(N * pct_tested_per_day) + max_tracing_tests_per_day = int(tests_per_day * max_pct_tests_for_traces) + max_symptomatic_tests_per_day = int(tests_per_day * max_pct_tests_for_symptomatics) + return tests_per_day, max_tracing_tests_per_day, max_symptomatic_tests_per_day + return test_policy + +def stop_at_detection(lag=1): + """Returns stopping policy function that stops after the first positive result""" + def policy(model, hist): + # stop if there was a positive result after lag time + return (model.lastPositive>=0) and (model.lastPositive+lag <= model.t) + return policy From e729aa03238e8977ae40fbfeaeef95c4b1a0284c Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:22:50 -0400 Subject: [PATCH 082/117] fix typo --- seirsplus/sim_loops.py | 2 +- seirsplus/utilities.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index b7c2b02..a9d6a48 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -234,7 +234,7 @@ def vprint(s): if budget_policy: tests_per_day, max_tracing_tests_per_day, max_symptomatic_tests_per_day = budget_policy( model, - hist, + history, poolSize=poolSize, pct_tested_per_day = pct_tested_per_day, max_pct_tests_for_traces = max_pct_tests_for_traces, diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index ae336b8..03ccdc9 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -63,7 +63,7 @@ def results_summary(model): ######################################################################################################################################### -# Logging packages - requires pandas + try: import pandas as pd From 8baab947f5e6baa3f3ab5df3cdc0b104b5d7f9f6 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:25:01 -0400 Subject: [PATCH 083/117] add missing argument --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index a9d6a48..09fe58b 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -582,7 +582,7 @@ def hammer_and_dance(lag=1,hammer_wait = 7, test_schedule = [0], frac_of_pool=Tr """Returns a budget policy function that will test everyone if there is a positive test result. Otherwise go by the other budget parameters - if frac_of_pool=True then testing budget depends on eligible pool and not on original number of nodes""" - def test_policy(model, hist, poolSize, pct_tested_per_day, max_pct_tests_for_symptomatics): + def test_policy(model, hist, poolSize, pct_tested_per_day, max_pct_tests_for_symptomatics, max_pct_tests_for_traces): if not hasattr(model,"lastHammer"): model.lastHammer = -hammer_wait if (model.lastPositive>=0): From cd0b3fdcc266b2faaffaf376b35d75da725b904c Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:29:24 -0400 Subject: [PATCH 084/117] fix bug in interval scaling --- seirsplus/utilities.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 03ccdc9..83b891a 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -81,7 +81,9 @@ def summarize(df): orig_cols = list(df.columns) todrop = [] for col in orig_cols: - lengths = (temp[col].dropna().index - temp[col].dropna().index.shift(1)).fillna(0) + len1 = temp[col].dropna().index + len2 = temp[col].dropna().shift(1).index + lengths = (len1-len2).fillna(0) total = lengths.sum() temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 todrop.append(col+"/scaled/last") From 2347cd4310f6656d184354ab002e06eb4dea9af9 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:34:58 -0400 Subject: [PATCH 085/117] fix bug in interval scaling --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 83b891a..dfb54bc 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -84,7 +84,7 @@ def summarize(df): len1 = temp[col].dropna().index len2 = temp[col].dropna().shift(1).index lengths = (len1-len2).fillna(0) - total = lengths.sum() + total = pd.to_numeric(lengths).sum() temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) From 928d19488b44cf7591b9a961ca40ae42889ae838 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:36:45 -0400 Subject: [PATCH 086/117] fix bug in interval scaling --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index dfb54bc..3105699 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -84,7 +84,7 @@ def summarize(df): len1 = temp[col].dropna().index len2 = temp[col].dropna().shift(1).index lengths = (len1-len2).fillna(0) - total = pd.to_numeric(lengths).sum() + total = lengths.astype(float).sum() temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) From f8c2a9cb11b4eb59095c52d6fa05e2b7a92d10f8 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 13:41:07 -0400 Subject: [PATCH 087/117] fix bug in interval scaling --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 3105699..6529176 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -84,7 +84,7 @@ def summarize(df): len1 = temp[col].dropna().index len2 = temp[col].dropna().shift(1).index lengths = (len1-len2).fillna(0) - total = lengths.astype(float).sum() + total = sum(lengths) temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) From d304abe4e456578ed9954e85b51bcd3e61048f8f Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:20:57 -0400 Subject: [PATCH 088/117] fix another bug in interval scaling --- seirsplus/utilities.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 6529176..b08af72 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -81,11 +81,10 @@ def summarize(df): orig_cols = list(df.columns) todrop = [] for col in orig_cols: - len1 = temp[col].dropna().index - len2 = temp[col].dropna().shift(1).index - lengths = (len1-len2).fillna(0) + tempcol = temp[col].dropna().reset_index(name=col) + lengths = (tempcol.iloc[:,0] - tempcol.shift(1).iloc[:,0]).fillna(0) total = sum(lengths) - temp[col + "/scaled"] = (temp[col] * lengths / total) if total else 0 + temp[col+"/scaled"] = tempcol[col] * lengths / total if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) summary = summary.stack() From ba29a9a50ca9d0af772484966407477b7b21259d Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:28:51 -0400 Subject: [PATCH 089/117] fix another bug in interval scaling --- seirsplus/utilities.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index b08af72..f1ec2d4 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -81,10 +81,11 @@ def summarize(df): orig_cols = list(df.columns) todrop = [] for col in orig_cols: - tempcol = temp[col].dropna().reset_index(name=col) - lengths = (tempcol.iloc[:,0] - tempcol.shift(1).iloc[:,0]).fillna(0) + if col == 'time': continue + tcol = temp[['time',col]].dropna() + lengths = (tcol['time'] - tcol['time'].shift(1)).fillna(0) total = sum(lengths) - temp[col+"/scaled"] = tempcol[col] * lengths / total if total else 0 + temp[col+"/scaled"] = tcol[col] * lengths / total if total else 0 todrop.append(col+"/scaled/last") summary = temp.agg([last, numpy.sum]) summary = summary.stack() @@ -125,8 +126,6 @@ def hist2df(history , **kwargs): df = pd.DataFrame(L) if 'numPositive' in df.columns: df['overallPositive'] = df['numPositive'].fillna(0).cumsum() - df.set_index('time',inplace=True) - df.sort_index(inplace=True) summary = summarize(df) # add to summary statistics up to first detection @@ -144,9 +143,9 @@ def hist2df(history , **kwargs): temp = df[df.numPositive>0] row = None if len(temp)>0: - firstPositiveTestTime = temp.index[0] + firstPositiveTestTime = temp['time'][0] detectionTime = firstPositiveTestTime + test_lag - temp = df[df.index<= detectionTime] + temp = df[df['time']<= detectionTime] if len(temp): summary2 = summarize(temp) summary2.rename({col: col+"/1st" for col in summary2.index }, inplace=True) From 2e5f1bf7d983bf6ce83fa70f6ea99d0fa5f65de3 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:32:22 -0400 Subject: [PATCH 090/117] fix another bug in interval scaling --- seirsplus/utilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index f1ec2d4..bdc7a36 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -85,8 +85,9 @@ def summarize(df): tcol = temp[['time',col]].dropna() lengths = (tcol['time'] - tcol['time'].shift(1)).fillna(0) total = sum(lengths) - temp[col+"/scaled"] = tcol[col] * lengths / total if total else 0 + temp.loc[col+"/scaled"] = tcol[col] * lengths / total if total else 0 todrop.append(col+"/scaled/last") + temp = temp.fillna(0) summary = temp.agg([last, numpy.sum]) summary = summary.stack() summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] From 04dee3a28d6b6380988a80d3c72d62b79bb3ea13 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:38:02 -0400 Subject: [PATCH 091/117] fix another bug in interval scaling --- seirsplus/utilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index bdc7a36..365f16a 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -85,12 +85,13 @@ def summarize(df): tcol = temp[['time',col]].dropna() lengths = (tcol['time'] - tcol['time'].shift(1)).fillna(0) total = sum(lengths) - temp.loc[col+"/scaled"] = tcol[col] * lengths / total if total else 0 + temp = temp.assign(**{col+"/scaled": tcol[col] * lengths / total if total else 0}) todrop.append(col+"/scaled/last") temp = temp.fillna(0) summary = temp.agg([last, numpy.sum]) summary = summary.stack() summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] + print(summary.index) summary.drop(todrop,inplace=True) summary.rename({col+"/scaled/sum": col+"/average" for col in orig_cols},inplace=True) return summary From 17db0b2abd80756b521c21547f3626e3834639b5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:39:15 -0400 Subject: [PATCH 092/117] drop printing --- seirsplus/utilities.py | 1 - 1 file changed, 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 365f16a..988beaa 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -91,7 +91,6 @@ def summarize(df): summary = temp.agg([last, numpy.sum]) summary = summary.stack() summary.index = ['/'.join(reversed(col)).strip() for col in summary.index.values] - print(summary.index) summary.drop(todrop,inplace=True) summary.rename({col+"/scaled/sum": col+"/average" for col in orig_cols},inplace=True) return summary From 1ec9ef35b3b67a0fb41657629ed1a8244b8d6fb0 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Tue, 8 Sep 2020 18:41:43 -0400 Subject: [PATCH 093/117] another log bug --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 988beaa..3138cac 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -144,7 +144,7 @@ def hist2df(history , **kwargs): temp = df[df.numPositive>0] row = None if len(temp)>0: - firstPositiveTestTime = temp['time'][0] + firstPositiveTestTime = temp['time'].iloc[0] detectionTime = firstPositiveTestTime + test_lag temp = df[df['time']<= detectionTime] if len(temp): From 8b4bdf0fcbf2ddffeb5bcb15890719e2c3ff1ffa Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 10 Sep 2020 12:39:23 -0400 Subject: [PATCH 094/117] violin alignment --- seirsplus/utilities.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 3138cac..546f821 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -185,17 +185,17 @@ def violin_plot(lists, labels, title="", ylabel=""): if title: ax.set_title(title) for tick in ax.get_xticklabels(): - tick.set_rotation(45) + tick.set_rotation(45,ha="right") plt.show() - def show_violins(data, field, groupby = 'variant', ylabel=None,title=""): + def show_violins(data, field, groupby = 'variant', ylabel=None,title="", key = None): """Show 'violin graphs' of a certain field according to different variants""" plots = [] labels = [] if ylabel is None: ylabel = field - for v in sorted(data[groupby].unique()): + for v in sorted(data[groupby].unique(), key=key): plots.append(data[data[groupby] == v][field]) labels.append(v) violin_plot(plots, labels, ylabel=ylabel, title=title) From 707aeeb8e309d45c7988de5aa0cd936f4ff2f11e Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 10 Sep 2020 12:56:16 -0400 Subject: [PATCH 095/117] modified parenthesis --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 09fe58b..8f86b03 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -205,7 +205,7 @@ def vprint(s): currentPctInfected = model.total_num_infected()[model.tidx]/model.numNodes log({"currentNumInfected": currentNumInfected , "cadenceDayNumber": cadenceDayNumber }) - if(currentPctInfected >= intervention_start_pct_infected and not interventionOn): + if(currentPctInfected >= intervention_start_pct_infected) and (not interventionOn): interventionOn = True interventionStartTime = model.t From 2d24ac6d82de79d480efe19cfb661bb74c6f6385 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 10 Sep 2020 13:03:59 -0400 Subject: [PATCH 096/117] fix tick alignment --- seirsplus/utilities.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 546f821..279bab3 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -179,13 +179,11 @@ def violin_plot(lists, labels, title="", ylabel=""): ax.get_xaxis().set_tick_params(direction='out') ax.xaxis.set_ticks_position('bottom') ax.set_xticks(numpy.arange(1, len(labels) + 1)) - ax.set_xticklabels(labels) + ax.set_xticklabels(llabels, rotation=45, ha='right') ax.set_xlim(0.25, len(labels) + 0.75) ax.set_ylabel(ylabel) if title: ax.set_title(title) - for tick in ax.get_xticklabels(): - tick.set_rotation(45,ha="right") plt.show() From b3f030b625339164284406fb966fad8ae0a28949 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 10 Sep 2020 13:26:28 -0400 Subject: [PATCH 097/117] longer strings --- seirsplus/utilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 279bab3..309fcf1 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -113,7 +113,8 @@ def make_compact(val): return val if isinstance(val[0], (int, float, numpy.number)): return sum(val) / len(val) - return str(val)[:30] + return str(val)[:64] + def hist2df(history , **kwargs): From 874694ad6497aa7ce1a69129621f82fcaf9cb3e4 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 10 Sep 2020 13:31:05 -0400 Subject: [PATCH 098/117] fix typo --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 309fcf1..a19bcb4 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -180,7 +180,7 @@ def violin_plot(lists, labels, title="", ylabel=""): ax.get_xaxis().set_tick_params(direction='out') ax.xaxis.set_ticks_position('bottom') ax.set_xticks(numpy.arange(1, len(labels) + 1)) - ax.set_xticklabels(llabels, rotation=45, ha='right') + ax.set_xticklabels(labels, rotation=45, ha='right') ax.set_xlim(0.25, len(labels) + 0.75) ax.set_ylabel(ylabel) if title: From ce82dcf8b49f7c2d370b4cd12e5010e77c897f37 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 10:00:50 -0400 Subject: [PATCH 099/117] Import all of networkx graph gen routines --- seirsplus/parallel_run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index ef9afcb..615374a 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -19,6 +19,7 @@ import networkx import argparse import string +from networkx import * try: From bc707c11722b43249160ff8869d82dd56f89de5c Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 10:09:37 -0400 Subject: [PATCH 100/117] Allow digraphs --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 13ece33..e10897b 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1965,7 +1965,7 @@ def update_parameters(self): # Adjacency matrix: if type(self.G)==numpy.ndarray: self.A = scipy.sparse.csr_matrix(self.G) - elif type(self.G)==networkx.classes.graph.Graph: + elif (type(self.G)==networkx.classes.graph.Graph) or (type(self.G)==networkx.classes.digraph.DiGraph): self.A = networkx.adj_matrix(self.G) # adj_matrix gives scipy.sparse csr_matrix else: raise BaseException("Input an adjacency matrix or networkx object only.") From 6d6e26ae5f123e79aabe5d4ec59058d441100a69 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 10:11:53 -0400 Subject: [PATCH 101/117] Allow digraphs --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index e10897b..50786f7 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1979,7 +1979,7 @@ def update_parameters(self): # Quarantine Adjacency matrix: if type(self.G_Q)==numpy.ndarray: self.A_Q = scipy.sparse.csr_matrix(self.G_Q) - elif type(self.G_Q)==networkx.classes.graph.Graph: + elif (type(self.G_Q)==networkx.classes.graph.Graph) or (type(self.G_Q)==networkx.classes.digraph.DiGraph): self.A_Q = networkx.adj_matrix(self.G_Q) # adj_matrix gives scipy.sparse csr_matrix else: raise BaseException("Input an adjacency matrix or networkx object only.") From 5c760d8db2c695c714df2df652da9f4d786f0998 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 13:28:02 -0400 Subject: [PATCH 102/117] Add support for single introduction --- seirsplus/sim_loops.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 8f86b03..dbb9c7b 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -18,6 +18,7 @@ def run_tti_sim(model, T, isolation_compliance_positive_contact=[None], isolation_compliance_positive_contactgroupmate=[None], isolation_lag_symptomatic=1, isolation_lag_positive=1, isolation_lag_contact=0, isolation_groups=None, cadence_testing_days=None, cadence_cycle_length=28, temporal_falseneg_rates=None, + introduction_days = [], # introduce a single exposure in these days runTillEnd = False, # True: don't stop simulation if number of infected & isolated is zero, since more external infections may be introduced later budget_policy = None, # policy to adjust number of daily tests based on initial values and current circumstances @@ -67,6 +68,7 @@ def sample(param): + # Testing cadences involve a repeating 28 day cycle starting on a Monday # (0:Mon, 1:Tue, 2:Wed, 3:Thu, 4:Fri, 5:Sat, 6:Sun, 7:Mon, 8:Tues, ...) # For each cadence, testing is done on the day numbers included in the associated list. @@ -177,7 +179,9 @@ def vprint(s): if(int(model.t)!=int(timeOfLastIntroduction)): timeOfLastIntroduction = model.t - + if introduction_days: + if int(model.t) in introduction_days: + numNewExposures = 1 # introduce a single exposure in that day if isinstance(average_introductions_per_day,dict): numNewExposures = {} for group,num in average_introductions_per_day.items(): @@ -609,3 +613,8 @@ def policy(model, hist): # stop if there was a positive result after lag time return (model.lastPositive>=0) and (model.lastPositive+lag <= model.t) return policy + + +def single_introduction(end): + """Single return a single introduction day for the introduction_days parameter""" + return [random.randint(0,end)] \ No newline at end of file From e55508641e0cc916788781ae5da21286f94a4c56 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 13:42:31 -0400 Subject: [PATCH 103/117] Logging bug --- seirsplus/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index a19bcb4..9a7cfad 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -110,7 +110,7 @@ def make_compact(val): return val.flatten().mean() if isinstance(val, (list, tuple)): if len(val)<5: - return val + return str(val) if isinstance(val[0], (int, float, numpy.number)): return sum(val) / len(val) return str(val)[:64] From 7ab0ba4aeae8a49a8ffaf2920f0c26f71564f1b4 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 14:09:14 -0400 Subject: [PATCH 104/117] Introduction of exposures code --- seirsplus/parallel_run.py | 2 ++ seirsplus/sim_loops.py | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/seirsplus/parallel_run.py b/seirsplus/parallel_run.py index 615374a..7a8c203 100644 --- a/seirsplus/parallel_run.py +++ b/seirsplus/parallel_run.py @@ -102,6 +102,8 @@ def run(params_, keep_model = False): desc[k] = v desc.update({key : make_compact(val) for key,val in model_params.items() }) desc.update({key : make_compact(val) for key,val in run_params.items() }) + if ("verbose" in params_) and params_["verbose"]: + print("Parameters :", desc) model = ExtSEIRSNetworkModel(**model_params) hist = collections.OrderedDict() run_tti_sim(model, history=hist, **run_params) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index dbb9c7b..256ecab 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -179,15 +179,16 @@ def vprint(s): if(int(model.t)!=int(timeOfLastIntroduction)): timeOfLastIntroduction = model.t - if introduction_days: - if int(model.t) in introduction_days: - numNewExposures = 1 # introduce a single exposure in that day + baseline_exposure = 0 + if introduction_days and (int(model.t) in introduction_days): + vprint("Introduced new exposure at time", model.t) + baseline_exposure = 1 # introduce a single exposure in that day if isinstance(average_introductions_per_day,dict): numNewExposures = {} for group,num in average_introductions_per_day.items(): - numNewExposures[group] = numpy.random.poisson(lam=num) + numNewExposures[group] = baseline_exposure+numpy.random.poisson(lam=num) else: - numNewExposures = numpy.random.poisson(lam=average_introductions_per_day) + numNewExposures = baseline_exposure+numpy.random.poisson(lam=average_introductions_per_day) model.introduce_exposures(num_new_exposures=numNewExposures) log({"numNewExposures": numNewExposures}) From b92b28ce0fc7cdb5c5186793317da01d3db1a785 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Fri, 11 Sep 2020 14:11:45 -0400 Subject: [PATCH 105/117] fix log --- seirsplus/sim_loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 256ecab..365bcfd 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -181,7 +181,7 @@ def vprint(s): timeOfLastIntroduction = model.t baseline_exposure = 0 if introduction_days and (int(model.t) in introduction_days): - vprint("Introduced new exposure at time", model.t) + vprint("introduced new exposure at time "+ str(model.t)) baseline_exposure = 1 # introduce a single exposure in that day if isinstance(average_introductions_per_day,dict): numNewExposures = {} From 88c22d918103b82c5ec204e04490165ea7ea031d Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 14 Sep 2020 12:51:57 -0400 Subject: [PATCH 106/117] frequency --- seirsplus/sim_loops.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 365bcfd..3c9e131 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -582,6 +582,12 @@ def vprint(s): #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Policy generation functions +def scale_to_pool(model, hist, poolSize, pct_tested_per_day, max_pct_tests_for_symptomatics, max_pct_tests_for_traces): + N = poolSize + tests_per_day = int(N * pct_tested_per_day) + max_tracing_tests_per_day = int(tests_per_day * max_pct_tests_for_traces) + max_symptomatic_tests_per_day = int(tests_per_day * max_pct_tests_for_symptomatics) + return tests_per_day, max_tracing_tests_per_day, max_symptomatic_tests_per_day def hammer_and_dance(lag=1,hammer_wait = 7, test_schedule = [0], frac_of_pool=True): """Returns a budget policy function that will test everyone if there is a positive test result. @@ -618,4 +624,11 @@ def policy(model, hist): def single_introduction(end): """Single return a single introduction day for the introduction_days parameter""" - return [random.randint(0,end)] \ No newline at end of file + return [random.randint(0,end)] + +def test_frequency(frequency): + MAX_TIME = 365 + testing_cadence = f"every {frequency}" + offset = random.randint(0,frequency-1) + cadence_testing_days = { testing_cadence : [offset+i for i in range(MAX_TIME) if (i % frequency ==0)] } + return testing_cadence, cadence_testing_days \ No newline at end of file From 23f664e2fc8ca74b66991ee1231e338254ad6101 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 14 Sep 2020 15:38:42 -0400 Subject: [PATCH 107/117] update cadence cycle length --- seirsplus/sim_loops.py | 3 ++- seirsplus/utilities.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index 3c9e131..daaf3fc 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -631,4 +631,5 @@ def test_frequency(frequency): testing_cadence = f"every {frequency}" offset = random.randint(0,frequency-1) cadence_testing_days = { testing_cadence : [offset+i for i in range(MAX_TIME) if (i % frequency ==0)] } - return testing_cadence, cadence_testing_days \ No newline at end of file + cadence_cycle_length = MAX_TIME + return testing_cadence, cadence_testing_days, cadence_cycle_length \ No newline at end of file diff --git a/seirsplus/utilities.py b/seirsplus/utilities.py index 9a7cfad..3708acb 100644 --- a/seirsplus/utilities.py +++ b/seirsplus/utilities.py @@ -163,7 +163,7 @@ def hist2df(history , **kwargs): return df, summary - def violin_plot(lists, labels, title="", ylabel=""): + def violin_plot(lists, labels, title="", ylabel="", xlabel=""): sns.set() fig, ax = plt.subplots(figsize=(16, 8)) @@ -183,6 +183,8 @@ def violin_plot(lists, labels, title="", ylabel=""): ax.set_xticklabels(labels, rotation=45, ha='right') ax.set_xlim(0.25, len(labels) + 0.75) ax.set_ylabel(ylabel) + if xlabel: + ax.set_xlabel(xlabel) if title: ax.set_title(title) plt.show() From 1a397633913edf313e1c9019dd6fc4366beaaa26 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Wed, 16 Sep 2020 16:42:53 -0400 Subject: [PATCH 108/117] update cadence cycle length --- seirsplus/sim_loops.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/sim_loops.py b/seirsplus/sim_loops.py index daaf3fc..23cf2e9 100644 --- a/seirsplus/sim_loops.py +++ b/seirsplus/sim_loops.py @@ -161,6 +161,7 @@ def vprint(s): d[groupName+"/"+att] = groupData[att][model.tidx] d["numInfectious"] = sum( getattr(model,att)[model.tidx] for att in ["numI_pre","numI_sym","numI_asym"]) # number of infectionus non quaranteened people d["overallInfected"] = model.numNodes - model.numS[model.tidx] # total number of people infect (initial - susceptible) + d["numNodes"] = model.numNodes if (model.nodeGroupData): for groupName in model.nodeGroupData: groupData = model.nodeGroupData[groupName] From fad92a2af028302267dd991eaeaaa80d4948473d Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 15 Oct 2020 14:08:06 -0400 Subject: [PATCH 109/117] Enable skip asym/sym --- seirsplus/models.py | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 50786f7..811b934 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1724,7 +1724,8 @@ class ExtSEIRSNetworkModel(): initQ_sym Initial number of isolated infectious symptomatic individuals initQ_asym Initial number of isolated infectious asymptomatic individuals initQ_R Initial number of isolated recovered individuals - (all remaining nodes initialized susceptible) + (all remaining nodes initialized susceptible) + skip_pre Skip from pre symptomatic state to H or R state """ def __init__(self, G, beta, sigma, lamda, gamma, gamma_asym=None, eta=0, gamma_H=None, mu_H=0, alpha=1.0, xi=0, mu_0=0, nu=0, a=0, h=0, f=0, p=0, @@ -1735,7 +1736,7 @@ def __init__(self, G, beta, sigma, lamda, gamma, initE=0, initI_pre=0, initI_sym=0, initI_asym=0, initH=0, initR=0, initF=0, initQ_S=0, initQ_E=0, initQ_pre=0, initQ_sym=0, initQ_asym=0, initQ_R=0, o=0, prevalence_ext=0, - transition_mode='exponential_rates', node_groups=None, store_Xseries=False, seed=None): + transition_mode='exponential_rates', node_groups=None, store_Xseries=False, seed=None, skip_pre = False): if(seed is not None): numpy.random.seed(seed) @@ -1759,7 +1760,7 @@ def __init__(self, G, beta, sigma, lamda, gamma, 'initH':initH, 'initR':initR, 'initF':initF, 'initQ_S':initQ_S, 'initQ_E':initQ_E, 'initQ_pre':initQ_pre, 'initQ_sym':initQ_sym, 'initQ_asym':initQ_asym, 'initQ_R':initQ_R, - 'o':o, 'prevalence_ext':prevalence_ext} + 'o':o, 'prevalence_ext':prevalence_ext, 'skip_pre':skip_pre } self.update_parameters() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1880,6 +1881,15 @@ def __init__(self, G, beta, sigma, lamda, gamma, '_toS': {'currentState':True, 'newState':self.S}, } + + if self.skip_pre: + self.transitions.update( + { + 'IPREtoH': {'currentState': self.I_pre, 'newState': self.H }, + 'IPREtoR': {'currentState': self.I_pre, 'newState': self.R } + } + ) + self.transition_mode = transition_mode #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1957,7 +1967,7 @@ def get_mask(self,groupName='all'): # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ def update_parameters(self): - + self.skip_pre = parameters['skip_pre'] # skip from pre-symptomatic state to H/R directly #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Model graphs: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2355,6 +2365,12 @@ def calc_propensities(self): propensities_IPREtoIASYM = 1e5 * ((self.X==self.I_pre) & numpy.greater(self.timer_state, 1/self.lamda) & numpy.less(self.rand_a, self.a)) + if self.skip_pre: + propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoR = 1e5 * ((self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.gamma) & numpy.greater_equal( self.rand_h, self.h)) + propensities_ISYMtoH = 1e5 * ( (self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.eta) & numpy.less(self.rand_h, self.h)) + propensities_ISYMtoR = 1e5 * ((self.X==self.I_sym) & numpy.greater(self.timer_state, 1/self.gamma) & numpy.greater_equal(self.rand_h, self.h)) propensities_ISYMtoH = 1e5 * ((self.X==self.I_sym) & numpy.greater(self.timer_state, 1/self.eta) & numpy.less(self.rand_h, self.h)) @@ -2401,6 +2417,12 @@ def calc_propensities(self): propensities_IPREtoIASYM = self.lamda * ((self.X==self.I_pre) & (numpy.less(self.rand_a, self.a))) + if self.skip_pre: + propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoR = self.gamma * ((self.X == self.I_pre) & (numpy.greater_equal(self.rand_h, self.h))) + propensities_IPREtoH = self.eta * ((self.X == self.I_pre) & (numpy.less(self.rand_h, self.h))) + propensities_ISYMtoR = self.gamma * ((self.X==self.I_sym) & (numpy.greater_equal(self.rand_h, self.h))) propensities_ISYMtoH = self.eta * ((self.X==self.I_sym) & (numpy.less(self.rand_h, self.h))) @@ -2438,18 +2460,21 @@ def calc_propensities(self): propensities__toS = self.nu * (self.X!=self.F) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - propensities = numpy.hstack([propensities_StoE, propensities_EtoIPRE, propensities_IPREtoISYM, propensities_IPREtoIASYM, - propensities_ISYMtoR, propensities_ISYMtoH, propensities_IASYMtoR, propensities_HtoR, propensities_HtoF, - propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, propensities_ISYMtoQSYM, propensities_IASYMtoQASYM, - propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQSYM, propensities_QPREtoQASYM, - propensities_QSYMtoQR, propensities_QSYMtoH, propensities_QASYMtoQR, propensities_RtoS, propensities__toS]) + propensities_list = [propensities_StoE, propensities_EtoIPRE, propensities_IPREtoISYM, propensities_IPREtoIASYM, propensities_ISYMtoR, propensities_ISYMtoH, propensities_IASYMtoR, propensities_HtoR, propensities_HtoF, + propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, propensities_ISYMtoQSYM, propensities_IASYMtoQASYM, + propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQSYM, propensities_QPREtoQASYM, + propensities_QSYMtoQR, propensities_QSYMtoH, propensities_QASYMtoQR, propensities_RtoS, propensities__toS] + if self.skip_pre: + propensities_list += [propensities_IPREtoR, propensities_IPREtoH ] + propensities = numpy.hstack(propensities_list) columns = [ 'StoE', 'EtoIPRE', 'IPREtoISYM', 'IPREtoIASYM', 'ISYMtoR', 'ISYMtoH', 'IASYMtoR', 'HtoR', 'HtoF', 'StoQS', 'EtoQE', 'IPREtoQPRE', 'ISYMtoQSYM', 'IASYMtoQASYM', 'QStoQE', 'QEtoQPRE', 'QPREtoQSYM', 'QPREtoQASYM', 'QSYMtoQR', 'QSYMtoH', 'QASYMtoQR', 'RtoS', '_toS' ] + if self.skip_pre: + columns += ['IPREtoR','IPREtoH'] return propensities, columns From 22542af296de5d20d2d53f8e7cc6b4fbff9a2eea Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Thu, 15 Oct 2020 17:21:46 -0400 Subject: [PATCH 110/117] fix bug --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 811b934..7f02609 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1967,7 +1967,7 @@ def get_mask(self,groupName='all'): # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ def update_parameters(self): - self.skip_pre = parameters['skip_pre'] # skip from pre-symptomatic state to H/R directly + self.skip_pre = self.parameters['skip_pre'] # skip from pre-symptomatic state to H/R directly #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Model graphs: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 663e5d46961028e3c7505522c6767444727f45ce Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 19 Oct 2020 09:54:33 -0400 Subject: [PATCH 111/117] fix typo --- seirsplus/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index 7f02609..ab8fa4d 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2367,7 +2367,7 @@ def calc_propensities(self): if self.skip_pre: propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) propensities_IPREtoR = 1e5 * ((self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.gamma) & numpy.greater_equal( self.rand_h, self.h)) propensities_ISYMtoH = 1e5 * ( (self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.eta) & numpy.less(self.rand_h, self.h)) @@ -2419,7 +2419,7 @@ def calc_propensities(self): if self.skip_pre: propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) propensities_IPREtoR = self.gamma * ((self.X == self.I_pre) & (numpy.greater_equal(self.rand_h, self.h))) propensities_IPREtoH = self.eta * ((self.X == self.I_pre) & (numpy.less(self.rand_h, self.h))) From 3bc53d361143b6377076badb7f1b67b674a42ca0 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 19 Oct 2020 16:04:52 -0400 Subject: [PATCH 112/117] fix typo --- seirsplus/models.py | 77 +++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index ab8fa4d..ca6b7d4 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -1886,7 +1886,9 @@ def __init__(self, G, beta, sigma, lamda, gamma, self.transitions.update( { 'IPREtoH': {'currentState': self.I_pre, 'newState': self.H }, - 'IPREtoR': {'currentState': self.I_pre, 'newState': self.R } + 'IPREtoR': {'currentState': self.I_pre, 'newState': self.R }, + 'QPREtoQR': {'currentState': self.Q_pre, 'newState': self.Q_R}, + 'QPREtoH': {'currentState': self.Q_pre, 'newState': self.H} } ) @@ -2365,11 +2367,6 @@ def calc_propensities(self): propensities_IPREtoIASYM = 1e5 * ((self.X==self.I_pre) & numpy.greater(self.timer_state, 1/self.lamda) & numpy.less(self.rand_a, self.a)) - if self.skip_pre: - propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoR = 1e5 * ((self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.gamma) & numpy.greater_equal( self.rand_h, self.h)) - propensities_ISYMtoH = 1e5 * ( (self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.eta) & numpy.less(self.rand_h, self.h)) propensities_ISYMtoR = 1e5 * ((self.X==self.I_sym) & numpy.greater(self.timer_state, 1/self.gamma) & numpy.greater_equal(self.rand_h, self.h)) @@ -2377,6 +2374,8 @@ def calc_propensities(self): propensities_IASYMtoR = 1e5 * ((self.X==self.I_asym) & numpy.greater(self.timer_state, 1/self.gamma)) + + propensities_HtoR = 1e5 * ((self.X==self.H) & numpy.greater(self.timer_state, 1/self.gamma_H) & numpy.greater_equal(self.rand_f, self.f)) propensities_HtoF = 1e5 * ((self.X==self.H) & numpy.greater(self.timer_state, 1/self.mu_H) & numpy.less(self.rand_f, self.f)) @@ -2407,6 +2406,19 @@ def calc_propensities(self): propensities__toS = 1e5 * ((self.X!=self.F) & numpy.greater(self.timer_state, 1/self.nu)) + if self.skip_pre: + propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoR = 1e5 * ((self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.gamma) & numpy.greater_equal( self.rand_h, self.h)) + propensities_IPREtoH = 1e5 * ( (self.X == self.I_pre) & numpy.greater(self.timer_state, 1 / self.eta) & numpy.less(self.rand_h, self.h)) + propensities_QPREtoH = 1e5 * ( + (self.X == self.Q_pre) & numpy.greater(self.timer_state, 1 / self.eta_Q) & numpy.less( + self.rand_h, self.h)) + + propensities_QASYMtoQR = 1e5 * ( + (self.X == self.Q_pre) & numpy.greater(self.timer_state, 1 / self.gamma_Q_asym)) + + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else: # exponential_rates @@ -2417,11 +2429,6 @@ def calc_propensities(self): propensities_IPREtoIASYM = self.lamda * ((self.X==self.I_pre) & (numpy.less(self.rand_a, self.a))) - if self.skip_pre: - propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) - propensities_IPREtoR = self.gamma * ((self.X == self.I_pre) & (numpy.greater_equal(self.rand_h, self.h))) - propensities_IPREtoH = self.eta * ((self.X == self.I_pre) & (numpy.less(self.rand_h, self.h))) propensities_ISYMtoR = self.gamma * ((self.X==self.I_sym) & (numpy.greater_equal(self.rand_h, self.h))) @@ -2459,22 +2466,44 @@ def calc_propensities(self): propensities__toS = self.nu * (self.X!=self.F) + if self.skip_pre: + propensities_IPREtoISYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoIASYM = numpy.zeros_like(propensities_StoE) + propensities_IPREtoR = self.gamma * ((self.X == self.I_pre) & (numpy.greater_equal(self.rand_h, self.h))) + propensities_IPREtoH = self.eta * ((self.X == self.I_pre) & (numpy.less(self.rand_h, self.h))) + propensities_QPREtoQR = self.gamma_Q_sym * ( + (self.X == self.Q_pre) & (numpy.greater_equal(self.rand_h, self.h))) + + propensities_QPREtoH = self.eta_Q * ((self.X == self.Q_pre) & (numpy.less(self.rand_h, self.h))) + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - propensities_list = [propensities_StoE, propensities_EtoIPRE, propensities_IPREtoISYM, propensities_IPREtoIASYM, propensities_ISYMtoR, propensities_ISYMtoH, propensities_IASYMtoR, propensities_HtoR, propensities_HtoF, + + if self.skip_pre: + propensities_list = [propensities_StoE, propensities_EtoIPRE, propensities_IPREtoH, propensities_IPREtoR, + propensities_HtoR, propensities_HtoF, + propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, + propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQR, propensities_QPREtoQH, propensities_RtoS, + propensities__toS] + columns = [ 'StoE', 'EtoIPRE', 'IPREtoH', 'IPREtoR', 'HtoR', 'HtoF', + 'StoQS', 'EtoQE', 'IPREtoQPRE', + 'QStoQE', 'QEtoQPRE', 'QPREtoR', 'QPREtoH', + 'RtoS', '_toS' ] + + + else: + + propensities_list = [propensities_StoE, propensities_EtoIPRE, propensities_IPREtoISYM, propensities_IPREtoIASYM, propensities_ISYMtoR, propensities_ISYMtoH, propensities_IASYMtoR, propensities_HtoR, propensities_HtoF, propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, propensities_ISYMtoQSYM, propensities_IASYMtoQASYM, propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQSYM, propensities_QPREtoQASYM, propensities_QSYMtoQR, propensities_QSYMtoH, propensities_QASYMtoQR, propensities_RtoS, propensities__toS] - if self.skip_pre: - propensities_list += [propensities_IPREtoR, propensities_IPREtoH ] - propensities = numpy.hstack(propensities_list) - - columns = [ 'StoE', 'EtoIPRE', 'IPREtoISYM', 'IPREtoIASYM', - 'ISYMtoR', 'ISYMtoH', 'IASYMtoR', 'HtoR', 'HtoF', - 'StoQS', 'EtoQE', 'IPREtoQPRE', 'ISYMtoQSYM', 'IASYMtoQASYM', - 'QStoQE', 'QEtoQPRE', 'QPREtoQSYM', 'QPREtoQASYM', - 'QSYMtoQR', 'QSYMtoH', 'QASYMtoQR', 'RtoS', '_toS' ] - if self.skip_pre: - columns += ['IPREtoR','IPREtoH'] + propensities = numpy.hstack(propensities_list) + + columns = [ 'StoE', 'EtoIPRE', 'IPREtoISYM', 'IPREtoIASYM', + 'ISYMtoR', 'ISYMtoH', 'IASYMtoR', 'HtoR', 'HtoF', + 'StoQS', 'EtoQE', 'IPREtoQPRE', 'ISYMtoQSYM', 'IASYMtoQASYM', + 'QStoQE', 'QEtoQPRE', 'QPREtoQSYM', 'QPREtoQASYM', + 'QSYMtoQR', 'QSYMtoH', 'QASYMtoQR', 'RtoS', '_toS' ] + return propensities, columns @@ -2715,7 +2744,7 @@ def run_iteration(self): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if(transitionType in ['EtoQE', 'IPREtoQPRE', 'ISYMtoQSYM', 'IASYMtoQASYM', 'ISYMtoH']): + if(transitionType in ['EtoQE', 'IPREtoQPRE', 'ISYMtoQSYM', 'IASYMtoQASYM', 'ISYMtoH', 'IPREtoH']): self.set_positive(node=transitionNode, positive=True) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From b91b22dbbad3cdd3585031f9f4e27e71f0841c6b Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 19 Oct 2020 17:39:50 -0400 Subject: [PATCH 113/117] fix typo --- seirsplus/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seirsplus/models.py b/seirsplus/models.py index ca6b7d4..1a359fc 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2482,7 +2482,7 @@ def calc_propensities(self): propensities_list = [propensities_StoE, propensities_EtoIPRE, propensities_IPREtoH, propensities_IPREtoR, propensities_HtoR, propensities_HtoF, propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, - propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQR, propensities_QPREtoQH, propensities_RtoS, + propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQR, propensities_QPREtoH, propensities_RtoS, propensities__toS] columns = [ 'StoE', 'EtoIPRE', 'IPREtoH', 'IPREtoR', 'HtoR', 'HtoF', 'StoQS', 'EtoQE', 'IPREtoQPRE', From 8bdca3c3a3dfd87ea3844a086acf2fb7f68260e2 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 19 Oct 2020 17:41:51 -0400 Subject: [PATCH 114/117] fix typo --- seirsplus/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seirsplus/models.py b/seirsplus/models.py index 1a359fc..64deae1 100644 --- a/seirsplus/models.py +++ b/seirsplus/models.py @@ -2484,6 +2484,7 @@ def calc_propensities(self): propensities_StoQS, propensities_EtoQE, propensities_IPREtoQPRE, propensities_QStoQE, propensities_QEtoQPRE, propensities_QPREtoQR, propensities_QPREtoH, propensities_RtoS, propensities__toS] + propensities = numpy.hstack(propensities_list) columns = [ 'StoE', 'EtoIPRE', 'IPREtoH', 'IPREtoR', 'HtoR', 'HtoF', 'StoQS', 'EtoQE', 'IPREtoQPRE', 'QStoQE', 'QEtoQPRE', 'QPREtoR', 'QPREtoH', From b8cf1aaec60ec00885eb35fb56a90997ce01cdf5 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 16 Nov 2020 10:43:13 -0500 Subject: [PATCH 115/117] Update readm --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 15ba948..b250e81 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ + +This is a fork of [the SEIRS+ package]((https://github.com/ryansmcgee/seirsplus) by Ryan McGee. + +The main additions to the package are the following: + +* Support for running multiple simulations in parallel using the file `parallel_run.py` + +* More support for logging results of simulations as `pandas` DataFrames. + +* more flexiblity in testing policies, in particular for asymptomatic testing of sub-groups + +* Some fixes for low prevalence situations, ensuring that there is an event in the simulation loop every day even when there few or no infected people. + +The remainder of this readme file below is taken from the original SEIRS+ package. + + # SEIRS+ Model Framework This package implements models of generalized SEIRS infectious disease dynamics with extensions that allow us to study the effect of social contact network structures, heterogeneities, stochasticity, and interventions, such as social distancing, testing, contact tracing, and isolation. From f954bd89903fc04d668b0229de3c2951a46fcd08 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 16 Nov 2020 10:46:54 -0500 Subject: [PATCH 116/117] Update readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b250e81..bc4892f 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ The main additions to the package are the following: * Some fixes for low prevalence situations, ensuring that there is an event in the simulation loop every day even when there few or no infected people. +This fork was made by Boaz Barak for the paper "Optimizing testing policies for detecting COVID-19 outbreaks" by Janni Yuval, Mor Nitzan, Neta Ravid Tannenbaum, and Boaz Barak. +See [the repository boazbk/testingstrategies](https://github.com/boazbk/testingstrategies) for examples how to use it. + The remainder of this readme file below is taken from the original SEIRS+ package. From 040f167eed92cd947be2bd51749e95c5dc75a797 Mon Sep 17 00:00:00 2001 From: Boaz Barak Date: Mon, 16 Nov 2020 10:48:30 -0500 Subject: [PATCH 117/117] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc4892f..dddf860 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -This is a fork of [the SEIRS+ package]((https://github.com/ryansmcgee/seirsplus) by Ryan McGee. +This is a fork of [the SEIRS+ package](https://github.com/ryansmcgee/seirsplus) by Ryan Seamus McGee. The main additions to the package are the following: