Transformations#
A Transform is a composable, callable mapping Expr -> Expr.
Bijective transforms additionally implement inverse and
log_det_jacobian, so they can double as a distribution bijector via
TransformedDistribution.
a * x + b — bijective, with closed-form inverse.
A @ x + b for vector-valued x.
sum_i coeffs[i] * x**i.
smooth=0 gives the exact (subgradient) curve; smooth=tau
blends neighbouring segments for a fully continuous gradient at the
knots.
Exponential (exp(-x/scale)) or power-law decay, typically
composed after a distance primitive.
Dose-response / regulatory-acceptance curves.
Interpolated 1D characteristic curve (e.g. a power curve).
Bilinearly interpolated 2D lookup (e.g. sound power level over wind speed x direction).
Smoothing behavior of PiecewiseLinear#
Because a hard piecewise-linear kink has a discontinuous gradient at each
knot, PiecewiseLinear lets the smoothing temperature trade exactness
against gradient continuity:
A smooth value that is too large relative to the knot spacing will
blend in neighbouring segments’ slopes even at points deep inside one
segment — worth checking for if a transformed probability unexpectedly
drifts outside its valid range (e.g. below 0 for a probability fed into
Bernoulli).
- class prophys.transformations.Transform[source]#
Base class of deterministic transformations that map expressions to expressions.
A transform is called like a function,
t(x), and returns a new Expr. Transforms compose withthen(). Bijective transforms additionally implement inverse and log_det_jacobian, so they can be used to build aTransformedDistribution.Example:
attenuation = prp.Decay(scale=150.0).then(prp.Linear(a=0.9, b=0.05)) exposure = attenuation(houses.closest_distance(source))
- log_det_jacobian(x)[source]#
Return
log|det J(x)|of the forward map at x, as an expression (bijective transforms only).
- class prophys.transformations.Linear(a=1.0, b=0.0)[source]#
Elementwise linear map
y = a * x + b, bijective fora != 0.- Parameters:
a (Any) – Slope, a scalar or broadcastable array. It may be an Expr such as a Param, making it learnable.
b (Any) – Intercept, likewise.
- class prophys.transformations.Affine(A, b=0.0)[source]#
Affine map
y = A @ x + bof a vector x, bijective for invertible A.- Parameters:
A (Any) –
(d, d)matrix, possibly an expression.b (Any) –
(d,)offset (or scalar), possibly an expression.
- class prophys.transformations.Polynomial(coeffs)[source]#
Elementwise polynomial
y = sum_i coeffs[i] * x**i, lowest order first. Not bijective.- Parameters:
coeffs (Sequence[Any]) – Coefficients
c0, c1, ..., each may be an expression.
Example:
drag = prp.Polynomial([0.0, 0.0, 0.5 * rho * cd * area]) # 0.5 rho Cd A v^2
- class prophys.transformations.PiecewiseLinear(knots, values, smooth=0.0)[source]#
Piecewise linear curve through
(knots[i], values[i]).smooth=0 (default) gives the exact piecewise linear function, clamped flat beyond the end knots, which reproduces a dose response table exactly. smooth=tau > 0 blends the segment lines with soft weights, so the gradient in x is continuous across the knots too. The smooth curve extends the end segments linearly beyond the end knots instead of clamping.
- Parameters:
Example:
damage = prp.PiecewiseLinear(knots=[0.0, 0.5, 2.0], values=[0.0, 0.2, 1.0]) # depth [m] -> damage ratio
- class prophys.transformations.Decay(scale=1.0, kind='exp')[source]#
Exponential or power law decay with distance, typically composed after a distance primitive.
kind="exp"givesexp(-x / scale)andkind="power"givesx ** (-scale), so scale is then the exponent of the power law.- Parameters:
scale (Any) – Decay length (
"exp") or exponent ("power"), may be a Param.kind (str) –
"exp"or"power". Any other value raises ValueError when the transform is applied.
- class prophys.transformations.Logistic(x0=0.0, k=1.0, L=1.0)[source]#
Logistic dose response curve
L / (1 + exp(-k * (x - x0))).- Parameters:
x0 (Any) – Midpoint, where the curve reaches
L / 2.k (Any) – Steepness (per unit of x).
L (Any) – Upper asymptote.
- class prophys.transformations.TableLookup1D(grid, values)[source]#
Linearly interpolated 1D lookup table, e.g. a wind turbine power curve.
Equivalent to an exact
PiecewiseLinear, clamped flat beyond the table ends.
Periodic & recurring phenomena#
For seasonal, diurnal, tidal, or otherwise recurring signals — and for the “return period” framing common in extreme-event risk (e.g. a “100-year flood”).
- class prophys.transformations.Phase(period=1.0)[source]#
Wrap a continuous variable into
[0, period), e.g. hours since start into hour of day.Uses a floor modulo, which is continuous except at the wrap points (measure zero), the same character as the library’s other hard boundary primitives (PiecewiseLinear with
smooth=0, polygon containment).- Parameters:
period (Any) – Wrap period, in the units of the input.
- class prophys.transformations.Periodic(period, amplitude, phase=None, offset=0.0)[source]#
Learnable finite Fourier series for seasonal, diurnal or tidal signals.
y = offset + sum_k amplitude[k] * cos(2*pi*k*x/period - phase[k])amplitude and phase are sequences with one coefficient per harmonic, and their length is the number of harmonics. All coefficients may be Expr (typically Param), so the shape of a seasonal cycle can be learned from data with fit_distribution, calibrate or finetune like any other parameter. Harmonic
kruns from 1 to the number of harmonics.- Parameters:
period (Any) – Period of the fundamental, in the units of the input.
amplitude (Sequence[Any]) – Amplitude of each harmonic.
phase (Sequence[Any] | None) – Phase shift of each harmonic in radians (zeros by default).
offset (Any) – Constant term.
- Raises:
ValueError – When amplitude and phase differ in length.
Example:
season = prp.Periodic(365.25, amplitude=[prp.Param("a1", init=3.0)], phase=[prp.Param("p1", init=0.0)], offset=12.0) temperature_mean = season(day_of_year)
- class prophys.transformations.ReturnPeriod[source]#
Convert an annual exceedance probability to a return period
1 / pand back.This is the familiar “flood of 100 years” framing.
return_period = 1 / exceedance_probabilityBijective and defined for
p in (0, 1], with p clipped at1e-12. Use inverse to go from a target return period back to the probability an event or annual model needs to reproduce it.
- class prophys.transformations.RecurrenceRate[source]#
Convert a mean time between events to an event rate
1 / intervaland back.The rate is the natural parameter for a Poisson process modeling recurring hazards (equipment failures, extreme weather events and so on).
rate = 1 / mean_interval. Modulating the rate with a Periodic signal gives an inhomogeneous Poisson process, whose counts over a window of lengthwfollowprp.Poisson(rate * w). There is no log_det_jacobian, so it is not usable as a distribution bijector.