Skip to content

Public Documentation

Documentation for ModifiedDistributions's public interface.

Contents

Index

Public API

ModifiedDistributions.AbstractModifiedDistribution Type
julia
abstract type AbstractModifiedDistribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport} <: Distributions.Distribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport}

Supertype of the single-base modifier leaves that wrap one inner distribution and modify it: Affine, Weighted, Transformed, Modified. CensoredDistributions' TimeChange and Shared leaves stay upstream until the migration (CensoredDistributions#343) lands. Parametric on variate form for symmetry with the upstream hierarchy.

Required methods a concrete subtype implements (the leaf interface):

  • an inner base reachable as .dist (the default show accessor; override ModifiedDistributions._modified_inner if stored elsewhere) and via get_dist;

  • the univariate interface (pdf / logpdf / cdf / quantile / minimum / maximum / insupport / params), forwarded or specialised;

  • optionally Base.show; the default below prints Name(inner).

The free_leaf / rewrap_leaf round-trip verbs are owned by ComposedDistributions.jl and live in its package extension, so they are not part of this package's contract.

Verify a subtype with ModifiedDistributions.TestUtils.test_modified_interface.


Fields

source
ModifiedDistributions.Affine Type
julia
struct Affine{D<:(Distributions.UnivariateDistribution), T<:Real, S<:Distributions.ValueSupport} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, S<:Distributions.ValueSupport}

The distribution of a deterministic affine transform Y = scale * X + shift of an inner distribution X, with scale > 0 and any real shift.

For a continuous inner distribution, computed by the change-of-variables for a strictly increasing affine map: with x = (y - shift) / scale,

For a discrete inner distribution, the probability mass moves to the rescaled lattice without the Jacobian term: P(Y = y) = P(X = (y - shift) / scale).

Affine is a UnivariateDistribution with the value support of the inner distribution, so it works anywhere a distribution is expected.

See also


Fields

  • dist::Distributions.UnivariateDistribution: The inner distribution being transformed.

  • scale::Real: The positive multiplicative scale.

  • shift::Real: The additive shift.

source
ModifiedDistributions.HazardLink Type
julia
struct HazardLink{G, GI}

A link for the hazard modification carried by a Modified distribution.

The modification acts on the hazard through the link g,

so log gives proportional hazards and identity gives additive hazards. A HazardLink pairs the link g with its inverse invlink (g⁻¹); the three named links (LogLink, IdentityLink, LogitLink) are built-in, and any invertible callable can be wrapped with hazard_link. Only the log and identity links have analytic forms; modify rejects the others until numeric integration is supported.

See also


Fields

  • g::Any: The link g mapping a hazard onto the modification scale.

  • invlink::Any: The inverse link g⁻¹ mapping back to a hazard.

source
ModifiedDistributions.IdentityLink Constant
julia
IdentityLink

The identity link (additive hazards): g = g⁻¹ = identity.

IdentityLink adds to the cumulative hazard from the support minimum m,   , the additive-hazards form. Only non-negative effects and bases with a finite lower support bound are supported (see modify).

Examples

julia
using ModifiedDistributions, Distributions

# Additive-hazards modification of an Exponential delay.
modify(Exponential(1.0), 0.5; link = ModifiedDistributions.IdentityLink)

See also

source
ModifiedDistributions.LogLink Constant
julia
LogLink

The log link (proportional hazards): g = log, g⁻¹ = exp.

LogLink scales the survival function,  , the proportional-hazards form, and is the default link of modify.

Examples

julia
using ModifiedDistributions, Distributions

# Proportional-hazards modification of an Exponential delay.
modify(Exponential(1.0), 0.5; link = ModifiedDistributions.LogLink)

See also

source
ModifiedDistributions.LogitLink Constant
julia
LogitLink

The logit link: g = logit, g⁻¹ = logistic.

LogitLink pairs the logit with its logistic inverse. On a continuous base it requires numeric cumulative-hazard integration, which this package does not yet provide, so modify rejects it with an ArgumentError.

Examples

julia
using ModifiedDistributions

