Univariate spline in the B-spline basis.
.. math::
S(x) = \sum_j=0
^n-1
c_j B_j, k; t
(x)
where :math:`B_j, k; t
` are B-spline basis functions of degree `k` and knots `t`.
Parameters ---------- t : ndarray, shape (n+k+1,) knots c : ndarray, shape (>=n, ...) spline coefficients k : int B-spline degree extrapolate : bool or 'periodic', optional whether to extrapolate beyond the base interval, ``tk
.. tn
``, or to return nans. If True, extrapolates the first and last polynomial pieces of b-spline functions active on the base interval. If 'periodic', periodic extrapolation is used. Default is True. axis : int, optional Interpolation axis. Default is zero.
Attributes ---------- t : ndarray knot vector c : ndarray spline coefficients k : int spline degree extrapolate : bool If True, extrapolates the first and last polynomial pieces of b-spline functions active on the base interval. axis : int Interpolation axis. tck : tuple A read-only equivalent of ``(self.t, self.c, self.k)``
Methods ------- __call__ basis_element derivative antiderivative integrate construct_fast
Notes ----- B-spline basis elements are defined via
.. math::
B_, 0(x) = 1, \textrmf $t_i \le x < t_+1$, otherwise $0$,
B_, k(x) = \fracx - t_i
B_, k-1(x)
\frac
B_+1, k-1(x)
**Implementation details**
- At least ``k+1`` coefficients are required for a spline of degree `k`, so that ``n >= k+1``. Additional coefficients, ``c
j
`` with ``j > n``, are ignored.
- B-spline basis elements of degree `k` form a partition of unity on the *base interval*, ``t
k
<= x <= tn
``.
Examples --------
Translating the recursive definition of B-splines into Python code, we have:
>>> def B(x, k, i, t): ... if k == 0: ... return 1.0 if ti
<= x < ti+1
else 0.0 ... if ti+k
== ti
: ... c1 = 0.0 ... else: ... c1 = (x - ti
)/(ti+k
- ti
) * B(x, k-1, i, t) ... if ti+k+1
== ti+1
: ... c2 = 0.0 ... else: ... c2 = (ti+k+1
- x)/(ti+k+1
- ti+1
) * B(x, k-1, i+1, t) ... return c1 + c2
>>> def bspline(x, t, c, k): ... n = len(t) - k - 1 ... assert (n >= k+1) and (len(c) >= n) ... return sum(ci
* B(x, k, i, t) for i in range(n))
Note that this is an inefficient (if straightforward) way to evaluate B-splines --- this spline class does it in an equivalent, but much more efficient way.
Here we construct a quadratic spline function on the base interval ``2 <= x <= 4`` and compare with the naive way of evaluating the spline:
>>> from scipy.interpolate import BSpline >>> k = 2 >>> t = 0, 1, 2, 3, 4, 5, 6
>>> c = -1, 2, 0, -1
>>> spl = BSpline(t, c, k) >>> spl(2.5) array(1.375) >>> bspline(2.5, t, c, k) 1.375
Note that outside of the base interval results differ. This is because `BSpline` extrapolates the first and last polynomial pieces of B-spline functions active on the base interval.
>>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> xx = np.linspace(1.5, 4.5, 50) >>> ax.plot(xx, bspline(x, t, c ,k) for x in xx
, 'r-', lw=3, label='naive') >>> ax.plot(xx, spl(xx), 'b-', lw=4, alpha=0.7, label='BSpline') >>> ax.grid(True) >>> ax.legend(loc='best') >>> plt.show()
References ---------- .. 1
Tom Lyche and Knut Morken, Spline methods, http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v05/undervisningsmateriale/ .. 2
Carl de Boor, A practical guide to splines, Springer, 2001.