Source code for stream.analysis.UQ.uncertainty

from dataclasses import asdict, dataclass

import numpy as np
from cytoolz import valfilter

from stream.units import Value

Uncertuple = tuple[Value, Value]


[docs] @dataclass(frozen=True) class Uncertainty: r"""Describes perturbations, both statistical and systematic. In relation to a given variable :math:`x` which, unperturbed, is denoted :math:`x_0`. The perturbed value is assumed to have the following distribution :math:`X`: .. math:: X \sim x_0 (1 + \mu_\text{sys, rel.}) \mathcal{N}(1, \sigma^2_\text{stat, rel.}) + \mathcal{N}(\mu_\text{sys, abs.}, \sigma^2_\text{stat, abs.}) Where :math:`\mu_\text{sys, rel.}` defines a systematic relative uncertainty, :math:`\sigma_\text{stat, rel.}` defines a statistical relative uncertainty, :math:`\mu_\text{sys, abs.}` defines a systematic absolute uncertainty and :math:`\sigma_\text{stat, abs.}` defines statistical absolute uncertainty """ systematic_relative: Value = 0.0 statistical_relative: Value = 0.0 systematic_absolute: Value = 0.0 statistical_absolute: Value = 0.0
[docs] def as_absolute(self, nominal: Value) -> Uncertuple: """Returns an absolute representation of the systematic and statistical uncertainties. Parameters ---------- nominal: Value The nominal value to use for the relative-to-absolute conversion. """ return ( self.systematic_relative * nominal + self.systematic_absolute, np.sqrt((self.statistical_relative * nominal) ** 2 + self.statistical_absolute**2), )
def __bool__(self): return any( ( self.systematic_relative, self.statistical_relative, self.statistical_absolute, self.systematic_absolute, ) ) def __add__(self, other: "Uncertainty") -> "Uncertainty": if not isinstance(other, Uncertainty): return NotImplemented return Uncertainty( self.systematic_relative + other.systematic_relative, np.sqrt(self.statistical_relative**2 + other.statistical_relative**2), self.systematic_absolute + other.systematic_absolute, np.sqrt(self.statistical_absolute**2 + other.statistical_absolute**2), ) def __repr__(self) -> str: non_zeros = valfilter(np.any, asdict(self)) val_string = ", ".join([f"{k}={v}" for k, v in non_zeros.items()]) return f"Uncertainty({val_string})"