axsdb.math¶
Fast interpolation with Numba.
This module provides high-performance interpolation functions implemented
using Numba’s guvectorize decorator. These functions are designed to replace
xarray’s interpolation for specific use cases where performance is critical.
Functions:
|
Fast 1D linear interpolation. |
|
Linear interpolation using precomputed indices and weights. |
|
Precompute left-indices and interpolation weights for linear interpolation. |
- axsdb.math.interp1d(x: ndarray, y: ndarray, xnew: ndarray, bounds: Literal['fill', 'clamp', 'raise'] = 'fill', fill_value: float | tuple[float, float] = nan) ndarray[source]¶
Fast 1D linear interpolation.
This function provides high-performance linear interpolation that broadcasts over leading dimensions. It powers a drop-in replacement for cases where xarray’s interpolation is too slow.
- Parameters:
x (array-like) – X coordinates of the data points. Must be sorted in ascending order along the last axis. Results are undefined for unsorted x. Shape (…, n).
y (array-like) – Y coordinates of the data points. Shape (…, n).
xnew (array-like) – X coordinates at which to evaluate the interpolation. Shape (…, m).
bounds ({"fill", "clamp", "raise"}, default: "fill") –
How to handle out-of-bounds query points:
"fill": usefill_valuefor points outside the data range."clamp": use the nearest boundary value (y[0]ory[-1])."raise": raise a ValueError if any query point is out of bounds.
fill_value (float or tuple of (float, float), default: np.nan) –
Value(s) to use for out-of-bounds points when
bounds="fill":if a single float, use for both lower and upper bounds;
if a 2-tuple, use (
fill_lower,fill_upper).
- Returns:
Interpolated values at the query points. The output shape is determined by numpy broadcasting rules applied to x, y, and xnew. Shape (…, m).
- Return type:
ndarray
- Raises:
If
bounds="raise"and any query point is outside the data range. * Ifboundsis not one of “fill”, “clamp”, or “raise”. * Iffill_valueis a tuple with length != 2.
Notes
The implementation uses a Numba gufunc with signature
(n),(n),(m)->(m)for the core interpolation, enabling efficient broadcasting over arbitrary leading dimensions.The function assumes
xis sorted in ascending order along the last axis. Results are undefined if this assumption is violated.NaN values in
xneware passed through (output will be NaN).
Examples
Basic interpolation:
>>> x = np.array([0.0, 1.0, 2.0, 3.0]) >>> y = np.array([0.0, 1.0, 4.0, 9.0]) >>> xnew = np.array([0.5, 1.5, 2.5]) >>> interp1d(x, y, xnew) array([0.5, 2.5, 6.5])
With fill values for out-of-bounds:
>>> xnew = np.array([-1.0, 1.5, 5.0]) >>> interp1d(x, y, xnew, bounds="fill", fill_value=(-999.0, 999.0)) array([-999. , 2.5, 999. ])
Clamping to boundary values:
>>> interp1d(x, y, xnew, bounds="clamp") array([0. , 2.5, 9. ])
Broadcasting over multiple curves:
>>> x = np.array([0.0, 1.0, 2.0]) >>> y = np.array([[0.0, 1.0, 2.0], # Linear ... [0.0, 1.0, 4.0]]) # Quadratic >>> xnew = np.array([0.5, 1.5]) >>> interp1d(x, y, xnew) array([[0.5, 1.5], [0.5, 2.5]])
- axsdb.math.lerp(y: ndarray, indices: ndarray, weights: ndarray) ndarray[source]¶
Linear interpolation using precomputed indices and weights.
This is the fast inner loop for the case where many
yarrays share the samexgrid and query points. The binary search is done once vialerp_indices(); this function executes only the linear combinationy[i] + t * (y[i+1] - y[i]).- Parameters:
y (ndarray) – Data values. The last axis must correspond to the
xgrid used inlerp_indices(). Broadcasting over leading dimensions is handled by the underlying gufunc. Shape (…, n).indices (ndarray) – Left-bin indices from
lerp_indices(). IMPORTANT: Indices must be in the range[0, n-2]wheren = y.shape[-1]. This invariant is enforced bylerp_indices()but is not validated here for performance reasons. Shape (m,).weights (ndarray) – Interpolation weights from
lerp_indices(). Shape (m,).
- Returns:
Interpolated values. NaN weights (from
bounds="fill") propagate as NaN in the output. Shape (…, m).- Return type:
ndarray
Notes
This function does not perform bounds checking on
indicesfor performance. The caller must ensure indices are valid (in[0, n-2]). Usinglerp_indices()guarantees this invariant.
- axsdb.math.lerp_indices(x: ndarray, xnew: ndarray, bounds: Literal['fill', 'clamp', 'raise'] = 'fill') tuple[ndarray, ndarray][source]¶
Precompute left-indices and interpolation weights for linear interpolation.
When the same query points
xnewwill be applied to many differentyarrays sharing the samexgrid, it is far cheaper to run the binary search once here and then calllerp()for eachy. That function skips the search entirely and executes only they[left] + t*(y[left+1] - y[left])step.- Parameters:
x (ndarray) – Sorted coordinate grid (1-D). Shape (n,).
xnew (ndarray) – Query points (1-D). Shape (m,).
bounds ({"fill", "clamp", "raise"}, default: "fill") –
Out-of-bounds handling, same semantics as
interp1d()."fill": out-of-bounds indices are set to 0 with weight NaN so thatlerp()will produce NaN there. The caller can replace those NaNs after the fact if a different fill value is needed."clamp": out-of-bounds queries are clamped to the nearest boundary index with weight 0 (reproducingy[0]ory[-1])."raise": raises immediately if any query is out of bounds.
- Returns:
indices (ndarray) – Left-bin indices as floats (required by the gufunc signature). Shape (m,), dtype float64.
weights (ndarray) – Fractional position within each bin:
t = (xnew - x[i]) / (x[i+1] - x[i]). Shape (m,), dtype float64.
- Raises:
ValueError – If
bounds="raise"and any query point is outside[x[0], x[-1]].