Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

coefficients of spline interpolation in scipy

I want to calculate the coefficients of a spline interpolation by scipy. In MATLAB:

x=[0:3];
y=[0,1,4,0];
spl=spline(x,y);
disp(spl.coefs);

and it will return:

ans =

   -1.5000    5.5000   -3.0000         0
   -1.5000    1.0000    3.5000    1.0000
   -1.5000   -3.5000    1.0000    4.0000

But i can't do that by interpolate.splrep in scipy. Can you tell me how to calc it?

like image 319
Gochit Avatar asked Nov 14 '12 18:11

Gochit


People also ask

What are spline coefficients?

The spline function is defined by a number, m, of parameters represented by the vector β. In Villez et al. (2013), the parameters are the spline coefficients. Given a QR defining the shape constraints, the feasible set for these coefficients, Ω(θ), is a convex subset of the real space .

What is Scipy interpolate in Python?

Interpolation is a technique of constructing data points between given data points. The scipy. interpolate is a module in Python SciPy consisting of classes, spline functions, and univariate and multivariate interpolation classes. Interpolation is done in many ways some of them are : 1-D Interpolation.


4 Answers

I'm not sure there is any way to get exactly those coefficients from scipy. What scipy.interpolate.splrep gives you is the coefficients for the knots for a b-spline. What Matlab's spline gives you appears to be the partial polynomial coefficients describing the cubic equations connecting the points you pass in, which leads me to believe that the Matlab spline is a control-point based spline such as a Hermite or Catmull-Rom instead of a b-spline.

However, scipy.interpolate.interpolate.spltopp does provide a way to get the partial polynomial coefficients of a b-spline. Unfortunately, it doesn't seem to work very well.

>>> import scipy.interpolate
>>> x = [0, 1, 2, 3]
>>> y = [0, 1, 4, 0]
>>> tck = scipy.interpolate.splrep(x, y)
>>> tck
Out: 
    (array([ 0.,  0.,  0.,  0.,  3.,  3.,  3.,  3.]),
    array([  3.19142761e-16,  -3.00000000e+00,   1.05000000e+01,
        0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
        0.00000000e+00,   0.00000000e+00]),
    3)

>>> pp = scipy.interpolate.interpolate.spltopp(tck[0][1:-1], tck[1], tck[2])

>>> pp.coeffs.T
Out: 
    array([[ -4.54540394e-322,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000],
        [ -4.54540394e-322,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000],
        [ -4.54540394e-322,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000],
        [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000],
        [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000]])

Note that there is one set of coefficients per knot, not one for each of the original points passed in. Also, multiplying the coefficients by the b-spline basis matrix doesn't seem to be very helpful.

>>> bsbm = array([[-1,  3, -3,  1], [ 3, -6,  3,  0], [-3,  0,  3,  0], 
                 [ 1,  4,  1,  0]]) * 1.0/6
Out: 
    array([[-0.16666667,  0.5       , -0.5       ,  0.16666667],
        [ 0.5       , -1.        ,  0.5       ,  0.        ],
        [-0.5       ,  0.        ,  0.5       ,  0.        ],
        [ 0.16666667,  0.66666667,  0.16666667,  0.        ]])

>>> dot(pp.coeffs.T, bsbm)
Out: 
    array([[  7.41098469e-323,  -2.27270197e-322,   2.27270197e-322,
           -7.41098469e-323],
        [  7.41098469e-323,  -2.27270197e-322,   2.27270197e-322,
           -7.41098469e-323],
        [  7.41098469e-323,  -2.27270197e-322,   2.27270197e-322,
           -7.41098469e-323],
        [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000],
        [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000,
           0.00000000e+000]])

The FORTRAN Piecewise Polynomial Package, PPPack, has a command bsplpp that converts from B-spline to piecewise polynomial form, which may serve your needs. Unfortunately, there isn't a Python wrapper for PPPack at this time.

like image 162
brentlance Avatar answered Oct 16 '22 07:10

brentlance


Here is how I could get results similar to MATLAB:

>>> from scipy.interpolate import PPoly, splrep
>>> x = [0, 1, 2, 3]
>>> y = [0, 1, 4, 0]
>>> tck = splrep(x, y)
>>> tck
Out: (array([ 0.,  0.,  0.,  0.,  3.,  3.,  3.,  3.]),
 array([  3.19142761e-16,  -3.00000000e+00,   1.05000000e+01,
          0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
          0.00000000e+00,   0.00000000e+00]),
 3)

