问题
I have the following data:
x_old = [ 0.00000000e+00, -5.96880765e-24, -8.04361605e-23,
-2.11167774e-22, -2.30386081e-22, -7.86854147e-23,
1.17548440e-22, 1.93009272e-22, 1.49906866e-22,
9.66877465e-23, 1.48495705e-23]
y_old = [ 0. , 0.03711505, 0.03780602, 0.02524459, 0.01349815,
0.00964215, 0.00972842, 0.0168793 , 0.02577024, 0.02761626,
0.02141961]
z_old = [ 0. , 0.29834302, 0.59805918, 0.89773519, 1.19755092,
1.49749325, 1.79750314, 2.09741402, 2.39727031, 2.69726787,
2.99719479]
I want to find the 3-D
spline between these points so that the initial coordinate (0, 0, 0)
remains fixed (clamped) and the other end is free
.
I did:
from scipy.interpolate import splprep, splev
import numpy as np
# find the knot points
tckp,u = splprep([x_old,y_old,z_old],s=3.0,k=3,nest=-1)
# evaluate spline.
xnew,ynew,znew = splev(np.linspace(0,1,400),tckp)
Graph:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
ax.plot(xnew, ynew, znew, label='first iteration')
plt.scatter(x_old, y_old, z_old, color='blue', label='given')
ax.legend()
plt.show()
Question 1. In the above graph, the initial point is certainly not fixed. Mathematically, I know that I need to specify boundary conditions so that I get the 3-D spline I want. How can I do this in scipy
?. Is there any optional arguments I can use in splprep
and splev
that I can specify to achieve this or do I need a completely new way to do this?
Question 2 : If I wanted both ends to be clamped then how do I achieve that?
Some Math : 'Clamped at the initial point' means that the first derivative at the initial point is zero and 'free at the terminal' point means that the second derivative there is zero.
回答1:
It seems you want an interpolating spline, which means the smoothing parameter s should be set to 0.
tckp, u = splprep([x_old,y_old,z_old], s=0.0, k=3, nest=-1)
A clamped spline (or a spline with other boundary conditions) can be made with make_interp_spline. Below, the parameters l, r
are the boundary conditions at the left and right end. I prescribe zero first derivative at the left end, and zero second derivative at the right.
l, r = [(1, (0, 0, 0))], [(2, (0, 0, 0))]
clamped_spline = make_interp_spline(u, np.array([x_old, y_old, z_old]).T, bc_type=(l, r))
xnew2, ynew2, znew2 = clamped_spline(np.linspace(0,1,400)).T
Notice that I used the parameter u
from the first spline, expecting it to perform better than a random linearly-spaced array. (u
is computed based on the data points.)
Plotting both for comparison:
from mpl_toolkits.mplot3d import Axes3D as ax
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(xnew, ynew, znew, label='first iteration')
ax.plot(xnew2, ynew2, znew2, color='red', label='second iteration')
ax.scatter(x_old, y_old, z_old, color='blue', label='given')
ax.legend()
plt.show()
The clamping condition clearly had some effect near that end.
来源:https://stackoverflow.com/questions/47089749/one-end-clamped-and-other-end-free-cubic-spline-using-scipy-interpolate-splprep