# The logit link pair; modify rejects it until numeric integration lands.
ModifiedDistributions.LogitLink

See also

source
ModifiedDistributions.Modified Type
julia
struct Modified{D<:(Distributions.UnivariateDistribution), E<:Real, L<:ModifiedDistributions.HazardLink} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.Continuous}

A distribution whose hazard is modified through a link.

Modified carries a base distribution dist, a hazard effect and a HazardLink link, and lazily instantiates the modified hazard

in logpdf/cdf/ccdf/rand, where g is the link and h(t) = f(t)/S(t) the base hazard. The modification is never materialised eagerly, so a Modified composes with everything that consumes a UnivariateDistribution.

Two analytic paths are provided, chosen by dispatch on the link:

  • LogLink: proportional hazards,  ;

  • IdentityLink with a non-negative effect and a finite lower support bound m: additive hazards,   .

Other links (and negative additive effects) need numeric cumulative-hazard integration and are rejected at construction (see modify).

See also


Fields

  • dist::Distributions.UnivariateDistribution: The base distribution whose hazard is modified.

  • effect::Real: The hazard modification effect on the link scale.

  • link::ModifiedDistributions.HazardLink: The hazard link g and its inverse.

source
ModifiedDistributions.Transformed Type
julia
struct Transformed{D<:(Distributions.UnivariateDistribution), Op} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.ValueSupport}

A distribution carrying a forward-transform op, intended for a count series a downstream convolution layer produces. Transparent to logpdf and to every other distribution method (they delegate to the inner distribution). Construct with the generic series_transform or the specialised thin / cumulative.

See also


Fields

  • dist::Distributions.UnivariateDistribution: The inner distribution.

  • op::Any: The forward op applied to a convolved series.

source
ModifiedDistributions.Weighted Type
julia
struct Weighted{D<:(Distributions.UnivariateDistribution), T<:Union{Missing, Real}} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.ValueSupport}

A distribution wrapper that applies a weight to the log-probability of an underlying distribution. This is primarily used where observations have associated counts or weights.

Only the logpdf method is affected by the weight - all other methods (pdf, cdf, sampling, etc.) delegate directly to the underlying distribution.

Weight Types Supported

The Weighted struct supports three different weight scenarios:

  1. Real weights: Constructor weight is a specific value (e.g., 2.5)

  2. Missing weights: Constructor weight is missing, allowing weights to be provided at observation time via joint observations (value = x, weight = w)

  3. Zero weights: Handled specially to return -Inf and avoid NaN from 0 * -Inf

Examples

julia
using ModifiedDistributions, Distributions

# Single weighted observation
d = LogNormal(1.5, 0.5)
wd = weight(d, 10.0)  # Observation with weight/count of 10

# Weighted log-probability calculation
observed_value = 2.0
weighted_logpdf = logpdf(wd, observed_value)

# Compare with manual calculation
manual_logpdf = 10.0 * logpdf(d, observed_value)
# weighted_logpdf ≈ manual_logpdf

Fields

  • dist::Distributions.UnivariateDistribution: The underlying distribution being weighted.

  • weight::Union{Missing, Real}: The weight to apply to log-probabilities.

source
ModifiedDistributions.affine Function
julia
affine(
    dist::Distributions.UnivariateDistribution;
    scale,
    shift
) -> ModifiedDistributions.Affine{D, Float64} where D<:(Distributions.UnivariateDistribution)

Create an affine-transformed distribution Y = scale * X + shift.

Arguments

  • dist: the inner distribution X.

Keyword Arguments

  • scale: positive multiplicative factor (default 1).

  • shift: additive offset (default 0).

Examples

julia
using ModifiedDistributions, Distributions

d = affine(LogNormal(1.5, 0.5); scale = 2.0, shift = 1.0)
logpdf(d, 5.0)

See also

source
ModifiedDistributions.cumulative Function
julia
cumulative(
    dist::Distributions.UnivariateDistribution
) -> ModifiedDistributions.Transformed{D, ModifiedDistributions.CumulativeOp} where D<:(Distributions.UnivariateDistribution)

Accumulate a distribution's forward count series.

