I building a python library to analyze data (e.g. spectral data) with units and uncertainties.
For example, we have data on wavelength (nm), counts, and power (W). I want to be able to easily convert between units e.g. from wavelength in nm to um. I found that functionality in pint. I also want to handle uncertainties, and be able to, for example perform an sqrt(power) where the power uncertainty will be carried over. I found that functionality in uncertainties. Ideally, all of this information is stored and handled via a pandas.DataFrame, though that is not necessary.
My problem is that I can not figure out how to properly integrate pint quantities and quantity arrays with uncertainties.unumpy module. I would be happy to receive any suggestions on how to do this with the aforementioned packages, or any other packages.
There are two main issues I have noticed:
unumpy operations are not supported with pint.Quantity:
This code that tries to take the square root of a Quantity defined with uncertainty
from uncertainties import unumpy as unp
from pint import UnitRegistry
ureg = UnitRegistry()
Qty = ureg.Quantity
a = Qty(3, 'um').plus_minus(0.1)
b = unp.sqrt(a)
returns an error message that requires the Quantity to be dimensionless:
File "C:\Users\USERNAME\AppData\Local\Programs\Python\Python310\lib\site-packages\pint\facets\plain\quantity.py", line 707, in __float__
raise DimensionalityError(self._units, "dimensionless")
pint.errors.DimensionalityError: Cannot convert from 'micrometer' to 'dimensionless'
As a note, trying the same with numpy just returns the same error an uncertainties.ufloat would:
TypeError: loop of ufunc does not support argument 0 of type Measurement which has no callable sqrt method
Neither unumpy.uarray(), or pint.Measurement.from_list() can initialize an array of pint.Measurement objects. The first approach yields this error:
File "C:\Users\USERNAME\AppData\Local\Programs\Python\Python310\lib\site-packages\pint\facets\plain\quantity.py", line 707, in __float__
raise DimensionalityError(self._units, "dimensionless")
pint.errors.DimensionalityError: Cannot convert from 'micrometer' to 'dimensionless'
while the second approach yields this error, that is also related to the uncertainties package:
File "C:\Users\USERNAME\AppData\Local\Programs\Python\Python310\lib\site-packages\uncertainties\core.py", line 2714, in raise_error
raise TypeError("can't convert an affine function (%s)"
TypeError: can't convert an affine function (<class 'uncertainties.core.Variable'>) to float; use x.nominal_value
The trick is to make the magnitude of the Quantity an uncertainty. Once you do this a lot of things just work. The biggest thing that doesn't work is that uncertainties don't work well with Pint's REPR. There's a pending pull request to fix that: https://github.com/hgrecco/pint/pull/1615
And there's also a pending pull request to make this all work well with Pandas: https://github.com/hgrecco/pint-pandas/pull/140
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With