cf-xarray
cf-xarray copied to clipboard
updates to unit support
Current todo list remaining:
- [ ] add documentation
- Examples of using cf-xarray and pint-xarray together
- ~Instructing users to either import cf-xarray before pint-xarray or set~ not necessary with
pint>=0.18
- List current known shortfalls of this registry compared to full UDUNITS support (namely case sensitivity)
- xref #450 , #446
- [ ] add tests of this registry's quantities being used within xarray, and not just correctly parsing units with the customized features.
Originally posted by @jthielen in https://github.com/xarray-contrib/cf-xarray/pull/197#issuecomment-816038767
I've run across this discussion and work now and am interested in using it! Is the pint unit stuff sort of separate from the other cf-xarray stuff? I am looking to interpret units in xarray Datasets but with units including psu and for example m s-1.
indeed, the only thing it does for now is provide a special pint.UnitRegistry
object so datasets with cfunits
style "units"
attributes can be used with pint-xarray
.
The documentation for this feature of cf-xarray
is still missing, though, and we need to get pint
's application registry to work reliably but it should be usable right now. In any case I encourage you to try it out and report any issues you run into.
Thanks @keewis! I haven't actually used pint
before today so it's slow going, but I'll see what I can figure out.
if you're willing to take the time I'd also be interested in feedback on what you found difficult to understand: we didn't check the documentation of pint-xarray
in that regard, yet.
I've gotten a little bit into this and get something to work, so that has been exciting. I've immediately hit another unit problem though: salinity units as 1e-3. Is this one that can be added into the registry here?
I don't know a lot about the units used in oceanography (for example, what is the difference between those and the "psu"
that are already in the registry?) so I will leave this request to @dcherian or anyone else with more knowledge.
In general, if you can provide a unit name and the dimensionality / scale I think that should be possible.
Here is just a basic example I was able to cobble together from the pint-xarray
docs and looking at the commits in the new unit changes here in cf-xarray got me far:
import pint
# order apparently matters
from cf_xarray.units import units
import pint_xarray
ds = xr.open_dataset([your dataset])
ds = ds.pint.quantify() # to interpret units
# units like m s-1 will be interpretable by pint with the cf_xarray unit registry
ds['temp'] = ds['temp'].pint.to('degree_Celsius') # convert units
ds = ds.pint.dequantify() # to go back to normal use
@keewis Unfortunately salinity is represented by a bunch of "essentially" interchangeable units so of course I immediately have one!
@dcherian Can I add a line in the new units file for salinity units of 1e-3?
a tip:
ds['temp'] = ds['temp'].pint.to('degree_Celsius')
can also be written as
ds = ds.pint.to({"temp": "degree_Celsius"})
and while right now most operations are supported, some of the most important ones (e.g. sel
and interp
) are not. For that, there's wrapper methods on the .pint
accessors. In the future, I hope we can eliminate the dequantify
call (altogether or except from immediately before saving / converting to a different library).
Can I add a line in the new units file for salinity units of 1e-3?
At first I was skeptical but it looks like this is widespread (https://github.com/Unidata/UDUNITS-2/issues/27).
So i think it's OK to have 1e-3
as a synonym for psu
.
There are a few other aliases in this comment: https://github.com/PCMDI/pcmdi_metrics/issues/162#issuecomment-94022531
(1 psu = 1 PSS-78 = 1 Practical Salinity Scale 78 = 1.e-3
)
@keewis if you want to waste some time on the history of salinity measurements see http://www.coastalwiki.org/wiki/Salinity
I like the rant by frank Millero which ends with
If the field of oceanography is to become a recognized science, it must adopt the units that are basic to the fields of chemistry and physics. It also should not adopt new units for variables that are unitless.
Ok so should I change the line
https://github.com/xarray-contrib/cf-xarray/blob/main/cf_xarray/units.py#L44 to be the following (not sure if I need the change in capitalization for "E")
units.define("practical_salinity_unit = [] = psu = 1 PSS-78 = 1 Practical Salinity Scale 78 = 1.e-3 = 1E-3")
If anyone has some time, I would like to move this forward but I am stuck on knowing where to start. I tried my suggestion above and that didn't work.
May be easier if you open a PR and posted the error message. I assume you've looked at https://pint.readthedocs.io/en/stable/defining.html?
I am now at least!! Thanks. I'll try more and go via the PR route.
PR #238
FYI this:
Instructing users to either import cf-xarray before pint-xarray or set
will not be necessary anymore with hgrecco/pint#1366