cumulative(d) is transform with a running-sum op intended for a downstream count series, giving cumulative counts (cumulative incidence, cumulative deaths). Transparent to logpdf.

Arguments

  • d: the inner distribution.

Examples

julia
using ModifiedDistributions, Distributions

d = cumulative(Gamma(2.0, 1.0))
logpdf(d, 2.0) == logpdf(Gamma(2.0, 1.0), 2.0)

See also

source
ModifiedDistributions.get_dist Function
julia
get_dist(d) -> Distributions.UnivariateDistribution

Extract the underlying distribution from a wrapped distribution type.

This protocol provides a consistent interface for extracting the core distribution from the modifier wrappers in this package (and any downstream wrapper that adds a method). For unwrapped distributions, it returns the distribution unchanged.

Arguments

  • d: A distribution or wrapped distribution.

Returns

The underlying distribution. For base distributions, returns d unchanged.

Examples

julia
using ModifiedDistributions, Distributions

# Base distribution - returns unchanged
d1 = Normal(0, 1)
get_dist(d1)

# Affine-transformed distribution
d2 = affine(LogNormal(1.5, 0.5); scale = 2.0)
get_dist(d2)
source
julia
get_dist(
    d::ModifiedDistributions.Affine
) -> Distributions.UnivariateDistribution

Extract the underlying distribution from an affine-transformed distribution.

Returns the inner distribution before the affine transform was applied.

source
julia
get_dist(
    d::ModifiedDistributions.Weighted
) -> Distributions.UnivariateDistribution

Extract the underlying distribution from a weighted distribution.

Returns the base distribution before weighting was applied.

source
julia
get_dist(
    d::ModifiedDistributions.Transformed
) -> Distributions.UnivariateDistribution

Extract the underlying distribution from a forward-transformed distribution.

Returns the inner distribution before the forward-transform op was attached.

source
julia
get_dist(
    d::ModifiedDistributions.Modified
) -> Distributions.UnivariateDistribution

Extract the underlying distribution from a hazard-modified distribution.

Returns the base distribution before the hazard modification was applied.

source
ModifiedDistributions.get_dist_recursive Function
julia
get_dist_recursive(d) -> Any

Recursively extract the underlying distribution from nested wrapper types.

This function keeps applying get_dist until it reaches a distribution that doesn't have a specialised method, meaning no further unwrapping is possible.

Arguments

  • d: A distribution or nested wrapped distribution.

Returns

The deeply underlying distribution after all unwrapping is complete.

Examples

julia
using ModifiedDistributions, Distributions

# Single wrapper - same as get_dist
wd = weight(LogNormal(1.5, 0.75), 2.0)
get_dist_recursive(wd)

# Nested wrappers
nested = weight(affine(Normal(0, 1); scale = 2.0), 3.0)
get_dist_recursive(nested)

# Base distribution - returns unchanged
get_dist_recursive(Normal(0, 1))

Note

For a wrapper that unwraps to a vector of components, this function applies recursive extraction to each component, potentially returning mixed types of underlying distributions.

source
ModifiedDistributions.hazard_link Function
julia
hazard_link(g, invlink) -> ModifiedDistributions.HazardLink

Wrap a link and its inverse as a HazardLink.

The link g maps a hazard onto the scale the additive effect acts on, and invlink maps back. Use the built-in LogLink or IdentityLink for the analytic choices; this constructor is for a user-supplied invertible callable. Note that modify currently rejects links other than log and identity, since general links need numeric cumulative-hazard integration.

Arguments

  • g: the link function g.

  • invlink: the inverse link g⁻¹.

Examples

julia
using ModifiedDistributions

# A complementary-log-log link.
cloglog = ModifiedDistributions.hazard_link(
    h -> log(-log1p(-h)), x -> -expm1(-exp(x)))

See also

  • modify: the verb that consumes a link.
source
ModifiedDistributions.modify Function
julia
modify(
    dist::Distributions.UnivariateDistribution,
    effect::Real;
    link
) -> ModifiedDistributions.Modified{D, E, ModifiedDistributions.HazardLink{typeof(log), typeof(exp)}} where {D<:(Distributions.UnivariateDistribution), E<:Real}

