|
13 | 13 | from __future__ import annotations |
14 | 14 |
|
15 | 15 | import typing |
| 16 | +import warnings |
16 | 17 | from typing import cast |
17 | 18 |
|
18 | 19 | import numpy as np |
|
24 | 25 | if typing.TYPE_CHECKING: |
25 | 26 | import uxarray as ux |
26 | 27 |
|
27 | | -_NEMO_EXPECTED_COORDS = ["glamf", "gphif"] |
28 | | - |
29 | | -_NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "glamf", "gphif"] |
| 28 | +_NEMO_EXPECTED_COORDS = [ |
| 29 | + "glamf", |
| 30 | + "gphif", |
| 31 | +] # "depthw" # TODO: Depthw needs to be available if the data has a depth dim. Refactor the whole convert module, this can surely all be handled better. |
| 32 | + |
| 33 | +_NEMO_DIMENSION_COORD_NAMES = [ |
| 34 | + "x", |
| 35 | + "y", |
| 36 | + "time", |
| 37 | + "x", |
| 38 | + "x_center", |
| 39 | + "y", |
| 40 | + "y_center", |
| 41 | + "depth", |
| 42 | + "depth_center", |
| 43 | + "glamf", |
| 44 | + "gphif", |
| 45 | +] |
30 | 46 |
|
31 | 47 | _NEMO_AXIS_VARNAMES = { |
32 | 48 | "x": "X", |
33 | 49 | "x_center": "X", |
34 | 50 | "y": "Y", |
35 | 51 | "y_center": "Y", |
36 | 52 | "depth": "Z", |
| 53 | + "depth_center": "Z", |
37 | 54 | "time": "T", |
38 | 55 | } |
39 | 56 |
|
@@ -95,16 +112,18 @@ def _pick_expected_coords(coords: xr.Dataset, expected_coord_names: list[str]) - |
95 | 112 |
|
96 | 113 |
|
97 | 114 | def _maybe_bring_other_depths_to_depth(ds): |
98 | | - if "depth" in ds.coords: |
99 | | - for var in ds.data_vars: |
100 | | - for old_depth in ["depthu", "depthv", "deptht", "depthw"]: |
101 | | - if old_depth in ds[var].dims: |
102 | | - ds[var] = ds[var].assign_coords(**{old_depth: ds["depth"].values}).rename({old_depth: "depth"}) |
103 | | - return ds |
104 | | - |
| 115 | + for var in ds.data_vars: |
| 116 | + for old_depth, target in [ |
| 117 | + ("depthu", "depth_center"), |
| 118 | + ("depthv", "depth_center"), |
| 119 | + ("deptht", "depth_center"), |
| 120 | + ("depthw", "depth"), |
| 121 | + ]: |
| 122 | + if old_depth in ds[var].dims: |
| 123 | + ds[var] = ds[var].rename({old_depth: target}) |
105 | 124 |
|
106 | | -def _maybe_create_depth_dim(ds): |
107 | 125 | if "depth" not in ds.dims: |
| 126 | + warnings.warn("No depth dimension found in your dataset. Assuming no depth (i.e., surface data).", stacklevel=1) |
108 | 127 | ds = ds.expand_dims({"depth": [0]}) |
109 | 128 | ds["depth"] = xr.DataArray([0], dims=["depth"]) |
110 | 129 | return ds |
@@ -286,17 +305,18 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da |
286 | 305 | if coords.sizes["time"] != 1: |
287 | 306 | raise ValueError("Time dimension in coords must be length 1 (i.e., no time-varying grid).") |
288 | 307 | coords = coords.isel(time=0).drop("time") |
289 | | - if len(coords.dims) == 3: |
| 308 | + |
| 309 | + if ( |
| 310 | + len(coords.dims) == 3 |
| 311 | + ): #! 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 |
290 | 312 | for dim, len_ in coords.sizes.items(): |
291 | 313 | if len_ == 1: |
292 | 314 | # TODO: log statement about selecting along z dim of 1 |
293 | 315 | coords = coords.isel({dim: 0}) |
294 | | - if len(coords.dims) != 2: |
295 | | - raise ValueError("Expected coordsinates to be 2 dimensional") |
296 | | - |
| 316 | + # 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 |
| 317 | + # raise ValueError("Expected coordinates to be 2 dimensional") |
297 | 318 | ds = xr.merge(list(fields.values()) + [coords]) |
298 | 319 | ds = _maybe_rename_variables(ds, _NEMO_VARNAMES_MAPPING) |
299 | | - ds = _maybe_create_depth_dim(ds) |
300 | 320 | ds = _maybe_bring_other_depths_to_depth(ds) |
301 | 321 | ds = _drop_unused_dimensions_and_coords(ds, _NEMO_DIMENSION_COORD_NAMES) |
302 | 322 | ds = _assign_dims_as_coords(ds, _NEMO_DIMENSION_COORD_NAMES) |
@@ -332,7 +352,7 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da |
332 | 352 | sgrid.FaceNodePadding("x_center", "x", sgrid.Padding.LOW), |
333 | 353 | sgrid.FaceNodePadding("y_center", "y", sgrid.Padding.LOW), |
334 | 354 | ), |
335 | | - vertical_dimensions=(sgrid.FaceNodePadding("z_center", "depth", sgrid.Padding.HIGH),), |
| 355 | + vertical_dimensions=(sgrid.FaceNodePadding("depth_center", "depth", sgrid.Padding.HIGH),), |
336 | 356 | ).to_attrs(), |
337 | 357 | ) |
338 | 358 |
|
@@ -525,7 +545,7 @@ def copernicusmarine_to_sgrid( |
525 | 545 | sgrid.FaceNodePadding("x_center", "lon", sgrid.Padding.LOW), |
526 | 546 | sgrid.FaceNodePadding("y_center", "lat", sgrid.Padding.LOW), |
527 | 547 | ), |
528 | | - vertical_dimensions=(sgrid.FaceNodePadding("z_center", "depth", sgrid.Padding.LOW),), |
| 548 | + vertical_dimensions=(sgrid.FaceNodePadding("depth_center", "depth", sgrid.Padding.LOW),), |
529 | 549 | ).to_attrs(), |
530 | 550 | ) |
531 | 551 |
|
|
0 commit comments