-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
upstream xclim.core.units? #780
Comments
Yes! That is one of our long-term goals. Currently, all unit handling is done "by hand" inside xclim, which is suboptimal. I think moving a much of what we can upstream is a great idea. The registry modifications here are also based on MetPy, but augmented as other issues arose. I don't think we will be able to remove all unit handling from xclim, but switching to integrated units will be a plus. I'll try to look into this when I have time, but I don't think anyone from the core team will have much time to work on this in the next month. |
posted first as jbusecke/xMIP#167 (comment):
|
Nice work @keewis . This looks like a good time to upstream this to |
just tried it: In [7]: import pint
...:
...: pint.formatting._FORMATTERS.pop("cf", None)
...:
...: @pint.register_unit_format("cf")
...: def pint2cfunits(unit, registry, **options) -> str:
...: """Return a CF-compliant unit string from a `pint` unit.
...:
...: Parameters
...: ----------
...: unit : pint.UnitContainer
...: Input unit.
...: registry : pint.UnitRegistry
...: the associated registry
...: **options
...: Additional options (may be ignored)
...:
...: Returns
...: -------
...: out : str
...: Units following CF-Convention, using symbols.
...: """
...: import re
...:
...: # convert UnitContainer back to Unit
...: unit = registry.Unit(unit)
...: # Print units using abbreviations (millimeter -> mm)
...: s = f"{unit:~D}"
...:
...: # Search and replace patterns
...: pat = r"(?P<inverse>/ )?(?P<unit>\w+)(?: \*\* (?P<pow>\d))?"
...:
...: def repl(m):
...: i, u, p = m.groups()
...: p = p or (1 if i else "")
...: neg = "-" if i else ("^" if p else "")
...:
...: return f"{u}{neg}{p}"
...:
...: out, n = re.subn(pat, repl, s)
...:
...: # Remove multiplications
...: out = out.replace(" * ", " ")
...: # Delta degrees:
...: out = out.replace("Δ°", "delta_deg")
...: return out.replace("percent", "%")
...:
...: ureg = pint.application_registry
...: u = ureg.Unit("m ** 2 / (s ** 3 * kg)")
...: display(u)
...: display(f"{u:cf}")
<Unit('meter ** 2 / kilogram / second ** 3')>
'm^2 kg-1 s-3' which I think should do the same as The caret seems a bit odd to me (I was assuming it would return |
This is nice ! |
Indeed that's nice! So as for upstreaming, I understand that for the moment it concerns the following elements:
Other tools of |
I'd keep the "hydro" context in
As for the unit manipulation, if you can list what exactly you have I can help figuring out what |
Quite honestly, I don't like the "hydro" context myself, but it reflects an issue I have seen in many CF-oriented projects : conversion from flux to amount is often implicit in the context of water. In xclim, we are trying to remove the need for this by explicitly converting from rate to amount and vice-versa. xclim's
|
CF follows UDUNITS so it should be Perhaps we should have two versions: one for |
closing for #1010 |
Hello,
It looks like large parts of
xclim.core.units
could be upstreamed to cf-xarray and pint-xarray. Would you be interested in doing this?The unit registry definitions could be moved to
cf-xarray
now that it provides a pint registry that aims to be CF-aware (mostly copied from MetPy right now).pin2cfunits
looks particularly useful as a custom format for "dequantifying" pint-backed xarray objects (cc @keewis, @TomNicholas, @jthielen).xclim/xclim/core/units.py
Line 167 in 6102e54
The text was updated successfully, but these errors were encountered: