From dfa31d9631e59d21e63bfa56e487c6513ca2d5d0 Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 08:31:05 +0100 Subject: [PATCH 1/7] Start working on ponding imod5 classmethod --- imod/msw/ponding.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/imod/msw/ponding.py b/imod/msw/ponding.py index afc1629af..b7d15c8d5 100644 --- a/imod/msw/ponding.py +++ b/imod/msw/ponding.py @@ -70,3 +70,13 @@ def _render(self, file: TextIO, index: IntArray, svat: xr.DataArray, *args: Any) self._check_range(dataframe) return self.write_dataframe_fixed_width(file, dataframe) + + @classmethod + def from_imod5_data(cls, imod5_data): + cap_data = imod5_data["cap"] + data = {} + data["runoff_resistance"] = xr.concat([cap_data["rural_runoff_resistance"], cap_data["urban_runoff_resistance"]], dims="subunit").assign_coords(subunit=[0, 1]) + data["runon_resistance"] = xr.concat([cap_data["rural_runon_resistance"], cap_data["urbon_runon_resistance"]], dims="subunit").assign_coords(subunit=[0, 1]) + data["ponding_depth"] = xr.concat([cap_data["rural_ponding_depth"], cap_data["urban_ponding_depth"]], dims="subunit").assign_coords(subunit=[0, 1]) + + return cls(**data) From 8a5138f2a99ad7fbe625968a2195f5fba3306565 Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:19:56 +0100 Subject: [PATCH 2/7] Generalize concatenation --- imod/msw/ponding.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imod/msw/ponding.py b/imod/msw/ponding.py index b7d15c8d5..3741f11b4 100644 --- a/imod/msw/ponding.py +++ b/imod/msw/ponding.py @@ -8,6 +8,7 @@ from imod.msw.pkgbase import DataDictType, MetaSwapPackage from imod.msw.regrid.regrid_schemes import PondingRegridMethod from imod.typing import IntArray +from imod.typing.grid import concat class Ponding(MetaSwapPackage, IRegridPackage): @@ -73,10 +74,13 @@ def _render(self, file: TextIO, index: IntArray, svat: xr.DataArray, *args: Any) @classmethod def from_imod5_data(cls, imod5_data): + """ + Concatenate ponding depths along subunits + """ cap_data = imod5_data["cap"] data = {} - data["runoff_resistance"] = xr.concat([cap_data["rural_runoff_resistance"], cap_data["urban_runoff_resistance"]], dims="subunit").assign_coords(subunit=[0, 1]) - data["runon_resistance"] = xr.concat([cap_data["rural_runon_resistance"], cap_data["urbon_runon_resistance"]], dims="subunit").assign_coords(subunit=[0, 1]) - data["ponding_depth"] = xr.concat([cap_data["rural_ponding_depth"], cap_data["urban_ponding_depth"]], dims="subunit").assign_coords(subunit=[0, 1]) + for key in cls._with_subunit: + data_ls = [cap_data[f"{landuse}_{key}"] for landuse in ["rural", "urban"]] + data[key] = concat(data_ls, dim="subunit").assign_coords(subunit=[0, 1]) return cls(**data) From e977f33ff94e4719e6324dd81e7957c3b2e12d0c Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:21:13 +0100 Subject: [PATCH 3/7] Add from_imod5_data test --- imod/tests/test_msw/test_ponding.py | 51 ++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/imod/tests/test_msw/test_ponding.py b/imod/tests/test_msw/test_ponding.py index 626cd6412..060b7e19f 100644 --- a/imod/tests/test_msw/test_ponding.py +++ b/imod/tests/test_msw/test_ponding.py @@ -14,7 +14,7 @@ def setup_ponding(): x = [1.0, 2.0, 3.0] - y = [1.0, 2.0, 3.0] + y = [3.0, 2.0, 1.0] subunit = [0, 1] dx = 1.0 dy = 1.0 @@ -69,16 +69,17 @@ def setup_ponding(): # fmt: on index = (svat != 0).values.ravel() - ponding = Ponding( - ponding_depth=ponding_depth, - runoff_resistance=runoff_resistance, - runon_resistance=runoff_resistance, - ) - return ponding, index, svat + data_ponding = { + "ponding_depth": ponding_depth, + "runoff_resistance": runoff_resistance, + "runon_resistance": runoff_resistance, + } + return data_ponding, index, svat def test_simple_model(fixed_format_parser): - ponding, index, svat = setup_ponding() + data_ponding, index, svat = setup_ponding() + ponding = Ponding(**data_ponding) with tempfile.TemporaryDirectory() as output_dir: output_dir = Path(output_dir) ponding.write(output_dir, index, svat, None, None) @@ -95,7 +96,8 @@ def test_simple_model(fixed_format_parser): def test_regrid_ponding(simple_2d_grid_with_subunits): - ponding, _, _ = setup_ponding() + data_ponding, _, _ = setup_ponding() + ponding = Ponding(**data_ponding) new_grid = simple_2d_grid_with_subunits regrid_context = RegridderWeightsCache() @@ -104,3 +106,34 @@ def test_regrid_ponding(simple_2d_grid_with_subunits): assert np.all(regridded_ponding.dataset["x"].values == new_grid["x"].values) assert np.all(regridded_ponding.dataset["y"].values == new_grid["y"].values) + + +def test_from_imod5_data(): + data_ponding, _, _ = setup_ponding() + expected_ponding = Ponding(**data_ponding) + + cap_data = {} + cap_data["rural_runoff_resistance"] = data_ponding["runoff_resistance"].sel( + subunit=0, drop=True + ) + cap_data["urban_runoff_resistance"] = data_ponding["runoff_resistance"].sel( + subunit=1, drop=True + ) + cap_data["rural_runon_resistance"] = data_ponding["runon_resistance"].sel( + subunit=0, drop=True + ) + cap_data["urban_runon_resistance"] = data_ponding["runon_resistance"].sel( + subunit=1, drop=True + ) + cap_data["rural_ponding_depth"] = data_ponding["ponding_depth"].sel( + subunit=0, drop=True + ) + cap_data["urban_ponding_depth"] = data_ponding["ponding_depth"].sel( + subunit=1, drop=True + ) + + imod5_data = {"cap": cap_data} + + actual_ponding = Ponding.from_imod5_data(imod5_data) + + xr.testing.assert_equal(expected_ponding.dataset, actual_ponding.dataset) From cc911660dad66401f29493724f2d73af246d7142 Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:31:49 +0100 Subject: [PATCH 4/7] Declutter test --- imod/tests/test_msw/test_ponding.py | 30 ++++++++++++----------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/imod/tests/test_msw/test_ponding.py b/imod/tests/test_msw/test_ponding.py index 060b7e19f..e6279036b 100644 --- a/imod/tests/test_msw/test_ponding.py +++ b/imod/tests/test_msw/test_ponding.py @@ -112,25 +112,19 @@ def test_from_imod5_data(): data_ponding, _, _ = setup_ponding() expected_ponding = Ponding(**data_ponding) + # Create cap data cap_data = {} - cap_data["rural_runoff_resistance"] = data_ponding["runoff_resistance"].sel( - subunit=0, drop=True - ) - cap_data["urban_runoff_resistance"] = data_ponding["runoff_resistance"].sel( - subunit=1, drop=True - ) - cap_data["rural_runon_resistance"] = data_ponding["runon_resistance"].sel( - subunit=0, drop=True - ) - cap_data["urban_runon_resistance"] = data_ponding["runon_resistance"].sel( - subunit=1, drop=True - ) - cap_data["rural_ponding_depth"] = data_ponding["ponding_depth"].sel( - subunit=0, drop=True - ) - cap_data["urban_ponding_depth"] = data_ponding["ponding_depth"].sel( - subunit=1, drop=True - ) + mapping_ls = [ + ("rural_runoff_resistance", "runoff_resistance", 0), + ("rural_runoff_resistance", "runoff_resistance", 0), + ("urban_runoff_resistance", "runoff_resistance", 1), + ("rural_runon_resistance", "runon_resistance", 0), + ("urban_runon_resistance", "runon_resistance", 1), + ("rural_ponding_depth", "ponding_depth", 0), + ("urban_ponding_depth", "ponding_depth", 1), + ] + for cap_key, pkg_key, subunit_nr in mapping_ls: + cap_data[cap_key] = data_ponding[pkg_key].sel(subunit=subunit_nr, drop=True) imod5_data = {"cap": cap_data} From b94ea1e3172a4e7b18f1b404f9cd754630caadaf Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:38:41 +0100 Subject: [PATCH 5/7] Create separate utility namespace and put concat_imod5 in there --- imod/msw/grid_data.py | 13 +++++-------- imod/msw/ponding.py | 4 ++-- imod/msw/utilities/common.py | 6 ++++++ 3 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 imod/msw/utilities/common.py diff --git a/imod/msw/grid_data.py b/imod/msw/grid_data.py index 27c08829c..3e08a69b0 100644 --- a/imod/msw/grid_data.py +++ b/imod/msw/grid_data.py @@ -13,15 +13,12 @@ from imod.msw.fixed_format import VariableMetaData from imod.msw.pkgbase import MetaSwapPackage from imod.msw.regrid.regrid_schemes import GridDataRegridMethod +from imod.msw.utilities.common import concat_imod5 from imod.typing import GridDataArray, GridDataDict -from imod.typing.grid import concat, ones_like +from imod.typing.grid import ones_like from imod.util.spatial import get_cell_area, spatial_reference -def _concat_subunits(arg1: GridDataArray, arg2: GridDataArray): - return concat([arg1, arg2], dim="subunit").assign_coords(subunit=[0, 1]) - - def get_cell_area_from_imod5_data( imod5_cap: GridDataDict, ) -> GridDataArray: @@ -45,7 +42,7 @@ def get_cell_area_from_imod5_data( ) urban_area = urban_area.where(rural_area > 0.0, other=0.0) rural_area = mf6_area - (wetted_area + urban_area) - return _concat_subunits(rural_area, urban_area) + return concat_imod5(rural_area, urban_area) def get_landuse_from_imod5_data( @@ -59,7 +56,7 @@ def get_landuse_from_imod5_data( rural_landuse = imod5_cap["landuse"] # Urban landuse = 18 urban_landuse = ones_like(rural_landuse) * 18 - return _concat_subunits(rural_landuse, urban_landuse) + return concat_imod5(rural_landuse, urban_landuse) def get_rootzone_depth_from_imod5_data( @@ -72,7 +69,7 @@ def get_rootzone_depth_from_imod5_data( """ rootzone_thickness = imod5_cap["rootzone_thickness"] * 0.01 # rootzone depth is equal for both svats. - return _concat_subunits(rootzone_thickness, rootzone_thickness) + return concat_imod5(rootzone_thickness, rootzone_thickness) class GridData(MetaSwapPackage, IRegridPackage): diff --git a/imod/msw/ponding.py b/imod/msw/ponding.py index 3741f11b4..7732c46e8 100644 --- a/imod/msw/ponding.py +++ b/imod/msw/ponding.py @@ -7,8 +7,8 @@ from imod.msw.fixed_format import VariableMetaData from imod.msw.pkgbase import DataDictType, MetaSwapPackage from imod.msw.regrid.regrid_schemes import PondingRegridMethod +from imod.msw.utilities.common import concat_imod5 from imod.typing import IntArray -from imod.typing.grid import concat class Ponding(MetaSwapPackage, IRegridPackage): @@ -81,6 +81,6 @@ def from_imod5_data(cls, imod5_data): data = {} for key in cls._with_subunit: data_ls = [cap_data[f"{landuse}_{key}"] for landuse in ["rural", "urban"]] - data[key] = concat(data_ls, dim="subunit").assign_coords(subunit=[0, 1]) + data[key] = concat_imod5(*data_ls) return cls(**data) diff --git a/imod/msw/utilities/common.py b/imod/msw/utilities/common.py new file mode 100644 index 000000000..53faf9e07 --- /dev/null +++ b/imod/msw/utilities/common.py @@ -0,0 +1,6 @@ +from imod.typing import GridDataArray +from imod.typing.grid import concat + + +def concat_imod5(arg1: GridDataArray, arg2: GridDataArray): + return concat([arg1, arg2], dim="subunit").assign_coords(subunit=[0, 1]) From af270c2d7e83f1be2c68eaf13d443dee9707d5e5 Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:40:58 +0100 Subject: [PATCH 6/7] Type annotate --- imod/msw/ponding.py | 4 ++-- imod/msw/utilities/common.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imod/msw/ponding.py b/imod/msw/ponding.py index 7732c46e8..89ab6af44 100644 --- a/imod/msw/ponding.py +++ b/imod/msw/ponding.py @@ -8,7 +8,7 @@ from imod.msw.pkgbase import DataDictType, MetaSwapPackage from imod.msw.regrid.regrid_schemes import PondingRegridMethod from imod.msw.utilities.common import concat_imod5 -from imod.typing import IntArray +from imod.typing import GridDataDict, IntArray class Ponding(MetaSwapPackage, IRegridPackage): @@ -73,7 +73,7 @@ def _render(self, file: TextIO, index: IntArray, svat: xr.DataArray, *args: Any) return self.write_dataframe_fixed_width(file, dataframe) @classmethod - def from_imod5_data(cls, imod5_data): + def from_imod5_data(cls, imod5_data: dict[str, GridDataDict]) -> "Ponding": """ Concatenate ponding depths along subunits """ diff --git a/imod/msw/utilities/common.py b/imod/msw/utilities/common.py index 53faf9e07..836902662 100644 --- a/imod/msw/utilities/common.py +++ b/imod/msw/utilities/common.py @@ -2,5 +2,5 @@ from imod.typing.grid import concat -def concat_imod5(arg1: GridDataArray, arg2: GridDataArray): +def concat_imod5(arg1: GridDataArray, arg2: GridDataArray) -> GridDataArray: return concat([arg1, arg2], dim="subunit").assign_coords(subunit=[0, 1]) From 0d88a33916d35a197afaf4b53740a575a63d797c Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Thu, 14 Nov 2024 17:44:55 +0100 Subject: [PATCH 7/7] Type annotate --- imod/tests/test_msw/test_ponding.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imod/tests/test_msw/test_ponding.py b/imod/tests/test_msw/test_ponding.py index e6279036b..e7bb47e06 100644 --- a/imod/tests/test_msw/test_ponding.py +++ b/imod/tests/test_msw/test_ponding.py @@ -10,9 +10,10 @@ RegridderWeightsCache, ) from imod.msw import Ponding +from imod.typing import GridDataArray, GridDataDict -def setup_ponding(): +def setup_ponding() -> tuple[GridDataDict, np.ndarray, GridDataArray]: x = [1.0, 2.0, 3.0] y = [3.0, 2.0, 1.0] subunit = [0, 1]