scijit.interpolate.LSQUnivariateSpline

scijit.interpolate.LSQUnivariateSpline(x, y, t, w=array([], dtype=float64), bbox=None, k=3, ext=0, check_finite=False)

Build a least-squares spline on given interior knots.

Parameters:
x1-D float64 ndarray, length m

Abscissae, increasing; a duplicated value is allowed.

y1-D float64 ndarray, length m

Ordinates.

t1-D array_like of float

The INTERIOR knots only, strictly inside (xb, xe) and strictly increasing. The constructor builds the full knot vector by repeating xb and xe k+1 times at the ends. (The raw fitters.curfit_lsq wants the FULL vector instead.) An EMPTY t is valid and gives the least-squares polynomial of degree k.

w1-D array_like of float, optional

Positive weights, length m. None and a zero-length array both mean unit weights. fp scales as w**2, so weights DO change the residual here even though the knots are fixed.

bbox(2,) array_like of float, optional

Boundary of the approximation interval, and the padding values for the knot vector: bbox=[-1, 5] makes the full vector [-1,-1,-1,-1, t..., 5,5,5,5]. None, in place of the pair or in one slot, means x[0] / x[-1], and is the default. May only WIDEN.

kint, optional

Spline degree, 1 <= k <= 5. Default 3.

extint or str, optional

Extrapolation mode: 0 or 'extrapolate', 1 or 'zeros', 2 or 'raise', 3 or 'const'. Default 0.

check_finitebool, optional

Raise if x, y or w contains a NaN or an inf. Default False.

Attributes:
t1-D float64 ndarray

Full knot vector, including the repeated boundary knots.

c1-D float64 ndarray

Coefficients in FITPACK’s padded form.

kint

Spline degree.

fpfloat

Weighted sum of squared residuals.

ierint

FITPACK status, 0 for every knot vector that passes the checks above.

extint

The resolved extrapolation code, 0..3.

Methods

ev(x), ev_one(x), __getitem__(x), derivative_ev(x, nu), derivatives(x),

integral(a, b), roots(), get_knots(), get_coeffs(), get_residual()

Returns:
spl_LSQUnivariateSpline

A jitclass instance carrying the attributes and methods below.

Raises:
ValueError

Non-finite input under check_finite, mismatched lengths, a bbox that is not length 2, k outside 1..5, an unknown ext, m <= k, then x must be increasing (a DUPLICATED x is allowed here and rejected by InterpolatedUnivariateSpline), then Interior knots t must satisfy Schoenberg-Whitney conditions, then FITPACK’s fpchec rejection. All three knot checks run before the fit.

See also

scipy.interpolate.LSQUnivariateSpline

The scipy class this mirrors.

Notes

  • spl(x) runs .ev for an array and .ev_one for a scalar. .ev(x), .ev_one(x) and spl[x] reach the same methods. spl(x, nu) and spl(x, nu, ext) carry scipy’s second and third positional parameters, and spl(x, nu=1) and spl(x, ext=1) carry them by keyword. .ev(x, nu=1) takes the keyword inside @njit and not from the interpreter, where the jitclass method raises TypeError; the call spelling works from both.

  • There is no s argument on either side: with the knots fixed the fit is the least-squares one. scipy’s set_smoothing_factor is a no-op plus a UserWarning on this class, and is absent here.

  • .derivative() / .antiderivative() returning new spline objects are absent.

  • ier = 10 RAISES here. scipy warns and returns an object whose knot vector was never filled; a status that means “no approximation returned” is not carried into a usable object. ier of 1, 2 or 3 warns.

  • A complex y raises TypeError. scipy 1.18 accepts it, emits a ComplexWarning and discards the imaginary part, returning a float64 spline.

Defaults work in both worlds. LSQUnivariateSpline is a plain @njit factory, not the jitclass itself, so LSQUnivariateSpline(x, y, t) compiles and runs inside @njit as well as from Python. The class it returns, _LSQUnivariateSpline, takes every argument explicitly, because a jitclass constructor’s defaults are Python-only.

Accuracy against scipy 1.18.0, max absolute difference: knots, coefficients, fp, values, get_knots, get_coeffs, integral and derivatives all 0.0, including the empty-t case and weighted fits.

prange-safe: yes.

Examples

>>> import numpy as np
>>> from numba import njit
>>> from scijit.interpolate import LSQUnivariateSpline
>>> x = np.linspace(0, 4, 40)
>>> y = np.sin(x)
>>> knots = np.array([1.0, 2.0, 3.0])
>>> spl = LSQUnivariateSpline(x, y, knots)     # fit once on given interior knots
>>> float(np.round(spl(1.5), 6))
0.99578

Inside compiled code, scanning the domain for the fit’s peak:

>>> @njit
... def peak(spl):
...     xs = np.linspace(0.0, 4.0, 201)
...     return np.max(spl(xs))
>>> float(np.round(peak(spl), 6))
0.998422