-
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
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. |
tests/test_interpolation.py
Outdated
@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
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.
And yes, we absolutely also need 3D tests. Perhaps again comparing to JIT mode?
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
bff8ca2
to
14b93c9
Compare
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
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
?
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.
Agreed - I have pushed these changes. I haven't made any changes to VectorField, I will make those in another PR
Not needed anymore since show_time isn't in the codebase anymore #1816 (comment)
tests/test_interpolation.py
Outdated
# pytest.param(interpolation._linear_2d, ...), | ||
# pytest.param(interpolation._linear_invdist_land_tracer_2d, ...), |
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 think it's crucial that we test all interpolation methods with these simple unit tests. But I must say I don't really understand how this test-function is now set up. Why a class?
And indeed, I would not test just one point, but a few edge cases too.
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 think it's crucial that we test all interpolation methods with these simple unit tests
Agreed
But I must say I don't really understand how this test-function is now set up. Why a class?
Admittedly classes aren't used much in Pytest beyond a way of grouping together tests (even then - not used often). I thought it would be a straight-forward way to group the tests that are testing on ti,zi,yi,xi = 0,1,1,1 on the data_2d and data_3d datasets.
And indeed, I would not test just one point, but a few edge cases too.
Agreed - those can be functions outside of this class. Also testing of the land interp method
tests/test_interpolation.py
Outdated
@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.
And yes, we absolutely also need 3D tests. Perhaps again comparing to JIT mode?
f4c6d83
to
973b293
Compare
Not needed anymore since show_time isn't in the codebase anymore #1816 (comment)
Note that "cgrid_velocity" at the moment breaks; so there may be an issue there with the new scipy interpolation?
fb5a593
to
46a2853
Compare
Cleaned up now. We can either merge this first, or #1834. Whichever one comes first, I'll rebase the other |
I encountered this
Perhaps due to #1834 due to it being in the depth dimension (though could not recreate locally) |
Hmm, it's a 1e-6 error; it could also be because of accumulating round-off errors. I found the 1e-8 extremely tight already, but since it worked locally on my computer too I didn't change it. I think 1e-6 is still totally acceptable, so I'll see if that fixes the breaking assert |
Co-authored-by: Erik van Sebille <[email protected]> Co-authored-by: Vecko <[email protected]>
bb275c3
to
cc87fcd
Compare
Pushed a small change to the Patch unit test commit (now cc87fcd). Otherwise I think this is good to go? |
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