问题描述
我正在构建一个可以很好地插入我拥有的一些数据的脊椎,我想将其存储在数据库中。我认为这很简单,因为我可以只获取节点和系数,然后用它们创建一个新的样条。然而,这是非常错误的。这是一个最小(非)工作示例。
import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate
xs = np.linspace(0,2,101)
ys = xs*np.cos(2*np.pi*xs)
knotNumber = 9
knots = np.linspace(0,knotNumber)[1:-1]
spline = interpolate.LSQUnivariateSpline(xs,ys,knots,k=3)
re_spline = interpolate.BSpline(spline.get_knots(),spline.get_coeffs(),3)
sp_ys = spline(xs)
re_ys = re_spline(xs)
plt.plot(xs,'-',color='black');
plt.plot(xs,sp_ys,color='blue');
plt.plot(xs,re_ys,color='red');
结果如下图:
如您所见,LSQUnivariateSpline
蓝色曲线完全覆盖了黑色。来自我创建的样条曲线的红色曲线似乎完全无关。
我在这里遗漏了什么明显的东西吗?如何重建样条曲线?
解决方法
BSpline
在起点和终点(固定点)需要 k
个额外的结;不同于 (LSQ
)`UnivariateSpline。
我通过查看
的结果发现了这一点interpolate.splrep(xs,ys,k=3,task=-1,t=knots)
在输出结的开头显示 3 个额外的零,在结尾显示 3 个额外的 2:
[0. 0. 0. 0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. 2. 2. 2. ]
。
(额外端点的数量显然取决于程度。)
有了这个,以下应该可以工作:
xs = np.linspace(0,2,101)
ys = xs*np.cos(2*np.pi*xs)
k = 3
knotNumber = 9
knots = np.linspace(0,knotNumber)
spline = interpolate.LSQUnivariateSpline(xs,knots[1:-1],k=k)
bknots = np.array(k * [knots[0]] + spline.get_knots().tolist() + k * [knots[-1]])
re_spline = interpolate.BSpline(bknots,spline.get_coeffs(),k)
sp_ys = spline(xs)
re_ys = re_spline(xs)
(或使用任何其他更漂亮的方式将额外的结添加到 spline.get_knots()
。)