scijit.interpolate.RegularGridInterpolator

scijit.interpolate.RegularGridInterpolator(points, values, method='linear', bounds_error=True, fill_value=nan, extrapolate=False)

Build an _RGI for interpolation on a regular grid.

Parameters:
pointstuple or list of 1-D float array_like

Axis coordinates, one array per dimension, each strictly ascending OR strictly descending (a descending axis is flipped along with the corresponding axis of values). Anything non-monotone raises ValueError. Arbitrary ndim; tested to 4-D.

valuesarray_like, shape tuple(len(p) for p in points) + rest

Grid data. A real values of any width is held as float64 and a complex one as complex128, which is the dtype the interpolated result carries. rest is the shape of the block at each node, empty for one number per node and up to 2 axes beyond that; rgi(xi) then returns xi.shape[:-1] + rest. A shape that disagrees with the grid raises ValueError.

methodstr, optional

'linear' for multilinear interpolation, 'nearest' for nearest-neighbour, ties at the cell midpoint rounding down, or 'pchip' for a shape-preserving cubic along each axis in turn. The value may be a runtime string. Anything that is not one of those three raises ValueError. Default 'linear'. 'pchip' needs at least four nodes on every axis and a real values, and raises ValueError otherwise.

bounds_errorbool, optional

If True, a query point outside the grid raises ValueError at evaluation time. Default True.

fill_valuescalar, array_like or None, optional

Value returned for out-of-bounds queries when bounds_error is False. None extrapolates linearly off the edge cell instead. A scalar fills every component; a sequence broadcasts up to rest and gives one value per component. A value that cannot be cast to the stored dtype raises ValueError, so a complex fill_value on a real values raises. Default NaN.

extrapolatebool, optional

Continue the interpolant off the edge cell for an out-of-bounds query, ignoring fill_value. The same thing fill_value=None does, and the two spellings reach the same code. Default False.

Returns:
rgijitclass

A jitclass instance to pass into @njit code, where it is evaluated with rgi(xi) or rgi(xi, method), or by name with .ev(xi), .ev_point(p), .ev_nd(xi) and their _m twins. Which class it is follows the dtype of values and how many trailing axes it carries, both fixed while compiling.

See also

scipy.interpolate.RegularGridInterpolator

The scipy routine this mirrors.

Notes

Validation, the descending-axis flip and the ragged-to-flat packing all run in compiled code, so the interpolator can be built inside @njit. The jitclass constructor underneath always takes all of its arguments.

Only 'linear', 'nearest' and 'pchip' are implemented. scipy’s 'slinear', 'cubic' and 'quintic' build tensor-product B-splines solved with a sparse Krylov solver this package does not ship, and raise here; 'pchip' is the shape-preserving cubic alternative.

extrapolate has no scipy counterpart. It is fill_value=None under a boolean spelling; a scipy-shaped call never passes it.

nu, solver and solver_args, scipy’s three keyword-only arguments for the spline methods, do not exist here. A callable jitclass dispatches on the types of its POSITIONAL arguments, so a keyword-only argument has no spelling on rgi(xi, ...).

A fill_value whose shape does not broadcast up to rest raises when the interpolator is built. scipy raises inside a numpy assignment at evaluation instead, with a message naming the number of out-of-bounds rows, and it raises on every call, including one whose points are all in bounds.

A values with trailing axes needs points as a TUPLE when the call is compiled: a list has no length until it runs, and the rank of the result is fixed while compiling. A list passed from Python is converted here, so the constraint applies to a list built inside @njit.

Accuracy: see the module docstring.

prange-safe: yes. 64 interpolators built inside one prange and evaluated reproduce the serial build exactly, 0.000e+00.

Examples

>>> import numpy as np
>>> from numba import njit
>>> from scijit.interpolate import RegularGridInterpolator
>>> x = np.linspace(0.0, 1.0, 5)
>>> y = np.linspace(0.0, 1.0, 6)
>>> vals = np.exp(x[:, None] + y[None, :])
>>> rgi = RegularGridInterpolator((x, y), vals)     # build once
>>> float(rgi(np.array([[0.25, 0.4]]))[0])
1.9155408290138962

Inside compiled code, the largest value over a set of query points:

>>> @njit
... def query_max(rgi):
...     pts = np.array([[0.1, 0.2], [0.5, 0.5], [0.9, 0.8]])
...     return np.max(rgi(pts))
>>> float(np.round(query_max(rgi), 6))
5.514377