Distributions

Every distribution below implements log_prob, a reparameterized sample where possible, and closed-form mean/variance/ quantile where they exist in closed form. Parameters may themselves be Expr (typically Param), so a distribution’s shape can be learned or driven by upstream geometry. Each family below is shown with its probability-density plots and, where useful, parameter-sensitivity sweeps.

Univariate

Gaussian

Gaussian(mean, sigma)

Weibull

Weibull(scale, concentration)

Exponential

Exponential(rate)

LogNormal

LogNormal(mu, sigma)

Gamma

Gamma(concentration, rate)

Beta

Beta(alpha, beta)

Uniform

Uniform(low, high)

Gumbel

Gumbel(loc, scale)

TruncatedGaussian

TruncatedGaussian(mean, sigma, low, high)

Parameter sensitivity

Each univariate distribution also has a small-multiples sensitivity panel and per-parameter sweeps, e.g.:

Weibull — parameter sensitivity grid

Gaussian — effect of sigma

Cumulative distributions

Closed-form quantiles give exact CDFs (Gaussian, Weibull, Exponential, Uniform, Gumbel); the remaining families are integrated numerically.

Weibull — CDF (closed-form quantile)

Gamma — CDF (numeric)

class prophys.distributions.Gaussian(mean=0.0, sigma=1.0)[source]
Parameters:
  • mean (Any)

  • sigma (Any)

class prophys.distributions.Weibull(scale=1.0, concentration=1.0)[source]

Scale-shape parameterization: p(x) = (k/lam) (x/lam)^(k-1) exp(-(x/lam)^k).

Parameters:
  • scale (Any)

  • concentration (Any)

class prophys.distributions.Exponential(rate=1.0)[source]
Parameters:

rate (Any)

class prophys.distributions.LogNormal(mu=0.0, sigma=1.0)[source]
Parameters:
  • mu (Any)

  • sigma (Any)

class prophys.distributions.Gamma(concentration=1.0, rate=1.0)[source]
Parameters:
  • concentration (Any)

  • rate (Any)

class prophys.distributions.Beta(alpha=1.0, beta=1.0)[source]
Parameters:
  • alpha (Any)

  • beta (Any)

class prophys.distributions.Uniform(low=0.0, high=1.0)[source]
Parameters:
  • low (Any)

  • high (Any)

class prophys.distributions.Gumbel(loc=0.0, scale=1.0)[source]
Parameters:
  • loc (Any)

  • scale (Any)

class prophys.distributions.TruncatedGaussian(mean=0.0, sigma=1.0, low=-inf, high=inf)[source]
Parameters:
class prophys.distributions.Bernoulli(prob=0.5)[source]
Parameters:

prob (Any)

class prophys.distributions.Poisson(rate=1.0)[source]
Parameters:

rate (Any)

class prophys.distributions.Categorical(probs)[source]
Parameters:

probs (Any)

Circular

For angular quantities like wind direction, where ordinary Gaussians are wrong because \(0\) and \(2\pi\) are the same point.

VonMises — concentration sweep

Higher kappa -> more concentrated around loc.

WrappedGaussian — sigma sweep

A Gaussian wrapped onto the circle.

class prophys.distributions.VonMises(loc=0.0, kappa=1.0)[source]

Von Mises distribution on the circle (radians), the circular analog of a Gaussian. loc is the mean direction, kappa the concentration (kappa -> 0 is uniform, kappa -> inf concentrates at loc).

Parameters:
  • loc (Any)

  • kappa (Any)

class prophys.distributions.WrappedGaussian(loc=0.0, sigma=1.0, n_wraps=3)[source]

A Gaussian wrapped onto the circle; approximate log-density via a small number of wraps (n_wraps terms on each side), which is accurate for sigma well below 2*pi.

Parameters:
  • loc (Any)

  • sigma (Any)

  • n_wraps (int)

Directional climatologies

DirectionalMixture is the standard representation of a directional climatology — wind rose, wave rose, current regime, or any other joint distribution of “which direction” and “how strong”: the circle is divided into sectors, each with an occurrence weight, a circular spread (a VonMises around the sector center), and its own conditional intensity distribution (e.g. a per-sector Weibull of wind speed). All parameters — sector weights, spreads, and every conditional intensity distribution’s parameters — are ordinary Exprs, so a climatology fitted from met-mast or reanalysis observations is a single fit_distribution() call, and its sector weights can just as well be design variables (e.g. trading off wake losses against a site’s directional wind resource).

import jax.numpy as jnp
import prophys as prp

sector_speeds = [
    prp.Weibull(scale=prp.Param(f"scale_{i}", init=7.0), concentration=2.0)
    for i in range(8)
]
wind_rose = prp.DirectionalMixture.evenly_spaced(
    weights=prp.Param("sector_weights", shape=(8,), init=jnp.full((8,), 1 / 8)),
    intensities=sector_speeds,
)
wind_rose.log_prob(direction=jnp.deg2rad(200.0), intensity=9.5)
class prophys.distributions.DirectionalMixture(directions, concentrations, intensities, logits)[source]

