-
Notifications
You must be signed in to change notification settings - Fork 6
Issue #1738 add ignore time arguments #1742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
6b3ba45
6de94c0
4ca3036
315d928
7ee12fd
ab16d18
9aceb46
9a573a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,7 @@ | |
| from imod.common.serializer import EngineType | ||
| from imod.common.statusinfo import NestedStatusInfo, StatusInfo, StatusInfoBase | ||
| from imod.common.utilities.clip import clip_box_dataset | ||
| from imod.common.utilities.mask import _mask_all_packages | ||
| from imod.common.utilities.mask import mask_all_packages | ||
| from imod.common.utilities.regrid import _regrid_like | ||
| from imod.common.utilities.schemata import ( | ||
| concatenate_schemata_dicts, | ||
|
|
@@ -697,6 +697,7 @@ def clip_box( | |
| y_min: Optional[float] = None, | ||
| y_max: Optional[float] = None, | ||
| state_for_boundary: Optional[GridDataArray] = None, | ||
| ignore_time_purge_empty: bool = False, | ||
| ): | ||
| """ | ||
| Clip a model by a bounding box (time, layer, y, x). | ||
|
|
@@ -724,6 +725,14 @@ def clip_box( | |
| state_for_boundary : optional, Union[xr.DataArray, xu.UgridDataArray] | ||
| A grids with states that are used to put as boundary values. This | ||
| model will get a :class:`imod.mf6.ConstantHead`. | ||
| ignore_time_purge_empty : bool, default False | ||
| Whether to ignore the time dimension when purging empty packages. | ||
| Can improve performance when clipping models with many time steps. | ||
| Clipping models can cause package data with all nans. These packages | ||
| are considered empty and need to be removed. However, checking all | ||
| timesteps for each package is a costly operation. Therefore, this | ||
| option can be set to True to only check the first timestep. Defaults | ||
| to False. | ||
|
|
||
| Returns | ||
| ------- | ||
|
|
@@ -786,7 +795,7 @@ def clip_box( | |
| if clipped_boundary_condition is not None: | ||
| clipped[pkg_name] = clipped_boundary_condition | ||
|
|
||
| clipped.purge_empty_packages() | ||
| clipped.purge_empty_packages(ignore_time=ignore_time_purge_empty) | ||
|
|
||
| return clipped | ||
|
|
||
|
|
@@ -882,6 +891,7 @@ def regrid_like( | |
| def mask_all_packages( | ||
| self, | ||
| mask: GridDataArray, | ||
| ignore_time_purge_empty: bool = False, | ||
| ): | ||
| """ | ||
| This function applies a mask to all packages in a model. The mask must | ||
|
|
@@ -898,9 +908,12 @@ def mask_all_packages( | |
| mask: xr.DataArray, xu.UgridDataArray of ints | ||
| idomain-like integer array. >0 sets cells to active, 0 sets cells to inactive, | ||
| <0 sets cells to vertical passthrough | ||
| ignore_time_purge_empty: bool, default False | ||
| Whether to ignore time dimension when purging empty packages. Can | ||
| improve performance when masking models with many time steps. | ||
| """ | ||
|
|
||
| _mask_all_packages(self, mask) | ||
| mask_all_packages(self, mask, ignore_time_purge_empty) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I first thought that this method was calling itself but it is actually calling a utilities method. Same applies to mask_all_models
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, that might have been part of the reason the underscore was left there in the first place. I tried the following:
from imod.common import utilities as common_utilities
...
common_utilities.mask.mask_all_packages(...)Pythons runs this without error, but this was not understood by the linters and VSCode couldn't trace the function for some reason.
import imod.common.utilities as utilities
...
def mask_all_packages(mask, ...)
...
mask.mask_all_packages(mask, ...)The function also has
import imod.common.utilities.mask as mask_utils
...
mask_utils.mask_all_packages(...)This too can lead to confusion, as it can lead to developers looking for a module file/folder named
import imod
...
imod.common.utilities.mask.mask_all_packages(...)Too much clutter in my opinion. I think I keep it as is in this PR, downside is that developers have to be sharp for the difference between function and method calls here. It appears changing it back to how it was (as a function starting with an underscore) and using it outside the module is a no no in the python world. |
||
|
|
||
| def purge_empty_packages( | ||
| self, model_name: Optional[str] = "", ignore_time: bool = False | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,13 +9,15 @@ | |
| from imod.tests.fixtures.mf6_modelrun_fixture import assert_simulation_can_run | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("ignore_time", [True, False]) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In all the test it doesnt matter what the flag does
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, we already have a test that do this:
I also tried adding a test to test in I think spending a lot of time on adding more tests in |
||
| def test_mask_simulation( | ||
| tmp_path: Path, | ||
| flow_transport_simulation: imod.mf6.Modflow6Simulation, | ||
| ignore_time: bool, | ||
| ): | ||
| mask = deepcopy(flow_transport_simulation["flow"].domain) | ||
| mask.loc[1, 0.5, 15] = 0 | ||
| flow_transport_simulation.mask_all_models(mask) | ||
| flow_transport_simulation.mask_all_models(mask, ignore_time_purge_empty=ignore_time) | ||
| assert ( | ||
| flow_transport_simulation["flow"].domain.sel({"layer": 1, "y": 0.5, "x": 15}) | ||
| == 0 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this a very confusing name.
I think that we need to keep the user away from the internals of this method. They shouldn't have to know that packages are being purged.
Would
ignore_time_validationwork? Or have them provide a ValidationContext?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Legitimate critique. Unfortunately there are already some methods with this argument as name in the public API, so if I change it here, I have to change it everywhere, and keep on supporting the old argument for the next versions to keep the API stable.
Not the end of the world, but perhaps out of scope for this PR?
I want to refrain from letting users provide ValidationContext themselves, as limiting the amount of custom objects users have to create themselves decreases the learning curve for iMOD Python.