0
$\begingroup$

I am looking at the construction of BSplines out of curiosity. I created a small code that uses scipy.interpolate.BSpline to create basic splines. I get the following basic splines for order 0, 1 and 2 :

import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import BSpline

x = np.linspace(-1,10,1000)
t = np.array([0, 1, 2, 3, 4, 5, 6])
k = 1
e = np.eye(t.size)
plt.figure()
for i in range(t.size):
    c = e[i]
    spl = BSpline(t, c, k, extrapolate=False)
    y = spl(x)
    plt.plot(x,y)

I obtain the following results, which seems inconsistent with the results here. The splines should be defined on the whole interval [0, 6] regardless of the order no? However, it seems that each time we increase by 1 the order of the BSplines, the domain decreases by 1 which is not the case in the just linked reference.

Basic splines of order 0:

enter image description here

Basic splines of order 1:

enter image description here

Basic splines of order 2:

enter image description here

$\endgroup$

1 Answer 1

2
$\begingroup$

The reason your answer differs is because of spline boundary conditions. Consider the spline $B_{j,1}$. To compute this we need $B_{j,0}$, $B_{j+1,0}$, and $\omega_{j,1}$ and $\omega_{j+1,1}$. $$ B_{j,0} = \begin{cases}1 & x \in [t_j,t_{j+1}]\\0&\mathrm{else}\end{cases}\\ B_{j+1,0} = \begin{cases}1 & x \in [t_{j+1},t_{j+2}]\\0&\mathrm{else}\end{cases}\\ \omega_{j,1} = \frac{x - t_{j}}{t_{j+1}-t_j}\\ \omega_{j+1,1} = \frac{x - t_{j+1}}{t_{j+2}-t_{j+1}} $$ Notice that to compute $B_{j,1}$ in the interval $[t_{i},t_{i+1}]$ requires knowing the knots $t_{i}$ through $t_{i+2}$. If we try evaluating in $[t_{4},t_{5}]$ we need to know $t_6$, which is undefined. Additionally, there are a few weird things which happen when we try to evaluate in $[t_0,t_1]$. There could be some $t_{-1}$ which would affect the result in this interval. In general to compute $B_{j,k}$ we only know for certainty what its value is between $[t_{k},t_{n-1-k}]$.

We can adjust our original knots vector by adding extra knots $t'$ on both sides to allow us to evaluate our spline for the full original interval $[t_0,t_{n-1}]$. The most common way is to simply duplicate the end knots $k$ times on each side, so we have $t'=[t_0,\ldots,t_0, \ldots,t_{n-1},\ldots,t_{n-1}]$. This is what the page you linked does. Some other options are what the extrapolate option does in SciPy: for extrapolate='periodic' the knots vector is considered to be periodic. For extrapolate=True the resultant polynomial is simply extrapolated as-is outside the interval $[t_{k},t_{n-1-k}]$.

Here's code for duplicating the figures in the linked page:

import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import BSpline

x = np.linspace(-1,10,1000)
t = np.array([1, 2, 3, 4, 5, 6])
k = 1
tp = np.concatenate((np.repeat(t[0], k), t, np.repeat(t[-1], k)))
e = np.eye(tp.size)
plt.figure()
for i in range(t.size-1-k):
    c = e[i+k]
    spl = BSpline(tp, c, k, extrapolate=False)
    y = spl(x)
    plt.plot(x,y)
```
$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.