>>> pp = PPoly.from_spline(tck)
>>> pp.c.T
Out: array([[ -1.50000000e+00,   5.50000000e+00,  -3.00000000e+00,
      3.19142761e-16],
   [ -1.50000000e+00,   5.50000000e+00,  -3.00000000e+00,
      3.19142761e-16],
   [ -1.50000000e+00,   5.50000000e+00,  -3.00000000e+00,
      3.19142761e-16],
   [ -1.50000000e+00,   5.50000000e+00,  -3.00000000e+00,
      3.19142761e-16],
   [ -1.50000000e+00,  -8.00000000e+00,  -1.05000000e+01,
      0.00000000e+00],
   [ -1.50000000e+00,  -8.00000000e+00,  -1.05000000e+01,
      0.00000000e+00],
   [ -1.50000000e+00,  -8.00000000e+00,  -1.05000000e+01,
      0.00000000e+00]])
like image 35
dashesy Avatar answered Oct 16 '22 07:10

dashesy


If you have scipy version >= 0.18.0 installed you can use CubicSpline function from scipy.interpolate for cubic spline interpolation.

You can check scipy version by running following commands in python:

#!/usr/bin/env python3
import scipy
scipy.version.version

If your scipy version is >= 0.18.0 you can run following example code for cubic spline interpolation:

#!/usr/bin/env python3

import numpy as np
from scipy.interpolate import CubicSpline

# calculate 5 natural cubic spline polynomials for 6 points
# (x,y) = (0,12) (1,14) (2,22) (3,39) (4,58) (5,77)
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([12,14,22,39,58,77])

# calculate natural cubic spline polynomials
cs = CubicSpline(x,y,bc_type='natural')

# show values of interpolation function at x=1.25
print('S(1.25) = ', cs(1.25))

## Aditional - find polynomial coefficients for different x regions

# if you want to print polynomial coefficients in form
# S0(0<=x<=1) = a0 + b0(x-x0) + c0(x-x0)^2 + d0(x-x0)^3
# S1(1< x<=2) = a1 + b1(x-x1) + c1(x-x1)^2 + d1(x-x1)^3
# ...
# S4(4< x<=5) = a4 + b4(x-x4) + c5(x-x4)^2 + d5(x-x4)^3
# x0 = 0; x1 = 1; x4 = 4; (start of x region interval)

# show values of a0, b0, c0, d0, a1, b1, c1, d1 ...
cs.c

# Polynomial coefficients for 0 <= x <= 1
a0 = cs.c.item(3,0)
b0 = cs.c.item(2,0)
c0 = cs.c.item(1,0)
d0 = cs.c.item(0,0)

# Polynomial coefficients for 1 < x <= 2
a1 = cs.c.item(3,1)
b1 = cs.c.item(2,1)
c1 = cs.c.item(1,1)
d1 = cs.c.item(0,1)

# ...

# Polynomial coefficients for 4 < x <= 5
a4 = cs.c.item(3,4)
b4 = cs.c.item(2,4)
c4 = cs.c.item(1,4)
d4 = cs.c.item(0,4)

# Print polynomial equations for different x regions
print('S0(0<=x<=1) = ', a0, ' + ', b0, '(x-0) + ', c0, '(x-0)^2  + ', d0, '(x-0)^3')
print('S1(1< x<=2) = ', a1, ' + ', b1, '(x-1) + ', c1, '(x-1)^2  + ', d1, '(x-1)^3')
print('...')
print('S5(4< x<=5) = ', a4, ' + ', b4, '(x-4) + ', c4, '(x-4)^2  + ', d4, '(x-4)^3')

# So we can calculate S(1.25) by using equation S1(1< x<=2)
print('S(1.25) = ', a1 + b1*0.25 + c1*(0.25**2) + d1*(0.25**3))

# Cubic spline interpolation calculus example
    #  https://www.youtube.com/watch?v=gT7F3TWihvk
like image 31
nexayq Avatar answered Oct 16 '22 07:10

nexayq


The docs on scipy.interpolate.splrep say that you can get the coefficients:

Returns:

  tck : tuple

  (t,c,k) a tuple containing the vector of knots, the B-spline coefficients, and the degree of the spline.
like image 29
Bitwise Avatar answered Oct 16 '22 06:10

Bitwise