Repository navigation
Extend method="multilinear" to grids of any number of dimensions and to scattered points - #73
Merged
Merged
Conversation
Work in progress: the locators and the cell math, with their tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
Recognize a rectilinear grid from the strides of its coordinates before comparing their values, return NaN where the continuation of a curvilinear grid cannot reach a point, and add a benchmark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #73 +/- ##
==========================================
+ Coverage 99.72% 99.82% +0.09%
==========================================
Files 65 72 +7
Lines 4346 5612 +1266
==========================================
+ Hits 4334 5602 +1268
+ Misses 12 10 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Newton's method has converged once the distance from the position to the point is down to its rounding error, as well as once a step is short. In a thin cell at an angle to the axes, rounding along its length kept the step across its width above the tolerance, and points well inside the cell were reported outside it. One routine now serves both the search within a cell and the extrapolating walk across the grid, which had copied it. - Without `axis_output`, the points must have as many axes as the grid again, so that a forgotten `axis_output` raises rather than taking the orthogonal axes for points. Points arranged in other numbers of axes pass `axis_output` explicitly. - Every orthogonal element is searched in one call: rectilinear grids together, even if each element has its own, and the points of every element at once on a curvilinear grid they share. A spectrum for each of many pixels had become several times slower than on `main`. - A rectilinear grid is compared in floating point, since the difference of two unsigned integers wraps around instead of going negative, which took a descending grid for an ascending one. - `regrid_from_weights()` gives the number of elements when it flattens them, which it cannot infer when there are no points, and its docstring says what `axis_output` may be. - The tests have thin cells, an oracle for three dimensions which shares nothing with the code under test, and the boundary of the grid under `bounds="raise"`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
Without `axis_output`, a scattered set of points now trips this error, so it reads better without NumPy's integer types in it. Also give scipy its options as a literal, which is what its type annotations ask for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
`regrid_from_weights()` handed the kernel an empty typed list, which has no type to compile it for, when an orthogonal axis had a length of zero. With no elements the output is already all zeros, so the kernel is skipped. Newton's method halves a step which does not bring the position closer, as crossing from a narrow cell into a wide one does, and a test now does that. The exits which the test of the rounding error of the position now reaches first are marked as such. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
method="multilinear"used to work only along one axis. It now interpolates on logically-rectangular grids of any number of dimensions, rectilinear or curvilinear, at output points arranged along any number of axes. This is the first step toward evaluating a sampledna.FunctionArray(such as a map of a mirror's surface error) at scattered points.What changes
axis_outputmay have any number of axes. A 2D grid can be interpolated at one axis of scattered points (axis_output=0), or at a single point (axis_output=()). Withoutaxis_output, the points must still have as many axes as the grid, so a forgottenaxis_outputraises instead of turning the orthogonal axes into points. The conservative method still requires the two to match.named-arrayspasses them, is recognized without reading its values. Axes which run backwards work, including unsigned integer ones. A 1D grid which ran backwards used to give wrong answers silently.bounds. On a rectilinear grid,"extrapolate"behaves as before, along each axis. On a curvilinear grid, the same Newton routine runs across the whole grid in index space, with the edge cells continued beyond it, starting from the cell whose box is nearest. On a grid of parallelograms that is the same as clamping each index. A point the continuation can't reach (beyond a strongly curved edge) gets NaN, as does a point with a non-finite coordinate.regrid_from_weightsflattens the resampled axes of each element, giving the number of elements explicitly. That lets through outputs with no resampled axes (a single point), no points, or no elements. The CUDA apply path is untouched; multilinear weights are still built on the host only.Why not
index_of_point_secantThe conservative sweep already has a 2D Newton locator, so I tested it against
index_of_point_brutefirst (300 random interior points each):The causes:
1e-10in coordinate units;The first two faults also reached
weights(..., method="conservative")through the sweep's row seeds; #74 fixes that separately. Here the boxes do the global search and Newton's method only runs inside one cell, where it is well behaved. Its tests are in local coordinates, and positions are measured from the cell's first corner. That means a grid's scale, and its distance from the origin, don't matter.Tests
scipy.interpolate.RegularGridInterpolator, with and without extrapolation. They agree to 1e-14, and the NaNs fall in the same places. The same for 50 elements on grids of their own, some reversed.point_is_inside_polygon. In other dimensions it usesscipy.optimize.rooton each cell, judged by its residual.axis_outputraises.bounds="raise"; grids that vary along an orthogonal axis, and grids broadcast across one;weights_input, shared or per element; units; non-finite points; cells of zero size; Newton's halved steps across cells of very different widths.NUMBA_DISABLE_JIT=1.Speed
On a 1001×1000 grid, building the weights for scattered points with
coalesce=False(the new asv benchmarktime_weights_multilinear_2d, best of three):The single-point cost is the setup: comparing a materialized meshgrid's values, or building the boxes. For a rectilinear grid broadcast from 1D coordinates, the setup takes 0.4 ms.
With many elements, a grid of 50 points for each pixel and 40 points to interpolate at,
weights()takes about as long as onmain, where most of the time goes to merging repeated pairs:mainReview
An xhigh review of the first version found ten issues, all fixed here:
axis_outputreturning a wrongly shaped result instead of raising;regrid_from_weightsdocstring;find_indicesis unchanged. Itsbruteandsearchsortedmethods could use these locators to work in more than 1D in a later PR.🤖 Generated with Claude Code
https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP