or
Why splprep
does not work with its own knots?
I am trying to figure out how to set the knots in scipy.interpolate.splprep
.
In a non-periodic case I succeed, i.e. I can reproduce this SE example.
In case of periodic boundary conditions (PBC) I have a problem, though. Here scipy.interpolate.splprep
doesn't even work with its own knots as this example shows:
import numpy as np
from scipy.interpolate import splev, splrep
import scipy
print "my scipy version: ", scipy.__version__
srate = 192000.
freq = 1200.
timeList = [ i / srate for i in range( int( srate / freq + 1 ) ) ]
signal = np.fromiter( ( np.sin( 2 * np.pi * freq * t ) for t in timeList ), np.float )
spl = splrep( timeList, signal, per=1 )
knots = spl[0]
spl = splrep( timeList, signal, t=knots, per=1 )
gives:
my scipy version: 1.0.0
Traceback (most recent call last):
File "splrevtest.py", line 15, in <module>
spl = splrep( timeList, signal, t=knots, per=1 )
File "/somepath/python2.7/site-packages/scipy-1.0.0-py2.7-linux-/python2.7/site-packages/scipy-1.0.0-py2.7-linux-x86_64.egg/scipy/interpolate/fitpack.py", line 289, in splrep
res = _impl.splrep(x, y, w, xb, xe, k, task, s, t, full_output, per, quiet)
File "/somepath/python2.7/site-packages/scipy-1.0.0-py2.7-linux-x86_64.egg/scipy/interpolate/_fitpack_impl.py", line 514, in splrep
raise _iermess[ier][1](_iermess[ier][0])
ValueError: Error on input data
Moreover, if you plot the first and the last knots like:
print timeList[-1]
print knots[:4]
print knots[-4:]
you get
>> 0.000833333333333
>> [-1.56250000e-05 -1.04166667e-05 -5.20833333e-06 0.00000000e+00]
>> [0.00083333 0.00083854 0.00084375 0.00084896]
meaning that there are six dots out of the actual data range, three before and three after. This is probably OK as we have PBC and the knots are identical to knots inside the data range modulus the period, but strange anyway. (BTW, the example does not even work when setting per=0
.) Moreover, setting points outside the data range fails if I set the dots manually. It works, even with per=1
, if the dots are well inside the data range. Like e.g.:
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import splev, splrep
import scipy
x = np.linspace( 0, 1, 120 )
timeList = np.linspace( 0, 1, 15 )
signal = np.fromiter( ( np.sin( 2 * np.pi * t +.3 ) for t in timeList ), np.float )
signal[ -1 ] -= .15
myKnots=np.linspace( .05, .95, 8 )
spl = splrep( timeList, signal, t=myKnots, per=1 )
fit = splev(x,spl)
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( timeList, signal, marker='o' )
ax.plot( x, fit , 'r' )
for i in myKnots:
ax.axvline( i )
plt.show()
providing:
wehre one can also see that the last point is ignored in PBC.
So what is scipy.interpolate.splprep
actually doing here, and why is it not accepting a similar knot construction for manual set knots if per=1
. Is it a bug?
I hope the answer to the last question is 'no', as otherwise I'd be wrong asking this here.