From c1bf85ae423bac80c45e565dd3f8ead2239de646 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:22:32 +0100 Subject: [PATCH 1/4] Update _maybe_bring_other_depths_to_depth --- src/parcels/convert.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/parcels/convert.py b/src/parcels/convert.py index e8f2b84b9..3972145b8 100644 --- a/src/parcels/convert.py +++ b/src/parcels/convert.py @@ -96,9 +96,14 @@ def _pick_expected_coords(coords: xr.Dataset, expected_coord_names: list[str]) - def _maybe_bring_other_depths_to_depth(ds): if "depth" in ds.coords: for var in ds.data_vars: - for old_depth in ["depthu", "depthv", "deptht", "depthw"]: + for old_depth, target in [ + ("depthu", "depth_center"), + ("depthv", "depth_center"), + ("deptht", "depth_center"), + ("depthw", "depth"), + ]: if old_depth in ds[var].dims: - ds[var] = ds[var].assign_coords(**{old_depth: ds["depth"].values}).rename({old_depth: "depth"}) + ds[var] = ds[var].rename({old_depth: target}) return ds From cc0c0cb6744c5edca3b813b4e22ecd530853077d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:51:52 +0100 Subject: [PATCH 2/4] bugfix --- src/parcels/convert.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parcels/convert.py b/src/parcels/convert.py index 3972145b8..d9cb13dae 100644 --- a/src/parcels/convert.py +++ b/src/parcels/convert.py @@ -25,7 +25,7 @@ _NEMO_EXPECTED_COORDS = ["glamf", "gphif"] -_NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "glamf", "gphif"] +_NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "depth_center", "glamf", "gphif"] _NEMO_AXIS_VARNAMES = { "x": "X", @@ -33,6 +33,7 @@ "y": "Y", "y_center": "Y", "depth": "Z", + "depth_center": "Z", "time": "T", } @@ -297,7 +298,6 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da coords = coords.isel({dim: 0}) if len(coords.dims) != 2: raise ValueError("Expected coordsinates to be 2 dimensional") - ds = xr.merge(list(fields.values()) + [coords]) ds = _maybe_rename_variables(ds, _NEMO_VARNAMES_MAPPING) ds = _maybe_create_depth_dim(ds) @@ -336,7 +336,7 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da sgrid.DimDimPadding("x_center", "x", sgrid.Padding.LOW), sgrid.DimDimPadding("y_center", "y", sgrid.Padding.LOW), ), - vertical_dimensions=(sgrid.DimDimPadding("z_center", "depth", sgrid.Padding.HIGH),), + vertical_dimensions=(sgrid.DimDimPadding("depth_center", "depth", sgrid.Padding.HIGH),), ).to_attrs(), ) From d004bf7542e253ac9efd0c1d426d76c69b58565d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Wed, 18 Mar 2026 15:46:03 +0100 Subject: [PATCH 3/4] Improve --- src/parcels/convert.py | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/parcels/convert.py b/src/parcels/convert.py index d9cb13dae..cd6ede21c 100644 --- a/src/parcels/convert.py +++ b/src/parcels/convert.py @@ -9,8 +9,8 @@ Xarray dataset so that users can further provide any missing metadata that was unable to be determined before they pass it to the FieldSet constructor. """ - from __future__ import annotations +import warnings import typing @@ -23,7 +23,7 @@ if typing.TYPE_CHECKING: import uxarray as ux -_NEMO_EXPECTED_COORDS = ["glamf", "gphif"] +_NEMO_EXPECTED_COORDS = ["glamf", "gphif", "depthw"] _NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "depth_center", "glamf", "gphif"] @@ -95,25 +95,22 @@ def _pick_expected_coords(coords: xr.Dataset, expected_coord_names: list[str]) - def _maybe_bring_other_depths_to_depth(ds): - if "depth" in ds.coords: - for var in ds.data_vars: - for old_depth, target in [ - ("depthu", "depth_center"), - ("depthv", "depth_center"), - ("deptht", "depth_center"), - ("depthw", "depth"), - ]: - if old_depth in ds[var].dims: - ds[var] = ds[var].rename({old_depth: target}) - return ds - - -def _maybe_create_depth_dim(ds): + for var in ds.data_vars: + for old_depth, target in [ + ("depthu", "depth_center"), + ("depthv", "depth_center"), + ("deptht", "depth_center"), + ("depthw", "depth"), + ]: + if old_depth in ds[var].dims: + ds[var] = ds[var].rename({old_depth: target}) + if "depth" not in ds.dims: + warnings.warn("No depth dimension found in your dataset. Assuming no depth (i.e., surface data).", stacklevel=1) ds = ds.expand_dims({"depth": [0]}) ds["depth"] = xr.DataArray([0], dims=["depth"]) return ds - + def _maybe_rename_coords(ds, axis_varnames): try: @@ -291,16 +288,16 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da if coords.sizes["time"] != 1: raise ValueError("Time dimension in coords must be length 1 (i.e., no time-varying grid).") coords = coords.isel(time=0).drop("time") - if len(coords.dims) == 3: + + if len(coords.dims) == 3: #! This should really be looking at the dimensionality of the lons and lats arrays. Currently having 2D lon lat and 1D depth triggers this `if` clause for dim, len_ in coords.sizes.items(): if len_ == 1: # TODO: log statement about selecting along z dim of 1 coords = coords.isel({dim: 0}) - if len(coords.dims) != 2: - raise ValueError("Expected coordsinates to be 2 dimensional") + # if len(coords.dims) != 2: #! This should really be looking at the dimensionality of the lons and lats arrays. Currently having 2D lon lat and 1D depth triggers this `if` clause + # raise ValueError("Expected coordinates to be 2 dimensional") ds = xr.merge(list(fields.values()) + [coords]) ds = _maybe_rename_variables(ds, _NEMO_VARNAMES_MAPPING) - ds = _maybe_create_depth_dim(ds) ds = _maybe_bring_other_depths_to_depth(ds) ds = _drop_unused_dimensions_and_coords(ds, _NEMO_DIMENSION_COORD_NAMES) ds = _assign_dims_as_coords(ds, _NEMO_DIMENSION_COORD_NAMES) From 3e02b35b4be84a7c3a3e033edbc6412e81e35d28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 15:32:03 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/parcels/convert.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/parcels/convert.py b/src/parcels/convert.py index cd6ede21c..e324dcd11 100644 --- a/src/parcels/convert.py +++ b/src/parcels/convert.py @@ -9,10 +9,11 @@ Xarray dataset so that users can further provide any missing metadata that was unable to be determined before they pass it to the FieldSet constructor. """ + from __future__ import annotations -import warnings import typing +import warnings import numpy as np import xarray as xr @@ -25,7 +26,19 @@ _NEMO_EXPECTED_COORDS = ["glamf", "gphif", "depthw"] -_NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "depth_center", "glamf", "gphif"] +_NEMO_DIMENSION_COORD_NAMES = [ + "x", + "y", + "time", + "x", + "x_center", + "y", + "y_center", + "depth", + "depth_center", + "glamf", + "gphif", +] _NEMO_AXIS_VARNAMES = { "x": "X", @@ -104,13 +117,13 @@ def _maybe_bring_other_depths_to_depth(ds): ]: if old_depth in ds[var].dims: ds[var] = ds[var].rename({old_depth: target}) - + if "depth" not in ds.dims: warnings.warn("No depth dimension found in your dataset. Assuming no depth (i.e., surface data).", stacklevel=1) ds = ds.expand_dims({"depth": [0]}) ds["depth"] = xr.DataArray([0], dims=["depth"]) return ds - + def _maybe_rename_coords(ds, axis_varnames): try: @@ -288,8 +301,10 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da if coords.sizes["time"] != 1: raise ValueError("Time dimension in coords must be length 1 (i.e., no time-varying grid).") coords = coords.isel(time=0).drop("time") - - if len(coords.dims) == 3: #! This should really be looking at the dimensionality of the lons and lats arrays. Currently having 2D lon lat and 1D depth triggers this `if` clause + + if ( + len(coords.dims) == 3 + ): #! This should really be looking at the dimensionality of the lons and lats arrays. Currently having 2D lon lat and 1D depth triggers this `if` clause for dim, len_ in coords.sizes.items(): if len_ == 1: # TODO: log statement about selecting along z dim of 1