From 831a4cede22bdd5567996f00da6420eaac73a4ca Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Mon, 30 Mar 2026 14:54:41 +0200 Subject: [PATCH 1/6] Make sure GridData.generate_index_array is stable --- imod/msw/grid_data.py | 27 +++++++++++++++++++++++++-- imod/msw/model.py | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/imod/msw/grid_data.py b/imod/msw/grid_data.py index 89d1aacb7..1e92b23db 100644 --- a/imod/msw/grid_data.py +++ b/imod/msw/grid_data.py @@ -1,3 +1,5 @@ +import warnings + import numpy as np import xarray as xr @@ -83,7 +85,7 @@ def __init__( self._pkgcheck() - def generate_index_array(self) -> np.ndarray: + def _generate_index_array(self) -> np.ndarray: """ Generate index array to be used on other packages. @@ -116,7 +118,7 @@ def generate_index_svat_array(self) -> tuple[np.ndarray, xr.DataArray]: The index array is a 1D array with the index of the active cells. The svat grid is a 2D array with the SVAT numbers for each cell. """ - index = self.generate_index_array() + index = self._generate_index_array() area = self.dataset["area"] active = self.dataset["active"] @@ -132,6 +134,27 @@ def generate_index_svat_array(self) -> tuple[np.ndarray, xr.DataArray]: return index, svat + def generate_index_array(self) -> tuple[np.ndarray, xr.DataArray]: + """ + This method is kept for backward compatibility, but will be removed in + future versions and will thus throw a deprecation warning. Use + :meth:`imod.msw.GridData.generate_index_svat_array` instead. + + Generate index array and svat grid to be used on other packages. + + Returns + ------- + tuple[np.ndarray, xr.DataArray] + Index array and svat grid. + The index array is a 1D array with the index of the active cells. + The svat grid is a 2D array with the SVAT numbers for each cell. + """ + warnings.warn( + "Method 'generate_index_array' is deprecated and will be removed in the future, use 'generate_index_svat_array' instead.", + DeprecationWarning, + ) + return self.generate_index_svat_array() + def _pkgcheck(self): super()._pkgcheck() diff --git a/imod/msw/model.py b/imod/msw/model.py index 7bbc4d23f..7140b8802 100644 --- a/imod/msw/model.py +++ b/imod/msw/model.py @@ -566,7 +566,7 @@ def split( for submodel_name, submodel in partitioned_submodels.items(): partition_info = submodel_to_partition[submodel_name] sliced_grid_pkg = clip_by_grid(grid_pkg, partition_info.active_domain) - sliced_index = sliced_grid_pkg.generate_index_array() + sliced_index = sliced_grid_pkg._generate_index_array() # Add package to model if it has data in the active domain. if bool(sliced_index.any()): From 8e69f2158d73fa49f3c973b93447382e64e1e2fe Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Mon, 30 Mar 2026 15:19:26 +0200 Subject: [PATCH 2/6] Refactor to reduce lines of code --- imod/msw/grid_data.py | 45 ++++++++++----------------- imod/msw/model.py | 6 ++-- imod/tests/test_msw/test_grid_data.py | 10 +++--- 3 files changed, 25 insertions(+), 36 deletions(-) diff --git a/imod/msw/grid_data.py b/imod/msw/grid_data.py index 1e92b23db..dd7682ec0 100644 --- a/imod/msw/grid_data.py +++ b/imod/msw/grid_data.py @@ -85,15 +85,14 @@ def __init__( self._pkgcheck() - def _generate_index_array(self) -> np.ndarray: + def _generate_isactive_array(self) -> np.ndarray: """ - Generate index array to be used on other packages. + Generate a 1D array of active cells to be used on other packages. Returns ------- np.ndarray - Index array and svat grid. - The index array is a 1D array with the index of the active cells. + A 1D array with which cells are active. """ area = self.dataset["area"] active = self.dataset["active"] @@ -103,57 +102,47 @@ def _generate_index_array(self) -> np.ndarray: # https://github.com/dask/dask/issues/11753 isactive.load() - index = isactive.values.ravel() + return isactive - return index - - def generate_index_svat_array(self) -> tuple[np.ndarray, xr.DataArray]: + def generate_isactive_svat_arrays(self) -> tuple[np.ndarray, xr.DataArray]: """ Generate index array and svat grid to be used on other packages. Returns ------- tuple[np.ndarray, xr.DataArray] - Index array and svat grid. - The index array is a 1D array with the index of the active cells. + isactive array and svat grid. + The isactive array is a 1D array with which cells are active. The svat grid is a 2D array with the SVAT numbers for each cell. """ - index = self._generate_index_array() - - area = self.dataset["area"] - active = self.dataset["active"] - isactive = area.where(active).notnull() - - svat = xr.full_like(area, fill_value=0, dtype=np.int64).rename("svat") - # Load into memory to avoid dask issue - # https://github.com/dask/dask/issues/11753 - isactive.load() - svat.load() + isactive = self._generate_isactive_array() + isactive_1d = isactive.values.ravel() - svat.data[isactive.data] = np.arange(1, index.sum() + 1) + svat = xr.full_like(isactive, fill_value=0, dtype=np.int64).rename("svat") + svat.data[isactive.data] = np.arange(1, isactive_1d.sum() + 1) - return index, svat + return isactive_1d, svat def generate_index_array(self) -> tuple[np.ndarray, xr.DataArray]: """ This method is kept for backward compatibility, but will be removed in future versions and will thus throw a deprecation warning. Use - :meth:`imod.msw.GridData.generate_index_svat_array` instead. + :meth:`imod.msw.GridData.generate_isactive_svat_arrays` instead. Generate index array and svat grid to be used on other packages. Returns ------- tuple[np.ndarray, xr.DataArray] - Index array and svat grid. - The index array is a 1D array with the index of the active cells. + isactive array and svat grid. + The isactive array is a 1D array with which cells are active. The svat grid is a 2D array with the SVAT numbers for each cell. """ warnings.warn( - "Method 'generate_index_array' is deprecated and will be removed in the future, use 'generate_index_svat_array' instead.", + "Method 'generate_index_array' is deprecated and will be removed in the future, use 'generate_isactive_svat_arrays' instead.", DeprecationWarning, ) - return self.generate_index_svat_array() + return self.generate_isactive_svat_arrays() def _pkgcheck(self): super()._pkgcheck() diff --git a/imod/msw/model.py b/imod/msw/model.py index 7140b8802..7cd70b75f 100644 --- a/imod/msw/model.py +++ b/imod/msw/model.py @@ -360,7 +360,7 @@ def write( # Get index and svat grid_key = self.get_pkgkey(GridData) grid_pkg = cast(GridData, self[grid_key]) - index, svat = grid_pkg.generate_index_svat_array() + index, svat = grid_pkg.generate_isactive_svat_arrays() # write package contents for pkgname in self: @@ -566,10 +566,10 @@ def split( for submodel_name, submodel in partitioned_submodels.items(): partition_info = submodel_to_partition[submodel_name] sliced_grid_pkg = clip_by_grid(grid_pkg, partition_info.active_domain) - sliced_index = sliced_grid_pkg._generate_index_array() + sliced_isactive = sliced_grid_pkg._generate_isactive().values # Add package to model if it has data in the active domain. - if bool(sliced_index.any()): + if bool(sliced_isactive.any()): is_in_active_domain[submodel_name] = True submodel[grid_key] = sliced_grid_pkg else: diff --git a/imod/tests/test_msw/test_grid_data.py b/imod/tests/test_msw/test_grid_data.py index d50490b70..f38559d14 100644 --- a/imod/tests/test_msw/test_grid_data.py +++ b/imod/tests/test_msw/test_grid_data.py @@ -64,7 +64,7 @@ def test_write( xr.full_like(like, True, dtype=bool), ) - index, svat = grid_data.generate_index_svat_array() + index, svat = grid_data.generate_isactive_svat_arrays() with tempfile.TemporaryDirectory() as output_dir: output_dir = Path(output_dir) @@ -293,12 +293,12 @@ def case_grid_data_two_subunits__dask( @parametrize_with_cases("grid_data_dict", cases=".", has_tag="two_subunit") -def test_generate_index_svat_array( +def test_generate_isactive_svat_arrays( grid_data_dict: dict[str, xr.DataArray], coords_two_subunit: dict ): grid_data = GridData(**grid_data_dict) - index, svat = grid_data.generate_index_svat_array() + index, svat = grid_data.generate_isactive_svat_arrays() index_expected = [ False, @@ -346,7 +346,7 @@ def test_generate_index_svat_array( def test_simple_model(fixed_format_parser, grid_data_dict: dict[str, xr.DataArray]): grid_data = GridData(**grid_data_dict) - index, svat = grid_data.generate_index_svat_array() + index, svat = grid_data.generate_isactive_svat_arrays() with tempfile.TemporaryDirectory() as output_dir: output_dir = Path(output_dir) @@ -388,7 +388,7 @@ def test_simple_model_1_subunit( ): grid_data = GridData(**grid_data_dict) - index, svat = grid_data.generate_index_svat_array() + index, svat = grid_data.generate_isactive_svat_arrays() with tempfile.TemporaryDirectory() as output_dir: output_dir = Path(output_dir) From cbb32a064850f6ef9b7a4f5621c5e561c5deac7b Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Mon, 30 Mar 2026 15:19:54 +0200 Subject: [PATCH 3/6] Update changelog and add generate_isactive_svat_arrays to public API --- docs/api/changelog.rst | 2 ++ docs/api/msw.rst | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/api/changelog.rst b/docs/api/changelog.rst index 1e06933d3..9942338e7 100644 --- a/docs/api/changelog.rst +++ b/docs/api/changelog.rst @@ -64,6 +64,8 @@ Changed :class:`imod.mf6.Evapotranspiration` are now optional variables. If provided, now require ``"segment"`` dimension when ``proportion_depth`` and ``proportion_rate``. +- :meth:`imod.msw.GridData.generate_index_array` is now deprecated, use + :meth:`imod.msw.GridData.generate_isactive_svat_arrays` instead. [1.0.0] - 2025-11-11 diff --git a/docs/api/msw.rst b/docs/api/msw.rst index 2a6d177ec..c42fe5ab9 100644 --- a/docs/api/msw.rst +++ b/docs/api/msw.rst @@ -28,6 +28,7 @@ Grid packages GridData.from_imod5_data GridData.get_regrid_methods GridData.generate_index_array + GridData.generate_isactive_svat_arrays GridData.write Infiltration Infiltration.regrid_like From 286e23ca79ee86d84dd1b212c2b4da1877c6f892 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Mon, 30 Mar 2026 16:48:40 +0200 Subject: [PATCH 4/6] fix type annotation --- imod/msw/grid_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imod/msw/grid_data.py b/imod/msw/grid_data.py index dd7682ec0..24fbece43 100644 --- a/imod/msw/grid_data.py +++ b/imod/msw/grid_data.py @@ -85,7 +85,7 @@ def __init__( self._pkgcheck() - def _generate_isactive_array(self) -> np.ndarray: + def _generate_isactive_array(self) -> xr.DataArray: """ Generate a 1D array of active cells to be used on other packages. @@ -128,7 +128,7 @@ def generate_index_array(self) -> tuple[np.ndarray, xr.DataArray]: This method is kept for backward compatibility, but will be removed in future versions and will thus throw a deprecation warning. Use :meth:`imod.msw.GridData.generate_isactive_svat_arrays` instead. - + Generate index array and svat grid to be used on other packages. Returns From f934877b08f0ae7262b51c0d2836684d7ab7526e Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Tue, 31 Mar 2026 08:00:06 +0200 Subject: [PATCH 5/6] fix broken call --- imod/msw/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imod/msw/model.py b/imod/msw/model.py index 7cd70b75f..892f0cbe5 100644 --- a/imod/msw/model.py +++ b/imod/msw/model.py @@ -566,7 +566,7 @@ def split( for submodel_name, submodel in partitioned_submodels.items(): partition_info = submodel_to_partition[submodel_name] sliced_grid_pkg = clip_by_grid(grid_pkg, partition_info.active_domain) - sliced_isactive = sliced_grid_pkg._generate_isactive().values + sliced_isactive = sliced_grid_pkg._generate_isactive_array().values # Add package to model if it has data in the active domain. if bool(sliced_isactive.any()): From 5ff14ade56d0c4ab812c1350c87e8c55a748e623 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Tue, 31 Mar 2026 08:04:21 +0200 Subject: [PATCH 6/6] Enforce type annotation on sliced grid data, so that methods can be checked. --- imod/msw/model.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imod/msw/model.py b/imod/msw/model.py index 892f0cbe5..ce40d6b8d 100644 --- a/imod/msw/model.py +++ b/imod/msw/model.py @@ -565,7 +565,9 @@ def split( for submodel_name, submodel in partitioned_submodels.items(): partition_info = submodel_to_partition[submodel_name] - sliced_grid_pkg = clip_by_grid(grid_pkg, partition_info.active_domain) + sliced_grid_pkg = cast( + GridData, clip_by_grid(grid_pkg, partition_info.active_domain) + ) sliced_isactive = sliced_grid_pkg._generate_isactive_array().values # Add package to model if it has data in the active domain.