API Reference

prophys.symbolic

prophys.frames

prophys.structures

prophys.transformations

prophys.distributions

prophys.processes

prophys.domain

prophys.engine

prophys.export

Standardized export of a compiled model, with provenance.

prophys.inference

Full posterior inference for a compiled prophys model.

prophys.io

Reading measurement records into prophys objects.

prophys.plot

prophys.units

Physical units and dimensional checking.

Symbolic core

class prophys.symbolic.Expr[source]

Base class for all symbolic nodes.

Subclasses must implement _evaluate() and _children(). Operators are implemented once here in terms of Op, so new leaf/operator types automatically get + - * / ** @ etc.

evaluate(env=None)[source]

Evaluate this expression to a concrete jax.numpy array.

env maps Param/Input names to values; leaves without an entry fall back to their declared default/init value (for Param) or raise if no default exists (for Input).

Parameters:

env (Mapping[str, Any] | None)

Return type:

Any

params()[source]

Collect all distinct Param leaves reachable from this node.

Return type:

dict[str, Expr]

class prophys.symbolic.Const(value)[source]

A fixed constant (Python scalar, NumPy array, or JAX array).

Parameters:

value (Any)

class prophys.symbolic.Input(name, shape=None)[source]

A named placeholder for data supplied at evaluation time (e.g. observations). Unlike Param, an Input is never optimized.

Parameters:
class prophys.symbolic.Param(name, shape=(), init=0.0, bounds=None, transform=None)[source]

A named, learnable/optimizable leaf.

bounds=(lo, hi) constrains the unconstrained optimization variable through a sigmoid transform; transform=”softplus” constrains to positive values. The raw (unconstrained) value lives in the parameter dict used by the engine; _evaluate always applies the forward transform, so downstream expressions see the constrained value.

Parameters:
unconstrained_init()[source]

Initial value in unconstrained space (what the optimizer sees).

Return type:

Any

forward(raw)[source]

Map an unconstrained value to the constrained value seen by the graph.

Parameters:

raw (Any)

Return type:

Any

class prophys.symbolic.Surrogate(fn, *args, name='surrogate')[source]

Wrap an arbitrary pure JAX-compatible callable as a symbolic node.

Use this for user-supplied physics (e.g. a noise propagation formula or a power curve) that doesn’t need to be expressed in terms of other prophys primitives, but must still be differentiable.

Parameters:
  • args (Any)

  • name (str)

class prophys.symbolic.BinaryState(name, init=0.5, mode=None, tau=None)[source]

A learnable on/off state.

Evaluates to a scalar in [0, 1]: exactly 0/1 in eval mode (hard threshold at logit 0), and sigmoid(logit / tau) in opt mode, so a design optimizer can trade the state continuously and the final hard decision is read off the same graph.

Multiply it into any expression to gate that term:

flow = pipe_capacity * prp.BinaryState("valve_a", init=0.9)
Parameters:
class prophys.symbolic.CategoricalState(name, k, init=None, mode=None, tau=None)[source]

A learnable choice among k discrete states.

Evaluates to a (k,) assignment vector on the probability simplex: a hard one-hot argmax in eval mode, and a tempered softmax(logits / tau) in opt mode. Dot it with a vector of per-state consequences to make the choice differentiable:

setting = prp.dot(prp.CategoricalState("pump_mode", 3), jnp.array([0.0, 0.5, 1.0]))
Parameters:

Processes

class prophys.Autoregressive(init, mean, phi, innovation, n_steps, dt=1.0, geometry=None)[source]

First-order autoregressive process with a pluggable innovation distribution:

x_t = mean + phi (x_{t-1} - mean) + eps_t, x_0 = init, eps_t ~ innovation (i.i.d.).

phi in (-1, 1) gives mean reversion with serial correlation — the minimal structure under which “the past matters”: consecutive steps are dependent, so path-dependent quantities built downstream (running totals, drawdowns, hard-threshold excursions) have non-trivial distributions, unlike under i.i.d. draws.

