Basic Usage
The goal is to have minimal changes to your code in order to enable uncertainty propagation.
Creating a scalar
Uncertaintyvariable is relatively simple:>>> from auto_uncertainties import Uncertainty >>> value = 1.0 >>> error = 0.1 >>> u = Uncertainty(value, error) >>> u 1 +/- 0.1
As is creating a
numpyarray of Uncertainties:>>> from auto_uncertainties import Uncertainty >>> import numpy as np >>> value = np.linspace(start=0, stop=10, num=5) >>> error = np.ones_like(value)*0.1 >>> u = Uncertainty(value, error) >>> u [0 +/- 0.1, 2.5 +/- 0.1, 5 +/- 0.1, 7.5 +/- 0.1, 10 +/- 0.1]
The
Uncertaintyclass automatically determines which methods should be implemented based on whether it represents a vector uncertainty, or a scalar uncertainty. When instantiated with a sequence ornumpyarray, vector-based operations are enabled; when instantiated with scalars, only scalar operations are permitted.Scalar uncertainties implement all mathematical and logical dunder methods explicitly using linear uncertainty propagation.
>>> from auto_uncertainties import Uncertainty >>> u = Uncertainty(10.0, 3.0) >>> v = Uncertainty(20.0, 4.0) >>> u + v 30 +/- 5
Array uncertainties implement a large subset of the numpy ufuncs and methods using
jax.gradorjax.jacfwd, depending on the output shape.>>> from auto_uncertainties import Uncertainty >>> import numpy as np >>> value = np.linspace(start=0, stop=10, num=5) >>> error = np.ones_like(value)*0.1 >>> u = Uncertainty(value, error) >>> np.exp(u) [1 +/- 0.1, 12.1825 +/- 1.21825, 148.413 +/- 14.8413, 1808.04 +/- 180.804, 22026.5 +/- 2202.65] >>> np.sum(u) 25 +/- 0.223607 >>> u.sum() 25 +/- 0.223607 >>> np.sqrt(np.sum(error**2)) 0.223606797749979
The central value, uncertainty, and relative error are available as attributes:
>>> from auto_uncertainties import Uncertainty >>> u = Uncertainty(10.0, 3.0) >>> u.value 10.0 >>> u.error 3.0 >>> u.rel 0.3
To strip central values and uncertainty from arbitrary variables, accessor functions
nominal_valuesandstd_devsare provided:>>> from auto_uncertainties import nominal_values, std_devs >>> u = Uncertainty(10.0, 3.0) >>> v = 5.0 >>> nominal_values(u) 10.0 >>> std_devs(u) 3.0 >>> nominal_values(v) 5.0 >>> std_devs(v) 0.0
Displayed values are automatically rounded according to the
gformat specifier. To enable rounding consistent with the Particle Data Group (PDG) standard, theset_display_roundingfunction can be called as follows:>>> from auto_uncertainties import Uncertainty, set_display_rounding >>> import numpy as np >>> value = np.linspace(start=0, stop=10, num=5) >>> error = np.ones_like(value)*0.1 >>> u = Uncertainty(value, error) >>> set_display_rounding(True) # enable PDG rules >>> np.sum(u) 25.0 +/- 0.22 >>> set_display_rounding(False) # default behavior >>> np.sum(u) 25 +/- 0.223607
If enabled, the PDG rounding rules will, in general, cause
Uncertaintyobjects to be displayed with:Error to 2 significant digits.
Central value to first signficant digit of error, or two significant figures (whichever is more significant digits).
If
numpy.arrayis called on anUncertaintyobject, it will automatically get cast down to anumpyarray (losing all uncertainty information!), and emit a warning. To force an exception to be raised instead, useset_downcast_error:>>> from auto_uncertainties import Uncertainty, set_downcast_error >>> import numpy as np >>> set_downcast_error(True) >>> value = np.linspace(start=0, stop=10, num=5) >>> error = np.ones_like(value)*0.1 >>> u = Uncertainty(value, error) >>> np.array(u) Traceback (most recent call last): ... auto_uncertainties.exceptions.DowncastError: The uncertainty is stripped when downcasting to ndarray.