library.mnch
Maternal, newborn, and child health (MNCH) example modules.
Demonstrates how to model congenital infection, neonatal mortality, and fetal health outcomes on top of ss.Pregnancy and ss.PrenatalNet. See the folder README for a walkthrough of how these modules fit together.
Used with: agents; coded modules
Classes
| Name | Description |
|---|---|
| CongenitalDisease | Simple disease with congenital outcomes, scheduled around delivery |
| FetalHealth | Track fetal health outcomes during pregnancy. |
| NeonatalSepsis | Minimal neonatal sepsis model. |
| PregnancyTreatment | What treat_pregnant delivers: a cure of the infection, and a partial reversal of the fetal damage |
| fetal_infection | Connect a disease to fetal health outcomes during pregnancy. |
| treat_pregnant | Treat infected pregnant women and partially reverse fetal damage. |
CongenitalDisease
library.mnch.CongenitalDisease(pars=None, **kwargs)Simple disease with congenital outcomes, scheduled around delivery
Infected mothers transmit to their unborn via PrenatalNet. At transmission, set_congenital() samples an outcome (stillborn, congenital, normal) and schedules it for delivery time. step_congenital() in step_state() executes those scheduled events.
Note: CRN safe.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| birth_outcome_keys | list |
outcome names — each needs a ti_<key> state |
|
| birth_outcomes | objdict |
ss.choice distributions keyed by category; use ‘default’ for a single distribution applied to all infections |
|
| pars | dict |
the same parameters, as a dict | None |
Attributes
| Name | Type | Description |
|---|---|---|
| ti_stillborn | FloatArr | timestep when stillbirth fires (triggers request_death) |
| ti_congenital | FloatArr | timestep when congenital infection fires (sets BoolArr) |
| ti_normal | FloatArr | timestep when normal outcome fires (no effect) |
| congenital | BoolArr | True if agent has congenital infection |
| cs_outcome | FloatArr | index into birth_outcome_keys for each agent |
Methods
| Name | Description |
|---|---|
| set_congenital | Assign congenital outcomes during in-utero infection (called when |
| step_congenital | Execute scheduled congenital events whose ti_<key> has arrived. |
set_congenital
library.mnch.CongenitalDisease.set_congenital(target_uids, sources=None)Assign congenital outcomes during in-utero infection (called when transmission occurs via PrenatalNet).
Does nothing unless the disease defines birth_outcome_keys and birth_outcomes in its pars. Diseases that need fully custom logic (e.g. syphilis, which has stage-dependent outcomes) can override this method entirely.
To use it, define in the disease’s __init__:
self.define_pars(
birth_outcome_keys = ['stillborn', 'congenital', 'normal'],
birth_outcomes = sc.obj(default=ss.choice(a=3, p=[0.3, 0.4, 0.3])), # Illustrative placeholder
)
Each outcome name needs a matching ti_<name> FloatArr state; non-lethal outcomes also need a BoolArr of the same name. Death outcomes (‘miscarriage’, ‘neonatal_death’, ‘stillborn’) fire via request_death; others set a bool state.
Outcomes are scheduled for the mother’s delivery timestep, except for fetal losses (‘miscarriage’, ‘stillborn’), which are scheduled one timestep earlier so that they occur before the fetus is delivered and are classified as fetal losses rather than neonatal deaths. A fetus infected within one timestep of delivery is therefore born alive, and a lethal outcome for it counts as a neonatal death.
For state- or GA-dependent probabilities, provide multiple keyed distributions in birth_outcomes and override _assign_congenital_outcomes.
Call step_congenital from the disease’s step_state() to execute the scheduled events each timestep.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| target_uids | array |
the unborn agents infected, by their mothers (people.parent), over ss.PrenatalNet |
required |
| sources | array |
who infected them (their mothers), if known; not used here | None |
step_congenital
library.mnch.CongenitalDisease.step_congenital()Execute scheduled congenital events whose ti_<key> has arrived.
Does nothing unless the disease defines birth_outcome_keys in its pars. Call from the disease’s step_state(); see set_congenital for setup details.
FetalHealth
library.mnch.FetalHealth(pars=None, **kwargs)Track fetal health outcomes during pregnancy.
Works alongside the Pregnancy module to model birth weight outcomes (low birth weight, small for gestational age) based on fetal growth restriction. Disease-agnostic by design: external modules (connectors, interventions) modify fetal health via the public API methods.
Preterm classification is handled by the Pregnancy module (based on gestational age at birth). This module focuses on the weight/growth axis.
Integrates with Pregnancy via its callbacks (add_callback()): Pregnancy calls on_conception when new pregnancies begin and on_delivery when births occur. External modules (e.g. disease connectors) can register their own on preg.conception, after this module’s, to act on new pregnancies after baseline initialization.
During pregnancy, weight_percentile, growth_restriction, timing_shift, and n_exposures are tracked on the mother. At delivery, birth_weight, lbw, vlbw, and sga are stored on the newborn.
Each pregnancy gets a baseline weight percentile drawn at conception. Two modification levers are available:
1. **Delivery timing**: bring the delivery (`ti_exit_P`) forward (preterm birth risk)
2. **Growth restriction**: accumulate fractional weight reduction
At delivery: birth_weight = baseline_for_GA × percentile × (1 - restriction)
The results are counts of births and outcomes on each step, and means and rates over a step’s births (mean_birth_weight, lbw_rate, …), which are NaN on a step with no births, and are left out of a mean over time (e.g. res.mean_birth_weight.resample('year')).
Note: CRN safe.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| weight_by_ga | array |
Nx2 array of [gestational_age_weeks, weight_grams] | |
| interp_fn | callable |
interpolation function with signature (x, xp, fp) -> array (default np.interp) | |
| sga_ratio | float |
fraction of GA-appropriate weight below which SGA is declared | |
| lbw_threshold | float |
birth weight in grams below which LBW is declared | |
| vlbw_threshold | float |
birth weight in grams below which VLBW is declared | |
| min_ga | dur |
floor for timing shifts (delivery can’t be brought before this GA) | |
| percentile_dist | Dist | distribution for baseline fetal weight percentile | |
| pars | dict |
the same parameters, as a dict | None |
Examples
import starsim as ss
import starsim.library as ssl
sim = ss.Sim(
demographics=[ss.Pregnancy(fertility_rate=10), ss.Deaths(death_rate=10)],
modules=ssl.mnch.FetalHealth(),
networks=ss.PrenatalNet(),
)
sim.run()Methods
| Name | Description |
|---|---|
| apply_growth_restriction | Apply fractional growth restriction (cumulative, diminishing). |
| apply_timing_shift | Bring delivery forward for pregnant women. |
| compute_birth_weight | Compute birth weight at delivery. |
| init_pre | Register callbacks with the Pregnancy module |
| on_conception | Initialize fetal health for new pregnancies (called by Pregnancy) |
| on_delivery | Classify birth outcomes (called by Pregnancy). |
| reverse_growth_restriction | Reverse a specific amount of growth restriction. |
| reverse_timing_shift | Recover a fraction of the accumulated delivery timing shift. |
apply_growth_restriction
library.mnch.FetalHealth.apply_growth_restriction(uids, penalty)Apply fractional growth restriction (cumulative, diminishing).
Positive penalties use diminishing returns: current + (1-current) * penalty. Negative penalties (growth boost, e.g. GDM macrosomia) are additive.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | UIDs of pregnant women | required | |
| penalty | float |
fractional weight reduction; negative = growth boost | required |
apply_timing_shift
library.mnch.FetalHealth.apply_timing_shift(uids, shift_weeks)Bring delivery forward for pregnant women.
Uses a one-way ratchet: delivery can only be brought forward, never pushed back. The actual shift applied is tracked in timing_shift.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | UIDs of pregnant women | required | |
| shift_weeks | float / array |
shift in weeks; positive = earlier delivery | required |
compute_birth_weight
library.mnch.FetalHealth.compute_birth_weight(uids)Compute birth weight at delivery.
Override this method to customize the birth weight formula. The interpolation function can be swapped via pars.interp_fn.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | array |
the mother of each newborn | required |
Returns
| Name | Type | Description |
|---|---|---|
| tuple | (birth_weights, ga_weeks) arrays |
init_pre
library.mnch.FetalHealth.init_pre(sim)Register callbacks with the Pregnancy module
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | Sim | the sim being initialized | required |
on_conception
library.mnch.FetalHealth.on_conception(uids)Initialize fetal health for new pregnancies (called by Pregnancy)
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | array |
the women who conceived | required |
on_delivery
library.mnch.FetalHealth.on_delivery(newborn_uids)Classify birth outcomes (called by Pregnancy).
Birth weight is computed from the mother’s pregnancy-time states (weight_percentile, growth_restriction). Outcomes (birth_weight, lbw, vlbw, sga) are stored on the newborn agents.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| newborn_uids | array |
the newborns | required |
reverse_growth_restriction
library.mnch.FetalHealth.reverse_growth_restriction(uids, amount)Reverse a specific amount of growth restriction.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | UIDs of pregnant women | required | |
| amount | float / array |
amount to reverse | required |
reverse_timing_shift
library.mnch.FetalHealth.reverse_timing_shift(uids, fraction)Recover a fraction of the accumulated delivery timing shift.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | UIDs of pregnant women | required | |
| fraction | float / array |
fraction to recover (0-1) | required |
NeonatalSepsis
library.mnch.NeonatalSepsis(pars=None, **kwargs)Minimal neonatal sepsis model.
Infects newborns at birth with probability p_at_birth, then kills a fraction (p_death) within a short window (dur_inf). Useful for testing passive neonatal death detection in the Pregnancy module.
Note: CRN safe.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| beta | float |
transmission rate — set to 0 since infection is only at birth | |
| p_at_birth | Dist | fraction of newborns infected at birth | |
| init_prev | Dist | fraction of the people at the start who are infected (none by default) | |
| dur_inf | Dist | time from infection to death (for those who die) | |
| p_death | Dist | case fatality rate among infected neonates | |
| pars | dict |
the same parameters, as a dict | None |
Methods
| Name | Description |
|---|---|
| init_post | Exempt the initial population from being treated as newborns |
| set_prognoses | Set prognoses — only apply lethal outcomes to neonates (age < 28 days). |
| step | Infect newly born agents. |
init_post
library.mnch.NeonatalSepsis.init_post()Exempt the initial population from being treated as newborns
set_prognoses
library.mnch.NeonatalSepsis.set_prognoses(uids, sources=None)Set prognoses — only apply lethal outcomes to neonates (age < 28 days).
Non-neonates who get infected (e.g. via init_prev at sim start) just recover normally via the base SIR logic.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| uids | array |
the agents infected | required |
| sources | array |
the agents who infected them | None |
step
library.mnch.NeonatalSepsis.step()Infect newly born agents.
Newborns are infected explicitly, each with p_at_birth. Each agent is screened once, the first timestep after they are born.
PregnancyTreatment
library.mnch.PregnancyTreatment(delivery, **kwargs)What treat_pregnant delivers: a cure of the infection, and a partial reversal of the fetal damage
fetal_infection
library.mnch.fetal_infection(pars=None, **kwargs)Connect a disease to fetal health outcomes during pregnancy.
Monitors for infections in pregnant women and applies fetal damage: - Timing shift: brings delivery forward (increases preterm birth risk). Drawn from a lognormal distribution per affected pregnancy. - Growth restriction: reduces birth weight by a fixed fractional penalty.
Damage is applied at two points: 1. At conception, if the mother is already infected (via a conception callback registered with the pregnancy, after FetalHealth’s). 2. During pregnancy, when a new infection occurs (detected in step() by checking ti_infected == self.ti - 1, since transmission happens after connectors).
Requires ssl.mnch.FetalHealth() in modules and an SIR disease written as code (ssl.AgentSIR(name="sir")) in diseases.
Note: CRN safe.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timing_shift | Dist | weeks to shift delivery forward per infection (default: lognormal mean=3, std=1) | |
| growth_penalty | float |
fractional birth weight reduction per infection (default: 0.15 = 15%) | |
| pars | dict |
the same parameters, as a dict | None |
To adapt for a different disease::
class my_fetal_connector(fetal_infection):
def init_pre(self, sim):
# Register with FetalHealth, but check for your disease instead
...
def _apply_damage(self, uids):
# Custom damage logic, e.g. stage-dependent penalties
fh = self.fh
disease = self.sim.diseases.my_disease
severe = disease.severe[uids]
mild_uids = uids[~severe]
severe_uids = uids[severe]
fh.apply_growth_restriction(mild_uids, 0.05)
fh.apply_growth_restriction(severe_uids, 0.25)
...
Attributes
| Name | Description |
|---|---|
| fh | Shortcut to the FetalHealth module |
Methods
| Name | Description |
|---|---|
| init_post | Register a callback so we can apply damage at conception for women who are already infected when they become pregnant: after FetalHealth’s (registered in its init_pre()), which sets the baseline |
| init_pre | Check that the sim has what the connector needs |
| step | Each timestep, check for new infections in pregnant women and apply damage |
init_post
library.mnch.fetal_infection.init_post()Register a callback so we can apply damage at conception for women who are already infected when they become pregnant: after FetalHealth’s (registered in its init_pre()), which sets the baseline
init_pre
library.mnch.fetal_infection.init_pre(sim)Check that the sim has what the connector needs
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | Sim | the sim being initialized | required |
step
library.mnch.fetal_infection.step()Each timestep, check for new infections in pregnant women and apply damage
treat_pregnant
library.mnch.treat_pregnant(
disease='sir',
coverage=0.9,
who=None,
when=None,
growth_reversal=0.7,
timing_reversal=0.7,
name=None,
**kwargs,
)Treat infected pregnant women and partially reverse fetal damage.
A delivery, as ss.treat() is: by default each pregnant woman infected with the target disease is offered treatment once, with the probability coverage. Treatment cures the infection, and reverses a fraction of the fetal damage accumulated so far (growth restriction and timing shift). who= restricts who among them is offered it, and when= when, as for any delivery (e.g. when=ss.schedule(start=2025)).
Note: CRN safe.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| disease | str |
name of the target disease (default: ‘sir’), written as code (e.g. ssl.AgentSIR) |
'sir' |
| coverage | float |
the probability that each woman eligible is treated | 0.9 |
| who | Cond / func |
who among the infected pregnant women is offered it | None |
| when | various |
when it is offered, as for any delivery (default: on every step, once to each woman when she becomes eligible) | None |
| growth_reversal | float |
the fraction of the growth restriction reversed (0-1) | 0.7 |
| timing_reversal | float |
the fraction of the timing shift reversed (0-1) | 0.7 |
| kwargs | dict |
passed to ss.Delivery (e.g. capacity=, name=) |
Attributes
| Name | Type | Description |
|---|---|---|
| ti_treated | FloatArr | timestep when each agent was treated |
Example — treatment from 2025, of half the women eligible::
ssl.mnch.treat_pregnant(disease='sir', start=2025, coverage=0.5)
Methods
| Name | Description |
|---|---|
| eligible | The pregnant women infected with the disease |
| init_pre | Check that the sim has the disease and ssl.mnch.FetalHealth |
eligible
library.mnch.treat_pregnant.eligible(sim)The pregnant women infected with the disease
init_pre
library.mnch.treat_pregnant.init_pre(sim)Check that the sim has the disease and ssl.mnch.FetalHealth
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | Sim | the sim being initialized | required |