Units and Uncertainties¶
Units¶
Units were introduced for parameters and binnings in PISA using the Pint package. The package is fully compatible with the NumPy and uncertainties packages.
Note the terminology used:
Unit has no attached value(s). Type:
pint.UnitQuantity is a number (or array) with units attached to them. Type:
pint.QuantityMagnitude is the value of a quantity sans units. Type:
float,int,numpy.ndarray, etc.
Pint’s quirks¶
As Pint has no “global units”, to ensure we always use the same shared unit registry, the standard way of importing pint in PISA is the line
from pisa import ureg, Q_
, where ureg is the shared unit registry and Q_ is the associated shared Quantity type.
Basic attributes of Pint quantities¶
To access the units of a quantity:
>>> q = 10.2 * ureg.meter >>> q.units <Unit('meter')> >>> units_2 = q.u <Unit('meter')>
To access the magnitude of a Pint quantity:
>>> q = 12.4 * ureg.foot >>> q.magnitude 12.4 >>> q.m 12.4 >>> q.m_as('meter') 3.77952
Uncertainties¶
Support for the handling of errors is available from the uncertainties package. This interoperates well with units, too. Note that there is a performance penalty for using uncertainties, so hooks are provided to enable or disable this feature at the user’s discretion.
Basic attributes of numbers with uncertainties¶
Nominal value:
>>> x = ufloat(10.0, 0.3) >>> x.nominal_value 10.0 >>> x.n 10.0
Standard deviation:
>>> x = ufloat(-12.3, 0.6) >>> x.std_dev 0.6 >>> x.s 0.6
Pint and uncertainties interoperate well. So a quantity can have uncertainty. All of the above attributes work for numbers that are wrapped with both features. See examples below.
Examples¶
More examples of how to use the above packages are given below.
For ordinary numbers (floats):
>>> from uncertainties import ufloat >>> from pisa import ureg, Q_ >>> q = ufloat(1.3, 0.2) * ureg.meter >>> q.m # magnitude 1.3+/-0.2 >>> q.u # unit <Unit('meter')> >>> q.n # nominal value 1.3 >>> q.s # standard deviation 0.2 >>> q.to('foot') # conversion <Quantity(4.3+/-0.7, 'foot')> >>> q.dimensionality <UnitsContainer({'[length]': 1.0})>
For numpy arrays:
>>> from uncertainties import unumpy as unp >>> a = unp.uarray([1., 2., 3.], [1., 1.41, 1.73]) # with list of values, and list of errors, or alternatively: >>> a = np.array([ufloat(1.,1.),ufloat(2.,1.41), ufloat( 3.,1.73)]) >>> a *= ureg.seconds <Quantity([1.0+/-1.0 2.0+/-1.41 3.0+/-1.73], 'second')> >>> a.u <Unit('second')> >>> a.m array([1.0+/-1.0, 2.0+/-1.41, 3.0+/-1.73], dtype=object) >>> unp.nominal_values((a) array([ 1., 2., 3.]) >>> unp.std_devs(a) array([ 1. , 1.41, 1.73])
Check if units are compatible
Explicitly check if
dimensionalityis equal for two units, quantities, or a combination thereof:>>> units0 = ureg.meter >>> units1 = ureg.yard >>> units2 = ureg.kg >>> quant0 = 1 * units0 >>> quant1 = 1 * units1 >>> quant0.dimensionality == quant1.dimensionality True >>> quant0.dimensionality == units1.dimensionality True >>> units1.dimensionality == units2.dimensionality False
Implicitly check if one quantity is convertible to a different unit (whether a raw units object, the units attached to another quantity, or a string that Pint can convert into units):
>>> q0 = ureg.meter * 10 >>> q1 = ureg.yard * 2 >>> u0 = ureg.cm >>> u1 = ureg.second >>> # Convert q0 from meters to the units of q1 (yards) >>> q0.to(q1) <Quantity(10.9361329834, 'yard')> >>> q0.to(u0) <Quantity(1000.0, 'centimeter')> >>> q0.to('mile') <Quantity(0.00621371192237, 'mile')> >>> q0.to(u1) DimensionalityError: Cannot convert from 'meter' ([length]) to 'second' ([time])
The
pisa.core.Mapobject integrates uncertainties, which are turned off by default but can be enabled with either theset_poisson_errors()orset_errors(...)methods. Once enabled, all subsequent operations on theMapwill propagate errors (to first order).