Changelog¶
All notable changes to simACE are documented here.
The format follows Keep a Changelog.
simACE uses CalVer versioning (YYYY.MM) derived from git tags.
Unreleased¶
2026.05.1 — 2026-05-07¶
Highlights¶
- Phenotype model architecture. Replaces much of the monolithic
phenotype dispatch with a
PhenotypeModelABC and separate model modules forfrailty,cure_frailty,adult, andfirst_passage. - Prevalence config moved into model params. Threshold-style
prevalence is now model-owned under
phenotype.traitN.params.prevalence, with migration tooling and validation for old top-level prevalence keys. - Hazard and standardization overhaul. Adds a hazard registry,
three-way liability standardization (
none,global,per_generation), and per-traitstandardize_hazardoverrides for hazard-bearing models. - Hierarchical config support. Config loading now supports
sectioned YAML (
pedigree,phenotype,censoring,sampling,analysis,tstrait) while still flattening internally for workflow use. - Snakemake wrapper simplification. Adds shared Snakemake adapter
utilities, reduces repeated wrapper boilerplate, splits simulation
into pedigree/params stages, and adds an explicit
emit_paramspath. - Documentation + repo cleanup. Moves docs fully into MkDocs,
adds concept/user-guide/example pages, refreshes API docs, removes
stale standalone docs and the public
notes/, adds rule graph generation, and updates README/setup docs for Python>=3.13. - Plotting and atlas refactor. Introduces an atlas manifest, collapses plot dispatch, updates captions, redesigns tetrachoric/reference panels, and improves plot styling and example figures.
- Pipeline schema contracts. Adds explicit DataFrame schema
contracts for pedigree → phenotype → censor/sample handoffs, plus a
@stagedecorator to enforce and expose stage input/output metadata. - PedigreeGraph externalized. Removes internal pedigree graph and
kinship-kernel code in favor of the standalone
pedigree-graphpackage pinned atv0.2.0. - Stats package split. The old
simace/analysis/stats.pywas split into focused modules: correlations, tetrachoric, incidence, censoring, pedigree, sampling, effective size, and runner orchestration. - Effective population size estimators. Adds per-replicate Ne summaries, theoretical expectations for the ZTP mating model, and validation/reference tests for those estimators.
- Gene-drop + tstrait pipeline. Adds a full tskit/tstrait branch
for realistic genotype inheritance: preprocessing SimHumanity
trees, fixed-pedigree drops, causal-effect assignment,
genetic-value calculation, and
A1augmentation.
Secondary theme: test coverage expanded across config loading, phenotyping models, tskit/tstrait, stats, core schema/stage helpers, workflow scripts, and plotting.
Added¶
- MkDocs documentation site with Material theme
- Three-way liability standardization:
standardizenow acceptsnone,global, orper_generation(replacing the previous boolean flag, which is still accepted via a back-compat shim withtrue → "global"andfalse → "none"). Default is"global". - Per-trait
standardize_hazardoverride insidephenotype.trait{N}.paramsfor the four hazard-bearing model families (frailty,cure_frailty,first_passage, andadultwithmethod: cox). Defaults toNone→ inherit from the globalstandardizeflag.cure_frailtyis the only family that honors both knobs independently (threshold step + hazard step). See ACE Model § Standardisation. - New
e_*_pergenexample scenarios (e_flat_pergen,e_rise_mild_pergen,e_rise_steep_pergen,e_fall_steep_pergen) matching the existing_std/_nostdE-trajectory pairs but withstandardize: per_generation. Thedocs/images/examples/increasing_e/prevalence_drift.pngfigure now shows three lines per panel (global/none/per_generation) instead of two.
Changed¶
phenotype.threshold.apply_thresholdnow standardizes liability once outside the per-generation loop using the chosen mode. Understandardize=true(now"global"), this changes behaviour for any scenario whoseapply_thresholdcall previously relied on per-gen standardization to preserve K (including thephenotype_simple_ltmbenchmark output produced for every scenario). Setstandardize: per_generationin the scenario YAML to restore exact per-gen prevalence preservation._apply_threshold_sex_awarenow z-scores liability once across both sexes (per the chosen mode) before applying per-(sex, gen) prevalence thresholds. Sex-shifted liability means now translate into sex-specific realised prevalences within each generation.--standardizeCLI flag changed fromaction="store_true"(a no-op flag that could not be turned off) tochoices=["none", "global", "per_generation"]with default"global".simace.plotting.compare_scenarios.compare_prevalence_driftnow accepts an optional third series viapergen_paths_per_trajectory/pergen_label; the existing two-series call signature is unchanged.simace.phenotyping._prototypes.bimodal_phenotype(phenotype_mixture_cip,phenotype_mixture_cure_frailty,phenotype_two_threshold) ported to the mode-aware standardize API (StandardizeMode | bool, withper_generationrejected since these prototypes don't take agenerationarray). The samecure_frailtyraw-vs-standardized-L fix applies here too.
Fixed¶
- The phenotype-stage
--standardizeCLI flag could previously not be set tofalsefrom the command line. cure_frailtywas passing the threshold-standardized liabilityL_zto its hazard kernel where the kernel expects raw liability. Combined with themeanandscaled_betaderived from the raw liability, this produced a hazard ofexp((beta/std)·(L_z − mean))instead of the intendedexp((beta/std)·(L_raw − mean)) = exp(beta·z_score(L_raw)). Equivalent to a1/std²instead of1/stdscaling and an extra constant offset of−beta·mean/std. Silent under the defaultA + C + E = 1ACE configurations (where liability has mean ≈ 0 and std ≈ 1) but real for any scenario with non-zero-mean or non-unit-variance liability — including all per-generationC/Econfigurations. After the fix, the case-onset distribution understandardize="global"is invariant to additive shifts and multiplicative scales of liability, as it should be.