Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the bbox agrument in scipy.interpolate.UnivariateSpline do?

I am getting quite different answers to an integration over (0,1) spline.integral(0,1) when

spline = UnivariateSpline(x, y, bbox=[0,1], k=3.0,s=0.0)

versus

spline = UnivariateSpline(x, y, k=3.0,s=0.0)

, with the result generated from the latter being significantly lower than the first. So I am wondering what the bbox argument actually does?? An example of my x vector would be [0.0518429, 0.102736, 0.153367, 0.254166, 0.354551, 0.404618, 0.454606, 0.479576, 0.504523, 0.529457, 0.554374, 0.604159, 0.653876, 0.753149, 0.85219, 0.901613, 0.970617] so x is contained within (0,1)

like image 474
vgdev Avatar asked Dec 18 '25 11:12

vgdev


1 Answers

TL;DR: you're intergrating two different splines.

The bbox parameter itself does exactly what is says on the tin, https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.UnivariateSpline.html

bbox : (2,) array_like, optional 2-sequence specifying the boundary of the approximation interval. If None (default), bbox=[x[0], x[-1]].

The wording is a bit cryptic, I agree. A simple example helps:

In [1]: from scipy.interpolate import UnivariateSpline

In [2]: import numpy as np

In [4]: x = np.array([0.2, 0.4, 0.6, 0.8])

In [5]: y = x**4

In [6]: s1 = UnivariateSpline(x, y, s=0)

In [7]: s1.get_coeffs()
Out[7]: array([ 0.0016,  0.0176,  0.0096,  0.4096])

In [8]: s1.get_knots()
Out[8]: array([ 0.2,  0.8])

Now, specifying the bbox changes the spline:

In [15]: s2 = UnivariateSpline(x, y, s=0, bbox=[0, 1])

In [16]: s2.get_knots()
Out[16]: array([ 0.,  1.])

So if you integrate each spline within their base interval, without relying on extrapolation, everything seems to be fine:

In [23]: s2.integral(0, 1)
Out[23]: 0.19493333333333332

In [24]: s1.integral(0.2, 0.8)
Out[24]: 0.06576000000000003

In [25]: (0.8**5 - 0.2**5) / 5
Out[25]: 0.06547200000000002

However, once you try integraing s1 over a larger interval, it bombs:

In [26]: s1.integral(0.2, 0.8) - s1.integral(0, 1)
Out[26]: 0.0

Notice that it should not do that: default is to extrapolate, so it should have been something non-zero. This might actually be a bug.

like image 148
ev-br Avatar answered Dec 21 '25 03:12

ev-br



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!