Skip to content

Commit e94ef85

Browse files
653 udsugridto netcdf writes dataset that cannot be depth sliced afterwards (#662)
* added remove_nan_fillvalue_attrs * added testcase * updated whatsnew
1 parent 0ed0447 commit e94ef85

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

dfm_tools/xugrid_helpers.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ def decode_default_fillvals(ds):
141141
return ds
142142

143143

144+
def remove_nan_fillvalue_attrs(ds : (xr.Dataset, xu.UgridDataset)):
145+
"""
146+
xarray writes {"_FillValue": np.nan} to encoding for variables without _FillValue attribute.
147+
Remove these again upon reading to avoid issues.
148+
"""
149+
if isinstance(ds,xu.UgridDataset):
150+
ds = ds.obj
151+
152+
count = 0
153+
for varn in ds.variables:
154+
if '_FillValue' in ds[varn].encoding:
155+
if np.isnan(ds[varn].encoding['_FillValue']):
156+
ds[varn].encoding.pop('_FillValue')
157+
count += 1
158+
if count > 0:
159+
print(f"[{count} nan fillvalue attrs removed]", end="")
160+
161+
144162
def open_partitioned_dataset(file_nc, decode_fillvals=False, remove_edges=True, remove_ghost=True, **kwargs):
145163
"""
146164
using xugrid to read and merge partitions, with some additional features (remaning old layerdim, timings, set zcc/zw as data_vars)
@@ -200,6 +218,7 @@ def open_partitioned_dataset(file_nc, decode_fillvals=False, remove_edges=True,
200218
print('[mapformat1] ',end='')
201219
#for mapformat1 mapfiles: merge different face dimensions (rename nFlowElem to nNetElem) to make sure the dataset topology is correct
202220
ds = ds.rename({'nFlowElem':'nNetElem'})
221+
remove_nan_fillvalue_attrs(ds)
203222
uds = xu.core.wrap.UgridDataset(ds)
204223
if remove_ghost: #TODO: this makes it way slower (at least for GTSM, although merging seems faster), but is necessary since values on overlapping cells are not always identical (eg in case of Venice ucmag)
205224
uds = remove_ghostcells(uds, file_nc_one)

docs/whats-new.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## UNRELEASED
22

33
### Feat
4+
- pop np.nan `_FillValue` attrs in `dfmt.open_partitioned_dataset()` by [@veenstrajelmer](https://github.com/veenstrajelmer) in [#662](https://github.com/Deltares/dfm_tools/pull/662)
45
- interpolation of edge/node variables to faces with `dfmt.uda_to_faces()` (deprecates `dfmt.uda_edges_to_faces()`) by [@veenstrajelmer](https://github.com/veenstrajelmer) in [#651](https://github.com/Deltares/dfm_tools/pull/651) and [#644](https://github.com/Deltares/dfm_tools/pull/644)
56

67
### Fix

tests/test_xugrid_helpers.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,42 @@ def test_remove_unassociated_edges():
3030
assert ds2_edgedimsize == ds_edgedimsize-1
3131

3232

33+
@pytest.mark.unittest
34+
def test_remove_nan_fillvalue_attrs():
35+
"""
36+
xarray writes {"_FillValue": np.nan} to encoding for variables without _FillValue attribute.
37+
This test checks if that is still the case and checks if dfmt.open_partitioned_dataset removes them.
38+
"""
39+
file_nc = dfmt.data.fm_curvedbend_map(return_filepath=True)
40+
file_out = "temp_fillvals_map.nc"
41+
ds_org = xr.open_dataset(file_nc)
42+
ds_org.to_netcdf(file_out)
43+
44+
ds_out_xr = xr.open_dataset(file_out)
45+
ds_out_dfmt = dfmt.open_partitioned_dataset(file_out, chunks="auto")
46+
47+
print("nan fillvalue attrs in dataset written by xugrid/xarray")
48+
ds = ds_out_xr
49+
count_xr = 0
50+
for varn in ds.variables:
51+
if '_FillValue' in ds[varn].encoding:
52+
if np.isnan(ds[varn].encoding['_FillValue']):
53+
print(varn, ds[varn].encoding['_FillValue'])
54+
count_xr += 1
55+
56+
print("nan fillvalue attrs in dataset written by xugrid/xarray, read with dfm_tools")
57+
ds = ds_out_dfmt
58+
count_dfmt = 0
59+
for varn in ds.variables:
60+
if '_FillValue' in ds[varn].encoding:
61+
if np.isnan(ds[varn].encoding['_FillValue']):
62+
print(varn, ds[varn].encoding['_FillValue'])
63+
count_dfmt += 1
64+
65+
assert count_xr == 10
66+
assert count_dfmt == 0
67+
68+
3369
@pytest.mark.unittest
3470
def test_get_uds_isgeographic():
3571
file_nc = dfmt.data.fm_grevelingen_map(return_filepath=True) #zlayer

0 commit comments

Comments
 (0)