innovation is any Distribution exposing quantile (for sampling) and log_prob (for path density); its parameters may be Param instances and are calibrated from observed paths like any other (fit_distribution works unchanged: log_prob of a (batch, n_steps) array of paths has shape (batch,)). All process parameters may be Expr instances.

geometry sets the space the state lives in: the default Linear is the real line; a Circular makes the mean-reversion difference and the per-step placement operate modulo the circle’s period, so the process is correct for angular state (see circular_autoregressive). The innovation itself always lives in the (Euclidean) difference space, so any real-valued innovation distribution composes with either geometry.

Parameters:
  • init (Any)

  • mean (Any)

  • phi (Any)

  • innovation (Distribution)

  • n_steps (int)

  • dt (float)

  • geometry (Geometry | None)

innovations(x)[source]

Residuals eps_t = residual(x_t, predicted_t) — the innovation draws implied by an observed path, in the state geometry. Pure algebra; all density evaluation happens in the innovation distribution.

Parameters:

x (Any)

Return type:

Expr

path_from_innovations(eps)[source]

Path from concrete innovation values (*batch, n_steps).

Parameters:

eps (Any)

Return type:

Expr

path_from_uniforms(u)[source]

Deterministic map from per-step uniforms (*batch, n_steps) in (0, 1) to the path (*batch, n_steps).

Parameters:

u (Any)

Return type:

Expr

mean()[source]

E[x_t] for t = 1..n_steps, shape (n_steps,): the AR recursion applied to the innovation distribution’s mean, placed into the state geometry. For a Circular geometry this is the wrapped linear-recursion mean, exact only in the concentrated regime where the state stays away from the wrap seam.

Return type:

Expr

class prophys.RandomWalk(init, innovation, n_steps, dt=1.0)[source]

Pure accumulation of innovations: x_t = x_{t-1} + eps_t (the phi = 1 boundary of Autoregressive, where the level mean drops out). Drift and step scale live entirely in the innovation distribution — e.g. Gaussian(drift * dt, sigma * sqrt(dt)).

Parameters:
  • init (Any)

  • innovation (Distribution)

  • n_steps (int)

  • dt (float)

prophys.ornstein_uhlenbeck(init, mean, theta, sigma, n_steps, dt=1.0)[source]

Ornstein-Uhlenbeck process dx = theta (mean - x) dt + sigma dW on a regular grid, via its exact discretization: an Autoregressive with phi = exp(-theta dt) and Gaussian innovations of standard deviation sigma sqrt((1 - exp(-2 theta dt)) / (2 theta)) (continuous-time theta/sigma, which must be positive, stay meaningful under any dt).

A factory, not a class: the derived parameters are ordinary symbolic expressions of theta/sigma, so both remain calibratable/optimizable leaves like any other Param.

Parameters:
Return type:

Autoregressive

prophys.circular_autoregressive(init, mean, phi, innovation, n_steps, dt=1.0, period=360.0)[source]

An Autoregressive on the circle of circumference period (default 360, i.e. degrees): mean reversion follows the shortest signed arc and each state is folded into [0, period), so the process is correct for angular quantities such as wind direction where the linear recursion would revert the long way around and report spurious ramps across the wrap seam.

A factory, not a class: it is Autoregressive with a Circular geometry, so every parameter stays a calibratable/optimizable Expr and it composes into a JointProcess like any other.

Parameters:
Return type:

Autoregressive

class prophys.JointProcess(processes, corr_raw)[source]

k autoregressive processes with instantaneously coupled innovations.

sample(key, shape) returns (*shape, n_steps, k) — the component axis last, matching the JointRandomVariable component-slicing convention, so joint["name"] yields a (*shape, n_steps) path.