Modify the hazard of a distribution through a link.

modify(d, effect; link = log) returns a Modified distribution whose hazard is   , where g is the link (log for proportional hazards, identity for additive hazards). The modification is instantiated lazily, so the result composes everywhere a UnivariateDistribution does.

Both supported links use closed forms. The identity link requires effect >= 0: a negative additive effect can push the hazard below zero, which needs hazard clamping and numeric cumulative-hazard integration (see CensoredDistributions#670/#680); that path stays upstream in CensoredDistributions, as does the discrete (interval-censored) path. Links other than log and identity are rejected for the same reason. The identity link also requires a base with a finite lower support bound m (the extra hazard accrues from m, so an unbounded-below base has no valid additive form).

Arguments

  • d: the base continuous distribution.

  • effect: the scalar hazard modification on the link scale.

Keyword Arguments

  • link: the hazard link. The functions log (default) and identity, the symbols :log/:identity, or a HazardLink.

Examples

julia
using ModifiedDistributions, Distributions

# Proportional hazards: halve the hazard of a LogNormal delay.
d = modify(LogNormal(1.5, 0.5), -log(2.0); link = log)
ccdf(d, 2.0)

# Additive hazards: a constant extra hazard.
da = modify(LogNormal(1.5, 0.5), 0.2; link = identity)
cdf(da, 2.0)

See also

source
julia
modify(
    dist::Distributions.UnivariateDistribution,
    _::Nothing
) -> Distributions.UnivariateDistribution

Return the distribution unmodified when the effect is nothing.

This lets callers thread an optional hazard effect through modify(dist, effect) and pass nothing to mean "no modification": the distribution is returned unchanged, mirroring weight(dist, nothing).

Examples

julia
using ModifiedDistributions, Distributions

d = LogNormal(1.5, 0.5)
modify(d, nothing) === d
source
ModifiedDistributions.series_transform Function
julia
series_transform(
    d::Distributions.UnivariateDistribution,
    op
) -> ModifiedDistributions.Transformed

Map a distribution's convolved count series through a forward op.

series_transform(d, op) carries op (a thin/cumulative op or any callable series -> series) intended for the series a downstream convolution layer produces. Transparent to logpdf. Prefer thin / cumulative for the common cases; use series_transform for an arbitrary deterministic series map. Renamed from transform so it cannot clash with DataFrames.transform (#35).

Arguments

  • d: the inner distribution.

  • op: a forward op or a callable series -> series.

Examples

julia
using ModifiedDistributions, Distributions

d = series_transform(Gamma(2.0, 1.0), s -> 0.5 .* s)
logpdf(d, 2.0) == logpdf(Gamma(2.0, 1.0), 2.0)

See also

source
ModifiedDistributions.thin Function
julia
thin(
    dist::Distributions.UnivariateDistribution,
    p::Real
) -> ModifiedDistributions.Transformed{D, Op} where {D<:(Distributions.UnivariateDistribution), Op<:ModifiedDistributions.ThinOp}

Thin a distribution's forward count by a probability p.

thin(d, p) is series_transform with a fixed factor p ∈ [0, 1] intended to be multiplied into a downstream count series (e.g. ascertainment of cases, the infection fatality ratio for deaths). Transparent to logpdf. thin(d, nothing) returns d unchanged.

Arguments

  • d: the inner distribution.

  • p: the thinning probability in .

Examples

julia
using ModifiedDistributions, Distributions

d = thin(LogNormal(1.5, 0.5), 0.3)
logpdf(d, 2.0) == logpdf(LogNormal(1.5, 0.5), 2.0)

See also

source
ModifiedDistributions.weight Function
julia
weight(
    dist::Distributions.UnivariateDistribution,
    w::Real
) -> ModifiedDistributions.Weighted{D, T} where {D<:(Distributions.UnivariateDistribution), T<:Real}

Create a weighted distribution where the log-probability is scaled by w.

A Weighted distribution will contribute w * logpdf(dist, x) to the log-probability when evaluating logpdf(weighted_dist, x). Unlike an ad hoc w * logpdf(dist, x) term in model code, the result is still a real distribution whose sampling delegates to dist, so a Turing.jl model (or any PPL built on Distributions.jl) that uses it stays a complete generative model with working prior and posterior-predictive simulation.

Examples

julia
using ModifiedDistributions, Distributions

# For aggregated count data
y_obs = 3.5  # Observed value
n_count = 25  # Number of times this value was observed

d = Normal(2.0, 1.0)
weighted_d = weight(d, n_count)

# Weighted log-probability calculation
weighted_logpdf = logpdf(weighted_d, y_obs)
# equivalent to: n_count * logpdf(d, y_obs)
source
julia
weight(
    dist::Distributions.UnivariateDistribution,
    _::Nothing
) -> Distributions.UnivariateDistribution

Return the distribution unweighted when the weight is nothing.

This lets callers thread an optional weight through weight(dist, w) and pass nothing to mean "no weight": the distribution is returned unchanged.

Examples

julia
using ModifiedDistributions, Distributions

d = Normal(2.0, 1.0)
weight(d, nothing) === d
source
julia
weight(
    dist::Distributions.UnivariateDistribution,
    weights::AbstractVector{<:Real}
) -> Any

Create a product distribution of weighted distributions, each with a different weight.

A Product distribution of Weighted distributions suitable for vectorised observations.

Arguments

  • dist: The univariate distribution to be replicated and weighted for each observation

  • weights: Vector of weights to apply to each copy of the distribution

Examples

julia
using ModifiedDistributions, Distributions

y_obs = [3.5, 4.2, 3.8]  # Observed values
n_counts = [25, 10, 15]  # Counts for each observation

d = Normal(2.0, 1.0)
weighted_dists = weight(d, n_counts)

# Weighted log-probability calculation
weighted_logpdf = logpdf(weighted_dists, y_obs)
# equivalent to: sum(n_counts .* logpdf.(d, y_obs))

See also

  • Weighted: The underlying weighted distribution type
source
julia
weight(
    dists::AbstractVector{<:Distributions.UnivariateDistribution},
    weights::AbstractVector{<:Real}
) -> Any

Create a product distribution of weighted distributions, where each distribution has its own weight.

A Product distribution of Weighted distributions suitable for vectorised observations with different distributions.

Examples

julia
using ModifiedDistributions, Distributions

y_obs = [3.5, 4.2, 3.8]  # Observed values
dists = [Normal(2.0, 0.5), Normal(2.5, 0.8), Normal(1.8, 0.6)]
n_counts = [25, 10, 15]  # Counts for each observation
weighted_dists = weight(dists, n_counts)
source
julia
weight(
    dist::Distributions.UnivariateDistribution
) -> ModifiedDistributions.Weighted{D, Missing} where D<:(Distributions.UnivariateDistribution)

Create a weighted distribution with missing constructor weight.

Useful for creating distributions where weights will be provided at observation time. Uses missing as constructor weight, enabling observation weight to be used directly.

Examples

julia
using ModifiedDistributions, Distributions

d = Normal(2.0, 0.5)

# Create weighted distribution with missing constructor weight
weighted_dist = weight(d)

# Weight provided at observation time via joint observations
logpdf(weighted_dist, (value = 3.5, weight = 25))
source
julia
weight(
    dists::AbstractVector{<:Distributions.UnivariateDistribution}
) -> Any

Create a product distribution of weighted distributions with missing constructor weights.

Useful for creating distributions where weights will be provided at observation time. Each distribution uses missing as constructor weight, enabling observation weight to be used directly.

Examples

julia
using ModifiedDistributions, Distributions

y_obs = [3.5, 4.2, 3.8]  # Observed values
dists = [Normal(2.0, 0.5), Normal(2.5, 0.8), Normal(1.8, 0.6)]

# Create weighted distributions with missing constructor weights
weighted_dists = weight(dists)

# Weights provided at observation time via joint observations
logpdf(weighted_dists, (values = y_obs, weights = [25, 10, 15]))
source