A joint distribution over an angle and a conditional intensity — the standard representation of directional climatologies (wind or wave climate, current regimes, directional seismic loading): the circle is divided into k directional sectors, each with an occurrence weight, a circular spread around its center direction, and its own conditional intensity distribution (e.g. a per-sector Weibull of wind speed).

  • directions: sector center angles in radians, shape (k,)

  • concentrations: von Mises concentration per sector, shape (k,) (higher = narrower sector; may be a learnable Param)

  • intensities: k conditional intensity distributions, one per sector

  • logits: unnormalized sector occurrence log-weights, shape (k,) (normalized internally via softmax; may be a learnable Param)

All parameters are Expr`s, so the whole climatology is calibratable against observed ``(angle, intensity)` pairs with fit_distribution.

Parameters:
  • directions (Any)

  • concentrations (Any)

  • intensities (Sequence[Distribution])

  • logits (Any)

classmethod evenly_spaced(weights, intensities, concentration=None)[source]

Build a climatology with k sectors evenly spaced around the circle (sector 0 centered at angle 0) from occurrence weights (e.g. observed sector frequencies, shape (k,), normalized internally). concentration defaults to a spread that roughly tiles the circle (kappa such that one sector width ~ one std).

Parameters:
  • weights (Any)

  • intensities (Sequence[Distribution])

  • concentration (Any)

Return type:

DirectionalMixture

log_prob(direction, intensity)[source]

Joint log-density of (direction, intensity) pairs (radians, intensity units), elementwise over the inputs.

Parameters:
  • direction (Any)

  • intensity (Any)

Return type:

Expr

sample(key, shape=())[source]

Draw (direction, intensity) pairs, shape shape + (2,): pick a sector per draw, then sample its direction spread and its conditional intensity.

Parameters:
Return type:

Expr

mean_intensity()[source]

Sector-weighted mean intensity.

Return type:

Expr

mean_direction()[source]

Circular mean of the sector centers under the occurrence weights (the resultant direction), in radians.

Return type:

Expr

Multivariate & mixtures

MultivariateGaussian

Cholesky-parameterized covariance — always positive-definite under gradient updates.

Mixture

Finite mixture with softmax-normalized weights.

Empirical

Kernel-density estimate from raw samples — stays differentiable.

Histogram

Piecewise-constant density from bin edges/probabilities.

class prophys.distributions.MultivariateGaussian(mean, cholesky)[source]

mean shape (d,), cholesky shape (d, d) — lower-triangular factor of the covariance (cov = L @ L.T); parameterizing via the Cholesky factor keeps the covariance positive-definite by construction under gradient updates.

Parameters:
  • mean (Any)

  • cholesky (Any)

class prophys.distributions.Mixture(components, logits)[source]

A finite mixture of component distributions with (possibly learnable) log-weights, normalized internally via softmax.

Parameters:
  • components (Sequence[Distribution])

  • logits (Any)

sample(key, shape=())[source]

Draw samples: pick a component per draw (categorical on the mixture logits) then sample from that component.

Parameters:
Return type:

Expr

class prophys.distributions.Empirical(samples, bandwidth=0.1)[source]

A distribution defined by a fixed sample set, e.g. observed wind speeds. log_prob uses kernel-density estimation (Gaussian kernel, bandwidth bw) so it stays differentiable; sample resamples with replacement.

Parameters:
  • samples (Any)

  • bandwidth (float)

class prophys.distributions.Histogram(edges, probs)[source]

A piecewise-constant density from bin edges (n+1,) and probs (n,), normalized internally.

Parameters:
  • edges (Any)

  • probs (Any)

Copulas & dependence structures

A GaussianCopula couples arbitrary marginals (each just needs a quantile method) through a correlation matrix that is parameterized so it is always valid — an unconstrained gradient step can never produce a non-positive-definite correlation matrix.

rho = -0.7
rho = 0
rho = +0.7
class prophys.distributions.GaussianCopula(marginals, corr_raw)[source]

A Gaussian copula coupling marginals (a list of Distribution, each with a quantile method) via a correlation structure.

The correlation is parameterized by a raw unconstrained vector (the hyperspherical/LKJ-style Cholesky construction lives in the native prophys._ffi.copula_logp kernel), so it may be an Expr/Param and remain a valid correlation matrix under any gradient step.

Parameters:
  • marginals (Sequence[Distribution])

  • corr_raw (Any)

class prophys.distributions.Correlation(marginal_a, marginal_b, rho_raw)[source]

Convenience: a bivariate Gaussian copula between two marginals, parameterized directly by rho in (-1, 1) via tanh of a raw Expr.

Parameters:
  • marginal_a (Distribution)

  • marginal_b (Distribution)

  • rho_raw (Any)

class prophys.distributions.Independent(marginals)[source]

Explicit product of independent marginals (a degenerate copula with zero correlation, provided for readability at call sites).

Parameters:

marginals (Sequence[Distribution])

Discrete distributions

Poisson
Bernoulli