Skip to content

Commit 59ebe13

Browse files
authored
Merge pull request #188 from csiro-coasts/159-ugrid-data-vars
Don't use Dataset.data_vars to access DataArrays in UGrid
2 parents 3e1d529 + a254f86 commit 59ebe13

File tree

2 files changed

+29
-24
lines changed

2 files changed

+29
-24
lines changed

docs/releases/development.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ Next release (in development)
1212
* Fixed :func:`emsarray.utils.datetime_from_np_time`
1313
when the system timezone is not UTC and a specific timezone is requested
1414
(:issue:`176`, :pr:`183`).
15+
* Fixed an issue with UGrid datasets when some of the mesh topology variables
16+
are not present in Dataset.data_vars as they are detected as coordinate variables
17+
(:issue:`159`, :pr:`188`).

src/emsarray/conventions/ugrid.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,11 @@ def mesh_variable(self) -> xarray.DataArray:
378378
``cf_role`` of ``"mesh_topology"``.
379379
"""
380380
if self.topology_key is not None:
381-
return self.dataset.data_vars[self.topology_key]
381+
return self.dataset[self.topology_key]
382382
try:
383+
data_arrays = (self.dataset[name] for name in self.dataset.variables.keys())
383384
return next(
384-
data_array for data_array in self.dataset.data_vars.values()
385+
data_array for data_array in data_arrays
385386
if data_array.attrs.get('cf_role') == 'mesh_topology'
386387
)
387388
except StopIteration:
@@ -436,42 +437,42 @@ def _face_coordinates(self) -> tuple[Hashable, Hashable]:
436437
@property
437438
def node_x(self) -> xarray.DataArray:
438439
"""Data array of node X / longitude coordinates."""
439-
return self.dataset.data_vars[self._node_coordinates[0]]
440+
return self.dataset[self._node_coordinates[0]]
440441

441442
@property
442443
def node_y(self) -> xarray.DataArray:
443444
"""Data array of node Y / latitude coordinates."""
444-
return self.dataset.data_vars[self._node_coordinates[1]]
445+
return self.dataset[self._node_coordinates[1]]
445446

446447
@property
447448
def edge_x(self) -> xarray.DataArray | None:
448449
"""Data array of characteristic edge X / longitude coordinates. Optional."""
449450
try:
450-
return self.dataset.data_vars[self._edge_coordinates[0]]
451+
return self.dataset[self._edge_coordinates[0]]
451452
except KeyError:
452453
return None
453454

454455
@property
455456
def edge_y(self) -> xarray.DataArray | None:
456457
"""Data array of characteristic edge y / latitude coordinates. Optional."""
457458
try:
458-
return self.dataset.data_vars[self._edge_coordinates[1]]
459+
return self.dataset[self._edge_coordinates[1]]
459460
except KeyError:
460461
return None
461462

462463
@property
463464
def face_x(self) -> xarray.DataArray | None:
464465
"""Data array of characteristic face x / longitude coordinates. Optional."""
465466
try:
466-
return self.dataset.data_vars[self._face_coordinates[0]]
467+
return self.dataset[self._face_coordinates[0]]
467468
except KeyError:
468469
return None
469470

470471
@property
471472
def face_y(self) -> xarray.DataArray | None:
472473
"""Data array of characteristic face y / latitude coordinates. Optional."""
473474
try:
474-
return self.dataset.data_vars[self._face_coordinates[1]]
475+
return self.dataset[self._face_coordinates[1]]
475476
except KeyError:
476477
return None
477478

@@ -537,7 +538,7 @@ def has_valid_edge_node_connectivity(self) -> bool:
537538
return False
538539

539540
try:
540-
data_array = self.dataset.data_vars[self.mesh_attributes["edge_node_connectivity"]]
541+
data_array = self.dataset[self.mesh_attributes["edge_node_connectivity"]]
541542
except KeyError:
542543
return False
543544

@@ -570,7 +571,7 @@ def edge_node_connectivity(self) -> xarray.DataArray:
570571
"No valid edge_node_connectivity defined")
571572

572573
name = self.mesh_attributes['edge_node_connectivity']
573-
return self.dataset.data_vars[name]
574+
return self.dataset[name]
574575

575576
@cached_property
576577
def edge_node_array(self) -> numpy.ndarray:
@@ -625,7 +626,7 @@ def has_valid_edge_face_connectivity(self) -> bool:
625626
return False
626627

627628
try:
628-
data_array = self.dataset.data_vars[self.mesh_attributes["edge_face_connectivity"]]
629+
data_array = self.dataset[self.mesh_attributes["edge_face_connectivity"]]
629630
except KeyError:
630631
return False
631632

@@ -650,7 +651,7 @@ def edge_face_connectivity(self) -> xarray.DataArray:
650651
raise NoConnectivityVariableException(
651652
"No valid edge_face_connectivity defined")
652653
name = self.mesh_attributes['edge_face_connectivity']
653-
return self.dataset.data_vars[name]
654+
return self.dataset[name]
654655

655656
@cached_property
656657
def edge_face_array(self) -> numpy.ndarray:
@@ -689,7 +690,7 @@ def has_valid_face_node_connectivity(self) -> bool:
689690
If this is invalid, the entire dataset is invalid.
690691
"""
691692
try:
692-
data_array = self.dataset.data_vars[self.mesh_attributes["face_node_connectivity"]]
693+
data_array = self.dataset[self.mesh_attributes["face_node_connectivity"]]
693694
except KeyError:
694695
return False
695696

