66
77from .dims .grid import polygons_from_model_ds
88from .dims .resample import get_affine_mod_to_world
9+ from .dims .layers import calculate_thickness
910
1011logger = 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" ]
0 commit comments