Skip to content

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_pars for 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. {'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05)}

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 all.

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 _full suffix first.

True
n_results int

Number of top results to keep when shrinking. Default: len(self.df) // 10 (minimum 1).

None
save_pars bool

If True (default), also save calib.df.

True
pars_filename str / Path

Path for the parameter DataFrame. If None, uses {stem}_pars.df next to filename.

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_pars for 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. {'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05)}

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 all.

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 _full suffix first.

True
n_results int

Number of top results to keep when shrinking. Default: len(self.df) // 10 (minimum 1).

None
save_pars bool

If True (default), also save calib.df.

True
pars_filename str / Path

Path for the parameter DataFrame. If None, uses {stem}_pars.df next to filename.

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 years), or a DataFrame (subclass-specific, e.g. SymptomaticTesting accepts risk-group-stratified DataFrames). Default: 1.0 (test all eligible agents per year).

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 f(sim) -> BoolArr or f(sim) -> UIDs defining who can be tested. Can filter on any agent property, e.g. lambda sim: sim.people.female & (sim.people.age > 15). Default: all agents (subclasses may override, e.g. HIVTest defaults to undiagnosed agents only).

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
  1. Agents scheduled to stop ART are removed
  2. Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
  3. If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
  4. If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
  5. 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.nan for 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 'module.par' keys.

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. {'hiv.beta_m2f': 0.05, ...}

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 calib.get_pars() and uses calib.sim as the base if sim is not provided.

None
calib_pars

Parameter source — one of:

  • dict: single parameter set → 1 sim (× seeds_per_par)
  • list[dict]: N parameter sets → N sims
  • DataFrame: rows are parameter sets (like calib.df)
None
sim Sim

Base (uninitialized) simulation to copy. If None, uses calib.sim.

None
n_parsets int

Number of top parameter sets to use. None = all.

None
check_fn callable

Post-run filter — check_fn(sim) → bool. Sims returning False are dropped. If None and calib is provided, uses calib.check_fn.

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 check_fn) is kept.

1
**kwargs

Passed to ss.parallel().

{}

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_pars for 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. {'hiv.beta_m2f': dict(low=0.01, high=0.1, guess=0.05)}

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 all.

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 _full suffix first.

True
n_results int

Number of top results to keep when shrinking. Default: len(self.df) // 10 (minimum 1).

None
save_pars bool

If True (default), also save calib.df.

True
pars_filename str / Path

Path for the parameter DataFrame. If None, uses {stem}_pars.df next to filename.

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 'module.par' keys.

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. {'hiv.beta_m2f': 0.05, ...}

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 calib.get_pars() and uses calib.sim as the base if sim is not provided.

None
calib_pars

Parameter source — one of:

  • dict: single parameter set → 1 sim (× seeds_per_par)
  • list[dict]: N parameter sets → N sims
  • DataFrame: rows are parameter sets (like calib.df)
None
sim Sim

Base (uninitialized) simulation to copy. If None, uses calib.sim.

None
n_parsets int

Number of top parameter sets to use. None = all.

None
check_fn callable

Post-run filter — check_fn(sim) → bool. Sims returning False are dropped. If None and calib is provided, uses calib.check_fn.

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 check_fn) is kept.

1
**kwargs

Passed to ss.parallel().

{}

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 years), or a DataFrame (subclass-specific, e.g. SymptomaticTesting accepts risk-group-stratified DataFrames). Default: 1.0 (test all eligible agents per year).

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 f(sim) -> BoolArr or f(sim) -> UIDs defining who can be tested. Can filter on any agent property, e.g. lambda sim: sim.people.female & (sim.people.age > 15). Default: all agents (subclasses may override, e.g. HIVTest defaults to undiagnosed agents only).

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
  1. Agents scheduled to stop ART are removed
  2. Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
  3. If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
  4. If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
  5. 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 years), or a DataFrame (subclass-specific, e.g. SymptomaticTesting accepts risk-group-stratified DataFrames). Default: 1.0 (test all eligible agents per year).

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 f(sim) -> BoolArr or f(sim) -> UIDs defining who can be tested. Can filter on any agent property, e.g. lambda sim: sim.people.female & (sim.people.age > 15). Default: all agents (subclasses may override, e.g. HIVTest defaults to undiagnosed agents only).

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
  1. Agents scheduled to stop ART are removed
  2. Newly diagnosed agents (ti_diagnosed == this timestep) are filtered by art_initiation probability
  3. If coverage is specified: agents are added/removed to match the target number, prioritized by CD4 count and care-seeking propensity
  4. If no coverage is specified: all newly diagnosed who pass art_initiation go directly on ART (no capacity constraint)
  5. 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.nan for 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.