fourierror.variable#

A scipp.Variable subclass carrying a full covariance.

class fourierror.variable.CovVariable(*, dims, values, covariance=None, unit=Unit(1), dtype=None)#

Bases: Variable

A scipp.Variable that stores and propagates a full covariance matrix.

Instances are scipp.Variable objects as far as C++ is concerned: they carry values and variances, so isinstance(x, sc.Variable) holds and every existing scipp function accepts them. In addition they carry a covariance: a Variable with dims (*dims, *mirror(dims)) and unit unit**2, whose diagonal is kept equal to the inherited variances.

Parameters:
  • dims (Sequence[str]) – Dimension labels.

  • values (Any) – Array of values.

  • covariance (Any) – Covariance matrix, as a scipp.Variable with dims (*dims, *mirror(dims)), an array-like of shape (*shape, *shape), or None for a zero covariance.

  • unit (Any) – Physical unit of the values; the covariance carries unit**2.

  • dtype (Any) – Element type, deduced from values if omitted.

Examples

Two 50% correlated measurements:

>>> a = covariance_array(
...     dims=['x'],
...     values=[1.0, 2.0],
...     covariance=[[0.04, 0.02], [0.02, 0.04]],
...     unit='m',
... )
>>> a.variances
array([0.04, 0.04])

Summing correlated elements accounts for the off-diagonal terms, which plain scipp cannot do:

>>> round(float(a.sum('x').variance), 12)
0.12
classmethod from_variable(var, covariance=None)#

Build a CovVariable from a plain Variable.

With covariance=None the variable’s own variances become the diagonal, i.e. its elements are assumed uncorrelated – exactly the assumption plain scipp makes implicitly.

Return type:

CovVariable

property covariance: Variable#

The full covariance matrix, with dims (*dims, *mirror(dims)).

A copy. Returning the stored matrix would let a caller write through the accessor – var.covariance.values[0, 0] = x – and leave the variances == diag(covariance) invariant broken with no error. Bind it to a local name if you read it repeatedly; it is N x N.

Setter accepts:

Any

property correlation: Variable#

The correlation matrix (dimensionless), with the covariance’s dims.

property variances#

Array of variances of the data.

Returns a NumPy array that shares memory with the variable’s variance buffer, or None if the variable has no variances.

Examples

>>> import scipp as sc
>>> var = sc.array(dims=['x'], values=[1.0, 2.0, 3.0], variances=[0.1, 0.2, 0.3])
>>> var.variances
array([0.1, 0.2, 0.3])

Variables without variances return None:

>>> var_no_var = sc.array(dims=['x'], values=[1.0, 2.0, 3.0])
>>> var_no_var.variances is None
True

Variances can be set or removed:

>>> var_no_var.variances = [0.01, 0.02, 0.03]
>>> var_no_var.variances
array([0.01, 0.02, 0.03])
>>> var_no_var.variances = None
>>> var_no_var.variances is None
True
Setter accepts:

Any

to_variable()#

Explicitly drop the correlations, returning a plain Variable.

The variances of the result are the diagonal of the covariance, so marginal uncertainties are preserved.

Return type:

Variable

__add__(other)#

Return self + other, propagating the covariance.

Return type:

CovVariable

__radd__(other)#

Return self + other, propagating the covariance.

Return type:

CovVariable

__sub__(other)#

Return self - other, propagating the covariance.

Return type:

CovVariable

__rsub__(other)#

Return other - self, propagating the covariance.

Return type:

CovVariable

__mul__(other)#

Return self * other, propagating the covariance.

Return type:

CovVariable

__rmul__(other)#

Return self * other, propagating the covariance.

Return type:

CovVariable

__truediv__(other)#

Return self / other, propagating the covariance.

Return type:

CovVariable

__rtruediv__(other)#

Return other / self, propagating the covariance.

Return type:

CovVariable

__neg__()#

Return -self; the covariance is unchanged.

Return type:

CovVariable

__abs__()#

Return abs(self), flipping the sign of correlations as needed.

Return type:

CovVariable

__pow__(exponent)#

Return self ** exponent, propagating the covariance.

Raises CovarianceError if the exponent has an uncertainty.

Return type:

CovVariable

sqrt()#

Elementwise square root, propagating the covariance.

Return type:

CovVariable

