scipy.interpolate.

generate_knots#

scipy.interpolate.generate_knots(x, y, *, w=None, xb=None, xe=None, k=3, s=0, nest=None)[source]#

Replicate FITPACK’s constructing the knot vector.

Parameters:
x, yarray_like

The data points defining the curve y = f(x).

warray_like, optional

Weights.

xbfloat, optional

The boundary of the approximation interval. If None (default), is set to x[0].

xefloat, optional

The boundary of the approximation interval. If None (default), is set to x[-1].

kint, optional

The spline degree. Default is cubic, k = 3.

sfloat, optional

The smoothing factor. Default is s = 0.

nestint, optional

Stop when at least this many knots are placed.

Yields:
tndarray

Knot vectors with an increasing number of knots. The generator is finite: it stops when the smoothing critetion is satisfied, or when then number of knots exceeds the maximum value: the user-provided nest or x.size + k + 1 — which is the knot vector for the interpolating spline.

Notes

The routine generates successive knots vectors of increasing length, starting from 2*(k+1) to len(x) + k + 1, trying to make knots more dense in the regions where the deviation of the LSQ spline from data is large.

When the maximum number of knots, len(x) + k + 1 is reached (this happens when s is small and nest is large), the generator stops, and the last output is the knots for the interpolation with the not-a-knot boundary condition.

Knots are located at data sites, unless k is even and the number of knots is len(x) + k + 1. In that case, the last output of the generator has internal knots at Greville sites, (x[1:] + x[:-1]) / 2.

Added in version 1.15.0.

Examples

Generate some noisy data and fit a sequence of LSQ splines:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from scipy.interpolate import make_lsq_spline, generate_knots
>>> rng = np.random.default_rng()
>>> x = np.linspace(-3, 3, 50)
>>> y = np.exp(-x**2) + 0.1 * rng.standard_normal(size=50)
>>> knots = list(generate_knots(x, y, s=1e-10))
>>> for t in knots[::3]:
...     spl = make_lsq_spline(x, y, t)
...     xs = xs = np.linspace(-3, 3, 201)
...     plt.plot(xs, spl(xs), '-', label=f'n = {len(t)}', lw=3, alpha=0.7)
>>> plt.plot(x, y, 'o', label='data')
>>> plt.plot(xs, np.exp(-xs**2), '--')
>>> plt.legend()

Note that increasing the number of knots make the result follow the data more and more closely.

Also note that a step of the generator may add multiple knots:

>>> [len(t) for t in knots]
[8, 9, 10, 12, 16, 24, 40, 48, 52, 54]
../../_images/scipy-interpolate-generate_knots-1.png