corr_raw is an unconstrained k(k-1)/2 vector (may be a Param); it is the same raw correlation parameterization as GaussianCopula — always a valid correlation matrix under gradient updates, and one fitted value means the same matrix in the density and sampling directions.

Parameters:
log_prob(x)[source]

Log-density of a joint path batch (..., n_steps, k).

Parameters:

x (Any)

Return type:

Expr

class prophys.Recurrence(name, step, init, drivers, params=(), output='path')[source]

A lax.scan over the time axis as a symbolic node.

step(carry, drivers_t, params) -> (carry, output_t) is a pure function of jax.numpy values: drivers_t is a tuple with one entry per driver expression (each the (..., ) slice of that driver at one time step), params a tuple of the evaluated params_ expressions (constant along the path). Drivers carry time as their last axis and are broadcast against each other; init must broadcast against their common batch shape.

output="path" evaluates to the stacked per-step outputs with time as the last axis, output="final" to the final carry. The scan is inside the same JAX trace as everything else, so jit/grad/vmap flow through the recursion — including into init, every driver, and every parameter.

Parameters:
  • name (str)

  • step (Callable[..., Any])

  • init (Any)

  • drivers (Sequence[Any])

  • params (Sequence[Any])

  • output (str)

class prophys.Geometry[source]

Difference and placement operations of a value space.

residual(x, ref)[source]

Signed difference of x from ref (x - ref on the line).

Parameters:
Return type:

Any

wrap(x)[source]

Canonical representative of x in the value space.

Parameters:

x (Any)

Return type:

Any

class prophys.LinearGeometry[source]

The real line: difference is subtraction, placement is the identity.

residual(x, ref)[source]

Signed difference of x from ref (x - ref on the line).

Parameters:
Return type:

Any

wrap(x)[source]

Canonical representative of x in the value space.

Parameters:

x (Any)

Return type:

Any

class prophys.Circular(period=6.283185307179586)[source]

The circle of circumference period: difference is the shortest signed arc in (-period/2, period/2], placement folds into [0, period).

Parameters:

period (float)

residual(x, ref)[source]

Signed difference of x from ref (x - ref on the line).

Parameters:
Return type:

Any

wrap(x)[source]

Canonical representative of x in the value space.

Parameters:

x (Any)

Return type:

Any

prophys.time_diff(x, geometry=None)[source]

First difference along the time axis: (..., T) -> (..., T-1). The building block for step-change magnitudes (combine with abs_, relu, threshold kernels, …).

With a geometry the difference is taken in that space — a Circular geometry gives the shortest signed step for angular paths, so a change from 359 deg to 1 deg reads as +2, not -358.

Parameters:
Return type:

Expr

Domain layer

class prophys.domain.UncertainAttribute(name, distribution, unit='', domain='')[source]

A named, documented uncertain quantity — the primary unit of meaning in prophys. Carries metadata (unit, domain description) used by diagnostics, plotting, and export, in addition to the plain RandomVariable graph behavior.

Parameters:
property measurement_unit

The parsed Unit of this attribute.

convert(values, to)[source]

Convert values of this attribute into another unit.

Raises UnitError when to measures a different quantity, which is the check that makes an attribute declared in “kW” impossible to read as “kWh”.

Parameters:

to (str)

upstream_random_variables()[source]

All RandomVariable leaves this attribute’s distribution depends on (e.g. an attribute whose mean is derived from wind speed/direction).

Return type:

dict[str, RandomVariable]

class prophys.domain.AttributeInteractions(attributes, coupling)[source]

A joint dependence structure over several UncertainAttribute objects (Gaussian copula or plain correlation), used when attributes shouldn’t be assumed independent.

Parameters:
class prophys.domain.ProbabilityModel(*attributes, interactions=None)[source]

A named collection of UncertainAttribute instances (optionally coupled by AttributeInteractions), representing one probabilistic model.

This is the standardized handoff object: build it once from symbolic pieces, then call .compile(…) to obtain a CompiledModel with a stable log_prob/sample/expectation interface.

