This notebook illustrates an example present in the Simpact Cyan documentation. There, it is explained that upon infection with HIV the survival time is calculated as $$ t_{\rm survival} = \frac{C}{V_{\rm sp}^{-k}} $$ Because of the start of antiretroviral treatment, or because of dropping out of treatment, the set-point viral load $V_{\rm sp}$ of a person can go down or up again, and the simulations below show what happens to the AIDS based time of death.
This is a very artificial example, meant to illustrate the reasoning in the reference documentation
In [1]:
# First, we'll load the Python interface to Simpact Cyan, as well as the 'math' library
import pysimpactcyan
import math
In [2]:
# Create an instance of the PySimpactCyan class, with which we can run Simpact Cyan simulations
simpact = pysimpactcyan.PySimpactCyan()
In the example from the documentation, survival times of 10 or 50 years are used, depending on treatment. The function below calculates which viral load corresponds to this for a fixed value of $C$ and $k$: $$V_{\rm sp} = \left(\frac{C}{t}\right)^\left(-\frac{1}{k}\right) $$
In [3]:
def solveForVsp(t, C, k):
return (float(C)/t)**(-1.0/k)
We then set some values for $C$ and $k$, set the time to live before treatment to 10 years, the time to live because of treatment to 50 years, and we calculate the corresponding $V_{\rm sp}$ values
In [4]:
t_before = 10.0
t_after = 50.0
C = 1000
k = -0.5
Vsp_before = solveForVsp(t_before, C, k)
Vsp_after = solveForVsp(t_after, C, k);
In [5]:
cfg = {
# To focus on the AIDS mortality event we'll just use a population that consists
# of one man
"population.nummen": 1,
"population.numwomen": 0,
# By default, at the start of the simulation a number of people will be infected
# with HIV. We set the fraction to 100%, so that the only member of our population
# will certainly get infected when the simulation starts.
"hivseed.fraction": 1,
# By setting the age scale for the normal (non-AIDS) mortality event to something
# very large and by setting the simulation time to something large as well, we can
# be sure that the simulation will only stop when the one person in it dies from
# AIDS
"mortality.normal.weibull.scale": 1000,
"population.simtime": 1000,
# Here, we set the values of the C and k parameters that we defined earlier
"mortality.aids.survtime.C": C,
"mortality.aids.survtime.k": k,
# To make sure that upon infection the person gets the value of Vsp that we want,
# we use the 'usealternativeseeddist' setting which can be used to specify a distribution
# for Vsp that can is used when seeding. This distribution should provide the Vsp value
# on a log10 scale. Since we want one specific value, we'll use the 'fixed' distribution.
"person.vsp.model.logdist2d.usealternativeseeddist": "yes",
"person.vsp.model.logdist2d.alternativeseed.dist.type": "fixed",
"person.vsp.model.logdist2d.alternativeseed.dist.fixed.value": math.log10(Vsp_before),
# Because we don't want treatment in this example, we could in principle just give
# the diagnosis event a very low hazard. But to make it easier for the following
# examples we'll actually use a very high hazard for diagnosis so it will happen
# very shortly after infection
"diagnosis.baseline": 100,
# To make sure that no treatment is performed, we'll set the threshold for treatment
# to zero
"monitoring.cd4.threshold": 0,
# On the other hand, thinking ahead again, when a person does get offered treatment
# we'd like to make sure that he accepts it. This is done by setting the ART
# accept threshold to 100%, using a 'fixed' distribution again.
"person.art.accept.threshold.dist.type": "fixed",
"person.art.accept.threshold.dist.fixed.value": 1,
# Here we set the interval for the monitoring event to one year.
"monitoring.interval.piecewise.left": 1,
"monitoring.interval.piecewise.right": 1,
"monitoring.interval.piecewise.cd4s": 500,
"monitoring.interval.piecewise.times": 1,
# When a monitoring event is triggered and the person's CD4 count is below the
# threshold, he will be offered treatment. We've already made sure that the person
# will accept the treatment, and here we specify that treatment should alter the
# Vsp value to Vsp_after. This is not actually used in this first example, but
# will be in the next two.
"monitoring.fraction.log_viralload": math.log10(Vsp_after)/math.log10(Vsp_before),
}
In [7]:
# Now we'll execute the Simpact Cyan simulation with these settings. The `run` function returns
# an object which contains paths to the output files.
r = simpact.run(cfg, "/tmp/simptest")
r
Out[7]:
In [8]:
# We'll display the log of all events which is stored in the file specified by `logevents`.
print(open(r["logevents"]).read())
Each line starts with the time an event took place, followed by the name of the event and some additional information. An overview:
In the second example, we'll make sure the person is treated after one year. To do so, we make use of the simulation intervention, by which we can change parameters of the previous simulation at certain times.
In the previous simulation, no treatment occurred because the CD4 threshold was set to zero. To make sure that the person will get treated during the monitoring event that occurs after the first simulation year has passed, we'll trigger a simulation intervention just before that time and set the CD4 threshold to a very high value (so the person's CD4 will be below that value)
In [9]:
intCfg = {
# This change in configuration will take place one year into the simulation
"time": 0.99,
# At that time the CD4 threshold is set to a very large value, so that during
# the next monitoring event the person will receive treatment
"monitoring.cd4.threshold": 100000,
# We're not interested in any more monitoring events, so we'll set the interval
# to 1000 years
"monitoring.interval.piecewise.left": 1000,
"monitoring.interval.piecewise.right": 1000,
"monitoring.interval.piecewise.times": 1000,
# In this example we do not want the person to drop out of treatment, so the
# dropout interval is set to the fixed value of 1000 years
"dropout.interval.dist.type": "fixed",
"dropout.interval.dist.fixed.value": 1000,
}
# Then we run the simulation with the existing configuration and with the intervention
# configuration above
r = simpact.run(cfg, "/tmp/simptest", interventionConfig=[intCfg])
In [10]:
# Let's show the event log again
print open(r["logevents"]).read()
When the monitoring event is triggered at the simulation time of one year, the CD4 count is now below the (very high) threshold that we installed in the simulation intervention that happened right before. This causes the man to receive treatment, which in turn lowers his Vsp value.
As you can see, because of this the man now continues to live for 45 more years. Also note that again one year and three months before dying, the AIDS stage event is triggered, and six months before dying, the final AIDS stage.
In [11]:
intCfg = {
# This change in configuration will take place one year into the simulation
"time": 0.99,
# At that time the CD4 threshold is set to a very large value, so that during
# the next monitoring event the person will receive treatment
"monitoring.cd4.threshold": 100000,
# To make sure that the person drops out of treatment 10 years later, we
# fix this value
"dropout.interval.dist.type": "fixed",
"dropout.interval.dist.fixed.value": 10,
# To prevent a person from being re-diagnoses after dropout, we'll set the
# baselline value for this hazard to a very negative value (causes a very low
# hazard)
"diagnosis.baseline": -100,
# We're not interested in any more monitoring events, so we'll set the interval
# to 1000 years
"monitoring.interval.piecewise.left": 1000,
"monitoring.interval.piecewise.right": 1000,
"monitoring.interval.piecewise.times": 1000,
}
r = simpact.run(cfg, "/tmp/simptest", interventionConfig=[intCfg])
In [12]:
# Let's show the event log again
print open(r["logevents"]).read()
The start of the simulation is the same as before and one year after getting infected, the man receives treatment. But now, ten years after that time, the man decides to drop out of treatment which causes his $V_{\rm sp}$ value to go up again. Instead of living for tens of years afterwards, after dropping out only seven more years remain until the person dies of AIDS.