xarray-contrib / pint-xarray

Interface for using pint with xarray, providing convenience accessors
https://pint-xarray.readthedocs.io/en/latest/
Apache License 2.0
101 stars 12 forks source link

use `.pint.quantify()` as a identity operator #175

Closed keewis closed 2 years ago

keewis commented 2 years ago

Building on #174, this allows quantifying without any units involved at all, requantifying without new units, or requantifying quantified variables with the same units (they have to match exactly):

In [1]: import xarray as xr
   ...: import pint_xarray

In [2]: ds = xr.Dataset({"a": ("x", [1, 2, 3, 4], {"units": "m"})})
   ...: q = ds.pint.quantify()
   ...: q
Out[2]: 
<xarray.Dataset>
Dimensions:  (x: 4)
Dimensions without coordinates: x
Data variables:
    a        (x) int64 [m] 1 2 3 4

In [3]: q.pint.quantify()
Out[3]: 
<xarray.Dataset>
Dimensions:  (x: 4)
Dimensions without coordinates: x
Data variables:
    a        (x) int64 [m] 1 2 3 4

In [4]: q.pint.quantify({"a": "m"})
Out[4]: 
<xarray.Dataset>
Dimensions:  (x: 4)
Dimensions without coordinates: x
Data variables:
    a        (x) int64 [m] 1 2 3 4

In [5]: q.pint.quantify({"a": "s"})
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [5], in <cell line: 1>()
----> 1 q.pint.quantify({"a": "s"})

File .../pint_xarray/accessors.py:1087, in PintDatasetAccessor.quantify(self, units, unit_registry, **unit_kwargs)
   1076 if overwritten_units:
   1077     errors = {
   1078         name: (
   1079             new,
   (...)
   1085         for name, (old, new) in overwritten_units.items()
   1086     }
-> 1087     raise ValueError(format_error_message(errors, "attach"))
   1089 return self.ds.pipe(conversion.strip_unit_attributes).pipe(
   1090     conversion.attach_units, new_units
   1091 )

ValueError: Cannot attach units:
    cannot attach units to variable 'a': second (reason: Cannot attach unit <Unit('second')> to quantity: data already has units <Unit('meter')>)

In [6]: q.pint.quantify({"a": "mm"})
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [6], in <cell line: 1>()
----> 1 q.pint.quantify({"a": "mm"})

File ~/repos/pint-xarray/pint_xarray/accessors.py:1087, in PintDatasetAccessor.quantify(self, units, unit_registry, **unit_kwargs)
   1076 if overwritten_units:
   1077     errors = {
   1078         name: (
   1079             new,
   (...)
   1085         for name, (old, new) in overwritten_units.items()
   1086     }
-> 1087     raise ValueError(format_error_message(errors, "attach"))
   1089 return self.ds.pipe(conversion.strip_unit_attributes).pipe(
   1090     conversion.attach_units, new_units
   1091 )

ValueError: Cannot attach units:
    cannot attach units to variable 'a': millimeter (reason: Cannot attach unit <Unit('millimeter')> to quantity: data already has units <Unit('meter')>)

cc @lukelbd

lukelbd commented 2 years ago

Very cool, thanks for doing this. Sorry I never got around to it

keewis commented 2 years ago

no worries, I did take my time deciding on what to do