ENH: interpolate.RBFInterpolator to accept user kernels

scipy.interpolate.RBFInterpolator currently offers a choice of several predefined RBF kernel functions. Allowing user-supplied kernels is a long-standing feature request [1]. A technical difficulty is that RBFInterpolator cannot accept arbitrary Python callables (implementation details: it is written in C via pythran). Therefore, the user API is strings for kernel names: kernel="multiquadratic" and the string is mapped internally to a C callable).

Here’s an pull request (from a first-time contributor!) [2], which does two things:
allows passing in LowLevelCallables, and add several new built-in kernels.

Several things of note: in its current form,

  • the PR addresses a long-standing feature request;
  • LowLevelCallable inputs only work on numpy/pythran as the backend, and not on alternative Array API backends;
  • once we allow LowLevelCallables in addition to strings, we fix the user ABI. As long as we accepted string names, we had a freedom of interpreting a kernel as either a scalar function of a scalar argument, or as a “vectorized” function (this is required for decent performance with alternative backends). Once we commit to accepting LowLevelCallables, the ABI is frozen.

Thoughts?

Evgeni

[1] ENH: Custom kernel for RBFInterpolator · Issue #17294 · scipy/scipy · GitHub
[2] https://github.com/scipy/scipy/pull/24893

That sounded potentially worrying, but after having a closer look I think it’s a safe bet. There’s not much choice for signatures there, double (double) shouldn’t have to change in the future I’d think.

For ndimage we also never had a need to change anything related to the low-level interface AFAIK (see Multidimensional Image Processing (scipy.ndimage) — SciPy v1.18.0.dev Manual).

There’s not much choice for signatures there, double (double) shouldn’t have to change in the future I’d think.

With non-numpy backends, kernel strings map onto array->array functions, see e.g. scipy/scipy/interpolate/_rbfinterp_xp.py at v1.17.0 · scipy/scipy · GitHub

IOW, currently numpy+pythran kernels are indeed scalar functions of a scalar argument, and LowLevelCallable with a double(double) signature is just right.
On alternative backends, I’m not even 100% sure what the C signature is, (double *)(double *), with additional rules on array dimensions/strides etc.