0

I am trying to use Python's SciPy package to make a spline through some data. In reference to the Question here, I think the reason why there are duplicate knots at the beginning and end of using interpolate.splrep is because it is making a clamped spline. I want the knots to go through the data (s=0). The output of splrep repeats the first and last knots 4x each (as in the question above), and it includes the interior data points as knots except the second point and the next to last point. Here is a MWE:

import math
import numpy as np
import scipy.interpolate
import matplotlib.pyplot as plt

x_dec = np.array([ 3.0289979374768700e-01, 3.0280333252410779e-01, 3.0270688524899364e-01,
    3.0261045192336944e-01, 3.0251403254826026e-01, 3.0241762712469000e-01,
    3.0232123565368257e-01, 3.0222485813626193e-01, 3.0212849457345037e-01])
# Make monotonically increase
x_inc = math.pi/2 - x_dec
print x_inc
y = np.array([0.914024505, 0.914049905, 0.914075289, 0.914100656, 0.914126008, 0.914151343,
    0.914176662, 0.914201964, 0.91422725])

spl_tck = scipy.interpolate.splrep(x_inc,y,k=3,s=0.0)
# Print the knots
print spl_tck[0]

Here is the output:

[ 1.26789653  1.26799299  1.26808944  1.26818587  1.26828229  1.2683787 1.26847509  1.26857147  1.26866783]

[ 1.26789653  1.26789653  1.26789653  1.26789653  1.26808944  1.26818587 1.26828229  1.2683787   1.26847509  1.26866783  1.26866783  1.26866783 1.26866783]

The first line is the data, the second line is the knots. As you can see, the knots repeat the first and last data points (x_inc[0] and x_inc[-1]). Then data points x_inc[2] through x_inc[-3] are all knot points. However, data points x_inc[1] and x_inc[-2] are skipped as knot points.

I thought that specifying s=0 would force the spline through all the points. Is there something about B-splines and repeated the endpoints as knot points that precludes using the adjacent data points to the end points as knot points?

Community
  • 1
  • 1
Paul
  • 195
  • 1
  • 8

1 Answers1

1

This is the so-called not-a-knot boundary condition for b-splines. The spline still passes through all the data points (check it: try splev(x, tck) - y. Two things are at play here: 1) a cubic b-spline basis element needs five knots; to have a spline defined at x[0], you pad the data points --- thus a repeated value at the beginning, ditto at the end. 2) for cubic splines, the number of coefficients to be determined by the fit and the number of conditions (the number of data points to interpolate) differs by two. You can either come up with two extra conditions (eg, specify the values of end derivatives or require that the 2nd derivatives are zero at the edges of the base interval) or require extra smoothness at the second at second-to-last points -- hence the name not-a-knot.

ev-br
  • 24,968
  • 9
  • 65
  • 78
  • Thank you! Very helpful. I am curious, though, why when converting from B-splines to cubic polynomials, it keeps the repeated knot points? When I take the output from the above code and do: `poly = scipy.interpolate.PPoly.from_spline(spl_tck)` the out put in `poly.x` has the repeated points. This, to me, seems silly since the knots in a cubic spline are the points between which the coefficients are valid, so repeating doesn't do anything. Simply a result of sending in a not-a-knot B-spline to a cubic spline converter?? – Paul Jan 04 '16 at 16:56
  • Well, I think it's just that equality is not very well defined in the floating point, so trying to detect that spline knots are coinciding is not really worth it. You can have a look at the source of `PPoly.from_spline`, it's really five lines. – ev-br Jan 04 '16 at 17:53
  • I should add that the future scipy version is likely to have an interpolating spline object in the polynomial basis. See https://github.com/scipy/scipy/pull/5653 – ev-br Jan 04 '16 at 17:55