Skip to content

Commit 228ee4a

Browse files
kthyngpre-commit-ci[bot]dcherian
authored
new vertical coord decode and reordering (#315)
* new vertical coord decode and reordering The vertical decoding has been added for `ocean_sigma_coordinate` and the free surface variable has been expanded dimensionally for all the calculations so that the results preserve the standard ordering of time, vertical, lat/Y, lon/X. Three of the tests do not work anymore, though. Expanding dimensionally apparently bumps the attributes off of s_rho, for one. For another, the values are very similar but do not match anymore — not sure why. Interested to see what @dcherian thinks! * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update doc/whats-new.rst Co-authored-by: Deepak Cherian <[email protected]> * Update cf_xarray/accessor.py Co-authored-by: Deepak Cherian <[email protected]> * preferentially use outnames over prefix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added in transpose statement that does not work yet * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed reordering stuff that did not work * provide a default name now * I think the tests are back how they were * trying to follow dcherian suggestions * small precommit change * Update cf_xarray/tests/test_accessor.py Co-authored-by: Deepak Cherian <[email protected]> * small fix from review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update cf_xarray/accessor.py * Update cf_xarray/tests/test_accessor.py * fixed tests I think Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Deepak Cherian <[email protected]>
1 parent 0908033 commit 228ee4a

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

cf_xarray/accessor.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,12 +2190,15 @@ def bounds_to_vertices(
21902190
)
21912191
return obj
21922192

2193-
def decode_vertical_coords(self, prefix="z"):
2193+
def decode_vertical_coords(self, *, outnames=None, prefix=None):
21942194
"""
21952195
Decode parameterized vertical coordinates in place.
21962196
21972197
Parameters
21982198
----------
2199+
outnames : dict, optional
2200+
Keys of outnames are the input sigma/s coordinate variable name and
2201+
the values are the name to use for the associated vertical coordinate.
21992202
prefix : str, optional
22002203
Prefix for newly created z variables.
22012204
E.g. ``s_rho`` becomes ``z_rho``
@@ -2209,7 +2212,8 @@ def decode_vertical_coords(self, prefix="z"):
22092212
Will only decode when the ``formula_terms`` and ``standard_name`` attributes
22102213
are set on the parameter (e.g ``s_rho`` )
22112214
2212-
Currently only supports ``ocean_s_coordinate_g1`` and ``ocean_s_coordinate_g2``.
2215+
Currently only supports ``ocean_s_coordinate_g1``, ``ocean_s_coordinate_g2``,
2216+
and ``ocean_sigma_coordinate``.
22132217
22142218
.. warning::
22152219
Very lightly tested. Please double check the results.
@@ -2223,12 +2227,28 @@ def decode_vertical_coords(self, prefix="z"):
22232227
requirements = {
22242228
"ocean_s_coordinate_g1": {"depth_c", "depth", "s", "C", "eta"},
22252229
"ocean_s_coordinate_g2": {"depth_c", "depth", "s", "C", "eta"},
2230+
"ocean_sigma_coordinate": {"sigma", "eta", "depth"},
22262231
}
22272232

22282233
allterms = self.formula_terms
22292234
for dim in allterms:
2230-
suffix = dim.split("_")
2231-
zname = f"{prefix}_" + "_".join(suffix[1:])
2235+
if prefix is None:
2236+
assert (
2237+
outnames is not None
2238+
), "if prefix is None, outnames must be provided"
2239+
# set outnames here
2240+
try:
2241+
zname = outnames[dim]
2242+
except KeyError:
2243+
raise KeyError("Your `outnames` need to include a key of `dim`.")
2244+
2245+
else:
2246+
warnings.warn(
2247+
"`prefix` is being deprecated; use `outnames` instead.",
2248+
DeprecationWarning,
2249+
)
2250+
suffix = dim.split("_")
2251+
zname = f"{prefix}_" + "_".join(suffix[1:])
22322252

22332253
if "standard_name" not in ds[dim].attrs:
22342254
continue
@@ -2254,23 +2274,31 @@ def decode_vertical_coords(self, prefix="z"):
22542274
terms["depth_c"] * terms["s"]
22552275
+ (terms["depth"] - terms["depth_c"]) * terms["C"]
22562276
)
2277+
22572278
# z(n,k,j,i) = S(k,j,i) + eta(n,j,i) * (1 + S(k,j,i) / depth(j,i))
2258-
ds.coords[zname] = S + terms["eta"] * (1 + S / terms["depth"])
2279+
ztemp = S + terms["eta"] * (1 + S / terms["depth"])
22592280

22602281
elif stdname == "ocean_s_coordinate_g2":
22612282
# make sure all necessary terms are present in terms
22622283
# (depth_c * s(k) + depth(j,i) * C(k)) / (depth_c + depth(j,i))
22632284
S = (terms["depth_c"] * terms["s"] + terms["depth"] * terms["C"]) / (
22642285
terms["depth_c"] + terms["depth"]
22652286
)
2287+
22662288
# z(n,k,j,i) = eta(n,j,i) + (eta(n,j,i) + depth(j,i)) * S(k,j,i)
2267-
ds.coords[zname] = terms["eta"] + (terms["eta"] + terms["depth"]) * S
2289+
ztemp = terms["eta"] + (terms["eta"] + terms["depth"]) * S
2290+
2291+
elif stdname == "ocean_sigma_coordinate":
2292+
# z(n,k,j,i) = eta(n,j,i) + sigma(k)*(depth(j,i)+eta(n,j,i))
2293+
ztemp = terms["eta"] + terms["sigma"] * (terms["depth"] + terms["eta"])
22682294

22692295
else:
22702296
raise NotImplementedError(
22712297
f"Coordinate function for {stdname!r} not implemented yet. Contributions welcome!"
22722298
)
22732299

2300+
ds.coords[zname] = ztemp
2301+
22742302

22752303
@xr.register_dataarray_accessor("cf")
22762304
class CFDataArrayAccessor(CFAccessor):

cf_xarray/datasets.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@
1616
ds_no_attrs[variable].attrs = {}
1717

1818

19+
# POM dataset
20+
pomds = xr.Dataset()
21+
pomds["sigma"] = (
22+
# fmt: off
23+
"sigma",
24+
[-0.983333, -0.95 , -0.916667, -0.883333, -0.85 , -0.816667,
25+
-0.783333, -0.75 , -0.716667, -0.683333, -0.65 , -0.616667,
26+
-0.583333, -0.55 , -0.516667, -0.483333, -0.45 , -0.416667,
27+
-0.383333, -0.35 , -0.316667, -0.283333, -0.25 , -0.216667,
28+
-0.183333, -0.15 , -0.116667, -0.083333, -0.05 , -0.016667],
29+
# fmt: on
30+
{
31+
"units": "sigma_level",
32+
"long_name": "Sigma Stretched Vertical Coordinate at Nodes",
33+
"positive": "down",
34+
"standard_name": "ocean_sigma_coordinate",
35+
"formula_terms": "sigma: sigma eta: zeta depth: depth",
36+
}
37+
)
38+
pomds["depth"] = 175.0
39+
pomds["zeta"] = ("ocean_time", [-0.155356, -0.127435])
40+
41+
1942
popds = xr.Dataset()
2043
popds.coords["TLONG"] = (
2144
("nlat", "nlon"),

cf_xarray/tests/test_accessor.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
forecast,
2525
mollwds,
2626
multiple,
27+
pomds,
2728
popds,
2829
romsds,
2930
vert,
@@ -1029,32 +1030,47 @@ def test_param_vcoord_ocean_s_coord():
10291030
romsds.hc + romsds.h
10301031
)
10311032
expected = romsds.zeta + (romsds.zeta + romsds.h) * Zo_rho
1032-
romsds.cf.decode_vertical_coords()
1033+
romsds.cf.decode_vertical_coords(outnames={"s_rho": "z_rho"})
10331034
assert_allclose(
10341035
romsds.z_rho.reset_coords(drop=True), expected.reset_coords(drop=True)
10351036
)
10361037

10371038
romsds.s_rho.attrs["standard_name"] = "ocean_s_coordinate_g1"
10381039
Zo_rho = romsds.hc * (romsds.s_rho - romsds.Cs_r) + romsds.Cs_r * romsds.h
1040+
10391041
expected = Zo_rho + romsds.zeta * (1 + Zo_rho / romsds.h)
1040-
romsds.cf.decode_vertical_coords()
1042+
romsds.cf.decode_vertical_coords(outnames={"s_rho": "z_rho"})
10411043
assert_allclose(
10421044
romsds.z_rho.reset_coords(drop=True), expected.reset_coords(drop=True)
10431045
)
10441046

1045-
romsds.cf.decode_vertical_coords(prefix="ZZZ")
1047+
romsds.cf.decode_vertical_coords(outnames={"s_rho": "ZZZ_rho"})
10461048
assert "ZZZ_rho" in romsds.coords
10471049

10481050
copy = romsds.copy(deep=True)
10491051
del copy["zeta"]
10501052
with pytest.raises(KeyError):
1051-
copy.cf.decode_vertical_coords()
1053+
copy.cf.decode_vertical_coords(outnames={"s_rho": "z_rho"})
10521054

10531055
copy = romsds.copy(deep=True)
10541056
copy.s_rho.attrs["formula_terms"] = "s: s_rho C: Cs_r depth: h depth_c: hc"
10551057
with pytest.raises(KeyError):
1058+
copy.cf.decode_vertical_coords(outnames={"s_rho": "z_rho"})
1059+
1060+
1061+
def test_param_vcoord_ocean_sigma_coordinate():
1062+
expected = pomds.zeta + pomds.sigma * (pomds.depth + pomds.zeta)
1063+
pomds.cf.decode_vertical_coords(outnames={"sigma": "z"})
1064+
assert_allclose(pomds.z.reset_coords(drop=True), expected.reset_coords(drop=True))
1065+
1066+
copy = pomds.copy(deep=True)
1067+
del copy["zeta"]
1068+
with pytest.raises(AssertionError):
10561069
copy.cf.decode_vertical_coords()
10571070

1071+
with pytest.raises(KeyError):
1072+
copy.cf.decode_vertical_coords(outnames={})
1073+
10581074

10591075
def test_formula_terms():
10601076
srhoterms = {

doc/parametricz.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ xr.set_options(display_expand_data=False)
2121

2222
# Parametric Vertical Coordinates
2323

24-
`cf_xarray` supports decoding [parametric vertical coordinates](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#parametric-vertical-coordinate) encoded in the `formula_terms` attribute using {py:meth}`Dataset.cf.decode_vertical_coords`. Right now, only the two ocean s-coordinates are supported, but support for the [rest](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#parametric-v-coord) should be easy to add (Pull Requests are very welcome!).
24+
`cf_xarray` supports decoding [parametric vertical coordinates](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#parametric-vertical-coordinate) encoded in the `formula_terms` attribute using {py:meth}`Dataset.cf.decode_vertical_coords`. Right now, only the two ocean s-coordinates and `ocean_sigma_coordinate` are supported, but support for the [rest](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#parametric-v-coord) should be easy to add (Pull Requests are very welcome!).
2525

2626
## Decoding parametric coordinates
2727
```{code-cell}
@@ -33,7 +33,7 @@ romsds
3333
Now we decode the vertical coordinates **in-place**. Note the new `z_rho` variable. `cf_xarray` sees that `s_rho` has a `formula_terms` attribute, looks up the right formula using `s_rho.attrs["standard_name"]` and computes a new vertical coordinate variable.
3434

3535
```{code-cell}
36-
romsds.cf.decode_vertical_coords() # adds new z_rho variable
36+
romsds.cf.decode_vertical_coords(outnames={'s_rho': 'z_rho'}) # adds new z_rho variable
3737
romsds.z_rho
3838
```
3939

doc/whats-new.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
What's New
44
----------
5+
6+
v 0.7.1 (unreleased)
7+
====================
8+
- added another type of vertical coordinate to decode: ``ocean_sigma_coordinate``. By `Kristen Thyng`_.
9+
10+
511
v0.7.0 (January 24, 2022)
612
=========================
713
- Many improvements to autoguessing for plotting. By `Deepak Cherian`_

0 commit comments

Comments
 (0)