scijit.interpolate.make_interp_spline¶
- scijit.interpolate.make_interp_spline(x, y, k=3, t=None, bc_type=None, axis=0, check_finite=True)¶
Interpolating B-spline through
(x, y).- Parameters:
- x1-D float64 ndarray, length n
Abscissae, strictly increasing. A non-increasing pair raises
ValueError. Must satisfyn >= k + 1.- yfloat64 ndarray of rank 1, 2 or 3
Values to interpolate. Its length along axis must be n.
- kint, optional
Spline degree, >= 0. Default 3.
k = 0gives the piecewise-constant spline and takes no boundary condition.- t1-D float64 ndarray, optional
Knot vector,
len(t) == n + k + 1when no derivative conditions accompany it, and longer by one per condition when they do. Default None, which builds the knot set bc_type implies. It must be non-decreasing and cover[x[0], x[-1]]; otherwiseValueError.bc_type='periodic'builds its own knots and refuses this withNotImplementedError.k = 0refuses it withValueError.- bc_typestr or pair of lists, optional
Boundary condition. Default None, which selects
'not-a-knot'. The strings are'not-a-knot', which the default selects and which works for anyk >= 1;'natural',S'' = 0at both ends;'clamped',S' = 0at both ends; and'periodic', which makes the spline repeat with periodx[-1] - x[0]and requiresy[0] == y[-1].Otherwise a pair of LISTS of
(order, value)pairs, one list per end, fixingS^(order)to value there:([(1, 0.0)], [(1, 0.0)])is'clamped'and([(2, 0.0)], [(2, 0.0)])is'natural'. This shape is NOT CubicSpline’s, which takes a pair of PAIRS; each refuses the other’s shape.The conditions must use up exactly the
k - 1coefficients the augmented knot vector leaves free, so a cubic takes one per end and a quintic two. An unrecognised string raisesValueError, and a shape that is neither is refused while compiling.- axisint, optional
Which axis of y the interpolation runs along, default 0. Negative values count from the end. Ignored for a 1-D y.
ev(xs)returns the shape of y with this axis replaced bylen(xs); a scalar query returns it with this axis removed.- check_finitebool, optional
Whether to refuse a non-finite x or y, default True. The check is worth having on: every comparison against NaN is False, so a NaN x passes the strictly-increasing loop and reaches the solve. With it off a NaN reaches
np.linalg.solve, which raisesLinAlgErrorof its own.
- Returns:
- splBSpline
The interpolating spline.
extrapolate=True, except forbc_type='periodic', where a query is folded into[x[0], x[-1]]first.
See also
scipy.interpolate.make_interp_splineThe scipy routine this mirrors.
Notes
Deviations from scipy. A derivative value is one scalar per end and applies to every series of an N-D y, where scipy takes an array of the trailing shape. y is capped at rank 3 and is float64. A y of size zero raises here, where scipy returns a spline with zero-size coefficients. The returned spline goes through the BSpline constructor and is validated a second time, where scipy builds it with
construct_fastand skips that; a knot vector this function produced that the constructor rejects therefore raises here and does not there. scipy has no weights argument either, so there is none to match.k = 0andk = 1resolve before the periodic branch, in scipy and here, sobc_type='periodic'at those degrees gives the piecewise-constant and piecewise-linear splines with ordinary extrapolation. The ends are still required to match.Unlike a jitclass constructor, this is a plain
@njitFUNCTION, so its defaults work in both worlds –make_interp_spline(x, y)is verified to compile and run inside@njit– and it is where the bc_type string resolves.Accuracy vs
scipy.interpolate.make_interp_splineon 14 random nodes, evaluated at 101 points: not-a-knot gives exactly 0.0 in values, coefficients and knots for k = 2, 3, 4, 5, and 1.1e-16 in values and coefficients for k = 1 (knots exact).'natural'and'clamped'with k=3 are exactly 0.0 in both values and coefficients.On 9 nodes at [0.07, 0.3, 0.55, 0.7, 0.94], values, coefficients and knots together: an explicit t 0.000e+00; the per-end
(order, value)pairs 0.000e+00 at k=3 and 3.331e-16 with two conditions per end at k=5;'periodic'0.000e+00 at k=0 and k=1, and 2.220e-16, 3.331e-16, 3.331e-16 and 8.882e-16 at k = 2, 3, 4 and 5.prange-safe: yes – pure numpy plus
np.linalg.solve, no state.Examples
>>> import numpy as np >>> from numba import njit >>> from scijit.interpolate import make_interp_spline >>> x = np.linspace(0.0, 1.0, 11) >>> y = np.sin(3.0 * x) >>> spl = make_interp_spline(x, y, 3) # build once >>> np.round(spl(np.array([0.25, 0.75])), 6) array([0.681629, 0.778063])
Inside compiled code, scanning the domain for the curve’s peak:
>>> @njit ... def peak(spl): ... xs = np.linspace(0.0, 1.0, 201) ... return np.max(spl(xs)) >>> float(np.round(peak(spl), 6)) 0.999979