exp()#

Elementwise exponential, propagating the covariance.

Return type:

CovVariable

log()#

Elementwise natural logarithm, propagating the covariance.

Return type:

CovVariable

sin()#

Elementwise sine of an angle, propagating the covariance.

Return type:

CovVariable

cos()#

Elementwise cosine of an angle, propagating the covariance.

Return type:

CovVariable

sum(dim=None)#

Sum over dim, accounting for correlations between the summands.

Return type:

CovVariable

mean(dim=None)#

Mean over dim (all dims if None), including off-diagonal terms.

Return type:

CovVariable

__getitem__(key)#

Slice, selecting the same elements on both axes of the covariance.

Return type:

CovVariable

transpose(dims=None)#

Transpose to dims, reordering both axes of the covariance.

Parameters:

dims (Sequence[str] | None) – The new dimension order; reversed if None.

Return type:

CovVariable

broadcast(dims=None, shape=None, sizes=None)#

Broadcast, recording the correlations the broadcast introduces.

Plain scipp raises VariancesError here (ADR 0015) because a broadcast duplicates an uncertain value, perfectly correlating the copies. With a full covariance matrix those correlations are representable, so the operation becomes well defined.

Return type:

CovVariable

to(*, unit=None, dtype=None, copy=True)#

Convert unit and/or dtype, scaling the covariance quadratically.

Parameters:
  • unit (Any) – Target unit.

  • dtype (Any) – Target dtype.

  • copy (bool) – Passed to scipp.Variable.to.

Return type:

CovVariable

copy(deep=True)#

Return a copy of the variable and its covariance.

Parameters:

deep (bool) – Whether to copy the underlying buffers.

Return type:

CovVariable

exception fourierror.variable.CovarianceError#

Bases: RuntimeError

Raised when an operation cannot propagate a full covariance matrix.

fourierror.variable.concat(variables, dim)#

Concatenate along dim, producing a block-diagonal covariance.

The inputs are assumed mutually independent, so the cross-blocks are zero.

Return type:

CovVariable

fourierror.variable.covariance_array(*, dims, values, covariance=None, unit=Unit(1), dtype=None)#

Create a CovVariable, mirroring scipp.array().

Return type:

CovVariable

fourierror.variable.covariance_scalar(value, *, variance=0.0, unit=Unit(1))#

Create a 0-D CovVariable, mirroring scipp.scalar().

Return type:

CovVariable

fourierror.variable.install_dispatch()#

Route scipp’s free functions through CovVariable.

Scipp’s free functions (sc.sum, sc.concat, …) call into C++ and return a plain Variable, dropping the covariance with no error. Inside a DataGroup this is especially easy to miss, because call_func in src/scipp/core/_cpp_wrapper_util.py hands the raw C++ function to data_group_nary – so the per-item call never reaches this class, and overriding methods cannot help.

This patches the listed functions in the scipp namespace so they dispatch to the covariance-aware implementation, or refuse when there is none. Opt-in, and reversible with uninstall_dispatch().

It is a stand-in for the __scipp_dispatch__ protocol proposed in the README: functions outside _AWARE and _LOSSY are untouched and still degrade silently, which is why the real fix belongs in scipp itself.

Return type:

None

fourierror.variable.install_operand_deferral()#

Make plain scipp objects defer to a covariance-carrying right operand.

Installed automatically when fourierror.data_array is imported, because without it plain_variable * cov_data_array silently returns a plain DataArray: CovDataArray subclasses DataArray but not Variable, so Python grants it no reflected-operand priority, and Variable.__mul__’s DataArray overload wins outright. A fix for silently wrong numbers should not be opt-in.

Narrow by construction: the wrappers change behaviour only when the right operand carries a _covariance, so plain scipp arithmetic is untouched. Idempotent.

Return type:

None

fourierror.variable.uninstall_dispatch()#

Undo install_dispatch().

Leaves the operand deferral in place; that is a correctness fix installed at import, not part of the opt-in free-function patching. Use uninstall_operand_deferral() to undo it too.

Return type:

None

fourierror.variable.uninstall_operand_deferral()#

Restore scipp’s own arithmetic operators.

Only for callers who need scipp’s operator slots pristine. Afterwards plain_variable * cov_data_array silently drops the covariance again.

Return type:

None