@@ -713,7 +714,7 @@ def face_node_connectivity(self) -> xarray.DataArray:
713714
all the others can be derived from this if required.
714715
"""
715716
name = self.mesh_attributes['face_node_connectivity']
716-
return self.dataset.data_vars[name]
717+
return self.dataset[name]
717718

718719
@cached_property
719720
def face_node_array(self) -> numpy.ndarray:
@@ -734,7 +735,7 @@ def has_valid_face_edge_connectivity(self) -> bool:
734735
variable is incorrect.
735736
"""
736737
try:
737-
data_array = self.dataset.data_vars[self.mesh_attributes["face_edge_connectivity"]]
738+
data_array = self.dataset[self.mesh_attributes["face_edge_connectivity"]]
738739
except KeyError:
739740
return False
740741

@@ -773,7 +774,7 @@ def face_edge_connectivity(self) -> xarray.DataArray:
773774
raise NoConnectivityVariableException(
774775
"No valid face_edge_connectivity defined")
775776
name = self.mesh_attributes['face_edge_connectivity']
776-
return self.dataset.data_vars[name]
777+
return self.dataset[name]
777778

778779
@cached_property
779780
def face_edge_array(self) -> numpy.ndarray:
@@ -816,7 +817,7 @@ def has_valid_face_face_connectivity(self) -> bool:
816817
variable is incorrect.
817818
"""
818819
try:
819-
data_array = self.dataset.data_vars[self.mesh_attributes["face_face_connectivity"]]
820+
data_array = self.dataset[self.mesh_attributes["face_face_connectivity"]]
820821
except KeyError:
821822
return False
822823

@@ -841,7 +842,7 @@ def face_face_connectivity(self) -> xarray.DataArray:
841842
raise NoConnectivityVariableException(
842843
"No valid face_face_connectivity defined")
843844
name = self.mesh_attributes['face_face_connectivity']
844-
return self.dataset.data_vars[name]
845+
return self.dataset[name]
845846

846847
@cached_property
847848
def face_face_array(self) -> numpy.ndarray:
@@ -1201,7 +1202,7 @@ def apply_clip_mask(self, clip_mask: xarray.Dataset, work_dir: Pathish) -> xarra
12011202
topology_variables: list[xarray.DataArray] = [topology.mesh_variable]
12021203

12031204
# This is the fill value used in the mask.
1204-
new_fill_value = clip_mask.data_vars['new_node_index'].encoding['_FillValue']
1205+
new_fill_value = clip_mask['new_node_index'].encoding['_FillValue']
12051206

12061207
def integer_indexes(data_array: xarray.DataArray) -> numpy.ndarray:
12071208
masked_values = numpy.ma.masked_invalid(data_array.values)
@@ -1211,11 +1212,11 @@ def integer_indexes(data_array: xarray.DataArray) -> numpy.ndarray:
12111212
masked_integers: numpy.ndarray = masked_values.astype(numpy.int_)
12121213
return masked_integers
12131214

1214-
new_node_indexes = integer_indexes(clip_mask.data_vars['new_node_index'])
1215-
new_face_indexes = integer_indexes(clip_mask.data_vars['new_face_index'])
1216-
has_edges = 'new_edge_index' in clip_mask.data_vars
1215+
new_node_indexes = integer_indexes(clip_mask['new_node_index'])
1216+
new_face_indexes = integer_indexes(clip_mask['new_face_index'])
1217+
has_edges = 'new_edge_index' in clip_mask.variables
12171218
if has_edges:
1218-
new_edge_indexes = integer_indexes(clip_mask.data_vars['new_edge_index'])
1219+
new_edge_indexes = integer_indexes(clip_mask['new_edge_index'])
12191220

12201221
# Re-index the face_node_connectivity variable
12211222
topology_variables.append(update_connectivity(
@@ -1273,7 +1274,8 @@ def integer_indexes(data_array: xarray.DataArray) -> numpy.ndarray:
12731274
dimension_masks[topology.edge_dimension] = ~numpy.ma.getmask(new_edge_indexes)
12741275
mesh_dimensions = set(dimension_masks.keys())
12751276

1276-
for name, data_array in dataset.data_vars.items():
1277+
for name in dataset.variables.keys():
1278+
data_array = dataset[name]
12771279
data_array_path = work_path / (str(name) + '.nc')
12781280
if name in topology_variable_names:
12791281
logger.debug("Skipping %r as it is a topology variable", name)

0 commit comments

Comments
 (0)