npplus.pwpoly module¶
Piecewise polynomial interpolation and curve fitting.
This module simplifies, replaces, or enhances many scipy.interpolate programming interfaces. The interface consists of two classes, PwPoly and its periodic subclass PerPwPoly, and four functions, pline, spline, plfit, splfit. The pline and plfit functions are special cases of the general spline and splfit functions returning piecewise linear functions; spline and splfit return piecewise cubics by default, but can be used to construct piecewise polynomials of any degree.
The spline and pline functions return the interpolating function passing exactly through a given set of points. The splfit and plfit functions return the least squares best fit to a cloud of given points with given knot points (the x values separating the polynomial pieces). All four functions work for curves in multidimensional space. A quick tour of PwPoly functionality:
f = pline(x, y) # polyline through points (x, y)
g = spline(x, y) # natural cubic spline through (x, y)
f = plfit(x, xdat, ydat) # best fit polyline with knots at x
g = splfit(x, xdat, ydat) # best fit cubic spline with knots at x
f(xp) # if f from pline, same as interp(xp, x, y)
g(xp) # evaluate cubic spline at points xp
h = 2*f + g # operators +, -, * work for piecewise polynomials
xv = h.roots(value) # all xv such that h(xv) = value
dydx = h.deriv() # piecewise poly of one less degree than h
iydx = h.integ() # piecewise poly of one greater degree than h
The only common use cases for the PwPoly constructor are for making
histograms, that is, piecewise constant functions, which you do by
supplying one more or less y value than x value, and for constructing
piecewise cubic functions passing through (x,y)
with given dy/dx
:
histo = PwPoly(x, y) # y.size = x.size+1 or x.size-1
cubic = PwPoly(x, y, dydx) # x, y, dydx same size
The spline interpolation and fitting routines here use only standard numpy plus the scipy solve_banded function. The scipy.interpolate spline routines are wrappers around the old Fortran fitpack package. A key advantage of the pwpoly module is that you can mine the code here and adapt it to slightly different problems, whereas compiled fitpack code is not adaptable.
- class PerPwPoly(xk=None, *args)[source]¶
Bases:
PwPoly
Periodic piecewise polynomial function.
Like PwPoly, except first and last knot points xk are the same point, but advanced by one period. Input arguments to the function will be reduced to this period before evaluation, so there is no extrapolation.
Note that when you initialize a PerPwPoly, you must explicitly supply the duplicate final point at the end of the period.
- class PwPoly(xk=None, *args)[source]¶
Bases:
object
Piecewise polynomial function.
Typical usage:
pwp = PwPoly(xk, yk, dydxk) # define a piecewise cubic function y = pwp(x) # evaluate function at x y, dydx, d2ydx2 = pwp(x, 2) # evaluate function and 2 derivatives
The points xk are called “knot points” of the piecewise polynomial. Outside the endpoints of xk, the function will have the degree to which it is continuous at the other endpoints.
- Parameters
xk (array_like) – List of abcissa values bounding the pieces, in increasing order. As a convenience, strictly decreasing xk are also accepted.
yk (array_like) –
Each is a list of function and derivative values yk, dydxk, d2ydx2k/2, etc. corresponding to the points xk. This produces an odd degree polynomial in each interval, continuous to the specified derivatives at the xk points.
Note that when you specify derivatives higher than first, you need to divide the n-th derivative by n!. That is, you are actually furnishing the Taylor series coefficients, not the derivatives.
To get even degree polynomials, specify the final derivative with one fewer point than xk – this produces a polynomial of degree
P=2*N
continuous at xk up to the N-1 derivatives you specified at all xk points, and with the P-th (not N-th) derivative/p! equal to the final values specified.Finally, for complete generality, you can specify every argument with one more point than xk. In this case, the arguments simply become the coefficients of the polynomials in each interval with no continuity guaranteed at the xk. Note that the origin for coefficients in each interval is the first point of the interval (the smaller), except for the semi-infinite interval before the first knot point, which is relative to the first knot.
All the yk, dydxk, etc. may have a set of leading axes to define a multidimensional piecewise polynomial function of xk. That is, the interpolation direction is the last axis of xk, yk, dydxk, etc.
dydxk (array_like) –
Each is a list of function and derivative values yk, dydxk, d2ydx2k/2, etc. corresponding to the points xk. This produces an odd degree polynomial in each interval, continuous to the specified derivatives at the xk points.
Note that when you specify derivatives higher than first, you need to divide the n-th derivative by n!. That is, you are actually furnishing the Taylor series coefficients, not the derivatives.
To get even degree polynomials, specify the final derivative with one fewer point than xk – this produces a polynomial of degree
P=2*N
continuous at xk up to the N-1 derivatives you specified at all xk points, and with the P-th (not N-th) derivative/p! equal to the final values specified.Finally, for complete generality, you can specify every argument with one more point than xk. In this case, the arguments simply become the coefficients of the polynomials in each interval with no continuity guaranteed at the xk. Note that the origin for coefficients in each interval is the first point of the interval (the smaller), except for the semi-infinite interval before the first knot point, which is relative to the first knot.
All the yk, dydxk, etc. may have a set of leading axes to define a multidimensional piecewise polynomial function of xk. That is, the interpolation direction is the last axis of xk, yk, dydxk, etc.
d2ydx2k/2 (array_like) –
Each is a list of function and derivative values yk, dydxk, d2ydx2k/2, etc. corresponding to the points xk. This produces an odd degree polynomial in each interval, continuous to the specified derivatives at the xk points.
Note that when you specify derivatives higher than first, you need to divide the n-th derivative by n!. That is, you are actually furnishing the Taylor series coefficients, not the derivatives.
To get even degree polynomials, specify the final derivative with one fewer point than xk – this produces a polynomial of degree
P=2*N
continuous at xk up to the N-1 derivatives you specified at all xk points, and with the P-th (not N-th) derivative/p! equal to the final values specified.Finally, for complete generality, you can specify every argument with one more point than xk. In this case, the arguments simply become the coefficients of the polynomials in each interval with no continuity guaranteed at the xk. Note that the origin for coefficients in each interval is the first point of the interval (the smaller), except for the semi-infinite interval before the first knot point, which is relative to the first knot.
All the yk, dydxk, etc. may have a set of leading axes to define a multidimensional piecewise polynomial function of xk. That is, the interpolation direction is the last axis of xk, yk, dydxk, etc.
... (array_like) –
Each is a list of function and derivative values yk, dydxk, d2ydx2k/2, etc. corresponding to the points xk. This produces an odd degree polynomial in each interval, continuous to the specified derivatives at the xk points.
Note that when you specify derivatives higher than first, you need to divide the n-th derivative by n!. That is, you are actually furnishing the Taylor series coefficients, not the derivatives.
To get even degree polynomials, specify the final derivative with one fewer point than xk – this produces a polynomial of degree
P=2*N
continuous at xk up to the N-1 derivatives you specified at all xk points, and with the P-th (not N-th) derivative/p! equal to the final values specified.Finally, for complete generality, you can specify every argument with one more point than xk. In this case, the arguments simply become the coefficients of the polynomials in each interval with no continuity guaranteed at the xk. Note that the origin for coefficients in each interval is the first point of the interval (the smaller), except for the semi-infinite interval before the first knot point, which is relative to the first knot.
All the yk, dydxk, etc. may have a set of leading axes to define a multidimensional piecewise polynomial function of xk. That is, the interpolation direction is the last axis of xk, yk, dydxk, etc.
- xk¶
1D array of knot points in strictly increasing order.
- Type
ndarray
- c¶
Coefficient array. Axes are
(degree, dimensionality, knots+1)
The polynomial coefficients are for the polynomial in(x-xk[i-1])
, wherexk[i-1] <= x < xk[i]
, except forc[...,0]
, which likec[...,1]
is for the polynomial in(x-xk[0])
. Coefficients are in order of increasing powers of x.- Type
ndarray
See also
Notes
Let p and q be PwPoly instances. The following operators work:
p(x)
Evaluate p at x, returning array of same shape as x. If p is multidimensional, its additional dimensions are leading dimensions of the result.
p+q, p-q, -p, p*q
Return a new PwPoly instance. If p and q have different xk, result the union of the two xk. Either p or q may be scalars (or arrays same shape as
p(0)
). For array_like q, division p/q also works.p[i]
Components of p, only for multidimensional p.
len(p)
First dimension length of p, only for multidimensional p.
The PwPoly constructor produces a smooth fit that is local, in the sense that the function in the interval between consecutive knot points depends only on the given function and derivative values at the interval endpoints.
Use the spline function to construct a PwPoly which is smoother (for a given degree) by using the function values you provide at all the knot points to determine the function within each interval. The splfit function constructs a PwPoly that is the statistical best fit to a cloud of data points you provide.
The pline and plfit functions are piecewise linear variants of spline and splfit.
PwPoly is intended for low degree polynomials, usually degree 1 and 3. It should work tolerably well at or below degree 7, but roundoff errors will become significant at higher degree. To get a better fit with PwPoly, use more knots, not higher degree.
PwPoly(x, y)
where y has one more or one less element than x produces a histogram, that is, a piecewise polynomial of degree zero. This is probably the only useful application of the PwPoly constructor to produce a PwPoly of even degree. For other even degree piecewise polynomials, you probably want to use spline or splfit.- addknots(xk, _nocheck=False)[source]¶
Return a new PwPoly with knot points xk that matches this one.
The xk must be a superset of the existing knot points for this to work as intended.
- allknots(*args, **kwargs)[source]¶
Return union of knot points among piecewise polynomials.
- Parameters
- Returns
xk – 1D union of knot points in increasing order.
- Return type
ndarray
- property deg¶
Highest power of the piecewise polynomial as a property.
- integ(m=1, k=(), lbnd=0)[source]¶
Integral as a new piecewise polynomial.
- Parameters
m (int, optional) – The number of integrations to perform, default 1.
k (array_like, optional) – Integration constants. The first constant is applied to the first integration, the second to the second, and so on. The list of values must less than or equal to m in length and any missing values are set to zero.
lbnd (float, optional) – The lower bound of the definite integral, default 0. The integration constant k is the value of the integral at
x = lbnd
, where x is the independent variable of the piecewise polynomial.
- Returns
The integral of the PwPoly.
- Return type
- jumps(n=None)[source]¶
Return jumps in polynomial coefficients at the knot points.
- Parameters
n (int, optional) – Maximum degree of returned coefficients, all by default.
- Returns
dc – Shape is
(n, ..., K)
where K is number of knot points. Degree is first axis,dc[0]
is jump in function value,dc[1]
is jump in derivative,dc[2]
is half the jump in second derivative, and so on. Knot is final axis. Any additional axes are the dimensionality of the PwPoly.- Return type
ndarray
- property ndim¶
Number of dimensions of result when evaluated at a scalar x.
- classmethod new(xk, c)[source]¶
Make a new PwPoly with given knots and coefficients.
- Parameters
xk (ndarray, shape (K) or (K+1)) –
c (ndarray, shape (N, ..., K+1)) –
- Returns
p – The new PwPoly.
- Return type
PwPoly or a subclass
Notes
If
xk.size
is K+1, xk will not be copied. Ifxk.size
is K,xk[0]
will be duplicated. The coefficient array c is always used uncopied. No error checking is done; this is a low level method for creating PwPoly results, not a user interface.
- reknot(xk, n=None)[source]¶
Return a new PwPoly with knot points xk that approximates this one.
If n is the polynomial degree, the resulting piecewise polynomial will match
(n-1)/2
derivatives of the old one at the points xk. If n is even, the n-th derivative at the midpoint of each xk interval will also match the original.
- roots(value=0.0, tol=1e-09)[source]¶
Return the values of x for which the piecewise polynomial is zero.
Only works for scalar PwPoly.
- Parameters
value (float, optional) – Return values of x for which piecewise polynomial equals value. Defaults to 0.0.
- Returns
1D array of x values where this PwPoly evaluates to value.
- Return type
ndarray
- property shape¶
Shape of result when evaluated at a scalar x.
- plfit(xk, x, y, sigy=None, lo=(), hi=(), per=False, extrap=None, solver=<function _plfitter>, **kwargs)[source]¶
Return best fit linear PwPoly with knots xk to given points (x,y).
Gives the same fit as
splfit(xk, x, y, n=1, nc=0)
, that is, the best fit piecewise polynomial through(x,y)
with knots xk. See splfit documentation for detailed description of the common parameters. If you need the cost of continuity constraints, use splfit instead.See also
splfit
general PwPoly spline fitting function
- pline(x, y, extrap=None, per=False)[source]¶
Return a piecewise linear function through given points (x,y).
Convenience shorthand for
spline(x, y, n=1)
, intended as a more general version of the interp function with a slightly different interface:pline(x, y)(xp) <---> interp(xp, x, y)
But pline permits y to have additional dimensions and x can be a decreasing series.
Note that
pline(x, y)
by default is constant before the first x and after the final x. Usepline(x, y, 1)
to extrapolate using the linear function in the first and last intervals.See also
spline
general PwPoly spline interpolation function
- splfit(xk, x, y, sigy=None, n=3, nc=None, lo=(), hi=(), per=False, extrap=None, cost=None)[source]¶
Return the best fit PwPoly with knots xk to given points (x,y).
- Parameters
xk (1D array_like) – Knot points of the PwPoly, sparse enough that there are some x values “near” each interval of xk. The xk must be strictly monotonic.
x (array_like) –
Cloud of points to fit. If f is the returned PwPoly,
chi2 = sum(((f(x) - y)/sigy)**2)
will be minimum for the given PwPoly knot points xk, degree n, and boundary constraints. The y array must have the same or conformable trailing dimensions as x. However, y may have additional leading dimensions to produce a multi-dimensional PwPoly curve. In this case, the chi2 sum extends over all the leading dimensions for each point. The order of the
(x,y)
points is irrelevant; indeed x need not be a 1D array.y (array_like) –
Cloud of points to fit. If f is the returned PwPoly,
chi2 = sum(((f(x) - y)/sigy)**2)
will be minimum for the given PwPoly knot points xk, degree n, and boundary constraints. The y array must have the same or conformable trailing dimensions as x. However, y may have additional leading dimensions to produce a multi-dimensional PwPoly curve. In this case, the chi2 sum extends over all the leading dimensions for each point. The order of the
(x,y)
points is irrelevant; indeed x need not be a 1D array.sigy (array_like, optional) – Standard deviations of y, must be conformable to y, default 1.
n (int, optional) – The degree of the PwPoly, default 3 (piecewise cubic).
nc (int, optional) – The degree to which the result PwPoly is continuous, default n-1 (that is, the PwPoly is a spline of degree n). Note that a smaller value of nc requires more
(x,y)
points per xk interval.lo (tuple of array_like, optional) – Boundary conditions at the endpoints
xk[0]
andxk[-1]
. Each tuple represents the values of(y, dydx, d2ydx2/2, d3ydx3/6, ...)
atxk[0]
for lo orxk[-1]
for hi. Use None for a derivative to be not specified. See the docstring for spline for details; however, note that the lo and hi tuples for splfit begin with the function value (zero-th derivative), while the lo and hi tuples for spline begin with the first derivative.hi (tuple of array_like, optional) – Boundary conditions at the endpoints
xk[0]
andxk[-1]
. Each tuple represents the values of(y, dydx, d2ydx2/2, d3ydx3/6, ...)
atxk[0]
for lo orxk[-1]
for hi. Use None for a derivative to be not specified. See the docstring for spline for details; however, note that the lo and hi tuples for splfit begin with the function value (zero-th derivative), while the lo and hi tuples for spline begin with the first derivative.per (bool) – True to make all derivatives match at first and last points of xk. This produces a PerPwPoly function, which maps any inputs outside the first and last points of xk into that interval.
extrap (int or (int,int)) – Degree to maintain continuity beyond endpoints, can be set separately for before first and after last interval.
cost (bool, optional) – Set True to return cost array continuity of various degrees.
- Returns
fit (PwPoly) – The best fit to the given
(x,y)
with the given knots xk.cost (tuple of ndarray) – This return is only present with
cost=1
parameter. The Lagrange multipliers used to enforce the chi2 minimization constraints associated with the continuous function values and nc derivative values, plus any additional boundary condition constraints you specified with the lo or hi keywords. The interior knot point constraints arecost[0]
for function continuity,cost[1]
for first derivative continuity, throughcost[nc]
for nc-derivative continuity. Thencost[nc+1:nc+1+nlo]
are the costs of the lo constraints andcost[nc+1+nlo:]
are the costs of the hi constraints, wherenlo=len(lo)
.The shape of each of the
cost[:nc+1]
interior constraints isy[...,1:-1].shape
, that is, any leading dimensions of y followed by the number of interior knot points where the constraints apply. The shape of each of thecost[nc+1:]
boundary constraints isy[...,0].shape
, that is, any leading dimensions of y.
See also
Notes
The cost values require a bit more explanation. Each interior constraint is schematically
c[this] - l2r.dot(c[prev]) = 0
where l2r is the linear transformation mapping the polynomial coefficients c[prev] in the interval to the left to their values atxk[this]
knot. That is, each interior constraint is that the jump in the value of the polynomial coefficient of some degree be zero. The cost is defined to be the partial derivative of chi2 with respect to that jump. In other words, if we relaxed just that one constraint and allowed a jump of dc, chi2 would change bycost*dc
. We keep this sign convention for the lo and hi constraints as well – a positive cost means that if the coefficient changes by a positive amount for increasing x across the knot, then chi2 will increase.
- spline(x, y, n=3, lo=(), hi=(), per=False, extrap=None)[source]¶
Construct a PwPoly as a spline through given points (x,y).
A spline is a piecewise polynomial of degree n (default 3) passing through all of the given points with continuous derivatives up to degree n-1 at every point. Before
x[0]
and afterx[-1]
, the result will be of degree n-1, maintaining continuity of n-1 derivatives at every knot point, including the first and last.- Parameters
x (array_like) – 1D array of knot points, strictly monotonic.
y (array_like) – The given
(x,y)
data points to be fit. The y data may have additional leading dimensions, in order to fit a curve in a multi-dimensional space.n (int, optional) – The degree of the PwPoly. Defaults to 3, a piecewise cubic spline.
lo (tuple of array_like, optional) –
Boundary conditions at the endpoints
x[0]
andx[-1]
. Each tuple represents the values of(dydx, d2ydx2/2, d3ydx3/6, ...)
atx[0]
for lo orx[-1]
for hi. Use None for a derivative to be not specified. The derivatives are broadcast to any leading dimensions of y if necessary.The highest derivative you can specify is n-1, that is d2ydx2/2 for a cubic spline, dydx for a quadratic spline, and so on. For the special case that you only wish to specify dydx at an endpoint, lo or hi need not be a tuple
(dydx,)
; spline accepts simply dydx to mean(dydx, None, None, ...)
. The maximum number of derivatives you can specify in both lo and hi is n-1, that is, 2 for a cubic spline, 4 for a pentic, and so on. If you specify fewer than n-1 derivatives, spline will set the highest unspecified derivatives to zero, begining with lo and alternating lo, hi, lo, etc., until n-1 derivative are specified. For example, if you specify neither lo nor hi for a cubic spline, then spline setsd2ydx2=0
at both endpoints, and the natural spline with zero curvature at the endpoints is the result. This is equivalent tolo=(None,0.)
,hi=(None,0.)
.hi (tuple of array_like, optional) –
Boundary conditions at the endpoints
x[0]
andx[-1]
. Each tuple represents the values of(dydx, d2ydx2/2, d3ydx3/6, ...)
atx[0]
for lo orx[-1]
for hi. Use None for a derivative to be not specified. The derivatives are broadcast to any leading dimensions of y if necessary.The highest derivative you can specify is n-1, that is d2ydx2/2 for a cubic spline, dydx for a quadratic spline, and so on. For the special case that you only wish to specify dydx at an endpoint, lo or hi need not be a tuple
(dydx,)
; spline accepts simply dydx to mean(dydx, None, None, ...)
. The maximum number of derivatives you can specify in both lo and hi is n-1, that is, 2 for a cubic spline, 4 for a pentic, and so on. If you specify fewer than n-1 derivatives, spline will set the highest unspecified derivatives to zero, begining with lo and alternating lo, hi, lo, etc., until n-1 derivative are specified. For example, if you specify neither lo nor hi for a cubic spline, then spline setsd2ydx2=0
at both endpoints, and the natural spline with zero curvature at the endpoints is the result. This is equivalent tolo=(None,0.)
,hi=(None,0.)
.per (bool) – True to make all derivatives match at first and last points of x. This produces a PerPwPoly function, which maps any inputs outside the first and last points of x into that interval.
extrap (int or (int, int)) – Degree to maintain continuity beyond endpoints, can be set separately for before first and after last interval.
See also
Notes
The K knots define K-1 intervals, requiring a total of
(n+1)*(K-1)=n*K-n+K-1
polynomial coefficients. There aren*(K-2)
continuity constraints at the interior knots and K y values, for a total ofn*K-2*n+K
constraint equations. We require n-1 additional constraints to determine a unique spline fit. When n is odd (linear, cubic, pentic, etc.), these additional constraints may be divided equally between the first and last knots points. When n is even, there is no way to treat the first and last knots symmetrically.By default, spline forces the
(n-1)//2
highest derivatives to zero at each endpoint, with the first endpoint getting an extra zero derivative in the case of even n. The lo and hi keywords allow you to split up the n-1 constraints among the possible derivatives and endpoints however you wish.