antiderivative#
- BSpline.antiderivative(nu=1)[source]#
Return a B-spline representing the antiderivative.
- Parameters:
- nuint, optional
Antiderivative order. Default is 1.
- Returns:
- b
BSplineobject A new instance representing the antiderivative.
- b
See also
Notes
If antiderivative is computed and
self.extrapolate='periodic', it will be set to False for the returned instance. This is done because the antiderivative is no longer periodic and its correct evaluation outside of the initially given x interval is difficult.The coefficient array of the returned instance will be padded with
b.k + 1trailing entries, so thatlen(b.c) == len(b.t). The trailing coefficients never enter evaluations, only the firstlen(b.t) - b.k - 1coefficients are used.Examples
Taking the derivative of the antiderivative recovers the original spline, up to floating point error:
>>> import numpy as np >>> from scipy.interpolate import make_interp_spline >>> x = np.linspace(0, np.pi/2, 70) >>> y = 1 / np.sqrt(1 - 0.8*np.sin(x)**2) >>> spl = make_interp_spline(x, y) # spl is a cubic spline >>> spl(1.7), spl.antiderivative().derivative()(1.7) (array(2.15654299), array(2.15654299))
Antiderivative can be used to evaluate definite integrals:
>>> ispl = spl.antiderivative() >>> ispl(np.pi/2) - ispl(0) np.float64(2.25720536)
This is indeed an approximation to the complete elliptic integral \(K(m) = \int_0^{\pi/2} [1 - m\sin^2 x]^{-1/2} dx\):
>>> from scipy.special import ellipk >>> ellipk(0.8) np.float64(2.25720533)
The coefficient array of the returned spline is padded with
k + 1extra trailing entries, which are not used in evaluations, as the examples below demonstrate:>>> from scipy.interpolate import BSpline, make_interp_spline >>> x = np.arange(11) >>> y = x**4 + np.sin(x) >>> spl = make_interp_spline(x, y, k=3) # spl is a cubic (degree 3) spline
A spline of degree
kis built from polynomial pieces of degreek, joined at the knotst. The number of knots, the number of coefficients, and the degree are related bylen(t) - len(c) == k + 1. Padded coefficients instead satisfylen(c) == len(t):>>> len(spl.t), len(spl.c), spl.k # knots, coefficients, degree of spl (15, 11, 3) >>> a = spl.antiderivative() # a is a quartic spline >>> len(a.t), len(a.c), a.k # knots, coefficients, degree of a (17, 17, 4) >>> a.c[len(a.t) - a.k - 1:] # repeat padding, unused in evaluations array([20002.23910041, 20002.23910041, 20002.23910041, 20002.23910041, 20002.23910041])
Slice off the padding to get exactly
len(a.t) - a.k - 1coefficients:>>> c = a.c[:len(a.t) - a.k - 1] >>> len(c) 12
The trimmed coefficients define the same spline, since the padding never enters evaluations. Evaluating the spline before (
a) and after (BSpline(a.t, c, a.k)) trimming on a grid of points spanning the data range gives the same values:>>> xx = np.linspace(0, 10, 51) >>> np.allclose(BSpline(a.t, c, a.k)(xx), a(xx)) True