scipy.interpolate.

BSpline#

class scipy.interpolate.BSpline(t, c, k, extrapolate=True, axis=0)[源代码][源代码]#

B样条基底中的单变量样条。

\[S(x) = \sum_{j=0}^{n-1} c_j B_{j, k; t}(x)\]

其中 \(B_{j, k; t}\) 是度数为 k 和节点 t 的 B 样条基函数。

参数:
tndarray, 形状 (n+k+1,)

cndarray, 形状 (>=n, …)

样条系数

k整数

B样条次数

外推布尔值或 ‘periodic’,可选

是否在基础区间 t[k] .. t[n] 之外进行外推,或者返回 nans。如果为 True,则在基础区间上激活的 b-样条函数的第一段和最后一段进行外推。如果为 ‘periodic’,则使用周期性外推。默认为 True。

int, 可选

插值轴。默认值为零。

属性:
tndarray

结向量

cndarray

样条系数

k整数

样条度数

外推布尔

如果为 True,则外推 b-spline 函数在基区间上活动的第一段和最后一段多项式。

整数

插值轴。

tck元组

等同于 (self.t, self.c, self.k) (只读)。

方法

__call__(x[, nu, extrapolate])

评估一个样条函数。

basis_element(t[, extrapolate])

返回一个B样条基元素 B(x | t[0], ..., t[k+1])

derivative([nu])

返回表示导数的B样条。

antiderivative([nu])

返回表示不定积分的B样条。

integrate(a, b[, extrapolate])

计算样条的定积分。

insert_knot(x[, m])

x 处插入一个重数为 m 的新节点。

construct_fast(t, c, k[, extrapolate, axis])

构建一个样条而不进行检查。

design_matrix(x, t, k[, extrapolate])

返回一个以 CSR 格式稀疏数组表示的设计矩阵。

from_power_basis(pp[, bc_type])

从幂基的分段多项式构造B样条基的多项式。

注释

B样条基元素通过定义

\[ \begin{align}\begin{aligned}B_{i, 0}(x) = 1, \textrm{如果 $t_i \le x < t_{i+1}$, 否则 $0$,}\\B_{i, k}(x) = \frac{x - t_i}{t_{i+k} - t_i} B_{i, k-1}(x) + \frac{t_{i+k+1} - x}{t_{i+k+1} - t_{i+1}} B_{i+1, k-1}(x)\end{aligned}\end{align} \]

实现细节

  • 对于一个度数为 k 的样条,至少需要 k+1 个系数,因此 n >= k+1。额外的系数,即 j > nc[j],将被忽略。

  • 度数为 k 的 B 样条基元素在 基区间 上形成了一个单位分割,t[k] <= x <= t[n]

参考文献

[2]

Carl de Boor, A practical guide to splines, Springer, 2001.

示例

将B样条的递归定义翻译成Python代码,我们有:

>>> def B(x, k, i, t):
...    if k == 0:
...       return 1.0 if t[i] <= x < t[i+1] else 0.0
...    if t[i+k] == t[i]:
...       c1 = 0.0
...    else:
...       c1 = (x - t[i])/(t[i+k] - t[i]) * B(x, k-1, i, t)
...    if t[i+k+1] == t[i+1]:
...       c2 = 0.0
...    else:
...       c2 = (t[i+k+1] - x)/(t[i+k+1] - t[i+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(c[i] * B(x, k, i, t) for i in range(n))

注意,这是一种评估B样条的低效(尽管直接)方法——这个样条类以一种等效但更高效的方式实现了它。

在这里,我们在基区间 2 <= x <= 4 上构造一个二次样条函数,并与直接评估样条的简单方法进行比较:

>>> 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

请注意,在基本区间之外的结果会有所不同。这是因为 BSpline 会外推基本区间上活动的 B 样条函数的第一段和最后一段多项式。

>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> 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()
../../_images/scipy-interpolate-BSpline-1.png