interventions
Interventions, which change the course of a sim during a run
Interventions typically include things like testing, treatment, and vaccination. An event (ss.Event) moves the people it reaches, on a schedule or when another event happens, e.g. seeding infections; a delivery (ss.Delivery, and ss.vaccinate(), ss.screen(), and ss.treat()) is an event that gives a product. Both exist so that the same intervention can be written once and run under any solver. It also works with a disease written as code, as agents.
Used with: agents and compartments; declared and coded modules
Classes
| Name | Description |
|---|---|
| Delivery | Deliver a product to people: an ss.Event with what only interventions need; see ss.vaccinate(), ss.screen(), and ss.treat() |
| Event | Something that happens to people: a move between states, on a schedule or when another event happens; see ss.Delivery to deliver a product |
| Intervention | Base class for interventions written as code |
| at_age | Who an event reaches: people as they reach an age, as its who=; e.g. ss.vaccinate(who=ss.at_age(ss.months(9))) |
| capacity | How many a delivery can serve, who is served first, and what happens to the rest, as its capacity= |
| screen | Deliver a diagnostic test; see ss.Delivery for the arguments |
| treat | Deliver a treatment; see ss.Delivery for the arguments |
| vaccinate | Deliver a vaccine; see ss.Delivery for the arguments |
Delivery
interventions.Delivery(
what=None,
who=None,
when=None,
coverage=None,
capacity=None,
strain=None,
increment=None,
trace=None,
skip_reached_within=None,
disease=None,
start=None,
stop=None,
name=None,
label=None,
**kwargs,
)Deliver a product to people: an ss.Event with what only interventions need; see ss.vaccinate(), ss.screen(), and ss.treat()
Who and when are as for ss.Event. What is delivered is a product (an ss.Vaccine, ss.Diagnostic, or ss.Treatment, or one written as code, an ss.Product with an administer(uids) method), or a move, as for an event, which a campaign can make (e.g. dict(vaccinated=True)). How many is said as for services: coverage=, the fraction reached, and capacity=, how many can be served, with ss.capacity() for who is served first and whether the rest wait. With an event as when=, the delivery reaches the people it happened to: an outcome of another delivery (when=screening.positive) on the same step, a transition of a disease (when=tb.care) on the next, since deliveries run before the diseases in each step.
A delivery is an event too, and so is each outcome of its product (a test’s positive and negative, a cure’s cured, failed, and unneeded): a follow-up is a delivery of its own, triggered by one (ss.treat(drug, when=screening.positive)), and runs after it in the same step.
Its methods are how it runs as agents; in a compartmental run, what differs is delivery.in_compartments (see ss.solvers.CompartmentalDelivery).
Note: CRN safe as agents.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| what | Product / Transition / dict |
what is delivered: a product, or a move as for ss.Event; ss.vaccinate(), ss.screen(), and ss.treat() instead take the product’s own keywords and make it, e.g. ss.vaccinate(efficacy=0.9, ...) |
None |
| who | Cond / func / at_age |
who is eligible, as for ss.Event |
None |
| when | date / list / dur / event / func / schedule |
when it is delivered, as for ss.Event: in rounds (times, or ss.schedule(), e.g. with every=), on an event (with ss.on(event, delay=...) for a time after it, which is the time from the trigger to delivery, drawn per person if a distribution, agents only), or with none, routinely: each person is offered it once, at the first step they are eligible |
None |
| start | date / float / dur |
the start of a window it is delivered in, with any when=, as for ss.Event: e.g. when=onset, start=2001, on an event from 2001 |
None |
| stop | date / float / dur |
the end of the window, likewise | None |
| coverage | float / rate / func |
the fraction of those eligible who are reached; also ss.by(...), a typed rate or probability (e.g. ss.perday(0.1), ss.probperyear(0.5)): the chance over the step or the round (and, for routine delivery, offered at every step to those eligible); or a function of the sim, called at each step, returning one of these or, as agents, a probability for each person: an array over everyone alive, in the order of sim.people.uid, or an ss.Arr, read by UID; only the values of those eligible are used |
None |
| capacity | float / rate / capacity |
how many can be served: a number per round (or per step, for delivery on events), or a rate (e.g. ss.peryear(50_000)), which routine delivery needs; or ss.capacity(n, priority=..., queue=...), also saying who is served first and whether the rest wait. A capacity is for a service limited by supply or staff, rather than by how many come forward |
None |
| strain | str / Strain |
with a move into a state where people carry a strain, the strain they arrive with | None |
| increment | str / dict |
instead of a product, a counter that goes up for those reached, as for ss.Event |
None |
| trace | str / Network / list |
contact tracing: deliver to the contacts, in this network (or these), of the people the event in when= reaches, instead of to them; who= and coverage= then apply to the contacts. Agents only. A network with memory= also gives the partnerships of that long ago that have ended (e.g. ss.DegreeNet(..., memory=ss.months(12))) |
None |
| skip_reached_within | dur |
skip the people this delivery reached less than this long ago (agents only), e.g. ss.years(1) for a re-screening interval; the same as who=~(delivery.since < ss.years(1)), which the delivery cannot name before it exists |
None |
| disease | str / list |
the disease the product acts on (default: the only one); or a list of them, for one product that acts on several (e.g. a bivalent vaccine), delivered once | None |
| name | str |
the name; if not given, taken from the variable it is assigned to | None |
| label | str |
a human-readable name | None |
Examples
# A campaign that leaves a mark, for 70% of the unvaccinated in two rounds
rollout = ss.Delivery(dict(vaccinated=True), coverage=0.7, when=[5, 30], who=~sir.vaccinated)
# A test, and a treatment of those who test positive, as two deliveries
screening = ss.screen(sensitivity=0.9, specificity=0.95, who=ss.person.age > 30, coverage=0.4, when=ss.schedule(every=ss.days(7)))
treatment = ss.treat(cure=0.95, when=screening.positive, coverage=0.8)
# Routine vaccination at nine months, from 2025 (the same as when=ss.schedule(start=2025))
mcv1 = ss.vaccinate(efficacy=0.85, who=ss.at_age(ss.months(9)), coverage=0.8, start=2025)
# Testing those with symptoms, from 2001 to 2010
testing = ss.screen(sensitivity=0.9, when=sir.infection, coverage=0.3, start=2001, stop=2010)Event
interventions.Event(
what=None,
who=None,
when=None,
n=None,
p=None,
strain=None,
increment=None,
start=None,
stop=None,
name=None,
label=None,
**kwargs,
)Something that happens to people: a move between states, on a schedule or when another event happens; see ss.Delivery to deliver a product
An event has three parts, each optional. What happens to those it reaches: a move between two states (S >> I), levels of a stratification (dict(risk=('low', 'high'))), or strains (DS >> RIF), or an increment of a counter; with none, it is only an event, which others trigger on (e.g. a clinic visit). Who it reaches: a condition on people, or on the population (sir.I.n > 1000, which decides for everyone at once), or people as they reach an age (ss.at_age()). And when: at times (when=[2025, 2030], when='2024-03-01', or when=ss.days(30), 30 days after the start), on a schedule (when=ss.schedule(every=ss.months(1), start='2024-01-01', stop='2025-01-01')), when another event happens (when=sir.infection, or when=ss.on(sir.infection, delay=ss.days(5))), or, with no when=, routinely: each person once, at the first step they are eligible. start= and stop= limit any of these to a window (the same as when=ss.schedule(start=..., stop=...) for routine events), e.g. when=screening.positive, start=2001.
n= and p= say how many it reaches each time, as for ss.move(): at most n of those eligible, chosen at random, and each with probability p.
It is an event itself: others trigger on it (when=seeding), and it remembers per person whether (.ever), how often (.n_times), and how long ago (.since) it happened. event.reached() is the UIDs of the people it reached on the step (agents only).
Note: CRN safe as agents.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| what | Transition / dict / str |
what happens to those it reaches: a move between states (S >> I, from any of several, U + P >> P, or by the paths of the states, 'sir.S >> sir.I'), a move to a level of a stratification (dict(vaccinated=True)) or from one level to another (dict(risk=('low', 'high'))), or a change of strains (DS >> RIF) |
None |
| who | Cond / func / at_age |
who it can reach: a condition on people (ss.person.age < 5, or a state by its path, 'sir.I'), on the population (sir.I.n > 1000), or both joined with &; people as they reach an age (ss.at_age(ss.months(9))); or a function of the sim returning who is eligible (UIDs, a mask, or True or False for everyone); to reach exactly those it returns at each step, also give when= every step |
None |
| when | date / list / dur / event / func / schedule |
when it happens: a time or list of them (dates, years, or durations after the start of the sim: ss.days(10) is 10 days in, and with no calendar day 10); an event that triggers it (sir.infection, screening.positive, or a transition by its path), or ss.on(event, delay=...) for a time after it; a function of the date of each step, true when it happens; or ss.schedule(), for how often (every=), or any of these with a start= and stop= (with only those, routinely between them) |
None |
| start | date / float / dur |
the start of a window it happens in, with any when= (e.g. on an event, from 2001): a shorthand for when=ss.schedule(start=...) that also goes with an event (default: the start of the sim) |
None |
| stop | date / float / dur |
the end of the window, likewise (default: the end of the sim) | None |
| n | float / rate |
the most it reaches each time: a number, or a rate (e.g. ss.peryear(20)), which routine events need, since they have no rounds for a number to be per |
None |
| p | float / rate / func |
the probability that each person eligible is reached; also ss.by(...), a typed rate or probability (e.g. ss.perday(0.1)), or a function of the sim returning one, or (as agents) one per person |
None |
| strain | str / Strain |
with a move into a state where people carry a strain (e.g. S >> E), the strain they arrive with |
None |
| increment | str / dict |
instead of a move, a counter that goes up for those reached: its name, which adds 1, or a dict of the amount for each | None |
| name | str |
the name; if not given, taken from the variable it is assigned to | None |
| label | str |
a human-readable name | None |
Examples
# Seeding: three people, chosen from everyone susceptible, infected every 30 days for ten years
seeds = ss.Event(S >> I, n=3, when=ss.schedule(every=ss.days(30), start=ss.days(30), stop=ss.years(10)))
# A new strain on a date
alpha = ss.Event(S >> E, n=20, when='2021-01-01', strain='alpha')
# Twenty importations a year, for the first five years
imports = ss.Event(S >> I, n=ss.peryear(20), stop=ss.years(5))
# Moving people to high risk, five days after infection, half of them
risky = ss.Event(dict(risk=('low', 'high')), when=ss.on(sir.infection, delay=ss.days(5)), p=0.5)
# Each round of a campaign adds a dose (with sim.stratify(doses=[0, 1, 2, 3]))
campaign = ss.Event(increment='doses', p=0.6, when=[2025, 2026, 2027])Attributes
| Name | Description |
|---|---|
| age_years | With at_age=: the age, in years |
| cost | The cost of each delivery: its product’s |
| dis | The disease the product acts on: declared, or written as code |
| disease | The disease whose engine evaluates the conditions: as given, else the one whose states move= names, else the first that the product names, else the first declared disease its conditions name |
| dt_sim | The timestep, in the sim’s unit |
| eng | The engine of the disease, which applies its effects (see ss.solvers.Effects) |
| event_owners | What fires its events: the delivery, and its product if it has one |
| holds | Whether people hold what is delivered |
| in_rounds | Whether it is given in rounds (at times, or every so often), rather than routinely or on an event |
| move_arrow | With move= between states: the move, as written (S >> V) |
| move_names | With move= between states: the names of the states it moves people from, and the one it moves them to |
| offered | The name of the property of people that records who has been offered it (see remembers) |
| remembers | Whether the model has to record who has been offered the product; not if everyone eligible receives something they then hold for good, nor for a rate among those eligible |
| routine | Whether each person is offered the product once, at the first step on which they are eligible |
| selector | The selector of the disease’s engine, which evaluates the delivery’s conditions |
| span | The time this delivery stands for now: the step, or the round |
| tabulated | Whether a compartmental run can apply this delivery in the compiled kernels, for the whole run at once (fast), rather than step by |
| waits | Whether the results of the test it delivers come after a delay |
Methods
| Name | Description |
|---|---|
| add | Add people to a result (and to its part for one disease and transition): agents by UID, or people by group |
| age_reason | With at_age=: why a compartmental run cannot deliver it, or None. As compartments, people reach the age by aging from |
| agent_reasons | The reasons, if any, that this delivery needs agents (a priority per agent is ignored by a compartmental solver that was asked for, with a note: see key()) |
| arrivals | Who is offered it now, before eligibility: everyone, or those its event happened to (with a delay, those it happened to the delay ago) |
| boxed | Whether holding the product has the levels of a boxcar in this sim: in a compartmental run, for a product that wanes as an ss.boxcar (see ss.products.Held.boxcar_form) |
| check_coded | For a disease written as code: agents only, and it has the parts the product uses, or this raises naming the missing one |
| convert | Convert a typed quantity to a plain number in the sim’s unit |
| cure | Move the people treated along the transitions of the treatment (see ss.Treatment), and record the outcomes as results |
| default_eligible | Who is eligible if nothing is said: for a treatment that is not triggered, the people it can cure (those in the sources of its moves, or who are infected) |
| delay_steps | The number of steps from the trigger to delivery, with a fixed delay (when=ss.on(…, delay=…), at least one) |
| delayed_arrivals | With a delay (when=ss.on(event, delay=…); agents only): those triggered since its last step start waiting (unless waiting already), and those whose wait is over arrive |
| describe | A line saying what is delivered and how |
| dim_moves | Movement along those properties that happens by itself: losing the protection of a product (at a rate, or through the levels of a boxcar) |
| dims | The properties of people that this delivery needs, as stratifications where everyone starts at the first level |
| due | Whether it acts on this step: within its window, on one of its rounds (if it has them), and when its when= function holds (if it has one) |
| edge_prob | The probability of moving along one of the treatment’s transitions: its own (a number, or a dict by state), times the modifiers of the transition if it is undriven (scalar, per agent, or per state and group) |
| edge_sources | The condition of being in a source state of a transition the treatment moves people along |
| eligible_now | Who can receive it now: eligible, in a state a move is from (or carrying the strains a change of strains is from), not holding it already (unless held=False, or its protection fades by a function of time, when a new dose restarts it), and not at the level a transfer moves them to |
| fire | Record an event of this delivery, which is one of its product too (see ss.products.EventSource) |
| follow | Move the selected people to other levels of some dimensions; returns those chosen among them, as they now are |
| give | Deliver the product to the people chosen, and record them (and the outcomes) as its events |
| hold | Those chosen now hold the product: at level 1, or with doses (doses=), the next dose |
| infected_states | The infected states of the disease, which a test with no detects= finds and a treatment with no who= is for; raises if there are none |
| init_pre | Find the disease and the product, check them against the sim, and set up what is delivered |
| init_results | The number delivered, eligible, and covered on each step, and the cost, capacity lost, outcomes, and queue, as it has them |
| key | The order in which each agent, or each state and group, is served (lowest first), or None for a random order: a |
| key_product | For a delivery for several diseases (disease=[...]): their names, as the sim has them, and the product keyed by them |
| limit | The most people that can be served now: what is left of the capacity this step |
| mark_offered | Record that the selected people have been offered the product; returns those chosen, as they now are |
| marks | When the delivery acts, as times on the results’ time axis, for marking on plots (see sim.plot()): a list of times |
| max_wait | The most steps anyone waits (inf for queue=True) |
| moved_edges | The transitions the product moves people along, as (disease, transition) names, once initialized |
| n_agents | As agents, the number of agents selected |
| n_selected | The number of people selected, as results count them (see ss.results.people_scale()) |
| new_spells | Routine delivery is once per spell of being eligible: those offered it who are no longer eligible can be offered it again when they are |
| offer | Those of some people who are eligible: not holding the product already, not yet offered it (for routine delivery), and so on |
| outcome_names | The names of its outcomes, which are events and results: its product’s, and never_ran for a queue with a limit |
| people | The number of people selected, whatever the results count in |
| per_state | A value for each state (each a number or an ss.by), as a value for each agent, or each state and group (of eng, the delivery’s disease by default) |
| receive | Offer the product to some people: those eligible among them, thinned by coverage, served within capacity, and recorded as offered it |
| record_events | The coverage of what was delivered in the step |
| report | Count the results, from the least severe (see ss.Diagnostic.result_names), and record the people with each as an event, which the steps that follow it act on |
| row | The row of the results by group that time point ti is in |
| score | A priority given as a score (served highest first), per agent or per state and group |
| serve | Who is served now, of those chosen (and those waiting, with queue=), within what is left of the capacity; returns those offered and those served |
| serve_queue | Serve those waiting and those just chosen, by priority and then by how long they have waited; the rest wait, until queue= |
| shift | Move the selected people to other levels of some dimensions (mover is the event they are, if known, which a compartmental run uses) |
| skip_past | For at_age=: the people already past the age are recorded as offered it, so only those who reach the age get it: on its |
| step | Deliver the product to whoever it is due to in this step (at its time point, as for all code in a step: see ss.loop.Loop), before the disease’s transitions in it, under every solver |
| step_results | Act on the test results that have become available (agents only) |
| take | Choose n people (a number of people, not agents) from the candidates, in the order of priority=: as agents, |
| tally | Add the people selected to a result, in total and by group; returns the total |
| test | Work out the result of each test (one draw per person, from the probability of each result: see ss.Diagnostic.tails()), and either act on it or wait for it |
| tiebreak | A random number per agent, the same for every choice of the step (from the delivery’s own stream, so scenarios stay paired) |
| trigger_disease | The disease of the first transition or delivery in the event that triggers this delivery, if any |
| typed_function | Whether the coverage is a function of the sim that gives a typed rate (e.g. lambda sim: ss.peryear(4)): worked out the first time it can be called |
| uids | As agents, the UIDs of the agents selected |
| use | Record the people served, against the capacity of the step |
| used_now | The number of people served so far in this step, against the capacity |
add
interventions.Event.add(key, uids=None, groups=None, part=None)Add people to a result (and to its part for one disease and transition): agents by UID, or people by group
age_reason
interventions.Event.age_reason(sim)With at_age=: why a compartmental run cannot deliver it, or None. As compartments, people reach the age by aging from the age group below it into the one it starts, so the sim needs age groups with an edge at the age. It is an error rather than a reason for solver='auto' to run as agents (see ss.solvers.init_capabilities()), since a comparison with a baseline without it would then compare two solvers.
agent_reasons
interventions.Event.agent_reasons(sim)The reasons, if any, that this delivery needs agents (a priority per agent is ignored by a compartmental solver that was asked for, with a note: see key())
arrivals
interventions.Event.arrivals()Who is offered it now, before eligibility: everyone, or those its event happened to (with a delay, those it happened to the delay ago)
boxed
interventions.Event.boxed(sim)Whether holding the product has the levels of a boxcar in this sim: in a compartmental run, for a product that wanes as an ss.boxcar (see ss.products.Held.boxcar_form)
check_coded
interventions.Event.check_coded(sim)For a disease written as code: agents only, and it has the parts the product uses, or this raises naming the missing one
convert
interventions.Event.convert(val)Convert a typed quantity to a plain number in the sim’s unit
cure
interventions.Event.cure(chosen)Move the people treated along the transitions of the treatment (see ss.Treatment), and record the outcomes as results and events: each person in a source of one of a disease’s moves along it with its probability (cured), or does not (failed); one in none is unneeded.
default_eligible
interventions.Event.default_eligible()Who is eligible if nothing is said: for a treatment that is not triggered, the people it can cure (those in the sources of its moves, or who are infected)
delay_steps
interventions.Event.delay_steps(sim)The number of steps from the trigger to delivery, with a fixed delay (when=ss.on(…, delay=…), at least one)
delayed_arrivals
interventions.Event.delayed_arrivals()With a delay (when=ss.on(event, delay=…); agents only): those triggered since its last step start waiting (unless waiting already), and those whose wait is over arrive
It runs whether or not its trigger has run in the step (see order_steps()), so it reads the events of the step before that it has not read yet (those of deliveries that run after it), then those of this step. A wait is at least a step: one drawn as less (including zero) ends on the step after the trigger.
describe
interventions.Event.describe()A line saying what is delivered and how
dim_moves
interventions.Event.dim_moves(sim=None)Movement along those properties that happens by itself: losing the protection of a product (at a rate, or through the levels of a boxcar)
dims
interventions.Event.dims(sim=None)The properties of people that this delivery needs, as stratifications where everyone starts at the first level
due
interventions.Event.due()Whether it acts on this step: within its window, on one of its rounds (if it has them), and when its when= function holds (if it has one)
edge_prob
interventions.Event.edge_prob(e, eng, state=None)The probability of moving along one of the treatment’s transitions: its own (a number, or a dict by state), times the modifiers of the transition if it is undriven (scalar, per agent, or per state and group)
edge_sources
interventions.Event.edge_sources()The condition of being in a source state of a transition the treatment moves people along
eligible_now
interventions.Event.eligible_now(held=True)Who can receive it now: eligible, in a state a move is from (or carrying the strains a change of strains is from), not holding it already (unless held=False, or its protection fades by a function of time, when a new dose restarts it), and not at the level a transfer moves them to
fire
interventions.Event.fire(outcome, sel, eng=None, before=None)Record an event of this delivery, which is one of its product too (see ss.products.EventSource)
follow
interventions.Event.follow(sel, chosen, changes, mover=None)Move the selected people to other levels of some dimensions; returns those chosen among them, as they now are
give
interventions.Event.give(chosen, capped=False)Deliver the product to the people chosen, and record them (and the outcomes) as its events
hold
interventions.Event.hold(chosen)Those chosen now hold the product: at level 1, or with doses (doses=), the next dose
infected_states
interventions.Event.infected_states()The infected states of the disease, which a test with no detects= finds and a treatment with no who= is for; raises if there are none
init_pre
interventions.Event.init_pre(sim)Find the disease and the product, check them against the sim, and set up what is delivered
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | Sim | the sim being initialized | required |
init_results
interventions.Event.init_results()The number delivered, eligible, and covered on each step, and the cost, capacity lost, outcomes, and queue, as it has them
key
interventions.Event.key(strict=False)The order in which each agent, or each state and group, is served (lowest first), or None for a random order: a condition’s people (or the first of a list’s) first, then the next; or the highest score first
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strict | bool |
in a compartmental run, raise ss.CapabilityError for a priority that is per agent, rather than ignoring it with a note |
False |
key_product
interventions.Event.key_product(sim)For a delivery for several diseases (disease=[...]): their names, as the sim has them, and the product keyed by them
limit
interventions.Event.limit()The most people that can be served now: what is left of the capacity this step
mark_offered
interventions.Event.mark_offered(sel, chosen)Record that the selected people have been offered the product; returns those chosen, as they now are
marks
interventions.Event.marks()When the delivery acts, as times on the results’ time axis, for marking on plots (see sim.plot()): a list of times (for each round, up to 10 of them) or of (start, stop) pairs (for routine delivery, or more rounds, from a start or to a stop within the run); none for delivery on an event, a condition, or a function, whose times are not fixed
max_wait
interventions.Event.max_wait(sim)The most steps anyone waits (inf for queue=True)
moved_edges
interventions.Event.moved_edges()The transitions the product moves people along, as (disease, transition) names, once initialized
n_agents
interventions.Event.n_agents(sel)As agents, the number of agents selected
n_selected
interventions.Event.n_selected(sel)The number of people selected, as results count them (see ss.results.people_scale())
new_spells
interventions.Event.new_spells()Routine delivery is once per spell of being eligible: those offered it who are no longer eligible can be offered it again when they are
offer
interventions.Event.offer(sel)Those of some people who are eligible: not holding the product already, not yet offered it (for routine delivery), and so on
outcome_names
interventions.Event.outcome_names()The names of its outcomes, which are events and results: its product’s, and never_ran for a queue with a limit
people
interventions.Event.people(sel)The number of people selected, whatever the results count in
per_state
interventions.Event.per_state(values, what, eng=None)A value for each state (each a number or an ss.by), as a value for each agent, or each state and group (of eng, the delivery’s disease by default)
receive
interventions.Event.receive(sel)Offer the product to some people: those eligible among them, thinned by coverage, served within capacity, and recorded as offered it
record_events
interventions.Event.record_events()The coverage of what was delivered in the step
report
interventions.Event.report(sels)Count the results, from the least severe (see ss.Diagnostic.result_names), and record the people with each as an event, which the steps that follow it act on
row
interventions.Event.row(ti)The row of the results by group that time point ti is in
score
interventions.Event.score(val)A priority given as a score (served highest first), per agent or per state and group
serve
interventions.Event.serve(sel, chosen)Who is served now, of those chosen (and those waiting, with queue=), within what is left of the capacity; returns those offered and those served
serve_queue
interventions.Event.serve_queue(sel, chosen)Serve those waiting and those just chosen, by priority and then by how long they have waited; the rest wait, until queue=
shift
interventions.Event.shift(sel, changes, mover=None)Move the selected people to other levels of some dimensions (mover is the event they are, if known, which a compartmental run uses)
skip_past
interventions.Event.skip_past()For at_age=: the people already past the age are recorded as offered it, so only those who reach the age get it: on its first step, everyone past it (as agents, older by more than a step; in a compartmental run, everyone in an age group at or above it); and as agents, on each step after, the agents who have arrived since (e.g. immigrants made by people.grow())
step
interventions.Event.step()Deliver the product to whoever it is due to in this step (at its time point, as for all code in a step: see ss.loop.Loop), before the disease’s transitions in it, under every solver
step_results
interventions.Event.step_results()Act on the test results that have become available (agents only)
take
interventions.Event.take(cands, n, carry=False, wait=None)Choose n people (a number of people, not agents) from the candidates, in the order of priority=: as agents, sorted by priority with ties broken at random; as compartments, whole cells in order and pro rata within a tie
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| cands | array |
the candidates, as a selection | required |
| n | float |
the number of people | required |
| carry | bool |
as agents, keep the part of an agent left over for the next step (for a capacity) | False |
| wait | array |
the steps each has waited (per agent, or the level of waiting of each group): longest first, after the priority | None |
tally
interventions.Event.tally(key, sel, weight=1.0)Add the people selected to a result, in total and by group; returns the total
test
interventions.Event.test(chosen)Work out the result of each test (one draw per person, from the probability of each result: see ss.Diagnostic.tails()), and either act on it or wait for it
tiebreak
interventions.Event.tiebreak(uids)A random number per agent, the same for every choice of the step (from the delivery’s own stream, so scenarios stay paired)
trigger_disease
interventions.Event.trigger_disease(sim)The disease of the first transition or delivery in the event that triggers this delivery, if any
typed_function
interventions.Event.typed_function()Whether the coverage is a function of the sim that gives a typed rate (e.g. lambda sim: ss.peryear(4)): worked out the first time it can be called
uids
interventions.Event.uids(sel)As agents, the UIDs of the agents selected
use
interventions.Event.use(served)Record the people served, against the capacity of the step
used_now
interventions.Event.used_now()The number of people served so far in this step, against the capacity
Intervention
interventions.Intervention(*args, who=None, **kwargs)Base class for interventions written as code
Write one when the built-in events and deliveries cannot say what the intervention does. Its key method is step(), called on each timestep, which can change the states of the diseases (e.g. treating or vaccinating agents). To deliver a product, or to move people between states, use ss.vaccinate(), ss.screen(), ss.treat(), or ss.Event() instead, which run under every solver.
An intervention written as code can be given who=, who it can reach, as for a delivery: a condition on people (ss.person.age < 5), or a function of the sim (and of the intervention, as self) returning UIDs or a mask. Its step() then reads the people eligible now with check_eligibility().
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| args | list |
passed to ss.Module |
|
| who | Cond / func |
who it can reach (by default everyone alive), read by check_eligibility() |
None |
| kwargs | dict |
passed to ss.Module |
Example:
class Discount(ss.Intervention):
def step(self):
uids = self.check_eligibility() # Those who= holds for now, alive
self.sim.diseases.sis.rel_trans[uids] = 0.5
sim = ss.Sim(diseases='sis', networks='random', interventions=Discount(who=ss.person.age < 15)).run()Attributes
| Name | Description |
|---|---|
| has_product | Whether the intervention delivers a product |
Methods
| Name | Description |
|---|---|
| check_eligibility | The UIDs of the people eligible now: those alive whom who= holds for (evaluated as a delivery’s who= is), or everyone alive |
| init_pre | Initialize the module, and its product if it has one |
check_eligibility
interventions.Intervention.check_eligibility()The UIDs of the people eligible now: those alive whom who= holds for (evaluated as a delivery’s who= is), or everyone alive
A subclass can override it, for a rule of its own.
init_pre
interventions.Intervention.init_pre(sim)Initialize the module, and its product if it has one
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | Sim | the sim being initialized | required |
at_age
interventions.at_age(age, who=None)Who an event reaches: people as they reach an age, as its who=; e.g. ss.vaccinate(who=ss.at_age(ss.months(9)))
Each person is reached once, at the first step on which they are that age or older; not those already past it when the event starts, nor (as agents) those who arrive past it later, e.g. immigrants. As compartments, people reach it by aging into the age group it starts, so the sim needs age groups with an edge at the age (an error otherwise). Join it to other conditions with &, e.g. ss.at_age(ss.years(9)) & ss.person.female.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| age | dur / float |
the age (a bare number is in years) | required |
| who | Cond |
any other condition on who is reached; usually given by joining with & instead |
None |
capacity
interventions.capacity(n, priority=None, queue=False)How many a delivery can serve, who is served first, and what happens to the rest, as its capacity=
capacity=n is the same as capacity=ss.capacity(n): this is for when there is a priority or a queue too.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| n | float / rate |
the number that can be served: per round (or per step, for delivery triggered by an event or by a function), or a rate (e.g. ss.peryear(50_000)), which routine delivery needs, since it has no rounds for a number to be per; a rate in rounds gives what accrues between them |
required |
| priority | Cond / list / Expr / func |
who is served first: a condition, or a list of them served in order (all of the first, then the second); a score, highest first: an expression (e.g. -hiv.cd4, the lowest CD4 first) or a function of the sim (or of (sim, uids), agents only); or a list of conditions and scores, each breaking the ties of the ones before (e.g. [due, ss.person.age], those due first, and among them the oldest); other ties are broken at random |
None |
| queue | bool / dur |
what happens to those not served (agents only): False (the default), they are lost; True, they wait until served; a duration, they wait at most that long, and those still waiting then are the outcome never_ran. Those waiting are served before anyone newly reached in their class (longest first), and leave the queue if they stop being eligible. A queue is for a service with a waiting list (e.g. treatment slots), where demand turned away comes back rather than being lost |
False |
Examples
art = ss.treat(drug, who=hiv.diagnosed, capacity=ss.capacity(ss.peryear(50_000), priority=-hiv.cd4, queue=True))screen
interventions.screen(
what=None,
who=None,
when=None,
coverage=None,
capacity=None,
strain=None,
increment=None,
trace=None,
skip_reached_within=None,
disease=None,
start=None,
stop=None,
name=None,
label=None,
**kwargs,
)Deliver a diagnostic test; see ss.Delivery for the arguments
when=ss.on(event, delay=...) is the delivery’s, the time from its trigger to the test, as for any delivery; the time from the test to its result is the test’s (ss.Diagnostic(result_delay=...)).
Its outcomes, positive and negative, are events on the step the result is available (after the test’s result_delay), and results: the number with each result on each step. What happens next is a step of its own, triggered by an outcome (when=screening.positive).
Note: CRN safe as agents.
Examples
S, I, R = ss.states(3)
sir = ss.Disease(infection=S >> I @ 0.3*I, recovery=ss.Transition(I, R, dur=10), init_prev=0.01)
screening = ss.screen(sensitivity=0.9, specificity=0.98, coverage=0.4, when=ss.schedule(every=ss.days(7)))
treatment = ss.treat(cure=0.95, when=screening.positive, coverage=0.8)
sim = ss.Sim(sir, interventions=[screening, treatment], stop=100).run()treat
interventions.treat(
what=None,
who=None,
when=None,
coverage=None,
capacity=None,
strain=None,
increment=None,
trace=None,
skip_reached_within=None,
disease=None,
start=None,
stop=None,
name=None,
label=None,
**kwargs,
)Deliver a treatment; see ss.Delivery for the arguments
Note: CRN safe as agents.
Examples
S, I, R = ss.states(3)
sir = ss.Disease(infection=S >> I @ 0.3*I, recovery=ss.Transition(I, R, dur=10), init_prev=0.01)
treatment = ss.treat(cure=0.95, coverage=0.5, when=ss.schedule(every=ss.days(7))) # Makes the drug, ss.Treatment(cure=0.95)
sim = ss.Sim(sir, interventions=treatment, stop=100).run()vaccinate
interventions.vaccinate(
what=None,
who=None,
when=None,
coverage=None,
capacity=None,
strain=None,
increment=None,
trace=None,
skip_reached_within=None,
disease=None,
start=None,
stop=None,
name=None,
label=None,
**kwargs,
)Deliver a vaccine; see ss.Delivery for the arguments
Note: CRN safe as agents.
Examples
S, I, R = ss.states(3)
sir = ss.Disease(infection=S >> I @ 0.3*I, recovery=ss.Transition(I, R, dur=10), init_prev=0.01)
campaign = ss.vaccinate(efficacy=0.85, coverage=0.7, when=[20, 40]) # Makes the vaccine, ss.Vaccine(efficacy=0.85)
sim = ss.Sim(sir, interventions=campaign, stop=100).run()Functions
| Name | Description |
|---|---|
| check_replaced | An error for a keyword that an event or delivery does not take (Starsim 3’s, one of replaced, or one only a delivery takes), saying what to give instead |
| coded_disease | The disease of this name if it is written as code (not declared), else None |
| fired | The people an event happened to on this step (see ss.conditions.Selector.leaf()) |
| flush_memory | At the start of a step: put any events not yet there into the memory |
| memory_needs | The events whose memory something in the sim reads, by (module name, outcome): the kinds read (ever, count, since) |
| modules_of | The modules of a kind (‘interventions’, ‘connectors’, ‘diseases’): the sim’s, once it has them, and before then those in its parameters |
| move_paths | For move= as a string, e.g. ‘sir.S >> sir.V’ or ‘U + B >> B’: the names of the states people move from (a list) and to, and the name of their module (None if not given) |
| movers | The names of the products and deliveries that name a transition: those that move people along it, and those triggered by it |
| order_steps | The interventions in the order they run: each delivery after the deliveries whose events trigger it, so a step acts on |
| parse_when | The when= of an event, as the keywords of Event._init(): nothing (routine), an event that triggers it, times (a date, a year, |
| parse_who | The who= of an event, as the keywords of Event._init(): a condition on people (who=), one on the population (where=), or ss.at_age() |
| product_keys | The keywords of a kind of product (e.g. efficacy and waning for ss.Vaccine), which its delivery takes to make one |
| remembered | The memory of an event for each agent or group: whether (ever), how often (n_times), or how long ago (since, in the sim’s unit) it happened |
| trigger_moves | The transitions triggered by an event of a delivery or product (e.g. ss.Transition(I, R_res, when=drug.failed, p=0.05)): |
check_replaced
interventions.check_replaced(kwargs, cls)An error for a keyword that an event or delivery does not take (Starsim 3’s, one of replaced, or one only a delivery takes), saying what to give instead
coded_disease
interventions.coded_disease(sim, name)The disease of this name if it is written as code (not declared), else None
fired
interventions.fired(selector, cond)The people an event happened to on this step (see ss.conditions.Selector.leaf())
flush_memory
interventions.flush_memory(sim)At the start of a step: put any events not yet there into the memory
memory_needs
interventions.memory_needs(sim)The events whose memory something in the sim reads, by (module name, outcome): the kinds read (ever, count, since)
Found by walking every expression of the interventions, connectors, diseases, and demographics: conditions, rates, p=, dur=, attributes, results, and modifier amounts.
modules_of
interventions.modules_of(sim, key)The modules of a kind (‘interventions’, ‘connectors’, ‘diseases’): the sim’s, once it has them, and before then those in its parameters
move_paths
interventions.move_paths(move, name)For move= as a string, e.g. ‘sir.S >> sir.V’ or ‘U + B >> B’: the names of the states people move from (a list) and to, and the name of their module (None if not given)
movers
interventions.movers(sim, modname, name)The names of the products and deliveries that name a transition: those that move people along it, and those triggered by it
order_steps
interventions.order_steps(mods)The interventions in the order they run: each delivery after the deliveries whose events trigger it, so a step acts on the step its trigger happens; otherwise in the order given. A delivery with a delay (when=ss.on(event, delay=...)) is at least a step after its trigger, so it need not run after it, and may be in a cycle of triggers (e.g. a test repeated a year after a negative result); any other cycle raises.
parse_when
interventions.parse_when(when, name, start=None, stop=None)The when= of an event, as the keywords of Event._init(): nothing (routine), an event that triggers it, times (a date, a year, a duration after the start of the sim, or a list of them), a function of the date, or an ss.schedule() with these, how often, and a start and stop; and the window of start= and stop=, which any of these can have (the same as in ss.schedule(), which then must have none of its own)
parse_who
interventions.parse_who(who)The who= of an event, as the keywords of Event._init(): a condition on people (who=), one on the population (where=), or ss.at_age()
product_keys
interventions.product_keys(kind)The keywords of a kind of product (e.g. efficacy and waning for ss.Vaccine), which its delivery takes to make one
remembered
interventions.remembered(selector, cond)The memory of an event for each agent or group: whether (ever), how often (n_times), or how long ago (since, in the sim’s unit) it happened
trigger_moves
interventions.trigger_moves(owner, outcome, sel, eng=None, before=None)The transitions triggered by an event of a delivery or product (e.g. ss.Transition(I, R_res, when=drug.failed, p=0.05)): the people it happened to who are in the transition’s source, and meet the rest of its condition, move now, with its probability (p=), or split between its destinations; under every solver
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| owner | Event / Product | what fired the event | required |
| outcome | str |
the outcome (None for the delivery itself) | required |
| sel | uids / array |
the people it happened to: UIDs, or a fraction of each state and group of eng |
required |
| eng | Engine |
in a compartmental run, the engine whose states and groups sel is a fraction of |
None |
| before | array |
in a compartmental run, the people in each state and group that sel is a fraction of, if not those now |
None |