Variation in survival time after HIV infection

In this example, the person.survtime.logoffset.dist.type configuration setting is used to add some randomness to the survival time after infection by HIV. This survival time is given by

$$ t_{\rm surv} = \frac{C}{V_{\rm sp}^{-k}} \times 10^x $$

By default, the $x$ parameter is zero, causing a very strict relationship between the survival time and the set-point viral load $V_{\rm sp}$. Using the aforementioned configuration option, one can set the value of $x$ on a per-person basis. This allows for variability in the survival time.


In [1]:
# First we'll load the nesessary modules
%matplotlib inline
import pysimpactcyan
import pandas as pd
import matplotlib.pyplot as plt
import math
import numpy as np

In [2]:
# Create an instance of PySimpactCyan, with which we can run simulations
simpact = pysimpactcyan.PySimpactCyan()


Setting data directory to /usr/local/share/simpact-cyan/

In [3]:
# We'll run a simulation with 1000 men and 1000 women. To make the relation
# above easy to see, we're going to disable treatment by setting the acceptance
# threshold to zero
cfg = { }
cfg["population.simtime"] = 100
cfg["population.nummen"] = 1000
cfg["population.numwomen"] = 1000
cfg["person.art.accept.threshold.dist.type"] = "fixed"
cfg["person.art.accept.threshold.dist.fixed.value"] = 0 # Make sure a person never accepts treatment
r = simpact.run(cfg, "/tmp/simptest")


Using identifier 'simpact-cyan-2015-08-25-09-15-57_13290_SSRY4y3k-'
Results will be stored in directory '/tmp/simptest'
Running simpact executable...
Done.

# read seed from /dev/urandom
# Using seed 525772461
# Performing extra check on read configuration parameters
# WARNING: ignoring consistency check for config key population.agedistfile (config value is '/usr/local/share/simpact-cyan/sa_2003.csv')
# mNRM: using advanced algorithm
# Release version
# Simpact version is: 0.19.0testing3
# Number of events executed is 109022
# Started with 2000 people, ending with 889 (difference is -1111)

In [4]:
# Get a value for 'infinity'
inf = float("inf")

# This is the line with t_surv = C/Vsp^(-k), on a log-log plot
C = 1325.0
k = -0.49
logVL = np.linspace(2, 6, 2)
logTS = np.log10(C) + k*logVL

In [5]:
# Read the person log from the simulation output
persons = pd.read_csv(r["logpersons"])

# We're only interested in people that got infected by transmission, not by
# the HIV seeding event (InfectType == 1), in persons who actually have died
# (TOD < inf) and who did not receive treatment (TreatTime == inf, which is
# actually always the case since no person will accept treatment)
filteredPersons = persons[(persons["InfectType"] == 1) & 
                          (persons["TOD"].astype(float) < inf) & 
                          (persons["TreatTime"].astype(float) == inf)]

# The survival time is the difference between the time of death and the time
# infection took place. We're going to take the logarithm of this.
survTime = np.log10(filteredPersons["TOD"].astype(float) - filteredPersons["InfectTime"].astype(float))
# We're going to plot this logarithm of the survival time against the logarithm
# of the set-point viral load
SPVL = filteredPersons["log10SPVL"].astype(float)

plt.plot(SPVL, survTime, 'o')
plt.plot(logVL, logTS); # The green reference line


Out[5]:
[<matplotlib.lines.Line2D at 0x7fd35f773290>]

In [6]:
# In the plot above, you can see that there are several points below the reference line.
# This is because we didn't specify that we're only interested in people who actually died
# by AIDS related causes: each person also has a regular mortality event scheduled, so it's
# possible that a person dies sooner than from AIDS

In [7]:
# Here, we'll repeat the procedure from above, but we're also going to specify that
# we only want to plot the survival time for people who died from AIDS (AIDSDeath == 1)
filteredPersons = persons[(persons["InfectType"] == 1) & 
                          (persons["TOD"].astype(float) < inf) &  
                          (persons["TreatTime"].astype(float) == inf) &
                          (persons["AIDSDeath"] == 1)
                          ]

survTime = np.log10(filteredPersons["TOD"].astype(float) - filteredPersons["InfectTime"].astype(float))
SPVL = filteredPersons["log10SPVL"].astype(float)

plt.plot(SPVL, survTime, 'o')
plt.plot(logVL, logTS) # The green reference line


Out[7]:
[<matplotlib.lines.Line2D at 0x7fd35f417e90>]

In [8]:
# In the plot above, all survival times lie precisely on the curve that was used to
# generate them, as expected.

In [9]:
# In the following simulation, we're going to specify that for a specific person
# the 'x' parameter in the formula at the top should be picked from a normal
# distribution with a width of 0.1. 
cfg = { }
cfg["population.simtime"] = 100
cfg["population.nummen"] = 1000
cfg["population.numwomen"] = 1000
cfg["person.survtime.logoffset.dist.type"] = "normal"
cfg["person.survtime.logoffset.dist.normal.mu"] = 0
cfg["person.survtime.logoffset.dist.normal.sigma"] = 0.1
cfg["person.art.accept.threshold.dist.type"] = "fixed"
cfg["person.art.accept.threshold.dist.fixed.value"] = 0 # Make sure a person never accepts treatment
r = simpact.run(cfg, "/tmp/simptest")


Using identifier 'simpact-cyan-2015-08-25-09-16-58_13290_CxUIxfvE-'
Results will be stored in directory '/tmp/simptest'
Running simpact executable...
Done.

# read seed from /dev/urandom
# Using seed 236962080
# Performing extra check on read configuration parameters
# WARNING: ignoring consistency check for config key population.agedistfile (config value is '/usr/local/share/simpact-cyan/sa_2003.csv')
# mNRM: using advanced algorithm
# Release version
# Simpact version is: 0.19.0testing3
# Number of events executed is 107569
# Started with 2000 people, ending with 893 (difference is -1107)

In [10]:
# If we now create the same plot as before, the survival times will no
# longer lie precisely on a line (in the log-log plot), but will show
# some variation

persons = pd.read_csv(r["logpersons"])
filteredPersons = persons[(persons["InfectType"] == 1) & 
                          (persons["TOD"].astype(float) < inf) & 
                          (persons["TreatTime"].astype(float) == inf) &
                          (persons["AIDSDeath"] == 1)
                          ]

survTime = np.log10(filteredPersons["TOD"].astype(float) - filteredPersons["InfectTime"].astype(float))
SPVL = filteredPersons["log10SPVL"].astype(float)

plt.plot(SPVL, survTime, 'o')
plt.plot(logVL, logTS); # The green reference line


Out[10]:
[<matplotlib.lines.Line2D at 0x7fd35f4a4990>]

In [ ]: