hpv
Per-genotype HPV disease module.
Scope note: HPVsim only models cervical cancer outcomes. HPV is also associated with anal, oropharyngeal, penile, vaginal, and vulvar cancers (the first three of which can occur in males); those are out of scope here.
Models the natural-history pipeline as a Starsim Infection:
susceptible -> precin -> (clear | CIN -> (clear | cancerous -> death))
Females are eligible for the full progression; males clear from precin without entering CIN/cancer. Clearance grants partial same-genotype immunity: per-agent beta samples accumulate as a running max into nab_imm (humoral) and cell_imm (cell-mediated). Vaccine-conferred immunity is stored separately in vax_imm and does NOT flow through the cross-immunity matrix — the CSV’s per-genotype rel_imm is the complete vaccine cross-protection profile. The CrossImmunity connector reads nab_imm / cell_imm each step, matrix-multiplies to derive cross-genotype rel_sus / sev_imm, then combines with vax_imm via independent-protection paths.
Multi-genotype runs instantiate one HPV per genotype, all sharing the People and going through the same Connector path; a 1-genotype run uses a 1×1 identity matrix on the Connector.
Classes
| Name | Description |
|---|---|
| HPV | Per-genotype HPV disease module. |
HPV
hpv.HPV(genotype='hpv16', pars=None, **kwargs)Per-genotype HPV disease module.
The genotype attribute identifies which strain this instance models. The CrossImmunity connector reads each registered HPV’s nab_imm/cell_imm (clearance-conferred) each step, matrix-multiplies to derive per-target rel_sus/sev_imm, then combines with vax_imm (vaccine-conferred, per-target direct) via independent-protection paths. Vaccine immunity does NOT flow through the cross-immunity matrix.
Methods
| Name | Description |
|---|---|
| init_results | Per-step Results emitted from step_state. |
| set_prognoses | Sample full natural-history trajectory for newly-infected agents. |
| step_die | Set states to False for the newly-dead. |
| step_state | Advance agents through the natural-history compartment chain. |
| update_results | Recompute per-step stock counts as scale-weighted floats. |
| validate_beta | Expand a scalar pars.beta via rel_beta/transf2m/transm2f (mirrors |
init_results
hpv.HPV.init_results()Per-step Results emitted from step_state.
new_cancers / new_undetected_cancers / new_cancer_deaths are realized-event counters (undetected -> detected, cin -> cancerous, and cancerous -> dead respectively); at the default zero-duration dur_undetected, the two cancer counters match per ti. cum_* are populated as cumulative sums in finalize_results. sum_age_at_* are per-step accumulators; mean age = sum / count.
Starsim auto-generates n_<state> results as dtype=int for every BoolState. We promote each stock result to dtype=float here so that update_results can write scale-weighted values (fine agents carry scale=1/ratio and must count as 1/ratio, not 1).
set_prognoses
hpv.HPV.set_prognoses(uids, sources=None)Sample full natural-history trajectory for newly-infected agents.
- dur_precin sampled for everyone; males then clear after dur_inf_male without entering CIN/cancer.
- For females, P(CIN) = compute_severity(dur_precin, cin_fn). Non-CIN agents clear after dur_precin.
- For CIN agents, P(cancer) = compute_severity(dur_cin, cancer_fn). Non-cancer agents clear after dur_precin + dur_cin.
- Cancer agents get ti_cancerous and ti_dead_cancer scheduled; the CIN -> cancerous transition and request_death fire from step_state.
Initial seeding via init_post -> set_prognoses flows through here so init_prev-seeded agents get ti_first_infection set at ti=0.
step_die
hpv.HPV.step_die(uids)Set states to False for the newly-dead. IMPORTANT: if you add any new states, remember to add them here!
step_state
hpv.HPV.step_state()Advance agents through the natural-history compartment chain.
Order matters: clearance fires first so a just-cleared agent isn’t re-flipped by a forward transition at the same timestep.
- Clearance from precin or CIN (partial-immunity path)
- precin -> CIN
- CIN -> cancerous (stops transmitting; flagged undetected)
- undetected_cancerous -> detected (registers new_cancers)
- Cancer death (via people.request_death)
Steps 3 and 4 fire the same tick at the default dur_undetected=0.
update_results
hpv.HPV.update_results()Recompute per-step stock counts as scale-weighted floats.
Starsim’s Module.update_results writes n_<state>[ti] = state.sum() — a plain boolean count that treats every agent as one body regardless of its scale. Fine agents carry scale = 1/ms_agent_ratio, so they must count as 1/ratio, not 1.
We call super().update_results() first so the starsim pipeline runs normally (prevalence, new_infections, etc.), then overwrite each stock slot with people.scale_flows(uids_in_state).
After the stock overwrite, prevalence is re-derived from the corrected scale-weighted n_infected divided by the scale-weighted alive-agent total. Infection.update_results (called via super) computed prevalence from the stale plain-count n_infected, so at ms_agent_ratio>1 it would be inflated by roughly the ratio. Re-deriving here is a no-op at ratio==1 (where scale_flows == len).
validate_beta
hpv.HPV.validate_beta()Expand a scalar pars.beta via rel_beta/transf2m/transm2f (mirrors stisim’s BaseSTI.validate_beta). An explicit dict pars.beta is passed through unchanged. A bare (unattached) module has no self.sim to validate networks against, so skip super() and expand/pass-through directly.