Skip to content

Commit 6fe9016

Browse files
committed
Deprecate Convention.get_depth_name() et al
`Convention.depth_coordinate` and `Convention.depth_coordinates` are better suited to the job when used in conjunction with `utils.data_array_to_name` and `utils.name_to_data_array`.
1 parent 13f63d3 commit 6fe9016

File tree

10 files changed

+208
-146
lines changed

10 files changed

+208
-146
lines changed

src/emsarray/cli/commands/extract_points.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import emsarray
88
from emsarray.cli import BaseCommand, CommandException
9+
from emsarray.exceptions import NoSuchCoordinateError
910
from emsarray.operations import point_extraction
1011
from emsarray.utils import to_netcdf_with_fixes
1112

@@ -79,8 +80,8 @@ def handle(self, options: argparse.Namespace) -> None:
7980
f"{rows.head()}\n"
8081
f"(total rows: {len(rows)})")
8182
try:
82-
time_name = dataset.ems.get_time_name()
83-
except KeyError:
83+
time_name = dataset.ems.time_coordinate.name
84+
except NoSuchCoordinateError:
8485
time_name = None
8586

8687
to_netcdf_with_fixes(

src/emsarray/conventions/_base.py

Lines changed: 135 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -276,51 +276,8 @@ def _get_data_array(self, data_array: DataArrayOrName) -> xarray.DataArray:
276276

277277
@cached_property
278278
def time_coordinate(self) -> xarray.DataArray:
279-
"""The time coordinate for this dataset.
280-
281-
Returns
282-
-------
283-
xarray.DataArray
284-
The variable for the time coordinate for this dataset.
285-
286-
Raises
287-
------
288-
exceptions.NoSuchCoordinateError
289-
If no time coordinate was found
290-
291-
See Also
292-
--------
293-
get_time_name
294-
"""
295-
return self.dataset[self.get_time_name()]
296-
297-
@cached_property
298-
def depth_coordinate(self) -> xarray.DataArray:
299-
"""The depth coordinate for this dataset.
300-
301-
Returns
302-
-------
303-
xarray.DataArray
304-
The variable for the depth coordinate for this dataset.
305-
306-
Raises
307-
------
308-
exceptions.NoSuchCoordinateError
309-
If no depth coordinate was found
310-
311-
See Also
312-
--------
313-
get_depth_name
314279
"""
315-
return self.dataset[self.get_depth_name()]
316-
317-
def get_time_name(self) -> Hashable:
318-
"""Get the name of the time variable in this dataset.
319-
320-
Returns
321-
-------
322-
Hashable
323-
The name of the time coordinate.
280+
xarray.DataArray: The time coordinate for this dataset.
324281
325282
Raises
326283
------
@@ -339,7 +296,8 @@ def get_time_name(self) -> Hashable:
339296
----------
340297
.. [1] `CF Conventions v1.10, 4.4 Time Coordinate <https://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#time-coordinate>`_
341298
"""
342-
for name, variable in self.dataset.variables.items():
299+
for name in self.dataset.variables.keys():
300+
variable = self.dataset[name]
343301
# xarray will automatically decode all time variables
344302
# and move the 'units' attribute over to encoding to store this change.
345303
if 'units' in variable.encoding:
@@ -348,27 +306,20 @@ def get_time_name(self) -> Hashable:
348306
if 'since' in units:
349307
# The variable must now be a numpy datetime
350308
if variable.dtype.type == numpy.datetime64:
351-
return name
309+
return variable
352310
raise NoSuchCoordinateError("Could not find time coordinate in dataset")
353311

354-
def get_depth_name(self) -> Hashable:
355-
"""Get the name of the layer depth coordinate variable.
356-
357-
For datasets with multiple depth variables, this should be the one that
358-
represents the centre of the layer, not the bounds.
359-
360-
Note that this is the name of the coordinate variable,
361-
not the name of the dimension, for datasets where these differ.
362-
363-
Returns
364-
-------
365-
Hashable
366-
The name of the depth coordinate.
312+
@cached_property
313+
def depth_coordinate(self) -> xarray.DataArray:
314+
"""
315+
xarray.DataArray: The depth coordinate for this dataset.
316+
For datasets with multiple depth coordinates
317+
this will be the depth coordinate with the smallest :attr:`~xarray.DataArray.size`.
367318
368319
Raises
369320
------
370321
exceptions.NoSuchCoordinateError
371-
If no time coordinate was found
322+
If no depth coordinate was found
372323
373324
Notes
374325
-----
@@ -382,24 +333,31 @@ def get_depth_name(self) -> Hashable:
382333
all coordinates are checked for a ``standard_name: "depth"``,
383334
``coordinate_type: "Z"``, or ``axiz: "Z"``.
384335
336+
See Also
337+
--------
338+
:attr:`depth_coordinates`
339+
:attr:`get_depth_coordinate_for_data_array`
340+
385341
References
386342
----------
387343
.. [2] `CF Conventions v1.10, 4.3 Vertical (Height or Depth) Coordinate <https://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#vertical-coordinate>`_
388344
"""
389-
try:
390-
return self.get_all_depth_names()[0]
391-
except IndexError:
392-
raise NoSuchCoordinateError("Could not find depth coordinate in dataset")
345+
depth_coordinates = self.depth_coordinates
346+
if len(depth_coordinates) == 0:
347+
raise NoSuchCoordinateError("Dataset has no depth coordinate")
348+
return min(depth_coordinates, key=lambda c: c.size)
393349

394-
def get_all_depth_names(self) -> list[Hashable]:
395-
"""Get the names of all depth layers.
396-
Some datasets include both a depth layer centre,
397-
and the depth layer 'edges'.
350+
@cached_property
351+
def depth_coordinates(self) -> tuple[xarray.DataArray, ...]:
352+
"""
353+
tuple of xarray.DataArray: All the depth coordinate for this dataset.
398354
399-
Note that this is the names of the coordinate variables,
400-
not the names of the dimensions, for datasets where these differ.
355+
See Also
356+
--------
357+
:attr:`depth_coordinate`
358+
:attr:`get_depth_coordinate_for_data_array`
401359
"""
402-
depth_names = []
360+
depth_coordinates = []
403361
for name in self.dataset.variables.keys():
404362
data_array = self.dataset[name]
405363

@@ -422,9 +380,103 @@ def get_all_depth_names(self) -> list[Hashable]:
422380
# The variable isn't on a grid - this is good!
423381
pass
424382

425-
depth_names.append(name)
383+
depth_coordinates.append(data_array)
426384

427-
return depth_names
385+
return tuple(depth_coordinates)
386+
387+
@utils.deprecated(
388+
(
389+
"Convention.get_time_name() is deprecated. "
390+
"Use Convention.time_coordinate.name instead."
391+
),
392+
DeprecationWarning,
393+
)
394+
def get_time_name(self) -> Hashable:
395+
"""Get the name of the time variable in this dataset.
396+
397+
.. deprecated:: 0.7.0
398+
:meth:`Convention.get_time_name()` is deprecated and will be removed.
399+
Use `Convention.time_coordinate.name` instead.
400+
401+
Returns
402+
-------
403+
Hashable
404+
The name of the time coordinate.
405+
406+
See Also
407+
--------
408+
:attr:`Convention.time_coordinate`
409+
410+
Raises
411+
------
412+
exceptions.NoSuchCoordinateError
413+
If no time coordinate was found
414+
"""
415+
return self.time_coordinate.name
416+
417+
@utils.deprecated(
418+
(
419+
"Convention.get_depth_name() is deprecated. "
420+
"Use Convention.depth_coordinate.name instead."
421+
),
422+
DeprecationWarning,
423+
)
424+
def get_depth_name(self) -> Hashable:
425+
"""Get the name of the layer depth coordinate variable.
426+
427+
.. deprecated:: 0.7.0
428+
:meth:`Convention.get_depth_name()` is deprecated and will be removed.
429+
Use `Convention.depth_coordinate.name` instead.
430+
431+
For datasets with multiple depth variables, this should be the one that
432+
represents the centre of the layer, not the bounds.
433+
434+
Note that this is the name of the coordinate variable,
435+
not the name of the dimension, for datasets where these differ.
436+
437+
Returns
438+
-------
439+
Hashable
440+
The name of the depth coordinate.
441+
442+
Raises
443+
------
444+
exceptions.NoSuchCoordinateError
445+
If no time coordinate was found
446+
447+
See Also
448+
--------
449+
:attr:`Convention.depth_coordinate`
450+
:meth:`Convention.get_depth_coordinate_for_data_array`
451+
"""
452+
return self.depth_coordinate.name
453+
454+
@utils.deprecated(
455+
(
456+
"Convention.get_all_depth_names() is deprecated. "
457+
"Use [c.name for c in Convention.depth_coordinates] instead."
458+
),
459+
DeprecationWarning,
460+
)
461+
def get_all_depth_names(self) -> list[Hashable]:
462+
"""Get the names of all depth layers.
463+
Some datasets include both a depth layer centre,
464+
and the depth layer 'edges'.
465+
466+
.. deprecated:: 0.7.0
467+
:meth:`Convention.get_all_depth_names()` is deprecated and will be removed.
468+
Use `[c.name for c in Convention.depth_coordinates]` instead.
469+
470+
Note that this is the names of the coordinate variables,
471+
not the names of the dimensions, for datasets where these differ.
472+
473+
See also
474+
--------
475+
:attr:`depth_coordinate`
476+
:attr:`depth_coordinates`
477+
:meth:`get_depth_coordinate_for_data_array`
478+
"""
479+
return [c.name for c in self.depth_coordinates]
428480

429481
@utils.deprecated(
430482
(
@@ -980,7 +1032,7 @@ def animate_on_figure(
9801032
Pass in either the name of a coordinate variable
9811033
or coordinate variable itself.
9821034
Optional, if not supplied the time coordinate
983-
from :meth:`get_time_name` is used.
1035+
from :attr:`Convention.time_coordinate` is used.
9841036
Other appropriate coordinates to animate over include depth.
9851037
**kwargs
9861038
Any extra arguments are passed to :func:`.plot.animate_on_figure`.
@@ -1556,17 +1608,17 @@ def select_variables(self, variables: Iterable[DataArrayOrName]) -> xarray.Datas
15561608
drop_geometry
15571609
"""
15581610
all_vars = set(self.dataset.variables.keys())
1559-
keep_vars = {
1611+
keep_vars = [
15601612
*variables,
15611613
*self.get_all_geometry_names(),
1562-
*self.get_all_depth_names(),
1563-
}
1614+
*self.depth_coordinates,
1615+
]
15641616
try:
1565-
keep_vars.add(self.get_time_name())
1617+
keep_vars.append(self.time_coordinate)
15661618
except NoSuchCoordinateError:
15671619
pass
1568-
keep_vars = {utils.data_array_to_name(self.dataset, v) for v in keep_vars}
1569-
return self.dataset.drop_vars(all_vars - keep_vars)
1620+
keep_var_names = {utils.data_array_to_name(self.dataset, v) for v in keep_vars}
1621+
return self.dataset.drop_vars(all_vars - keep_var_names)
15701622

15711623
@abc.abstractmethod
15721624
def make_clip_mask(
@@ -1685,7 +1737,7 @@ def to_netcdf(self, path: Pathish, **kwargs: Any) -> None:
16851737
make the EMS compatible.
16861738
"""
16871739
try:
1688-
time_variable = self.get_time_name()
1740+
time_variable = self.time_coordinate
16891741
except KeyError:
16901742
time_variable = None
16911743
utils.to_netcdf_with_fixes(
@@ -1696,7 +1748,7 @@ def to_netcdf(self, path: Pathish, **kwargs: Any) -> None:
16961748
def ocean_floor(self) -> xarray.Dataset:
16971749
"""An alias for :func:`emsarray.operations.depth.ocean_floor`"""
16981750
return depth.ocean_floor(
1699-
self.dataset, self.get_all_depth_names(),
1751+
self.dataset, self.depth_coordinates,
17001752
non_spatial_variables=[self.time_coordinate])
17011753

17021754
def normalize_depth_variables(
@@ -1707,7 +1759,7 @@ def normalize_depth_variables(
17071759
) -> xarray.Dataset:
17081760
"""An alias for :func:`emsarray.operations.depth.normalize_depth_variables`"""
17091761
return depth.normalize_depth_variables(
1710-
self.dataset, self.get_all_depth_names(),
1762+
self.dataset, self.depth_coordinates,
17111763
positive_down=positive_down, deep_to_shallow=deep_to_shallow)
17121764

17131765

0 commit comments

Comments
 (0)