API reference
Documentation is generated from the stisim package using mkdocstrings.
Main entry point
Bases: Sim
A subclass of starsim.Sim that is specifically designed for STI simulations. It initializes with a structured sexual network and includes STI-specific analyzers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
dict
|
Parameters for the simulation |
None
|
label
|
str
|
A label for the simulation. |
None
|
people
|
People
|
People object containing the agents in the simulation. |
None
|
demographics
|
(Demographics, list)
|
Demographic modules to include. |
None
|
diseases
|
(Disease, list)
|
Disease modules to include. |
None
|
networks
|
(Network, list)
|
Network modules to include. |
None
|
interventions
|
(Intervention, list)
|
Intervention modules to include. |
None
|
analyzers
|
(Analyzer, list)
|
Analyzer modules to include. |
None
|
connectors
|
bool or list
|
If True, use default connectors; otherwise, provide a list of connectors. |
None
|
copy_inputs
|
bool
|
Whether to copy input parameters or not. |
required |
data
|
Additional data to be used in the simulation. |
None
|
|
e.g.
|
|
required | |
Example usage
|
|
required | |
# demographics, and connectors. If you want to specify parameters for the diseases, you can do so like this
|
|
required | |
You can also pass in custom parameters for the default modules, such as networks or demographics, like this
|
|
required | |
These are all in addition to the standard starsim input style using module instances directly, e.g.
|
|
required | |
and in the kwargs), the order of precedence is as follows
|
|
required |
stisim.Sim.case_insensitive_getattr(searchspace, attrname)
Find a class in the given package that matches the name, ignoring case.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
searchspace
|
list
|
A list of classes or modules to search through. |
required |
attrname
|
str
|
The name of the attribute to find, case-insensitive. |
required |
stisim.Sim.init(force=False, **kwargs)
Perform all initializations for the sim
stisim.Sim.plot(key=None, **kwargs)
Plot sim results. If key is the name of a disease in the sim (e.g. 'hiv'), shows a curated panel for that disease. Otherwise falls back to the standard starsim plot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str / list
|
Result key(s) to plot, or a disease name for curated plots |
None
|
**kwargs
|
Passed to ss.Sim.plot() |
{}
|
Returns:
| Type | Description |
|---|---|
|
matplotlib.figure.Figure |
stisim.Sim.process_connectors()
Get the default connectors for the diseases in the simulation.
Connectors are loaded based on the disease names or modules provided in the format
stisim.Sim.process_demographics()
Process the location to create people and demographics if not provided.
stisim.Sim.process_networks()
Process the network parameters to create network module. If networks are provided, they will be used; otherwise, use default networks (usual case)
stisim.Sim.process_stis()
Look up a disease by its name and return the corresponding module.
stisim.Sim.remap_pars(pars)
staticmethod
Remap any parameter names to match the expected format for STIs and networks. This is useful for ensuring that parameters are correctly interpreted by the modules.
stisim.Sim.separate_pars(pars=None, sim_pars=None, sti_pars=None, nw_pars=None, dem_pars=None, sim_kwargs=None, **kwargs)
Create a nested dict of parameters that get passed to Sim constructor and the component modules Prioritization: - If any key appears in both pars and _pars, the value from _pars will be used. - If any key appears in both pars and kwargs, the value from kwargs will be used.
Networks
Bases: SexualNetwork
Structured sexual network
stisim.networks.StructuredSexual.count_partners()
Count the number of partners each person has had over the past 3/12 months
stisim.networks.StructuredSexual.match_pairs()
Match pairs by age, using sorting rather than the linear sum assignment
stisim.networks.StructuredSexual.match_sex_workers()
Match sex workers to clients
stisim.networks.StructuredSexual.set_concurrency(upper_age=None)
Assign each person a preferred number of simultaneous partners
stisim.networks.StructuredSexual.set_condom_use()
Set condom use
stisim.networks.StructuredSexual.set_risk_groups(upper_age=None)
Assign each person to a risk group
Bases: DynamicNetwork
Lightweight network for storing prior partners, for use in partner notification In this network, 'dur' refers to the duration of time since the relationship ended
Bases: StructuredSexual
stisim.networks.AgeMatchedMSM.match_pairs()
Match males by age using sorting
Calibration
Bases: Calibration
Customized STIsim calibration class.
Inherits all the functionality of the Starsim calibration class, but adds:
- A default build function that routes parameters using dot notation
(e.g.
'hiv.beta_m2f') - A default evaluation function that uses the data provided in the constructor
- :meth:
get_parsfor extracting calibrated parameter sets
If no build_fn is provided, uses :func:default_build_fn which looks
up modules via sim.get_module() and sets their parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
The simulation to calibrate |
required |
calib_pars
|
dict
|
Parameters to calibrate using dot notation, e.g.
|
required |
data
|
DataFrame
|
Calibration targets with 'time' column + result columns |
None
|
weights
|
dict
|
Optional weight multipliers per result |
None
|
extra_results
|
list
|
Additional results to track beyond data columns |
None
|
save_results
|
bool
|
Save sim results for each trial |
False
|
Examples::
sim = make_sim()
data = pd.read_csv('calibration_data.csv')
calib_pars = {
'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05),
'structuredsexual.prop_f0': dict(low=0.5, high=0.9, guess=0.8),
}
calib = sti.Calibration(sim=sim, calib_pars=calib_pars, data=data, total_trials=100)
calib.calibrate()
# Extract best parameters and run multi-sim
par_sets = calib.get_pars(n=200)
msim = sti.make_calib_sims(calib=calib, n_parsets=200)
stisim.calibration.Calibration.calibrate(calib_pars=None, **kwargs)
Perform calibration with crash-recovery support.
If continue_db=True and the database already has completed trials, only the remaining trials will be run. This allows recovery from crashes by simply re-running the same command.
stisim.calibration.Calibration.get_pars(n=None)
Extract top-N calibrated parameter sets as a list of flat dicts.
Each dict maps 'module.par' keys to scalar values (metadata columns
like index, mismatch, and rand_seed are stripped). The
returned dicts can be passed directly to :func:set_sim_pars or
:func:make_calib_sims.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of top parameter sets. |
None
|
Returns:
| Type | Description |
|---|---|
|
list[dict]: Parameter sets sorted by mismatch (best first). |
stisim.calibration.Calibration.load_results(study)
Load the results from the tmp files, tracking which loaded successfully
stisim.calibration.Calibration.parse_study(study)
Parse the study into a data frame -- called automatically
stisim.calibration.Calibration.run_trial(trial)
Define the objective for Optuna
stisim.calibration.Calibration.save(filename, shrink=True, n_results=None, save_pars=True, pars_filename=None)
Save calibration results.
Optionally shrinks to the top n_results before saving (default: keep top 10% of completed trials). Also saves the parameter DataFrame as a separate file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str / Path
|
Path for the saved calibration object. |
required |
shrink
|
bool
|
If True (default), shrink before saving. The full
(unshrunk) object is saved with a |
True
|
n_results
|
int
|
Number of top results to keep when shrinking.
Default: |
None
|
save_pars
|
bool
|
If True (default), also save |
True
|
pars_filename
|
str / Path
|
Path for the parameter DataFrame. If
None, uses |
None
|
Returns:
| Type | Description |
|---|---|
|
The (possibly shrunk) calibration object. |
stisim.calibration.Calibration.shrink(n_results=100, make_df=True)
Shrink the results to only the best fit
stisim.calibration.Calibration.worker()
Run a single worker, catching exceptions so one crash doesn't kill all workers
Package contents
stisim.Calibration(sim, calib_pars, data=None, weights=None, extra_results=None, save_results=False, check_fn=None, **kwargs)
Bases: Calibration
Customized STIsim calibration class.
Inherits all the functionality of the Starsim calibration class, but adds:
- A default build function that routes parameters using dot notation
(e.g.
'hiv.beta_m2f') - A default evaluation function that uses the data provided in the constructor
- :meth:
get_parsfor extracting calibrated parameter sets
If no build_fn is provided, uses :func:default_build_fn which looks
up modules via sim.get_module() and sets their parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
The simulation to calibrate |
required |
calib_pars
|
dict
|
Parameters to calibrate using dot notation, e.g.
|
required |
data
|
DataFrame
|
Calibration targets with 'time' column + result columns |
None
|
weights
|
dict
|
Optional weight multipliers per result |
None
|
extra_results
|
list
|
Additional results to track beyond data columns |
None
|
save_results
|
bool
|
Save sim results for each trial |
False
|
Examples::
sim = make_sim()
data = pd.read_csv('calibration_data.csv')
calib_pars = {
'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05),
'structuredsexual.prop_f0': dict(low=0.5, high=0.9, guess=0.8),
}
calib = sti.Calibration(sim=sim, calib_pars=calib_pars, data=data, total_trials=100)
calib.calibrate()
# Extract best parameters and run multi-sim
par_sets = calib.get_pars(n=200)
msim = sti.make_calib_sims(calib=calib, n_parsets=200)
stisim.Calibration.worker()
Run a single worker, catching exceptions so one crash doesn't kill all workers
stisim.Calibration.calibrate(calib_pars=None, **kwargs)
Perform calibration with crash-recovery support.
If continue_db=True and the database already has completed trials, only the remaining trials will be run. This allows recovery from crashes by simply re-running the same command.
stisim.Calibration.run_trial(trial)
Define the objective for Optuna
stisim.Calibration.parse_study(study)
Parse the study into a data frame -- called automatically
stisim.Calibration.load_results(study)
Load the results from the tmp files, tracking which loaded successfully
stisim.Calibration.get_pars(n=None)
Extract top-N calibrated parameter sets as a list of flat dicts.
Each dict maps 'module.par' keys to scalar values (metadata columns
like index, mismatch, and rand_seed are stripped). The
returned dicts can be passed directly to :func:set_sim_pars or
:func:make_calib_sims.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of top parameter sets. |
None
|
Returns:
| Type | Description |
|---|---|
|
list[dict]: Parameter sets sorted by mismatch (best first). |
stisim.Calibration.save(filename, shrink=True, n_results=None, save_pars=True, pars_filename=None)
Save calibration results.
Optionally shrinks to the top n_results before saving (default: keep top 10% of completed trials). Also saves the parameter DataFrame as a separate file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str / Path
|
Path for the saved calibration object. |
required |
shrink
|
bool
|
If True (default), shrink before saving. The full
(unshrunk) object is saved with a |
True
|
n_results
|
int
|
Number of top results to keep when shrinking.
Default: |
None
|
save_pars
|
bool
|
If True (default), also save |
True
|
pars_filename
|
str / Path
|
Path for the parameter DataFrame. If
None, uses |
None
|
Returns:
| Type | Description |
|---|---|
|
The (possibly shrunk) calibration object. |
stisim.Calibration.shrink(n_results=100, make_df=True)
Shrink the results to only the best fit
stisim.CareSeeking(pars=None, **kwargs)
Bases: Module
Cross-disease care-seeking propensity for each individual.
Each agent gets a baseline propensity drawn from a distribution at birth. Men have lower propensity by default (controlled by rel_care_m2f). The propensity may be temporarily modified by factors like pregnancy.
stisim.CareSeeking.set_care_seeking_states(upper_age=None)
Set baseline care-seeking propensity for each agent. Called at init (upper_age=None for all agents) and each step (upper_age=dt to initialize newborns).
stisim.CareSeeking.step()
Initialize propensity for newborns, then reset all propensities to baseline before applying temporary modifiers.
stisim.BaseSTI(name=None, pars=None, init_prev_data=None, **kwargs)
Bases: Infection
Base class for sexually transmitted infections. Modifies make_new_cases to account for barrier protection.
stisim.BaseSTI.treatable
property
Assume infected people are treatable, can be overwritten in subclasses
stisim.BaseSTI.make_init_prev(uids=None, data=None, active=True)
Initialize prevalence by sex and risk group
stisim.BaseSTI.agehist(a)
Return an age histogram
stisim.BaseSTI.init_results()
Initialize results
stisim.BaseSTI.infect()
Determine who gets infected on this timestep via transmission on the network
stisim.SEIS(pars=None, name=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.SEIS.treatable
property
Active bacterial presence -- includes exposed and infected, and responds to treatment
stisim.SEIS.init_results()
Initialize results
stisim.SEIS.step_state()
Updates for this timestep
stisim.SEIS.wipe_dates(uids)
Clear all previous dates
stisim.SEIS.set_prognoses(uids, sources=None)
Set initial prognoses for adults newly infected
stisim.ChlamydiaBL(pars=None, **kwargs)
Bases: Chlamydia
stisim.ChlamydiaBL.update_pre()
Updates prior to interventions
stisim.ChlamydiaBL.set_ct_load(uids)
Bacterial load dynamics
stisim.ChlamydiaBL.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.SimpleBV(pars=None, name='bv', **kwargs)
Bases: Disease
stisim.SimpleBV.treatable
property
Responds to treatment
stisim.SimpleBV.init_results()
Initialize results
stisim.SimpleBV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.SimpleBV.init_post()
Initialize with sim properties
stisim.SimpleBV.spontaneous(uids)
Create new cases via spontaneous occurrence
stisim.SimpleBV.step_state()
Updates for this timestep
stisim.SimpleBV.wipe_dates(uids)
Clear all previous dates
stisim.SimpleBV.set_duration(symp, asymp)
Set duration of infection
stisim.SimpleBV.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.BV(pars=None, name='bv', **kwargs)
Bases: BaseSTI
stisim.BV.init_results()
Initialize results
stisim.BV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.BV.set_circumcision(upper_age=None)
Set circumcision status
stisim.BV.compute_circumcision_impact(spontaneous=True)
Compute the relative impact of circumcision on susceptibility for women. This is used for spontaneous occurence only. If sexual transmission in model, then we adjust man's susceptibility.
stisim.BV.init_post()
Initialize with sim properties
stisim.BV.spontaneous(uids, cst='cst1')
Determine the probability of transitioning to worse CST states for agents in CST 1, we determine probability of transitioning to CST 3 (assuming no transition directly to CST 4) for agents in CST 3, we determine probability of transitioning to CST 4 agents in CST 4 have no further transitions
stisim.BV.sexual_transmission()
Determine who gets infected on this timestep via transmission on the network
stisim.BV.clear_infection(uids)
Clear infection
stisim.BV.step_state()
Updates for this timestep
stisim.BV.wipe_dates(uids)
Clear all previous dates
stisim.BV.set_male_prognoses(uids)
Set initial prognoses for newly infected males
stisim.BV.set_prognoses(uids, new_cst=3)
Set initial prognoses for newly infected females
stisim.Placeholder(pars=None, name=None, **kwargs)
Bases: Disease
stisim.Placeholder.step()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.GUD(pars=None, init_prev_data=None, **kwargs)
Bases: Infection
stisim.GUD.step_state()
Update states
stisim.GUD.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected with syphilis
stisim.HIV(pars=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.HIV.init_results()
Initialize results
stisim.HIV.init_post()
Set states
stisim.HIV.acute_decline(uids)
Acute decline in CD4
stisim.HIV.falling_decline(uids)
Decline in CD4 during late-stage infection, when counts are falling
stisim.HIV.post_art_decline(uids)
Decline in CD4 after going off treatment This implementation has the possibly-undesirable feature that a person who goes on ART for a year and then off again might have a slightly shorter lifespan than if they'd never started treatment.
stisim.HIV.cd4_increase(uids)
Increase CD4 counts for people who are receiving treatment. Growth curves are calculated to match EMODs CD4 reconstitution equation for people who initiate treatment with a CD4 count of 50 (https://docs.idmod.org/projects/emod-hiv/en/latest/hiv-model-healthcare-systems.html) However, here we use a logistic growth function and assume that ART CD4 count depends on CD4 at initiation. Sources:
- https://i-base.info/guides/starting/cd4-increase
- https://www.sciencedirect.com/science/article/pii/S1876034117302022
- https://bmcinfectdis.biomedcentral.com/articles/10.1186/1471-2334-8-20
stisim.HIV.init_cd4()
Set CD4 counts
stisim.HIV.init_care_seeking()
Set care seeking behavior
stisim.HIV.step_state()
Carry out autonomous updates at the start of the timestep (prior to transmission)
stisim.HIV.step_die(uids)
Clear all states for dead agents
stisim.HIV.update_transmission()
Update rel_trans and rel_sus for all agents. These are reset on each timestep then adjusted depending on states. Adjustments are made throughout different modules:
- rel_trans for acute and late-stage untreated infection are adjusted below
- rel_trans for all people on treatment (including pregnant women) below
- rel_sus for unborn babies of pregnant WLHIV receiving treatment is adjusted in the ART intervention
stisim.HIV.update_results()
Update results at each time step
stisim.HIV.set_prognoses(uids, sources=None, ti=None)
Set prognoses upon infection
stisim.HIV.start_art(uids)
Check who is ready to start ART treatment and put them on ART
stisim.HIV.stop_art(uids=None)
Check who is stopping ART treatment and put them off ART
stisim.SyphilisPlaceholder(pars=None, **kwargs)
Bases: Disease
stisim.SyphilisPlaceholder.step_state()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.Syphilis(pars=None, name='syph', init_prev_data=None, init_prev_latent_data=None, **kwargs)
Bases: BaseSTI
stisim.Syphilis.naive
property
Never exposed
stisim.Syphilis.sus_not_naive
property
Susceptible but with syphilis antibodies, which persist after treatment
stisim.Syphilis.mat_active
property
Definition of infection used for maternal transmission, includes exposed + primary + secondary stages
stisim.Syphilis.active
property
Active infection includes primary and secondary stages
stisim.Syphilis.infectious
property
Infectious
stisim.Syphilis.ulcerative
property
Has a visible genital ulcer (chancre at a visible site during primary stage)
stisim.Syphilis.symptomatic
property
Has noticeable symptoms: visible ulcer or visible rash
stisim.Syphilis.infect()
Override to use rel_trans=1 for maternal transmission. Stage-specific rel_trans (primary >> latent) only applies to sexual transmission. For MTC, all infected stages transmit equally since spirochetemia during pregnancy affects the fetus regardless of the mother's clinical stage.
stisim.Syphilis.init_post()
Make initial cases
stisim.Syphilis.init_results()
Initialize results
stisim.Syphilis.step_state()
Updates to states
stisim.Syphilis.step_die(uids)
Clear all states and dates for dead agents (including NND/stillborn babies)
stisim.Syphilis.set_prognoses(uids, source_uids=None, ti=None)
Set initial prognoses for adults newly infected with syphilis. Note: congenital infections are routed to set_congenital by starsim's set_outcomes(), so only adult infections reach this method.
stisim.Syphilis.set_secondary_prognoses(uids)
Set prognoses for people who have just progressed to secondary infection
stisim.Syphilis.set_congenital(target_uids, source_uids=None)
Natural history of syphilis for congenital infection. Birth outcomes depend on the mother's disease stage: mat_active (exposed|primary|secondary), early latent, late latent.
stisim.Trichomoniasis(pars=None, name='tv', init_prev_data=None, **kwargs)
Bases: SEIS
stisim.Trichomoniasis.set_duration(p, symp, asymp, pid)
Overwrite duration setting with persistence for female asymptomatic infection
stisim.Migration(pars=None, migration_data=None, **kwargs)
Bases: Demographics
Remove / add migrants Assumes a datafile with the number of migrants each year
stisim.Migration.init_migration_propensity()
Set individual's propensity to migrate This is currently a random variable but could be defined as a function of age/sex/other properties
stisim.Migration.get_migrants()
Get the number of migrants for this timestep
stisim.Migration.make_immigrants(twin_uids)
Make immigrants by making copies of existing agents
stisim.Migration.step()
Perform all updates
stisim.Migration.step_migration()
Select people to migrate
stisim.Migration.remove_emigrants()
Remove people who've decided to emigrate this timestep
stisim.STIDx(df, disease, *args, **kwargs)
Bases: Product
Generic class for diagnostics with a positive/negative outcome Uses bernoulli sampling, so can only be used for tests with binary outcomes Results vary depending on agents' true underlying health state
stisim.STIDx.administer(sim, uids)
Administer a testing product.
stisim.STITest(pars=None, test_prob_data=None, years=None, start=None, stop=None, eligibility=None, product=None, name=None, label=None, **kwargs)
Bases: Intervention
Base class for STI testing.
Controls who gets tested, how often, and with what diagnostic product.
Each timestep, eligible agents are tested with a probability derived from
test_prob_data. By default (dt_scale=True), test_prob_data is interpreted
as an annual testing probability and converted to a per-timestep
probability via ss.probperyear. This correctly recovers the annual
probability over a full year of timesteps (e.g. test_prob_data=0.24 with
monthly dt gives ~2.26% per month, recovering exactly 24% per year).
If you need to specify a per-timestep probability directly (not an annual probability), set dt_scale=False: - test_prob_data=0.5, dt_scale=False → 50% chance per timestep
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
diagnostic product (e.g. STIDx, HIVDx) that determines test outcomes (sensitivity, specificity). If None, subclasses supply a default (e.g. HIVTest uses a perfect HIVDx). For STITest, a product is required. |
None
|
|
test_prob_data
|
annual testing probability (if dt_scale=True, the default)
or per-timestep probability (if dt_scale=False). Accepts a
scalar (constant probability), an array (one value per
entry in |
None
|
|
years
|
array
|
calendar years corresponding to entries in test_prob_data when test_prob_data is an array. Mutually exclusive with start. |
None
|
start
|
float
|
calendar year when the intervention activates (inclusive). Defaults to the first simulation year. |
None
|
stop
|
float
|
calendar year when the intervention deactivates (inclusive). Defaults to the last simulation year. |
None
|
eligibility
|
function |
None
|
|
rel_test
|
relative testing probability multiplier (default 1.0) |
required | |
dt_scale
|
if True (default), interpret test_prob_data as an annual probability. Set to False to interpret test_prob_data as a per-timestep probability. |
required |
States set on agents
tested (bool): ever tested diagnosed (bool): ever diagnosed positive ti_tested (float): timestep of last test ti_scheduled (float): timestep of next scheduled test ti_positive (float): timestep of last positive result ti_negative (float): timestep of last negative result tests (float): cumulative number of tests received
stisim.STITest.state_list
property
Include products in the state list
stisim.STITest.make_test_prob_fn(sim, uids)
staticmethod
Testing probabilites over time
stisim.STITest.get_testers(sim)
Find who tests by applying eligibility and coverage/uptake
stisim.STITest.step(uids=None)
Apply the testing intervention
stisim.SymptomaticTesting(pars=None, treatments=None, diseases=None, disease_treatment_map=None, negative_treatments=None, treat_prob_data=None, years=None, start=None, stop=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
Base class for symptomatic testing with multiple possible etiologies Unlike other test classes, this doesn't return positive/negative outcomes, since syndromic management doesn't involve reaching a diagnosis. Rather, the testing intervention itself contains a linked treatment intervention.
stisim.SymptomaticTesting.step(uids=None)
Apply syndromic management
stisim.STITreatment(name=None, pars=None, diseases=None, eligibility=None, max_capacity=None, years=None, *args, **kwargs)
Bases: Intervention
Base class for treatment of STI infection. The majority of STI treatments will clear infection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
|
None
|
|
disease
|
str
|
should match the name of one of the diseases in the simulation |
required |
stisim.STITreatment.get_candidates(sim)
Get people who are willing to accept treatment
stisim.STITreatment.set_treat_eff(uids)
Can be changed by derived classes
stisim.STITreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment, keeping track of unnecessarily treated individuals
stisim.STITreatment.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.STITreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.PartnerNotification(eligibility, test, test_prob=0.5, **kwargs)
Bases: Intervention
:param disease: The disease module from which to draw the transmission tree used to find contacts
:param eligible: A function f(sim) that returns the UIDs/BoolArr of people to trace (typically people who just tested positive)
:param test: The testing intervention to use when testing identified contacts
:param test_prob: The probability of a contact being identified and accepting a test
:param kwargs: Other arguments passed to ss.Intervention
stisim.ProductMix(df, excl_cols=None, *args, **kwargs)
Bases: Product
Generic class for algorithms that determine which product a person will receive Uses ss.choice() sampling, which is slower than bernoulli, when there are more than two options The test that agents are given does NOT depend on their underlying health state.
stisim.ProductMix.administer(sim, uids)
Apply a testing algorithm
stisim.treat_BV(*args, pars=None, eligibility=None, **kwargs)
Bases: Intervention
Treat BV
stisim.treat_BV.tx_cst1_change_duration(uids)
Calculate and set the duration of transitioning to a stable CST 1 based on douching and menstrual hygiene practices for individual agents.
stisim.HIVTest(product=None, pars=None, test_prob_data=None, years=None, start=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
HIV-specific testing intervention.
Tests eligible agents for HIV; positive results set hiv.diagnosed=True, which is a prerequisite for ART initiation. By default, only undiagnosed agents are eligible.
The testing → diagnosis → ART pipeline works as follows:
1. HIVTest tests eligible agents each timestep (annual probability, converted via ss.probperyear)
2. Positive results set hiv.diagnosed=True and hiv.ti_diagnosed
3. ART checks for newly diagnosed agents (ti_diagnosed == current ti)
4. Newly diagnosed agents initiate ART with probability art_initiation
5. If coverage data is provided, ART corrects to match targets
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
test_prob_data
|
annual testing probability (if dt_scale=True, the default). A value of 0.1 means ~10% of eligible agents tested per year. To specify a per-timestep probability instead, set dt_scale=False. |
None
|
|
eligibility
|
func
|
who can be tested. Default: undiagnosed agents. |
None
|
start
|
float
|
calendar year when testing begins |
None
|
dt_scale
|
bool
|
if True (default), test_prob_data is an annual probability. Set to False for per-timestep probability. |
required |
Example::
# Test 20% of undiagnosed agents per year starting in 2000
test = sti.HIVTest(test_prob_data=0.2, start=2000, name='hiv_test')
# Test everyone every timestep (per-timestep probability)
test = sti.HIVTest(test_prob_data=1.0, dt_scale=False, name='hiv_test')
# FSW-targeted testing at higher rate
fsw_test = sti.HIVTest(
test_prob_data=0.5,
name='fsw_test',
eligibility=lambda sim: sim.networks.structuredsexual.fsw & ~sim.diseases.hiv.diagnosed,
)
stisim.ART(pars=None, coverage=None, coverage_data=None, **kwargs)
Bases: Intervention
Antiretroviral therapy intervention.
Requires HIVTest (or equivalent) to diagnose agents first — ART only initiates agents who have hiv.diagnosed=True. A warning is raised if no HIVTest is found in the sim.
Processing flow each timestep
- Agents scheduled to stop ART are removed
- Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
- If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
- If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
- Mothers on ART protect unborn infants (rel_sus=0) via MaternalNet
Coverage can be specified in several formats
- None: no coverage target; treat all who initiate (default)
- Scalar (e.g. 0.8): constant proportion of infected on ART
- Dict: {'year': [2000, 2020], 'value': [0, 0.9]} — linearly interpolated
- DataFrame: index=years, column 'n_art' (absolute numbers) or 'p_art' (proportion of infected). Values are linearly interpolated to the sim yearvec.
- Stratified DataFrame: columns Year, Gender/Sex, AgeBin (format '[lo,hi)'), plus a numeric value column. Values are interpolated per stratum.
Intervention ordering: HIVTest must appear before ART in the interventions list so that agents diagnosed this timestep can initiate ART in the same step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None) |
None
|
|
art_initiation
|
probability a newly diagnosed person initiates ART (default: ss.bernoulli(p=0.9)). Set to 1 to treat all diagnosed. |
required |
Example::
# Simple: 80% of infected on ART
art = sti.ART(coverage=0.8)
# Time-varying coverage
art = sti.ART(coverage={'year': [2000, 2010, 2025], 'value': [0, 0.5, 0.9]})
# No coverage target — 90% of newly diagnosed initiate (default art_initiation)
art = sti.ART()
# Treat ALL diagnosed with no coverage constraint
art = sti.ART(art_initiation=1)
# From a CSV file
art = sti.ART(coverage=pd.read_csv('art_coverage.csv').set_index('year'))
stisim.ART.step()
Apply ART at each timestep: stop ART for those scheduled, initiate for newly diagnosed, and correct overall coverage to match targets.
stisim.ART.prioritize_art(sim, n=None, awaiting_art_uids=None)
Prioritize ART to n agents among those awaiting treatment
stisim.ART.art_coverage_correction(sim, target_coverage=None)
Adjust ART coverage to match data
stisim.VMMC(pars=None, coverage=None, coverage_data=None, eligibility=None, **kwargs)
Bases: Intervention
Voluntary medical male circumcision.
Reduces male susceptibility to HIV acquisition by eff_circ (default 60%). Unlike ART, VMMC does not require diagnosis — it circumcises males up to a coverage target, prioritized by willingness (a random per-agent score).
If no coverage is specified, VMMC does nothing. Coverage must be provided explicitly via the coverage parameter.
Coverage formats (same as ART): - Scalar: constant proportion of males (e.g. 0.3) - Dict: {'year': [...], 'value': [...]} — linearly interpolated - DataFrame: index=years, column 'n_vmmc' or 'p_vmmc' - Stratified DataFrame: Year/Gender/AgeBin columns
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None; VMMC does nothing without coverage data) |
None
|
|
eff_circ
|
efficacy (default 0.6 = 60% reduction in HIV acquisition) |
required | |
eligibility
|
optional function to restrict who is eligible (default: all males) |
None
|
Example::
vmmc = sti.VMMC(coverage=0.3)
vmmc = sti.VMMC(coverage={'year': [2010, 2025], 'value': [0, 0.4]})
stisim.Prep(pars=None, eligibility=None, **kwargs)
Bases: Intervention
Pre-exposure prophylaxis (PrEP).
By default targets HIV-negative FSWs who are not already on PrEP. Reduces HIV susceptibility by eff_prep (default 80%). Coverage ramps up over time according to the years/coverage parameters (linearly interpolated). Use the eligibility parameter to target a different population.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
list
|
coverage values at each year (default [0, 0.01, 0.5, 0.8]) |
required |
years
|
list
|
corresponding calendar years (default [2004, 2005, 2015, 2025]) |
required |
eff_prep
|
float
|
efficacy (default 0.8 = 80% reduction in acquisition) |
required |
eligibility
|
function to override default FSW targeting |
None
|
Example::
prep = sti.Prep(coverage=[0, 0.5], years=[2020, 2025])
stisim.GonorrheaTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: STITreatment
Treatment for gonorrhea infection. - successful treatment clears infection immediately - unsuccessful treatment reduces dur_inf and rel_trans, but results in lower rel_treat - unnecessary treatment results in lower rel_treat
stisim.GonorrheaTreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.UpdateDrugs(pars=None, eligibility=None, years=None, *args, **kwargs)
Bases: Intervention
An intervention that samples rel_treat and updates the rel_treat values if they fall below a given level.
stisim.SyphTx(pars=None, max_capacity=None, years=None, eligibility=None, name=None, **kwargs)
Bases: STITreatment
Treat a fixed number of people each timestep.
stisim.SyphTx.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.SyphTx.treat_fetus(sim, mother_uids)
Treat fetuses of successfully treated mothers. Birth outcomes of successfully treated fetuses will be updated. If fetus is not yet infected, the treatment doesn't do anything. Treatment success depends on when in the pregnancy the mother gets treated with reduced treatment efficacy above the cut off age
stisim.SyphTx.step()
Apply treatment
stisim.NewbornTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: SyphTx
stisim.NewbornTreatment.change_states(disease, treat_succ)
Change states of congenital cases
stisim.NewbornTreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment to newborns
stisim.SyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: STITest
Base class for syphilis tests
stisim.SyphTest.process_data(sim)
Turn dataframe into a dictionary
stisim.SyphTest.make_test_prob_fn(sim, uids)
staticmethod
Process symptomatic testing probabilites over time by sex and risk group
stisim.ANCSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to pregnant women Need to adjust timing using Trivedi (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7138526/)
stisim.ANCSyphTest.schedule_tests()
Schedule a test for newly pregnant women
stisim.NewbornSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to newborns if the mother was confirmed to have syphilis at any stage of the pregnancy
stisim.StructuredSexual(pars=None, condom_data=None, name=None, **kwargs)
Bases: SexualNetwork
Structured sexual network
stisim.StructuredSexual.set_risk_groups(upper_age=None)
Assign each person to a risk group
stisim.StructuredSexual.set_concurrency(upper_age=None)
Assign each person a preferred number of simultaneous partners
stisim.StructuredSexual.match_pairs()
Match pairs by age, using sorting rather than the linear sum assignment
stisim.StructuredSexual.match_sex_workers()
Match sex workers to clients
stisim.StructuredSexual.set_condom_use()
Set condom use
stisim.StructuredSexual.count_partners()
Count the number of partners each person has had over the past 3/12 months
stisim.PriorPartners(pars=None, name='priorpartners', **kwargs)
Bases: DynamicNetwork
Lightweight network for storing prior partners, for use in partner notification In this network, 'dur' refers to the duration of time since the relationship ended
stisim.AgeMatchedMSM(pars=None, **kwargs)
Bases: StructuredSexual
stisim.AgeMatchedMSM.match_pairs()
Match males by age using sorting
stisim.AgeApproxMSM(**kwargs)
Bases: StructuredSexual
stisim.AgeApproxMSM.match_pairs(ppl)
Match pairs using age preferences
stisim.TimeSeries(t=None, vals=None, units=None, assumption=None, sigma=None)
Class to store time-series data
Internally values are stored as lists rather than numpy arrays because
insert/remove operations on lists tend to be faster (and working with sparse
data is a key role of TimeSeries objects). Note that methods like :meth:interpolate()
return numpy arrays, so the output types from such functions should generally match up
with what is required by the calling function.
:param t: Optionally specify a scalar, list, or array of time values
:param vals: Optionally specify a scalar, list, or array of values (must be same size as t)
:param units: Optionally specify units (as a string)
:param assumption: Optionally specify a scalar assumption
:param sigma: Optionally specify a scalar uncertainty
stisim.TimeSeries.has_data
property
Check if any data has been provided
:return: True if any data has been entered (assumption or time-specific)
stisim.TimeSeries.has_time_data
property
Check if time-specific data has been provided
Unlike has_data, this will return False if only an assumption has been entered
:return: True if any time-specific data has been entered
stisim.TimeSeries.__eq__(other)
Check TimeSeries equality
Two TimeSeries instances are equal if all of their attributes are equal. This is easy to
implement because == is directly defined for all of the attribute types (lists and scalars)
and due to __slots__ there are guaranteed not to be any other attributes
:param other: :return:
stisim.TimeSeries.copy()
Return a copy of the TimeSeries
:return: An independent copy of the TimeSeries
stisim.TimeSeries.insert(t, v)
Insert a value or list of at a particular time
If the value already exists in the TimeSeries, it will be overwritten/updated.
The arrays are internally sorted by time value, and this order will be maintained.
:param t: Time value to insert or update. If None, the value will be assigned to the assumption
:param v: Value to insert. If None, this function will return immediately without doing anything
stisim.TimeSeries.get(t)
Retrieve value at a particular time
This function will automatically retrieve the value of the assumption if no time specific values have been provided, or if any time specific values are provided, will return the value entered at that time. If time specific values have been entered and the requested time is not explicitly present, an error will be raised.
This function may be deprecated in future because generally it is more useful
to either call TimeSeries.interpolate() if interested in getting values at
arbitrary times, or TimeSeries.get_arrays() if interested in retrieving
values that have been entered.
:param t: A time value. If None, will return assumption regardless of whether
time data has been entered or not
:return: The value at the corresponding time. Returns None if the value no value present
stisim.TimeSeries.get_arrays()
Return arrays with the contents of this TimeSeries
The TimeSeries instance may have time values, or may simply have
an assumption. If obtaining raw arrays is desired, this function will
return arrays with values extracted from the appropriate attribute of the
TimeSeries. However, in general, it is usually .interpolate() that is
desired, rather than .get_arrays()
:return: Tuple with two arrays - the first item is times (with a single NaN if the TimeSeries only has an assumption) and the second item is values
stisim.TimeSeries.remove(t)
Remove single time point
:param t: Time value to remove. Set to None to remove the assumption
stisim.TimeSeries.remove_before(t_remove)
Remove times from start
:param tval: Remove times up to but not including this time
stisim.TimeSeries.remove_after(t_remove)
Remove times from start
:param tval: Remove times up to but not including this time
stisim.TimeSeries.remove_between(t_remove)
Remove a range of times
Note that the endpoints are not included
:param t_remove: two element iterable e.g. array, with [min,max] times
stisim.TimeSeries.interpolate(t2, method='linear', **kwargs)
Return interpolated values
This method returns interpolated values from the time series at time points t2
according to a given interpolation method. There are 4 possibilities for the method
- 'linear' - normal linear interpolation (with constant, zero-gradient extrapolation)
- 'pchip' - legacy interpolation with some curvature between points (with constant, zero-gradient extrapolation)
- 'previous' - stepped interpolation, maintain value until the next timepoint is reached (with constant, zero-gradient extrapolation)
- Interpolation class or generator function
That final option allows the use of arbitrary interpolation methods. The underlying call will be::
c = method(t1, v1, **kwargs)
return c(t2)
so for example, if you wanted to use the base Scipy pchip method with no extrapolation, then could pass in::
TimeSeries.interpolate(...,method=scipy.interpolate.PchipInterpolator)
Note that the following special behaviours apply:
- If there is no data at all, this function will return
np.nanfor all requested time points - If only an assumption exists, this assumption will be returned for all requested time points
-
Otherwise, arrays will be formed with all finite time values
- If no finite time values remain, an error will be raised (in general, a TimeSeries should not store such values anyway)
- If only one finite time value remains, then that value will be returned for all requested time points
- Otherwise, the specified interpolation method will be used
:param t2: float, list, or array, with times :param method: A string 'linear', 'pchip' or 'previous' OR a callable item that returns an Interpolator :return: array the same length as t2, with interpolated values
stisim.TimeSeries.sample(constant=True)
Return a sampled copy of the TimeSeries
This method returns a copy of the TimeSeries in which the values have been perturbed based on the uncertainty value.
:param constant: If True, time series will be perturbed by a single constant offset. If False,
an different perturbation will be applied to each time specific value independently.
:return: A copied TimeSeries with perturbed values
stisim.coinfection_stats(disease1, disease2, disease1_infected_state_name='infected', disease2_infected_state_name='infected', age_limits=None, denom=None, *args, **kwargs)
Bases: result_grouper
Generates stats for the coinfection of two diseases. This is useful for looking at the coinfection of HIV and syphilis, for example.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
disease1
|
str | Disease
|
name of the first disease |
required |
disease2
|
str | Disease
|
name of the second disease |
required |
disease1_infected_state_name
|
str
|
name of the infected state for disease1 (default: 'infected') |
'infected'
|
disease2_infected_state_name
|
str
|
name of the infected state for disease2 (default: 'infected') |
'infected'
|
age_limits
|
list
|
list of two integers that define the age limits for the denominator. |
None
|
denom
|
function
|
function that returns a boolean array of the denominator, usually the relevant population. default: lambda self: (self.sim.people.age >= 15) & (self.sim.people.age < 50) |
None
|
*args, **kwargs
|
optional, passed to ss.Analyzer constructor |
required |
stisim.RelationshipDurations(*args, **kwargs)
Bases: Analyzer
Analyzes the durations of relationships in a structuredsexual network.
stisim.RelationshipDurations.get_relationship_durations()
Returns the durations of all relationships, separated by sex.
If include_current is False, return the duration of only relationships that have ended
Returns:
| Name | Type | Description |
|---|---|---|
female_durations |
list of durations of relationships |
|
male_durations |
list of durations of relationships |
stisim.NetworkDegree(year=None, bins=None, relationship_types=None, *args, **kwargs)
Bases: Analyzer
stisim.NetworkDegree.init_results()
Add results for n_rships, separated for males and females
Optionally disaggregate for risk level / age?
stisim.NetworkDegree.init_pre(sim, **kwargs)
Initialize the analyzer
stisim.NetworkDegree.step()
record lifetime_partners for the user-specified year
stisim.NetworkDegree.plot()
Plot histograms and stats by sex and relationship type
stisim.TimeBetweenRelationships(relationship_type='stable', *args, **kwargs)
Bases: Analyzer
Analyzes the time between relationships in a structuredsexual network. Each timestep, for each debuted agent, check if they are in a relationship of the provided type. If not, increment the counter Otherwise, reset the counter to 0 and append the counter to the list of times between relationships for that agent.
stisim.TimeBetweenRelationships.step()
For each debuted agent, check if they are in a relationship. If they are not, increment the time since last relationship by 1. If they are and time since last relationship is greater than 0, append the time to the list of times between relationships.
stisim.partner_age_diff(year=2000, age_bins=['teens', 'young', 'adult'], network='structuredsexual', *args, **kwargs)
Bases: Analyzer
stisim.partner_age_diff.init_results()
Initialize the results for the age differences.
stisim.partner_age_diff.step()
Record the age differences between partners in the specified year.
stisim.partner_age_diff.plot()
Plot histograms of the age differences between partners.
stisim.DebutAge(bins=None, cohort_starts=None, *args, **kwargs)
Bases: Analyzer
Analyzes the debut age of relationships in a structuredsexual network.
stisim.DebutAge.plot()
Plot the proportion of active agents by cohort and debut age
stisim.art_coverage(age_bins=None, *args, **kwargs)
Bases: Analyzer
Track ART coverage (number and proportion) by sex and age bin.
Results are stored as time series per stratum, accessible via: analyzer.results['n_art_f_15_25'] # Women 15-25 on ART (count) analyzer.results['p_art_m_25_35'] # Men 25-35 on ART (proportion of infected)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
age_bins
|
list
|
age bin edges, e.g. [15, 25, 35, 45, 65]. Default: [15, 25, 35, 45, 65]. Bins are half-open intervals: [lo, hi), i.e. lo <= age < hi. |
None
|
stisim.art_coverage.plot(by_age=True)
Plot ART coverage over time.
Creates a 2-panel figure: aggregate coverage (left) and by age/sex (right). If by_age=False, only plots aggregate.
Example::
sim.run()
sim.analyzers.art_coverage.plot()
stisim.SimPars(**kwargs)
Bases: SimPars
Subclass of Starsim's SimPars with defaults for STI simulations. Refer to Starsim's SimPars for more information on the parameters.
stisim.Sim(pars=None, sim_pars=None, sti_pars=None, nw_pars=None, dem_pars=None, label=None, people=None, demographics=None, diseases=None, networks=None, interventions=None, analyzers=None, connectors=None, custom=None, datafolder=None, data=None, **kwargs)
Bases: Sim
A subclass of starsim.Sim that is specifically designed for STI simulations. It initializes with a structured sexual network and includes STI-specific analyzers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
dict
|
Parameters for the simulation |
None
|
label
|
str
|
A label for the simulation. |
None
|
people
|
People
|
People object containing the agents in the simulation. |
None
|
demographics
|
(Demographics, list)
|
Demographic modules to include. |
None
|
diseases
|
(Disease, list)
|
Disease modules to include. |
None
|
networks
|
(Network, list)
|
Network modules to include. |
None
|
interventions
|
(Intervention, list)
|
Intervention modules to include. |
None
|
analyzers
|
(Analyzer, list)
|
Analyzer modules to include. |
None
|
connectors
|
bool or list
|
If True, use default connectors; otherwise, provide a list of connectors. |
None
|
copy_inputs
|
bool
|
Whether to copy input parameters or not. |
required |
data
|
Additional data to be used in the simulation. |
None
|
|
e.g.
|
|
required | |
Example usage
|
|
required | |
# demographics, and connectors. If you want to specify parameters for the diseases, you can do so like this
|
|
required | |
You can also pass in custom parameters for the default modules, such as networks or demographics, like this
|
|
required | |
These are all in addition to the standard starsim input style using module instances directly, e.g.
|
|
required | |
and in the kwargs), the order of precedence is as follows
|
|
required |
stisim.Sim.separate_pars(pars=None, sim_pars=None, sti_pars=None, nw_pars=None, dem_pars=None, sim_kwargs=None, **kwargs)
Create a nested dict of parameters that get passed to Sim constructor and the component modules Prioritization: - If any key appears in both pars and _pars, the value from _pars will be used. - If any key appears in both pars and kwargs, the value from kwargs will be used.
stisim.Sim.remap_pars(pars)
staticmethod
Remap any parameter names to match the expected format for STIs and networks. This is useful for ensuring that parameters are correctly interpreted by the modules.
stisim.Sim.init(force=False, **kwargs)
Perform all initializations for the sim
stisim.Sim.plot(key=None, **kwargs)
Plot sim results. If key is the name of a disease in the sim (e.g. 'hiv'), shows a curated panel for that disease. Otherwise falls back to the standard starsim plot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str / list
|
Result key(s) to plot, or a disease name for curated plots |
None
|
**kwargs
|
Passed to ss.Sim.plot() |
{}
|
Returns:
| Type | Description |
|---|---|
|
matplotlib.figure.Figure |
stisim.Sim.process_networks()
Process the network parameters to create network module. If networks are provided, they will be used; otherwise, use default networks (usual case)
stisim.Sim.process_demographics()
Process the location to create people and demographics if not provided.
stisim.Sim.process_stis()
Look up a disease by its name and return the corresponding module.
stisim.Sim.process_connectors()
Get the default connectors for the diseases in the simulation.
Connectors are loaded based on the disease names or modules provided in the format
stisim.Sim.case_insensitive_getattr(searchspace, attrname)
Find a class in the given package that matches the name, ignoring case.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
searchspace
|
list
|
A list of classes or modules to search through. |
required |
attrname
|
str
|
The name of the attribute to find, case-insensitive. |
required |
stisim.compute_gof(actual, predicted, normalize=True, use_frac=False, use_squared=False, as_scalar='none', eps=1e-09, skestimator=None, estimator=None, **kwargs)
Calculate the goodness of fit. By default use normalized absolute error, but highly customizable. For example, mean squared error is equivalent to setting normalize=False, use_squared=True, as_scalar='mean'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
arr
|
array of actual (data) points |
required |
predicted
|
arr
|
corresponding array of predicted (model) points |
required |
normalize
|
bool
|
whether to divide the values by the largest value in either series |
True
|
use_frac
|
bool
|
convert to fractional mismatches rather than absolute |
False
|
use_squared
|
bool
|
square the mismatches |
False
|
as_scalar
|
str
|
return as a scalar instead of a time series: choices are sum, mean, median |
'none'
|
eps
|
float
|
to avoid divide-by-zero |
1e-09
|
skestimator
|
str
|
if provided, use this scikit-learn estimator instead |
None
|
estimator
|
func
|
if provided, use this custom estimator instead |
None
|
kwargs
|
dict
|
passed to the scikit-learn or custom estimator |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
gofs |
arr
|
array of goodness-of-fit values, or a single value if as_scalar is True |
Examples::
x1 = np.cumsum(np.random.random(100))
x2 = np.cumsum(np.random.random(100))
e1 = compute_gof(x1, x2) # Default, normalized absolute error
e2 = compute_gof(x1, x2, normalize=False, use_frac=False) # Fractional error
e3 = compute_gof(x1, x2, normalize=False, use_squared=True, as_scalar='mean') # Mean squared error
e4 = compute_gof(x1, x2, skestimator='mean_squared_error') # Scikit-learn's MSE method
e5 = compute_gof(x1, x2, as_scalar='median') # Normalized median absolute error -- highly robust
stisim.flatten_calib_pars(calib_pars)
Normalize calibration parameters to flat dot-notation format.
Accepts two formats:
Nested (grouped by module)::
dict(hiv=dict(beta_m2f=dict(low=0.01, high=0.10)))
Flat (dot notation — returned unchanged)::
{'hiv.beta_m2f': dict(low=0.01, high=0.10)}
Nested format is detected when a value is a dict whose keys don't
overlap with spec keys (low, high, guess, etc.).
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Flat dict with |
stisim.set_sim_pars(sim, pars)
Set calibrated parameters on a sim.
All parameters are set directly on the module objects via
sim.get_module(). This works on uninitialized sims because every
module stores its pars dict immediately on construction.
Supports both dot notation ('hiv.beta_m2f') and legacy underscore
format ('hiv_beta_m2f'). Legacy keys are matched greedily against
the sim's module names (longest match first).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
A simulation (modules must be instances, not strings) |
required |
pars
|
dict
|
Flat parameter dict, e.g. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Sim |
The same sim, modified in place |
stisim.default_build_fn(sim, calib_pars, **kwargs)
Default build function for STIsim calibration.
Routes calibration parameters to the correct sim module using dot notation:
- ``'hiv.beta_m2f'`` → ``sim.get_module('hiv').pars['beta_m2f']``
- ``'structuredsexual.prop_f0'`` → ``sim.get_module('structuredsexual').pars['prop_f0']``
- ``'hiv_syph.rel_sus_syph_hiv'`` → ``sim.get_module('hiv_syph').pars['rel_sus_syph_hiv']``
- ``'symp_algo.rel_test'`` → ``sim.get_module('symp_algo').pars['rel_test']``
All parameters are set on the uninitialized sim before sim.init() is
called. This works because every module stores its pars dict
immediately on construction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
An uninitialized simulation (modules must be instances, not strings) |
required |
calib_pars
|
dict
|
Calibration parameters with values set by the sampler |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Sim |
The initialized and modified simulation |
Example::
calib_pars = {
'hiv.beta_m2f': dict(low=0.01, high=0.10, guess=0.035, value=0.05),
'structuredsexual.f1_conc': dict(low=0.005, high=0.3, guess=0.16, value=0.10),
'hiv_syph.rel_sus_syph_hiv': dict(low=1.0, high=4.0, guess=2.5, value=3.0),
'symp_algo.rel_test': dict(low=0.5, high=1.5, guess=1.0, value=1.2),
}
sim = default_build_fn(sim, calib_pars)
stisim.make_calib_sims(calib=None, calib_pars=None, sim=None, n_parsets=None, check_fn=None, seeds_per_par=1, **kwargs)
Create and run simulations using calibrated parameters.
Provide either a :class:Calibration object or a set of calibration
parameters directly. The function creates one sim per parameter set (with
optional seed replication), runs them in parallel, and optionally filters
the results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
calib
|
Calibration
|
A completed calibration. Extracts pars via
|
None
|
calib_pars
|
Parameter source — one of:
|
None
|
|
sim
|
Sim
|
Base (uninitialized) simulation to copy. If |
None
|
n_parsets
|
int
|
Number of top parameter sets to use. |
None
|
check_fn
|
callable
|
Post-run filter — |
None
|
seeds_per_par
|
int
|
Random seeds per parameter set. When > 1, each
par set is run with multiple seeds and only the first surviving
seed (per |
1
|
**kwargs
|
Passed to |
{}
|
Returns:
| Type | Description |
|---|---|
|
ss.MultiSim: A MultiSim containing the completed simulations. |
Examples::
# From a Calibration object
msim = sti.make_calib_sims(calib=calib, n_parsets=200)
# From a saved parameters DataFrame
pars_df = sc.loadobj('results/pars.df')
msim = sti.make_calib_sims(calib_pars=pars_df, sim=make_sim(), n_parsets=50)
# Single parameter set with multiple seeds
msim = sti.make_calib_sims(
calib_pars={'hiv.beta_m2f': 0.05, 'syph.beta_m2f': 0.2},
sim=make_sim(), seeds_per_par=5,
)
# Different scenario with calibrated parameters
msim = sti.make_calib_sims(
calib_pars=pars_df, n_parsets=10, seeds_per_par=5,
sim=make_sim(scenario='intervention'),
check_fn=lambda s: float(np.sum(s.results.syph.new_infections[-60:])) > 0,
)
stisim.sti_aliases()
Define aliases for STIs
stisim.sti_register(key=None)
Registry of STI names linked to disease classes
stisim.merged_sti_pars()
Merge all the parameters from the STI disease modules
stisim.make_sti(name, pars=None)
Create an STI disease module based on the name and parameters provided.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the STI disease module to create. |
required |
pars
|
dict
|
Parameters to initialize the disease module with. |
None
|
Returns:
| Type | Description |
|---|---|
|
ss.Disease: An instance of the specified STI disease module. |
stisim.mergepars(*args)
Merge all parameter dictionaries into a single dictionary. This is used to initialize the SimPars class with all relevant parameters. It wraps the sc.mergedicts function to ensure all inputs are dicts
stisim.dem_pars()
Return a dictionary with all parameters used within demographic modules
stisim.analyzers
Common analyzers for STI analyses
stisim.analyzers.coinfection_stats(disease1, disease2, disease1_infected_state_name='infected', disease2_infected_state_name='infected', age_limits=None, denom=None, *args, **kwargs)
Bases: result_grouper
Generates stats for the coinfection of two diseases. This is useful for looking at the coinfection of HIV and syphilis, for example.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
disease1
|
str | Disease
|
name of the first disease |
required |
disease2
|
str | Disease
|
name of the second disease |
required |
disease1_infected_state_name
|
str
|
name of the infected state for disease1 (default: 'infected') |
'infected'
|
disease2_infected_state_name
|
str
|
name of the infected state for disease2 (default: 'infected') |
'infected'
|
age_limits
|
list
|
list of two integers that define the age limits for the denominator. |
None
|
denom
|
function
|
function that returns a boolean array of the denominator, usually the relevant population. default: lambda self: (self.sim.people.age >= 15) & (self.sim.people.age < 50) |
None
|
*args, **kwargs
|
optional, passed to ss.Analyzer constructor |
required |
stisim.analyzers.RelationshipDurations(*args, **kwargs)
Bases: Analyzer
Analyzes the durations of relationships in a structuredsexual network.
stisim.analyzers.RelationshipDurations.get_relationship_durations()
Returns the durations of all relationships, separated by sex.
If include_current is False, return the duration of only relationships that have ended
Returns:
| Name | Type | Description |
|---|---|---|
female_durations |
list of durations of relationships |
|
male_durations |
list of durations of relationships |
stisim.analyzers.NetworkDegree(year=None, bins=None, relationship_types=None, *args, **kwargs)
Bases: Analyzer
stisim.analyzers.NetworkDegree.init_results()
Add results for n_rships, separated for males and females
Optionally disaggregate for risk level / age?
stisim.analyzers.NetworkDegree.init_pre(sim, **kwargs)
Initialize the analyzer
stisim.analyzers.NetworkDegree.step()
record lifetime_partners for the user-specified year
stisim.analyzers.NetworkDegree.plot()
Plot histograms and stats by sex and relationship type
stisim.analyzers.TimeBetweenRelationships(relationship_type='stable', *args, **kwargs)
Bases: Analyzer
Analyzes the time between relationships in a structuredsexual network. Each timestep, for each debuted agent, check if they are in a relationship of the provided type. If not, increment the counter Otherwise, reset the counter to 0 and append the counter to the list of times between relationships for that agent.
stisim.analyzers.TimeBetweenRelationships.step()
For each debuted agent, check if they are in a relationship. If they are not, increment the time since last relationship by 1. If they are and time since last relationship is greater than 0, append the time to the list of times between relationships.
stisim.analyzers.partner_age_diff(year=2000, age_bins=['teens', 'young', 'adult'], network='structuredsexual', *args, **kwargs)
Bases: Analyzer
stisim.analyzers.partner_age_diff.init_results()
Initialize the results for the age differences.
stisim.analyzers.partner_age_diff.step()
Record the age differences between partners in the specified year.
stisim.analyzers.partner_age_diff.plot()
Plot histograms of the age differences between partners.
stisim.analyzers.DebutAge(bins=None, cohort_starts=None, *args, **kwargs)
Bases: Analyzer
Analyzes the debut age of relationships in a structuredsexual network.
stisim.analyzers.DebutAge.plot()
Plot the proportion of active agents by cohort and debut age
stisim.analyzers.art_coverage(age_bins=None, *args, **kwargs)
Bases: Analyzer
Track ART coverage (number and proportion) by sex and age bin.
Results are stored as time series per stratum, accessible via: analyzer.results['n_art_f_15_25'] # Women 15-25 on ART (count) analyzer.results['p_art_m_25_35'] # Men 25-35 on ART (proportion of infected)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
age_bins
|
list
|
age bin edges, e.g. [15, 25, 35, 45, 65]. Default: [15, 25, 35, 45, 65]. Bins are half-open intervals: [lo, hi), i.e. lo <= age < hi. |
None
|
stisim.analyzers.art_coverage.plot(by_age=True)
Plot ART coverage over time.
Creates a 2-panel figure: aggregate coverage (left) and by age/sex (right). If by_age=False, only plots aggregate.
Example::
sim.run()
sim.analyzers.art_coverage.plot()
stisim.calibration
Define the calibration class
stisim.calibration.Calibration(sim, calib_pars, data=None, weights=None, extra_results=None, save_results=False, check_fn=None, **kwargs)
Bases: Calibration
Customized STIsim calibration class.
Inherits all the functionality of the Starsim calibration class, but adds:
- A default build function that routes parameters using dot notation
(e.g.
'hiv.beta_m2f') - A default evaluation function that uses the data provided in the constructor
- :meth:
get_parsfor extracting calibrated parameter sets
If no build_fn is provided, uses :func:default_build_fn which looks
up modules via sim.get_module() and sets their parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
The simulation to calibrate |
required |
calib_pars
|
dict
|
Parameters to calibrate using dot notation, e.g.
|
required |
data
|
DataFrame
|
Calibration targets with 'time' column + result columns |
None
|
weights
|
dict
|
Optional weight multipliers per result |
None
|
extra_results
|
list
|
Additional results to track beyond data columns |
None
|
save_results
|
bool
|
Save sim results for each trial |
False
|
Examples::
sim = make_sim()
data = pd.read_csv('calibration_data.csv')
calib_pars = {
'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05),
'structuredsexual.prop_f0': dict(low=0.5, high=0.9, guess=0.8),
}
calib = sti.Calibration(sim=sim, calib_pars=calib_pars, data=data, total_trials=100)
calib.calibrate()
# Extract best parameters and run multi-sim
par_sets = calib.get_pars(n=200)
msim = sti.make_calib_sims(calib=calib, n_parsets=200)
stisim.calibration.Calibration.worker()
Run a single worker, catching exceptions so one crash doesn't kill all workers
stisim.calibration.Calibration.calibrate(calib_pars=None, **kwargs)
Perform calibration with crash-recovery support.
If continue_db=True and the database already has completed trials, only the remaining trials will be run. This allows recovery from crashes by simply re-running the same command.
stisim.calibration.Calibration.run_trial(trial)
Define the objective for Optuna
stisim.calibration.Calibration.parse_study(study)
Parse the study into a data frame -- called automatically
stisim.calibration.Calibration.load_results(study)
Load the results from the tmp files, tracking which loaded successfully
stisim.calibration.Calibration.get_pars(n=None)
Extract top-N calibrated parameter sets as a list of flat dicts.
Each dict maps 'module.par' keys to scalar values (metadata columns
like index, mismatch, and rand_seed are stripped). The
returned dicts can be passed directly to :func:set_sim_pars or
:func:make_calib_sims.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of top parameter sets. |
None
|
Returns:
| Type | Description |
|---|---|
|
list[dict]: Parameter sets sorted by mismatch (best first). |
stisim.calibration.Calibration.save(filename, shrink=True, n_results=None, save_pars=True, pars_filename=None)
Save calibration results.
Optionally shrinks to the top n_results before saving (default: keep top 10% of completed trials). Also saves the parameter DataFrame as a separate file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str / Path
|
Path for the saved calibration object. |
required |
shrink
|
bool
|
If True (default), shrink before saving. The full
(unshrunk) object is saved with a |
True
|
n_results
|
int
|
Number of top results to keep when shrinking.
Default: |
None
|
save_pars
|
bool
|
If True (default), also save |
True
|
pars_filename
|
str / Path
|
Path for the parameter DataFrame. If
None, uses |
None
|
Returns:
| Type | Description |
|---|---|
|
The (possibly shrunk) calibration object. |
stisim.calibration.Calibration.shrink(n_results=100, make_df=True)
Shrink the results to only the best fit
stisim.calibration.compute_gof(actual, predicted, normalize=True, use_frac=False, use_squared=False, as_scalar='none', eps=1e-09, skestimator=None, estimator=None, **kwargs)
Calculate the goodness of fit. By default use normalized absolute error, but highly customizable. For example, mean squared error is equivalent to setting normalize=False, use_squared=True, as_scalar='mean'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
arr
|
array of actual (data) points |
required |
predicted
|
arr
|
corresponding array of predicted (model) points |
required |
normalize
|
bool
|
whether to divide the values by the largest value in either series |
True
|
use_frac
|
bool
|
convert to fractional mismatches rather than absolute |
False
|
use_squared
|
bool
|
square the mismatches |
False
|
as_scalar
|
str
|
return as a scalar instead of a time series: choices are sum, mean, median |
'none'
|
eps
|
float
|
to avoid divide-by-zero |
1e-09
|
skestimator
|
str
|
if provided, use this scikit-learn estimator instead |
None
|
estimator
|
func
|
if provided, use this custom estimator instead |
None
|
kwargs
|
dict
|
passed to the scikit-learn or custom estimator |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
gofs |
arr
|
array of goodness-of-fit values, or a single value if as_scalar is True |
Examples::
x1 = np.cumsum(np.random.random(100))
x2 = np.cumsum(np.random.random(100))
e1 = compute_gof(x1, x2) # Default, normalized absolute error
e2 = compute_gof(x1, x2, normalize=False, use_frac=False) # Fractional error
e3 = compute_gof(x1, x2, normalize=False, use_squared=True, as_scalar='mean') # Mean squared error
e4 = compute_gof(x1, x2, skestimator='mean_squared_error') # Scikit-learn's MSE method
e5 = compute_gof(x1, x2, as_scalar='median') # Normalized median absolute error -- highly robust
stisim.calibration.eval_fn(sim, data=None, sim_result_list=None, weights=None, df_res_list=None)
Custom evaluation function for STIsim
stisim.calibration.flatten_calib_pars(calib_pars)
Normalize calibration parameters to flat dot-notation format.
Accepts two formats:
Nested (grouped by module)::
dict(hiv=dict(beta_m2f=dict(low=0.01, high=0.10)))
Flat (dot notation — returned unchanged)::
{'hiv.beta_m2f': dict(low=0.01, high=0.10)}
Nested format is detected when a value is a dict whose keys don't
overlap with spec keys (low, high, guess, etc.).
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Flat dict with |
stisim.calibration.set_sim_pars(sim, pars)
Set calibrated parameters on a sim.
All parameters are set directly on the module objects via
sim.get_module(). This works on uninitialized sims because every
module stores its pars dict immediately on construction.
Supports both dot notation ('hiv.beta_m2f') and legacy underscore
format ('hiv_beta_m2f'). Legacy keys are matched greedily against
the sim's module names (longest match first).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
A simulation (modules must be instances, not strings) |
required |
pars
|
dict
|
Flat parameter dict, e.g. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Sim |
The same sim, modified in place |
stisim.calibration.default_build_fn(sim, calib_pars, **kwargs)
Default build function for STIsim calibration.
Routes calibration parameters to the correct sim module using dot notation:
- ``'hiv.beta_m2f'`` → ``sim.get_module('hiv').pars['beta_m2f']``
- ``'structuredsexual.prop_f0'`` → ``sim.get_module('structuredsexual').pars['prop_f0']``
- ``'hiv_syph.rel_sus_syph_hiv'`` → ``sim.get_module('hiv_syph').pars['rel_sus_syph_hiv']``
- ``'symp_algo.rel_test'`` → ``sim.get_module('symp_algo').pars['rel_test']``
All parameters are set on the uninitialized sim before sim.init() is
called. This works because every module stores its pars dict
immediately on construction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sim
|
Sim
|
An uninitialized simulation (modules must be instances, not strings) |
required |
calib_pars
|
dict
|
Calibration parameters with values set by the sampler |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Sim |
The initialized and modified simulation |
Example::
calib_pars = {
'hiv.beta_m2f': dict(low=0.01, high=0.10, guess=0.035, value=0.05),
'structuredsexual.f1_conc': dict(low=0.005, high=0.3, guess=0.16, value=0.10),
'hiv_syph.rel_sus_syph_hiv': dict(low=1.0, high=4.0, guess=2.5, value=3.0),
'symp_algo.rel_test': dict(low=0.5, high=1.5, guess=1.0, value=1.2),
}
sim = default_build_fn(sim, calib_pars)
stisim.calibration.make_calib_sims(calib=None, calib_pars=None, sim=None, n_parsets=None, check_fn=None, seeds_per_par=1, **kwargs)
Create and run simulations using calibrated parameters.
Provide either a :class:Calibration object or a set of calibration
parameters directly. The function creates one sim per parameter set (with
optional seed replication), runs them in parallel, and optionally filters
the results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
calib
|
Calibration
|
A completed calibration. Extracts pars via
|
None
|
calib_pars
|
Parameter source — one of:
|
None
|
|
sim
|
Sim
|
Base (uninitialized) simulation to copy. If |
None
|
n_parsets
|
int
|
Number of top parameter sets to use. |
None
|
check_fn
|
callable
|
Post-run filter — |
None
|
seeds_per_par
|
int
|
Random seeds per parameter set. When > 1, each
par set is run with multiple seeds and only the first surviving
seed (per |
1
|
**kwargs
|
Passed to |
{}
|
Returns:
| Type | Description |
|---|---|
|
ss.MultiSim: A MultiSim containing the completed simulations. |
Examples::
# From a Calibration object
msim = sti.make_calib_sims(calib=calib, n_parsets=200)
# From a saved parameters DataFrame
pars_df = sc.loadobj('results/pars.df')
msim = sti.make_calib_sims(calib_pars=pars_df, sim=make_sim(), n_parsets=50)
# Single parameter set with multiple seeds
msim = sti.make_calib_sims(
calib_pars={'hiv.beta_m2f': 0.05, 'syph.beta_m2f': 0.2},
sim=make_sim(), seeds_per_par=5,
)
# Different scenario with calibrated parameters
msim = sti.make_calib_sims(
calib_pars=pars_df, n_parsets=10, seeds_per_par=5,
sim=make_sim(scenario='intervention'),
check_fn=lambda s: float(np.sum(s.results.syph.new_infections[-60:])) > 0,
)
stisim.care_seeking
Define care-seeking propensity module for STIsim.
Provides a cross-disease individual-level care-seeking propensity that can be used by testing interventions across HIV, syphilis, and other diseases.
stisim.care_seeking.CareSeeking(pars=None, **kwargs)
Bases: Module
Cross-disease care-seeking propensity for each individual.
Each agent gets a baseline propensity drawn from a distribution at birth. Men have lower propensity by default (controlled by rel_care_m2f). The propensity may be temporarily modified by factors like pregnancy.
stisim.care_seeking.CareSeeking.set_care_seeking_states(upper_age=None)
Set baseline care-seeking propensity for each agent. Called at init (upper_age=None for all agents) and each step (upper_age=dt to initialize newborns).
stisim.care_seeking.CareSeeking.step()
Initialize propensity for newborns, then reset all propensities to baseline before applying temporary modifiers.
stisim.connectors
stisim.connectors.gud_syph
stisim.connectors.gud_syph.gud_syph(pars=None, **kwargs)
Bases: Connector
stisim.connectors.gud_syph.gud_syph.update(sim)
GUD-syphilis interactions
stisim.connectors.hiv_sti
Syphilis-HIV connector for running coinfection analyses
stisim.data
stisim.data.get_age_distribution(location=None, year=None, datafolder=None)
Load age distribution for a given location & year
stisim.data.get_rates(location, which, datafolder=None)
Load birth/death/fertility/migration rates for a given location
stisim.data.get_filename(location, indicator, year=None)
Get the filename for a given location, indicator, and year.
stisim.data.check_downloaded(location, indicators=None, year=None, verbose=1)
Check if data is downloaded for this location Args: location (str): the location to check indicators (list): the indicators to check for; if None, checks all verbose (int): detail to print (0 = none, 1 = reason for failure, 2 = everything)
stisim.data.get_country_aliases()
Define aliases for countries
stisim.data.get_country_code(df, location)
Find a match between the data file and the provided location.
stisim.data.download_data(location, indicators=None, start=1950, stop=2100, step=10)
Download data
stisim.data.get_available(base_url, auth_key, which, filename=None, do_save=True)
Save a list of indicators or locations to a csv file
stisim.data.downloaders
Download data needed for STIsim.
To use this, you will need to get an auth_key from the UN Data Portal API.
stisim.data.downloaders.get_filename(location, indicator, year=None)
Get the filename for a given location, indicator, and year.
stisim.data.downloaders.check_downloaded(location, indicators=None, year=None, verbose=1)
Check if data is downloaded for this location Args: location (str): the location to check indicators (list): the indicators to check for; if None, checks all verbose (int): detail to print (0 = none, 1 = reason for failure, 2 = everything)
stisim.data.downloaders.get_country_aliases()
Define aliases for countries
stisim.data.downloaders.get_country_code(df, location)
Find a match between the data file and the provided location.
stisim.data.downloaders.download_data(location, indicators=None, start=1950, stop=2100, step=10)
Download data
stisim.data.downloaders.get_available(base_url, auth_key, which, filename=None, do_save=True)
Save a list of indicators or locations to a csv file
stisim.data.loaders
Load data
stisim.data.loaders.get_age_distribution(location=None, year=None, datafolder=None)
Load age distribution for a given location & year
stisim.data.loaders.get_rates(location, which, datafolder=None)
Load birth/death/fertility/migration rates for a given location
stisim.data.test_downloaders
Test data downloaders; does not require a full STIsim install
stisim.demographics
Define demographic modules used within STIsim
stisim.demographics.Migration(pars=None, migration_data=None, **kwargs)
Bases: Demographics
Remove / add migrants Assumes a datafile with the number of migrants each year
stisim.demographics.Migration.init_migration_propensity()
Set individual's propensity to migrate This is currently a random variable but could be defined as a function of age/sex/other properties
stisim.demographics.Migration.get_migrants()
Get the number of migrants for this timestep
stisim.demographics.Migration.make_immigrants(twin_uids)
Make immigrants by making copies of existing agents
stisim.demographics.Migration.step()
Perform all updates
stisim.demographics.Migration.step_migration()
Select people to migrate
stisim.demographics.Migration.remove_emigrants()
Remove people who've decided to emigrate this timestep
stisim.diseases
stisim.diseases.BaseSTI(name=None, pars=None, init_prev_data=None, **kwargs)
Bases: Infection
Base class for sexually transmitted infections. Modifies make_new_cases to account for barrier protection.
stisim.diseases.BaseSTI.treatable
property
Assume infected people are treatable, can be overwritten in subclasses
stisim.diseases.BaseSTI.make_init_prev(uids=None, data=None, active=True)
Initialize prevalence by sex and risk group
stisim.diseases.BaseSTI.agehist(a)
Return an age histogram
stisim.diseases.BaseSTI.init_results()
Initialize results
stisim.diseases.BaseSTI.infect()
Determine who gets infected on this timestep via transmission on the network
stisim.diseases.SEIS(pars=None, name=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.SEIS.treatable
property
Active bacterial presence -- includes exposed and infected, and responds to treatment
stisim.diseases.SEIS.init_results()
Initialize results
stisim.diseases.SEIS.step_state()
Updates for this timestep
stisim.diseases.SEIS.wipe_dates(uids)
Clear all previous dates
stisim.diseases.SEIS.set_prognoses(uids, sources=None)
Set initial prognoses for adults newly infected
stisim.diseases.ChlamydiaBL(pars=None, **kwargs)
Bases: Chlamydia
stisim.diseases.ChlamydiaBL.update_pre()
Updates prior to interventions
stisim.diseases.ChlamydiaBL.set_ct_load(uids)
Bacterial load dynamics
stisim.diseases.ChlamydiaBL.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.diseases.SimpleBV(pars=None, name='bv', **kwargs)
Bases: Disease
stisim.diseases.SimpleBV.treatable
property
Responds to treatment
stisim.diseases.SimpleBV.init_results()
Initialize results
stisim.diseases.SimpleBV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.diseases.SimpleBV.init_post()
Initialize with sim properties
stisim.diseases.SimpleBV.spontaneous(uids)
Create new cases via spontaneous occurrence
stisim.diseases.SimpleBV.step_state()
Updates for this timestep
stisim.diseases.SimpleBV.wipe_dates(uids)
Clear all previous dates
stisim.diseases.SimpleBV.set_duration(symp, asymp)
Set duration of infection
stisim.diseases.SimpleBV.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.diseases.BV(pars=None, name='bv', **kwargs)
Bases: BaseSTI
stisim.diseases.BV.init_results()
Initialize results
stisim.diseases.BV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.diseases.BV.set_circumcision(upper_age=None)
Set circumcision status
stisim.diseases.BV.compute_circumcision_impact(spontaneous=True)
Compute the relative impact of circumcision on susceptibility for women. This is used for spontaneous occurence only. If sexual transmission in model, then we adjust man's susceptibility.
stisim.diseases.BV.init_post()
Initialize with sim properties
stisim.diseases.BV.spontaneous(uids, cst='cst1')
Determine the probability of transitioning to worse CST states for agents in CST 1, we determine probability of transitioning to CST 3 (assuming no transition directly to CST 4) for agents in CST 3, we determine probability of transitioning to CST 4 agents in CST 4 have no further transitions
stisim.diseases.BV.sexual_transmission()
Determine who gets infected on this timestep via transmission on the network
stisim.diseases.BV.clear_infection(uids)
Clear infection
stisim.diseases.BV.step_state()
Updates for this timestep
stisim.diseases.BV.wipe_dates(uids)
Clear all previous dates
stisim.diseases.BV.set_male_prognoses(uids)
Set initial prognoses for newly infected males
stisim.diseases.BV.set_prognoses(uids, new_cst=3)
Set initial prognoses for newly infected females
stisim.diseases.Placeholder(pars=None, name=None, **kwargs)
Bases: Disease
stisim.diseases.Placeholder.step()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.diseases.GUD(pars=None, init_prev_data=None, **kwargs)
Bases: Infection
stisim.diseases.GUD.step_state()
Update states
stisim.diseases.GUD.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected with syphilis
stisim.diseases.HIV(pars=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.HIV.init_results()
Initialize results
stisim.diseases.HIV.init_post()
Set states
stisim.diseases.HIV.acute_decline(uids)
Acute decline in CD4
stisim.diseases.HIV.falling_decline(uids)
Decline in CD4 during late-stage infection, when counts are falling
stisim.diseases.HIV.post_art_decline(uids)
Decline in CD4 after going off treatment This implementation has the possibly-undesirable feature that a person who goes on ART for a year and then off again might have a slightly shorter lifespan than if they'd never started treatment.
stisim.diseases.HIV.cd4_increase(uids)
Increase CD4 counts for people who are receiving treatment. Growth curves are calculated to match EMODs CD4 reconstitution equation for people who initiate treatment with a CD4 count of 50 (https://docs.idmod.org/projects/emod-hiv/en/latest/hiv-model-healthcare-systems.html) However, here we use a logistic growth function and assume that ART CD4 count depends on CD4 at initiation. Sources:
- https://i-base.info/guides/starting/cd4-increase
- https://www.sciencedirect.com/science/article/pii/S1876034117302022
- https://bmcinfectdis.biomedcentral.com/articles/10.1186/1471-2334-8-20
stisim.diseases.HIV.init_cd4()
Set CD4 counts
stisim.diseases.HIV.init_care_seeking()
Set care seeking behavior
stisim.diseases.HIV.step_state()
Carry out autonomous updates at the start of the timestep (prior to transmission)
stisim.diseases.HIV.step_die(uids)
Clear all states for dead agents
stisim.diseases.HIV.update_transmission()
Update rel_trans and rel_sus for all agents. These are reset on each timestep then adjusted depending on states. Adjustments are made throughout different modules:
- rel_trans for acute and late-stage untreated infection are adjusted below
- rel_trans for all people on treatment (including pregnant women) below
- rel_sus for unborn babies of pregnant WLHIV receiving treatment is adjusted in the ART intervention
stisim.diseases.HIV.update_results()
Update results at each time step
stisim.diseases.HIV.set_prognoses(uids, sources=None, ti=None)
Set prognoses upon infection
stisim.diseases.HIV.start_art(uids)
Check who is ready to start ART treatment and put them on ART
stisim.diseases.HIV.stop_art(uids=None)
Check who is stopping ART treatment and put them off ART
stisim.diseases.SyphilisPlaceholder(pars=None, **kwargs)
Bases: Disease
stisim.diseases.SyphilisPlaceholder.step_state()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.diseases.Syphilis(pars=None, name='syph', init_prev_data=None, init_prev_latent_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.Syphilis.naive
property
Never exposed
stisim.diseases.Syphilis.sus_not_naive
property
Susceptible but with syphilis antibodies, which persist after treatment
stisim.diseases.Syphilis.mat_active
property
Definition of infection used for maternal transmission, includes exposed + primary + secondary stages
stisim.diseases.Syphilis.active
property
Active infection includes primary and secondary stages
stisim.diseases.Syphilis.infectious
property
Infectious
stisim.diseases.Syphilis.ulcerative
property
Has a visible genital ulcer (chancre at a visible site during primary stage)
stisim.diseases.Syphilis.symptomatic
property
Has noticeable symptoms: visible ulcer or visible rash
stisim.diseases.Syphilis.infect()
Override to use rel_trans=1 for maternal transmission. Stage-specific rel_trans (primary >> latent) only applies to sexual transmission. For MTC, all infected stages transmit equally since spirochetemia during pregnancy affects the fetus regardless of the mother's clinical stage.
stisim.diseases.Syphilis.init_post()
Make initial cases
stisim.diseases.Syphilis.init_results()
Initialize results
stisim.diseases.Syphilis.step_state()
Updates to states
stisim.diseases.Syphilis.step_die(uids)
Clear all states and dates for dead agents (including NND/stillborn babies)
stisim.diseases.Syphilis.set_prognoses(uids, source_uids=None, ti=None)
Set initial prognoses for adults newly infected with syphilis. Note: congenital infections are routed to set_congenital by starsim's set_outcomes(), so only adult infections reach this method.
stisim.diseases.Syphilis.set_secondary_prognoses(uids)
Set prognoses for people who have just progressed to secondary infection
stisim.diseases.Syphilis.set_congenital(target_uids, source_uids=None)
Natural history of syphilis for congenital infection. Birth outcomes depend on the mother's disease stage: mat_active (exposed|primary|secondary), early latent, late latent.
stisim.diseases.Trichomoniasis(pars=None, name='tv', init_prev_data=None, **kwargs)
Bases: SEIS
stisim.diseases.Trichomoniasis.set_duration(p, symp, asymp, pid)
Overwrite duration setting with persistence for female asymptomatic infection
stisim.diseases.bv
BV modules Includes: - a simple BV model for generating background prevalence of vaginal discharge - a detailed model of the vaginal microbiome including community state types (CSTs)
stisim.diseases.bv.SimpleBV(pars=None, name='bv', **kwargs)
Bases: Disease
stisim.diseases.bv.SimpleBV.treatable
property
Responds to treatment
stisim.diseases.bv.SimpleBV.init_results()
Initialize results
stisim.diseases.bv.SimpleBV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.diseases.bv.SimpleBV.init_post()
Initialize with sim properties
stisim.diseases.bv.SimpleBV.spontaneous(uids)
Create new cases via spontaneous occurrence
stisim.diseases.bv.SimpleBV.step_state()
Updates for this timestep
stisim.diseases.bv.SimpleBV.wipe_dates(uids)
Clear all previous dates
stisim.diseases.bv.SimpleBV.set_duration(symp, asymp)
Set duration of infection
stisim.diseases.bv.SimpleBV.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.diseases.bv.BVPars(**kwargs)
Bases: BaseSTIPars
Parameters for the BV model
stisim.diseases.bv.BV(pars=None, name='bv', **kwargs)
Bases: BaseSTI
stisim.diseases.bv.BV.init_results()
Initialize results
stisim.diseases.bv.BV.set_hygiene_states(upper_age=None)
Set vaginal hygiene states
stisim.diseases.bv.BV.set_circumcision(upper_age=None)
Set circumcision status
stisim.diseases.bv.BV.compute_circumcision_impact(spontaneous=True)
Compute the relative impact of circumcision on susceptibility for women. This is used for spontaneous occurence only. If sexual transmission in model, then we adjust man's susceptibility.
stisim.diseases.bv.BV.init_post()
Initialize with sim properties
stisim.diseases.bv.BV.spontaneous(uids, cst='cst1')
Determine the probability of transitioning to worse CST states for agents in CST 1, we determine probability of transitioning to CST 3 (assuming no transition directly to CST 4) for agents in CST 3, we determine probability of transitioning to CST 4 agents in CST 4 have no further transitions
stisim.diseases.bv.BV.sexual_transmission()
Determine who gets infected on this timestep via transmission on the network
stisim.diseases.bv.BV.clear_infection(uids)
Clear infection
stisim.diseases.bv.BV.step_state()
Updates for this timestep
stisim.diseases.bv.BV.wipe_dates(uids)
Clear all previous dates
stisim.diseases.bv.BV.set_male_prognoses(uids)
Set initial prognoses for newly infected males
stisim.diseases.bv.BV.set_prognoses(uids, new_cst=3)
Set initial prognoses for newly infected females
stisim.diseases.chlamydia
Chlamydia trachomatis disease module
stisim.diseases.chlamydia.ChlamydiaBL(pars=None, **kwargs)
Bases: Chlamydia
stisim.diseases.chlamydia.ChlamydiaBL.update_pre()
Updates prior to interventions
stisim.diseases.chlamydia.ChlamydiaBL.set_ct_load(uids)
Bacterial load dynamics
stisim.diseases.chlamydia.ChlamydiaBL.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected
stisim.diseases.gonorrhea
Gonorrhea disease module
stisim.diseases.gud
Placeholder modules for non-specific STIs, including: - Genital ulcer disease - Vaginal discharge
stisim.diseases.gud.Placeholder(pars=None, name=None, **kwargs)
Bases: Disease
stisim.diseases.gud.Placeholder.step()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.diseases.gud.GUD(pars=None, init_prev_data=None, **kwargs)
Bases: Infection
stisim.diseases.gud.GUD.step_state()
Update states
stisim.diseases.gud.GUD.set_prognoses(uids, source_uids=None)
Set initial prognoses for adults newly infected with syphilis
stisim.diseases.hiv
Define HIV disease module
stisim.diseases.hiv.HIV(pars=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.hiv.HIV.init_results()
Initialize results
stisim.diseases.hiv.HIV.init_post()
Set states
stisim.diseases.hiv.HIV.acute_decline(uids)
Acute decline in CD4
stisim.diseases.hiv.HIV.falling_decline(uids)
Decline in CD4 during late-stage infection, when counts are falling
stisim.diseases.hiv.HIV.post_art_decline(uids)
Decline in CD4 after going off treatment This implementation has the possibly-undesirable feature that a person who goes on ART for a year and then off again might have a slightly shorter lifespan than if they'd never started treatment.
stisim.diseases.hiv.HIV.cd4_increase(uids)
Increase CD4 counts for people who are receiving treatment. Growth curves are calculated to match EMODs CD4 reconstitution equation for people who initiate treatment with a CD4 count of 50 (https://docs.idmod.org/projects/emod-hiv/en/latest/hiv-model-healthcare-systems.html) However, here we use a logistic growth function and assume that ART CD4 count depends on CD4 at initiation. Sources:
- https://i-base.info/guides/starting/cd4-increase
- https://www.sciencedirect.com/science/article/pii/S1876034117302022
- https://bmcinfectdis.biomedcentral.com/articles/10.1186/1471-2334-8-20
stisim.diseases.hiv.HIV.init_cd4()
Set CD4 counts
stisim.diseases.hiv.HIV.init_care_seeking()
Set care seeking behavior
stisim.diseases.hiv.HIV.step_state()
Carry out autonomous updates at the start of the timestep (prior to transmission)
stisim.diseases.hiv.HIV.step_die(uids)
Clear all states for dead agents
stisim.diseases.hiv.HIV.update_transmission()
Update rel_trans and rel_sus for all agents. These are reset on each timestep then adjusted depending on states. Adjustments are made throughout different modules:
- rel_trans for acute and late-stage untreated infection are adjusted below
- rel_trans for all people on treatment (including pregnant women) below
- rel_sus for unborn babies of pregnant WLHIV receiving treatment is adjusted in the ART intervention
stisim.diseases.hiv.HIV.update_results()
Update results at each time step
stisim.diseases.hiv.HIV.set_prognoses(uids, sources=None, ti=None)
Set prognoses upon infection
stisim.diseases.hiv.HIV.start_art(uids)
Check who is ready to start ART treatment and put them on ART
stisim.diseases.hiv.HIV.stop_art(uids=None)
Check who is stopping ART treatment and put them off ART
stisim.diseases.sti
Template class for SEIS-type STIs Used for chlamydia, gonorrhea, and trich
stisim.diseases.sti.BaseSTI(name=None, pars=None, init_prev_data=None, **kwargs)
Bases: Infection
Base class for sexually transmitted infections. Modifies make_new_cases to account for barrier protection.
stisim.diseases.sti.BaseSTI.treatable
property
Assume infected people are treatable, can be overwritten in subclasses
stisim.diseases.sti.BaseSTI.make_init_prev(uids=None, data=None, active=True)
Initialize prevalence by sex and risk group
stisim.diseases.sti.BaseSTI.agehist(a)
Return an age histogram
stisim.diseases.sti.BaseSTI.init_results()
Initialize results
stisim.diseases.sti.BaseSTI.infect()
Determine who gets infected on this timestep via transmission on the network
stisim.diseases.sti.SEIS(pars=None, name=None, init_prev_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.sti.SEIS.treatable
property
Active bacterial presence -- includes exposed and infected, and responds to treatment
stisim.diseases.sti.SEIS.init_results()
Initialize results
stisim.diseases.sti.SEIS.step_state()
Updates for this timestep
stisim.diseases.sti.SEIS.wipe_dates(uids)
Clear all previous dates
stisim.diseases.sti.SEIS.set_prognoses(uids, sources=None)
Set initial prognoses for adults newly infected
stisim.diseases.syphilis
Define syphilis disease module
stisim.diseases.syphilis.SyphilisPlaceholder(pars=None, **kwargs)
Bases: Disease
stisim.diseases.syphilis.SyphilisPlaceholder.step_state()
When using a connector to the syphilis module, this is not needed. The connector should update the syphilis-positive state.
stisim.diseases.syphilis.Syphilis(pars=None, name='syph', init_prev_data=None, init_prev_latent_data=None, **kwargs)
Bases: BaseSTI
stisim.diseases.syphilis.Syphilis.naive
property
Never exposed
stisim.diseases.syphilis.Syphilis.sus_not_naive
property
Susceptible but with syphilis antibodies, which persist after treatment
stisim.diseases.syphilis.Syphilis.mat_active
property
Definition of infection used for maternal transmission, includes exposed + primary + secondary stages
stisim.diseases.syphilis.Syphilis.active
property
Active infection includes primary and secondary stages
stisim.diseases.syphilis.Syphilis.infectious
property
Infectious
stisim.diseases.syphilis.Syphilis.ulcerative
property
Has a visible genital ulcer (chancre at a visible site during primary stage)
stisim.diseases.syphilis.Syphilis.symptomatic
property
Has noticeable symptoms: visible ulcer or visible rash
stisim.diseases.syphilis.Syphilis.infect()
Override to use rel_trans=1 for maternal transmission. Stage-specific rel_trans (primary >> latent) only applies to sexual transmission. For MTC, all infected stages transmit equally since spirochetemia during pregnancy affects the fetus regardless of the mother's clinical stage.
stisim.diseases.syphilis.Syphilis.init_post()
Make initial cases
stisim.diseases.syphilis.Syphilis.init_results()
Initialize results
stisim.diseases.syphilis.Syphilis.step_state()
Updates to states
stisim.diseases.syphilis.Syphilis.step_die(uids)
Clear all states and dates for dead agents (including NND/stillborn babies)
stisim.diseases.syphilis.Syphilis.set_prognoses(uids, source_uids=None, ti=None)
Set initial prognoses for adults newly infected with syphilis. Note: congenital infections are routed to set_congenital by starsim's set_outcomes(), so only adult infections reach this method.
stisim.diseases.syphilis.Syphilis.set_secondary_prognoses(uids)
Set prognoses for people who have just progressed to secondary infection
stisim.diseases.syphilis.Syphilis.set_congenital(target_uids, source_uids=None)
Natural history of syphilis for congenital infection. Birth outcomes depend on the mother's disease stage: mat_active (exposed|primary|secondary), early latent, late latent.
stisim.diseases.trichomoniasis
Trichomoniasis disease module
stisim.diseases.trichomoniasis.Trichomoniasis(pars=None, name='tv', init_prev_data=None, **kwargs)
Bases: SEIS
stisim.diseases.trichomoniasis.Trichomoniasis.set_duration(p, symp, asymp, pid)
Overwrite duration setting with persistence for female asymptomatic infection
stisim.interventions
stisim.interventions.STIDx(df, disease, *args, **kwargs)
Bases: Product
Generic class for diagnostics with a positive/negative outcome Uses bernoulli sampling, so can only be used for tests with binary outcomes Results vary depending on agents' true underlying health state
stisim.interventions.STIDx.administer(sim, uids)
Administer a testing product.
stisim.interventions.STITest(pars=None, test_prob_data=None, years=None, start=None, stop=None, eligibility=None, product=None, name=None, label=None, **kwargs)
Bases: Intervention
Base class for STI testing.
Controls who gets tested, how often, and with what diagnostic product.
Each timestep, eligible agents are tested with a probability derived from
test_prob_data. By default (dt_scale=True), test_prob_data is interpreted
as an annual testing probability and converted to a per-timestep
probability via ss.probperyear. This correctly recovers the annual
probability over a full year of timesteps (e.g. test_prob_data=0.24 with
monthly dt gives ~2.26% per month, recovering exactly 24% per year).
If you need to specify a per-timestep probability directly (not an annual probability), set dt_scale=False: - test_prob_data=0.5, dt_scale=False → 50% chance per timestep
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
diagnostic product (e.g. STIDx, HIVDx) that determines test outcomes (sensitivity, specificity). If None, subclasses supply a default (e.g. HIVTest uses a perfect HIVDx). For STITest, a product is required. |
None
|
|
test_prob_data
|
annual testing probability (if dt_scale=True, the default)
or per-timestep probability (if dt_scale=False). Accepts a
scalar (constant probability), an array (one value per
entry in |
None
|
|
years
|
array
|
calendar years corresponding to entries in test_prob_data when test_prob_data is an array. Mutually exclusive with start. |
None
|
start
|
float
|
calendar year when the intervention activates (inclusive). Defaults to the first simulation year. |
None
|
stop
|
float
|
calendar year when the intervention deactivates (inclusive). Defaults to the last simulation year. |
None
|
eligibility
|
function |
None
|
|
rel_test
|
relative testing probability multiplier (default 1.0) |
required | |
dt_scale
|
if True (default), interpret test_prob_data as an annual probability. Set to False to interpret test_prob_data as a per-timestep probability. |
required |
States set on agents
tested (bool): ever tested diagnosed (bool): ever diagnosed positive ti_tested (float): timestep of last test ti_scheduled (float): timestep of next scheduled test ti_positive (float): timestep of last positive result ti_negative (float): timestep of last negative result tests (float): cumulative number of tests received
stisim.interventions.STITest.state_list
property
Include products in the state list
stisim.interventions.STITest.make_test_prob_fn(sim, uids)
staticmethod
Testing probabilites over time
stisim.interventions.STITest.get_testers(sim)
Find who tests by applying eligibility and coverage/uptake
stisim.interventions.STITest.step(uids=None)
Apply the testing intervention
stisim.interventions.SymptomaticTesting(pars=None, treatments=None, diseases=None, disease_treatment_map=None, negative_treatments=None, treat_prob_data=None, years=None, start=None, stop=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
Base class for symptomatic testing with multiple possible etiologies Unlike other test classes, this doesn't return positive/negative outcomes, since syndromic management doesn't involve reaching a diagnosis. Rather, the testing intervention itself contains a linked treatment intervention.
stisim.interventions.SymptomaticTesting.step(uids=None)
Apply syndromic management
stisim.interventions.STITreatment(name=None, pars=None, diseases=None, eligibility=None, max_capacity=None, years=None, *args, **kwargs)
Bases: Intervention
Base class for treatment of STI infection. The majority of STI treatments will clear infection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
|
None
|
|
disease
|
str
|
should match the name of one of the diseases in the simulation |
required |
stisim.interventions.STITreatment.get_candidates(sim)
Get people who are willing to accept treatment
stisim.interventions.STITreatment.set_treat_eff(uids)
Can be changed by derived classes
stisim.interventions.STITreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment, keeping track of unnecessarily treated individuals
stisim.interventions.STITreatment.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.interventions.STITreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.interventions.PartnerNotification(eligibility, test, test_prob=0.5, **kwargs)
Bases: Intervention
:param disease: The disease module from which to draw the transmission tree used to find contacts
:param eligible: A function f(sim) that returns the UIDs/BoolArr of people to trace (typically people who just tested positive)
:param test: The testing intervention to use when testing identified contacts
:param test_prob: The probability of a contact being identified and accepting a test
:param kwargs: Other arguments passed to ss.Intervention
stisim.interventions.ProductMix(df, excl_cols=None, *args, **kwargs)
Bases: Product
Generic class for algorithms that determine which product a person will receive Uses ss.choice() sampling, which is slower than bernoulli, when there are more than two options The test that agents are given does NOT depend on their underlying health state.
stisim.interventions.ProductMix.administer(sim, uids)
Apply a testing algorithm
stisim.interventions.treat_BV(*args, pars=None, eligibility=None, **kwargs)
Bases: Intervention
Treat BV
stisim.interventions.treat_BV.tx_cst1_change_duration(uids)
Calculate and set the duration of transitioning to a stable CST 1 based on douching and menstrual hygiene practices for individual agents.
stisim.interventions.HIVTest(product=None, pars=None, test_prob_data=None, years=None, start=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
HIV-specific testing intervention.
Tests eligible agents for HIV; positive results set hiv.diagnosed=True, which is a prerequisite for ART initiation. By default, only undiagnosed agents are eligible.
The testing → diagnosis → ART pipeline works as follows:
1. HIVTest tests eligible agents each timestep (annual probability, converted via ss.probperyear)
2. Positive results set hiv.diagnosed=True and hiv.ti_diagnosed
3. ART checks for newly diagnosed agents (ti_diagnosed == current ti)
4. Newly diagnosed agents initiate ART with probability art_initiation
5. If coverage data is provided, ART corrects to match targets
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
test_prob_data
|
annual testing probability (if dt_scale=True, the default). A value of 0.1 means ~10% of eligible agents tested per year. To specify a per-timestep probability instead, set dt_scale=False. |
None
|
|
eligibility
|
func
|
who can be tested. Default: undiagnosed agents. |
None
|
start
|
float
|
calendar year when testing begins |
None
|
dt_scale
|
bool
|
if True (default), test_prob_data is an annual probability. Set to False for per-timestep probability. |
required |
Example::
# Test 20% of undiagnosed agents per year starting in 2000
test = sti.HIVTest(test_prob_data=0.2, start=2000, name='hiv_test')
# Test everyone every timestep (per-timestep probability)
test = sti.HIVTest(test_prob_data=1.0, dt_scale=False, name='hiv_test')
# FSW-targeted testing at higher rate
fsw_test = sti.HIVTest(
test_prob_data=0.5,
name='fsw_test',
eligibility=lambda sim: sim.networks.structuredsexual.fsw & ~sim.diseases.hiv.diagnosed,
)
stisim.interventions.ART(pars=None, coverage=None, coverage_data=None, **kwargs)
Bases: Intervention
Antiretroviral therapy intervention.
Requires HIVTest (or equivalent) to diagnose agents first — ART only initiates agents who have hiv.diagnosed=True. A warning is raised if no HIVTest is found in the sim.
Processing flow each timestep
- Agents scheduled to stop ART are removed
- Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
- If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
- If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
- Mothers on ART protect unborn infants (rel_sus=0) via MaternalNet
Coverage can be specified in several formats
- None: no coverage target; treat all who initiate (default)
- Scalar (e.g. 0.8): constant proportion of infected on ART
- Dict: {'year': [2000, 2020], 'value': [0, 0.9]} — linearly interpolated
- DataFrame: index=years, column 'n_art' (absolute numbers) or 'p_art' (proportion of infected). Values are linearly interpolated to the sim yearvec.
- Stratified DataFrame: columns Year, Gender/Sex, AgeBin (format '[lo,hi)'), plus a numeric value column. Values are interpolated per stratum.
Intervention ordering: HIVTest must appear before ART in the interventions list so that agents diagnosed this timestep can initiate ART in the same step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None) |
None
|
|
art_initiation
|
probability a newly diagnosed person initiates ART (default: ss.bernoulli(p=0.9)). Set to 1 to treat all diagnosed. |
required |
Example::
# Simple: 80% of infected on ART
art = sti.ART(coverage=0.8)
# Time-varying coverage
art = sti.ART(coverage={'year': [2000, 2010, 2025], 'value': [0, 0.5, 0.9]})
# No coverage target — 90% of newly diagnosed initiate (default art_initiation)
art = sti.ART()
# Treat ALL diagnosed with no coverage constraint
art = sti.ART(art_initiation=1)
# From a CSV file
art = sti.ART(coverage=pd.read_csv('art_coverage.csv').set_index('year'))
stisim.interventions.ART.step()
Apply ART at each timestep: stop ART for those scheduled, initiate for newly diagnosed, and correct overall coverage to match targets.
stisim.interventions.ART.prioritize_art(sim, n=None, awaiting_art_uids=None)
Prioritize ART to n agents among those awaiting treatment
stisim.interventions.ART.art_coverage_correction(sim, target_coverage=None)
Adjust ART coverage to match data
stisim.interventions.VMMC(pars=None, coverage=None, coverage_data=None, eligibility=None, **kwargs)
Bases: Intervention
Voluntary medical male circumcision.
Reduces male susceptibility to HIV acquisition by eff_circ (default 60%). Unlike ART, VMMC does not require diagnosis — it circumcises males up to a coverage target, prioritized by willingness (a random per-agent score).
If no coverage is specified, VMMC does nothing. Coverage must be provided explicitly via the coverage parameter.
Coverage formats (same as ART): - Scalar: constant proportion of males (e.g. 0.3) - Dict: {'year': [...], 'value': [...]} — linearly interpolated - DataFrame: index=years, column 'n_vmmc' or 'p_vmmc' - Stratified DataFrame: Year/Gender/AgeBin columns
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None; VMMC does nothing without coverage data) |
None
|
|
eff_circ
|
efficacy (default 0.6 = 60% reduction in HIV acquisition) |
required | |
eligibility
|
optional function to restrict who is eligible (default: all males) |
None
|
Example::
vmmc = sti.VMMC(coverage=0.3)
vmmc = sti.VMMC(coverage={'year': [2010, 2025], 'value': [0, 0.4]})
stisim.interventions.Prep(pars=None, eligibility=None, **kwargs)
Bases: Intervention
Pre-exposure prophylaxis (PrEP).
By default targets HIV-negative FSWs who are not already on PrEP. Reduces HIV susceptibility by eff_prep (default 80%). Coverage ramps up over time according to the years/coverage parameters (linearly interpolated). Use the eligibility parameter to target a different population.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
list
|
coverage values at each year (default [0, 0.01, 0.5, 0.8]) |
required |
years
|
list
|
corresponding calendar years (default [2004, 2005, 2015, 2025]) |
required |
eff_prep
|
float
|
efficacy (default 0.8 = 80% reduction in acquisition) |
required |
eligibility
|
function to override default FSW targeting |
None
|
Example::
prep = sti.Prep(coverage=[0, 0.5], years=[2020, 2025])
stisim.interventions.GonorrheaTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: STITreatment
Treatment for gonorrhea infection. - successful treatment clears infection immediately - unsuccessful treatment reduces dur_inf and rel_trans, but results in lower rel_treat - unnecessary treatment results in lower rel_treat
stisim.interventions.GonorrheaTreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.interventions.UpdateDrugs(pars=None, eligibility=None, years=None, *args, **kwargs)
Bases: Intervention
An intervention that samples rel_treat and updates the rel_treat values if they fall below a given level.
stisim.interventions.SyphTx(pars=None, max_capacity=None, years=None, eligibility=None, name=None, **kwargs)
Bases: STITreatment
Treat a fixed number of people each timestep.
stisim.interventions.SyphTx.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.interventions.SyphTx.treat_fetus(sim, mother_uids)
Treat fetuses of successfully treated mothers. Birth outcomes of successfully treated fetuses will be updated. If fetus is not yet infected, the treatment doesn't do anything. Treatment success depends on when in the pregnancy the mother gets treated with reduced treatment efficacy above the cut off age
stisim.interventions.SyphTx.step()
Apply treatment
stisim.interventions.NewbornTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: SyphTx
stisim.interventions.NewbornTreatment.change_states(disease, treat_succ)
Change states of congenital cases
stisim.interventions.NewbornTreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment to newborns
stisim.interventions.SyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: STITest
Base class for syphilis tests
stisim.interventions.SyphTest.process_data(sim)
Turn dataframe into a dictionary
stisim.interventions.SyphTest.make_test_prob_fn(sim, uids)
staticmethod
Process symptomatic testing probabilites over time by sex and risk group
stisim.interventions.ANCSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to pregnant women Need to adjust timing using Trivedi (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7138526/)
stisim.interventions.ANCSyphTest.schedule_tests()
Schedule a test for newly pregnant women
stisim.interventions.NewbornSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to newborns if the mother was confirmed to have syphilis at any stage of the pregnancy
stisim.interventions.base_interventions
Define interventions for STIsim
stisim.interventions.base_interventions.STIDx(df, disease, *args, **kwargs)
Bases: Product
Generic class for diagnostics with a positive/negative outcome Uses bernoulli sampling, so can only be used for tests with binary outcomes Results vary depending on agents' true underlying health state
stisim.interventions.base_interventions.STIDx.administer(sim, uids)
Administer a testing product.
stisim.interventions.base_interventions.STITest(pars=None, test_prob_data=None, years=None, start=None, stop=None, eligibility=None, product=None, name=None, label=None, **kwargs)
Bases: Intervention
Base class for STI testing.
Controls who gets tested, how often, and with what diagnostic product.
Each timestep, eligible agents are tested with a probability derived from
test_prob_data. By default (dt_scale=True), test_prob_data is interpreted
as an annual testing probability and converted to a per-timestep
probability via ss.probperyear. This correctly recovers the annual
probability over a full year of timesteps (e.g. test_prob_data=0.24 with
monthly dt gives ~2.26% per month, recovering exactly 24% per year).
If you need to specify a per-timestep probability directly (not an annual probability), set dt_scale=False: - test_prob_data=0.5, dt_scale=False → 50% chance per timestep
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
diagnostic product (e.g. STIDx, HIVDx) that determines test outcomes (sensitivity, specificity). If None, subclasses supply a default (e.g. HIVTest uses a perfect HIVDx). For STITest, a product is required. |
None
|
|
test_prob_data
|
annual testing probability (if dt_scale=True, the default)
or per-timestep probability (if dt_scale=False). Accepts a
scalar (constant probability), an array (one value per
entry in |
None
|
|
years
|
array
|
calendar years corresponding to entries in test_prob_data when test_prob_data is an array. Mutually exclusive with start. |
None
|
start
|
float
|
calendar year when the intervention activates (inclusive). Defaults to the first simulation year. |
None
|
stop
|
float
|
calendar year when the intervention deactivates (inclusive). Defaults to the last simulation year. |
None
|
eligibility
|
function |
None
|
|
rel_test
|
relative testing probability multiplier (default 1.0) |
required | |
dt_scale
|
if True (default), interpret test_prob_data as an annual probability. Set to False to interpret test_prob_data as a per-timestep probability. |
required |
States set on agents
tested (bool): ever tested diagnosed (bool): ever diagnosed positive ti_tested (float): timestep of last test ti_scheduled (float): timestep of next scheduled test ti_positive (float): timestep of last positive result ti_negative (float): timestep of last negative result tests (float): cumulative number of tests received
stisim.interventions.base_interventions.STITest.state_list
property
Include products in the state list
stisim.interventions.base_interventions.STITest.make_test_prob_fn(sim, uids)
staticmethod
Testing probabilites over time
stisim.interventions.base_interventions.STITest.get_testers(sim)
Find who tests by applying eligibility and coverage/uptake
stisim.interventions.base_interventions.STITest.step(uids=None)
Apply the testing intervention
stisim.interventions.base_interventions.SymptomaticTesting(pars=None, treatments=None, diseases=None, disease_treatment_map=None, negative_treatments=None, treat_prob_data=None, years=None, start=None, stop=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
Base class for symptomatic testing with multiple possible etiologies Unlike other test classes, this doesn't return positive/negative outcomes, since syndromic management doesn't involve reaching a diagnosis. Rather, the testing intervention itself contains a linked treatment intervention.
stisim.interventions.base_interventions.SymptomaticTesting.step(uids=None)
Apply syndromic management
stisim.interventions.base_interventions.STITreatment(name=None, pars=None, diseases=None, eligibility=None, max_capacity=None, years=None, *args, **kwargs)
Bases: Intervention
Base class for treatment of STI infection. The majority of STI treatments will clear infection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
|
None
|
|
disease
|
str
|
should match the name of one of the diseases in the simulation |
required |
stisim.interventions.base_interventions.STITreatment.get_candidates(sim)
Get people who are willing to accept treatment
stisim.interventions.base_interventions.STITreatment.set_treat_eff(uids)
Can be changed by derived classes
stisim.interventions.base_interventions.STITreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment, keeping track of unnecessarily treated individuals
stisim.interventions.base_interventions.STITreatment.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.interventions.base_interventions.STITreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.interventions.base_interventions.PartnerNotification(eligibility, test, test_prob=0.5, **kwargs)
Bases: Intervention
:param disease: The disease module from which to draw the transmission tree used to find contacts
:param eligible: A function f(sim) that returns the UIDs/BoolArr of people to trace (typically people who just tested positive)
:param test: The testing intervention to use when testing identified contacts
:param test_prob: The probability of a contact being identified and accepting a test
:param kwargs: Other arguments passed to ss.Intervention
stisim.interventions.base_interventions.ProductMix(df, excl_cols=None, *args, **kwargs)
Bases: Product
Generic class for algorithms that determine which product a person will receive Uses ss.choice() sampling, which is slower than bernoulli, when there are more than two options The test that agents are given does NOT depend on their underlying health state.
stisim.interventions.base_interventions.ProductMix.administer(sim, uids)
Apply a testing algorithm
stisim.interventions.bv_interventions
Define BV interventions
stisim.interventions.bv_interventions.treat_BV(*args, pars=None, eligibility=None, **kwargs)
Bases: Intervention
Treat BV
stisim.interventions.bv_interventions.treat_BV.tx_cst1_change_duration(uids)
Calculate and set the duration of transitioning to a stable CST 1 based on douching and menstrual hygiene practices for individual agents.
stisim.interventions.gonorrhea_interventions
Define gonorrhea interventions for STIsim
stisim.interventions.gonorrhea_interventions.GonorrheaTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: STITreatment
Treatment for gonorrhea infection. - successful treatment clears infection immediately - unsuccessful treatment reduces dur_inf and rel_trans, but results in lower rel_treat - unnecessary treatment results in lower rel_treat
stisim.interventions.gonorrhea_interventions.GonorrheaTreatment.step()
Apply treatment. On each timestep, this method will add eligible people who are willing to accept treatment to a queue, and then will treat as many people in the queue as there is capacity for.
stisim.interventions.gonorrhea_interventions.UpdateDrugs(pars=None, eligibility=None, years=None, *args, **kwargs)
Bases: Intervention
An intervention that samples rel_treat and updates the rel_treat values if they fall below a given level.
stisim.interventions.hiv_interventions
Define HIV interventions for STIsim By default, these all have units of a year and timesteps of 1/12
stisim.interventions.hiv_interventions.HIVTest(product=None, pars=None, test_prob_data=None, years=None, start=None, eligibility=None, name=None, label=None, **kwargs)
Bases: STITest
HIV-specific testing intervention.
Tests eligible agents for HIV; positive results set hiv.diagnosed=True, which is a prerequisite for ART initiation. By default, only undiagnosed agents are eligible.
The testing → diagnosis → ART pipeline works as follows:
1. HIVTest tests eligible agents each timestep (annual probability, converted via ss.probperyear)
2. Positive results set hiv.diagnosed=True and hiv.ti_diagnosed
3. ART checks for newly diagnosed agents (ti_diagnosed == current ti)
4. Newly diagnosed agents initiate ART with probability art_initiation
5. If coverage data is provided, ART corrects to match targets
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
test_prob_data
|
annual testing probability (if dt_scale=True, the default). A value of 0.1 means ~10% of eligible agents tested per year. To specify a per-timestep probability instead, set dt_scale=False. |
None
|
|
eligibility
|
func
|
who can be tested. Default: undiagnosed agents. |
None
|
start
|
float
|
calendar year when testing begins |
None
|
dt_scale
|
bool
|
if True (default), test_prob_data is an annual probability. Set to False for per-timestep probability. |
required |
Example::
# Test 20% of undiagnosed agents per year starting in 2000
test = sti.HIVTest(test_prob_data=0.2, start=2000, name='hiv_test')
# Test everyone every timestep (per-timestep probability)
test = sti.HIVTest(test_prob_data=1.0, dt_scale=False, name='hiv_test')
# FSW-targeted testing at higher rate
fsw_test = sti.HIVTest(
test_prob_data=0.5,
name='fsw_test',
eligibility=lambda sim: sim.networks.structuredsexual.fsw & ~sim.diseases.hiv.diagnosed,
)
stisim.interventions.hiv_interventions.ART(pars=None, coverage=None, coverage_data=None, **kwargs)
Bases: Intervention
Antiretroviral therapy intervention.
Requires HIVTest (or equivalent) to diagnose agents first — ART only initiates agents who have hiv.diagnosed=True. A warning is raised if no HIVTest is found in the sim.
Processing flow each timestep
- Agents scheduled to stop ART are removed
- Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
- If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
- If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
- Mothers on ART protect unborn infants (rel_sus=0) via MaternalNet
Coverage can be specified in several formats
- None: no coverage target; treat all who initiate (default)
- Scalar (e.g. 0.8): constant proportion of infected on ART
- Dict: {'year': [2000, 2020], 'value': [0, 0.9]} — linearly interpolated
- DataFrame: index=years, column 'n_art' (absolute numbers) or 'p_art' (proportion of infected). Values are linearly interpolated to the sim yearvec.
- Stratified DataFrame: columns Year, Gender/Sex, AgeBin (format '[lo,hi)'), plus a numeric value column. Values are interpolated per stratum.
Intervention ordering: HIVTest must appear before ART in the interventions list so that agents diagnosed this timestep can initiate ART in the same step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None) |
None
|
|
art_initiation
|
probability a newly diagnosed person initiates ART (default: ss.bernoulli(p=0.9)). Set to 1 to treat all diagnosed. |
required |
Example::
# Simple: 80% of infected on ART
art = sti.ART(coverage=0.8)
# Time-varying coverage
art = sti.ART(coverage={'year': [2000, 2010, 2025], 'value': [0, 0.5, 0.9]})
# No coverage target — 90% of newly diagnosed initiate (default art_initiation)
art = sti.ART()
# Treat ALL diagnosed with no coverage constraint
art = sti.ART(art_initiation=1)
# From a CSV file
art = sti.ART(coverage=pd.read_csv('art_coverage.csv').set_index('year'))
stisim.interventions.hiv_interventions.ART.step()
Apply ART at each timestep: stop ART for those scheduled, initiate for newly diagnosed, and correct overall coverage to match targets.
stisim.interventions.hiv_interventions.ART.prioritize_art(sim, n=None, awaiting_art_uids=None)
Prioritize ART to n agents among those awaiting treatment
stisim.interventions.hiv_interventions.ART.art_coverage_correction(sim, target_coverage=None)
Adjust ART coverage to match data
stisim.interventions.hiv_interventions.VMMC(pars=None, coverage=None, coverage_data=None, eligibility=None, **kwargs)
Bases: Intervention
Voluntary medical male circumcision.
Reduces male susceptibility to HIV acquisition by eff_circ (default 60%). Unlike ART, VMMC does not require diagnosis — it circumcises males up to a coverage target, prioritized by willingness (a random per-agent score).
If no coverage is specified, VMMC does nothing. Coverage must be provided explicitly via the coverage parameter.
Coverage formats (same as ART): - Scalar: constant proportion of males (e.g. 0.3) - Dict: {'year': [...], 'value': [...]} — linearly interpolated - DataFrame: index=years, column 'n_vmmc' or 'p_vmmc' - Stratified DataFrame: Year/Gender/AgeBin columns
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
coverage target in any format above (default None; VMMC does nothing without coverage data) |
None
|
|
eff_circ
|
efficacy (default 0.6 = 60% reduction in HIV acquisition) |
required | |
eligibility
|
optional function to restrict who is eligible (default: all males) |
None
|
Example::
vmmc = sti.VMMC(coverage=0.3)
vmmc = sti.VMMC(coverage={'year': [2010, 2025], 'value': [0, 0.4]})
stisim.interventions.hiv_interventions.Prep(pars=None, eligibility=None, **kwargs)
Bases: Intervention
Pre-exposure prophylaxis (PrEP).
By default targets HIV-negative FSWs who are not already on PrEP. Reduces HIV susceptibility by eff_prep (default 80%). Coverage ramps up over time according to the years/coverage parameters (linearly interpolated). Use the eligibility parameter to target a different population.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coverage
|
list
|
coverage values at each year (default [0, 0.01, 0.5, 0.8]) |
required |
years
|
list
|
corresponding calendar years (default [2004, 2005, 2015, 2025]) |
required |
eff_prep
|
float
|
efficacy (default 0.8 = 80% reduction in acquisition) |
required |
eligibility
|
function to override default FSW targeting |
None
|
Example::
prep = sti.Prep(coverage=[0, 0.5], years=[2020, 2025])
stisim.interventions.hiv_interventions.parse_coverage(data, valid_names=None, yearvec=None)
Parse coverage data into a per-timestep array.
Accepts multiple input formats and normalizes them into (coverage_array, coverage_format, age_bins, sex_keys) where: - coverage_array: 1D array (len=yearvec) for aggregate, or dict of arrays for stratified - coverage_format: 'n' (absolute numbers) or 'p' (proportion) - age_bins: list of (lo, hi) tuples if stratified, else None - sex_keys: list of sex values if stratified, else None
Supported input formats
None → (None, None, None, None) 0.9 → constant proportion {'year': [...], 'value': [...]} → interpolated, infer format {'year': [...], 'value': [...], 'format': 'n'} → interpolated, explicit format pd.DataFrame(index=years, columns=['n_art']) → legacy single-column pd.DataFrame(columns=['Year','Gender','AgeBin',...]) → age/sex stratified
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
coverage input in any supported format |
required | |
valid_names
|
list of valid column names, e.g. ['n_art', 'p_art'] |
None
|
|
yearvec
|
simulation year vector for interpolation |
None
|
stisim.interventions.syphilis_interventions
Define syphilis interventions for STIsim
stisim.interventions.syphilis_interventions.SyphTx(pars=None, max_capacity=None, years=None, eligibility=None, name=None, **kwargs)
Bases: STITreatment
Treat a fixed number of people each timestep.
stisim.interventions.syphilis_interventions.SyphTx.change_states(disease, treat_succ)
Change the states of people who are treated
stisim.interventions.syphilis_interventions.SyphTx.treat_fetus(sim, mother_uids)
Treat fetuses of successfully treated mothers. Birth outcomes of successfully treated fetuses will be updated. If fetus is not yet infected, the treatment doesn't do anything. Treatment success depends on when in the pregnancy the mother gets treated with reduced treatment efficacy above the cut off age
stisim.interventions.syphilis_interventions.SyphTx.step()
Apply treatment
stisim.interventions.syphilis_interventions.NewbornTreatment(pars=None, eligibility=None, max_capacity=None, years=None, name=None, *args, **kwargs)
Bases: SyphTx
stisim.interventions.syphilis_interventions.NewbornTreatment.change_states(disease, treat_succ)
Change states of congenital cases
stisim.interventions.syphilis_interventions.NewbornTreatment.administer(sim, uids, disease, return_format='dict')
Administer treatment to newborns
stisim.interventions.syphilis_interventions.SyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: STITest
Base class for syphilis tests
stisim.interventions.syphilis_interventions.SyphTest.process_data(sim)
Turn dataframe into a dictionary
stisim.interventions.syphilis_interventions.SyphTest.make_test_prob_fn(sim, uids)
staticmethod
Process symptomatic testing probabilites over time by sex and risk group
stisim.interventions.syphilis_interventions.ANCSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to pregnant women Need to adjust timing using Trivedi (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7138526/)
stisim.interventions.syphilis_interventions.ANCSyphTest.schedule_tests()
Schedule a test for newly pregnant women
stisim.interventions.syphilis_interventions.NewbornSyphTest(test_prob_data=None, years=None, start=None, stop=None, pars=None, product=None, eligibility=None, name=None, label=None, newborn_test=None, **kwargs)
Bases: SyphTest
Test given to newborns if the mother was confirmed to have syphilis at any stage of the pregnancy
stisim.networks
Define sexual network for STI transmission.
Overview:
-
Risk groups: agents are randomly assigned into one of 3 main risk groups:
- 0 = marry and remain married to a single partner throughout their lifetime
- 1 = marry and then divorce or who have concurrent partner(s) during their marriage
- 2 = never marry
-
In addition, a proportion of each of the groups above engages in sex work.
stisim.networks.StructuredSexual(pars=None, condom_data=None, name=None, **kwargs)
Bases: SexualNetwork
Structured sexual network
stisim.networks.StructuredSexual.set_risk_groups(upper_age=None)
Assign each person to a risk group
stisim.networks.StructuredSexual.set_concurrency(upper_age=None)
Assign each person a preferred number of simultaneous partners
stisim.networks.StructuredSexual.match_pairs()
Match pairs by age, using sorting rather than the linear sum assignment
stisim.networks.StructuredSexual.match_sex_workers()
Match sex workers to clients
stisim.networks.StructuredSexual.set_condom_use()
Set condom use
stisim.networks.StructuredSexual.count_partners()
Count the number of partners each person has had over the past 3/12 months
stisim.networks.PriorPartners(pars=None, name='priorpartners', **kwargs)
Bases: DynamicNetwork
Lightweight network for storing prior partners, for use in partner notification In this network, 'dur' refers to the duration of time since the relationship ended
stisim.networks.AgeMatchedMSM(pars=None, **kwargs)
Bases: StructuredSexual
stisim.networks.AgeMatchedMSM.match_pairs()
Match males by age using sorting
stisim.networks.AgeApproxMSM(**kwargs)
Bases: StructuredSexual
stisim.networks.AgeApproxMSM.match_pairs(ppl)
Match pairs using age preferences
stisim.parameters
Set parameters
stisim.parameters.SimPars(**kwargs)
Bases: SimPars
Subclass of Starsim's SimPars with defaults for STI simulations. Refer to Starsim's SimPars for more information on the parameters.
stisim.parameters.sti_aliases()
Define aliases for STIs
stisim.parameters.sti_register(key=None)
Registry of STI names linked to disease classes
stisim.parameters.merged_sti_pars()
Merge all the parameters from the STI disease modules
stisim.parameters.make_sti(name, pars=None)
Create an STI disease module based on the name and parameters provided.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the STI disease module to create. |
required |
pars
|
dict
|
Parameters to initialize the disease module with. |
None
|
Returns:
| Type | Description |
|---|---|
|
ss.Disease: An instance of the specified STI disease module. |
stisim.parameters.mergepars(*args)
Merge all parameter dictionaries into a single dictionary. This is used to initialize the SimPars class with all relevant parameters. It wraps the sc.mergedicts function to ensure all inputs are dicts
stisim.parameters.dem_pars()
Return a dictionary with all parameters used within demographic modules
stisim.sim
stisim.sim.Sim(pars=None, sim_pars=None, sti_pars=None, nw_pars=None, dem_pars=None, label=None, people=None, demographics=None, diseases=None, networks=None, interventions=None, analyzers=None, connectors=None, custom=None, datafolder=None, data=None, **kwargs)
Bases: Sim
A subclass of starsim.Sim that is specifically designed for STI simulations. It initializes with a structured sexual network and includes STI-specific analyzers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pars
|
dict
|
Parameters for the simulation |
None
|
label
|
str
|
A label for the simulation. |
None
|
people
|
People
|
People object containing the agents in the simulation. |
None
|
demographics
|
(Demographics, list)
|
Demographic modules to include. |
None
|
diseases
|
(Disease, list)
|
Disease modules to include. |
None
|
networks
|
(Network, list)
|
Network modules to include. |
None
|
interventions
|
(Intervention, list)
|
Intervention modules to include. |
None
|
analyzers
|
(Analyzer, list)
|
Analyzer modules to include. |
None
|
connectors
|
bool or list
|
If True, use default connectors; otherwise, provide a list of connectors. |
None
|
copy_inputs
|
bool
|
Whether to copy input parameters or not. |
required |
data
|
Additional data to be used in the simulation. |
None
|
|
e.g.
|
|
required | |
Example usage
|
|
required | |
# demographics, and connectors. If you want to specify parameters for the diseases, you can do so like this
|
|
required | |
You can also pass in custom parameters for the default modules, such as networks or demographics, like this
|
|
required | |
These are all in addition to the standard starsim input style using module instances directly, e.g.
|
|
required | |
and in the kwargs), the order of precedence is as follows
|
|
required |
stisim.sim.Sim.separate_pars(pars=None, sim_pars=None, sti_pars=None, nw_pars=None, dem_pars=None, sim_kwargs=None, **kwargs)
Create a nested dict of parameters that get passed to Sim constructor and the component modules Prioritization: - If any key appears in both pars and _pars, the value from _pars will be used. - If any key appears in both pars and kwargs, the value from kwargs will be used.
stisim.sim.Sim.remap_pars(pars)
staticmethod
Remap any parameter names to match the expected format for STIs and networks. This is useful for ensuring that parameters are correctly interpreted by the modules.
stisim.sim.Sim.init(force=False, **kwargs)
Perform all initializations for the sim
stisim.sim.Sim.plot(key=None, **kwargs)
Plot sim results. If key is the name of a disease in the sim (e.g. 'hiv'), shows a curated panel for that disease. Otherwise falls back to the standard starsim plot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str / list
|
Result key(s) to plot, or a disease name for curated plots |
None
|
**kwargs
|
Passed to ss.Sim.plot() |
{}
|
Returns:
| Type | Description |
|---|---|
|
matplotlib.figure.Figure |
stisim.sim.Sim.process_networks()
Process the network parameters to create network module. If networks are provided, they will be used; otherwise, use default networks (usual case)
stisim.sim.Sim.process_demographics()
Process the location to create people and demographics if not provided.
stisim.sim.Sim.process_stis()
Look up a disease by its name and return the corresponding module.
stisim.sim.Sim.process_connectors()
Get the default connectors for the diseases in the simulation.
Connectors are loaded based on the disease names or modules provided in the format
stisim.sim.Sim.case_insensitive_getattr(searchspace, attrname)
Find a class in the given package that matches the name, ignoring case.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
searchspace
|
list
|
A list of classes or modules to search through. |
required |
attrname
|
str
|
The name of the attribute to find, case-insensitive. |
required |
stisim.stidata
Load data
stisim.stidata.get_age_distribution(location=None, year=None, datafolder=None)
Load age distribution for a given location & year
stisim.stidata.get_rates(location, which, datafolder=None)
Load birth/death/fertility/migration rates for a given location
stisim.stidl
Download data needed for STIsim.
To use this, you will need to get an auth_key from the UN Data Portal API.
stisim.stidl.get_filename(location, indicator, year=None)
Get the filename for a given location, indicator, and year.
stisim.stidl.check_downloaded(location, indicators=None, year=None, verbose=1)
Check if data is downloaded for this location Args: location (str): the location to check indicators (list): the indicators to check for; if None, checks all verbose (int): detail to print (0 = none, 1 = reason for failure, 2 = everything)
stisim.stidl.get_country_aliases()
Define aliases for countries
stisim.stidl.get_country_code(df, location)
Find a match between the data file and the provided location.
stisim.stidl.download_data(location, indicators=None, start=1950, stop=2100, step=10)
Download data
stisim.stidl.get_available(base_url, auth_key, which, filename=None, do_save=True)
Save a list of indicators or locations to a csv file
stisim.utils
STIsim utilities
stisim.utils.TimeSeries(t=None, vals=None, units=None, assumption=None, sigma=None)
Class to store time-series data
Internally values are stored as lists rather than numpy arrays because
insert/remove operations on lists tend to be faster (and working with sparse
data is a key role of TimeSeries objects). Note that methods like :meth:interpolate()
return numpy arrays, so the output types from such functions should generally match up
with what is required by the calling function.
:param t: Optionally specify a scalar, list, or array of time values
:param vals: Optionally specify a scalar, list, or array of values (must be same size as t)
:param units: Optionally specify units (as a string)
:param assumption: Optionally specify a scalar assumption
:param sigma: Optionally specify a scalar uncertainty
stisim.utils.TimeSeries.has_data
property
Check if any data has been provided
:return: True if any data has been entered (assumption or time-specific)
stisim.utils.TimeSeries.has_time_data
property
Check if time-specific data has been provided
Unlike has_data, this will return False if only an assumption has been entered
:return: True if any time-specific data has been entered
stisim.utils.TimeSeries.__eq__(other)
Check TimeSeries equality
Two TimeSeries instances are equal if all of their attributes are equal. This is easy to
implement because == is directly defined for all of the attribute types (lists and scalars)
and due to __slots__ there are guaranteed not to be any other attributes
:param other: :return:
stisim.utils.TimeSeries.copy()
Return a copy of the TimeSeries
:return: An independent copy of the TimeSeries
stisim.utils.TimeSeries.insert(t, v)
Insert a value or list of at a particular time
If the value already exists in the TimeSeries, it will be overwritten/updated.
The arrays are internally sorted by time value, and this order will be maintained.
:param t: Time value to insert or update. If None, the value will be assigned to the assumption
:param v: Value to insert. If None, this function will return immediately without doing anything
stisim.utils.TimeSeries.get(t)
Retrieve value at a particular time
This function will automatically retrieve the value of the assumption if no time specific values have been provided, or if any time specific values are provided, will return the value entered at that time. If time specific values have been entered and the requested time is not explicitly present, an error will be raised.
This function may be deprecated in future because generally it is more useful
to either call TimeSeries.interpolate() if interested in getting values at
arbitrary times, or TimeSeries.get_arrays() if interested in retrieving
values that have been entered.
:param t: A time value. If None, will return assumption regardless of whether
time data has been entered or not
:return: The value at the corresponding time. Returns None if the value no value present
stisim.utils.TimeSeries.get_arrays()
Return arrays with the contents of this TimeSeries
The TimeSeries instance may have time values, or may simply have
an assumption. If obtaining raw arrays is desired, this function will
return arrays with values extracted from the appropriate attribute of the
TimeSeries. However, in general, it is usually .interpolate() that is
desired, rather than .get_arrays()
:return: Tuple with two arrays - the first item is times (with a single NaN if the TimeSeries only has an assumption) and the second item is values
stisim.utils.TimeSeries.remove(t)
Remove single time point
:param t: Time value to remove. Set to None to remove the assumption
stisim.utils.TimeSeries.remove_before(t_remove)
Remove times from start
:param tval: Remove times up to but not including this time
stisim.utils.TimeSeries.remove_after(t_remove)
Remove times from start
:param tval: Remove times up to but not including this time
stisim.utils.TimeSeries.remove_between(t_remove)
Remove a range of times
Note that the endpoints are not included
:param t_remove: two element iterable e.g. array, with [min,max] times
stisim.utils.TimeSeries.interpolate(t2, method='linear', **kwargs)
Return interpolated values
This method returns interpolated values from the time series at time points t2
according to a given interpolation method. There are 4 possibilities for the method
- 'linear' - normal linear interpolation (with constant, zero-gradient extrapolation)
- 'pchip' - legacy interpolation with some curvature between points (with constant, zero-gradient extrapolation)
- 'previous' - stepped interpolation, maintain value until the next timepoint is reached (with constant, zero-gradient extrapolation)
- Interpolation class or generator function
That final option allows the use of arbitrary interpolation methods. The underlying call will be::
c = method(t1, v1, **kwargs)
return c(t2)
so for example, if you wanted to use the base Scipy pchip method with no extrapolation, then could pass in::
TimeSeries.interpolate(...,method=scipy.interpolate.PchipInterpolator)
Note that the following special behaviours apply:
- If there is no data at all, this function will return
np.nanfor all requested time points - If only an assumption exists, this assumption will be returned for all requested time points
-
Otherwise, arrays will be formed with all finite time values
- If no finite time values remain, an error will be raised (in general, a TimeSeries should not store such values anyway)
- If only one finite time value remains, then that value will be returned for all requested time points
- Otherwise, the specified interpolation method will be used
:param t2: float, list, or array, with times :param method: A string 'linear', 'pchip' or 'previous' OR a callable item that returns an Interpolator :return: array the same length as t2, with interpolated values
stisim.utils.TimeSeries.sample(constant=True)
Return a sampled copy of the TimeSeries
This method returns a copy of the TimeSeries in which the values have been perturbed based on the uncertainty value.
:param constant: If True, time series will be perturbed by a single constant offset. If False,
an different perturbation will be applied to each time specific value independently.
:return: A copied TimeSeries with perturbed values
stisim.version
Version and license information.