Overview
We’re excited to present a new addition to scipy.interpolate: a Python + C++ based implementation of the classic REGRID workflow for fitting 2-D B-spline surfaces to gridded data.
The new regrid_python function provides a readable, maintainable, and Fortran-free alternative to the existing implementation, while maintaining full mathematical and API compatibility with RectBivariateSpline. This work has been developing across iterations and community feedback, see the detailed discussion in the prototyping PR in my fork.
Final PR at SciPy Repository: gh-23962
What’s New?
Core Functionality
The PR introduces two private API functions to scipy.interpolate._regrid_python:
-
regrid_python(x, y, z, *, bbox=None, kx=3, ky=3, s=0.0, maxit=50)
Fits a tensor-product B-spline surface to gridded (x, y, z) data. Key features:- Adaptive knot-growth strategy guided by residual magnitude
- Automatic smoothing parameter search (when
sis specified) - Returns an
NdBSplineobject for efficient evaluation - Full FITPACK mathematical compatibility
-
ndbspline_call_like_bivariate(ndbs, x, y, dx=0, dy=0, grid=True)
A thin wrapper enabling the returnedNdBSplineto be evaluated using the familiarRectBivariateSpline.__call__calling pattern.
Design Highlights
The implementation decomposes the algorithm into explicit, composable steps:
-
Separable two-pass solves: Fits are built by solving 1-D problems in the x- and y-directions using FITPACK kernels (C++ implementations in
__fitpack.cc), rather than constructing a single monolithic system. -
Knot-growth strategy: Residuals are projected into row and column spaces; knots are inserted where the residual is largest, respecting storage constraints.
-
Smoothing parameter search: Uses the same penalty scaling as FITPACK (
penalty = 1/p), with special handling for interpolatory fits (p = -1). -
Banded linear algebra: Leverages banded QR decomposition and back-substitution for efficiency, converting to CSR format only when needed for residual evaluation.
-
Clear mathematics: The algorithm explicitly minimizes
|A \mathbf{c} - \mathbf{z}|^2 + \frac{1}{p}|D \mathbf{c}|^2,
with full documentation of the penalty convention and knot-insertion heuristics.
Why This Matters
- Readability: Every step is written in Python or carefully documented, making the algorithm transparent for debugging, teaching, and future optimization.
- Maintainability: No external Fortran dependency; the code is self-contained and well-commented.
- Extensibility: The modular structure makes it straightforward to experiment with variants (e.g., knot-insertion strategies).
- Compatibility: Passes the same test suite as
RectBivariateSplinefor supported scenarios; input validation and output format are identical.
Next Steps
This is currently a private API. The team plans to eventually replace the existing RectBivariateSpline backend with this implementation. Timeline and public API surface will be coordinated with the maintainers.
To experiment with this work, you can import from the private module:
from scipy.interpolate._regrid_python import regrid_python, ndbspline_call_like_bivariate
Feedback Welcome
We’d like to hear from the community! Please share:
- API design: Any suggestions for the eventual public interface?
- Extensions: What features or variants would be most valuable?
Discussion are ongoing in PR #23962.
Technical Details: See the detailed PR description and module docstring for a deep dive into the mathematics, knot-insertion strategy, smoothing parameter search, and design trade-offs.
Thanks to @ev-br @j-bowhay @ilayn for their reviews/feedback on the PRs.