Skip to content

Commit 0daca00

Browse files
committed
Merge remote-tracking branch 'upstream/main' into add-pint-registry
* upstream/main: Update README.rst Add earthcube 2021 notebook link to readme v0.5.2 Some CMIP6 support Add pooch to binder environment (#223) `add_bounds` uses `keys` rather than `dims` (#221)
2 parents af01b74 + 5d3e5fe commit 0daca00

File tree

6 files changed

+59
-20
lines changed

6 files changed

+59
-20
lines changed

.binder/environment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ dependencies:
77
- netcdf4
88
- pip
99
- xarray
10+
- pooch
1011
- pip:
1112
- git+https://github.com/xarray-contrib/cf-xarray

README.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ A lightweight convenience wrapper for using CF attributes on xarray objects.
3434

3535
For example you can use ``.cf.mean("latitude")`` instead of ``.mean("lat")`` if appropriate attributes are set! This allows you to write code that does not require knowledge of specific dimension or coordinate names particular to a dataset.
3636

37-
See more in the introductory notebook `here <https://cf-xarray.readthedocs.io/en/latest/examples/introduction.html>`_.
37+
See more in the `introductory notebook <https://cf-xarray.readthedocs.io/en/latest/examples/introduction.html>`_.
38+
39+
Try out our Earthcube 2021 Annual Meeting notebook `submission <https://binder.pangeo.io/v2/gh/malmans2/cf-xarray-earthcube/main?filepath=DC_01_cf-xarray.ipynb>`_.

cf_xarray/accessor.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,15 +1586,15 @@ def get_bounds_dim_name(self, key: str) -> str:
15861586
assert self._obj.sizes[bounds_dim] in [2, 4]
15871587
return bounds_dim
15881588

1589-
def add_bounds(self, dims: Union[Hashable, Iterable[Hashable]]):
1589+
def add_bounds(self, keys: Union[str, Iterable[str]]):
15901590
"""
15911591
Returns a new object with bounds variables. The bounds values are guessed assuming
15921592
equal spacing on either side of a coordinate label.
15931593
15941594
Parameters
15951595
----------
1596-
dims : Hashable or Iterable[Hashable]
1597-
Either a single dimension name or a list of dimension names.
1596+
keys : str or Iterable[str]
1597+
Either a single key or a list of keys corresponding to dimensions.
15981598
15991599
Returns
16001600
-------
@@ -1609,12 +1609,16 @@ def add_bounds(self, dims: Union[Hashable, Iterable[Hashable]]):
16091609
The bounds variables are automatically named f"{dim}_bounds" where ``dim``
16101610
is a dimension name.
16111611
"""
1612-
if isinstance(dims, Hashable):
1613-
dimensions = (dims,)
1614-
else:
1615-
dimensions = dims
1612+
if isinstance(keys, str):
1613+
keys = [keys]
1614+
1615+
dimensions = set()
1616+
for key in keys:
1617+
dimensions.update(
1618+
apply_mapper(_get_dims, self._obj, key, error=False, default=[key])
1619+
)
16161620

1617-
bad_dims: Set[Hashable] = set(dimensions) - set(self._obj.dims)
1621+
bad_dims: Set[str] = dimensions - set(self._obj.dims)
16181622
if bad_dims:
16191623
raise ValueError(
16201624
f"{bad_dims!r} are not dimensions in the underlying object."

cf_xarray/criteria.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66

77

8+
import copy
89
import re
910
from typing import MutableMapping, Tuple
1011

@@ -74,19 +75,20 @@
7475
}
7576

7677
# "long_name" and "standard_name" criteria are the same. For convenience.
77-
coordinate_criteria["long_name"] = coordinate_criteria["standard_name"]
78+
coordinate_criteria["long_name"] = copy.deepcopy(coordinate_criteria["standard_name"])
79+
coordinate_criteria["long_name"]["X"] += ("cell index along first dimension",)
80+
coordinate_criteria["long_name"]["Y"] += ("cell index along second dimension",)
7881

7982
#: regular expressions for guess_coord_axis
8083
regex = {
8184
"time": re.compile("\\bt\\b|(time|min|hour|day|week|month|year)[0-9]*"),
82-
"vertical": re.compile(
83-
"(z|nav_lev|gdep|lv_|bottom_top|sigma|h(ei)?ght|altitude|depth|"
85+
"Z": re.compile(
86+
"(z|nav_lev|gdep|lv_|[o]*lev|bottom_top|sigma|h(ei)?ght|altitude|depth|"
8487
"isobaric|pres|isotherm)[a-z_]*[0-9]*"
8588
),
86-
"Y": re.compile("y"),
89+
"Y": re.compile("y|j|nlat|nj"),
8790
"latitude": re.compile("y?(nav_lat|lat|gphi)[a-z0-9]*"),
88-
"X": re.compile("x"),
91+
"X": re.compile("x|i|nlon|ni"),
8992
"longitude": re.compile("x?(nav_lon|lon|glam)[a-z0-9]*"),
9093
}
91-
regex["Z"] = regex["vertical"]
9294
regex["T"] = regex["time"]

cf_xarray/tests/test_accessor.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,10 @@ def test_add_bounds(obj, dims):
634634
assert added[dim].attrs["bounds"] == name
635635
assert_allclose(added[name].reset_coords(drop=True), expected[dim])
636636

637+
# Test multiple dimensions
638+
assert not {"x1_bounds", "x2_bounds"} <= set(multiple.variables)
639+
assert {"x1_bounds", "x2_bounds"} <= set(multiple.cf.add_bounds("X").variables)
640+
637641

638642
def test_bounds():
639643
ds = airds.copy(deep=True).cf.add_bounds("lat")
@@ -776,9 +780,9 @@ def _make_names(prefixes):
776780
"nav_lev",
777781
]
778782
)
779-
_X_NAMES = _make_names(["x"])
780-
_Y_NAMES = _make_names(["y"])
781-
_Z_NAMES = _VERTICAL_NAMES
783+
_X_NAMES = _make_names(["x", "nlon", "i", "ni"])
784+
_Y_NAMES = _make_names(["y", "nlat", "j", "nj"])
785+
_Z_NAMES = _VERTICAL_NAMES + ["olevel", "level", "zlevel"]
782786
_LATITUDE_NAMES = _make_names(["lat", "latitude", "gphi", "nav_lat"])
783787
_LONGITUDE_NAMES = _make_names(["lon", "longitude", "glam", "nav_lon"])
784788

