-
Notifications
You must be signed in to change notification settings - Fork 142
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
Refactoring field interpolation and allow custom interpolation methods in Scipy mode #1816
base: main
Are you sure you want to change the base?
Conversation
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.
Thoughts on the below @erikvansebille ? Let me know if you want me to break this into separate PRs
Note for review: de89311 includes testing that shows the refactor of the 3d interpolation is 100% equivalent to the previous version for all combinations of interp method, grid types, and cell locations. |
I'm quite aware that this is getting to be a big PR. To be expected for such a big refactor, but I think it would be good to continue in other PRs (for vector interp and indexing) to keep this reviewable. |
@pytest.mark.parametrize( | ||
"func, eta, xsi, expected", | ||
[ | ||
pytest.param(interpolation._nearest_2d, 0.49, 0.49, 3.0, id="nearest_2d-1"), | ||
pytest.param(interpolation._nearest_2d, 0.49, 0.51, 4.0, id="nearest_2d-2"), | ||
pytest.param(interpolation._nearest_2d, 0.51, 0.49, 5.0, id="nearest_2d-3"), | ||
pytest.param(interpolation._nearest_2d, 0.51, 0.51, 6.0, id="nearest_2d-4"), | ||
pytest.param(interpolation._tracer_2d, None, None, 6.0, id="tracer_2d"), | ||
# pytest.param(interpolation._linear_2d, ...), | ||
# pytest.param(interpolation._linear_invdist_land_tracer_2d, ...), | ||
], | ||
) | ||
def test_2d(self, data_2d, func, eta, xsi, expected): | ||
ctx = interpolation.InterpolationContext2D(data_2d, eta, xsi, self.ti, self.yi, self.xi) | ||
assert func(ctx) == expected | ||
|
||
@pytest.mark.parametrize( | ||
"func, eta, xsi, expected", | ||
[ | ||
# pytest.param(interpolation._nearest_3d, ...), | ||
# pytest.param(interpolation._cgrid_velocity_3d, ...), | ||
# pytest.param(interpolation._linear_invdist_land_tracer_3d, ...), | ||
# pytest.param(interpolation._linear_3d, ...), | ||
# pytest.param(interpolation._tracer_3d, ...), | ||
], | ||
) |
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.
Thoughts on test cases @erikvansebille ? I think it might be good to add some on the raw arrays
8abec45
to
b38a17c
Compare
I added an extra commit in the history that shows 100% equivalence of the refactor. See updated #1816 (comment) |
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.
First bit of reviews (of the three main new files). Rest to come after the weekend
+ xsi * eta * grid.depth[:, yi + 1, xi + 1] | ||
+ (1 - xsi) * eta * grid.depth[:, yi + 1, xi] | ||
) | ||
z = np.float32(z) # type: ignore # TODO: remove type ignore once we migrate to float64 |
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'm surprised by this statement here. I know it doesn't come from this PR, but why only cast to float32 in the s-case (and not the z-case)? In general, z
can be either float32 or float64, depending on the lonlatdepth_dtype
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.
No idea :/
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.
OK, then I propose we remove it
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.
Then I propose we remove it
z = np.float32(z) # type: ignore # TODO: remove type ignore once we migrate to float64 |
…erpolation method
Try block should only have retrieving the function, not its execution
To help with refactoring
for more information, see https://pre-commit.ci
For some reason there is test pollution between the following 2 tests: tests/test_interpolation.py::test_interpolation_registry tests/test_interpolation.py::test_full_depth_provided_to_interpolators
Full context in Python Discord https://discord.com/channels/267624335836053506/1329136004459794483
To ensure refactoring is accurate
bff8ca2
to
14b93c9
Compare
|
||
@dataclass | ||
class InterpolationContext2D: | ||
"""Information provided by Parcels during 2D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. |
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.
"""Information provided by Parcels during 2D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. | |
"""Information provided by Parcels during 2D spatial interpolation. See Delandmeter and Van Sebille (2019), 10.5194/gmd-12-3571-2019 for more info. |
"""Information provided by Parcels during 2D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. | |
"""Information provided by Parcels during 2D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. |
|
||
@dataclass | ||
class InterpolationContext3D: | ||
"""Information provided by Parcels during 3D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. |
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.
"""Information provided by Parcels during 3D spatial interpolation. See Delandmeter, P. and van Sebille, E (2019) for more info. | |
"""Information provided by Parcels during 3D spatial interpolation. See Delandmeter and Van Sebille (2019), 10.5194/gmd-12-3571-2019 for more info. |
+ xsi * eta * grid.depth[:, yi + 1, xi + 1] | ||
+ (1 - xsi) * eta * grid.depth[:, yi + 1, xi] | ||
) | ||
z = np.float32(z) # type: ignore # TODO: remove type ignore once we migrate to float64 |
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.
OK, then I propose we remove it
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.
More comments, now on all files except for the tests/* files
+ xsi * eta * grid.depth[:, yi + 1, xi + 1] | ||
+ (1 - xsi) * eta * grid.depth[:, yi + 1, xi] | ||
) | ||
z = np.float32(z) # type: ignore # TODO: remove type ignore once we migrate to float64 |
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.
Then I propose we remove it
z = np.float32(z) # type: ignore # TODO: remove type ignore once we migrate to float64 |
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.
Should we not also move the _search_indices()
, _search_indices_curvilinear()
and _search_indices_rectilinear()
methods to the _index_search.py
file? Why are they still in field.py
?
In general, I see that even in this PR, field.py
still contains a lot of methods/functions that don't specifically need to be here. That would really clean up the field.py file?
E.g. VectorField.dist
, VectorField._is_land2D()
and VectorField.jacobian
can go to an interpolation_utils.py
file (mimicking what is in include
folder for C)?
And the spatial interpolation for VectorFields can also go to _interpolation.py
?
if msg == "show_time": | ||
message += " Try explicitly providing a 'show_time'." |
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.
We don't have show_time anymore (was part of the old plotting we got rid off years ago, so this is not needed
if msg == "show_time": | |
message += " Try explicitly providing a 'show_time'." |
This PR refactors many of the indexing methods and interpolation methods out of
field.py
, and moves indexing code to a separate file to make things more manageable and reduce the coupling with the Field class.This PR also allows users to easily overwrite the behaviour of existing interpolation methods or (untested) define new interpolation methods in Scipy mode. This can be done via the
register_2d_interpolator(...)
andregister_3d_interpolator(...)
decorators. This behaviour is in beta and is subject to change.This also makes the interpolation functions more easily testable by providing only the required data.
Fixes #1823