From bf5183dcbc25d3895b98e0a10c338710d14ef048 Mon Sep 17 00:00:00 2001 From: Eduard Grebe Date: Wed, 22 Jul 2020 20:02:09 -0700 Subject: [PATCH] Updated with Jupyter notebook with methods from Blood manuscript --- IWP_from_OperationalData.ipynb | 175 +++++ ResidualRisk.ipynb | 1225 ++++++++++++++++++++------------ residualrisk.py | 340 +++++++++ 3 files changed, 1288 insertions(+), 452 deletions(-) create mode 100644 IWP_from_OperationalData.ipynb create mode 100644 residualrisk.py diff --git a/IWP_from_OperationalData.ipynb b/IWP_from_OperationalData.ipynb new file mode 100644 index 0000000..4db3524 --- /dev/null +++ b/IWP_from_OperationalData.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Estimating the infectious window period from operational data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The simple algorithm in this notebook is based on the idea that you can estimate the duration of the infectious window period (or window of residual risk) from lookback investigation data.\n", + "\n", + "Lookback investigations are triggered when repeat donors seroconvert and trigger an investigation into transfused material collected at the donor's previous donation. The prior donation could have been collected while the donor was already infected (and infectious) but not yet detectable.\n", + "\n", + "Imagine the following situation: \n", + "* 100 donors seroconvert and become HIV-positive\n", + "* all 100 had prior donations exactly 105 days before the donation at which HIV was detected\n", + "* 1 recipient of material from prior donations became infected and it is confirmed that transfusion transmission occurred\n", + "* the least sensitive positive test at the seroconversion donation has a diagnostic delay of 10 days\n", + "* the most sensitive negative test at the prior donation has a diagnostic delay of 5 days\n", + "\n", + "Each of these IDIs of 105 days should be adjusted by the diagnostic delays relevant to the time of last negative and first positive donations to derive the interval during which infection could have occurred. In this case to 105+5-10 = 100 days.\n", + "\n", + "In this simple example, the infectious window period associated with the screening strategy in use would be 1% of the duration of the shared infection interval or 1 day. The 1% comes from the 1/100 donors who transmitted the infection. This can be generalized to a situation where each donor has a different IDI by considering the number of transmissions as a Poisson process and treating the adjusted IDIs as \"inverse exposure time\".\n", + "\n", + "$$IWP = \\frac{n}{\\sum_{i = 1}^{N} \\frac{1}{IDI_{i}} }$$\n", + "\n", + "with $n$ the number of transmissions, $N$ the number of seroconverting donors and $IDI_i$ the ith donor's adjusted interdonation interval.\n", + "\n", + "The properties of the Poisson and Chi-square distributions then allow us to obtain confidence intervals on the IWP estimate:\n", + "\n", + "$$IWP_{lb} = \\frac{ \\left. \\chi_{2n,\\alpha/2}^{2} \\middle/ 2 \\right. }{ \\sum_{i = 1}^{N} \\frac{1}{IDI_{i}} }$$\n", + "\n", + "$$IWP_{ub} = \\frac{ \\left. \\chi_{2n,1-\\alpha/2}^{2} \\middle/ 2 \\right. }{ \\sum_{i = 1}^{N} \\frac{1}{IDI_{i}} }$$" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import scipy.stats as stats" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def residual_risk_operational(n_transmissions,\n", + " intervals, \n", + " negative_diagnositc_day,\n", + " positive_diagnostic_delay,\n", + " alpha = 0.05\n", + " ):\n", + " inverse_intervals = [1/(x + negative_diagnositc_day - positive_diagnostic_delay) for x in intervals]\n", + " total_exposure = sum(inverse_intervals)\n", + " iwp = n_transmissions / total_exposure\n", + " if n_transmissions > 0:\n", + " iwp_lb = stats.chi2.ppf(alpha/2, df=2*n_transmissions)/2/total_exposure\n", + " else:\n", + " iwp_lb = 0.0\n", + " iwp_ub = stats.chi2.ppf(1.0-alpha/2, df=2*(n_transmissions+1))/2/total_exposure\n", + " return (iwp, (iwp_lb, iwp_ub))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example with equal IDIs" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.9999999999999993, (0.02531780798428986, 5.5716433909388945))" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IDIs = np.repeat(105,100)\n", + "residual_risk_operational(1, IDIs, 5, 10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example with more realistic IDIs" + ] + }, + { + "cell_type": "code", + "execution_count": 295, + "metadata": {}, + "outputs": [], + "source": [ + "def truncated_normal(mu=0, sigma=1, lower=-3, upper=3):\n", + " return stats.truncnorm(a = (lower - mu)/sigma,\n", + " b = (upper - mu)/sigma,\n", + " loc = mu,\n", + " scale = sigma\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 298, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(123)\n", + "X = truncated_normal(mu = 0, sigma = 600, lower = 56, upper = 2000)\n", + "IDIs = X.rvs(500)" + ] + }, + { + "cell_type": "code", + "execution_count": 299, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2.733677254711141, (0.887617563599965, 6.379490801132148))" + ] + }, + "execution_count": 299, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "residual_risk_operational(5, IDIs, 5, 10)" + ] + } + ], + "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 +} diff --git a/ResidualRisk.ipynb b/ResidualRisk.ipynb index 4cccd70..1fdef9e 100644 --- a/ResidualRisk.ipynb +++ b/ResidualRisk.ipynb @@ -86,54 +86,90 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Weusten model" + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import multiprocessing as mp\n", + "import numpy as np\n", + "import scipy.stats as stats\n", + "import scipy.integrate as si\n", + "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We use the model of Weusten et al. (2011), which is an improvement on Weusten et al. (2002).\n", + "## General approach to residual risk\n", + "\n", + "For the purposes of this analysis, residual risk is defined as the probability of transmission to the recipient (per unit transfused). Since sources of risk outside of the early-infection window period (such as laboratory error or that a rare genetic variant of the infectious agent fails to react to all screening assays) are thought to be neglible, the probability that any random unit will be infectious is a function of\n", + "* the the probability per unit time that any given donor will acquire the infection; and\n", + "* the length of the infectious window period, i.e. the interval from when a donor (on average) becomes infectious and when (on average) a particular laboratory test becomes reactive.\n", "\n", - "The model relies on four basic concepts:\n", + "Although in principle disease incidence is distinct from the per-unit time risk of infection that an uninfected at-risk persion would be exposed to, in practice when the incidence is small (such as HIV incidence in blood donors), it is essentially equivalent. So observed HIV incidence of 10 cases per 100,000 person-years in a donor population would equate to a 0.01% probability that any random HIV-uninfected donor becomes infected over a one year period. The risk that a random donor became infected within any given period, e.g. two weeks, prior to donation would be directly proportional to the risk per year, so that in our example the probability that any given donor became infected within the two weeks prior to donation would be $\\frac{2}{52} \\cdot 0.0001 = 0.00038\\%$.\n", "\n", - "1. Probability that a random donor donates during the WP of infection\n", - "2. The probability that a donor has mounted a certain viral load in the log-linear ramp-up phase of viraemia (depending on doubling time/growth rate)\n", - "3. The probability that a certain viral concentration is not detected (by NAT)\n", - "4. The probability that the amount of virus in the released blood component leads to an infection" + "In this notebook, and the linked web-based residual risk estimation tool, it is assumed that the user has appropriately estimated incidence in the donor pool. In practice this would usually require relying either solely on data from repeat donors (where prior negative donations allow the direct observation of infection events and exposure time or time 'at risk') or the use of a method for estimating incidence in first-time donors (e.g. biomarkers of 'recent infection') and an appropriately weighted incidence estimate according to the proportion of donations collected from each group of donors. It may also be necessary to adjust incidence to account for the probability that an infectious unit would be interdicted based on the presence of other markers. For example if there are high rates of pre-existing HCV infection in donors who acquire HIV, the risk of HIV transmission would be over-estimated if incidence were not adjusted based appropriately (Kleinman et al., 1997).\n", + "\n", + "It is important to account for the fact that material sourced from a newly-infected donor is not immediately infectious, since the infection first has to establish itself and a sufficient viral load be mounted to lead to infection in the recipient. This notebook therefore presents an approach for deriving the length of the 'infectious window period' (IWP) from data on transfusion transmission 'dose response' (i.e. the probability of transmission as a function of the transfused dose) and the sensitivity of the screening assay (i.e. the probability that an infection will fail to be detected as a function of the viral load). \n", + "\n", + "The residual risk of transfusion transmission is then simply the product of the infectious window period and incidence (in the same units of time):\n", + "\n", + "$$RR = IWP \\cdot \\hat{I}$$\n", + "\n", + "or (more accurately) the IWP (in years) times the annual risk of infection. In our example, an IWP of 7 days would translate to a per-unit residual risk of transfusion transmission of $ \\frac{7}{365.25} \\cdot 0.0001 = 0.00019\\%$ or 1 in 521,786 transfusions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Parameters" + "## Model for the infectious window period (IWP)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Key parameters in the model include:\n", - "\n", - "1. 50% infectious dose `N50` (in copies/mL and virions/mL)\n", - "2. Doubling time or log-growth rate (in log10 copies(/mL)/day) or as viral doubling time (in days)\n", - "3. Assay 95% LoD\n", - "4. Assay 50% LoD" + "We largely rely on the model of Weusten et al. (2011) and the HIV-TT dose-response model of Belov et al. (2020) to derive the infectious window period (called \"risk-day equivalents\" by Weusten et al.). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parameters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "*Note that we will ignore the Weusten formula based on total visiting repeat donors, IDIs, etc. and use incidence instead*\n", + "Key components of the model are:\n", "\n", - "We are therefore leaving out parameters relevant to that calculation, nl. $D_{total}$, $D_{conv}$ and $t_{between}$.\n", + "1. The log-linear viral growth rate (or doubling time) during ramp-up viraemia\n", + "2. The probability that a certain concentration of virus in the transfused component leads to transmission\n", + "3. The probability that a certain concentration of viral RNA in the tested sample will fail to be detected by the screening assay(which depends on the screening assay's 50% and 95% limits of detection)\n", + "4. The testing regime, including whether samples are pooled and the number of retests (e.g. pool resolution testing)\n", "\n", + "The most important parameters of the model are listed below" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "Definitions and corresponding variable names:\n", "\n", - "| Symbol | Python variable | Description |\n", + "| Symbol | Python variable name | Description |\n", "| ------------ | ------------------------- | ------------------------------------------------------------- |\n", + "| $k$ | `k` | Dose-response parameter |\n", "| $\\lambda$ | `doubling_time` | Doubling time |\n", "| $\\chi$ | `copies_per_virion` | Number of RNA copies per virion |\n", "| $\\Phi(x)$ | `scipy.stats.norm.cdf()` | Cumulative standard normal |\n", @@ -141,7 +177,6 @@ "| $C_0$ | `C0` | $C$ at $t=0$, i.e. at start of window period |\n", "| $n$ | `n_copies` | Number of copies (of viral RNA) **Used?** |\n", "| $m_{retest}$ | `retests` | Number of times a pool initially found reactive is retested |\n", - "| $p_v$ | `infectivity_pv` | Probability that a single viral particle leads to infection |\n", "| $r_{days}$ | `risk_days` | Overall risk in days, i.e. window period risk day equivalents |\n", "| $S_{pool}$ | `pool_size` | Pool size |\n", "| $t$ | `t` | Time (in the window period) |\n", @@ -155,34 +190,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Equations and functions" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "pycharm": { - "is_executing": false - } - }, - "outputs": [], - "source": [ - "import math\n", - "import numpy as np\n", - "import scipy.stats as stats\n", - "from scipy.integrate import quad\n", - "import statistics\n", - "import matplotlib.pyplot as plt" + "### Equations and functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Equation A1:\n", + "The concentration of virions as a function of time since infection is given below (Weusten eq. A1):\n", + "\n", + "$$C(t) = C_0 2^{\\frac{t}{\\lambda}}$$\n", "\n", - "$$C(t) = C_0 2^{\\frac{t}{\\lambda}}$$" + "with $C_0$ the initial concentration and $\\lambda$ the viral doubling time during the ramp-up phase. The initial concentration, as long as it is low, does not impact the estimation. " ] }, { @@ -196,7 +215,7 @@ "outputs": [], "source": [ "def concentration(C0, doubling_time, t):\n", - " concentration = C0 * 2 ** (t/doubling_time)\n", + " concentration = C0 * 2 ** (t / doubling_time)\n", " return concentration" ] }, @@ -204,33 +223,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Expected number of virions in blood product is a random variable with Poisson distribution, and is a function of viral load/concentration (in virions/mL) in the donor, and the volume transfused, so that \n", - "\n", - "Pr(n virions in transfusion product) (A2):\n", - "\n", - "$$P_n=\\frac{C \\cdot V_{trans}^n exp(-C \\cdot V_{trans})}{n!}$$\n", - "\n", - "and\n", + "We employ the Belov et al. dose-response model to model the probability of an HIV transmission occurring as a function of the total number of RNA copies transfused. This general form can be made applicable to other viruses if appropriate data are available.\n", "\n", - "Pr(n virions lead to infection) (A3):\n", + "$$P_{infectious}(n)=1-e^{-kn}$$\n", "\n", - "$$P_{infection}(n)=1-(1-p_v)^n$$\n", + "with $n$ the number of RNA copies in the transfused product, and $k$ the parameter capturing the dose response. We use the maximum a posteriori probability (MAP) estimate reported for $k$ in our analyses, and fit a Gamma distribution to the posterior distribution of $k$ for the uncertainty analysis. Note that we can obtain $n$ for any time post-infection by means of the first equation, the number of copies per virion (denoted $\\chi$, equal to 2 for HIV) and $V_{trans}$, the total volume of plasma transfused:\n", "\n", - "so that total probability that infection develops Pr(infectious) (A4) is:\n", + "$$n(t) = C(t) \\chi V_{trans}$$\n", "\n", - "$$P_{infectious} = 1-exp(-C \\cdot V_{trans} \\cdot p_v)$$\n", + "so that\n", "\n", - "with $C$ defined in equation A1. (A4 is already simplified in Weusten's derivation.) The same equation can be stated simply in terms of $N$, the expected number of virions in a blood product (Eq 1 in Weusten):\n", + "$$P_{infectious}(t)=1 - \\exp(-k C_0 2^{\\frac{t}{\\lambda}} \\chi V_{trans})$$\n", "\n", - "$$P_{infectious} = 1-exp(-N \\cdot p_v)$$\n", - "\n", - "Note that there is a simple relationship between the 50% infectious dose $ID_{50}$ and $p_v$ can be derived from the previous equation:\n", - "\n", - "$$ID_{50} \\cdot p_v = \\ln(2)$$\n", - "\n", - "$$p_v = \\frac{\\ln(2)}{ID_{50}}$$\n", - "\n", - "This is useful because we have published estimates of infectious dose from animal experiments." + "This is a different formulation from that of Weusten et al., who derive an infectivity per virion." ] }, { @@ -243,13 +248,20 @@ }, "outputs": [], "source": [ - "def infectivity_per_virion(ID50):\n", - " pv = math.log(2) / ID50\n", - " return pv\n", + "def prob_infectious_copies(n_copies, k):\n", + " prob = 1.000000000001 - math.exp(-k * n_copies)\n", + " return prob\n", "\n", - "def prob_infectious(t, C0, doubling_time, volume_transfused, infectivity_pv):\n", + "def prob_infectious(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k, \n", + " copies_per_virion = 2\n", + " ):\n", " C = concentration(C0, doubling_time, t)\n", - " prob = 1 - math.exp(-C * volume_transfused * infectivity_pv)\n", + " n_copies = C * copies_per_virion * volume_transfused\n", + " prob = prob_infectious_copies(n_copies, k)\n", " return prob" ] }, @@ -257,21 +269,53 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Probability positive for any one test given $n$ copies per sample (A5):\n", + "Following Weusten et al., we parameterized the probability of non-detection in terms of the probability of a positive result in the initial test of the minipool, and the probability of a negative test (resulting in a potential release of the product) upon individual donation resolution of the pool. The total probability of non-detection is given by (Weusten eq. A6):\n", "\n", - "$$P_{+} = \\Phi\\left(z \\frac{\\log_{10}(\\frac{n}{X_{50}})}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)$$\n", + "$$P_{nondetection}= 1 - P_{+,initial} \\cdot (1 - P_{-,retest})$$\n", "\n", - "Probability of non-detection, where there is initial testing in a pool and then singlicate retesting, is simple:\n", + "The probability of a positive result for any one test, given $n$ copies in the sample is (Weusten eq. A5):\n", "\n", - "Pr(nondetection) (A6)\n", + "$$P_{+}(n) = \\Phi\\left(z \\frac{\\log_{10}(\\frac{n}{X_{50}})}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)$$\n", "\n", - "$$P_{nondetection}= 1 - P_{+,initial} \\cdot (1 - P_{-,retest})$$\n", + "with $X_{50}$ the 50% and $X_{50}$ the 95% limits of detection (LoD), $\\Phi$ the cumulative standard normal and $z = 1.6449$ so that $\\Phi(z) = 0.95$. \n", + "\n", + "It follows that the probability of an initial positive result is given by (Weusten eq. A7):\n", + "\n", + "$$P_{+,initial}(t) = \\Phi\\left(z \\frac{\\log_{10}\\left(\\frac{\\chi C(t)}{S_{pool} X_{50}}\\right)}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)$$\n", "\n", - "So we need formulas for each of those probabilities (given in A7 and A9. Note we ignore a regime where the entire pool is retested, and only consider a regime where each individual donation is retested when the pool was found positive (the regime where entire pool is retested is considered in A8 not shown here). (Also remember the concentration $C$ is in /mL or otherwise normalized, and the LoD values are in the same units and take account of input volume. We therefore do not need to consider input volume at all.) (Are we assuming there can be only one positive donation in the pool? Not if $m_{retest}$ correctly captures the number of chances that *each donation/sample* gets to test negative.)\n", + "with $S_{pool}$ the number of samples pooled for initial testing. \n", "\n", - "$$P_{+,initial} = \\Phi\\left(z \\frac{\\log_{10}\\left(\\frac{\\chi C_0 2^{t/\\lambda}}{S_{pool} X_{50}}\\right)}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)$$\n", + "Products get released only if (and only if) all retests are negative. In the case of retesting of individual donations separately:\n", "\n", - "$$P_{-,retest} = \\left(1 - \\Phi\\left(z \\frac{\\log_{10}\\left(\\frac{\\chi C_0 2^{t/\\lambda}}{X_{50}}\\right)}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)\\right)^{m_{retest}}$$" + "$$P_{-,retest}(t) = \\left(1 - \\Phi\\left(z \\frac{\\log_{10}\\left(\\frac{\\chi C(t)}{X_{50}}\\right)}{\\log_{10}(\\frac{X_{95}}{X_{50}})}\\right)\\right)^{m_{retests}}$$\n", + "\n", + "with $m_{retests}$ the number of retests. In an alternate regime where the entire pool is subjected to retesting, the pooling dilution would remain relevant and $X_{50}$ would still be multiplied by $S_{pool}$ in the numerator. \n", + "\n", + "Also note the following:\n", + "* The presence of retesting in the algorithm is relevant insofar as a unit can be released despite an initial positive (e.g. an initially positive pool with a negative individual donation result)\n", + " * we assume that if multiple retests are performed, all retests must be negative in order for a unit to be released\n", + " * the presence of retesting in the algorithm by definition increases risk, since any nonzero probability of unit release after all-negative retests is added to the probability of an initial negative\n", + " * however, if retesting is performed, an increase in the number of retests reduces the risk (relative to a single retest)\n", + " * the number of retests should only be specified as greater than zero if retesting could result in release. For example, if ID-NAT screening is performed and a unit is automatically interdicted in the case of an initial positive, any retesting performed is not relevant to risk \n", + "* if a multiplexed NAT assay is used for initial screening, the sensitivity of the relevant discriminatory assay is not relevant, unless the testing algorithm calls for release of the unit in the event that there is a failure to discriminate\n", + " * the logic of Weusten et al. given above could be expanded to account for a discriminatory assay with a different detection limit in the event that the testing algorithm renders this relevant\n", + " \n", + "" ] }, { @@ -288,14 +332,14 @@ " doubling_time,\n", " pool_size,\n", " lod50,\n", - " lod95,\n", + " lod95_lod50_ratio,\n", " z\n", " ):\n", " if (not isinstance(pool_size, int)) or pool_size < 1:\n", " raise Exception(\"pool_size must be an integer of at least 1\")\n", - " \n", - " # C is in copies_per_virion, should be \"copies_per_virion * C\" when C in v/mL\n", - " X = z * (math.log10(((C) / (pool_size * lod50))) / math.log10((lod95/lod50)))\n", + " # C is in copies copies_per_virion * C when C in virions\n", + " X = z * (math.log10(((C) / (pool_size * lod50))) / \n", + " math.log10(lod95_lod50_ratio))\n", " prob = stats.norm.cdf(X)\n", " return prob\n", "\n", @@ -303,20 +347,20 @@ " doubling_time,\n", " pool_size,\n", " lod50,\n", - " lod95,\n", + " lod95_lod50_ratio,\n", " retests,\n", " z\n", " ):\n", " if (not isinstance(pool_size, int)) or pool_size < 1:\n", " raise Exception(\"pool_size must be an integer of at least 1\")\n", - " \n", " if (not isinstance(retests, int)) or retests < 0:\n", " raise Exception(\"retests must be a positive integer\")\n", " elif retests == 0:\n", " return 0\n", " elif retests >= 1:\n", - " # C is in copies_per_virion, should be \"copies_per_virion * C\" when C in v/mL\n", - " X = z * (math.log10(((C) / lod50)) / math.log10((lod95/lod50)))\n", + " # C is in copies copies_per_virion * C when C in virions\n", + " X = z * (math.log10(((C) / lod50)) / math.log10(lod95_lod50_ratio))\n", + " #print(X)\n", " prob = (1 - stats.norm.cdf(X)) ** retests\n", " return prob\n", "\n", @@ -326,27 +370,27 @@ " doubling_time,\n", " pool_size,\n", " lod50,\n", - " lod95,\n", + " lod95_lod50_ratio,\n", " retests,\n", " z = 1.6449\n", " ):\n", " Cv = concentration(C0, doubling_time, t)\n", " Cc = copies_per_virion * Cv\n", - " p_pos_init = prob_pos_init(Cc, doubling_time, pool_size, lod50, lod95, z)\n", - " p_neg_retest = prob_neg_retest(Cc, doubling_time, pool_size, lod50, lod95, retests, z)\n", + " p_pos_init = prob_pos_init(Cc, doubling_time, pool_size, lod50, \n", + " lod95_lod50_ratio, z)\n", + " p_neg_retest = prob_neg_retest(Cc, doubling_time, pool_size, lod50, \n", + " lod95_lod50_ratio, retests, z)\n", " prob = 1 - p_pos_init * (1 - p_neg_retest)\n", - " return prob\n" + " return prob" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To get the total risk-day equivalents, we simply need to get the area under the joint probability of infectiousness and non-detection (A10):\n", - "\n", - "$$r_{days} = \\int_{-\\infty}^{\\infty} P_{infectious} \\cdot P_{nondetection} dt$$\n", + "To get the infectious window period (\"risk-day equivalents\"), we simply need to get the area under the joint probability of infectiousness and non-detection (Weusten et al., eq. A10):\n", "\n", - "*Note that we call it risk-day equivalents, but really the unit of time is arbitrary and would be whatever you express the doubling time in. Hours or years would work too with exactly the same formula.*" + "$$IWP = \\int_{-\\infty}^{\\infty} P_{infectious}(t) \\cdot P_{nondetection}(t) \\; dt$$" ] }, { @@ -364,32 +408,35 @@ " C0,\n", " doubling_time,\n", " volume_transfused, \n", - " infectivity_pv,\n", + " k,\n", " pool_size,\n", " lod50,\n", - " lod95,\n", + " lod95_lod50_ratio,\n", " retests,\n", " z = 1.6449\n", " ):\n", - " product = (prob_infectious(t, C0, doubling_time, volume_transfused, infectivity_pv) * \n", - " prob_nondetection(t, copies_per_virion, C0, doubling_time, pool_size,lod50,lod95,retests,z))\n", + " product = (prob_infectious(t, C0, doubling_time, volume_transfused, k) * \n", + " prob_nondetection(t, copies_per_virion, C0, doubling_time, \n", + " pool_size,lod50,lod95_lod50_ratio,retests,z))\n", " return(product)\n", "\n", "def risk_days(copies_per_virion,\n", " C0,\n", " doubling_time,\n", " volume_transfused, \n", - " infectivity_pv,\n", + " k,\n", " pool_size,\n", " lod50,\n", - " lod95,\n", + " lod95_lod50_ratio,\n", " retests,\n", " z = 1.6449,\n", " limits = (-100,500)\n", " ):\n", - " # Ideally we would integrate from -np.inf to np.inf, but that causes an overflow error, so we choose safe limits instead\n", - " rd = quad(prob_infectious_nondetection, limits[0], limits[1], \n", - " args=(copies_per_virion,C0,doubling_time,volume_transfused,infectivity_pv,pool_size,lod50,lod95,retests,z))[0]\n", + " # Ideally we would integrate from -np.inf to np.inf, but that causes an \n", + " # overflow error, so we choose safe limits instead \n", + " rd = si.quad(prob_infectious_nondetection, limits[0], limits[1], \n", + " args=(copies_per_virion, C0, doubling_time, volume_transfused, k, \n", + " pool_size, lod50, lod95_lod50_ratio, retests, z))[0]\n", " return rd" ] }, @@ -397,189 +444,431 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Example" + "## Worst-case IWP" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We will calculate residual risk of HIV transfusion transmission in a demonstrative scenario, where:\n", + "If we assume that a single virion in the transfused product is guaranteed to result in infection – analogous to setting Weusten et al.'s $p_v$ parameter (per-virion infectivity) equal to 1, the infectiousness curve would transition stepwise from zero to 1 when the concentration reaches 1 virion per transfused volume. Below we create functions that encode this assumption and that can be used for a worst-case scenario analysis (together with conservative assumptions about detection probabilities)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def prob_infectious_copies_wc(n_copies, copies_per_virion = 2):\n", + " if n_copies < copies_per_virion:\n", + " return 0.0\n", + " elif n_copies >= copies_per_virion:\n", + " return 1.0\n", + " \n", + "def prob_infectious_wc(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " copies_per_virion = 2\n", + " ):\n", + " C = concentration(C0, doubling_time, t)\n", + " n_copies = C * copies_per_virion * volume_transfused\n", + " prob = prob_infectious_copies_wc(n_copies, copies_per_virion)\n", + " return prob\n", "\n", - "* All donations are screened with the Procleix Ultrio Plus multiplexed NAT assay \n", - " * Initial screening in minipools of 32 samples\n", - " * If a pool is positive, each sample is tested once by the same assay and the unit released if negative\n", - "* The transfused product is \n", - " * packed red blood cells, which contain an average of 20mL of plasma or \n", - " * fresh frozen plasma with a volume of 200mL\n", - "* The HIV incidence in the donor population is 20 cases/100,000 person-years" + "def prob_infectious_nondetection_wc(t,\n", + " copies_per_virion,\n", + " C0,\n", + " doubling_time,\n", + " volume_transfused, \n", + " pool_size,\n", + " lod50,\n", + " lod95_lod50_ratio,\n", + " retests,\n", + " z = 1.6449\n", + " ):\n", + " product = (prob_infectious_wc(t, C0, doubling_time, volume_transfused) * \n", + " prob_nondetection(t, copies_per_virion, C0, doubling_time, \n", + " pool_size,lod50,lod95_lod50_ratio,retests,z))\n", + " return(product)\n", + "\n", + "def risk_days_wc(copies_per_virion,\n", + " C0,\n", + " doubling_time,\n", + " volume_transfused, \n", + " pool_size,\n", + " lod50,\n", + " lod95_lod50_ratio,\n", + " retests,\n", + " z = 1.6449,\n", + " limits = (-20,100)\n", + " ):\n", + " # Ideally we would integrate from -np.inf to np.inf, but that causes an \n", + " # overflow error, so we choose safe limits instead\n", + " rd = si.quad(prob_infectious_nondetection_wc, limits[0], limits[1], \n", + " args=(copies_per_virion, C0, doubling_time, volume_transfused, \n", + " pool_size, lod50, lod95_lod50_ratio, retests, z))[0]\n", + " return rd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Uncertainty analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Parameter values\n", + "The functions above allow for the estimation of IWP and residual risk point estimates. In order to produce credible intervals, we conduct a bootstrapping analysis in which distributions are specified for each important parameter in the model, and parameters are then drawn from these distributions in each bootstrapping iteration. Note that\n", "\n", - "We need to set sensible values for all the parameters identified above. Note the following:\n", + "* the distributions have no meaning in the model, they are merely a way to express beliefs about input parameters\n", + "* the current implementation does not account for correlated parameters\n", + "* the distributions chosen may not be entirely appropriate to what is known about the parameters\n", "\n", - "* HIV is a double-stranded RNA virus, with two copies of RNA per virion.\n", - "* Following Weusten et al., we are setting the $ID_{50}$ based on the median of the log of copy numbers that infected no and all animals respectively. This is a bit of a stretch – we simply have too little information available to derive a sensible $ID_{50}$ and a plausible range around it. We obtain the numbers used here from Ma et al. (2009).\n", - "* Weusten at al. mention a \"worst case scenario\" of $p_v=1$, i.e. a single virion present in the transfused product is guaranteed to cause an infection. This is sensible to consider.\n", - " * We will additionally assume incidence is 30/100,000PY in the worst-case scenario\n", - "* Doubling time during the log-linear growth (\"ramp-up\") phase of infection was estimated at 20.5 hours by Fiebig et al. (2003)\n", - "* Assay limit of detection is usually estimated by probit analysis after testing serial dilutions of an analytic standard, standardized in international units (IU)/mL. The conversion factor between IU/mL and copies/mL is 1.72IU/RNA copy in WHO literature." + "Specifically, we use normal distributions for $\\lambda$ and $X_{50}$, a gamma distribution for $k$ and a uniform distribution for $V_{trans}$. Since $X_{50}$ and $X_{95}$ are derived from a probit analysis and highly correlated, we fix the ratio between the two LoDs and only draw values of $X_{50}$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next function bootstraps from distributions of input parameters and returns an IWP point estimate, credible interval, and the bootstrapped IWP values themselves." ] }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "pycharm": { - "is_executing": false - } - }, + "execution_count": 7, + "metadata": {}, "outputs": [], "source": [ - "copies_per_virion = 2\n", - "\n", - "copies_none_infected = 2 # Ma, Stone et al. (2009)\n", - "copies_all_infected = 20 # Ma, Stone et al. (2009)\n", - "ID50c = math.exp(statistics.median([math.log(copies_none_infected), math.log(copies_all_infected)]))\n", - "ID50v = ID50c / copies_per_virion\n", - "infectivity_pv = infectivity_per_virion(ID50v)\n", - "infectivity_pv_worst = 1\n", - "\n", - "C0 = 0.00025 # arbitrary and doesn't matter - set to approximately 1 virion / 4L of blood\n", - "doubling_time = 0.8542 # 20.5/24 Fiebig et al. (2003)\n", - "volume_transfused_rbc = 20.0 # An Red Blood Cell unit typically includes 20mL of plasma\n", - "volume_transfused_ffp = 200.0 #A fresh frozen plasma unit is typically 200mL \n", - "\n", - "IUs_per_copy = 1.72 # The WHO uses this conversion factor\n", - "lod50 = 4.7 / IUs_per_copy # Procleix Ultrio Plus analytical sensitivity by Probit analysis (Gen-Probe, 2012, p. 40)\n", - "lod95 = 21.2 / IUs_per_copy # Procleix Ultrio Plus analytical sensitivity by Probit analysis (Gen-Probe, 2012, p. 40)\n", - "\n", - "pool_size = 32\n", - "retests = 1\n", - "\n", - "incidence = 20 / 1e5 # in cases/person-year" + "def iwp_bs(k, \n", + " k_gamma_shape, \n", + " k_gamma_scale, \n", + " doubling_time, \n", + " doubling_time_norm_sd, \n", + " lod50, \n", + " lod50_sd, \n", + " lod95_lod50_ratio, \n", + " volume_transfused, \n", + " volume_transfused_range, \n", + " pool_size, \n", + " retests, \n", + " C0 = 0.00025, \n", + " copies_per_virion = 2, \n", + " alpha = 0.05, \n", + " n_bs = 10000, \n", + " seed = 126887\n", + " ):\n", + " iwp_pe = risk_days(copies_per_virion, C0, doubling_time, volume_transfused, \n", + " k, pool_size, lod50, lod95_lod50_ratio, retests)\n", + " np.random.seed(seed)\n", + " doubling_time_draws = stats.truncnorm.rvs(0, \n", + " np.inf, \n", + " doubling_time, \n", + " doubling_time_norm_sd, \n", + " n_bs)\n", + " k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs)\n", + " lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs)\n", + " volume_transfused_draws = np.random.uniform(volume_transfused_range[0],\n", + " volume_transfused_range[1],\n", + " n_bs)\n", + " iwp = []\n", + " for i in range(n_bs):\n", + " iwp.append(risk_days(copies_per_virion, C0, doubling_time_draws[i], \n", + " volume_transfused_draws[i], k_draws[i], pool_size, \n", + " lod50_draws[i], lod95_lod50_ratio, retests))\n", + " iwp_ci = np.quantile(iwp, (alpha/2, 1 - alpha/2))\n", + " return (iwp_pe, iwp_ci, iwp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Residual transmission risk from RBC transfusions" + "The next function takes bootstrapped IWP values, draws incidence and produces a RR point estimate and credible interval. Incidence values are also drawn from a normal distribution. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def residual_risk_iwp(iwp_pe, \n", + " iwp_bs, \n", + " incidence, \n", + " incidence_norm_sd, \n", + " per = 1e6,\n", + " alpha = 0.05,\n", + " seed = 126887):\n", + " rr_pe = incidence * iwp_pe / 365.25 * per\n", + " n_bs = len(iwp_bs)\n", + " np.random.seed(seed)\n", + " incidence_draws = stats.truncnorm.rvs(0, np.inf, incidence, \n", + " incidence_norm_sd, n_bs)\n", + " rr = []\n", + " for i in range(n_bs):\n", + " rr.append(incidence_draws[i] * iwp_bs[i] / 365.25 * per)\n", + " rr_ci = np.quantile(rr, (0.025,0.975))\n", + " rr_se = np.std(rr)\n", + " return (rr_pe, rr_ci, rr_se)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "* Risk-day equivalents:" + "This function simply combines the operations for the previous two functions." ] }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "pycharm": { - "is_executing": false - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7.19\n" - ] - } - ], + "execution_count": 9, + "metadata": {}, + "outputs": [], "source": [ - "iwp_risk_days_rbc = risk_days(copies_per_virion, C0, doubling_time, volume_transfused_rbc, \n", - " infectivity_pv, pool_size, lod50, lod95, retests)\n", - "print(round(iwp_risk_days_rbc, 2))\n", - "iwp_risk_years_rbc = iwp_risk_days_rbc / 365.25" + "def residual_risk(k, \n", + " k_gamma_shape, \n", + " k_gamma_scale, \n", + " doubling_time, \n", + " doubling_time_norm_sd, \n", + " lod50, \n", + " lod50_sd, \n", + " lod95_lod50_ratio, \n", + " volume_transfused, \n", + " volume_transfused_range, \n", + " pool_size, \n", + " retests, \n", + " incidence, \n", + " incidence_norm_sd, \n", + " C0 = 0.00025, \n", + " copies_per_virion = 2, \n", + " per = 1e6, \n", + " n_bs = 10000, \n", + " seed = 126887\n", + " ):\n", + " iwp_pe = risk_days(copies_per_virion, C0, doubling_time, volume_transfused, \n", + " k, pool_size, lod50, lod95_lod50_ratio, retests)\n", + " rr_pe = incidence * (iwp_pe / 365.25) * per\n", + " if n_bs > 0:\n", + " np.random.seed(seed)\n", + " doubling_time_draws = stats.truncnorm.rvs(0, np.inf, doubling_time, \n", + " doubling_time_norm_sd, n_bs)\n", + " volume_transfused_draws = np.random.uniform(volume_transfused_range[0],\n", + " volume_transfused_range[1],\n", + " n_bs)\n", + " k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs)\n", + " lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs)\n", + " incidence_draws = stats.truncnorm.rvs(0, np.inf, incidence, \n", + " incidence_norm_sd, n_bs)\n", + " iwp = []\n", + " rr = []\n", + " for i in range(n_bs):\n", + " #prog = i/n_bs*100\n", + " #print('Computing RR [%d%%]\\r'%prog, end=\"\")\n", + " iwp.append(risk_days(copies_per_virion, C0, doubling_time_draws[i], \n", + " volume_transfused_draws[i], k_draws[i], \n", + " pool_size, lod50_draws[i], lod95_lod50_ratio, \n", + " retests))\n", + " rr.append(incidence_draws[i] * iwp[i] / 365.25 * per)\n", + " iwp_ci = np.quantile(iwp, (0.025,0.975))\n", + " rr_ci = np.quantile(rr, (0.025,0.975))\n", + " rr_se = np.std(rr)\n", + " return (iwp_pe, iwp_ci, rr_pe, rr_ci, rr_se)\n", + " else:\n", + " return (iwp_pe, rr_pe)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "* Residual risk point estimate (per million transfusions)" + "And finally we create a parallelized version of `iwp_bs()` to improve performance." ] }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "pycharm": { - "is_executing": false - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.937\n" - ] - } - ], + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def iwp_bs_par(k, \n", + " k_gamma_shape, \n", + " k_gamma_scale, \n", + " doubling_time, \n", + " doubling_time_norm_sd, \n", + " lod50, \n", + " lod50_sd, \n", + " lod95_lod50_ratio, \n", + " volume_transfused, \n", + " volume_transfused_range, \n", + " pool_size, \n", + " retests, \n", + " C0 = 0.00025, \n", + " copies_per_virion = 2, \n", + " alpha = 0.05,\n", + " n_bs = 10000, \n", + " seed = 126887\n", + " ):\n", + "\n", + " iwp_pe = risk_days(copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", + " np.random.seed(seed)\n", + " doubling_time_draws = stats.truncnorm.rvs(0, \n", + " np.inf, \n", + " doubling_time, \n", + " doubling_time_norm_sd, \n", + " n_bs)\n", + " k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs)\n", + " lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs)\n", + " volume_transfused_draws = np.random.uniform(volume_transfused_range[0],\n", + " volume_transfused_range[1],\n", + " n_bs)\n", + " p = mp.Pool()\n", + " result = [p.apply_async(risk_days,\n", + " args=(copies_per_virion,\n", + " C0,\n", + " doubling_time_draws[i],\n", + " volume_transfused_draws[i],\n", + " k_draws[i],\n", + " pool_size,\n", + " lod50_draws[i],\n", + " lod95_lod50_ratio,\n", + " retests)\n", + " ) for i in range(n_bs)]\n", + " iwp = [r.get() for r in result]\n", + " p.close()\n", + " p.join()\n", + " iwp_ci = np.quantile(iwp, (alpha/2, 1 - alpha/2))\n", + " return (iwp_pe, iwp_ci, iwp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "RR_rbc = incidence * iwp_risk_years_rbc * 1e6\n", - "print(round(RR_rbc, 3))" + "## Example" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Residual transmission risk from FFP transfusions" + "We will calculate residual risk of HIV transfusion transmission in a demonstrative scenario, where:\n", + "\n", + "* All donations are screened with the Procleix Ultrio Plus multiplexed NAT assay \n", + " * Initial screening in minipools of 16 samples\n", + " * If a pool is positive, each sample is tested once by the same assay and the unit released if the retest is negative\n", + "* The transfused product is packed red blood cells, which contain an average of 20mL of plasma\n", + "* The HIV incidence in the donor population is 10 cases/100,000 person-years" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "* Risk-day equivalents:" + "Here are key parameter values and distributions for the uncertainty analysis.\n", + "\n", + "| Parameter | Point estimate | Distribution | Reference(s) |\n", + "| ------------ | ---------------------- | ----------------------------------- | -------------------------------------------- |\n", + "| $C_0$ | 0.00025 | fixed | Arbitrary number |\n", + "| $\\lambda$ | 0.8542 days | $\\mathcal{N}(0.8542, 0.00306)$ | Fiebig et al. (2003) |\n", + "| $k$ | 0.02434 | $\\Gamma (3.98547,0.00678)$ | Belov et al. (forthcoming); Ma et al. (2009) |\n", + "| $X_{50}$ | 2.73 c/mL | $\\mathcal{N}(2.73, 0.1099802)$ | Gen-Probe (2012) |\n", + "| $X_{95}$ | 12.33 c/mL | fixed $X_{95}:X_{50}$ ratio | Gen-Probe (2012) |\n", + "| $V_{trans}$ | 20 mL | $\\mathcal{U}(15,50)$ | Bruhn et al. (2013)24; Nguyen et al. (2016) |\n", + "| $\\hat{I}$ | $10/10^5$ person-years | $\\mathcal{N}(10,25)$ | N/A |\n" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "metadata": { "pycharm": { "is_executing": false } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10.03\n" - ] - } - ], + "outputs": [], + "source": [ + "pool_size = 16\n", + "retests = 1\n", + "copies_per_virion = 2\n", + "C0 = 0.00025\n", + "doubling_time = 0.8542\n", + "doubling_time_sigma = math.sqrt(0.00306)\n", + "k = 0.02434\n", + "k_shape = 3.98547\n", + "k_scale = 0.00678\n", + "lod50 = 2.73\n", + "lod50_sigma = math.sqrt(0.1099802)\n", + "lod95_lod50_ratio = 12.33/2.73\n", + "volume_transfused = 25\n", + "volume_transfused_range = [15,35]\n", + "incidence = 10/10e5\n", + "incidence_sigma = 5/10e5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "iwp_risk_days_ffp = risk_days(copies_per_virion, C0, doubling_time, volume_transfused_ffp, \n", - " infectivity_pv, pool_size, lod50, lod95, retests)\n", - "print(round(iwp_risk_days_ffp, 2))\n", - "iwp_risk_years_ffp = iwp_risk_days_ffp / 365.25" + "### Infectious Window Period" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "* Residual risk point estimate (per million transfusions)" + "Because multiprocessing seems not to work with functions defined in the notebook, we will import the separate module." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import residualrisk as rr" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "iwp_pe, iwp_ci, iwp_bs = rr.iwp_bs_par(k, \n", + " k_shape, \n", + " k_scale, \n", + " doubling_time, \n", + " doubling_time_sigma, \n", + " lod50, \n", + " lod50_sigma, \n", + " lod95_lod50_ratio, \n", + " volume_transfused,\n", + " volume_transfused_range,\n", + " pool_size, \n", + " retests, \n", + " C0 = C0, \n", + " copies_per_virion = copies_per_virion, \n", + " alpha = 0.05,\n", + " n_bs = 25000)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, "metadata": { "pycharm": { "is_executing": false @@ -590,79 +879,66 @@ "name": "stdout", "output_type": "stream", "text": [ - "5.491\n" + "4.763 days\n", + "95% CI: [3.408 6.489]\n" ] } ], "source": [ - "RR_ffp = incidence * iwp_risk_years_ffp * 1e6\n", - "print(round(RR_ffp, 3))" + "print(round(iwp_pe, 3), \"days\")\n", + "print(\"95% CI:\", np.round_(iwp_ci, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Worst case scenario" + "### Residual Risk" ] }, { "cell_type": "code", - "execution_count": 11, - "metadata": { - "pycharm": { - "is_executing": false - } - }, - "outputs": [], - "source": [ - "incidence_wc = 30 / 1e5" - ] - }, - { - "cell_type": "markdown", + "execution_count": 15, "metadata": {}, + "outputs": [], "source": [ - "* RR from RBC transfusions (per million)" + "rr_pe, rr_ci, rr_se = rr.residual_risk_iwp(iwp_pe, \n", + " iwp_bs, \n", + " incidence, \n", + " incidence_sigma,\n", + " per = 1e6\n", + " )" ] }, { "cell_type": "code", - "execution_count": 12, - "metadata": { - "pycharm": { - "is_executing": false - } - }, + "execution_count": 16, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "9.06\n", - "7.442\n" + "0.13 per million units\n", + "95% CI: [0.11 0.338]\n" ] } ], "source": [ - "iwp_risk_days_rbc = risk_days(copies_per_virion, C0, doubling_time, volume_transfused_rbc, \n", - " infectivity_pv_worst, pool_size, lod50, lod95, retests)\n", - "print(round(iwp_risk_days_rbc, 2))\n", - "iwp_risk_years_rbc = iwp_risk_days_rbc / 365.25\n", - "RR_rbc = incidence_wc * iwp_risk_years_rbc * 1e6\n", - "print(round(RR_rbc, 3))" + "print(round(rr_pe, 3), \"per million units\")\n", + "print(\"95% CI:\", np.round_(rr_ci, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "* RR from FFP transfusions (per million)" + "## \"Infectiousness worst case scenario\" IWP and RR" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 17, "metadata": { "pycharm": { "is_executing": false @@ -673,25 +949,46 @@ "name": "stdout", "output_type": "stream", "text": [ - "11.9\n", - "9.773\n" + "7.7806993693915425\n" + ] + } + ], + "source": [ + "iwp_wc = risk_days_wc(copies_per_virion,\n", + " C0,\n", + " doubling_time,\n", + " volume_transfused, \n", + " pool_size,\n", + " lod50,\n", + " lod95_lod50_ratio,\n", + " retests\n", + " )\n", + "print(iwp_wc)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.213 per million units\n" ] } ], "source": [ - "iwp_risk_days_ffp = risk_days(copies_per_virion, C0, doubling_time, volume_transfused_ffp, \n", - " infectivity_pv_worst, pool_size, lod50, lod95, retests)\n", - "print(round(iwp_risk_days_ffp, 2))\n", - "iwp_risk_years_ffp = iwp_risk_days_ffp / 365.25\n", - "RR_ffp = incidence_wc * iwp_risk_years_ffp * 1e6\n", - "print(round(RR_ffp, 3))" + "rr_wc = iwp_wc / 365.25 * incidence * 1e6\n", + "print(round(rr_wc, 3), \"per million units\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Residual risk from RBC transfusions with ID-NAT" + "## Residual risk with ID-NAT" ] }, { @@ -705,7 +1002,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 39, "metadata": { "pycharm": { "is_executing": false @@ -716,46 +1013,48 @@ "name": "stdout", "output_type": "stream", "text": [ - "2.95\n", - "1.613\n" + "1.572 days\n", + "0.043 per million units\n", + "66.99 % reduction in risk\n" ] } ], "source": [ "pool_size_idnat = 1\n", "retests_idnat = 0\n", - "iwp_risk_days_rbc = risk_days(copies_per_virion, C0, doubling_time, volume_transfused_rbc, \n", - " infectivity_pv, pool_size_idnat, lod50, lod95, retests_idnat)\n", - "print(round(iwp_risk_days_rbc, 2))\n", - "iwp_risk_years_rbc = iwp_risk_days_rbc / 365.25\n", - "RR_rbc = incidence * iwp_risk_years_rbc * 1e6\n", - "print(round(RR_rbc, 3))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Plot the probability of infection and non-detection and in our example" + "iwp_idnat = risk_days(copies_per_virion,\n", + " C0,\n", + " doubling_time,\n", + " volume_transfused, \n", + " k,\n", + " pool_size_idnat,\n", + " lod50,\n", + " lod95_lod50_ratio,\n", + " retests_idnat\n", + " )\n", + "rr_idnat = iwp_idnat / 365.25 * incidence * 1e6\n", + "print(round(iwp_idnat, 3), \"days\")\n", + "print(round(rr_idnat, 3), \"per million units\")\n", + "print(round((rr_pe-rr_idnat)/rr_pe*100, 3), \"% reduction in risk\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### RBC transfusion with MP32 screening" + "## Demonstrative plots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Probability of infection" + "### HIV TT dose-response model" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 20, "metadata": { "pycharm": { "is_executing": false @@ -764,7 +1063,17 @@ "outputs": [ { "data": { - "image/png": "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\n", + "text/plain": [ + "Text(0, 0.5, 'Probability')" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", "text/plain": [ "
" ] @@ -777,34 +1086,36 @@ ], "source": [ "%matplotlib inline\n", - "x = np.arange(-5, 25, 0.01)\n", + "x = np.arange(0, 1000, 0.01)\n", "y = []\n", - "for t in x:\n", - " p = prob_infectious(t, C0, doubling_time, volume_transfused_rbc, infectivity_pv)\n", + "for copies in x:\n", + " p = prob_infectious_copies(copies, k = k)\n", " y.append(p)\n", "plt.plot(x, y)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Probability of non-detection" + "plt.ylim(top=1.1)\n", + "plt.xscale(\"log\")\n", + "plt.xlabel('RNA copies transfused')\n", + "plt.ylabel('Probability')" ] }, { "cell_type": "code", - "execution_count": 16, - "metadata": { - "pycharm": { - "is_executing": false - } - }, + "execution_count": 21, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "text/plain": [ + "Text(0, 0.5, 'Probability')" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEGCAYAAABo25JHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAe2ElEQVR4nO3deZhU9Z3v8fe39wYaGroBERqapVVwwaVFRI27gcSMGp25mk1NjDGjSWbuZGZ85uaZ5N4kc7NMlpnEhEvUaGISMjFGGYPBXRRcAIMge7M3Wy/s3TS91Pf+UQUpmqYX6NOnqs7n9Tz91Nmq+FpW96fO73fO72fujoiIRFdW2AWIiEi4FAQiIhGnIBARiTgFgYhIxCkIREQiLifsAnqqtLTUy8vLwy5DRCStLFmypM7dh3a0L+2CoLy8nMWLF4ddhohIWjGzzSfap6YhEZGIUxCIiEScgkBEJOIUBCIiEacgEBGJOAWBiEjEKQhERCJOQSAiEnEKAhGRiFMQiIhEnIJARCTiFAQiIhGnIBARiTgFgYhIxAUWBGb2qJnVmNn7J9hvZvafZlZlZsvM7MKgahERkRML8ozgMWB6J/tnABWJn3uBnwZYi4iInEBgE9O4+3wzK+/kkJuAX7i7A2+ZWbGZjXD3HUHVJJLuDh5uZevuRuoPNnPwcAv7m1ppammjLebEHGIxp82dmDvuYVcrve2C0cVMG1/a668b5gxlI4GtSevViW3HBYGZ3Uv8rIHRo0f3SXEiqaBmfxN/XL6DN9fX8+ete6k9cDjskiRE9105PuOCwDrY1uF3GHefBcwCqKys1PccyXjvb9vHD19cx8urdxFzGFPSjysqSqkYVkTZkEKGFRUwID+HooIcCvOyyTYjK8vIMsjOMrLMMAPr8NdM0lVWQP87wwyCaqAsaX0UsD2kWkRSQsPhVv5t7ip+9fYWBhXm8vmrxvPRC0cxfuiAsEuTDBZmEMwBHjCz2cAlwD71D0iUba5v4O7HFrGxroF7Lh/LF6+rYGBBbthlSQQEFgRm9hvgKqDUzKqBrwK5AO4+E5gLfAioAhqBu4OqRSTVrdqxn088/DZt7vz6nqlcOr4k7JIkQoK8auiOLvY7cH9Q/75Iuthc38AnH3mH3OwsfvfZSxinZiDpY7qzWCREDYdb+fRji2iLxXjinikKAQlFmH0EIpHm7vzLH5azsa6BJ+65hAnDisIuSSJKZwQiIXl66TaeWbqdv7vujECuDRfpLgWBSAj2NjbzjWdXcX5ZMfdfPSHsciTi1DQkEoJvPbeavYdaeOKj55Id1F1CIt2kMwKRPrZ6535+u3grn76snIkjBoZdjoiCQKSv/fu8NQzIz+GBqyvCLkUEUBCI9Kklm3fz4qoa7rtyPIP66a5hSQ0KApE+9KOXqyjpn8fdl5WHXYrIUQoCkT6yZucBXl1Ty13TyumXp+s0JHUoCET6yM9e30BhbjafmDom7FJEjqEgEOkDu/Y38czSbfyPi8sY3D8v7HJEjqEgEOkDv120lZY2V9+ApCQFgUjA2mLObxdt5YqKUsaU9A+7HJHjKAhEAjZ/XS3b9h7ijimab1tSk4JAJGC/eXsLJf3zuG7i8LBLEemQgkAkQDUHmnhpdQ23VY4iL0e/bpKa9MkUCdAfl+2gLebcduGosEsROSEFgUiAnlm6nYkjBlIxXJPOSOpSEIgEZEt9I0u37uWm808PuxSRTikIRAIy571tAHxksoJAUpuCQCQA7s4zS7dTOWYwI4sLwy5HpFMKApEArN55gHU1B9UsJGlBQSASgD+9vxMzmH7OiLBLEemSgkAkAM+v3EXlmMEMLcoPuxSRLikIRHrZ1t2NrNqxnxsmnRZ2KSLdoiAQ6WXPr9wFwPWTNKSEpAcFgUgve37FTs4cXkR5qUYalfSgIBDpRbsbmlm0aTc3nK2zAUkfgQaBmU03szVmVmVmD3awf5CZ/beZvWdmK8zs7iDrEQnaS6t2EXPUPyBpJbAgMLNs4CFgBjAJuMPMJrU77H5gpbtPBq4CvmdmmsdP0tbzK3cxYlAB54wcGHYpIt0W5BnBFKDK3Te4ezMwG7ip3TEOFJmZAQOA3UBrgDWJBOZwaxsLquq4duIw4h9pkfQQZBCMBLYmrVcntiX7MTAR2A4sB77k7rH2L2Rm95rZYjNbXFtbG1S9IqdkyaY9NDa3cdUZw8IuRaRHggyCjr4Sebv1DwJLgdOB84Efm9lx59TuPsvdK929cujQob1fqUgveHVtLXnZWVw6viTsUkR6JMggqAbKktZHEf/mn+xu4CmPqwI2AmcFWJNIYF5bU8vFYwfTPz8n7FJEeiTIIFgEVJjZ2EQH8O3AnHbHbAGuBTCz4cCZwIYAaxIJxPa9h1iz6wBXnqEzVkk/gX11cfdWM3sAmAdkA4+6+wozuy+xfybwdeAxM1tOvCnpn929LqiaRILy2tp439VVZ6p/QNJPoOew7j4XmNtu28yk5e3ADUHWINIXXltTy4hBBVQMGxB2KSI9pjuLRU5RS1uMBVV1XHXmUF02KmlJQSByit7dvIcDh1vVPyBpS0EgcopeXVtLTpYxbUJp2KWInBQFgcgpem1NLReOGczAgtywSxE5KQoCkVOwu6GZlTv2c4XOBiSNKQhETsHC9fGrndUsJOlMQSByChZU1TMgP4fJowaFXYrISVMQiJyChevrmDpuCDnZ+lWS9KVPr8hJqt7TyOb6RqaNV7OQpDcFgchJWlhVD8Bl6h+QNKcgEDlJC9bXUTognzOGa1gJSW8KApGT4O4sXF/PtPElGlZC0p6CQOQkrKs5SO2Bw1w2QZPQSPpTEIichDfWJe4fUEexZAAFgchJWLi+jtFD+lE2pF/YpYicMgWBSA+1tsV4e8NuXS0kGUNBINJDy7bt48DhVvUPSMZQEIj00MKqeP/ApeMUBJIZFAQiPbSgqp6JIwZSMiA/7FJEeoWCQKQHmlraWLJlD5eN19mAZA4FgUgPLN60h+bWmDqKJaMoCER64I2qOnKyjCljh4Rdikiv6VYQmNmNZqbQkMhbuL6O88uK6Z+fE3YpIr2mu3/cbwfWmdl3zGxikAWJpKp9jS28v22fmoUk43QrCNz9E8AFwHrg52b2ppnda2ZFgVYnkkLe2lhPzGGaOoolw3S7ucfd9wO/B2YDI4BbgHfN7AsB1SaSUhZW1VGYm80FoweHXYpIr+puH8FfmdkfgJeBXGCKu88AJgNfDrA+kZSxcH09F48dQl6Oussks3S3x+s24AfuPj95o7s3mtmne78skdRSs7+JdTUHufWiUWGXItLruvvVZkf7EDCzbwO4+0u9XpVIinlzQ2JaSg07LRmou0FwfQfbZnT1JDObbmZrzKzKzB48wTFXmdlSM1thZq91sx6RPrWwqp6BBTlMOn1g2KWI9LpOm4bM7PPA3wLjzWxZ0q4iYEEXz80GHiIeItXAIjOb4+4rk44pBn4CTHf3LWY27OT+M0SCtWB9HVPHlZCdpWkpJfN01Ufwa+A54P8Cyd/oD7j77i6eOwWocvcNAGY2G7gJWJl0zMeAp9x9C4C71/SgdpE+sXV3I9V7DvHZK8aFXYpIILpqGnJ33wTcDxxI+sHMurrHfiSwNWm9OrEt2RnAYDN71cyWmNmnOnqhxD0Li81scW1tbRf/rEjvWlB1ZFpK3T8gmak7ZwQ3AksAB5LPix3o7CtSR+fQ3sG/fxFwLVAIvGlmb7n72mOe5D4LmAVQWVnZ/jVEArVwfT1Di/KZMGxA2KWIBKLTIHD3GxOPY0/itauBsqT1UcD2Do6pc/cGoMHM5hO/N2EtIinA3Vm4vp7LJpRgpv4ByUxddRZf2Nl+d3+3k92LgAozGwtsIz5e0cfaHfMM8GMzywHygEuAH3RVtEhfWVdzkLqDh3XZqGS0rpqGvtfJPgeuOeFO91YzewCYB2QDj7r7CjO7L7F/pruvMrM/AcuAGPCwu7/fo/8CkQAdnZZS/QOSwbpqGrr6VF7c3ecCc9ttm9lu/bvAd0/l3xEJyoL19ZQNKaRsSL+wSxEJTFdNQ9e4+8tm9tGO9rv7U8GUJRK+tpjz1oZ6PnzuiLBLEQlUV01DVxIfaO4jHexzQEEgGev9bfs40NSqZiHJeF01DX018Xh335QjkjoWro+PLzRNHcWS4bo7DHWJmf2nmb2buPHrP8xMX5Mkoy1cX8cZwwcwtCg/7FJEAtXdQedmA7XArcSHpK4FfhtUUSJhO9zaxqJNu3U2IJHQ3fkIhrj715PWv2FmNwdRkEgqWLplL00tMQ0rIZHQ3TOCV8zsdjPLSvz8DfDHIAsTCdOCqjqyDC4ZpyCQzNfV5aMH+MsYQ/8TeCKxKws4CHw10OpEQjJ/XR3nlxUzqDA37FJEAtfpGYG7F7n7wMRjlrvnJH6y3F0zdEhG2tfYwrLqvVxeMTTsUkT6RHf7CDCzwUAFUHBkW/vpK0UywcL1dcQcPlChjmKJhm4FgZndA3yJ+AiiS4GpwJt0MtaQSLqav66OovwcJpcVh12KSJ/obmfxl4CLgc2J8YcuIH4JqUhGcXfmr63l0vEl5GZ399dDJL1195Pe5O5NAGaW7+6rgTODK0skHJvqG9m29xBXqFlIIqS7fQTViYnmnwZeMLM9HD/JjEjae31d/ET3CnUUS4R0Kwjc/ZbE4tfM7BVgEPCnwKoSCcnr6+ooG1LImBINOy3R0ZOrhi4ELid+X8ECd28OrCqRELS0xXhzfT1/df7pmpZSIqW7g879K/A4UAKUAj83s68EWZhIX1u6dS8HD7dyxQT1D0i0dPeM4A7ggqQO428B7wLfCKowkb72+tpaskzDTkv0dPeqoU0k3UgG5APre70akRDNX1fH5LJiBvXTsBISLV2NNfQj4n0Ch4EVZvZCYv164I3gyxPpG7sbmnmvei9fvKYi7FJE+lxXTUOLE49LgD8kbX81kGpEQvLa2hrc4ZqzhoVdikif62qqysePLJtZHnBGYnWNu7cEWZhIX3pldS2lA/I4d+SgsEsR6XPdHWvoKuJXDW0iPiR1mZndqUHnJBO0tsV4bW0t100cTlaWLhuV6OnuVUPfA25w9zUAZnYG8BvgoqAKE+krS7fuZd+hFq4+S3cTSzR196qh3CMhAODuawFdWiEZ4eXVNWRnmYaVkMjq7hnBEjN7BPhlYv3jxDuQRdLeK2tqqRwzWLORSWR194zgPmAF8EXiQ1KvTGwTSWs79h1i1Y79XK2rhSTCujwjMLMsYIm7nwN8P/iSRPrOq2vio43qslGJsi7PCNw9BrxnZqP7oB6RPvXy6hpGFhdSMWxA2KWIhKa7TUMjiN9Z/JKZzTny09WTzGy6ma0xsyoze7CT4y42szYzu627hYucqqaWNhZU1XH1WUM12qhEWnc7i/93T1/YzLKBh4gPR1ENLDKzOe6+soPjvg3M6+m/IXIqFlTV0djcxg2TTgu7FJFQdTXWUAHxTuEJwHLgEXdv7eZrTwGq3H1D4rVmAzcR72hO9gXg98TnRBbpM/NW7KSoIIep40rCLkUkVF01DT0OVBIPgRnEbyzrrpHA1qT16sS2o8xsJHALMLOzFzKze81ssZktrq2t7UEJIh1rizkvrqrhmrOGkZejSeol2rpqGprk7ucCJO4jeKcHr91Ro6u3W/8h8M/u3tZZG627zwJmAVRWVrZ/DZEeW7xpN7sbmtUsJELXQXB0YDl3b+1hh1o1UJa0PorjJ7yvBGYnXrcU+JCZtbr70z35h0R66vmVu8jLyeLKM3U3sUhXQTDZzPYnlg0oTKwb4O4+sJPnLgIqzGwssA24HfhY8gHuPvbIspk9BjyrEJCguTvzVuzk8gmlDMjv9rTdIhmrq2Gos0/2hRNnEA8QvxooG3jU3VeY2X2J/Z32C4gEZdWOA1TvOcQDV08IuxSRlBDo1yF3nwvMbbetwwBw97uCrEXkiOdX7sQMrp04POxSRFKCLpeQyJm7fAeVYwYztCg/7FJEUoKCQCJl7a4DrN11kBvPOz3sUkRShoJAIuXZ97aTZTDjXF02KnKEgkAiw915dtkOpo4rYVhRQdjliKQMBYFExort+9lQ16BmIZF2FAQSGc8u20F2ljH9HDULiSRTEEgkxJuFtnP5hFKG9M8LuxyRlKIgkEhYunUv1XsOceN5I8IuRSTlKAgkEp56dxv5OVl8UM1CIsdREEjGO9zaxpz3tvPBs09jYEFu2OWIpBwFgWS8l1bVsO9QC7deNCrsUkRSkoJAMt7vl1QzfGA+l08oDbsUkZSkIJCMVnvgMK+ureXmC0aSnaUJ6kU6oiCQjPbM0m20xZzbLlSzkMiJKAgkY7k7Ty6pZvKoQVQMLwq7HJGUpSCQjPXulr2s3nmAv64s6/pgkQhTEEjG+tXbm+mfl83NF4wMuxSRlKYgkIy0p6GZZ5ft4JYLR2peYpEuKAgkIz25pJrm1hifmDom7FJEUp6CQDJOLOb8+p0tVI4ZzFmnDQy7HJGUpyCQjLNgfR0b6xr4+NTRYZcikhYUBJJxHnljI6UD8phxjkYaFekOBYFklLW7DvDqmlruvLScgtzssMsRSQsKAskoD7++gYLcLHUSi/SAgkAyRs2BJp7+83Zuu2gUgzULmUi3KQgkY/zyzc20xGJ85vJxYZciklYUBJIRDjS18Is3N3P9xOGMLe0fdjkiaUVBIBnh8YWb2HeohS9cUxF2KSJpJ9AgMLPpZrbGzKrM7MEO9n/czJYlfhaa2eQg65HMdPBwKw+/sZFrzxrGuaMGhV2OSNoJLAjMLBt4CJgBTALuMLNJ7Q7bCFzp7ucBXwdmBVWPZK7HF25ib2MLX7pOZwMiJyPIM4IpQJW7b3D3ZmA2cFPyAe6+0N33JFbfAjR7iPTIwcOt/Oz1DVx95lDOG1UcdjkiaSnIIBgJbE1ar05sO5HPAM8FWI9koP/32nr2Nrbw99efEXYpImkryPF5O5og1js80Oxq4kFw+Qn23wvcCzB6tMaPkbid+5r42esb+Mjk03U2IHIKgjwjqAaSp4YaBWxvf5CZnQc8DNzk7vUdvZC7z3L3SnevHDp0aCDFSvr5/gtraIs5//TBM8MuRSStBRkEi4AKMxtrZnnA7cCc5APMbDTwFPBJd18bYC2SYVbv3M+TS6r51KXllA3pF3Y5ImktsKYhd281sweAeUA28Ki7rzCz+xL7ZwL/CpQAPzEzgFZ3rwyqJskM7s7X5qygqCCXL1wzIexyRNJeoHP4uftcYG67bTOTlu8B7gmyBsk8Ty/dxlsbdvNvt5xLcT+NKSRyqnRnsaSVfYda+OYfVzG5rJjbLy7r+gki0iUFgaSV785bze6GZr558zlkZXV0YZqI9JSCQNLGwqo6nnhrC3dNG8s5IzWUhEhvURBIWjjQ1MI/PrmMsaX9+UddLirSqwLtLBbpLd/84yp27DvE7+6bRmGepqAU6U06I5CU99zyHcxetJXPfmAcF40ZHHY5IhlHQSApbVNdA//05DImlxXzD9erSUgkCAoCSVlNLW387a/eJSvLeOhjF5CXo4+rSBDURyApyd35l6eWs3LHfh65s5JRgzWMhEhQ9BVLUtKPX67iqT9v4++vO4NrJw4PuxyRjKYgkJQz573tfO+FtdxywUi+eK3GEhIJmoJAUsqra2r48n+9x8Xlg/nWreeSGIxQRAKkIJCU8eb6ej73yyVMGDaAhz91Mfk5ul9ApC8oCCQlvLNxN595fBGjh/Tjl5+ZwqB+uWGXJBIZCgIJ3Ysrd/HJR97mtEEF/OqeSygZkB92SSKRoiCQUP1u8VY+98QSzjqtiCfvm8awgQVhlyQSObqPQELR2hbjW8+t5uE3NnL5hFJmfvIiBuTr4ygSBv3mSZ/b09DMF2f/mdfX1XHnpWP4yo2TyM3WyalIWBQE0qfmr63ly797j72NLXzn1vP4G80yJhI6BYH0icbmVr47bw0/X7CJCcMG8PO7L+bs0zW5jEgqUBBIoNyd51fu4v/890q27T3EXdPKeXDGWRTk6h4BkVShIJDArN65n28/t5pX1tRy1mlF/O6+S7m4fEjYZYlIOwoC6XUbag/ygxfX8eyy7QzIy+ErH57IndPK1SEskqIUBNIr3J1Fm/bwyBsbeGHlLvJzsvn8leO59wPjKO6XF3Z5ItIJBYGckn2NLTy7fDuz39nK8m37KO6Xy+euHM+nLxvL0CLdISySDhQE0mONza3MX1vHnPe28eLKGprbYpwxfADfuPkcbr1wlCaXF0kzCgLpkruzdfchXltXy0urdrFwfT3NrTFK+ufx8amjufXCUZx9+kANGS2SphQEcpyWthhVNQdZsnkP72zczTsbd7NzfxMAY0r68YlLxnDdpGFcXD5EHcAiGUBBEGGxmLPrQBMb6xqoqjnIim37WbFjH2t3HqS5LQbAsKJ8powdwiVjh3Dp+BLGDx2gb/4iGSbQIDCz6cB/ANnAw+7+rXb7LbH/Q0AjcJe7vxtkTVFyuLWNmv2H2bW/iZ37m9iVWN5c38CmukY2726gqSV29PjB/XI5+/RB3HVZOWefPpDzRhVTXtJPf/hFMlxgQWBm2cBDwPVANbDIzOa4+8qkw2YAFYmfS4CfJh4jry3mNDa3cqi5jcbmNg61JB6b22hsbqWxuY39TS3saWhh76Fm9jW2sPdQC3sbm9l7qIU9Dc3saWw57nXzcrIoG1zI2NL+XFFRSnlpf8pL+jN+WH9OG1igP/oiERTkGcEUoMrdNwCY2WzgJiA5CG4CfuHuDrxlZsVmNsLdd/R2MZvrG3h9XR3uTswhlniMrzvuHN1+omOObCNp31+e68cc39rmtMac5rYYLa0xWmNOS1ss8ePHPLYmlpsT+xub22hujXX9H5VQlJ/DoH65FPfLpbgwjxHFhRQX5jJ8YAGnDSxg2MB8ThsUXx5UmKs/9iJyjCCDYCSwNWm9muO/7Xd0zEjgmCAws3uBewFGjx59UsUs37aPrzz9/kk9N8sgy4wsM7Bj1+3oMon1+LacLCM3O4ucbCMvO+vocm52FgW5WRQV5JCTlUVeTuK4pOXC3GwK87Lpl5dNYV4O/XKPLGfTLy/n6HJxYS4DC3PVYSsipyTIIOjoa6efxDG4+yxgFkBlZeVx+7vjuonDeed/XXv0D3iWgbV7PPYP+1/2iYhksiCDoBpIHmx+FLD9JI7pFQW52RrxUkSkA0G2KSwCKsxsrJnlAbcDc9odMwf4lMVNBfYF0T8gIiInFtgZgbu3mtkDwDzil48+6u4rzOy+xP6ZwFzil45WEb989O6g6hERkY4Feh+Bu88l/sc+edvMpGUH7g+yBhER6ZwuNxERiTgFgYhIxCkIREQiTkEgIhJxFu+vTR9mVgtsPsmnlwJ1vVhOJtJ71Dm9P13Te9S5sN6fMe4+tKMdaRcEp8LMFrt7Zdh1pDK9R53T+9M1vUedS8X3R01DIiIRpyAQEYm4qAXBrLALSAN6jzqn96dreo86l3LvT6T6CERE5HhROyMQEZF2FAQiIhEXmSAws+lmtsbMqszswbDrSUVmtsnMlpvZUjNbHHY9YTOzR82sxszeT9o2xMxeMLN1icfBYdYYthO8R18zs22Jz9FSM/tQmDWGyczKzOwVM1tlZivM7EuJ7Sn1OYpEEJhZNvAQMAOYBNxhZpPCrSplXe3u56fadc4heQyY3m7bg8BL7l4BvJRYj7LHOP49AvhB4nN0fmIU4qhqBf7B3ScCU4H7E397UupzFIkgAKYAVe6+wd2bgdnATSHXJCnO3ecDu9ttvgl4PLH8OHBznxaVYk7wHkmCu+9w93cTyweAVcTnZU+pz1FUgmAksDVpvTqxTY7lwPNmtsTM7g27mBQ1/MgseonHYSHXk6oeMLNliaajSDefHWFm5cAFwNuk2OcoKkHQ0Qz0um72eJe5+4XEm9DuN7MPhF2QpKWfAuOB84EdwPfCLSd8ZjYA+D3wd+6+P+x62otKEFQDZUnro4DtIdWSstx9e+KxBvgD8SY1OdYuMxsBkHisCbmelOPuu9y9zd1jwM+I+OfIzHKJh8Cv3P2pxOaU+hxFJQgWARVmNtbM8oDbgTkh15RSzKy/mRUdWQZuAN7v/FmRNAe4M7F8J/BMiLWkpCN/4BJuIcKfIzMz4BFglbt/P2lXSn2OInNnceISth8C2cCj7v7NkEtKKWY2jvhZAMTnsv511N8jM/sNcBXxYYN3AV8Fngb+CxgNbAH+2t0j21l6gvfoKuLNQg5sAj53pD08aszscuB1YDkQS2z+F+L9BCnzOYpMEIiISMei0jQkIiInoCAQEYk4BYGISMQpCEREIk5BICIScQoCkRMws5KkETR3Jo2oedDMfhJ2fSK9RZePinSDmX0NOOju/x52LSK9TWcEIj1kZleZ2bOJ5a+Z2eNm9nxiPoePmtl3EvM6/CkxvABmdpGZvZYY0G9eu7tvRUKlIBA5deOBDxMfWvgJ4BV3Pxc4BHw4EQY/Am5z94uAR4FI37UtqSUn7AJEMsBz7t5iZsuJD2Hyp8T25UA5cCZwDvBCfOgZsomPyimSEhQEIqfuMIC7x8ysxf/S8RYj/jtmwAp3vzSsAkU6o6YhkeCtAYaa2aUQH5bYzM4OuSaRoxQEIgFLTI96G/BtM3sPWApMC7cqkb/Q5aMiIhGnMwIRkYhTEIiIRJyCQEQk4hQEIiIRpyAQEYk4BYGISMQpCEREIu7/Awvuk9Dr/Z84AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] @@ -817,25 +1128,31 @@ ], "source": [ "%matplotlib inline\n", - "x = np.arange(-5, 25, 0.01)\n", + "x = np.arange(0, 21, 0.01)\n", "y = []\n", "for t in x:\n", - " p = prob_nondetection(t, copies_per_virion, C0, doubling_time, pool_size, lod50, lod95, retests)\n", + " p = prob_infectious(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k = k)\n", " y.append(p)\n", "plt.plot(x, y)\n", - "plt.show()" + "plt.ylim(top=1.1)\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Probability')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Probability of infection and non-detection" + "### Probability of non-detection" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 22, "metadata": { "pycharm": { "is_executing": false @@ -844,7 +1161,17 @@ "outputs": [ { "data": { - "image/png": "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\n", + "text/plain": [ + "Text(0, 0.5, 'Probability')" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", "text/plain": [ "
" ] @@ -860,23 +1187,31 @@ "x = np.arange(-5, 25, 0.01)\n", "y = []\n", "for t in x:\n", - " p = prob_infectious_nondetection(t, copies_per_virion,C0,doubling_time,volume_transfused_rbc,\n", - " infectivity_pv,pool_size,lod50,lod95,retests)\n", + " p = prob_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", " y.append(p)\n", "plt.plot(x, y)\n", - "plt.show()" + "plt.ylim(top=1.1)\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Probability')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### FFP transfusion with MP32 screening" + "### Probability of infection and non-detection" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 23, "metadata": { "pycharm": { "is_executing": false @@ -885,7 +1220,17 @@ "outputs": [ { "data": { - "image/png": "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\n", + "text/plain": [ + "Text(0, 0.5, 'Probability')" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", "text/plain": [ "
" ] @@ -898,42 +1243,71 @@ ], "source": [ "%matplotlib inline\n", - "x = np.arange(-5, 25, 0.01)\n", + "x = np.arange(0, 23, 0.01)\n", "y = []\n", + "inf = []\n", + "nd = []\n", "for t in x:\n", - " p = prob_infectious_nondetection(t, copies_per_virion,C0,doubling_time,volume_transfused_ffp,\n", - " infectivity_pv,pool_size,lod50,lod95,retests)\n", + " i = prob_infectious(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k = k)\n", + " inf.append(i)\n", + " n = prob_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", + " nd.append(n)\n", + " p = prob_infectious_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", " y.append(p)\n", + "plt.plot(x, inf, '--')\n", + "plt.plot(x, nd, '--')\n", "plt.plot(x, y)\n", - "plt.show()" + "plt.fill_between(x, 0, y, alpha = 0.3)\n", + "plt.ylim(top=1.05)\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Probability')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### RBC and ID-NAT screening" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note: Here we continue to assume that each donation is retested once, and if not repeat-reactive is released." + "### Probability of infection and non-detection (infectiousness worst case)" ] }, { "cell_type": "code", - "execution_count": 19, - "metadata": { - "pycharm": { - "is_executing": false - } - }, + "execution_count": 24, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "text/plain": [ + "Text(0, 0.5, 'Probability')" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", "text/plain": [ "
" ] @@ -946,173 +1320,120 @@ ], "source": [ "%matplotlib inline\n", - "x = np.arange(-5, 25, 0.01)\n", + "x = np.arange(0, 23, 0.01)\n", "y = []\n", + "inf = []\n", + "nd = []\n", "for t in x:\n", - " p = prob_infectious_nondetection(t, copies_per_virion,C0,doubling_time,volume_transfused_rbc,\n", - " infectivity_pv,pool_size_idnat,lod50,lod95,retests_idnat)\n", + " i = prob_infectious_wc(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused)\n", + " inf.append(i)\n", + " n = prob_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", + " nd.append(n)\n", + " p = prob_infectious_nondetection_wc(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " pool_size, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests)\n", " y.append(p)\n", + "plt.plot(x, inf, '--')\n", + "plt.plot(x, nd, '--')\n", "plt.plot(x, y)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Estimate IWP from lookback data" + "plt.fill_between(x, 0, y, alpha = 0.3)\n", + "plt.ylim(top=1.05)\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Probability')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This code is extracted from the Infection Dating Tool and is a placeholder for an implementation of the \"inverse exposure time\" logic." + "### Probability of infection and non-detection (ID-NAT)" ] }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "# user supplies inter-donation intervals of investigated donations from RD\n", - "def residual_risk_operational(n_transmissions,\n", - " intervals, \n", - " negative_diagnositc_day,\n", - " positive_diagnostic_delay):\n", - " inverse_intervals = [1/(x + negative_diagnositc_day - positive_diagnostic_delay) for x in intervals]\n", - " total_exposure = sum(inverse_intervals)\n", - " iwp = n_transmissions / total_exposure\n", - " if n_transmissions > 0:\n", - " iwp_lb = stats.chi2.ppf(0.025, df=2*n_transmissions)/2/total_exposure\n", - " else:\n", - " iwp_lb = 0.0\n", - " iwp_ub = stats.chi2.ppf(0.975, df=2*(n_transmissions+1))/2/total_exposure\n", - " return (iwp, (iwp_lb, iwp_ub))" - ] - }, - { - "cell_type": "code", - "execution_count": 21, + "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(2.504387870034906, (0.6823614054202072, 6.412227612141968))" + "Text(0, 0.5, 'Probability')" ] }, - "execution_count": 21, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" - } - ], - "source": [ - "# example calculation\n", - "intervals = stats.norm.rvs(180,60,250)\n", - "residual_risk_operational(4, intervals, 3, 3)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ + }, { - "ename": "NameError", - "evalue": "name 'BaseModelForm' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mDataResidualRiskForm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mBaseModelForm\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0minterval_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCharField\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequired\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwidget\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextarea\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0minterval_file\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFileField\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequired\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'BaseModelForm' is not defined" - ] + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" } ], "source": [ - "class DataResidualRiskForm(BaseModelForm):\n", - " interval_list = forms.CharField(required=False, widget=forms.Textarea())\n", - " interval_file = forms.FileField(required=False)\n", - "\n", - " def __init__(self, *args, **kwargs):\n", - " super(DataResidualRiskForm, self).__init__(*args, **kwargs)\n", - " user = self.instance.user\n", - " choices = GroupedModelChoiceField(queryset=IDTDiagnosticTest.objects.filter(Q(user=user) | Q(user=None)), group_by_field='category')\n", - " self.fields['positive_test'] = choices\n", - " self.fields['negative_test'] = choices\n", - "\n", - " class Meta:\n", - " model = ResidualRisk\n", - " fields = ['positive_test', 'negative_test', 'confirmed_transmissions']\n", - "\n", - " def clean_interval_file(self):\n", - " interval_file = self.cleaned_data.get('interval_file')\n", - " if not interval_file:\n", - " return interval_file\n", - " filename = interval_file.name\n", - " extension = os.path.splitext(filename)[1][1:].lower()\n", - " if extension == 'csv':\n", - " rows = (float(z[0]) for z in csv.reader(interval_file) if z)\n", - " elif extension in ['xls', 'xlsx']:\n", - " rows = (float(z[0]) for z in ExcelHelper(interval_file).rows() if z)\n", - " else:\n", - " raise forms.ValidationError('Unsupported file uploaded: Only CSV and Excel are allowed.')\n", - " self.cleaned_data['imported_intervals'] = [r for r in rows if r]\n", - " return interval_file\n", - "\n", - " def clean_interval_list(self):\n", - " value = self.cleaned_data.get('interval_list')\n", - " if not value:\n", - " return value\n", - " rows = [float(z.strip()) for z in value.split(u'\\n') if z and z != '\\r']\n", - " self.cleaned_data['imported_intervals'] = rows\n", - " return value\n", - "\n", - " def clean(self):\n", - " if self.cleaned_data.get('interval_file') and self.cleaned_data.get('interval_list'):\n", - " raise forms.ValidationError('You must upload either a file or a list of inter donation intervals, not both.')\n", - " if not self.cleaned_data.get('interval_file') and not self.cleaned_data.get('interval_list'):\n", - " raise forms.ValidationError('You must upload either a file or list of inter donation intervals.')\n", - "\n", - " return self.cleaned_data\n", - "\n", - " def save(self, user, commit=True):\n", - " residual_risk = super(DataResidualRiskForm, self).save(commit=False)\n", - " intervals = self.cleaned_data['imported_intervals']\n", - "\n", - " d1 = self.cleaned_data['negative_test'].get_diagnostic_delay_for_residual_risk(user)\n", - " d2 = self.cleaned_data['positive_test'].get_diagnostic_delay_for_residual_risk(user)\n", - " calculated_intervals = [1/(x + d1 - d2) for x in intervals]\n", - "\n", - " total_exposure = sum(calculated_intervals)\n", - " n_i = self.cleaned_data['confirmed_transmissions']\n", - "\n", - " ci_upper_bound = chi2.ppf(0.975, df=2*(n_i+1))/2/total_exposure\n", - " ci_lower_bound = 0\n", - " if n_i > 0:\n", - " ci_lower_bound = chi2.ppf(0.025, df=2*n_i)/2/total_exposure\n", - "\n", - " residual_risk.ci_upper_bound = ci_upper_bound\n", - " residual_risk.ci_lower_bound = ci_lower_bound\n", - "\n", - " # residual_risk is poisson rate (lambdahat)\n", - " residual_risk.residual_risk = n_i / total_exposure\n", - " residual_risk.choice = 'data'\n", - " residual_risk.upper_limit = ci_upper_bound\n", - " if commit:\n", - " residual_risk.save()\n", - "\n", - " return residual_risk\n" + "%matplotlib inline\n", + "x = np.arange(0, 23, 0.01)\n", + "y = []\n", + "inf = []\n", + "nd = []\n", + "for t in x:\n", + " i = prob_infectious(t, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k = k)\n", + " inf.append(i)\n", + " n = prob_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " pool_size_idnat, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests_idnat)\n", + " nd.append(n)\n", + " p = prob_infectious_nondetection(t, \n", + " copies_per_virion, \n", + " C0, \n", + " doubling_time, \n", + " volume_transfused, \n", + " k, \n", + " pool_size_idnat, \n", + " lod50, \n", + " lod95_lod50_ratio, \n", + " retests_idnat)\n", + " y.append(p)\n", + "plt.plot(x, inf, '--')\n", + "plt.plot(x, nd, '--')\n", + "plt.plot(x, y)\n", + "plt.fill_between(x, 0, y, alpha = 0.3)\n", + "plt.ylim(top=1.05)\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Probability')" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/residualrisk.py b/residualrisk.py new file mode 100644 index 0000000..74c6352 --- /dev/null +++ b/residualrisk.py @@ -0,0 +1,340 @@ +import math +import multiprocessing as mp +import numpy as np +import scipy.stats as stats +import scipy.integrate as si + +def concentration(C0, doubling_time, t): + concentration = C0 * 2 ** (t / doubling_time) + return concentration + +def prob_infectious_copies(n_copies, k): + prob = 1.000000000001 - math.exp(-k * n_copies) + return prob + +def prob_infectious(t, + C0, + doubling_time, + volume_transfused, + k, + copies_per_virion = 2 + ): + C = concentration(C0, doubling_time, t) + n_copies = C * copies_per_virion * volume_transfused + prob = prob_infectious_copies(n_copies, k) + return prob + +def prob_infectious_copies_wc(n_copies): + if n_copies < 2: + return 0.0 + elif n_copies >= 2: + return 1.0 + +def prob_infectious_wc(t, + C0, + doubling_time, + volume_transfused, + copies_per_virion = 2 + ): + C = concentration(C0, doubling_time, t) + n_copies = C * copies_per_virion * volume_transfused + prob = prob_infectious_copies_wc(n_copies) + return prob + +def prob_pos_init(C, + doubling_time, + pool_size, + lod50, + lod95_lod50_ratio, + z + ): + if (not isinstance(pool_size, int)) or pool_size < 1: + raise Exception("pool_size must be an integer of at least 1") + # C is in copies copies_per_virion * C when C in virions + X = z * (math.log10(((C) / (pool_size * lod50))) / + math.log10(lod95_lod50_ratio)) + prob = stats.norm.cdf(X) + return prob + +def prob_neg_retest(C, + doubling_time, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z + ): + if (not isinstance(pool_size, int)) or pool_size < 1: + raise Exception("pool_size must be an integer of at least 1") + if (not isinstance(retests, int)) or retests < 0: + raise Exception("retests must be a positive integer") + elif retests == 0: + return 0 + elif retests >= 1: + # C is in copies copies_per_virion * C when C in virions + X = z * (math.log10(((C) / lod50)) / math.log10(lod95_lod50_ratio)) + #print(X) + prob = (1 - stats.norm.cdf(X)) ** retests + return prob + +def prob_nondetection(t, + copies_per_virion, + C0, + doubling_time, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z = 1.6449 + ): + Cv = concentration(C0, doubling_time, t) + Cc = copies_per_virion * Cv + p_pos_init = prob_pos_init(Cc, doubling_time, pool_size, lod50, + lod95_lod50_ratio, z) + p_neg_retest = prob_neg_retest(Cc, doubling_time, pool_size, lod50, + lod95_lod50_ratio, retests, z) + prob = 1 - p_pos_init * (1 - p_neg_retest) + return prob + +def prob_infectious_nondetection(t, + copies_per_virion, + C0, + doubling_time, + volume_transfused, + k, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z = 1.6449 + ): + product = (prob_infectious(t, C0, doubling_time, volume_transfused, k) * + prob_nondetection(t, copies_per_virion, C0, doubling_time, + pool_size,lod50,lod95_lod50_ratio,retests,z)) + return(product) + +def risk_days(copies_per_virion, + C0, + doubling_time, + volume_transfused, + k, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z = 1.6449, + limits = (-100,500) + ): + + # Ideally we would integrate from -np.inf to np.inf, but that causes an + # overflow error, so we choose safe limits instead + rd = si.quad(prob_infectious_nondetection, limits[0], limits[1], + args=(copies_per_virion, C0, doubling_time, volume_transfused, k, + pool_size, lod50, lod95_lod50_ratio, retests, z))[0] + return rd + +def prob_infectious_nondetection_wc(t, + copies_per_virion, + C0, + doubling_time, + volume_transfused, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z = 1.6449 + ): + product = (prob_infectious_wc(t, C0, doubling_time, volume_transfused) * + prob_nondetection(t, copies_per_virion, C0, doubling_time, + pool_size,lod50,lod95_lod50_ratio,retests,z)) + return(product) + +def risk_days_wc(copies_per_virion, + C0, + doubling_time, + volume_transfused, + pool_size, + lod50, + lod95_lod50_ratio, + retests, + z = 1.6449, + limits = (-20,100) + ): + # Ideally we would integrate from -np.inf to np.inf, but that causes an + # overflow error, so we choose safe limits instead + rd = si.quad(prob_infectious_nondetection_wc, limits[0], limits[1], + args=(copies_per_virion, C0, doubling_time, volume_transfused, + pool_size, lod50, lod95_lod50_ratio, retests, z))[0] + return rd + +def iwp_bs(k, + k_gamma_shape, + k_gamma_scale, + doubling_time, + doubling_time_norm_sd, + lod50, + lod50_sd, + lod95_lod50_ratio, + volume_transfused, + volume_transfused_range, + pool_size, + retests, + C0 = 0.00025, + copies_per_virion = 2, + alpha = 0.05, + n_bs = 10000, + seed = 126887 + ): + iwp_pe = risk_days(copies_per_virion, C0, doubling_time, volume_transfused, + k, pool_size, lod50, lod95_lod50_ratio, retests) + np.random.seed(seed) + doubling_time_draws = stats.truncnorm.rvs(0, + np.inf, + doubling_time, + doubling_time_norm_sd, + n_bs) + k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs) + lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs) + volume_transfused_draws = np.random.uniform(volume_transfused_range[0], + volume_transfused_range[1], + n_bs) + iwp = [] + for i in range(n_bs): + iwp.append(risk_days(copies_per_virion, C0, doubling_time_draws[i], + volume_transfused_draws[i], k_draws[i], pool_size, + lod50_draws[i], lod95_lod50_ratio, retests)) + iwp_ci = np.quantile(iwp, (alpha/2, 1 - alpha/2)) + return (iwp_pe, iwp_ci, iwp) + +def residual_risk_iwp(iwp_pe, + iwp_bs, + incidence, + incidence_norm_sd, + per = 1e6, + alpha = 0.05, + seed = 126887): + rr_pe = incidence * iwp_pe / 365.25 * per + n_bs = len(iwp_bs) + np.random.seed(seed) + incidence_draws = stats.truncnorm.rvs(0, np.inf, incidence, + incidence_norm_sd, n_bs) + rr = [] + for i in range(n_bs): + rr.append(incidence_draws[i] * iwp_bs[i] / 365.25 * per) + rr_ci = np.quantile(rr, (0.025,0.975)) + rr_se = np.std(rr) + return (rr_pe, rr_ci, rr_se) + +def residual_risk(k, + k_gamma_shape, + k_gamma_scale, + doubling_time, + doubling_time_norm_sd, + lod50, + lod50_sd, + lod95_lod50_ratio, + volume_transfused, + volume_transfused_range, + pool_size, + retests, + incidence, + incidence_norm_sd, + C0 = 0.00025, + copies_per_virion = 2, + per = 1e6, + n_bs = 10000, + seed = 126887 + ): + iwp_pe = risk_days(copies_per_virion, C0, doubling_time, volume_transfused, + k, pool_size, lod50, lod95_lod50_ratio, retests) + rr_pe = incidence * (iwp_pe / 365.25) * per + if n_bs > 0: + np.random.seed(seed) + doubling_time_draws = stats.truncnorm.rvs(0, np.inf, doubling_time, + doubling_time_norm_sd, n_bs) + volume_transfused_draws = np.random.uniform(volume_transfused_range[0], + volume_transfused_range[1], + n_bs) + k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs) + lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs) + incidence_draws = stats.truncnorm.rvs(0, np.inf, incidence, + incidence_norm_sd, n_bs) + iwp = [] + rr = [] + for i in range(n_bs): + #prog = i/n_bs*100 + #print('Computing RR [%d%%]\r'%prog, end="") + iwp.append(risk_days(copies_per_virion, C0, doubling_time_draws[i], + volume_transfused_draws[i], k_draws[i], + pool_size, lod50_draws[i], lod95_lod50_ratio, + retests)) + rr.append(incidence_draws[i] * iwp[i] / 365.25 * per) + iwp_ci = np.quantile(iwp, (0.025,0.975)) + rr_ci = np.quantile(rr, (0.025,0.975)) + rr_se = np.std(rr) + return (iwp_pe, iwp_ci, rr_pe, rr_ci, rr_se) + else: + return (iwp_pe, rr_pe) + +def iwp_bs_par(k, + k_gamma_shape, + k_gamma_scale, + doubling_time, + doubling_time_norm_sd, + lod50, + lod50_sd, + lod95_lod50_ratio, + volume_transfused, + volume_transfused_range, + pool_size, + retests, + C0 = 0.00025, + copies_per_virion = 2, + alpha = 0.05, + n_bs = 10000, + seed = 126887 + ): + + iwp_pe = risk_days(copies_per_virion, + C0, + doubling_time, + volume_transfused, + k, + pool_size, + lod50, + lod95_lod50_ratio, + retests) + np.random.seed(seed) + doubling_time_draws = stats.truncnorm.rvs(0, + np.inf, + doubling_time, + doubling_time_norm_sd, + n_bs) + k_draws = np.random.gamma(k_gamma_shape, k_gamma_scale, n_bs) + lod50_draws = stats.truncnorm.rvs(0, np.inf, lod50, lod50_sd, n_bs) + volume_transfused_draws = np.random.uniform(volume_transfused_range[0], + volume_transfused_range[1], + n_bs) + p = mp.Pool() + result = [p.apply_async(risk_days, + args=(copies_per_virion, + C0, + doubling_time_draws[i], + volume_transfused_draws[i], + k_draws[i], + pool_size, + lod50_draws[i], + lod95_lod50_ratio, + retests) + ) for i in range(n_bs)] + iwp = [r.get() for r in result] + p.close() + p.join() + iwp_ci = np.quantile(iwp, (alpha/2, 1 - alpha/2)) + return (iwp_pe, iwp_ci, iwp) + +def count_cores(): + return mp.cpu_count() + +if __name__ == '__main__': + pass