Skip to content

ModifiedDistributions

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?

  • Rescale and shift — exact affine transforms of any univariate distribution, with the full distribution interface intact.

  • Weight likelihoods — scale an observation's contribution with weight while the result stays a real, samplable distribution, so a Turing.jl model (or any PPL built on Distributions.jl) remains a complete generative model.

  • Modify hazards — proportional or additive hazard changes with modify, in closed form.

  • Forward transforms — carry thinning or accumulation for a downstream count series without touching the distribution itself.

  • Unwrap anywhere — recover the distribution underneath any wrapper with get_dist.

  • Works with composed chains — modifiers apply across ComposedDistributions.jl chains.

  • AD-ready — tested in CI against ForwardDiff, ReverseDiff, Enzyme, and Mooncake.

Getting started

See documentation for a full walkthrough.

An affine transform gives the exact distribution of Y = 2X + 1, and the whole distribution interface follows:

julia
using ModifiedDistributions, Distributions

d = affine(LogNormal(1.5, 0.5); scale = 2.0, shift = 1.0)
(mean = mean(d), logpdf = logpdf(d, 5.0), median = quantile(d, 0.5))
(mean = 11.156838074360163, logpdf = -2.914108658241349, median = 9.963378140676129)

Weighting scales the log-likelihood contribution of an observation seen 10 times. The two numbers printed below match, showing the weighted log-density is exactly 10 times the base:

julia
wd = weight(d, 10.0)
(weighted = logpdf(wd, 5.0), manual = 10.0 * logpdf(d, 5.0))
(weighted = -29.141086582413493, manual = -29.141086582413493)

Hazard modification works in closed form. Halving the hazard raises the survival function to the power one half, and the two printed values agree:

julia
md = modify(LogNormal(1.5, 0.5), -log(2.0))
(modified = ccdf(md, 2.0), base_sqrt = ccdf(LogNormal(1.5, 0.5), 2.0)^0.5)
(modified = 0.9729873354092063, base_sqrt = 0.9729873354092063)

Unwrapping the weighted distribution returns the affine transform underneath:

julia
get_dist(wd)
Affine(Distributions.LogNormal{Float64}(μ=1.5, σ=0.5))

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.

What packages work well with ModifiedDistributions.jl?

  • Distributions.jl supplies the distributions being modified.

  • Turing.jl and other PPLs consume the wrappers directly, e.g. weighted likelihoods for aggregated data.

  • ComposedDistributions.jl composes distributions into chains; a package extension lets the modifier verbs apply across a chain's observed total.

  • CensoredDistributions.jl and the wider EpiAware ecosystem build censoring, convolution, and composition layers on top of these modifiers.

Where to learn more

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):

bibtex
@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.