Skip to content

Commit e99291d

Browse files
committed
Add support for icemod files in NEMODataTree constructors, fixed bug when using child domains in clip & mask methods.
1 parent 9768e6c commit e99291d

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

nemo_cookbook/nemodatatree.py

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,22 @@ def from_paths(
6565
paths : dict[str, str]
6666
Dictionary containing paths to NEMO grid files, structured as:
6767
{
68-
'parent': {'domain': 'path/to/domain.nc', 'gridT': 'path/to/gridT.nc', ...},
69-
'child': {'1': {'domain': 'path/to/child_domain.nc', 'gridT': 'path/to/child_gridT.nc', ...},
68+
'parent': {'domain': 'path/to/domain.nc',
69+
'gridT': 'path/to/gridT.nc',
70+
, ... ,
71+
'icemod': 'path/to/icemod.nc',
72+
},
73+
'child': {'1': {'domain': 'path/to/child_domain.nc',
74+
'gridT': 'path/to/child_gridT.nc',
75+
, ... ,
76+
'icemod': 'path/to/child_icemod.nc',
77+
},
7078
},
71-
'grandchild': {'2': {'domain': 'path/to/grandchild_domain.nc', 'gridT': 'path/to/grandchild_gridT.nc', ...},
79+
'grandchild': {'2': {'domain': 'path/to/grandchild_domain.nc',
80+
'gridT': 'path/to/grandchild_gridT.nc',
81+
, ...,
82+
'icemod': 'path/to/grandchild_icemod.nc',
83+
},
7284
}
7385
}
7486
@@ -154,17 +166,15 @@ def from_datasets(
154166
155167
Parameters
156168
----------
157-
datasets : dict[str, xr.Dataset]
169+
datasets : dict[str, dict[str, xr.Dataset]]
158170
Dictionary containing xarray.Datasets created from NEMO grid files, structured as:
159171
{
160-
'parent': {'domain': ds_domain, 'gridT': ds_gridT, ...},
161-
'child': {'1': {'domain': ds_domain_1, 'gridT': d_gridT_1, ...},
162-
},
163-
'grandchild': {'2': {'domain': ds_domain_2, 'gridT': ds_gridT_2, ...},
164-
}
172+
'parent': {'domain': ds_domain, 'gridT': ds_gridT, ... , 'icemod': ds_icemod.nc},
173+
'child': {'1': {'domain': ds_domain_1, 'gridT': d_gridT_1, ...}},
174+
'grandchild': {'2': {'domain': ds_domain_2, 'gridT': ds_gridT_2, ...}}
165175
}
166176
167-
nests : dict[str, str], optional
177+
nests : dict[str, dict[st, str]], optional
168178
Dictionary describing the properties of nested domains, structured as:
169179
{
170180
"1": {
@@ -723,7 +733,7 @@ def integral(
723733
dom_mask = cls[grid][f"{grid_str}mask"]
724734
else:
725735
# Apply 2-dimensional t/u/v/f/w mask:
726-
dom_mask = cls[grid][f"{grid_str}mask"][0, :, :]
736+
dom_mask = cls[grid][f"{grid_str}mask"][0, :, :].drop_vars("k")
727737

728738
# -- Perform integration -- #
729739
if cum_dims is not None:
@@ -772,10 +782,13 @@ def clip_grid(
772782
raise ValueError("bounding box must be a tuple (lon_min, lon_max, lat_min, lat_max).")
773783

774784
# -- Clip the grid to given bounding box -- #
785+
dom_inds = [char for char in grid if char.isdigit()]
786+
dom_str = f"{dom_inds[-1]}_" if len(dom_inds) != 0 else ""
775787
grid_str = f"{grid.lower()[-1]}"
788+
776789
# Indexing with a mask requires eager loading:
777-
glam = cls[grid][f"glam{grid_str}"].load()
778-
gphi = cls[grid][f"gphi{grid_str}"].load()
790+
glam = cls[grid][f"{dom_str}glam{grid_str}"].load()
791+
gphi = cls[grid][f"{dom_str}gphi{grid_str}"].load()
779792

780793
grid_clipped = cls[grid].dataset.where(
781794
(glam >= bbox[0]) &
@@ -822,8 +835,10 @@ def clip_domain(
822835
grid_paths = [path[0] for path in list(cls.subtree_with_keys)]
823836

824837
if dom == '.':
838+
dom_str = ""
825839
grid_paths = [path for path in grid_paths if ("_" not in path) & ("grid" in path)]
826840
else:
841+
dom_str = f"{dom}_"
827842
grid_paths = [path for path in grid_paths if dom in path]
828843

829844
# -- Clip grids to given bounding box -- #
@@ -834,8 +849,8 @@ def clip_domain(
834849
# Use (glamt, gphit) coords for W-grids:
835850
grid_str = f"{grid.lower()[-1]}" if 'W' not in grid else 't'
836851
# Indexing with a mask requires eager loading:
837-
glam = cls[grid][f"glam{grid_str}"].load()
838-
gphi = cls[grid][f"gphi{grid_str}"].load()
852+
glam = cls[grid][f"{dom_str}glam{grid_str}"].load()
853+
gphi = cls[grid][f"{dom_str}gphi{grid_str}"].load()
839854

840855
grid_clipped = cls[grid].dataset.where(
841856
(glam >= bbox[0]) &
@@ -892,13 +907,14 @@ def mask_with_polygon(
892907

893908
if dom_str == ".":
894909
i_name, j_name = "i", "j"
910+
lon_name = f"glam{grid.lower()[-1]}"
911+
lat_name = f"gphi{grid.lower()[-1]}"
895912
else:
896913
i_name, j_name = f"i{dom_str}", f"j{dom_str}"
914+
lon_name = f"{dom_str}_glam{grid.lower()[-1]}"
915+
lat_name = f"{dom_str}_gphi{grid.lower()[-1]}"
897916

898917
# -- Create mask using polygon coordinates -- #
899-
lon_name = f"glam{grid.lower()[-1]}"
900-
lat_name = f"gphi{grid.lower()[-1]}"
901-
902918
mask = add_polygon_msk(lon_grid=cls[grid][lon_name],
903919
lat_grid=cls[grid][lat_name],
904920
lon_poly=lon_poly,
@@ -964,9 +980,9 @@ def masked_statistic(
964980
dom_mask = cls[grid][f"{grid_str}mask"]
965981
else:
966982
# Apply 2-dimensional t/u/v/f/w mask:
967-
dom_mask = cls[grid][f"{grid_str}mask"][0, :, :]
983+
dom_mask = cls[grid][f"{grid_str}mask"][0, :, :].drop_vars("k")
968984

969-
da = cls[grid][var].where(dom_mask.astype(bool) & mask_poly)
985+
da = cls[grid][var].where(dom_mask & mask_poly)
970986

971987
match statistic:
972988
case "mean":
@@ -1172,8 +1188,16 @@ def binned_statistic(
11721188
raise ValueError(f"mask must have dimensions subset from {cls[grid].dims}.")
11731189

11741190
# -- Define input variables & apply grid mask -- #
1191+
dom_inds = [char for char in grid if char.isdigit()]
1192+
dom_str = f"{dom_inds[-1]}_" if len(dom_inds) != 0 else ""
11751193
grid_str = f"{grid.lower()[-1]}"
1176-
dom_mask = cls[grid][f"{grid_str}mask"]
1194+
1195+
if f"{dom_str}depth{grid_str}" in cls[grid][values].coords:
1196+
# Apply 3-dimensional t/u/v/f/w mask:
1197+
dom_mask = cls[grid][f"{grid_str}mask"]
1198+
else:
1199+
# Apply 2-dimensional t/u/v/f/w mask:
1200+
dom_mask = cls[grid][f"{grid_str}mask"][0, :, :].drop_vars("k")
11771201

11781202
values_data = cls[grid][values].where(mask & dom_mask) if mask is not None else cls[grid][values].where(dom_mask)
11791203
var_data = [cls[grid][var].where(mask & dom_mask) if mask is not None else cls[grid][var].where(dom_mask) for var in vars]
@@ -1210,7 +1234,7 @@ def transform_vertical_grid(
12101234
grid: str,
12111235
var: str,
12121236
e3_new: xr.DataArray
1213-
) -> tuple[xr.DataArray, xr.DataArray]:
1237+
) -> xr.Dataset:
12141238
"""
12151239
Transform variable defined on a NEMO model grid to a
12161240
new vertical grid using conservative interpolation.
@@ -1245,6 +1269,7 @@ def transform_vertical_grid(
12451269
# -- Define input variables -- #
12461270
dom_inds = [char for char in grid if char.isdigit()]
12471271
dom = dom_inds[-1] if len(dom_inds) != 0 else "."
1272+
12481273
if dom == ".":
12491274
i_name, j_name, k_name = "i", "j", "k"
12501275
else:

0 commit comments

Comments
 (0)