Parameters:
random_variables()[source]

All upstream RandomVariable leaves referenced anywhere in the model (e.g. wind speed/direction feeding a noise surrogate).

compile(mode='eval', tau=1.0, n_samples=256, seed=0)[source]

Compile this model into a CompiledModel.

mode="eval" uses hard min/max/contains everywhere in the geometry graph (exact evaluation); mode="opt" uses the smooth (soft) approximations at temperature tau, suitable for gradient- based calibration/design optimization. n_samples and seed control the default Monte-Carlo marginalization sample size and PRNG seed for any upstream RandomVariable leaves. n_samples is not license-limited (see License) — the free-tier object gate applies to structural model size (points, polygon vertices, segments, …), not to Monte-Carlo marginalization precision.

Parameters:
class prophys.domain.RandomVariable(name, distribution)[source]

A named stochastic leaf backed by a Distribution.

Evaluating a RandomVariable requires either:

  • a bound concrete value in env[name] (e.g. an observation), or

  • a pre-drawn sample in env[“__rv_samples__”][name], which is how the engine’s Monte-Carlo marginalization feeds samples through the graph while keeping everything inside a single JAX trace.

The distribution may be a scalar family or a Process (a distribution over discretely-indexed paths): the engine treats both identically, and a path-valued sample simply carries the index/time axis as its last axis (the Monte-Carlo sample axis stays axis 0).

Parameters:

name (str)

Frames

class prophys.frames.Frame(name, ndim=2, units='m', crs=None)[source]

A named coordinate system.

Parameters

name:

Unique identifier used for equality/compatibility checks.

ndim:

2 or 3.

units:

Free-text unit label (e.g. "m"), used only for documentation and plotting.

crs:

Optional EPSG/CRS tag, purely informational — used by the optional geo I/O extras when projecting external data into this frame.

property unit: Unit

The parsed coordinate unit of this frame.

Parameters:
class prophys.frames.FrameTransform(from_, to, matrix=None, offset=None)[source]

A differentiable affine map between two frames: y = R @ x + t.

matrix has shape (to.ndim, from_.ndim), offset has shape (to.ndim,). Both are plain arrays (not Expr) — frame alignment is considered a fixed, known calibration, not an optimizable quantity.

Parameters:
property unit_scale: float

The pure unit-conversion factor between the two frames, ignoring any rotation or translation this transform also applies.

apply(points)[source]

Map an (..., ndim_from) array of points into to’s frame.

Parameters:

points (Any)

Return type:

Any

class prophys.frames.FrameRegistry[source]

Process-local registry of transforms between frames.

A tiny convenience so structures declared in different (but related) frames can still be combined without the user re-threading transforms through every call.

align(points, from_, to)[source]

Return points expressed in to’s frame, applying a registered transform if the frames differ.

Parameters:
Return type:

Any

class prophys.frames.FrameError[source]

Raised when two structures with incompatible frames are combined.

Documented elsewhere

These APIs have their reference documentation on the narrative page that explains them, so each object has exactly one home:

Page

Covers

Units & Dimensions

prophys.units — dimensions, parsing, conversion, frame and attribute checking

Observations

Observations — censored, interval and missing records

Reading Data

prophys.io — CSV, tables, wind roses, rasters, NetCDF

Training & Design Optimization

calibrate(), finetune(), fit_distribution(), optimize(), CompiledModel

Uncertainty & Error

Monte-Carlo error (assess()) and parameter uncertainty (parameter_uncertainty(), propagate(), profile_likelihood())

Sensitivity Analysis

local_sensitivity(), sobol_sensitivity()

Model Validation

information_criteria(), waic(), loo(), compare(), calibration(), crps(), posterior_predictive_check(), report_card()

Posterior Inference

prophys.inference — NUTS posteriors over a compiled model

Export Format

ModelPackage, RunManifest and the reproducibility helpers