@@ -1189,3 +1193,24 @@ def test_differentiate_positive_upward(obj):
11891193
obj.z.attrs["positive"] = "zzz"
11901194
with pytest.raises(ValueError):
11911195
obj.cf.differentiate("z", positive_upward=True)
1196+
1197+
1198+
def test_cmip6_attrs():
1199+
da = xr.DataArray(
1200+
np.ones((10, 10)),
1201+
dims=("nlon", "nlat"),
1202+
coords={
1203+
"nlon": (
1204+
"nlon",
1205+
np.arange(10),
1206+
{"long_name": "cell index along first dimension"},
1207+
),
1208+
"nlat": (
1209+
"nlat",
1210+
np.arange(10),
1211+
{"long_name": "cell index along second dimension"},
1212+
),
1213+
},
1214+
)
1215+
assert da.cf.axes["X"] == ["nlon"]
1216+
assert da.cf.axes["Y"] == ["nlat"]

doc/whats-new.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
What's New
44
----------
55

6-
v0.5.2 (unreleased)
6+
v0.5.3 (unreleased)
77
===================
8-
98
- Begin adding support for units with a unit registry for pint arrays. :pr:`197`.
109
By `Jon Thielen`_ and `Justus Magin`_.
10+
11+
v0.5.2 (May 11, 2021)
12+
=====================
13+
14+
- Add some explicit support for CMIP6 output. By `Deepak Cherian`_.
15+
- Replace the ``dims`` argument of :py:meth:`Dataset.cf.add_bounds` with ``keys``, allowing to use CF keys. By `Mattia Almansi`_.
1116
- Added :py:attr:`DataArray.cf.formula_terms` and :py:attr:`Dataset.cf.formula_terms`.
1217
By `Deepak Cherian`_.
1318
- Added :py:attr:`Dataset.cf.bounds` to return a dictionary mapping valid keys to the variable names of their bounds. By `Mattia Almansi`_.

0 commit comments

Comments
 (0)