Skip to content

Repository files navigation

ModifiedDistributions ModifiedDistributions logo

Documentation Build Status Code Quality License & DOI Downloads
Stable Dev Test codecov AD SciML Code Style Aqua QA JET License: MIT Downloads Downloads
ForwardDiff ReverseDiff (tape) Enzyme forward Enzyme reverse Mooncake reverse Mooncake forward
cov ForwardDiff cov ReverseDiff cov Enzyme forward cov Enzyme reverse cov Mooncake reverse cov Mooncake forward

Wrappers for Distributions.jl univariate distributions that each change one behaviour — rescaling, likelihood weighting, hazard modification, or a forward transform — while everything else keeps working, plus the generic get_dist unwrap protocol.

Why ModifiedDistributions?

  • A model routinely needs "the same delay, but weighted, rescaled, or hazard-shifted"; ModifiedDistributions wraps each change as one small, composable piece instead of hand-deriving the change-of-variables maths each time.
  • Every wrapper stays a complete distribution — sampling, quantiles, moments — so a modified delay drops into a PPL model exactly like the distribution it wraps.
  • Wrappers nest and unwrap cleanly, so a pipeline built from several small changes stays inspectable and reversible rather than collapsing into one opaque function.
  • Weighting a likelihood is a one-line wrapper instead of an ad hoc n * logpdf(...) term scattered through model code.
  • Hazard-scale changes, such as an intervention that shifts risk, have no Distributions.jl counterpart and are given here in closed form.
  • The same wrappers apply across ComposedDistributions.jl chains and ConvolvedDistributions.jl count series, so a delay modified once carries that change through the rest of the pipeline.

Getting started

See documentation for a full walkthrough.

Modifiers nest, so a real pipeline stacks several changes on one delay: an intervention that halves the hazard of admission, a half-day reporting lag, and a 60% ascertainment fraction tagged for a downstream count series.

using ModifiedDistributions, Distributions

admission = Gamma(2.0, 1.0)   # baseline infection-to-admission delay

pipeline = thin(affine(modify(admission, -log(2.0)); shift = 0.5), 0.6)

pipeline prints as the nested wrapper it is.

pipeline

Each stage compounds the three-day survival: halving the hazard raises it to its square root, and the reporting lag raises it further (day 3 is now effectively day 2.5 post-admission); thin does not touch the scalar distribution at all, only tagging it for later use.

(baseline_survival = ccdf(admission, 3.0),
    after_intervention = ccdf(modify(admission, -log(2.0)), 3.0),
    after_reporting_lag = ccdf(pipeline, 3.0))

Unwrapping recovers the baseline delay underneath every layer.

get_dist_recursive(pipeline) == admission

The getting started guide carries this same pipeline further: what thin does once it meets a real count series, and how modifiers apply across a composed chain.

Relationship to Distributions.jl

Distributions.jl already supports affine arithmetic on some distributions (2.0 * X + 1.0) by returning a new parameterisation where one exists. affine instead wraps any univariate distribution with the exact change-of-variables maths, so it works uniformly and keeps the inner distribution recoverable via get_dist. Likewise weight replaces ad hoc n * logpdf(d, x) terms in model code with a distribution object that carries its weight, and modify gives hazard-scale transforms that have no Distributions.jl counterpart.

Related packages

  • ComposedDistributions.jl composes distributions into event-tree chains; a package extension here lets the modifier verbs apply across a chain's observed total, and ComposedDistributions.jl's own leaf-protocol support lets a modified leaf compose inside a chain.
  • ConvolvedDistributions.jl sums independent delays and convolves count series; a package extension applies thin/cumulative to the convolved counts and lets modified distributions serve as convolution components.
  • LoweredDistributions.jl turns a distribution into a backend-agnostic dynamical-systems representation; a package extension here lowers the modifiers that carry dynamics (an affine rescale, a modify hazard change on an Exponential) and refuses the observation-only ones (a shift, a weight, a forward transform) rather than approximating them.
  • CensoredDistributions.jl builds primary-event and interval censoring on distributions, including ones already modified by this package.
  • DistributionsInference.jl is the emerging home for probabilistic-programming integrations (Turing.jl, DynamicPPL, Bijectors) that a modified or weighted distribution plugs into.

Where to learn more

Getting help

For usage questions, ask on the Julia Discourse (the SciML or usage categories) or the epinowcast community forum, our home for epidemiological modelling questions. Please use GitHub issues for bug reports and feature requests only.

Contributing

We welcome contributions and new contributors! This package follows ColPrac and the SciML style.

Supporting and citing

If you would like to support ModifiedDistributions, please star the repository — such metrics help secure future funding.

If you use ModifiedDistributions in your work, please cite it (the DOI is a placeholder until the first Zenodo release):

@software{ModifiedDistributions_jl,
  author       = {Sam Abbott and EpiAware contributors},
  title        = {ModifiedDistributions.jl},
  year         = {2026},
  doi          = {10.5281/zenodo.XXXXXXX},
  url          = {https://github.com/EpiAware/ModifiedDistributions.jl}
}

Code of conduct

Please note that the ModifiedDistributions project is released with a Contributor Code of Conduct. By contributing, you agree to abide by its terms.

About

Distributions that modify the behaviour of the underlying Distributions.jl distributions

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages