Skip to content
Snippets Groups Projects

No xarray!

Merged Martin Lange requested to merge no-xarray into main
4 files
+ 125
22
Compare changes
  • Side-by-side
  • Inline
Files
4
+ 118
0
"""Module to provide unit support via pint approximating UDUNITS/CF.
Source: cf-xarray (https://github.com/xarray-contrib/cf-xarray/blob/main/cf_xarray/units.py)
License: Apache License 2.0 (https://github.com/xarray-contrib/cf-xarray/blob/main/LICENSE)
"""
import functools
import re
import warnings
import pint
# pylint: disable-next=unused-import
from pint import DimensionalityError, UndefinedUnitError, UnitStrippedWarning
# from `xclim`'s unit support module with permission of the maintainers
try:
@pint.register_unit_format("cf") # pylint: disable-next=unused-argument
def short_formatter(unit, registry, **options):
"""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.
"""
# 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>(?:1 )?/ )?(?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 ""
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", "%")
except ImportError:
pass
# ------
# Reused with modification from MetPy under the terms of the BSD 3-Clause License.
# Copyright (c) 2015,2017,2019 MetPy Developers.
# Create registry, with preprocessors for UDUNITS-style powers (m2 s-2) and percent signs
units = pint.UnitRegistry(
autoconvert_offset_to_baseunit=True,
preprocessors=[
functools.partial(
re.compile(
r"(?<=[A-Za-z])(?![A-Za-z])(?<![0-9\-][eE])(?<![0-9\-])(?=[0-9\-])"
).sub,
"**",
),
lambda string: string.replace("%", "percent"),
],
force_ndarray_like=True,
)
units.define("percent = 0.01 = %")
# Define commonly encountered units (both CF and non-CF) not defined by pint
units.define("@alias meter = gpm")
# ----- end block copied from metpy
# -----
# The following redefinitions were copied from xclim under the terms of their Apache-2 license
# In pint, the default symbol for year is "a" which is not CF-compliant (stands for "are")
units.define("year = 365.25 * day = yr")
# Define commonly encountered units not defined by pint
units.define("@alias degC = C = deg_C = Celsius = degrees_Celsius")
units.define("@alias degK = deg_K")
units.define("@alias day = d")
units.define("@alias hour = h") # Not the Planck constant...
units.define(
"degrees_north = degree = degrees_north = degrees_N = degreesN = degree_north = degree_N = degreeN"
)
units.define(
"degrees_east = degree = degrees_east = degrees_E = degreesE = degree_east = degree_E = degreeE"
)
units.define("[speed] = [length] / [time]")
# ----- end block copied from xclim
# Add other specific aliases (by cf_xarray developers)
units.define("practical_salinity_unit = [] = psu = PSU")
# Enable pint's built-in matplotlib support
try:
units.setup_matplotlib()
except ImportError:
warnings.warn(
"Import(s) unavailable to set up matplotlib support...skipping this portion "
"of the setup."
)
# end of vendored code from MetPy
# Set as application registry
pint.set_application_registry(units)
Loading