Skip to content

Commit f8046a9

Browse files
authored
Improve export to ugrid_nc-file, to support imod qgis plugin (#329)
* Improve export to ugrid_nc-file, to support imod qgis plugin * Improve docstring
1 parent 007d4c9 commit f8046a9

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

nlmod/gis.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .dims.grid import polygons_from_model_ds
88
from .dims.resample import get_affine_mod_to_world
9+
from .dims.layers import calculate_thickness
910

1011
logger = logging.getLogger(__name__)
1112

@@ -308,6 +309,9 @@ def ds_to_ugrid_nc_file(
308309
xv="xv",
309310
yv="yv",
310311
face_node_connectivity="icvert",
312+
split_layer_dimension=True,
313+
split_time_dimension=False,
314+
for_imod_qgis_plugin=False,
311315
):
312316
"""Save a model dataset to a UGRID NetCDF file, so it can be opened as a Mesh Layer
313317
in qgis.
@@ -335,13 +339,24 @@ def ds_to_ugrid_nc_file(
335339
face_node_connectivity : str, optional
336340
The name of the variable that contains the indexes of the vertices for
337341
each face. The default is 'icvert'.
342+
split_layer_dimension : bool, optional
343+
Splits the layer dimension into seperate variables when True. The defaults is
344+
True.
345+
split_time_dimension : bool, optional
346+
Splits the time dimension into seperate variables when True. The defaults is
347+
False.
348+
for_imod_qgis_plugin : bool, optional
349+
When True, set some properties of the netcdf file to improve compatibility with
350+
the iMOD-QGIS plugin. Layers are renamed to 'layer_i' until 'layer_n', a
351+
variable 'top' is added for each layer, and the variable 'botm' is renamed to
352+
'bottom'. The default is False.
338353
339354
Returns
340355
-------
341356
ds : xr.DataSet
342357
The dataset that was saved to a NetCDF-file. Can be used for debugging.
343358
"""
344-
assert model_ds.gridtype == "vertex", "Only vertex grids are supported"
359+
assert model_ds.gridtype == "vertex", "Only vertex grids are supported for now"
345360

346361
# copy the dataset, so we do not alter the original one
347362
ds = model_ds.copy()
@@ -377,6 +392,10 @@ def ds_to_ugrid_nc_file(
377392
ds[face_node_connectivity].attrs["cf_role"] = "face_node_connectivity"
378393
ds[face_node_connectivity].attrs["start_index"] = 0
379394

395+
if for_imod_qgis_plugin and "botm" in ds:
396+
ds["top"] = ds["botm"] + calculate_thickness(ds)
397+
ds = ds.rename({"botm": "bottom"})
398+
380399
# set for each of the variables that they describe the faces
381400
if variables is None:
382401
variables = list(ds.keys())
@@ -405,9 +424,16 @@ def ds_to_ugrid_nc_file(
405424
ds[var].encoding["dtype"] = np.int32
406425

407426
# Breaks down variables with a layer dimension into separate variables.
408-
ds, variables = _break_down_dimension(ds, variables, "layer")
409-
# Breaks down variables with a time dimension into separate variables.
410-
ds, variables = _break_down_dimension(ds, variables, "time")
427+
if split_layer_dimension:
428+
if for_imod_qgis_plugin:
429+
ds, variables = _break_down_dimension(
430+
ds, variables, "layer", add_dim_name=True, add_one_based_index=True
431+
)
432+
else:
433+
ds, variables = _break_down_dimension(ds, variables, "layer")
434+
if split_time_dimension:
435+
# Breaks down variables with a time dimension into separate variables.
436+
ds, variables = _break_down_dimension(ds, variables, "time")
411437

412438
# only keep the selected variables
413439
ds = ds[variables + [dummy_var, xv, yv, face_node_connectivity]]
@@ -417,14 +443,27 @@ def ds_to_ugrid_nc_file(
417443
return ds
418444

419445

420-
def _break_down_dimension(ds, variables, dim):
421-
# Copied and altered from imod-python.
446+
def _break_down_dimension(
447+
ds, variables, dim, add_dim_name=False, add_one_based_index=False
448+
):
449+
"""Internal method to split a dimension of a variable into multiple variables.
450+
451+
Copied and altered from imod-python.
452+
"""
453+
422454
keep_vars = []
423455
for var in variables:
424456
if dim in ds[var].dims:
425457
stacked = ds[var]
426-
for value in stacked[dim].values:
427-
name = f"{var}_{value}"
458+
for i, value in enumerate(stacked[dim].values):
459+
name = var
460+
if add_dim_name:
461+
name = f"{name}_{dim}"
462+
if add_one_based_index:
463+
name = f"{name}_{i+1}"
464+
else:
465+
name = f"{name}_{value}"
466+
428467
ds[name] = stacked.sel({dim: value}, drop=True)
429468
if "long_name" in ds[name].attrs:
430469
long_name = ds[name].attrs["long_name"]

tests/test_014_gis.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ def test_vertex_da_to_gdf():
1717

1818
def test_ds_to_ugrid_nc_file():
1919
ds = util.get_ds_vertex()
20-
nlmod.gis.ds_to_ugrid_nc_file(ds, os.path.join("data", "ugrid_test.nc"))
20+
fname = os.path.join("data", "ugrid_test.nc")
21+
nlmod.gis.ds_to_ugrid_nc_file(ds, fname)
22+
23+
fname = os.path.join("data", "ugrid_test_qgis.nc")
24+
nlmod.gis.ds_to_ugrid_nc_file(ds, fname, for_imod_qgis_plugin=True)

0 commit comments

Comments
 (0)