Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simultaneously handling uncertainties and units in python

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:

  1. 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
    
  2. 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
    
like image 568
Selewirre Avatar asked Dec 10 '25 08:12

Selewirre


1 Answers

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

like image 85
Michael Tiemann Avatar answered Dec 11 '25 21:12

Michael Tiemann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!