Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
190
venv/Lib/site-packages/scipy/interpolate/__init__.py
Normal file
190
venv/Lib/site-packages/scipy/interpolate/__init__.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
"""
|
||||
========================================
|
||||
Interpolation (:mod:`scipy.interpolate`)
|
||||
========================================
|
||||
|
||||
.. currentmodule:: scipy.interpolate
|
||||
|
||||
Sub-package for objects used in interpolation.
|
||||
|
||||
As listed below, this sub-package contains spline functions and classes,
|
||||
1-D and multidimensional (univariate and multivariate)
|
||||
interpolation classes, Lagrange and Taylor polynomial interpolators, and
|
||||
wrappers for `FITPACK <http://www.netlib.org/dierckx/>`__
|
||||
and DFITPACK functions.
|
||||
|
||||
Univariate interpolation
|
||||
========================
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
interp1d
|
||||
BarycentricInterpolator
|
||||
KroghInterpolator
|
||||
barycentric_interpolate
|
||||
krogh_interpolate
|
||||
pchip_interpolate
|
||||
CubicHermiteSpline
|
||||
PchipInterpolator
|
||||
Akima1DInterpolator
|
||||
CubicSpline
|
||||
PPoly
|
||||
BPoly
|
||||
|
||||
|
||||
Multivariate interpolation
|
||||
==========================
|
||||
|
||||
Unstructured data:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
griddata
|
||||
LinearNDInterpolator
|
||||
NearestNDInterpolator
|
||||
CloughTocher2DInterpolator
|
||||
Rbf
|
||||
interp2d
|
||||
|
||||
For data on a grid:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
interpn
|
||||
RegularGridInterpolator
|
||||
RectBivariateSpline
|
||||
|
||||
.. seealso::
|
||||
|
||||
`scipy.ndimage.map_coordinates`
|
||||
|
||||
Tensor product polynomials:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
NdPPoly
|
||||
|
||||
|
||||
1-D Splines
|
||||
===========
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
BSpline
|
||||
make_interp_spline
|
||||
make_lsq_spline
|
||||
|
||||
Functional interface to FITPACK routines:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
splrep
|
||||
splprep
|
||||
splev
|
||||
splint
|
||||
sproot
|
||||
spalde
|
||||
splder
|
||||
splantider
|
||||
insert
|
||||
|
||||
Object-oriented FITPACK interface:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
UnivariateSpline
|
||||
InterpolatedUnivariateSpline
|
||||
LSQUnivariateSpline
|
||||
|
||||
|
||||
|
||||
2-D Splines
|
||||
===========
|
||||
|
||||
For data on a grid:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
RectBivariateSpline
|
||||
RectSphereBivariateSpline
|
||||
|
||||
For unstructured data:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
BivariateSpline
|
||||
SmoothBivariateSpline
|
||||
SmoothSphereBivariateSpline
|
||||
LSQBivariateSpline
|
||||
LSQSphereBivariateSpline
|
||||
|
||||
Low-level interface to FITPACK functions:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
bisplrep
|
||||
bisplev
|
||||
|
||||
Additional tools
|
||||
================
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
lagrange
|
||||
approximate_taylor_polynomial
|
||||
pade
|
||||
|
||||
.. seealso::
|
||||
|
||||
`scipy.ndimage.map_coordinates`,
|
||||
`scipy.ndimage.spline_filter`,
|
||||
`scipy.signal.resample`,
|
||||
`scipy.signal.bspline`,
|
||||
`scipy.signal.gauss_spline`,
|
||||
`scipy.signal.qspline1d`,
|
||||
`scipy.signal.cspline1d`,
|
||||
`scipy.signal.qspline1d_eval`,
|
||||
`scipy.signal.cspline1d_eval`,
|
||||
`scipy.signal.qspline2d`,
|
||||
`scipy.signal.cspline2d`.
|
||||
|
||||
``pchip`` is an alias of `PchipInterpolator` for backward compatibility
|
||||
(should not be used in new code).
|
||||
"""
|
||||
from .interpolate import *
|
||||
from .fitpack import *
|
||||
|
||||
# New interface to fitpack library:
|
||||
from .fitpack2 import *
|
||||
|
||||
from .rbf import Rbf
|
||||
|
||||
from .polyint import *
|
||||
|
||||
from ._cubic import *
|
||||
|
||||
from .ndgriddata import *
|
||||
|
||||
from ._bsplines import *
|
||||
|
||||
from ._pade import *
|
||||
|
||||
__all__ = [s for s in dir() if not s.startswith('_')]
|
||||
|
||||
from scipy._lib._testutils import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
del PytestTester
|
||||
|
||||
# Backward compatibility
|
||||
pchip = PchipInterpolator
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/interpolate/_bspl.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/_bspl.cp36-win32.pyd
Normal file
Binary file not shown.
1009
venv/Lib/site-packages/scipy/interpolate/_bsplines.py
Normal file
1009
venv/Lib/site-packages/scipy/interpolate/_bsplines.py
Normal file
File diff suppressed because it is too large
Load diff
847
venv/Lib/site-packages/scipy/interpolate/_cubic.py
Normal file
847
venv/Lib/site-packages/scipy/interpolate/_cubic.py
Normal file
|
@ -0,0 +1,847 @@
|
|||
"""Interpolation algorithms using piecewise cubic polynomials."""
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import PPoly
|
||||
from .polyint import _isscalar
|
||||
from scipy.linalg import solve_banded, solve
|
||||
|
||||
|
||||
__all__ = ["CubicHermiteSpline", "PchipInterpolator", "pchip_interpolate",
|
||||
"Akima1DInterpolator", "CubicSpline"]
|
||||
|
||||
|
||||
def prepare_input(x, y, axis, dydx=None):
|
||||
"""Prepare input for cubic spline interpolators.
|
||||
|
||||
All data are converted to numpy arrays and checked for correctness.
|
||||
Axes equal to `axis` of arrays `y` and `dydx` are rolled to be the 0th
|
||||
axis. The value of `axis` is converted to lie in
|
||||
[0, number of dimensions of `y`).
|
||||
"""
|
||||
|
||||
x, y = map(np.asarray, (x, y))
|
||||
if np.issubdtype(x.dtype, np.complexfloating):
|
||||
raise ValueError("`x` must contain real values.")
|
||||
x = x.astype(float)
|
||||
|
||||
if np.issubdtype(y.dtype, np.complexfloating):
|
||||
dtype = complex
|
||||
else:
|
||||
dtype = float
|
||||
|
||||
if dydx is not None:
|
||||
dydx = np.asarray(dydx)
|
||||
if y.shape != dydx.shape:
|
||||
raise ValueError("The shapes of `y` and `dydx` must be identical.")
|
||||
if np.issubdtype(dydx.dtype, np.complexfloating):
|
||||
dtype = complex
|
||||
dydx = dydx.astype(dtype, copy=False)
|
||||
|
||||
y = y.astype(dtype, copy=False)
|
||||
axis = axis % y.ndim
|
||||
if x.ndim != 1:
|
||||
raise ValueError("`x` must be 1-dimensional.")
|
||||
if x.shape[0] < 2:
|
||||
raise ValueError("`x` must contain at least 2 elements.")
|
||||
if x.shape[0] != y.shape[axis]:
|
||||
raise ValueError("The length of `y` along `axis`={0} doesn't "
|
||||
"match the length of `x`".format(axis))
|
||||
|
||||
if not np.all(np.isfinite(x)):
|
||||
raise ValueError("`x` must contain only finite values.")
|
||||
if not np.all(np.isfinite(y)):
|
||||
raise ValueError("`y` must contain only finite values.")
|
||||
|
||||
if dydx is not None and not np.all(np.isfinite(dydx)):
|
||||
raise ValueError("`dydx` must contain only finite values.")
|
||||
|
||||
dx = np.diff(x)
|
||||
if np.any(dx <= 0):
|
||||
raise ValueError("`x` must be strictly increasing sequence.")
|
||||
|
||||
y = np.rollaxis(y, axis)
|
||||
if dydx is not None:
|
||||
dydx = np.rollaxis(dydx, axis)
|
||||
|
||||
return x, dx, y, axis, dydx
|
||||
|
||||
|
||||
class CubicHermiteSpline(PPoly):
|
||||
"""Piecewise-cubic interpolator matching values and first derivatives.
|
||||
|
||||
The result is represented as a `PPoly` instance.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like, shape (n,)
|
||||
1-D array containing values of the independent variable.
|
||||
Values must be real, finite and in strictly increasing order.
|
||||
y : array_like
|
||||
Array containing values of the dependent variable. It can have
|
||||
arbitrary number of dimensions, but the length along ``axis``
|
||||
(see below) must match the length of ``x``. Values must be finite.
|
||||
dydx : array_like
|
||||
Array containing derivatives of the dependent variable. It can have
|
||||
arbitrary number of dimensions, but the length along ``axis``
|
||||
(see below) must match the length of ``x``. Values must be finite.
|
||||
axis : int, optional
|
||||
Axis along which `y` is assumed to be varying. Meaning that for
|
||||
``x[i]`` the corresponding values are ``np.take(y, i, axis=axis)``.
|
||||
Default is 0.
|
||||
extrapolate : {bool, 'periodic', None}, optional
|
||||
If bool, determines whether to extrapolate to out-of-bounds points
|
||||
based on first and last intervals, or to return NaNs. If 'periodic',
|
||||
periodic extrapolation is used. If None (default), it is set to True.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x : ndarray, shape (n,)
|
||||
Breakpoints. The same ``x`` which was passed to the constructor.
|
||||
c : ndarray, shape (4, n-1, ...)
|
||||
Coefficients of the polynomials on each segment. The trailing
|
||||
dimensions match the dimensions of `y`, excluding ``axis``.
|
||||
For example, if `y` is 1-D, then ``c[k, i]`` is a coefficient for
|
||||
``(x-x[i])**(3-k)`` on the segment between ``x[i]`` and ``x[i+1]``.
|
||||
axis : int
|
||||
Interpolation axis. The same axis which was passed to the
|
||||
constructor.
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
derivative
|
||||
antiderivative
|
||||
integrate
|
||||
roots
|
||||
|
||||
See Also
|
||||
--------
|
||||
Akima1DInterpolator : Akima 1D interpolator.
|
||||
PchipInterpolator : PCHIP 1-D monotonic cubic interpolator.
|
||||
CubicSpline : Cubic spline data interpolator.
|
||||
PPoly : Piecewise polynomial in terms of coefficients and breakpoints
|
||||
|
||||
Notes
|
||||
-----
|
||||
If you want to create a higher-order spline matching higher-order
|
||||
derivatives, use `BPoly.from_derivatives`.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] `Cubic Hermite spline
|
||||
<https://en.wikipedia.org/wiki/Cubic_Hermite_spline>`_
|
||||
on Wikipedia.
|
||||
"""
|
||||
def __init__(self, x, y, dydx, axis=0, extrapolate=None):
|
||||
if extrapolate is None:
|
||||
extrapolate = True
|
||||
|
||||
x, dx, y, axis, dydx = prepare_input(x, y, axis, dydx)
|
||||
|
||||
dxr = dx.reshape([dx.shape[0]] + [1] * (y.ndim - 1))
|
||||
slope = np.diff(y, axis=0) / dxr
|
||||
t = (dydx[:-1] + dydx[1:] - 2 * slope) / dxr
|
||||
|
||||
c = np.empty((4, len(x) - 1) + y.shape[1:], dtype=t.dtype)
|
||||
c[0] = t / dxr
|
||||
c[1] = (slope - dydx[:-1]) / dxr - t
|
||||
c[2] = dydx[:-1]
|
||||
c[3] = y[:-1]
|
||||
|
||||
super(CubicHermiteSpline, self).__init__(c, x, extrapolate=extrapolate)
|
||||
self.axis = axis
|
||||
|
||||
|
||||
class PchipInterpolator(CubicHermiteSpline):
|
||||
r"""PCHIP 1-D monotonic cubic interpolation.
|
||||
|
||||
``x`` and ``y`` are arrays of values used to approximate some function f,
|
||||
with ``y = f(x)``. The interpolant uses monotonic cubic splines
|
||||
to find the value of new points. (PCHIP stands for Piecewise Cubic
|
||||
Hermite Interpolating Polynomial).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : ndarray
|
||||
A 1-D array of monotonically increasing real values. ``x`` cannot
|
||||
include duplicate values (otherwise f is overspecified)
|
||||
y : ndarray
|
||||
A 1-D array of real values. ``y``'s length along the interpolation
|
||||
axis must be equal to the length of ``x``. If N-D array, use ``axis``
|
||||
parameter to select correct axis.
|
||||
axis : int, optional
|
||||
Axis in the y array corresponding to the x-coordinate values.
|
||||
extrapolate : bool, optional
|
||||
Whether to extrapolate to out-of-bounds points based on first
|
||||
and last intervals, or to return NaNs.
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
derivative
|
||||
antiderivative
|
||||
roots
|
||||
|
||||
See Also
|
||||
--------
|
||||
CubicHermiteSpline : Piecewise-cubic interpolator.
|
||||
Akima1DInterpolator : Akima 1D interpolator.
|
||||
CubicSpline : Cubic spline data interpolator.
|
||||
PPoly : Piecewise polynomial in terms of coefficients and breakpoints.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The interpolator preserves monotonicity in the interpolation data and does
|
||||
not overshoot if the data is not smooth.
|
||||
|
||||
The first derivatives are guaranteed to be continuous, but the second
|
||||
derivatives may jump at :math:`x_k`.
|
||||
|
||||
Determines the derivatives at the points :math:`x_k`, :math:`f'_k`,
|
||||
by using PCHIP algorithm [1]_.
|
||||
|
||||
Let :math:`h_k = x_{k+1} - x_k`, and :math:`d_k = (y_{k+1} - y_k) / h_k`
|
||||
are the slopes at internal points :math:`x_k`.
|
||||
If the signs of :math:`d_k` and :math:`d_{k-1}` are different or either of
|
||||
them equals zero, then :math:`f'_k = 0`. Otherwise, it is given by the
|
||||
weighted harmonic mean
|
||||
|
||||
.. math::
|
||||
|
||||
\frac{w_1 + w_2}{f'_k} = \frac{w_1}{d_{k-1}} + \frac{w_2}{d_k}
|
||||
|
||||
where :math:`w_1 = 2 h_k + h_{k-1}` and :math:`w_2 = h_k + 2 h_{k-1}`.
|
||||
|
||||
The end slopes are set using a one-sided scheme [2]_.
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] F. N. Fritsch and R. E. Carlson, Monotone Piecewise Cubic Interpolation,
|
||||
SIAM J. Numer. Anal., 17(2), 238 (1980).
|
||||
:doi:`10.1137/0717021`.
|
||||
.. [2] see, e.g., C. Moler, Numerical Computing with Matlab, 2004.
|
||||
:doi:`10.1137/1.9780898717952`
|
||||
|
||||
|
||||
"""
|
||||
def __init__(self, x, y, axis=0, extrapolate=None):
|
||||
x, _, y, axis, _ = prepare_input(x, y, axis)
|
||||
xp = x.reshape((x.shape[0],) + (1,)*(y.ndim-1))
|
||||
dk = self._find_derivatives(xp, y)
|
||||
super(PchipInterpolator, self).__init__(x, y, dk, axis=0,
|
||||
extrapolate=extrapolate)
|
||||
self.axis = axis
|
||||
|
||||
@staticmethod
|
||||
def _edge_case(h0, h1, m0, m1):
|
||||
# one-sided three-point estimate for the derivative
|
||||
d = ((2*h0 + h1)*m0 - h0*m1) / (h0 + h1)
|
||||
|
||||
# try to preserve shape
|
||||
mask = np.sign(d) != np.sign(m0)
|
||||
mask2 = (np.sign(m0) != np.sign(m1)) & (np.abs(d) > 3.*np.abs(m0))
|
||||
mmm = (~mask) & mask2
|
||||
|
||||
d[mask] = 0.
|
||||
d[mmm] = 3.*m0[mmm]
|
||||
|
||||
return d
|
||||
|
||||
@staticmethod
|
||||
def _find_derivatives(x, y):
|
||||
# Determine the derivatives at the points y_k, d_k, by using
|
||||
# PCHIP algorithm is:
|
||||
# We choose the derivatives at the point x_k by
|
||||
# Let m_k be the slope of the kth segment (between k and k+1)
|
||||
# If m_k=0 or m_{k-1}=0 or sgn(m_k) != sgn(m_{k-1}) then d_k == 0
|
||||
# else use weighted harmonic mean:
|
||||
# w_1 = 2h_k + h_{k-1}, w_2 = h_k + 2h_{k-1}
|
||||
# 1/d_k = 1/(w_1 + w_2)*(w_1 / m_k + w_2 / m_{k-1})
|
||||
# where h_k is the spacing between x_k and x_{k+1}
|
||||
y_shape = y.shape
|
||||
if y.ndim == 1:
|
||||
# So that _edge_case doesn't end up assigning to scalars
|
||||
x = x[:, None]
|
||||
y = y[:, None]
|
||||
|
||||
hk = x[1:] - x[:-1]
|
||||
mk = (y[1:] - y[:-1]) / hk
|
||||
|
||||
if y.shape[0] == 2:
|
||||
# edge case: only have two points, use linear interpolation
|
||||
dk = np.zeros_like(y)
|
||||
dk[0] = mk
|
||||
dk[1] = mk
|
||||
return dk.reshape(y_shape)
|
||||
|
||||
smk = np.sign(mk)
|
||||
condition = (smk[1:] != smk[:-1]) | (mk[1:] == 0) | (mk[:-1] == 0)
|
||||
|
||||
w1 = 2*hk[1:] + hk[:-1]
|
||||
w2 = hk[1:] + 2*hk[:-1]
|
||||
|
||||
# values where division by zero occurs will be excluded
|
||||
# by 'condition' afterwards
|
||||
with np.errstate(divide='ignore'):
|
||||
whmean = (w1/mk[:-1] + w2/mk[1:]) / (w1 + w2)
|
||||
|
||||
dk = np.zeros_like(y)
|
||||
dk[1:-1][condition] = 0.0
|
||||
dk[1:-1][~condition] = 1.0 / whmean[~condition]
|
||||
|
||||
# special case endpoints, as suggested in
|
||||
# Cleve Moler, Numerical Computing with MATLAB, Chap 3.4
|
||||
dk[0] = PchipInterpolator._edge_case(hk[0], hk[1], mk[0], mk[1])
|
||||
dk[-1] = PchipInterpolator._edge_case(hk[-1], hk[-2], mk[-1], mk[-2])
|
||||
|
||||
return dk.reshape(y_shape)
|
||||
|
||||
|
||||
def pchip_interpolate(xi, yi, x, der=0, axis=0):
|
||||
"""
|
||||
Convenience function for pchip interpolation.
|
||||
|
||||
xi and yi are arrays of values used to approximate some function f,
|
||||
with ``yi = f(xi)``. The interpolant uses monotonic cubic splines
|
||||
to find the value of new points x and the derivatives there.
|
||||
|
||||
See `scipy.interpolate.PchipInterpolator` for details.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like
|
||||
A sorted list of x-coordinates, of length N.
|
||||
yi : array_like
|
||||
A 1-D array of real values. `yi`'s length along the interpolation
|
||||
axis must be equal to the length of `xi`. If N-D array, use axis
|
||||
parameter to select correct axis.
|
||||
x : scalar or array_like
|
||||
Of length M.
|
||||
der : int or list, optional
|
||||
Derivatives to extract. The 0th derivative can be included to
|
||||
return the function value.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
See Also
|
||||
--------
|
||||
PchipInterpolator : PCHIP 1-D monotonic cubic interpolator.
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : scalar or array_like
|
||||
The result, of length R or length M or M by R,
|
||||
|
||||
Examples
|
||||
--------
|
||||
We can interpolate 2D observed data using pchip interpolation:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> from scipy.interpolate import pchip_interpolate
|
||||
>>> x_observed = np.linspace(0.0, 10.0, 11)
|
||||
>>> y_observed = np.sin(x_observed)
|
||||
>>> x = np.linspace(min(x_observed), max(x_observed), num=100)
|
||||
>>> y = pchip_interpolate(x_observed, y_observed, x)
|
||||
>>> plt.plot(x_observed, y_observed, "o", label="observation")
|
||||
>>> plt.plot(x, y, label="pchip interpolation")
|
||||
>>> plt.legend()
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
P = PchipInterpolator(xi, yi, axis=axis)
|
||||
|
||||
if der == 0:
|
||||
return P(x)
|
||||
elif _isscalar(der):
|
||||
return P.derivative(der)(x)
|
||||
else:
|
||||
return [P.derivative(nu)(x) for nu in der]
|
||||
|
||||
|
||||
class Akima1DInterpolator(CubicHermiteSpline):
|
||||
"""
|
||||
Akima interpolator
|
||||
|
||||
Fit piecewise cubic polynomials, given vectors x and y. The interpolation
|
||||
method by Akima uses a continuously differentiable sub-spline built from
|
||||
piecewise cubic polynomials. The resultant curve passes through the given
|
||||
data points and will appear smooth and natural.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : ndarray, shape (m, )
|
||||
1-D array of monotonically increasing real values.
|
||||
y : ndarray, shape (m, ...)
|
||||
N-D array of real values. The length of ``y`` along the first axis
|
||||
must be equal to the length of ``x``.
|
||||
axis : int, optional
|
||||
Specifies the axis of ``y`` along which to interpolate. Interpolation
|
||||
defaults to the first axis of ``y``.
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
derivative
|
||||
antiderivative
|
||||
roots
|
||||
|
||||
See Also
|
||||
--------
|
||||
PchipInterpolator : PCHIP 1-D monotonic cubic interpolator.
|
||||
CubicSpline : Cubic spline data interpolator.
|
||||
PPoly : Piecewise polynomial in terms of coefficients and breakpoints
|
||||
|
||||
Notes
|
||||
-----
|
||||
.. versionadded:: 0.14
|
||||
|
||||
Use only for precise data, as the fitted curve passes through the given
|
||||
points exactly. This routine is useful for plotting a pleasingly smooth
|
||||
curve through a few given points for purposes of plotting.
|
||||
|
||||
References
|
||||
----------
|
||||
[1] A new method of interpolation and smooth curve fitting based
|
||||
on local procedures. Hiroshi Akima, J. ACM, October 1970, 17(4),
|
||||
589-602.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, x, y, axis=0):
|
||||
# Original implementation in MATLAB by N. Shamsundar (BSD licensed), see
|
||||
# https://www.mathworks.com/matlabcentral/fileexchange/1814-akima-interpolation
|
||||
x, dx, y, axis, _ = prepare_input(x, y, axis)
|
||||
# determine slopes between breakpoints
|
||||
m = np.empty((x.size + 3, ) + y.shape[1:])
|
||||
dx = dx[(slice(None), ) + (None, ) * (y.ndim - 1)]
|
||||
m[2:-2] = np.diff(y, axis=0) / dx
|
||||
|
||||
# add two additional points on the left ...
|
||||
m[1] = 2. * m[2] - m[3]
|
||||
m[0] = 2. * m[1] - m[2]
|
||||
# ... and on the right
|
||||
m[-2] = 2. * m[-3] - m[-4]
|
||||
m[-1] = 2. * m[-2] - m[-3]
|
||||
|
||||
# if m1 == m2 != m3 == m4, the slope at the breakpoint is not defined.
|
||||
# This is the fill value:
|
||||
t = .5 * (m[3:] + m[:-3])
|
||||
# get the denominator of the slope t
|
||||
dm = np.abs(np.diff(m, axis=0))
|
||||
f1 = dm[2:]
|
||||
f2 = dm[:-2]
|
||||
f12 = f1 + f2
|
||||
# These are the mask of where the the slope at breakpoint is defined:
|
||||
ind = np.nonzero(f12 > 1e-9 * np.max(f12))
|
||||
x_ind, y_ind = ind[0], ind[1:]
|
||||
# Set the slope at breakpoint
|
||||
t[ind] = (f1[ind] * m[(x_ind + 1,) + y_ind] +
|
||||
f2[ind] * m[(x_ind + 2,) + y_ind]) / f12[ind]
|
||||
|
||||
super(Akima1DInterpolator, self).__init__(x, y, t, axis=0,
|
||||
extrapolate=False)
|
||||
self.axis = axis
|
||||
|
||||
def extend(self, c, x, right=True):
|
||||
raise NotImplementedError("Extending a 1-D Akima interpolator is not "
|
||||
"yet implemented")
|
||||
|
||||
# These are inherited from PPoly, but they do not produce an Akima
|
||||
# interpolator. Hence stub them out.
|
||||
@classmethod
|
||||
def from_spline(cls, tck, extrapolate=None):
|
||||
raise NotImplementedError("This method does not make sense for "
|
||||
"an Akima interpolator.")
|
||||
|
||||
@classmethod
|
||||
def from_bernstein_basis(cls, bp, extrapolate=None):
|
||||
raise NotImplementedError("This method does not make sense for "
|
||||
"an Akima interpolator.")
|
||||
|
||||
|
||||
class CubicSpline(CubicHermiteSpline):
|
||||
"""Cubic spline data interpolator.
|
||||
|
||||
Interpolate data with a piecewise cubic polynomial which is twice
|
||||
continuously differentiable [1]_. The result is represented as a `PPoly`
|
||||
instance with breakpoints matching the given data.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like, shape (n,)
|
||||
1-D array containing values of the independent variable.
|
||||
Values must be real, finite and in strictly increasing order.
|
||||
y : array_like
|
||||
Array containing values of the dependent variable. It can have
|
||||
arbitrary number of dimensions, but the length along ``axis``
|
||||
(see below) must match the length of ``x``. Values must be finite.
|
||||
axis : int, optional
|
||||
Axis along which `y` is assumed to be varying. Meaning that for
|
||||
``x[i]`` the corresponding values are ``np.take(y, i, axis=axis)``.
|
||||
Default is 0.
|
||||
bc_type : string or 2-tuple, optional
|
||||
Boundary condition type. Two additional equations, given by the
|
||||
boundary conditions, are required to determine all coefficients of
|
||||
polynomials on each segment [2]_.
|
||||
|
||||
If `bc_type` is a string, then the specified condition will be applied
|
||||
at both ends of a spline. Available conditions are:
|
||||
|
||||
* 'not-a-knot' (default): The first and second segment at a curve end
|
||||
are the same polynomial. It is a good default when there is no
|
||||
information on boundary conditions.
|
||||
* 'periodic': The interpolated functions is assumed to be periodic
|
||||
of period ``x[-1] - x[0]``. The first and last value of `y` must be
|
||||
identical: ``y[0] == y[-1]``. This boundary condition will result in
|
||||
``y'[0] == y'[-1]`` and ``y''[0] == y''[-1]``.
|
||||
* 'clamped': The first derivative at curves ends are zero. Assuming
|
||||
a 1D `y`, ``bc_type=((1, 0.0), (1, 0.0))`` is the same condition.
|
||||
* 'natural': The second derivative at curve ends are zero. Assuming
|
||||
a 1D `y`, ``bc_type=((2, 0.0), (2, 0.0))`` is the same condition.
|
||||
|
||||
If `bc_type` is a 2-tuple, the first and the second value will be
|
||||
applied at the curve start and end respectively. The tuple values can
|
||||
be one of the previously mentioned strings (except 'periodic') or a
|
||||
tuple `(order, deriv_values)` allowing to specify arbitrary
|
||||
derivatives at curve ends:
|
||||
|
||||
* `order`: the derivative order, 1 or 2.
|
||||
* `deriv_value`: array_like containing derivative values, shape must
|
||||
be the same as `y`, excluding ``axis`` dimension. For example, if
|
||||
`y` is 1-D, then `deriv_value` must be a scalar. If `y` is 3-D with
|
||||
the shape (n0, n1, n2) and axis=2, then `deriv_value` must be 2-D
|
||||
and have the shape (n0, n1).
|
||||
extrapolate : {bool, 'periodic', None}, optional
|
||||
If bool, determines whether to extrapolate to out-of-bounds points
|
||||
based on first and last intervals, or to return NaNs. If 'periodic',
|
||||
periodic extrapolation is used. If None (default), ``extrapolate`` is
|
||||
set to 'periodic' for ``bc_type='periodic'`` and to True otherwise.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x : ndarray, shape (n,)
|
||||
Breakpoints. The same ``x`` which was passed to the constructor.
|
||||
c : ndarray, shape (4, n-1, ...)
|
||||
Coefficients of the polynomials on each segment. The trailing
|
||||
dimensions match the dimensions of `y`, excluding ``axis``.
|
||||
For example, if `y` is 1-d, then ``c[k, i]`` is a coefficient for
|
||||
``(x-x[i])**(3-k)`` on the segment between ``x[i]`` and ``x[i+1]``.
|
||||
axis : int
|
||||
Interpolation axis. The same axis which was passed to the
|
||||
constructor.
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
derivative
|
||||
antiderivative
|
||||
integrate
|
||||
roots
|
||||
|
||||
See Also
|
||||
--------
|
||||
Akima1DInterpolator : Akima 1D interpolator.
|
||||
PchipInterpolator : PCHIP 1-D monotonic cubic interpolator.
|
||||
PPoly : Piecewise polynomial in terms of coefficients and breakpoints.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Parameters `bc_type` and ``interpolate`` work independently, i.e. the
|
||||
former controls only construction of a spline, and the latter only
|
||||
evaluation.
|
||||
|
||||
When a boundary condition is 'not-a-knot' and n = 2, it is replaced by
|
||||
a condition that the first derivative is equal to the linear interpolant
|
||||
slope. When both boundary conditions are 'not-a-knot' and n = 3, the
|
||||
solution is sought as a parabola passing through given points.
|
||||
|
||||
When 'not-a-knot' boundary conditions is applied to both ends, the
|
||||
resulting spline will be the same as returned by `splrep` (with ``s=0``)
|
||||
and `InterpolatedUnivariateSpline`, but these two methods use a
|
||||
representation in B-spline basis.
|
||||
|
||||
.. versionadded:: 0.18.0
|
||||
|
||||
Examples
|
||||
--------
|
||||
In this example the cubic spline is used to interpolate a sampled sinusoid.
|
||||
You can see that the spline continuity property holds for the first and
|
||||
second derivatives and violates only for the third derivative.
|
||||
|
||||
>>> from scipy.interpolate import CubicSpline
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> x = np.arange(10)
|
||||
>>> y = np.sin(x)
|
||||
>>> cs = CubicSpline(x, y)
|
||||
>>> xs = np.arange(-0.5, 9.6, 0.1)
|
||||
>>> fig, ax = plt.subplots(figsize=(6.5, 4))
|
||||
>>> ax.plot(x, y, 'o', label='data')
|
||||
>>> ax.plot(xs, np.sin(xs), label='true')
|
||||
>>> ax.plot(xs, cs(xs), label="S")
|
||||
>>> ax.plot(xs, cs(xs, 1), label="S'")
|
||||
>>> ax.plot(xs, cs(xs, 2), label="S''")
|
||||
>>> ax.plot(xs, cs(xs, 3), label="S'''")
|
||||
>>> ax.set_xlim(-0.5, 9.5)
|
||||
>>> ax.legend(loc='lower left', ncol=2)
|
||||
>>> plt.show()
|
||||
|
||||
In the second example, the unit circle is interpolated with a spline. A
|
||||
periodic boundary condition is used. You can see that the first derivative
|
||||
values, ds/dx=0, ds/dy=1 at the periodic point (1, 0) are correctly
|
||||
computed. Note that a circle cannot be exactly represented by a cubic
|
||||
spline. To increase precision, more breakpoints would be required.
|
||||
|
||||
>>> theta = 2 * np.pi * np.linspace(0, 1, 5)
|
||||
>>> y = np.c_[np.cos(theta), np.sin(theta)]
|
||||
>>> cs = CubicSpline(theta, y, bc_type='periodic')
|
||||
>>> print("ds/dx={:.1f} ds/dy={:.1f}".format(cs(0, 1)[0], cs(0, 1)[1]))
|
||||
ds/dx=0.0 ds/dy=1.0
|
||||
>>> xs = 2 * np.pi * np.linspace(0, 1, 100)
|
||||
>>> fig, ax = plt.subplots(figsize=(6.5, 4))
|
||||
>>> ax.plot(y[:, 0], y[:, 1], 'o', label='data')
|
||||
>>> ax.plot(np.cos(xs), np.sin(xs), label='true')
|
||||
>>> ax.plot(cs(xs)[:, 0], cs(xs)[:, 1], label='spline')
|
||||
>>> ax.axes.set_aspect('equal')
|
||||
>>> ax.legend(loc='center')
|
||||
>>> plt.show()
|
||||
|
||||
The third example is the interpolation of a polynomial y = x**3 on the
|
||||
interval 0 <= x<= 1. A cubic spline can represent this function exactly.
|
||||
To achieve that we need to specify values and first derivatives at
|
||||
endpoints of the interval. Note that y' = 3 * x**2 and thus y'(0) = 0 and
|
||||
y'(1) = 3.
|
||||
|
||||
>>> cs = CubicSpline([0, 1], [0, 1], bc_type=((1, 0), (1, 3)))
|
||||
>>> x = np.linspace(0, 1)
|
||||
>>> np.allclose(x**3, cs(x))
|
||||
True
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] `Cubic Spline Interpolation
|
||||
<https://en.wikiversity.org/wiki/Cubic_Spline_Interpolation>`_
|
||||
on Wikiversity.
|
||||
.. [2] Carl de Boor, "A Practical Guide to Splines", Springer-Verlag, 1978.
|
||||
"""
|
||||
def __init__(self, x, y, axis=0, bc_type='not-a-knot', extrapolate=None):
|
||||
x, dx, y, axis, _ = prepare_input(x, y, axis)
|
||||
n = len(x)
|
||||
|
||||
bc, y = self._validate_bc(bc_type, y, y.shape[1:], axis)
|
||||
|
||||
if extrapolate is None:
|
||||
if bc[0] == 'periodic':
|
||||
extrapolate = 'periodic'
|
||||
else:
|
||||
extrapolate = True
|
||||
|
||||
dxr = dx.reshape([dx.shape[0]] + [1] * (y.ndim - 1))
|
||||
slope = np.diff(y, axis=0) / dxr
|
||||
|
||||
# If bc is 'not-a-knot' this change is just a convention.
|
||||
# If bc is 'periodic' then we already checked that y[0] == y[-1],
|
||||
# and the spline is just a constant, we handle this case in the same
|
||||
# way by setting the first derivatives to slope, which is 0.
|
||||
if n == 2:
|
||||
if bc[0] in ['not-a-knot', 'periodic']:
|
||||
bc[0] = (1, slope[0])
|
||||
if bc[1] in ['not-a-knot', 'periodic']:
|
||||
bc[1] = (1, slope[0])
|
||||
|
||||
# This is a very special case, when both conditions are 'not-a-knot'
|
||||
# and n == 3. In this case 'not-a-knot' can't be handled regularly
|
||||
# as the both conditions are identical. We handle this case by
|
||||
# constructing a parabola passing through given points.
|
||||
if n == 3 and bc[0] == 'not-a-knot' and bc[1] == 'not-a-knot':
|
||||
A = np.zeros((3, 3)) # This is a standard matrix.
|
||||
b = np.empty((3,) + y.shape[1:], dtype=y.dtype)
|
||||
|
||||
A[0, 0] = 1
|
||||
A[0, 1] = 1
|
||||
A[1, 0] = dx[1]
|
||||
A[1, 1] = 2 * (dx[0] + dx[1])
|
||||
A[1, 2] = dx[0]
|
||||
A[2, 1] = 1
|
||||
A[2, 2] = 1
|
||||
|
||||
b[0] = 2 * slope[0]
|
||||
b[1] = 3 * (dxr[0] * slope[1] + dxr[1] * slope[0])
|
||||
b[2] = 2 * slope[1]
|
||||
|
||||
s = solve(A, b, overwrite_a=True, overwrite_b=True,
|
||||
check_finite=False)
|
||||
else:
|
||||
# Find derivative values at each x[i] by solving a tridiagonal
|
||||
# system.
|
||||
A = np.zeros((3, n)) # This is a banded matrix representation.
|
||||
b = np.empty((n,) + y.shape[1:], dtype=y.dtype)
|
||||
|
||||
# Filling the system for i=1..n-2
|
||||
# (x[i-1] - x[i]) * s[i-1] +\
|
||||
# 2 * ((x[i] - x[i-1]) + (x[i+1] - x[i])) * s[i] +\
|
||||
# (x[i] - x[i-1]) * s[i+1] =\
|
||||
# 3 * ((x[i+1] - x[i])*(y[i] - y[i-1])/(x[i] - x[i-1]) +\
|
||||
# (x[i] - x[i-1])*(y[i+1] - y[i])/(x[i+1] - x[i]))
|
||||
|
||||
A[1, 1:-1] = 2 * (dx[:-1] + dx[1:]) # The diagonal
|
||||
A[0, 2:] = dx[:-1] # The upper diagonal
|
||||
A[-1, :-2] = dx[1:] # The lower diagonal
|
||||
|
||||
b[1:-1] = 3 * (dxr[1:] * slope[:-1] + dxr[:-1] * slope[1:])
|
||||
|
||||
bc_start, bc_end = bc
|
||||
|
||||
if bc_start == 'periodic':
|
||||
# Due to the periodicity, and because y[-1] = y[0], the linear
|
||||
# system has (n-1) unknowns/equations instead of n:
|
||||
A = A[:, 0:-1]
|
||||
A[1, 0] = 2 * (dx[-1] + dx[0])
|
||||
A[0, 1] = dx[-1]
|
||||
|
||||
b = b[:-1]
|
||||
|
||||
# Also, due to the periodicity, the system is not tri-diagonal.
|
||||
# We need to compute a "condensed" matrix of shape (n-2, n-2).
|
||||
# See https://web.archive.org/web/20151220180652/http://www.cfm.brown.edu/people/gk/chap6/node14.html
|
||||
# for more explanations.
|
||||
# The condensed matrix is obtained by removing the last column
|
||||
# and last row of the (n-1, n-1) system matrix. The removed
|
||||
# values are saved in scalar variables with the (n-1, n-1)
|
||||
# system matrix indices forming their names:
|
||||
a_m1_0 = dx[-2] # lower left corner value: A[-1, 0]
|
||||
a_m1_m2 = dx[-1]
|
||||
a_m1_m1 = 2 * (dx[-1] + dx[-2])
|
||||
a_m2_m1 = dx[-2]
|
||||
a_0_m1 = dx[0]
|
||||
|
||||
b[0] = 3 * (dxr[0] * slope[-1] + dxr[-1] * slope[0])
|
||||
b[-1] = 3 * (dxr[-1] * slope[-2] + dxr[-2] * slope[-1])
|
||||
|
||||
Ac = A[:, :-1]
|
||||
b1 = b[:-1]
|
||||
b2 = np.zeros_like(b1)
|
||||
b2[0] = -a_0_m1
|
||||
b2[-1] = -a_m2_m1
|
||||
|
||||
# s1 and s2 are the solutions of (n-2, n-2) system
|
||||
s1 = solve_banded((1, 1), Ac, b1, overwrite_ab=False,
|
||||
overwrite_b=False, check_finite=False)
|
||||
|
||||
s2 = solve_banded((1, 1), Ac, b2, overwrite_ab=False,
|
||||
overwrite_b=False, check_finite=False)
|
||||
|
||||
# computing the s[n-2] solution:
|
||||
s_m1 = ((b[-1] - a_m1_0 * s1[0] - a_m1_m2 * s1[-1]) /
|
||||
(a_m1_m1 + a_m1_0 * s2[0] + a_m1_m2 * s2[-1]))
|
||||
|
||||
# s is the solution of the (n, n) system:
|
||||
s = np.empty((n,) + y.shape[1:], dtype=y.dtype)
|
||||
s[:-2] = s1 + s_m1 * s2
|
||||
s[-2] = s_m1
|
||||
s[-1] = s[0]
|
||||
else:
|
||||
if bc_start == 'not-a-knot':
|
||||
A[1, 0] = dx[1]
|
||||
A[0, 1] = x[2] - x[0]
|
||||
d = x[2] - x[0]
|
||||
b[0] = ((dxr[0] + 2*d) * dxr[1] * slope[0] +
|
||||
dxr[0]**2 * slope[1]) / d
|
||||
elif bc_start[0] == 1:
|
||||
A[1, 0] = 1
|
||||
A[0, 1] = 0
|
||||
b[0] = bc_start[1]
|
||||
elif bc_start[0] == 2:
|
||||
A[1, 0] = 2 * dx[0]
|
||||
A[0, 1] = dx[0]
|
||||
b[0] = -0.5 * bc_start[1] * dx[0]**2 + 3 * (y[1] - y[0])
|
||||
|
||||
if bc_end == 'not-a-knot':
|
||||
A[1, -1] = dx[-2]
|
||||
A[-1, -2] = x[-1] - x[-3]
|
||||
d = x[-1] - x[-3]
|
||||
b[-1] = ((dxr[-1]**2*slope[-2] +
|
||||
(2*d + dxr[-1])*dxr[-2]*slope[-1]) / d)
|
||||
elif bc_end[0] == 1:
|
||||
A[1, -1] = 1
|
||||
A[-1, -2] = 0
|
||||
b[-1] = bc_end[1]
|
||||
elif bc_end[0] == 2:
|
||||
A[1, -1] = 2 * dx[-1]
|
||||
A[-1, -2] = dx[-1]
|
||||
b[-1] = 0.5 * bc_end[1] * dx[-1]**2 + 3 * (y[-1] - y[-2])
|
||||
|
||||
s = solve_banded((1, 1), A, b, overwrite_ab=True,
|
||||
overwrite_b=True, check_finite=False)
|
||||
|
||||
super(CubicSpline, self).__init__(x, y, s, axis=0,
|
||||
extrapolate=extrapolate)
|
||||
self.axis = axis
|
||||
|
||||
@staticmethod
|
||||
def _validate_bc(bc_type, y, expected_deriv_shape, axis):
|
||||
"""Validate and prepare boundary conditions.
|
||||
|
||||
Returns
|
||||
-------
|
||||
validated_bc : 2-tuple
|
||||
Boundary conditions for a curve start and end.
|
||||
y : ndarray
|
||||
y casted to complex dtype if one of the boundary conditions has
|
||||
complex dtype.
|
||||
"""
|
||||
if isinstance(bc_type, str):
|
||||
if bc_type == 'periodic':
|
||||
if not np.allclose(y[0], y[-1], rtol=1e-15, atol=1e-15):
|
||||
raise ValueError(
|
||||
"The first and last `y` point along axis {} must "
|
||||
"be identical (within machine precision) when "
|
||||
"bc_type='periodic'.".format(axis))
|
||||
|
||||
bc_type = (bc_type, bc_type)
|
||||
|
||||
else:
|
||||
if len(bc_type) != 2:
|
||||
raise ValueError("`bc_type` must contain 2 elements to "
|
||||
"specify start and end conditions.")
|
||||
|
||||
if 'periodic' in bc_type:
|
||||
raise ValueError("'periodic' `bc_type` is defined for both "
|
||||
"curve ends and cannot be used with other "
|
||||
"boundary conditions.")
|
||||
|
||||
validated_bc = []
|
||||
for bc in bc_type:
|
||||
if isinstance(bc, str):
|
||||
if bc == 'clamped':
|
||||
validated_bc.append((1, np.zeros(expected_deriv_shape)))
|
||||
elif bc == 'natural':
|
||||
validated_bc.append((2, np.zeros(expected_deriv_shape)))
|
||||
elif bc in ['not-a-knot', 'periodic']:
|
||||
validated_bc.append(bc)
|
||||
else:
|
||||
raise ValueError("bc_type={} is not allowed.".format(bc))
|
||||
else:
|
||||
try:
|
||||
deriv_order, deriv_value = bc
|
||||
except Exception:
|
||||
raise ValueError("A specified derivative value must be "
|
||||
"given in the form (order, value).")
|
||||
|
||||
if deriv_order not in [1, 2]:
|
||||
raise ValueError("The specified derivative order must "
|
||||
"be 1 or 2.")
|
||||
|
||||
deriv_value = np.asarray(deriv_value)
|
||||
if deriv_value.shape != expected_deriv_shape:
|
||||
raise ValueError(
|
||||
"`deriv_value` shape {} is not the expected one {}."
|
||||
.format(deriv_value.shape, expected_deriv_shape))
|
||||
|
||||
if np.issubdtype(deriv_value.dtype, np.complexfloating):
|
||||
y = y.astype(complex, copy=False)
|
||||
|
||||
validated_bc.append((deriv_order, deriv_value))
|
||||
|
||||
return validated_bc, y
|
BIN
venv/Lib/site-packages/scipy/interpolate/_fitpack.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/_fitpack.cp36-win32.pyd
Normal file
Binary file not shown.
1312
venv/Lib/site-packages/scipy/interpolate/_fitpack_impl.py
Normal file
1312
venv/Lib/site-packages/scipy/interpolate/_fitpack_impl.py
Normal file
File diff suppressed because it is too large
Load diff
66
venv/Lib/site-packages/scipy/interpolate/_pade.py
Normal file
66
venv/Lib/site-packages/scipy/interpolate/_pade.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
from numpy import zeros, asarray, eye, poly1d, hstack, r_
|
||||
from scipy import linalg
|
||||
|
||||
__all__ = ["pade"]
|
||||
|
||||
def pade(an, m, n=None):
|
||||
"""
|
||||
Return Pade approximation to a polynomial as the ratio of two polynomials.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
an : (N,) array_like
|
||||
Taylor series coefficients.
|
||||
m : int
|
||||
The order of the returned approximating polynomial `q`.
|
||||
n : int, optional
|
||||
The order of the returned approximating polynomial `p`. By default,
|
||||
the order is ``len(an)-m``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
p, q : Polynomial class
|
||||
The Pade approximation of the polynomial defined by `an` is
|
||||
``p(x)/q(x)``.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from scipy.interpolate import pade
|
||||
>>> e_exp = [1.0, 1.0, 1.0/2.0, 1.0/6.0, 1.0/24.0, 1.0/120.0]
|
||||
>>> p, q = pade(e_exp, 2)
|
||||
|
||||
>>> e_exp.reverse()
|
||||
>>> e_poly = np.poly1d(e_exp)
|
||||
|
||||
Compare ``e_poly(x)`` and the Pade approximation ``p(x)/q(x)``
|
||||
|
||||
>>> e_poly(1)
|
||||
2.7166666666666668
|
||||
|
||||
>>> p(1)/q(1)
|
||||
2.7179487179487181
|
||||
|
||||
"""
|
||||
an = asarray(an)
|
||||
if n is None:
|
||||
n = len(an) - 1 - m
|
||||
if n < 0:
|
||||
raise ValueError("Order of q <m> must be smaller than len(an)-1.")
|
||||
if n < 0:
|
||||
raise ValueError("Order of p <n> must be greater than 0.")
|
||||
N = m + n
|
||||
if N > len(an)-1:
|
||||
raise ValueError("Order of q+p <m+n> must be smaller than len(an).")
|
||||
an = an[:N+1]
|
||||
Akj = eye(N+1, n+1, dtype=an.dtype)
|
||||
Bkj = zeros((N+1, m), dtype=an.dtype)
|
||||
for row in range(1, m+1):
|
||||
Bkj[row,:row] = -(an[:row])[::-1]
|
||||
for row in range(m+1, N+1):
|
||||
Bkj[row,:] = -(an[row-m:row])[::-1]
|
||||
C = hstack((Akj, Bkj))
|
||||
pq = linalg.solve(C, an)
|
||||
p = pq[:n+1]
|
||||
q = r_[1.0, pq[n+1:]]
|
||||
return poly1d(p[::-1]), poly1d(q[::-1])
|
||||
|
BIN
venv/Lib/site-packages/scipy/interpolate/_ppoly.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/_ppoly.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/interpolate/dfitpack.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/dfitpack.cp36-win32.pyd
Normal file
Binary file not shown.
721
venv/Lib/site-packages/scipy/interpolate/fitpack.py
Normal file
721
venv/Lib/site-packages/scipy/interpolate/fitpack.py
Normal file
|
@ -0,0 +1,721 @@
|
|||
__all__ = ['splrep', 'splprep', 'splev', 'splint', 'sproot', 'spalde',
|
||||
'bisplrep', 'bisplev', 'insert', 'splder', 'splantider']
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
# These are in the API for fitpack even if not used in fitpack.py itself.
|
||||
from ._fitpack_impl import bisplrep, bisplev, dblint
|
||||
from . import _fitpack_impl as _impl
|
||||
from ._bsplines import BSpline
|
||||
|
||||
|
||||
def splprep(x, w=None, u=None, ub=None, ue=None, k=3, task=0, s=None, t=None,
|
||||
full_output=0, nest=None, per=0, quiet=1):
|
||||
"""
|
||||
Find the B-spline representation of an N-D curve.
|
||||
|
||||
Given a list of N rank-1 arrays, `x`, which represent a curve in
|
||||
N-D space parametrized by `u`, find a smooth approximating
|
||||
spline curve g(`u`). Uses the FORTRAN routine parcur from FITPACK.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
A list of sample vector arrays representing the curve.
|
||||
w : array_like, optional
|
||||
Strictly positive rank-1 array of weights the same length as `x[0]`.
|
||||
The weights are used in computing the weighted least-squares spline
|
||||
fit. If the errors in the `x` values have standard-deviation given by
|
||||
the vector d, then `w` should be 1/d. Default is ``ones(len(x[0]))``.
|
||||
u : array_like, optional
|
||||
An array of parameter values. If not given, these values are
|
||||
calculated automatically as ``M = len(x[0])``, where
|
||||
|
||||
v[0] = 0
|
||||
|
||||
v[i] = v[i-1] + distance(`x[i]`, `x[i-1]`)
|
||||
|
||||
u[i] = v[i] / v[M-1]
|
||||
|
||||
ub, ue : int, optional
|
||||
The end-points of the parameters interval. Defaults to
|
||||
u[0] and u[-1].
|
||||
k : int, optional
|
||||
Degree of the spline. Cubic splines are recommended.
|
||||
Even values of `k` should be avoided especially with a small s-value.
|
||||
``1 <= k <= 5``, default is 3.
|
||||
task : int, optional
|
||||
If task==0 (default), find t and c for a given smoothing factor, s.
|
||||
If task==1, find t and c for another value of the smoothing factor, s.
|
||||
There must have been a previous call with task=0 or task=1
|
||||
for the same set of data.
|
||||
If task=-1 find the weighted least square spline for a given set of
|
||||
knots, t.
|
||||
s : float, optional
|
||||
A smoothing condition. The amount of smoothness is determined by
|
||||
satisfying the conditions: ``sum((w * (y - g))**2,axis=0) <= s``,
|
||||
where g(x) is the smoothed interpolation of (x,y). The user can
|
||||
use `s` to control the trade-off between closeness and smoothness
|
||||
of fit. Larger `s` means more smoothing while smaller values of `s`
|
||||
indicate less smoothing. Recommended values of `s` depend on the
|
||||
weights, w. If the weights represent the inverse of the
|
||||
standard-deviation of y, then a good `s` value should be found in
|
||||
the range ``(m-sqrt(2*m),m+sqrt(2*m))``, where m is the number of
|
||||
data points in x, y, and w.
|
||||
t : int, optional
|
||||
The knots needed for task=-1.
|
||||
full_output : int, optional
|
||||
If non-zero, then return optional outputs.
|
||||
nest : int, optional
|
||||
An over-estimate of the total number of knots of the spline to
|
||||
help in determining the storage space. By default nest=m/2.
|
||||
Always large enough is nest=m+k+1.
|
||||
per : int, optional
|
||||
If non-zero, data points are considered periodic with period
|
||||
``x[m-1] - x[0]`` and a smooth periodic spline approximation is
|
||||
returned. Values of ``y[m-1]`` and ``w[m-1]`` are not used.
|
||||
quiet : int, optional
|
||||
Non-zero to suppress messages.
|
||||
This parameter is deprecated; use standard Python warning filters
|
||||
instead.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tck : tuple
|
||||
(t,c,k) a tuple containing the vector of knots, the B-spline
|
||||
coefficients, and the degree of the spline.
|
||||
u : array
|
||||
An array of the values of the parameter.
|
||||
fp : float
|
||||
The weighted sum of squared residuals of the spline approximation.
|
||||
ier : int
|
||||
An integer flag about splrep success. Success is indicated
|
||||
if ier<=0. If ier in [1,2,3] an error occurred but was not raised.
|
||||
Otherwise an error is raised.
|
||||
msg : str
|
||||
A message corresponding to the integer flag, ier.
|
||||
|
||||
See Also
|
||||
--------
|
||||
splrep, splev, sproot, spalde, splint,
|
||||
bisplrep, bisplev
|
||||
UnivariateSpline, BivariateSpline
|
||||
BSpline
|
||||
make_interp_spline
|
||||
|
||||
Notes
|
||||
-----
|
||||
See `splev` for evaluation of the spline and its derivatives.
|
||||
The number of dimensions N must be smaller than 11.
|
||||
|
||||
The number of coefficients in the `c` array is ``k+1`` less then the number
|
||||
of knots, ``len(t)``. This is in contrast with `splrep`, which zero-pads
|
||||
the array of coefficients to have the same length as the array of knots.
|
||||
These additional coefficients are ignored by evaluation routines, `splev`
|
||||
and `BSpline`.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] P. Dierckx, "Algorithms for smoothing data with periodic and
|
||||
parametric splines, Computer Graphics and Image Processing",
|
||||
20 (1982) 171-184.
|
||||
.. [2] P. Dierckx, "Algorithms for smoothing data with periodic and
|
||||
parametric splines", report tw55, Dept. Computer Science,
|
||||
K.U.Leuven, 1981.
|
||||
.. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs on
|
||||
Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Generate a discretization of a limacon curve in the polar coordinates:
|
||||
|
||||
>>> phi = np.linspace(0, 2.*np.pi, 40)
|
||||
>>> r = 0.5 + np.cos(phi) # polar coords
|
||||
>>> x, y = r * np.cos(phi), r * np.sin(phi) # convert to cartesian
|
||||
|
||||
And interpolate:
|
||||
|
||||
>>> from scipy.interpolate import splprep, splev
|
||||
>>> tck, u = splprep([x, y], s=0)
|
||||
>>> new_points = splev(u, tck)
|
||||
|
||||
Notice that (i) we force interpolation by using `s=0`,
|
||||
(ii) the parameterization, ``u``, is generated automatically.
|
||||
Now plot the result:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> fig, ax = plt.subplots()
|
||||
>>> ax.plot(x, y, 'ro')
|
||||
>>> ax.plot(new_points[0], new_points[1], 'r-')
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
res = _impl.splprep(x, w, u, ub, ue, k, task, s, t, full_output, nest, per,
|
||||
quiet)
|
||||
return res
|
||||
|
||||
|
||||
def splrep(x, y, w=None, xb=None, xe=None, k=3, task=0, s=None, t=None,
|
||||
full_output=0, per=0, quiet=1):
|
||||
"""
|
||||
Find the B-spline representation of a 1-D curve.
|
||||
|
||||
Given the set of data points ``(x[i], y[i])`` determine a smooth spline
|
||||
approximation of degree k on the interval ``xb <= x <= xe``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x, y : array_like
|
||||
The data points defining a curve y = f(x).
|
||||
w : array_like, optional
|
||||
Strictly positive rank-1 array of weights the same length as x and y.
|
||||
The weights are used in computing the weighted least-squares spline
|
||||
fit. If the errors in the y values have standard-deviation given by the
|
||||
vector d, then w should be 1/d. Default is ones(len(x)).
|
||||
xb, xe : float, optional
|
||||
The interval to fit. If None, these default to x[0] and x[-1]
|
||||
respectively.
|
||||
k : int, optional
|
||||
The degree of the spline fit. It is recommended to use cubic splines.
|
||||
Even values of k should be avoided especially with small s values.
|
||||
1 <= k <= 5
|
||||
task : {1, 0, -1}, optional
|
||||
If task==0 find t and c for a given smoothing factor, s.
|
||||
|
||||
If task==1 find t and c for another value of the smoothing factor, s.
|
||||
There must have been a previous call with task=0 or task=1 for the same
|
||||
set of data (t will be stored an used internally)
|
||||
|
||||
If task=-1 find the weighted least square spline for a given set of
|
||||
knots, t. These should be interior knots as knots on the ends will be
|
||||
added automatically.
|
||||
s : float, optional
|
||||
A smoothing condition. The amount of smoothness is determined by
|
||||
satisfying the conditions: sum((w * (y - g))**2,axis=0) <= s where g(x)
|
||||
is the smoothed interpolation of (x,y). The user can use s to control
|
||||
the tradeoff between closeness and smoothness of fit. Larger s means
|
||||
more smoothing while smaller values of s indicate less smoothing.
|
||||
Recommended values of s depend on the weights, w. If the weights
|
||||
represent the inverse of the standard-deviation of y, then a good s
|
||||
value should be found in the range (m-sqrt(2*m),m+sqrt(2*m)) where m is
|
||||
the number of datapoints in x, y, and w. default : s=m-sqrt(2*m) if
|
||||
weights are supplied. s = 0.0 (interpolating) if no weights are
|
||||
supplied.
|
||||
t : array_like, optional
|
||||
The knots needed for task=-1. If given then task is automatically set
|
||||
to -1.
|
||||
full_output : bool, optional
|
||||
If non-zero, then return optional outputs.
|
||||
per : bool, optional
|
||||
If non-zero, data points are considered periodic with period x[m-1] -
|
||||
x[0] and a smooth periodic spline approximation is returned. Values of
|
||||
y[m-1] and w[m-1] are not used.
|
||||
quiet : bool, optional
|
||||
Non-zero to suppress messages.
|
||||
This parameter is deprecated; use standard Python warning filters
|
||||
instead.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tck : tuple
|
||||
A tuple (t,c,k) containing the vector of knots, the B-spline
|
||||
coefficients, and the degree of the spline.
|
||||
fp : array, optional
|
||||
The weighted sum of squared residuals of the spline approximation.
|
||||
ier : int, optional
|
||||
An integer flag about splrep success. Success is indicated if ier<=0.
|
||||
If ier in [1,2,3] an error occurred but was not raised. Otherwise an
|
||||
error is raised.
|
||||
msg : str, optional
|
||||
A message corresponding to the integer flag, ier.
|
||||
|
||||
See Also
|
||||
--------
|
||||
UnivariateSpline, BivariateSpline
|
||||
splprep, splev, sproot, spalde, splint
|
||||
bisplrep, bisplev
|
||||
BSpline
|
||||
make_interp_spline
|
||||
|
||||
Notes
|
||||
-----
|
||||
See `splev` for evaluation of the spline and its derivatives. Uses the
|
||||
FORTRAN routine ``curfit`` from FITPACK.
|
||||
|
||||
The user is responsible for assuring that the values of `x` are unique.
|
||||
Otherwise, `splrep` will not return sensible results.
|
||||
|
||||
If provided, knots `t` must satisfy the Schoenberg-Whitney conditions,
|
||||
i.e., there must be a subset of data points ``x[j]`` such that
|
||||
``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``.
|
||||
|
||||
This routine zero-pads the coefficients array ``c`` to have the same length
|
||||
as the array of knots ``t`` (the trailing ``k + 1`` coefficients are ignored
|
||||
by the evaluation routines, `splev` and `BSpline`.) This is in contrast with
|
||||
`splprep`, which does not zero-pad the coefficients.
|
||||
|
||||
References
|
||||
----------
|
||||
Based on algorithms described in [1]_, [2]_, [3]_, and [4]_:
|
||||
|
||||
.. [1] P. Dierckx, "An algorithm for smoothing, differentiation and
|
||||
integration of experimental data using spline functions",
|
||||
J.Comp.Appl.Maths 1 (1975) 165-184.
|
||||
.. [2] P. Dierckx, "A fast algorithm for smoothing data on a rectangular
|
||||
grid while using spline functions", SIAM J.Numer.Anal. 19 (1982)
|
||||
1286-1304.
|
||||
.. [3] P. Dierckx, "An improved algorithm for curve fitting with spline
|
||||
functions", report tw54, Dept. Computer Science,K.U. Leuven, 1981.
|
||||
.. [4] P. Dierckx, "Curve and surface fitting with splines", Monographs on
|
||||
Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> from scipy.interpolate import splev, splrep
|
||||
>>> x = np.linspace(0, 10, 10)
|
||||
>>> y = np.sin(x)
|
||||
>>> spl = splrep(x, y)
|
||||
>>> x2 = np.linspace(0, 10, 200)
|
||||
>>> y2 = splev(x2, spl)
|
||||
>>> plt.plot(x, y, 'o', x2, y2)
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
res = _impl.splrep(x, y, w, xb, xe, k, task, s, t, full_output, per, quiet)
|
||||
return res
|
||||
|
||||
|
||||
def splev(x, tck, der=0, ext=0):
|
||||
"""
|
||||
Evaluate a B-spline or its derivatives.
|
||||
|
||||
Given the knots and coefficients of a B-spline representation, evaluate
|
||||
the value of the smoothing polynomial and its derivatives. This is a
|
||||
wrapper around the FORTRAN routines splev and splder of FITPACK.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
An array of points at which to return the value of the smoothed
|
||||
spline or its derivatives. If `tck` was returned from `splprep`,
|
||||
then the parameter values, u should be given.
|
||||
tck : 3-tuple or a BSpline object
|
||||
If a tuple, then it should be a sequence of length 3 returned by
|
||||
`splrep` or `splprep` containing the knots, coefficients, and degree
|
||||
of the spline. (Also see Notes.)
|
||||
der : int, optional
|
||||
The order of derivative of the spline to compute (must be less than
|
||||
or equal to k, the degree of the spline).
|
||||
ext : int, optional
|
||||
Controls the value returned for elements of ``x`` not in the
|
||||
interval defined by the knot sequence.
|
||||
|
||||
* if ext=0, return the extrapolated value.
|
||||
* if ext=1, return 0
|
||||
* if ext=2, raise a ValueError
|
||||
* if ext=3, return the boundary value.
|
||||
|
||||
The default value is 0.
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : ndarray or list of ndarrays
|
||||
An array of values representing the spline function evaluated at
|
||||
the points in `x`. If `tck` was returned from `splprep`, then this
|
||||
is a list of arrays representing the curve in an N-D space.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Manipulating the tck-tuples directly is not recommended. In new code,
|
||||
prefer using `BSpline` objects.
|
||||
|
||||
See Also
|
||||
--------
|
||||
splprep, splrep, sproot, spalde, splint
|
||||
bisplrep, bisplev
|
||||
BSpline
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] C. de Boor, "On calculating with b-splines", J. Approximation
|
||||
Theory, 6, p.50-62, 1972.
|
||||
.. [2] M. G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
|
||||
Applics, 10, p.134-149, 1972.
|
||||
.. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
|
||||
on Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
if tck.c.ndim > 1:
|
||||
mesg = ("Calling splev() with BSpline objects with c.ndim > 1 is "
|
||||
"not recommended. Use BSpline.__call__(x) instead.")
|
||||
warnings.warn(mesg, DeprecationWarning)
|
||||
|
||||
# remap the out-of-bounds behavior
|
||||
try:
|
||||
extrapolate = {0: True, }[ext]
|
||||
except KeyError:
|
||||
raise ValueError("Extrapolation mode %s is not supported "
|
||||
"by BSpline." % ext)
|
||||
|
||||
return tck(x, der, extrapolate=extrapolate)
|
||||
else:
|
||||
return _impl.splev(x, tck, der, ext)
|
||||
|
||||
|
||||
def splint(a, b, tck, full_output=0):
|
||||
"""
|
||||
Evaluate the definite integral of a B-spline between two given points.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a, b : float
|
||||
The end-points of the integration interval.
|
||||
tck : tuple or a BSpline instance
|
||||
If a tuple, then it should be a sequence of length 3, containing the
|
||||
vector of knots, the B-spline coefficients, and the degree of the
|
||||
spline (see `splev`).
|
||||
full_output : int, optional
|
||||
Non-zero to return optional output.
|
||||
|
||||
Returns
|
||||
-------
|
||||
integral : float
|
||||
The resulting integral.
|
||||
wrk : ndarray
|
||||
An array containing the integrals of the normalized B-splines
|
||||
defined on the set of knots.
|
||||
(Only returned if `full_output` is non-zero)
|
||||
|
||||
Notes
|
||||
-----
|
||||
`splint` silently assumes that the spline function is zero outside the data
|
||||
interval (`a`, `b`).
|
||||
|
||||
Manipulating the tck-tuples directly is not recommended. In new code,
|
||||
prefer using the `BSpline` objects.
|
||||
|
||||
See Also
|
||||
--------
|
||||
splprep, splrep, sproot, spalde, splev
|
||||
bisplrep, bisplev
|
||||
BSpline
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] P.W. Gaffney, The calculation of indefinite integrals of b-splines",
|
||||
J. Inst. Maths Applics, 17, p.37-41, 1976.
|
||||
.. [2] P. Dierckx, "Curve and surface fitting with splines", Monographs
|
||||
on Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
if tck.c.ndim > 1:
|
||||
mesg = ("Calling splint() with BSpline objects with c.ndim > 1 is "
|
||||
"not recommended. Use BSpline.integrate() instead.")
|
||||
warnings.warn(mesg, DeprecationWarning)
|
||||
|
||||
if full_output != 0:
|
||||
mesg = ("full_output = %s is not supported. Proceeding as if "
|
||||
"full_output = 0" % full_output)
|
||||
|
||||
return tck.integrate(a, b, extrapolate=False)
|
||||
else:
|
||||
return _impl.splint(a, b, tck, full_output)
|
||||
|
||||
|
||||
def sproot(tck, mest=10):
|
||||
"""
|
||||
Find the roots of a cubic B-spline.
|
||||
|
||||
Given the knots (>=8) and coefficients of a cubic B-spline return the
|
||||
roots of the spline.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tck : tuple or a BSpline object
|
||||
If a tuple, then it should be a sequence of length 3, containing the
|
||||
vector of knots, the B-spline coefficients, and the degree of the
|
||||
spline.
|
||||
The number of knots must be >= 8, and the degree must be 3.
|
||||
The knots must be a montonically increasing sequence.
|
||||
mest : int, optional
|
||||
An estimate of the number of zeros (Default is 10).
|
||||
|
||||
Returns
|
||||
-------
|
||||
zeros : ndarray
|
||||
An array giving the roots of the spline.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Manipulating the tck-tuples directly is not recommended. In new code,
|
||||
prefer using the `BSpline` objects.
|
||||
|
||||
See also
|
||||
--------
|
||||
splprep, splrep, splint, spalde, splev
|
||||
bisplrep, bisplev
|
||||
BSpline
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] C. de Boor, "On calculating with b-splines", J. Approximation
|
||||
Theory, 6, p.50-62, 1972.
|
||||
.. [2] M. G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
|
||||
Applics, 10, p.134-149, 1972.
|
||||
.. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
|
||||
on Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
if tck.c.ndim > 1:
|
||||
mesg = ("Calling sproot() with BSpline objects with c.ndim > 1 is "
|
||||
"not recommended.")
|
||||
warnings.warn(mesg, DeprecationWarning)
|
||||
|
||||
t, c, k = tck.tck
|
||||
|
||||
# _impl.sproot expects the interpolation axis to be last, so roll it.
|
||||
# NB: This transpose is a no-op if c is 1D.
|
||||
sh = tuple(range(c.ndim))
|
||||
c = c.transpose(sh[1:] + (0,))
|
||||
return _impl.sproot((t, c, k), mest)
|
||||
else:
|
||||
return _impl.sproot(tck, mest)
|
||||
|
||||
|
||||
def spalde(x, tck):
|
||||
"""
|
||||
Evaluate all derivatives of a B-spline.
|
||||
|
||||
Given the knots and coefficients of a cubic B-spline compute all
|
||||
derivatives up to order k at a point (or set of points).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
A point or a set of points at which to evaluate the derivatives.
|
||||
Note that ``t(k) <= x <= t(n-k+1)`` must hold for each `x`.
|
||||
tck : tuple
|
||||
A tuple ``(t, c, k)``, containing the vector of knots, the B-spline
|
||||
coefficients, and the degree of the spline (see `splev`).
|
||||
|
||||
Returns
|
||||
-------
|
||||
results : {ndarray, list of ndarrays}
|
||||
An array (or a list of arrays) containing all derivatives
|
||||
up to order k inclusive for each point `x`.
|
||||
|
||||
See Also
|
||||
--------
|
||||
splprep, splrep, splint, sproot, splev, bisplrep, bisplev,
|
||||
BSpline
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] C. de Boor: On calculating with b-splines, J. Approximation Theory
|
||||
6 (1972) 50-62.
|
||||
.. [2] M. G. Cox : The numerical evaluation of b-splines, J. Inst. Maths
|
||||
applics 10 (1972) 134-149.
|
||||
.. [3] P. Dierckx : Curve and surface fitting with splines, Monographs on
|
||||
Numerical Analysis, Oxford University Press, 1993.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
raise TypeError("spalde does not accept BSpline instances.")
|
||||
else:
|
||||
return _impl.spalde(x, tck)
|
||||
|
||||
|
||||
def insert(x, tck, m=1, per=0):
|
||||
"""
|
||||
Insert knots into a B-spline.
|
||||
|
||||
Given the knots and coefficients of a B-spline representation, create a
|
||||
new B-spline with a knot inserted `m` times at point `x`.
|
||||
This is a wrapper around the FORTRAN routine insert of FITPACK.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x (u) : array_like
|
||||
A 1-D point at which to insert a new knot(s). If `tck` was returned
|
||||
from ``splprep``, then the parameter values, u should be given.
|
||||
tck : a `BSpline` instance or a tuple
|
||||
If tuple, then it is expected to be a tuple (t,c,k) containing
|
||||
the vector of knots, the B-spline coefficients, and the degree of
|
||||
the spline.
|
||||
m : int, optional
|
||||
The number of times to insert the given knot (its multiplicity).
|
||||
Default is 1.
|
||||
per : int, optional
|
||||
If non-zero, the input spline is considered periodic.
|
||||
|
||||
Returns
|
||||
-------
|
||||
BSpline instance or a tuple
|
||||
A new B-spline with knots t, coefficients c, and degree k.
|
||||
``t(k+1) <= x <= t(n-k)``, where k is the degree of the spline.
|
||||
In case of a periodic spline (``per != 0``) there must be
|
||||
either at least k interior knots t(j) satisfying ``t(k+1)<t(j)<=x``
|
||||
or at least k interior knots t(j) satisfying ``x<=t(j)<t(n-k)``.
|
||||
A tuple is returned iff the input argument `tck` is a tuple, otherwise
|
||||
a BSpline object is constructed and returned.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Based on algorithms from [1]_ and [2]_.
|
||||
|
||||
Manipulating the tck-tuples directly is not recommended. In new code,
|
||||
prefer using the `BSpline` objects.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] W. Boehm, "Inserting new knots into b-spline curves.",
|
||||
Computer Aided Design, 12, p.199-201, 1980.
|
||||
.. [2] P. Dierckx, "Curve and surface fitting with splines, Monographs on
|
||||
Numerical Analysis", Oxford University Press, 1993.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
|
||||
t, c, k = tck.tck
|
||||
|
||||
# FITPACK expects the interpolation axis to be last, so roll it over
|
||||
# NB: if c array is 1D, transposes are no-ops
|
||||
sh = tuple(range(c.ndim))
|
||||
c = c.transpose(sh[1:] + (0,))
|
||||
t_, c_, k_ = _impl.insert(x, (t, c, k), m, per)
|
||||
|
||||
# and roll the last axis back
|
||||
c_ = np.asarray(c_)
|
||||
c_ = c_.transpose((sh[-1],) + sh[:-1])
|
||||
return BSpline(t_, c_, k_)
|
||||
else:
|
||||
return _impl.insert(x, tck, m, per)
|
||||
|
||||
|
||||
def splder(tck, n=1):
|
||||
"""
|
||||
Compute the spline representation of the derivative of a given spline
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tck : BSpline instance or a tuple of (t, c, k)
|
||||
Spline whose derivative to compute
|
||||
n : int, optional
|
||||
Order of derivative to evaluate. Default: 1
|
||||
|
||||
Returns
|
||||
-------
|
||||
`BSpline` instance or tuple
|
||||
Spline of order k2=k-n representing the derivative
|
||||
of the input spline.
|
||||
A tuple is returned iff the input argument `tck` is a tuple, otherwise
|
||||
a BSpline object is constructed and returned.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
See Also
|
||||
--------
|
||||
splantider, splev, spalde
|
||||
BSpline
|
||||
|
||||
Examples
|
||||
--------
|
||||
This can be used for finding maxima of a curve:
|
||||
|
||||
>>> from scipy.interpolate import splrep, splder, sproot
|
||||
>>> x = np.linspace(0, 10, 70)
|
||||
>>> y = np.sin(x)
|
||||
>>> spl = splrep(x, y, k=4)
|
||||
|
||||
Now, differentiate the spline and find the zeros of the
|
||||
derivative. (NB: `sproot` only works for order 3 splines, so we
|
||||
fit an order 4 spline):
|
||||
|
||||
>>> dspl = splder(spl)
|
||||
>>> sproot(dspl) / np.pi
|
||||
array([ 0.50000001, 1.5 , 2.49999998])
|
||||
|
||||
This agrees well with roots :math:`\\pi/2 + n\\pi` of
|
||||
:math:`\\cos(x) = \\sin'(x)`.
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
return tck.derivative(n)
|
||||
else:
|
||||
return _impl.splder(tck, n)
|
||||
|
||||
|
||||
def splantider(tck, n=1):
|
||||
"""
|
||||
Compute the spline for the antiderivative (integral) of a given spline.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tck : BSpline instance or a tuple of (t, c, k)
|
||||
Spline whose antiderivative to compute
|
||||
n : int, optional
|
||||
Order of antiderivative to evaluate. Default: 1
|
||||
|
||||
Returns
|
||||
-------
|
||||
BSpline instance or a tuple of (t2, c2, k2)
|
||||
Spline of order k2=k+n representing the antiderivative of the input
|
||||
spline.
|
||||
A tuple is returned iff the input argument `tck` is a tuple, otherwise
|
||||
a BSpline object is constructed and returned.
|
||||
|
||||
See Also
|
||||
--------
|
||||
splder, splev, spalde
|
||||
BSpline
|
||||
|
||||
Notes
|
||||
-----
|
||||
The `splder` function is the inverse operation of this function.
|
||||
Namely, ``splder(splantider(tck))`` is identical to `tck`, modulo
|
||||
rounding error.
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from scipy.interpolate import splrep, splder, splantider, splev
|
||||
>>> x = np.linspace(0, np.pi/2, 70)
|
||||
>>> y = 1 / np.sqrt(1 - 0.8*np.sin(x)**2)
|
||||
>>> spl = splrep(x, y)
|
||||
|
||||
The derivative is the inverse operation of the antiderivative,
|
||||
although some floating point error accumulates:
|
||||
|
||||
>>> splev(1.7, spl), splev(1.7, splder(splantider(spl)))
|
||||
(array(2.1565429877197317), array(2.1565429877201865))
|
||||
|
||||
Antiderivative can be used to evaluate definite integrals:
|
||||
|
||||
>>> ispl = splantider(spl)
|
||||
>>> splev(np.pi/2, ispl) - splev(0, ispl)
|
||||
2.2572053588768486
|
||||
|
||||
This is indeed an approximation to the complete elliptic integral
|
||||
:math:`K(m) = \\int_0^{\\pi/2} [1 - m\\sin^2 x]^{-1/2} dx`:
|
||||
|
||||
>>> from scipy.special import ellipk
|
||||
>>> ellipk(0.8)
|
||||
2.2572053268208538
|
||||
|
||||
"""
|
||||
if isinstance(tck, BSpline):
|
||||
return tck.antiderivative(n)
|
||||
else:
|
||||
return _impl.splantider(tck, n)
|
1819
venv/Lib/site-packages/scipy/interpolate/fitpack2.py
Normal file
1819
venv/Lib/site-packages/scipy/interpolate/fitpack2.py
Normal file
File diff suppressed because it is too large
Load diff
BIN
venv/Lib/site-packages/scipy/interpolate/interpnd.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/interpnd.cp36-win32.pyd
Normal file
Binary file not shown.
37
venv/Lib/site-packages/scipy/interpolate/interpnd_info.py
Normal file
37
venv/Lib/site-packages/scipy/interpolate/interpnd_info.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Here we perform some symbolic computations required for the N-D
|
||||
interpolation routines in `interpnd.pyx`.
|
||||
|
||||
"""
|
||||
from sympy import symbols, binomial, Matrix # type: ignore[import]
|
||||
|
||||
|
||||
def _estimate_gradients_2d_global():
|
||||
|
||||
#
|
||||
# Compute
|
||||
#
|
||||
#
|
||||
|
||||
f1, f2, df1, df2, x = symbols(['f1', 'f2', 'df1', 'df2', 'x'])
|
||||
c = [f1, (df1 + 3*f1)/3, (df2 + 3*f2)/3, f2]
|
||||
|
||||
w = 0
|
||||
for k in range(4):
|
||||
w += binomial(3, k) * c[k] * x**k*(1-x)**(3-k)
|
||||
|
||||
wpp = w.diff(x, 2).expand()
|
||||
intwpp2 = (wpp**2).integrate((x, 0, 1)).expand()
|
||||
|
||||
A = Matrix([[intwpp2.coeff(df1**2), intwpp2.coeff(df1*df2)/2],
|
||||
[intwpp2.coeff(df1*df2)/2, intwpp2.coeff(df2**2)]])
|
||||
|
||||
B = Matrix([[intwpp2.coeff(df1).subs(df2, 0)],
|
||||
[intwpp2.coeff(df2).subs(df1, 0)]]) / 2
|
||||
|
||||
print("A")
|
||||
print(A)
|
||||
print("B")
|
||||
print(B)
|
||||
print("solution")
|
||||
print(A.inv() * B)
|
2739
venv/Lib/site-packages/scipy/interpolate/interpolate.py
Normal file
2739
venv/Lib/site-packages/scipy/interpolate/interpolate.py
Normal file
File diff suppressed because it is too large
Load diff
227
venv/Lib/site-packages/scipy/interpolate/ndgriddata.py
Normal file
227
venv/Lib/site-packages/scipy/interpolate/ndgriddata.py
Normal file
|
@ -0,0 +1,227 @@
|
|||
"""
|
||||
Convenience interface to N-D interpolation
|
||||
|
||||
.. versionadded:: 0.9
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
from .interpnd import LinearNDInterpolator, NDInterpolatorBase, \
|
||||
CloughTocher2DInterpolator, _ndim_coords_from_arrays
|
||||
from scipy.spatial import cKDTree
|
||||
|
||||
__all__ = ['griddata', 'NearestNDInterpolator', 'LinearNDInterpolator',
|
||||
'CloughTocher2DInterpolator']
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Nearest-neighbor interpolation
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class NearestNDInterpolator(NDInterpolatorBase):
|
||||
"""
|
||||
NearestNDInterpolator(x, y)
|
||||
|
||||
Nearest-neighbor interpolation in N dimensions.
|
||||
|
||||
.. versionadded:: 0.9
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : (Npoints, Ndims) ndarray of floats
|
||||
Data point coordinates.
|
||||
y : (Npoints,) ndarray of float or complex
|
||||
Data values.
|
||||
rescale : boolean, optional
|
||||
Rescale points to unit cube before performing interpolation.
|
||||
This is useful if some of the input dimensions have
|
||||
incommensurable units and differ by many orders of magnitude.
|
||||
|
||||
.. versionadded:: 0.14.0
|
||||
tree_options : dict, optional
|
||||
Options passed to the underlying ``cKDTree``.
|
||||
|
||||
.. versionadded:: 0.17.0
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
Uses ``scipy.spatial.cKDTree``
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, x, y, rescale=False, tree_options=None):
|
||||
NDInterpolatorBase.__init__(self, x, y, rescale=rescale,
|
||||
need_contiguous=False,
|
||||
need_values=False)
|
||||
if tree_options is None:
|
||||
tree_options = dict()
|
||||
self.tree = cKDTree(self.points, **tree_options)
|
||||
self.values = np.asarray(y)
|
||||
|
||||
def __call__(self, *args):
|
||||
"""
|
||||
Evaluate interpolator at given points.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : ndarray of float, shape (..., ndim)
|
||||
Points where to interpolate data at.
|
||||
|
||||
"""
|
||||
xi = _ndim_coords_from_arrays(args, ndim=self.points.shape[1])
|
||||
xi = self._check_call_shape(xi)
|
||||
xi = self._scale_x(xi)
|
||||
dist, i = self.tree.query(xi)
|
||||
return self.values[i]
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Convenience interface function
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
def griddata(points, values, xi, method='linear', fill_value=np.nan,
|
||||
rescale=False):
|
||||
"""
|
||||
Interpolate unstructured D-D data.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
points : 2-D ndarray of floats with shape (n, D), or length D tuple of 1-D ndarrays with shape (n,).
|
||||
Data point coordinates.
|
||||
values : ndarray of float or complex, shape (n,)
|
||||
Data values.
|
||||
xi : 2-D ndarray of floats with shape (m, D), or length D tuple of ndarrays broadcastable to the same shape.
|
||||
Points at which to interpolate data.
|
||||
method : {'linear', 'nearest', 'cubic'}, optional
|
||||
Method of interpolation. One of
|
||||
|
||||
``nearest``
|
||||
return the value at the data point closest to
|
||||
the point of interpolation. See `NearestNDInterpolator` for
|
||||
more details.
|
||||
|
||||
``linear``
|
||||
tessellate the input point set to N-D
|
||||
simplices, and interpolate linearly on each simplex. See
|
||||
`LinearNDInterpolator` for more details.
|
||||
|
||||
``cubic`` (1-D)
|
||||
return the value determined from a cubic
|
||||
spline.
|
||||
|
||||
``cubic`` (2-D)
|
||||
return the value determined from a
|
||||
piecewise cubic, continuously differentiable (C1), and
|
||||
approximately curvature-minimizing polynomial surface. See
|
||||
`CloughTocher2DInterpolator` for more details.
|
||||
fill_value : float, optional
|
||||
Value used to fill in for requested points outside of the
|
||||
convex hull of the input points. If not provided, then the
|
||||
default is ``nan``. This option has no effect for the
|
||||
'nearest' method.
|
||||
rescale : bool, optional
|
||||
Rescale points to unit cube before performing interpolation.
|
||||
This is useful if some of the input dimensions have
|
||||
incommensurable units and differ by many orders of magnitude.
|
||||
|
||||
.. versionadded:: 0.14.0
|
||||
|
||||
Returns
|
||||
-------
|
||||
ndarray
|
||||
Array of interpolated values.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
.. versionadded:: 0.9
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Suppose we want to interpolate the 2-D function
|
||||
|
||||
>>> def func(x, y):
|
||||
... return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2
|
||||
|
||||
on a grid in [0, 1]x[0, 1]
|
||||
|
||||
>>> grid_x, grid_y = np.mgrid[0:1:100j, 0:1:200j]
|
||||
|
||||
but we only know its values at 1000 data points:
|
||||
|
||||
>>> points = np.random.rand(1000, 2)
|
||||
>>> values = func(points[:,0], points[:,1])
|
||||
|
||||
This can be done with `griddata` -- below we try out all of the
|
||||
interpolation methods:
|
||||
|
||||
>>> from scipy.interpolate import griddata
|
||||
>>> grid_z0 = griddata(points, values, (grid_x, grid_y), method='nearest')
|
||||
>>> grid_z1 = griddata(points, values, (grid_x, grid_y), method='linear')
|
||||
>>> grid_z2 = griddata(points, values, (grid_x, grid_y), method='cubic')
|
||||
|
||||
One can see that the exact result is reproduced by all of the
|
||||
methods to some degree, but for this smooth function the piecewise
|
||||
cubic interpolant gives the best results:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> plt.subplot(221)
|
||||
>>> plt.imshow(func(grid_x, grid_y).T, extent=(0,1,0,1), origin='lower')
|
||||
>>> plt.plot(points[:,0], points[:,1], 'k.', ms=1)
|
||||
>>> plt.title('Original')
|
||||
>>> plt.subplot(222)
|
||||
>>> plt.imshow(grid_z0.T, extent=(0,1,0,1), origin='lower')
|
||||
>>> plt.title('Nearest')
|
||||
>>> plt.subplot(223)
|
||||
>>> plt.imshow(grid_z1.T, extent=(0,1,0,1), origin='lower')
|
||||
>>> plt.title('Linear')
|
||||
>>> plt.subplot(224)
|
||||
>>> plt.imshow(grid_z2.T, extent=(0,1,0,1), origin='lower')
|
||||
>>> plt.title('Cubic')
|
||||
>>> plt.gcf().set_size_inches(6, 6)
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
|
||||
points = _ndim_coords_from_arrays(points)
|
||||
|
||||
if points.ndim < 2:
|
||||
ndim = points.ndim
|
||||
else:
|
||||
ndim = points.shape[-1]
|
||||
|
||||
if ndim == 1 and method in ('nearest', 'linear', 'cubic'):
|
||||
from .interpolate import interp1d
|
||||
points = points.ravel()
|
||||
if isinstance(xi, tuple):
|
||||
if len(xi) != 1:
|
||||
raise ValueError("invalid number of dimensions in xi")
|
||||
xi, = xi
|
||||
# Sort points/values together, necessary as input for interp1d
|
||||
idx = np.argsort(points)
|
||||
points = points[idx]
|
||||
values = values[idx]
|
||||
if method == 'nearest':
|
||||
fill_value = 'extrapolate'
|
||||
ip = interp1d(points, values, kind=method, axis=0, bounds_error=False,
|
||||
fill_value=fill_value)
|
||||
return ip(xi)
|
||||
elif method == 'nearest':
|
||||
ip = NearestNDInterpolator(points, values, rescale=rescale)
|
||||
return ip(xi)
|
||||
elif method == 'linear':
|
||||
ip = LinearNDInterpolator(points, values, fill_value=fill_value,
|
||||
rescale=rescale)
|
||||
return ip(xi)
|
||||
elif method == 'cubic' and ndim == 2:
|
||||
ip = CloughTocher2DInterpolator(points, values, fill_value=fill_value,
|
||||
rescale=rescale)
|
||||
return ip(xi)
|
||||
else:
|
||||
raise ValueError("Unknown interpolation method %r for "
|
||||
"%d dimensional data" % (method, ndim))
|
710
venv/Lib/site-packages/scipy/interpolate/polyint.py
Normal file
710
venv/Lib/site-packages/scipy/interpolate/polyint.py
Normal file
|
@ -0,0 +1,710 @@
|
|||
import numpy as np
|
||||
from scipy.special import factorial
|
||||
|
||||
from scipy._lib._util import _asarray_validated
|
||||
|
||||
|
||||
__all__ = ["KroghInterpolator", "krogh_interpolate", "BarycentricInterpolator",
|
||||
"barycentric_interpolate", "approximate_taylor_polynomial"]
|
||||
|
||||
|
||||
def _isscalar(x):
|
||||
"""Check whether x is if a scalar type, or 0-dim"""
|
||||
return np.isscalar(x) or hasattr(x, 'shape') and x.shape == ()
|
||||
|
||||
|
||||
class _Interpolator1D(object):
|
||||
"""
|
||||
Common features in univariate interpolation
|
||||
|
||||
Deal with input data type and interpolation axis rolling. The
|
||||
actual interpolator can assume the y-data is of shape (n, r) where
|
||||
`n` is the number of x-points, and `r` the number of variables,
|
||||
and use self.dtype as the y-data type.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
_y_axis
|
||||
Axis along which the interpolation goes in the original array
|
||||
_y_extra_shape
|
||||
Additional trailing shape of the input arrays, excluding
|
||||
the interpolation axis.
|
||||
dtype
|
||||
Dtype of the y-data arrays. Can be set via _set_dtype, which
|
||||
forces it to be float or complex.
|
||||
|
||||
Methods
|
||||
-------
|
||||
__call__
|
||||
_prepare_x
|
||||
_finish_y
|
||||
_reshape_yi
|
||||
_set_yi
|
||||
_set_dtype
|
||||
_evaluate
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ('_y_axis', '_y_extra_shape', 'dtype')
|
||||
|
||||
def __init__(self, xi=None, yi=None, axis=None):
|
||||
self._y_axis = axis
|
||||
self._y_extra_shape = None
|
||||
self.dtype = None
|
||||
if yi is not None:
|
||||
self._set_yi(yi, xi=xi, axis=axis)
|
||||
|
||||
def __call__(self, x):
|
||||
"""
|
||||
Evaluate the interpolant
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
Points to evaluate the interpolant at.
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : array_like
|
||||
Interpolated values. Shape is determined by replacing
|
||||
the interpolation axis in the original array with the shape of x.
|
||||
|
||||
"""
|
||||
x, x_shape = self._prepare_x(x)
|
||||
y = self._evaluate(x)
|
||||
return self._finish_y(y, x_shape)
|
||||
|
||||
def _evaluate(self, x):
|
||||
"""
|
||||
Actually evaluate the value of the interpolator.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _prepare_x(self, x):
|
||||
"""Reshape input x array to 1-D"""
|
||||
x = _asarray_validated(x, check_finite=False, as_inexact=True)
|
||||
x_shape = x.shape
|
||||
return x.ravel(), x_shape
|
||||
|
||||
def _finish_y(self, y, x_shape):
|
||||
"""Reshape interpolated y back to an N-D array similar to initial y"""
|
||||
y = y.reshape(x_shape + self._y_extra_shape)
|
||||
if self._y_axis != 0 and x_shape != ():
|
||||
nx = len(x_shape)
|
||||
ny = len(self._y_extra_shape)
|
||||
s = (list(range(nx, nx + self._y_axis))
|
||||
+ list(range(nx)) + list(range(nx+self._y_axis, nx+ny)))
|
||||
y = y.transpose(s)
|
||||
return y
|
||||
|
||||
def _reshape_yi(self, yi, check=False):
|
||||
yi = np.rollaxis(np.asarray(yi), self._y_axis)
|
||||
if check and yi.shape[1:] != self._y_extra_shape:
|
||||
ok_shape = "%r + (N,) + %r" % (self._y_extra_shape[-self._y_axis:],
|
||||
self._y_extra_shape[:-self._y_axis])
|
||||
raise ValueError("Data must be of shape %s" % ok_shape)
|
||||
return yi.reshape((yi.shape[0], -1))
|
||||
|
||||
def _set_yi(self, yi, xi=None, axis=None):
|
||||
if axis is None:
|
||||
axis = self._y_axis
|
||||
if axis is None:
|
||||
raise ValueError("no interpolation axis specified")
|
||||
|
||||
yi = np.asarray(yi)
|
||||
|
||||
shape = yi.shape
|
||||
if shape == ():
|
||||
shape = (1,)
|
||||
if xi is not None and shape[axis] != len(xi):
|
||||
raise ValueError("x and y arrays must be equal in length along "
|
||||
"interpolation axis.")
|
||||
|
||||
self._y_axis = (axis % yi.ndim)
|
||||
self._y_extra_shape = yi.shape[:self._y_axis]+yi.shape[self._y_axis+1:]
|
||||
self.dtype = None
|
||||
self._set_dtype(yi.dtype)
|
||||
|
||||
def _set_dtype(self, dtype, union=False):
|
||||
if np.issubdtype(dtype, np.complexfloating) \
|
||||
or np.issubdtype(self.dtype, np.complexfloating):
|
||||
self.dtype = np.complex_
|
||||
else:
|
||||
if not union or self.dtype != np.complex_:
|
||||
self.dtype = np.float_
|
||||
|
||||
|
||||
class _Interpolator1DWithDerivatives(_Interpolator1D):
|
||||
def derivatives(self, x, der=None):
|
||||
"""
|
||||
Evaluate many derivatives of the polynomial at the point x
|
||||
|
||||
Produce an array of all derivative values at the point x.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
Point or points at which to evaluate the derivatives
|
||||
der : int or None, optional
|
||||
How many derivatives to extract; None for all potentially
|
||||
nonzero derivatives (that is a number equal to the number
|
||||
of points). This number includes the function value as 0th
|
||||
derivative.
|
||||
|
||||
Returns
|
||||
-------
|
||||
d : ndarray
|
||||
Array with derivatives; d[j] contains the jth derivative.
|
||||
Shape of d[j] is determined by replacing the interpolation
|
||||
axis in the original array with the shape of x.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from scipy.interpolate import KroghInterpolator
|
||||
>>> KroghInterpolator([0,0,0],[1,2,3]).derivatives(0)
|
||||
array([1.0,2.0,3.0])
|
||||
>>> KroghInterpolator([0,0,0],[1,2,3]).derivatives([0,0])
|
||||
array([[1.0,1.0],
|
||||
[2.0,2.0],
|
||||
[3.0,3.0]])
|
||||
|
||||
"""
|
||||
x, x_shape = self._prepare_x(x)
|
||||
y = self._evaluate_derivatives(x, der)
|
||||
|
||||
y = y.reshape((y.shape[0],) + x_shape + self._y_extra_shape)
|
||||
if self._y_axis != 0 and x_shape != ():
|
||||
nx = len(x_shape)
|
||||
ny = len(self._y_extra_shape)
|
||||
s = ([0] + list(range(nx+1, nx + self._y_axis+1))
|
||||
+ list(range(1, nx+1)) +
|
||||
list(range(nx+1+self._y_axis, nx+ny+1)))
|
||||
y = y.transpose(s)
|
||||
return y
|
||||
|
||||
def derivative(self, x, der=1):
|
||||
"""
|
||||
Evaluate one derivative of the polynomial at the point x
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
Point or points at which to evaluate the derivatives
|
||||
|
||||
der : integer, optional
|
||||
Which derivative to extract. This number includes the
|
||||
function value as 0th derivative.
|
||||
|
||||
Returns
|
||||
-------
|
||||
d : ndarray
|
||||
Derivative interpolated at the x-points. Shape of d is
|
||||
determined by replacing the interpolation axis in the
|
||||
original array with the shape of x.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is computed by evaluating all derivatives up to the desired
|
||||
one (using self.derivatives()) and then discarding the rest.
|
||||
|
||||
"""
|
||||
x, x_shape = self._prepare_x(x)
|
||||
y = self._evaluate_derivatives(x, der+1)
|
||||
return self._finish_y(y[der], x_shape)
|
||||
|
||||
|
||||
class KroghInterpolator(_Interpolator1DWithDerivatives):
|
||||
"""
|
||||
Interpolating polynomial for a set of points.
|
||||
|
||||
The polynomial passes through all the pairs (xi,yi). One may
|
||||
additionally specify a number of derivatives at each point xi;
|
||||
this is done by repeating the value xi and specifying the
|
||||
derivatives as successive yi values.
|
||||
|
||||
Allows evaluation of the polynomial and all its derivatives.
|
||||
For reasons of numerical stability, this function does not compute
|
||||
the coefficients of the polynomial, although they can be obtained
|
||||
by evaluating all the derivatives.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like, length N
|
||||
Known x-coordinates. Must be sorted in increasing order.
|
||||
yi : array_like
|
||||
Known y-coordinates. When an xi occurs two or more times in
|
||||
a row, the corresponding yi's represent derivative values.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Be aware that the algorithms implemented here are not necessarily
|
||||
the most numerically stable known. Moreover, even in a world of
|
||||
exact computation, unless the x coordinates are chosen very
|
||||
carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
|
||||
polynomial interpolation itself is a very ill-conditioned process
|
||||
due to the Runge phenomenon. In general, even with well-chosen
|
||||
x values, degrees higher than about thirty cause problems with
|
||||
numerical instability in this code.
|
||||
|
||||
Based on [1]_.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Krogh, "Efficient Algorithms for Polynomial Interpolation
|
||||
and Numerical Differentiation", 1970.
|
||||
|
||||
Examples
|
||||
--------
|
||||
To produce a polynomial that is zero at 0 and 1 and has
|
||||
derivative 2 at 0, call
|
||||
|
||||
>>> from scipy.interpolate import KroghInterpolator
|
||||
>>> KroghInterpolator([0,0,1],[0,2,0])
|
||||
|
||||
This constructs the quadratic 2*X**2-2*X. The derivative condition
|
||||
is indicated by the repeated zero in the xi array; the corresponding
|
||||
yi values are 0, the function value, and 2, the derivative value.
|
||||
|
||||
For another example, given xi, yi, and a derivative ypi for each
|
||||
point, appropriate arrays can be constructed as:
|
||||
|
||||
>>> xi = np.linspace(0, 1, 5)
|
||||
>>> yi, ypi = np.random.rand(2, 5)
|
||||
>>> xi_k, yi_k = np.repeat(xi, 2), np.ravel(np.dstack((yi,ypi)))
|
||||
>>> KroghInterpolator(xi_k, yi_k)
|
||||
|
||||
To produce a vector-valued polynomial, supply a higher-dimensional
|
||||
array for yi:
|
||||
|
||||
>>> KroghInterpolator([0,1],[[2,3],[4,5]])
|
||||
|
||||
This constructs a linear polynomial giving (2,3) at 0 and (4,5) at 1.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, xi, yi, axis=0):
|
||||
_Interpolator1DWithDerivatives.__init__(self, xi, yi, axis)
|
||||
|
||||
self.xi = np.asarray(xi)
|
||||
self.yi = self._reshape_yi(yi)
|
||||
self.n, self.r = self.yi.shape
|
||||
|
||||
c = np.zeros((self.n+1, self.r), dtype=self.dtype)
|
||||
c[0] = self.yi[0]
|
||||
Vk = np.zeros((self.n, self.r), dtype=self.dtype)
|
||||
for k in range(1, self.n):
|
||||
s = 0
|
||||
while s <= k and xi[k-s] == xi[k]:
|
||||
s += 1
|
||||
s -= 1
|
||||
Vk[0] = self.yi[k]/float(factorial(s))
|
||||
for i in range(k-s):
|
||||
if xi[i] == xi[k]:
|
||||
raise ValueError("Elements if `xi` can't be equal.")
|
||||
if s == 0:
|
||||
Vk[i+1] = (c[i]-Vk[i])/(xi[i]-xi[k])
|
||||
else:
|
||||
Vk[i+1] = (Vk[i+1]-Vk[i])/(xi[i]-xi[k])
|
||||
c[k] = Vk[k-s]
|
||||
self.c = c
|
||||
|
||||
def _evaluate(self, x):
|
||||
pi = 1
|
||||
p = np.zeros((len(x), self.r), dtype=self.dtype)
|
||||
p += self.c[0,np.newaxis,:]
|
||||
for k in range(1, self.n):
|
||||
w = x - self.xi[k-1]
|
||||
pi = w*pi
|
||||
p += pi[:,np.newaxis] * self.c[k]
|
||||
return p
|
||||
|
||||
def _evaluate_derivatives(self, x, der=None):
|
||||
n = self.n
|
||||
r = self.r
|
||||
|
||||
if der is None:
|
||||
der = self.n
|
||||
pi = np.zeros((n, len(x)))
|
||||
w = np.zeros((n, len(x)))
|
||||
pi[0] = 1
|
||||
p = np.zeros((len(x), self.r), dtype=self.dtype)
|
||||
p += self.c[0, np.newaxis, :]
|
||||
|
||||
for k in range(1, n):
|
||||
w[k-1] = x - self.xi[k-1]
|
||||
pi[k] = w[k-1] * pi[k-1]
|
||||
p += pi[k, :, np.newaxis] * self.c[k]
|
||||
|
||||
cn = np.zeros((max(der, n+1), len(x), r), dtype=self.dtype)
|
||||
cn[:n+1, :, :] += self.c[:n+1, np.newaxis, :]
|
||||
cn[0] = p
|
||||
for k in range(1, n):
|
||||
for i in range(1, n-k+1):
|
||||
pi[i] = w[k+i-1]*pi[i-1] + pi[i]
|
||||
cn[k] = cn[k] + pi[i, :, np.newaxis]*cn[k+i]
|
||||
cn[k] *= factorial(k)
|
||||
|
||||
cn[n, :, :] = 0
|
||||
return cn[:der]
|
||||
|
||||
|
||||
def krogh_interpolate(xi, yi, x, der=0, axis=0):
|
||||
"""
|
||||
Convenience function for polynomial interpolation.
|
||||
|
||||
See `KroghInterpolator` for more details.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like
|
||||
Known x-coordinates.
|
||||
yi : array_like
|
||||
Known y-coordinates, of shape ``(xi.size, R)``. Interpreted as
|
||||
vectors of length R, or scalars if R=1.
|
||||
x : array_like
|
||||
Point or points at which to evaluate the derivatives.
|
||||
der : int or list, optional
|
||||
How many derivatives to extract; None for all potentially
|
||||
nonzero derivatives (that is a number equal to the number
|
||||
of points), or a list of derivatives to extract. This number
|
||||
includes the function value as 0th derivative.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
Returns
|
||||
-------
|
||||
d : ndarray
|
||||
If the interpolator's values are R-D then the
|
||||
returned array will be the number of derivatives by N by R.
|
||||
If `x` is a scalar, the middle dimension will be dropped; if
|
||||
the `yi` are scalars then the last dimension will be dropped.
|
||||
|
||||
See Also
|
||||
--------
|
||||
KroghInterpolator : Krogh interpolator
|
||||
|
||||
Notes
|
||||
-----
|
||||
Construction of the interpolating polynomial is a relatively expensive
|
||||
process. If you want to evaluate it repeatedly consider using the class
|
||||
KroghInterpolator (which is what this function uses).
|
||||
|
||||
Examples
|
||||
--------
|
||||
We can interpolate 2D observed data using krogh interpolation:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> from scipy.interpolate import krogh_interpolate
|
||||
>>> x_observed = np.linspace(0.0, 10.0, 11)
|
||||
>>> y_observed = np.sin(x_observed)
|
||||
>>> x = np.linspace(min(x_observed), max(x_observed), num=100)
|
||||
>>> y = krogh_interpolate(x_observed, y_observed, x)
|
||||
>>> plt.plot(x_observed, y_observed, "o", label="observation")
|
||||
>>> plt.plot(x, y, label="krogh interpolation")
|
||||
>>> plt.legend()
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
P = KroghInterpolator(xi, yi, axis=axis)
|
||||
if der == 0:
|
||||
return P(x)
|
||||
elif _isscalar(der):
|
||||
return P.derivative(x,der=der)
|
||||
else:
|
||||
return P.derivatives(x,der=np.amax(der)+1)[der]
|
||||
|
||||
|
||||
def approximate_taylor_polynomial(f,x,degree,scale,order=None):
|
||||
"""
|
||||
Estimate the Taylor polynomial of f at x by polynomial fitting.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
f : callable
|
||||
The function whose Taylor polynomial is sought. Should accept
|
||||
a vector of `x` values.
|
||||
x : scalar
|
||||
The point at which the polynomial is to be evaluated.
|
||||
degree : int
|
||||
The degree of the Taylor polynomial
|
||||
scale : scalar
|
||||
The width of the interval to use to evaluate the Taylor polynomial.
|
||||
Function values spread over a range this wide are used to fit the
|
||||
polynomial. Must be chosen carefully.
|
||||
order : int or None, optional
|
||||
The order of the polynomial to be used in the fitting; `f` will be
|
||||
evaluated ``order+1`` times. If None, use `degree`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : poly1d instance
|
||||
The Taylor polynomial (translated to the origin, so that
|
||||
for example p(0)=f(x)).
|
||||
|
||||
Notes
|
||||
-----
|
||||
The appropriate choice of "scale" is a trade-off; too large and the
|
||||
function differs from its Taylor polynomial too much to get a good
|
||||
answer, too small and round-off errors overwhelm the higher-order terms.
|
||||
The algorithm used becomes numerically unstable around order 30 even
|
||||
under ideal circumstances.
|
||||
|
||||
Choosing order somewhat larger than degree may improve the higher-order
|
||||
terms.
|
||||
|
||||
Examples
|
||||
--------
|
||||
We can calculate Taylor approximation polynomials of sin function with
|
||||
various degrees:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> from scipy.interpolate import approximate_taylor_polynomial
|
||||
>>> x = np.linspace(-10.0, 10.0, num=100)
|
||||
>>> plt.plot(x, np.sin(x), label="sin curve")
|
||||
>>> for degree in np.arange(1, 15, step=2):
|
||||
... sin_taylor = approximate_taylor_polynomial(np.sin, 0, degree, 1,
|
||||
... order=degree + 2)
|
||||
... plt.plot(x, sin_taylor(x), label=f"degree={degree}")
|
||||
>>> plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left',
|
||||
... borderaxespad=0.0, shadow=True)
|
||||
>>> plt.tight_layout()
|
||||
>>> plt.axis([-10, 10, -10, 10])
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
if order is None:
|
||||
order = degree
|
||||
|
||||
n = order+1
|
||||
# Choose n points that cluster near the endpoints of the interval in
|
||||
# a way that avoids the Runge phenomenon. Ensure, by including the
|
||||
# endpoint or not as appropriate, that one point always falls at x
|
||||
# exactly.
|
||||
xs = scale*np.cos(np.linspace(0,np.pi,n,endpoint=n % 1)) + x
|
||||
|
||||
P = KroghInterpolator(xs, f(xs))
|
||||
d = P.derivatives(x,der=degree+1)
|
||||
|
||||
return np.poly1d((d/factorial(np.arange(degree+1)))[::-1])
|
||||
|
||||
|
||||
class BarycentricInterpolator(_Interpolator1D):
|
||||
"""The interpolating polynomial for a set of points
|
||||
|
||||
Constructs a polynomial that passes through a given set of points.
|
||||
Allows evaluation of the polynomial, efficient changing of the y
|
||||
values to be interpolated, and updating by adding more x values.
|
||||
For reasons of numerical stability, this function does not compute
|
||||
the coefficients of the polynomial.
|
||||
|
||||
The values yi need to be provided before the function is
|
||||
evaluated, but none of the preprocessing depends on them, so rapid
|
||||
updates are possible.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like
|
||||
1-D array of x coordinates of the points the polynomial
|
||||
should pass through
|
||||
yi : array_like, optional
|
||||
The y coordinates of the points the polynomial should pass through.
|
||||
If None, the y values will be supplied later via the `set_y` method.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This class uses a "barycentric interpolation" method that treats
|
||||
the problem as a special case of rational function interpolation.
|
||||
This algorithm is quite stable, numerically, but even in a world of
|
||||
exact computation, unless the x coordinates are chosen very
|
||||
carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
|
||||
polynomial interpolation itself is a very ill-conditioned process
|
||||
due to the Runge phenomenon.
|
||||
|
||||
Based on Berrut and Trefethen 2004, "Barycentric Lagrange Interpolation".
|
||||
|
||||
"""
|
||||
def __init__(self, xi, yi=None, axis=0):
|
||||
_Interpolator1D.__init__(self, xi, yi, axis)
|
||||
|
||||
self.xi = np.asfarray(xi)
|
||||
self.set_yi(yi)
|
||||
self.n = len(self.xi)
|
||||
|
||||
self.wi = np.zeros(self.n)
|
||||
self.wi[0] = 1
|
||||
for j in range(1, self.n):
|
||||
self.wi[:j] *= (self.xi[j]-self.xi[:j])
|
||||
self.wi[j] = np.multiply.reduce(self.xi[:j]-self.xi[j])
|
||||
self.wi **= -1
|
||||
|
||||
def set_yi(self, yi, axis=None):
|
||||
"""
|
||||
Update the y values to be interpolated
|
||||
|
||||
The barycentric interpolation algorithm requires the calculation
|
||||
of weights, but these depend only on the xi. The yi can be changed
|
||||
at any time.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
yi : array_like
|
||||
The y coordinates of the points the polynomial should pass through.
|
||||
If None, the y values will be supplied later.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
"""
|
||||
if yi is None:
|
||||
self.yi = None
|
||||
return
|
||||
self._set_yi(yi, xi=self.xi, axis=axis)
|
||||
self.yi = self._reshape_yi(yi)
|
||||
self.n, self.r = self.yi.shape
|
||||
|
||||
def add_xi(self, xi, yi=None):
|
||||
"""
|
||||
Add more x values to the set to be interpolated
|
||||
|
||||
The barycentric interpolation algorithm allows easy updating by
|
||||
adding more points for the polynomial to pass through.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like
|
||||
The x coordinates of the points that the polynomial should pass
|
||||
through.
|
||||
yi : array_like, optional
|
||||
The y coordinates of the points the polynomial should pass through.
|
||||
Should have shape ``(xi.size, R)``; if R > 1 then the polynomial is
|
||||
vector-valued.
|
||||
If `yi` is not given, the y values will be supplied later. `yi` should
|
||||
be given if and only if the interpolator has y values specified.
|
||||
|
||||
"""
|
||||
if yi is not None:
|
||||
if self.yi is None:
|
||||
raise ValueError("No previous yi value to update!")
|
||||
yi = self._reshape_yi(yi, check=True)
|
||||
self.yi = np.vstack((self.yi,yi))
|
||||
else:
|
||||
if self.yi is not None:
|
||||
raise ValueError("No update to yi provided!")
|
||||
old_n = self.n
|
||||
self.xi = np.concatenate((self.xi,xi))
|
||||
self.n = len(self.xi)
|
||||
self.wi **= -1
|
||||
old_wi = self.wi
|
||||
self.wi = np.zeros(self.n)
|
||||
self.wi[:old_n] = old_wi
|
||||
for j in range(old_n, self.n):
|
||||
self.wi[:j] *= (self.xi[j]-self.xi[:j])
|
||||
self.wi[j] = np.multiply.reduce(self.xi[:j]-self.xi[j])
|
||||
self.wi **= -1
|
||||
|
||||
def __call__(self, x):
|
||||
"""Evaluate the interpolating polynomial at the points x
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
Points to evaluate the interpolant at.
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : array_like
|
||||
Interpolated values. Shape is determined by replacing
|
||||
the interpolation axis in the original array with the shape of x.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Currently the code computes an outer product between x and the
|
||||
weights, that is, it constructs an intermediate array of size
|
||||
N by len(x), where N is the degree of the polynomial.
|
||||
"""
|
||||
return _Interpolator1D.__call__(self, x)
|
||||
|
||||
def _evaluate(self, x):
|
||||
if x.size == 0:
|
||||
p = np.zeros((0, self.r), dtype=self.dtype)
|
||||
else:
|
||||
c = x[...,np.newaxis]-self.xi
|
||||
z = c == 0
|
||||
c[z] = 1
|
||||
c = self.wi/c
|
||||
p = np.dot(c,self.yi)/np.sum(c,axis=-1)[...,np.newaxis]
|
||||
# Now fix where x==some xi
|
||||
r = np.nonzero(z)
|
||||
if len(r) == 1: # evaluation at a scalar
|
||||
if len(r[0]) > 0: # equals one of the points
|
||||
p = self.yi[r[0][0]]
|
||||
else:
|
||||
p[r[:-1]] = self.yi[r[-1]]
|
||||
return p
|
||||
|
||||
|
||||
def barycentric_interpolate(xi, yi, x, axis=0):
|
||||
"""
|
||||
Convenience function for polynomial interpolation.
|
||||
|
||||
Constructs a polynomial that passes through a given set of points,
|
||||
then evaluates the polynomial. For reasons of numerical stability,
|
||||
this function does not compute the coefficients of the polynomial.
|
||||
|
||||
This function uses a "barycentric interpolation" method that treats
|
||||
the problem as a special case of rational function interpolation.
|
||||
This algorithm is quite stable, numerically, but even in a world of
|
||||
exact computation, unless the `x` coordinates are chosen very
|
||||
carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
|
||||
polynomial interpolation itself is a very ill-conditioned process
|
||||
due to the Runge phenomenon.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xi : array_like
|
||||
1-D array of x coordinates of the points the polynomial should
|
||||
pass through
|
||||
yi : array_like
|
||||
The y coordinates of the points the polynomial should pass through.
|
||||
x : scalar or array_like
|
||||
Points to evaluate the interpolator at.
|
||||
axis : int, optional
|
||||
Axis in the yi array corresponding to the x-coordinate values.
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : scalar or array_like
|
||||
Interpolated values. Shape is determined by replacing
|
||||
the interpolation axis in the original array with the shape of x.
|
||||
|
||||
See Also
|
||||
--------
|
||||
BarycentricInterpolator : Bary centric interpolator
|
||||
|
||||
Notes
|
||||
-----
|
||||
Construction of the interpolation weights is a relatively slow process.
|
||||
If you want to call this many times with the same xi (but possibly
|
||||
varying yi or x) you should use the class `BarycentricInterpolator`.
|
||||
This is what this function uses internally.
|
||||
|
||||
Examples
|
||||
--------
|
||||
We can interpolate 2D observed data using barycentric interpolation:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> from scipy.interpolate import barycentric_interpolate
|
||||
>>> x_observed = np.linspace(0.0, 10.0, 11)
|
||||
>>> y_observed = np.sin(x_observed)
|
||||
>>> x = np.linspace(min(x_observed), max(x_observed), num=100)
|
||||
>>> y = barycentric_interpolate(x_observed, y_observed, x)
|
||||
>>> plt.plot(x_observed, y_observed, "o", label="observation")
|
||||
>>> plt.plot(x, y, label="barycentric interpolation")
|
||||
>>> plt.legend()
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
return BarycentricInterpolator(xi, yi, axis=axis)(x)
|
279
venv/Lib/site-packages/scipy/interpolate/rbf.py
Normal file
279
venv/Lib/site-packages/scipy/interpolate/rbf.py
Normal file
|
@ -0,0 +1,279 @@
|
|||
"""rbf - Radial basis functions for interpolation/smoothing scattered N-D data.
|
||||
|
||||
Written by John Travers <jtravs@gmail.com>, February 2007
|
||||
Based closely on Matlab code by Alex Chirokov
|
||||
Additional, large, improvements by Robert Hetland
|
||||
Some additional alterations by Travis Oliphant
|
||||
Interpolation with multi-dimensional target domain by Josua Sassen
|
||||
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the SciPy (BSD style) license. See LICENSE.txt that came with
|
||||
this distribution for specifics.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
Copyright (c) 2006-2007, Robert Hetland <hetland@tamu.edu>
|
||||
Copyright (c) 2007, John Travers <jtravs@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Robert Hetland nor the names of any
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
from scipy import linalg
|
||||
from scipy.special import xlogy
|
||||
from scipy.spatial.distance import cdist, pdist, squareform
|
||||
|
||||
__all__ = ['Rbf']
|
||||
|
||||
|
||||
class Rbf(object):
|
||||
"""
|
||||
Rbf(*args)
|
||||
|
||||
A class for radial basis function interpolation of functions from
|
||||
N-D scattered data to an M-D domain.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*args : arrays
|
||||
x, y, z, ..., d, where x, y, z, ... are the coordinates of the nodes
|
||||
and d is the array of values at the nodes
|
||||
function : str or callable, optional
|
||||
The radial basis function, based on the radius, r, given by the norm
|
||||
(default is Euclidean distance); the default is 'multiquadric'::
|
||||
|
||||
'multiquadric': sqrt((r/self.epsilon)**2 + 1)
|
||||
'inverse': 1.0/sqrt((r/self.epsilon)**2 + 1)
|
||||
'gaussian': exp(-(r/self.epsilon)**2)
|
||||
'linear': r
|
||||
'cubic': r**3
|
||||
'quintic': r**5
|
||||
'thin_plate': r**2 * log(r)
|
||||
|
||||
If callable, then it must take 2 arguments (self, r). The epsilon
|
||||
parameter will be available as self.epsilon. Other keyword
|
||||
arguments passed in will be available as well.
|
||||
|
||||
epsilon : float, optional
|
||||
Adjustable constant for gaussian or multiquadrics functions
|
||||
- defaults to approximate average distance between nodes (which is
|
||||
a good start).
|
||||
smooth : float, optional
|
||||
Values greater than zero increase the smoothness of the
|
||||
approximation. 0 is for interpolation (default), the function will
|
||||
always go through the nodal points in this case.
|
||||
norm : str, callable, optional
|
||||
A function that returns the 'distance' between two points, with
|
||||
inputs as arrays of positions (x, y, z, ...), and an output as an
|
||||
array of distance. E.g., the default: 'euclidean', such that the result
|
||||
is a matrix of the distances from each point in ``x1`` to each point in
|
||||
``x2``. For more options, see documentation of
|
||||
`scipy.spatial.distances.cdist`.
|
||||
mode : str, optional
|
||||
Mode of the interpolation, can be '1-D' (default) or 'N-D'. When it is
|
||||
'1-D' the data `d` will be considered as 1-D and flattened
|
||||
internally. When it is 'N-D' the data `d` is assumed to be an array of
|
||||
shape (n_samples, m), where m is the dimension of the target domain.
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
N : int
|
||||
The number of data points (as determined by the input arrays).
|
||||
di : ndarray
|
||||
The 1-D array of data values at each of the data coordinates `xi`.
|
||||
xi : ndarray
|
||||
The 2-D array of data coordinates.
|
||||
function : str or callable
|
||||
The radial basis function. See description under Parameters.
|
||||
epsilon : float
|
||||
Parameter used by gaussian or multiquadrics functions. See Parameters.
|
||||
smooth : float
|
||||
Smoothing parameter. See description under Parameters.
|
||||
norm : str or callable
|
||||
The distance function. See description under Parameters.
|
||||
mode : str
|
||||
Mode of the interpolation. See description under Parameters.
|
||||
nodes : ndarray
|
||||
A 1-D array of node values for the interpolation.
|
||||
A : internal property, do not use
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from scipy.interpolate import Rbf
|
||||
>>> x, y, z, d = np.random.rand(4, 50)
|
||||
>>> rbfi = Rbf(x, y, z, d) # radial basis function interpolator instance
|
||||
>>> xi = yi = zi = np.linspace(0, 1, 20)
|
||||
>>> di = rbfi(xi, yi, zi) # interpolated values
|
||||
>>> di.shape
|
||||
(20,)
|
||||
|
||||
"""
|
||||
# Available radial basis functions that can be selected as strings;
|
||||
# they all start with _h_ (self._init_function relies on that)
|
||||
def _h_multiquadric(self, r):
|
||||
return np.sqrt((1.0/self.epsilon*r)**2 + 1)
|
||||
|
||||
def _h_inverse_multiquadric(self, r):
|
||||
return 1.0/np.sqrt((1.0/self.epsilon*r)**2 + 1)
|
||||
|
||||
def _h_gaussian(self, r):
|
||||
return np.exp(-(1.0/self.epsilon*r)**2)
|
||||
|
||||
def _h_linear(self, r):
|
||||
return r
|
||||
|
||||
def _h_cubic(self, r):
|
||||
return r**3
|
||||
|
||||
def _h_quintic(self, r):
|
||||
return r**5
|
||||
|
||||
def _h_thin_plate(self, r):
|
||||
return xlogy(r**2, r)
|
||||
|
||||
# Setup self._function and do smoke test on initial r
|
||||
def _init_function(self, r):
|
||||
if isinstance(self.function, str):
|
||||
self.function = self.function.lower()
|
||||
_mapped = {'inverse': 'inverse_multiquadric',
|
||||
'inverse multiquadric': 'inverse_multiquadric',
|
||||
'thin-plate': 'thin_plate'}
|
||||
if self.function in _mapped:
|
||||
self.function = _mapped[self.function]
|
||||
|
||||
func_name = "_h_" + self.function
|
||||
if hasattr(self, func_name):
|
||||
self._function = getattr(self, func_name)
|
||||
else:
|
||||
functionlist = [x[3:] for x in dir(self)
|
||||
if x.startswith('_h_')]
|
||||
raise ValueError("function must be a callable or one of " +
|
||||
", ".join(functionlist))
|
||||
self._function = getattr(self, "_h_"+self.function)
|
||||
elif callable(self.function):
|
||||
allow_one = False
|
||||
if hasattr(self.function, 'func_code') or \
|
||||
hasattr(self.function, '__code__'):
|
||||
val = self.function
|
||||
allow_one = True
|
||||
elif hasattr(self.function, "__call__"):
|
||||
val = self.function.__call__.__func__
|
||||
else:
|
||||
raise ValueError("Cannot determine number of arguments to "
|
||||
"function")
|
||||
|
||||
argcount = val.__code__.co_argcount
|
||||
if allow_one and argcount == 1:
|
||||
self._function = self.function
|
||||
elif argcount == 2:
|
||||
self._function = self.function.__get__(self, Rbf)
|
||||
else:
|
||||
raise ValueError("Function argument must take 1 or 2 "
|
||||
"arguments.")
|
||||
|
||||
a0 = self._function(r)
|
||||
if a0.shape != r.shape:
|
||||
raise ValueError("Callable must take array and return array of "
|
||||
"the same shape")
|
||||
return a0
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# `args` can be a variable number of arrays; we flatten them and store
|
||||
# them as a single 2-D array `xi` of shape (n_args-1, array_size),
|
||||
# plus a 1-D array `di` for the values.
|
||||
# All arrays must have the same number of elements
|
||||
self.xi = np.asarray([np.asarray(a, dtype=np.float_).flatten()
|
||||
for a in args[:-1]])
|
||||
self.N = self.xi.shape[-1]
|
||||
|
||||
self.mode = kwargs.pop('mode', '1-D')
|
||||
|
||||
if self.mode == '1-D':
|
||||
self.di = np.asarray(args[-1]).flatten()
|
||||
self._target_dim = 1
|
||||
elif self.mode == 'N-D':
|
||||
self.di = np.asarray(args[-1])
|
||||
self._target_dim = self.di.shape[-1]
|
||||
else:
|
||||
raise ValueError("Mode has to be 1-D or N-D.")
|
||||
|
||||
if not all([x.size == self.di.shape[0] for x in self.xi]):
|
||||
raise ValueError("All arrays must be equal length.")
|
||||
|
||||
self.norm = kwargs.pop('norm', 'euclidean')
|
||||
self.epsilon = kwargs.pop('epsilon', None)
|
||||
if self.epsilon is None:
|
||||
# default epsilon is the "the average distance between nodes" based
|
||||
# on a bounding hypercube
|
||||
ximax = np.amax(self.xi, axis=1)
|
||||
ximin = np.amin(self.xi, axis=1)
|
||||
edges = ximax - ximin
|
||||
edges = edges[np.nonzero(edges)]
|
||||
self.epsilon = np.power(np.prod(edges)/self.N, 1.0/edges.size)
|
||||
|
||||
self.smooth = kwargs.pop('smooth', 0.0)
|
||||
self.function = kwargs.pop('function', 'multiquadric')
|
||||
|
||||
# attach anything left in kwargs to self for use by any user-callable
|
||||
# function or to save on the object returned.
|
||||
for item, value in kwargs.items():
|
||||
setattr(self, item, value)
|
||||
|
||||
# Compute weights
|
||||
if self._target_dim > 1: # If we have more than one target dimension,
|
||||
# we first factorize the matrix
|
||||
self.nodes = np.zeros((self.N, self._target_dim), dtype=self.di.dtype)
|
||||
lu, piv = linalg.lu_factor(self.A)
|
||||
for i in range(self._target_dim):
|
||||
self.nodes[:, i] = linalg.lu_solve((lu, piv), self.di[:, i])
|
||||
else:
|
||||
self.nodes = linalg.solve(self.A, self.di)
|
||||
|
||||
@property
|
||||
def A(self):
|
||||
# this only exists for backwards compatibility: self.A was available
|
||||
# and, at least technically, public.
|
||||
r = squareform(pdist(self.xi.T, self.norm)) # Pairwise norm
|
||||
return self._init_function(r) - np.eye(self.N)*self.smooth
|
||||
|
||||
def _call_norm(self, x1, x2):
|
||||
return cdist(x1.T, x2.T, self.norm)
|
||||
|
||||
def __call__(self, *args):
|
||||
args = [np.asarray(x) for x in args]
|
||||
if not all([x.shape == y.shape for x in args for y in args]):
|
||||
raise ValueError("Array lengths must be equal")
|
||||
if self._target_dim > 1:
|
||||
shp = args[0].shape + (self._target_dim,)
|
||||
else:
|
||||
shp = args[0].shape
|
||||
xa = np.asarray([a.flatten() for a in args], dtype=np.float_)
|
||||
r = self._call_norm(xa, self.xi)
|
||||
return np.dot(self._function(r), self.nodes).reshape(shp)
|
63
venv/Lib/site-packages/scipy/interpolate/setup.py
Normal file
63
venv/Lib/site-packages/scipy/interpolate/setup.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
from os.path import join
|
||||
|
||||
|
||||
def configuration(parent_package='',top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration
|
||||
from scipy._build_utils import (get_f2py_int64_options,
|
||||
ilp64_pre_build_hook,
|
||||
uses_blas64)
|
||||
|
||||
if uses_blas64():
|
||||
# TODO: Note that fitpack does not use BLAS/LAPACK.
|
||||
# The reason why we use 64-bit ints only in this case
|
||||
# is because scipy._build_utils knows the 64-bit int
|
||||
# flags for too few Fortran compilers, so we cannot turn
|
||||
# this on by default.
|
||||
pre_build_hook = ilp64_pre_build_hook
|
||||
f2py_options = get_f2py_int64_options()
|
||||
define_macros = [("HAVE_ILP64", None)]
|
||||
else:
|
||||
pre_build_hook = None
|
||||
f2py_options = None
|
||||
define_macros = []
|
||||
|
||||
config = Configuration('interpolate', parent_package, top_path)
|
||||
|
||||
fitpack_src = [join('fitpack', '*.f')]
|
||||
config.add_library('fitpack', sources=fitpack_src,
|
||||
_pre_build_hook=pre_build_hook)
|
||||
|
||||
config.add_extension('interpnd',
|
||||
sources=['interpnd.c'])
|
||||
|
||||
config.add_extension('_ppoly',
|
||||
sources=['_ppoly.c'])
|
||||
|
||||
config.add_extension('_bspl',
|
||||
sources=['_bspl.c'],
|
||||
depends=['src/__fitpack.h'])
|
||||
|
||||
config.add_extension('_fitpack',
|
||||
sources=['src/_fitpackmodule.c'],
|
||||
libraries=['fitpack'],
|
||||
define_macros=define_macros,
|
||||
depends=(['src/__fitpack.h']
|
||||
+ fitpack_src)
|
||||
)
|
||||
|
||||
config.add_extension('dfitpack',
|
||||
sources=['src/fitpack.pyf'],
|
||||
libraries=['fitpack'],
|
||||
define_macros=define_macros,
|
||||
depends=fitpack_src,
|
||||
f2py_options=f2py_options
|
||||
)
|
||||
|
||||
config.add_data_dir('tests')
|
||||
|
||||
return config
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(**configuration(top_path='').todict())
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/interpolate/tests/data/bug-1310.npz
Normal file
BIN
venv/Lib/site-packages/scipy/interpolate/tests/data/bug-1310.npz
Normal file
Binary file not shown.
Binary file not shown.
1257
venv/Lib/site-packages/scipy/interpolate/tests/test_bsplines.py
Normal file
1257
venv/Lib/site-packages/scipy/interpolate/tests/test_bsplines.py
Normal file
File diff suppressed because it is too large
Load diff
491
venv/Lib/site-packages/scipy/interpolate/tests/test_fitpack.py
Normal file
491
venv/Lib/site-packages/scipy/interpolate/tests/test_fitpack.py
Normal file
|
@ -0,0 +1,491 @@
|
|||
import itertools
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import (assert_equal, assert_allclose, assert_,
|
||||
assert_almost_equal, assert_array_almost_equal)
|
||||
from pytest import raises as assert_raises
|
||||
import pytest
|
||||
from scipy._lib._testutils import check_free_memory
|
||||
|
||||
from numpy import array, asarray, pi, sin, cos, arange, dot, ravel, sqrt, round
|
||||
from scipy import interpolate
|
||||
from scipy.interpolate.fitpack import (splrep, splev, bisplrep, bisplev,
|
||||
sproot, splprep, splint, spalde, splder, splantider, insert, dblint)
|
||||
from scipy.interpolate.dfitpack import regrid_smth
|
||||
from scipy.interpolate.fitpack2 import dfitpack_int
|
||||
|
||||
|
||||
def data_file(basename):
|
||||
return os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'data', basename)
|
||||
|
||||
|
||||
def norm2(x):
|
||||
return sqrt(dot(x.T,x))
|
||||
|
||||
|
||||
def f1(x,d=0):
|
||||
if d is None:
|
||||
return "sin"
|
||||
if x is None:
|
||||
return "sin(x)"
|
||||
if d % 4 == 0:
|
||||
return sin(x)
|
||||
if d % 4 == 1:
|
||||
return cos(x)
|
||||
if d % 4 == 2:
|
||||
return -sin(x)
|
||||
if d % 4 == 3:
|
||||
return -cos(x)
|
||||
|
||||
|
||||
def f2(x,y=0,dx=0,dy=0):
|
||||
if x is None:
|
||||
return "sin(x+y)"
|
||||
d = dx+dy
|
||||
if d % 4 == 0:
|
||||
return sin(x+y)
|
||||
if d % 4 == 1:
|
||||
return cos(x+y)
|
||||
if d % 4 == 2:
|
||||
return -sin(x+y)
|
||||
if d % 4 == 3:
|
||||
return -cos(x+y)
|
||||
|
||||
|
||||
def makepairs(x, y):
|
||||
"""Helper function to create an array of pairs of x and y."""
|
||||
xy = array(list(itertools.product(asarray(x), asarray(y))))
|
||||
return xy.T
|
||||
|
||||
|
||||
def put(*a):
|
||||
"""Produce some output if file run directly"""
|
||||
import sys
|
||||
if hasattr(sys.modules['__main__'], '__put_prints'):
|
||||
sys.stderr.write("".join(map(str, a)) + "\n")
|
||||
|
||||
|
||||
class TestSmokeTests(object):
|
||||
"""
|
||||
Smoke tests (with a few asserts) for fitpack routines -- mostly
|
||||
check that they are runnable
|
||||
"""
|
||||
|
||||
def check_1(self,f=f1,per=0,s=0,a=0,b=2*pi,N=20,at=0,xb=None,xe=None):
|
||||
if xb is None:
|
||||
xb = a
|
||||
if xe is None:
|
||||
xe = b
|
||||
x = a+(b-a)*arange(N+1,dtype=float)/float(N) # nodes
|
||||
x1 = a+(b-a)*arange(1,N,dtype=float)/float(N-1) # middle points of the nodes
|
||||
v = f(x)
|
||||
nk = []
|
||||
|
||||
def err_est(k, d):
|
||||
# Assume f has all derivatives < 1
|
||||
h = 1.0/float(N)
|
||||
tol = 5 * h**(.75*(k-d))
|
||||
if s > 0:
|
||||
tol += 1e5*s
|
||||
return tol
|
||||
|
||||
for k in range(1,6):
|
||||
tck = splrep(x,v,s=s,per=per,k=k,xe=xe)
|
||||
if at:
|
||||
t = tck[0][k:-k]
|
||||
else:
|
||||
t = x1
|
||||
nd = []
|
||||
for d in range(k+1):
|
||||
tol = err_est(k, d)
|
||||
err = norm2(f(t,d)-splev(t,tck,d)) / norm2(f(t,d))
|
||||
assert_(err < tol, (k, d, err, tol))
|
||||
nd.append((err, tol))
|
||||
nk.append(nd)
|
||||
put("\nf = %s s=S_k(x;t,c) x in [%s, %s] > [%s, %s]" % (f(None),
|
||||
repr(round(xb,3)),repr(round(xe,3)),
|
||||
repr(round(a,3)),repr(round(b,3))))
|
||||
if at:
|
||||
str = "at knots"
|
||||
else:
|
||||
str = "at the middle of nodes"
|
||||
put(" per=%d s=%s Evaluation %s" % (per,repr(s),str))
|
||||
put(" k : |f-s|^2 |f'-s'| |f''-.. |f'''-. |f''''- |f'''''")
|
||||
k = 1
|
||||
for l in nk:
|
||||
put(' %d : ' % k)
|
||||
for r in l:
|
||||
put(' %.1e %.1e' % r)
|
||||
put('\n')
|
||||
k = k+1
|
||||
|
||||
def check_2(self,f=f1,per=0,s=0,a=0,b=2*pi,N=20,xb=None,xe=None,
|
||||
ia=0,ib=2*pi,dx=0.2*pi):
|
||||
if xb is None:
|
||||
xb = a
|
||||
if xe is None:
|
||||
xe = b
|
||||
x = a+(b-a)*arange(N+1,dtype=float)/float(N) # nodes
|
||||
v = f(x)
|
||||
|
||||
def err_est(k, d):
|
||||
# Assume f has all derivatives < 1
|
||||
h = 1.0/float(N)
|
||||
tol = 5 * h**(.75*(k-d))
|
||||
if s > 0:
|
||||
tol += 1e5*s
|
||||
return tol
|
||||
|
||||
nk = []
|
||||
for k in range(1,6):
|
||||
tck = splrep(x,v,s=s,per=per,k=k,xe=xe)
|
||||
nk.append([splint(ia,ib,tck),spalde(dx,tck)])
|
||||
put("\nf = %s s=S_k(x;t,c) x in [%s, %s] > [%s, %s]" % (f(None),
|
||||
repr(round(xb,3)),repr(round(xe,3)),
|
||||
repr(round(a,3)),repr(round(b,3))))
|
||||
put(" per=%d s=%s N=%d [a, b] = [%s, %s] dx=%s" % (per,repr(s),N,repr(round(ia,3)),repr(round(ib,3)),repr(round(dx,3))))
|
||||
put(" k : int(s,[a,b]) Int.Error Rel. error of s^(d)(dx) d = 0, .., k")
|
||||
k = 1
|
||||
for r in nk:
|
||||
if r[0] < 0:
|
||||
sr = '-'
|
||||
else:
|
||||
sr = ' '
|
||||
put(" %d %s%.8f %.1e " % (k,sr,abs(r[0]),
|
||||
abs(r[0]-(f(ib,-1)-f(ia,-1)))))
|
||||
d = 0
|
||||
for dr in r[1]:
|
||||
err = abs(1-dr/f(dx,d))
|
||||
tol = err_est(k, d)
|
||||
assert_(err < tol, (k, d))
|
||||
put(" %.1e %.1e" % (err, tol))
|
||||
d = d+1
|
||||
put("\n")
|
||||
k = k+1
|
||||
|
||||
def check_3(self,f=f1,per=0,s=0,a=0,b=2*pi,N=20,xb=None,xe=None,
|
||||
ia=0,ib=2*pi,dx=0.2*pi):
|
||||
if xb is None:
|
||||
xb = a
|
||||
if xe is None:
|
||||
xe = b
|
||||
x = a+(b-a)*arange(N+1,dtype=float)/float(N) # nodes
|
||||
v = f(x)
|
||||
put(" k : Roots of s(x) approx %s x in [%s,%s]:" %
|
||||
(f(None),repr(round(a,3)),repr(round(b,3))))
|
||||
for k in range(1,6):
|
||||
tck = splrep(x, v, s=s, per=per, k=k, xe=xe)
|
||||
if k == 3:
|
||||
roots = sproot(tck)
|
||||
assert_allclose(splev(roots, tck), 0, atol=1e-10, rtol=1e-10)
|
||||
assert_allclose(roots, pi*array([1, 2, 3, 4]), rtol=1e-3)
|
||||
put(' %d : %s' % (k, repr(roots.tolist())))
|
||||
else:
|
||||
assert_raises(ValueError, sproot, tck)
|
||||
|
||||
def check_4(self,f=f1,per=0,s=0,a=0,b=2*pi,N=20,xb=None,xe=None,
|
||||
ia=0,ib=2*pi,dx=0.2*pi):
|
||||
if xb is None:
|
||||
xb = a
|
||||
if xe is None:
|
||||
xe = b
|
||||
x = a+(b-a)*arange(N+1,dtype=float)/float(N) # nodes
|
||||
x1 = a + (b-a)*arange(1,N,dtype=float)/float(N-1) # middle points of the nodes
|
||||
v, _ = f(x),f(x1)
|
||||
put(" u = %s N = %d" % (repr(round(dx,3)),N))
|
||||
put(" k : [x(u), %s(x(u))] Error of splprep Error of splrep " % (f(0,None)))
|
||||
for k in range(1,6):
|
||||
tckp,u = splprep([x,v],s=s,per=per,k=k,nest=-1)
|
||||
tck = splrep(x,v,s=s,per=per,k=k)
|
||||
uv = splev(dx,tckp)
|
||||
err1 = abs(uv[1]-f(uv[0]))
|
||||
err2 = abs(splev(uv[0],tck)-f(uv[0]))
|
||||
assert_(err1 < 1e-2)
|
||||
assert_(err2 < 1e-2)
|
||||
put(" %d : %s %.1e %.1e" %
|
||||
(k,repr([round(z,3) for z in uv]),
|
||||
err1,
|
||||
err2))
|
||||
put("Derivatives of parametric cubic spline at u (first function):")
|
||||
k = 3
|
||||
tckp,u = splprep([x,v],s=s,per=per,k=k,nest=-1)
|
||||
for d in range(1,k+1):
|
||||
uv = splev(dx,tckp,d)
|
||||
put(" %s " % (repr(uv[0])))
|
||||
|
||||
def check_5(self,f=f2,kx=3,ky=3,xb=0,xe=2*pi,yb=0,ye=2*pi,Nx=20,Ny=20,s=0):
|
||||
x = xb+(xe-xb)*arange(Nx+1,dtype=float)/float(Nx)
|
||||
y = yb+(ye-yb)*arange(Ny+1,dtype=float)/float(Ny)
|
||||
xy = makepairs(x,y)
|
||||
tck = bisplrep(xy[0],xy[1],f(xy[0],xy[1]),s=s,kx=kx,ky=ky)
|
||||
tt = [tck[0][kx:-kx],tck[1][ky:-ky]]
|
||||
t2 = makepairs(tt[0],tt[1])
|
||||
v1 = bisplev(tt[0],tt[1],tck)
|
||||
v2 = f2(t2[0],t2[1])
|
||||
v2.shape = len(tt[0]),len(tt[1])
|
||||
err = norm2(ravel(v1-v2))
|
||||
assert_(err < 1e-2, err)
|
||||
put(err)
|
||||
|
||||
def test_smoke_splrep_splev(self):
|
||||
put("***************** splrep/splev")
|
||||
self.check_1(s=1e-6)
|
||||
self.check_1()
|
||||
self.check_1(at=1)
|
||||
self.check_1(per=1)
|
||||
self.check_1(per=1,at=1)
|
||||
self.check_1(b=1.5*pi)
|
||||
self.check_1(b=1.5*pi,xe=2*pi,per=1,s=1e-1)
|
||||
|
||||
def test_smoke_splint_spalde(self):
|
||||
put("***************** splint/spalde")
|
||||
self.check_2()
|
||||
self.check_2(per=1)
|
||||
self.check_2(ia=0.2*pi,ib=pi)
|
||||
self.check_2(ia=0.2*pi,ib=pi,N=50)
|
||||
|
||||
def test_smoke_sproot(self):
|
||||
put("***************** sproot")
|
||||
self.check_3(a=0.1,b=15)
|
||||
|
||||
def test_smoke_splprep_splrep_splev(self):
|
||||
put("***************** splprep/splrep/splev")
|
||||
self.check_4()
|
||||
self.check_4(N=50)
|
||||
|
||||
def test_smoke_bisplrep_bisplev(self):
|
||||
put("***************** bisplev")
|
||||
self.check_5()
|
||||
|
||||
|
||||
class TestSplev(object):
|
||||
def test_1d_shape(self):
|
||||
x = [1,2,3,4,5]
|
||||
y = [4,5,6,7,8]
|
||||
tck = splrep(x, y)
|
||||
z = splev([1], tck)
|
||||
assert_equal(z.shape, (1,))
|
||||
z = splev(1, tck)
|
||||
assert_equal(z.shape, ())
|
||||
|
||||
def test_2d_shape(self):
|
||||
x = [1, 2, 3, 4, 5]
|
||||
y = [4, 5, 6, 7, 8]
|
||||
tck = splrep(x, y)
|
||||
t = np.array([[1.0, 1.5, 2.0, 2.5],
|
||||
[3.0, 3.5, 4.0, 4.5]])
|
||||
z = splev(t, tck)
|
||||
z0 = splev(t[0], tck)
|
||||
z1 = splev(t[1], tck)
|
||||
assert_equal(z, np.row_stack((z0, z1)))
|
||||
|
||||
def test_extrapolation_modes(self):
|
||||
# test extrapolation modes
|
||||
# * if ext=0, return the extrapolated value.
|
||||
# * if ext=1, return 0
|
||||
# * if ext=2, raise a ValueError
|
||||
# * if ext=3, return the boundary value.
|
||||
x = [1,2,3]
|
||||
y = [0,2,4]
|
||||
tck = splrep(x, y, k=1)
|
||||
|
||||
rstl = [[-2, 6], [0, 0], None, [0, 4]]
|
||||
for ext in (0, 1, 3):
|
||||
assert_array_almost_equal(splev([0, 4], tck, ext=ext), rstl[ext])
|
||||
|
||||
assert_raises(ValueError, splev, [0, 4], tck, ext=2)
|
||||
|
||||
|
||||
class TestSplder(object):
|
||||
def setup_method(self):
|
||||
# non-uniform grid, just to make it sure
|
||||
x = np.linspace(0, 1, 100)**3
|
||||
y = np.sin(20 * x)
|
||||
self.spl = splrep(x, y)
|
||||
|
||||
# double check that knots are non-uniform
|
||||
assert_(np.diff(self.spl[0]).ptp() > 0)
|
||||
|
||||
def test_inverse(self):
|
||||
# Check that antiderivative + derivative is identity.
|
||||
for n in range(5):
|
||||
spl2 = splantider(self.spl, n)
|
||||
spl3 = splder(spl2, n)
|
||||
assert_allclose(self.spl[0], spl3[0])
|
||||
assert_allclose(self.spl[1], spl3[1])
|
||||
assert_equal(self.spl[2], spl3[2])
|
||||
|
||||
def test_splder_vs_splev(self):
|
||||
# Check derivative vs. FITPACK
|
||||
|
||||
for n in range(3+1):
|
||||
# Also extrapolation!
|
||||
xx = np.linspace(-1, 2, 2000)
|
||||
if n == 3:
|
||||
# ... except that FITPACK extrapolates strangely for
|
||||
# order 0, so let's not check that.
|
||||
xx = xx[(xx >= 0) & (xx <= 1)]
|
||||
|
||||
dy = splev(xx, self.spl, n)
|
||||
spl2 = splder(self.spl, n)
|
||||
dy2 = splev(xx, spl2)
|
||||
if n == 1:
|
||||
assert_allclose(dy, dy2, rtol=2e-6)
|
||||
else:
|
||||
assert_allclose(dy, dy2)
|
||||
|
||||
def test_splantider_vs_splint(self):
|
||||
# Check antiderivative vs. FITPACK
|
||||
spl2 = splantider(self.spl)
|
||||
|
||||
# no extrapolation, splint assumes function is zero outside
|
||||
# range
|
||||
xx = np.linspace(0, 1, 20)
|
||||
|
||||
for x1 in xx:
|
||||
for x2 in xx:
|
||||
y1 = splint(x1, x2, self.spl)
|
||||
y2 = splev(x2, spl2) - splev(x1, spl2)
|
||||
assert_allclose(y1, y2)
|
||||
|
||||
def test_order0_diff(self):
|
||||
assert_raises(ValueError, splder, self.spl, 4)
|
||||
|
||||
def test_kink(self):
|
||||
# Should refuse to differentiate splines with kinks
|
||||
|
||||
spl2 = insert(0.5, self.spl, m=2)
|
||||
splder(spl2, 2) # Should work
|
||||
assert_raises(ValueError, splder, spl2, 3)
|
||||
|
||||
spl2 = insert(0.5, self.spl, m=3)
|
||||
splder(spl2, 1) # Should work
|
||||
assert_raises(ValueError, splder, spl2, 2)
|
||||
|
||||
spl2 = insert(0.5, self.spl, m=4)
|
||||
assert_raises(ValueError, splder, spl2, 1)
|
||||
|
||||
def test_multidim(self):
|
||||
# c can have trailing dims
|
||||
for n in range(3):
|
||||
t, c, k = self.spl
|
||||
c2 = np.c_[c, c, c]
|
||||
c2 = np.dstack((c2, c2))
|
||||
|
||||
spl2 = splantider((t, c2, k), n)
|
||||
spl3 = splder(spl2, n)
|
||||
|
||||
assert_allclose(t, spl3[0])
|
||||
assert_allclose(c2, spl3[1])
|
||||
assert_equal(k, spl3[2])
|
||||
|
||||
|
||||
class TestBisplrep(object):
|
||||
def test_overflow(self):
|
||||
from numpy.lib.stride_tricks import as_strided
|
||||
if dfitpack_int.itemsize == 8:
|
||||
size = 1500000**2
|
||||
else:
|
||||
size = 400**2
|
||||
# Don't allocate a real array, as it's very big, but rely
|
||||
# on that it's not referenced
|
||||
x = as_strided(np.zeros(()), shape=(size,))
|
||||
assert_raises(OverflowError, bisplrep, x, x, x, w=x,
|
||||
xb=0, xe=1, yb=0, ye=1, s=0)
|
||||
|
||||
def test_regression_1310(self):
|
||||
# Regression test for gh-1310
|
||||
data = np.load(data_file('bug-1310.npz'))['data']
|
||||
|
||||
# Shouldn't crash -- the input data triggers work array sizes
|
||||
# that caused previously some data to not be aligned on
|
||||
# sizeof(double) boundaries in memory, which made the Fortran
|
||||
# code to crash when compiled with -O3
|
||||
bisplrep(data[:,0], data[:,1], data[:,2], kx=3, ky=3, s=0,
|
||||
full_output=True)
|
||||
|
||||
@pytest.mark.skipif(dfitpack_int != np.int64, reason="needs ilp64 fitpack")
|
||||
def test_ilp64_bisplrep(self):
|
||||
check_free_memory(28000) # VM size, doesn't actually use the pages
|
||||
x = np.linspace(0, 1, 400)
|
||||
y = np.linspace(0, 1, 400)
|
||||
x, y = np.meshgrid(x, y)
|
||||
z = np.zeros_like(x)
|
||||
tck = bisplrep(x, y, z, kx=3, ky=3, s=0)
|
||||
assert_allclose(bisplev(0.5, 0.5, tck), 0.0)
|
||||
|
||||
|
||||
def test_dblint():
|
||||
# Basic test to see it runs and gives the correct result on a trivial
|
||||
# problem. Note that `dblint` is not exposed in the interpolate namespace.
|
||||
x = np.linspace(0, 1)
|
||||
y = np.linspace(0, 1)
|
||||
xx, yy = np.meshgrid(x, y)
|
||||
rect = interpolate.RectBivariateSpline(x, y, 4 * xx * yy)
|
||||
tck = list(rect.tck)
|
||||
tck.extend(rect.degrees)
|
||||
|
||||
assert_almost_equal(dblint(0, 1, 0, 1, tck), 1)
|
||||
assert_almost_equal(dblint(0, 0.5, 0, 1, tck), 0.25)
|
||||
assert_almost_equal(dblint(0.5, 1, 0, 1, tck), 0.75)
|
||||
assert_almost_equal(dblint(-100, 100, -100, 100, tck), 1)
|
||||
|
||||
|
||||
def test_splev_der_k():
|
||||
# regression test for gh-2188: splev(x, tck, der=k) gives garbage or crashes
|
||||
# for x outside of knot range
|
||||
|
||||
# test case from gh-2188
|
||||
tck = (np.array([0., 0., 2.5, 2.5]),
|
||||
np.array([-1.56679978, 2.43995873, 0., 0.]),
|
||||
1)
|
||||
t, c, k = tck
|
||||
x = np.array([-3, 0, 2.5, 3])
|
||||
|
||||
# an explicit form of the linear spline
|
||||
assert_allclose(splev(x, tck), c[0] + (c[1] - c[0]) * x/t[2])
|
||||
assert_allclose(splev(x, tck, 1), (c[1]-c[0]) / t[2])
|
||||
|
||||
# now check a random spline vs splder
|
||||
np.random.seed(1234)
|
||||
x = np.sort(np.random.random(30))
|
||||
y = np.random.random(30)
|
||||
t, c, k = splrep(x, y)
|
||||
|
||||
x = [t[0] - 1., t[-1] + 1.]
|
||||
tck2 = splder((t, c, k), k)
|
||||
assert_allclose(splev(x, (t, c, k), k), splev(x, tck2))
|
||||
|
||||
|
||||
def test_splprep_segfault():
|
||||
# regression test for gh-3847: splprep segfaults if knots are specified
|
||||
# for task=-1
|
||||
t = np.arange(0, 1.1, 0.1)
|
||||
x = np.sin(2*np.pi*t)
|
||||
y = np.cos(2*np.pi*t)
|
||||
tck, u = interpolate.splprep([x, y], s=0)
|
||||
unew = np.arange(0, 1.01, 0.01)
|
||||
|
||||
uknots = tck[0] # using the knots from the previous fitting
|
||||
tck, u = interpolate.splprep([x, y], task=-1, t=uknots) # here is the crash
|
||||
|
||||
|
||||
def test_bisplev_integer_overflow():
|
||||
np.random.seed(1)
|
||||
|
||||
x = np.linspace(0, 1, 11)
|
||||
y = x
|
||||
z = np.random.randn(11, 11).ravel()
|
||||
kx = 1
|
||||
ky = 1
|
||||
|
||||
nx, tx, ny, ty, c, fp, ier = regrid_smth(
|
||||
x, y, z, None, None, None, None, kx=kx, ky=ky, s=0.0)
|
||||
tck = (tx[:nx], ty[:ny], c[:(nx - kx - 1) * (ny - ky - 1)], kx, ky)
|
||||
|
||||
xp = np.zeros([2621440])
|
||||
yp = np.zeros([2621440])
|
||||
|
||||
assert_raises((RuntimeError, MemoryError), bisplev, xp, yp, tck)
|
1056
venv/Lib/site-packages/scipy/interpolate/tests/test_fitpack2.py
Normal file
1056
venv/Lib/site-packages/scipy/interpolate/tests/test_fitpack2.py
Normal file
File diff suppressed because it is too large
Load diff
65
venv/Lib/site-packages/scipy/interpolate/tests/test_gil.py
Normal file
65
venv/Lib/site-packages/scipy/interpolate/tests/test_gil.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
import itertools
|
||||
import threading
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_equal
|
||||
import pytest
|
||||
import scipy.interpolate
|
||||
|
||||
|
||||
class TestGIL(object):
|
||||
"""Check if the GIL is properly released by scipy.interpolate functions."""
|
||||
|
||||
def setup_method(self):
|
||||
self.messages = []
|
||||
|
||||
def log(self, message):
|
||||
self.messages.append(message)
|
||||
|
||||
def make_worker_thread(self, target, args):
|
||||
log = self.log
|
||||
|
||||
class WorkerThread(threading.Thread):
|
||||
def run(self):
|
||||
log('interpolation started')
|
||||
target(*args)
|
||||
log('interpolation complete')
|
||||
|
||||
return WorkerThread()
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.xfail(reason='race conditions, may depend on system load')
|
||||
def test_rectbivariatespline(self):
|
||||
def generate_params(n_points):
|
||||
x = y = np.linspace(0, 1000, n_points)
|
||||
x_grid, y_grid = np.meshgrid(x, y)
|
||||
z = x_grid * y_grid
|
||||
return x, y, z
|
||||
|
||||
def calibrate_delay(requested_time):
|
||||
for n_points in itertools.count(5000, 1000):
|
||||
args = generate_params(n_points)
|
||||
time_started = time.time()
|
||||
interpolate(*args)
|
||||
if time.time() - time_started > requested_time:
|
||||
return args
|
||||
|
||||
def interpolate(x, y, z):
|
||||
scipy.interpolate.RectBivariateSpline(x, y, z)
|
||||
|
||||
args = calibrate_delay(requested_time=3)
|
||||
worker_thread = self.make_worker_thread(interpolate, args)
|
||||
worker_thread.start()
|
||||
for i in range(3):
|
||||
time.sleep(0.5)
|
||||
self.log('working')
|
||||
worker_thread.join()
|
||||
assert_equal(self.messages, [
|
||||
'interpolation started',
|
||||
'working',
|
||||
'working',
|
||||
'working',
|
||||
'interpolation complete',
|
||||
])
|
||||
|
386
venv/Lib/site-packages/scipy/interpolate/tests/test_interpnd.py
Normal file
386
venv/Lib/site-packages/scipy/interpolate/tests/test_interpnd.py
Normal file
|
@ -0,0 +1,386 @@
|
|||
import os
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import (assert_equal, assert_allclose, assert_almost_equal,
|
||||
suppress_warnings)
|
||||
from pytest import raises as assert_raises
|
||||
import pytest
|
||||
|
||||
import scipy.interpolate.interpnd as interpnd
|
||||
import scipy.spatial.qhull as qhull
|
||||
|
||||
import pickle
|
||||
|
||||
|
||||
def data_file(basename):
|
||||
return os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'data', basename)
|
||||
|
||||
|
||||
class TestLinearNDInterpolation(object):
|
||||
def test_smoketest(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
|
||||
yi = interpnd.LinearNDInterpolator(x, y)(x)
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_smoketest_alternate(self):
|
||||
# Test at single points, alternate calling convention
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
|
||||
yi = interpnd.LinearNDInterpolator((x[:,0], x[:,1]), y)(x[:,0], x[:,1])
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_complex_smoketest(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
yi = interpnd.LinearNDInterpolator(x, y)(x)
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_tri_input(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
yi = interpnd.LinearNDInterpolator(tri, y)(x)
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_square(self):
|
||||
# Test barycentric interpolation on a square against a manual
|
||||
# implementation
|
||||
|
||||
points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.double)
|
||||
values = np.array([1., 2., -3., 5.], dtype=np.double)
|
||||
|
||||
# NB: assume triangles (0, 1, 3) and (1, 2, 3)
|
||||
#
|
||||
# 1----2
|
||||
# | \ |
|
||||
# | \ |
|
||||
# 0----3
|
||||
|
||||
def ip(x, y):
|
||||
t1 = (x + y <= 1)
|
||||
t2 = ~t1
|
||||
|
||||
x1 = x[t1]
|
||||
y1 = y[t1]
|
||||
|
||||
x2 = x[t2]
|
||||
y2 = y[t2]
|
||||
|
||||
z = 0*x
|
||||
|
||||
z[t1] = (values[0]*(1 - x1 - y1)
|
||||
+ values[1]*y1
|
||||
+ values[3]*x1)
|
||||
|
||||
z[t2] = (values[2]*(x2 + y2 - 1)
|
||||
+ values[1]*(1 - x2)
|
||||
+ values[3]*(1 - y2))
|
||||
return z
|
||||
|
||||
xx, yy = np.broadcast_arrays(np.linspace(0, 1, 14)[:,None],
|
||||
np.linspace(0, 1, 14)[None,:])
|
||||
xx = xx.ravel()
|
||||
yy = yy.ravel()
|
||||
|
||||
xi = np.array([xx, yy]).T.copy()
|
||||
zi = interpnd.LinearNDInterpolator(points, values)(xi)
|
||||
|
||||
assert_almost_equal(zi, ip(xx, yy))
|
||||
|
||||
def test_smoketest_rescale(self):
|
||||
# Test at single points
|
||||
x = np.array([(0, 0), (-5, -5), (-5, 5), (5, 5), (2.5, 3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
|
||||
yi = interpnd.LinearNDInterpolator(x, y, rescale=True)(x)
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_square_rescale(self):
|
||||
# Test barycentric interpolation on a rectangle with rescaling
|
||||
# agaings the same implementation without rescaling
|
||||
|
||||
points = np.array([(0,0), (0,100), (10,100), (10,0)], dtype=np.double)
|
||||
values = np.array([1., 2., -3., 5.], dtype=np.double)
|
||||
|
||||
xx, yy = np.broadcast_arrays(np.linspace(0, 10, 14)[:,None],
|
||||
np.linspace(0, 100, 14)[None,:])
|
||||
xx = xx.ravel()
|
||||
yy = yy.ravel()
|
||||
xi = np.array([xx, yy]).T.copy()
|
||||
zi = interpnd.LinearNDInterpolator(points, values)(xi)
|
||||
zi_rescaled = interpnd.LinearNDInterpolator(points, values,
|
||||
rescale=True)(xi)
|
||||
|
||||
assert_almost_equal(zi, zi_rescaled)
|
||||
|
||||
def test_tripoints_input_rescale(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-5,-5), (-5,5), (5, 5), (2.5, 3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
yi = interpnd.LinearNDInterpolator(tri.points, y)(x)
|
||||
yi_rescale = interpnd.LinearNDInterpolator(tri.points, y,
|
||||
rescale=True)(x)
|
||||
assert_almost_equal(yi, yi_rescale)
|
||||
|
||||
def test_tri_input_rescale(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-5,-5), (-5,5), (5, 5), (2.5, 3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
match = ("Rescaling is not supported when passing a "
|
||||
"Delaunay triangulation as ``points``.")
|
||||
with pytest.raises(ValueError, match=match):
|
||||
interpnd.LinearNDInterpolator(tri, y, rescale=True)(x)
|
||||
|
||||
def test_pickle(self):
|
||||
# Test at single points
|
||||
np.random.seed(1234)
|
||||
x = np.random.rand(30, 2)
|
||||
y = np.random.rand(30) + 1j*np.random.rand(30)
|
||||
|
||||
ip = interpnd.LinearNDInterpolator(x, y)
|
||||
ip2 = pickle.loads(pickle.dumps(ip))
|
||||
|
||||
assert_almost_equal(ip(0.5, 0.5), ip2(0.5, 0.5))
|
||||
|
||||
|
||||
class TestEstimateGradients2DGlobal(object):
|
||||
def test_smoketest(self):
|
||||
x = np.array([(0, 0), (0, 2),
|
||||
(1, 0), (1, 2), (0.25, 0.75), (0.6, 0.8)], dtype=float)
|
||||
tri = qhull.Delaunay(x)
|
||||
|
||||
# Should be exact for linear functions, independent of triangulation
|
||||
|
||||
funcs = [
|
||||
(lambda x, y: 0*x + 1, (0, 0)),
|
||||
(lambda x, y: 0 + x, (1, 0)),
|
||||
(lambda x, y: -2 + y, (0, 1)),
|
||||
(lambda x, y: 3 + 3*x + 14.15*y, (3, 14.15))
|
||||
]
|
||||
|
||||
for j, (func, grad) in enumerate(funcs):
|
||||
z = func(x[:,0], x[:,1])
|
||||
dz = interpnd.estimate_gradients_2d_global(tri, z, tol=1e-6)
|
||||
|
||||
assert_equal(dz.shape, (6, 2))
|
||||
assert_allclose(dz, np.array(grad)[None,:] + 0*dz,
|
||||
rtol=1e-5, atol=1e-5, err_msg="item %d" % j)
|
||||
|
||||
def test_regression_2359(self):
|
||||
# Check regression --- for certain point sets, gradient
|
||||
# estimation could end up in an infinite loop
|
||||
points = np.load(data_file('estimate_gradients_hang.npy'))
|
||||
values = np.random.rand(points.shape[0])
|
||||
tri = qhull.Delaunay(points)
|
||||
|
||||
# This should not hang
|
||||
with suppress_warnings() as sup:
|
||||
sup.filter(interpnd.GradientEstimationWarning,
|
||||
"Gradient estimation did not converge")
|
||||
interpnd.estimate_gradients_2d_global(tri, values, maxiter=1)
|
||||
|
||||
|
||||
class TestCloughTocher2DInterpolator(object):
|
||||
|
||||
def _check_accuracy(self, func, x=None, tol=1e-6, alternate=False, rescale=False, **kw):
|
||||
np.random.seed(1234)
|
||||
if x is None:
|
||||
x = np.array([(0, 0), (0, 1),
|
||||
(1, 0), (1, 1), (0.25, 0.75), (0.6, 0.8),
|
||||
(0.5, 0.2)],
|
||||
dtype=float)
|
||||
|
||||
if not alternate:
|
||||
ip = interpnd.CloughTocher2DInterpolator(x, func(x[:,0], x[:,1]),
|
||||
tol=1e-6, rescale=rescale)
|
||||
else:
|
||||
ip = interpnd.CloughTocher2DInterpolator((x[:,0], x[:,1]),
|
||||
func(x[:,0], x[:,1]),
|
||||
tol=1e-6, rescale=rescale)
|
||||
|
||||
p = np.random.rand(50, 2)
|
||||
|
||||
if not alternate:
|
||||
a = ip(p)
|
||||
else:
|
||||
a = ip(p[:,0], p[:,1])
|
||||
b = func(p[:,0], p[:,1])
|
||||
|
||||
try:
|
||||
assert_allclose(a, b, **kw)
|
||||
except AssertionError:
|
||||
print(abs(a - b))
|
||||
print(ip.grad)
|
||||
raise
|
||||
|
||||
def test_linear_smoketest(self):
|
||||
# Should be exact for linear functions, independent of triangulation
|
||||
funcs = [
|
||||
lambda x, y: 0*x + 1,
|
||||
lambda x, y: 0 + x,
|
||||
lambda x, y: -2 + y,
|
||||
lambda x, y: 3 + 3*x + 14.15*y,
|
||||
]
|
||||
|
||||
for j, func in enumerate(funcs):
|
||||
self._check_accuracy(func, tol=1e-13, atol=1e-7, rtol=1e-7,
|
||||
err_msg="Function %d" % j)
|
||||
self._check_accuracy(func, tol=1e-13, atol=1e-7, rtol=1e-7,
|
||||
alternate=True,
|
||||
err_msg="Function (alternate) %d" % j)
|
||||
# check rescaling
|
||||
self._check_accuracy(func, tol=1e-13, atol=1e-7, rtol=1e-7,
|
||||
err_msg="Function (rescaled) %d" % j, rescale=True)
|
||||
self._check_accuracy(func, tol=1e-13, atol=1e-7, rtol=1e-7,
|
||||
alternate=True, rescale=True,
|
||||
err_msg="Function (alternate, rescaled) %d" % j)
|
||||
|
||||
def test_quadratic_smoketest(self):
|
||||
# Should be reasonably accurate for quadratic functions
|
||||
funcs = [
|
||||
lambda x, y: x**2,
|
||||
lambda x, y: y**2,
|
||||
lambda x, y: x**2 - y**2,
|
||||
lambda x, y: x*y,
|
||||
]
|
||||
|
||||
for j, func in enumerate(funcs):
|
||||
self._check_accuracy(func, tol=1e-9, atol=0.22, rtol=0,
|
||||
err_msg="Function %d" % j)
|
||||
self._check_accuracy(func, tol=1e-9, atol=0.22, rtol=0,
|
||||
err_msg="Function %d" % j, rescale=True)
|
||||
|
||||
def test_tri_input(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
yi = interpnd.CloughTocher2DInterpolator(tri, y)(x)
|
||||
assert_almost_equal(y, yi)
|
||||
|
||||
def test_tri_input_rescale(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-5,-5), (-5,5), (5, 5), (2.5, 3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
match = ("Rescaling is not supported when passing a "
|
||||
"Delaunay triangulation as ``points``.")
|
||||
with pytest.raises(ValueError, match=match):
|
||||
interpnd.CloughTocher2DInterpolator(tri, y, rescale=True)(x)
|
||||
|
||||
def test_tripoints_input_rescale(self):
|
||||
# Test at single points
|
||||
x = np.array([(0,0), (-5,-5), (-5,5), (5, 5), (2.5, 3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 3j*y
|
||||
|
||||
tri = qhull.Delaunay(x)
|
||||
yi = interpnd.CloughTocher2DInterpolator(tri.points, y)(x)
|
||||
yi_rescale = interpnd.CloughTocher2DInterpolator(tri.points, y, rescale=True)(x)
|
||||
assert_almost_equal(yi, yi_rescale)
|
||||
|
||||
def test_dense(self):
|
||||
# Should be more accurate for dense meshes
|
||||
funcs = [
|
||||
lambda x, y: x**2,
|
||||
lambda x, y: y**2,
|
||||
lambda x, y: x**2 - y**2,
|
||||
lambda x, y: x*y,
|
||||
lambda x, y: np.cos(2*np.pi*x)*np.sin(2*np.pi*y)
|
||||
]
|
||||
|
||||
np.random.seed(4321) # use a different seed than the check!
|
||||
grid = np.r_[np.array([(0,0), (0,1), (1,0), (1,1)], dtype=float),
|
||||
np.random.rand(30*30, 2)]
|
||||
|
||||
for j, func in enumerate(funcs):
|
||||
self._check_accuracy(func, x=grid, tol=1e-9, atol=5e-3, rtol=1e-2,
|
||||
err_msg="Function %d" % j)
|
||||
self._check_accuracy(func, x=grid, tol=1e-9, atol=5e-3, rtol=1e-2,
|
||||
err_msg="Function %d" % j, rescale=True)
|
||||
|
||||
def test_wrong_ndim(self):
|
||||
x = np.random.randn(30, 3)
|
||||
y = np.random.randn(30)
|
||||
assert_raises(ValueError, interpnd.CloughTocher2DInterpolator, x, y)
|
||||
|
||||
def test_pickle(self):
|
||||
# Test at single points
|
||||
np.random.seed(1234)
|
||||
x = np.random.rand(30, 2)
|
||||
y = np.random.rand(30) + 1j*np.random.rand(30)
|
||||
|
||||
ip = interpnd.CloughTocher2DInterpolator(x, y)
|
||||
ip2 = pickle.loads(pickle.dumps(ip))
|
||||
|
||||
assert_almost_equal(ip(0.5, 0.5), ip2(0.5, 0.5))
|
||||
|
||||
def test_boundary_tri_symmetry(self):
|
||||
# Interpolation at neighbourless triangles should retain
|
||||
# symmetry with mirroring the triangle.
|
||||
|
||||
# Equilateral triangle
|
||||
points = np.array([(0, 0), (1, 0), (0.5, np.sqrt(3)/2)])
|
||||
values = np.array([1, 0, 0])
|
||||
|
||||
ip = interpnd.CloughTocher2DInterpolator(points, values)
|
||||
|
||||
# Set gradient to zero at vertices
|
||||
ip.grad[...] = 0
|
||||
|
||||
# Interpolation should be symmetric vs. bisector
|
||||
alpha = 0.3
|
||||
p1 = np.array([0.5 * np.cos(alpha), 0.5 * np.sin(alpha)])
|
||||
p2 = np.array([0.5 * np.cos(np.pi/3 - alpha), 0.5 * np.sin(np.pi/3 - alpha)])
|
||||
|
||||
v1 = ip(p1)
|
||||
v2 = ip(p2)
|
||||
assert_allclose(v1, v2)
|
||||
|
||||
# ... and affine invariant
|
||||
np.random.seed(1)
|
||||
A = np.random.randn(2, 2)
|
||||
b = np.random.randn(2)
|
||||
|
||||
points = A.dot(points.T).T + b[None,:]
|
||||
p1 = A.dot(p1) + b
|
||||
p2 = A.dot(p2) + b
|
||||
|
||||
ip = interpnd.CloughTocher2DInterpolator(points, values)
|
||||
ip.grad[...] = 0
|
||||
|
||||
w1 = ip(p1)
|
||||
w2 = ip(p2)
|
||||
assert_allclose(w1, v1)
|
||||
assert_allclose(w2, v2)
|
2807
venv/Lib/site-packages/scipy/interpolate/tests/test_interpolate.py
Normal file
2807
venv/Lib/site-packages/scipy/interpolate/tests/test_interpolate.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,189 @@
|
|||
import numpy as np
|
||||
from numpy.testing import assert_equal, assert_array_equal, assert_allclose
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.interpolate import griddata, NearestNDInterpolator
|
||||
|
||||
|
||||
class TestGriddata(object):
|
||||
def test_fill_value(self):
|
||||
x = [(0,0), (0,1), (1,0)]
|
||||
y = [1, 2, 3]
|
||||
|
||||
yi = griddata(x, y, [(1,1), (1,2), (0,0)], fill_value=-1)
|
||||
assert_array_equal(yi, [-1., -1, 1])
|
||||
|
||||
yi = griddata(x, y, [(1,1), (1,2), (0,0)])
|
||||
assert_array_equal(yi, [np.nan, np.nan, 1])
|
||||
|
||||
def test_alternative_call(self):
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = (np.arange(x.shape[0], dtype=np.double)[:,None]
|
||||
+ np.array([0,1])[None,:])
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
for rescale in (True, False):
|
||||
msg = repr((method, rescale))
|
||||
yi = griddata((x[:,0], x[:,1]), y, (x[:,0], x[:,1]), method=method,
|
||||
rescale=rescale)
|
||||
assert_allclose(y, yi, atol=1e-14, err_msg=msg)
|
||||
|
||||
def test_multivalue_2d(self):
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = (np.arange(x.shape[0], dtype=np.double)[:,None]
|
||||
+ np.array([0,1])[None,:])
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
for rescale in (True, False):
|
||||
msg = repr((method, rescale))
|
||||
yi = griddata(x, y, x, method=method, rescale=rescale)
|
||||
assert_allclose(y, yi, atol=1e-14, err_msg=msg)
|
||||
|
||||
def test_multipoint_2d(self):
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
|
||||
xi = x[:,None,:] + np.array([0,0,0])[None,:,None]
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
for rescale in (True, False):
|
||||
msg = repr((method, rescale))
|
||||
yi = griddata(x, y, xi, method=method, rescale=rescale)
|
||||
|
||||
assert_equal(yi.shape, (5, 3), err_msg=msg)
|
||||
assert_allclose(yi, np.tile(y[:,None], (1, 3)),
|
||||
atol=1e-14, err_msg=msg)
|
||||
|
||||
def test_complex_2d(self):
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 2j*y[::-1]
|
||||
|
||||
xi = x[:,None,:] + np.array([0,0,0])[None,:,None]
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
for rescale in (True, False):
|
||||
msg = repr((method, rescale))
|
||||
yi = griddata(x, y, xi, method=method, rescale=rescale)
|
||||
|
||||
assert_equal(yi.shape, (5, 3), err_msg=msg)
|
||||
assert_allclose(yi, np.tile(y[:,None], (1, 3)),
|
||||
atol=1e-14, err_msg=msg)
|
||||
|
||||
def test_1d(self):
|
||||
x = np.array([1, 2.5, 3, 4.5, 5, 6])
|
||||
y = np.array([1, 2, 0, 3.9, 2, 1])
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
assert_allclose(griddata(x, y, x, method=method), y,
|
||||
err_msg=method, atol=1e-14)
|
||||
assert_allclose(griddata(x.reshape(6, 1), y, x, method=method), y,
|
||||
err_msg=method, atol=1e-14)
|
||||
assert_allclose(griddata((x,), y, (x,), method=method), y,
|
||||
err_msg=method, atol=1e-14)
|
||||
|
||||
def test_1d_borders(self):
|
||||
# Test for nearest neighbor case with xi outside
|
||||
# the range of the values.
|
||||
x = np.array([1, 2.5, 3, 4.5, 5, 6])
|
||||
y = np.array([1, 2, 0, 3.9, 2, 1])
|
||||
xi = np.array([0.9, 6.5])
|
||||
yi_should = np.array([1.0, 1.0])
|
||||
|
||||
method = 'nearest'
|
||||
assert_allclose(griddata(x, y, xi,
|
||||
method=method), yi_should,
|
||||
err_msg=method,
|
||||
atol=1e-14)
|
||||
assert_allclose(griddata(x.reshape(6, 1), y, xi,
|
||||
method=method), yi_should,
|
||||
err_msg=method,
|
||||
atol=1e-14)
|
||||
assert_allclose(griddata((x, ), y, (xi, ),
|
||||
method=method), yi_should,
|
||||
err_msg=method,
|
||||
atol=1e-14)
|
||||
|
||||
def test_1d_unsorted(self):
|
||||
x = np.array([2.5, 1, 4.5, 5, 6, 3])
|
||||
y = np.array([1, 2, 0, 3.9, 2, 1])
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
assert_allclose(griddata(x, y, x, method=method), y,
|
||||
err_msg=method, atol=1e-10)
|
||||
assert_allclose(griddata(x.reshape(6, 1), y, x, method=method), y,
|
||||
err_msg=method, atol=1e-10)
|
||||
assert_allclose(griddata((x,), y, (x,), method=method), y,
|
||||
err_msg=method, atol=1e-10)
|
||||
|
||||
def test_square_rescale_manual(self):
|
||||
points = np.array([(0,0), (0,100), (10,100), (10,0), (1, 5)], dtype=np.double)
|
||||
points_rescaled = np.array([(0,0), (0,1), (1,1), (1,0), (0.1, 0.05)], dtype=np.double)
|
||||
values = np.array([1., 2., -3., 5., 9.], dtype=np.double)
|
||||
|
||||
xx, yy = np.broadcast_arrays(np.linspace(0, 10, 14)[:,None],
|
||||
np.linspace(0, 100, 14)[None,:])
|
||||
xx = xx.ravel()
|
||||
yy = yy.ravel()
|
||||
xi = np.array([xx, yy]).T.copy()
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
msg = method
|
||||
zi = griddata(points_rescaled, values, xi/np.array([10, 100.]),
|
||||
method=method)
|
||||
zi_rescaled = griddata(points, values, xi, method=method,
|
||||
rescale=True)
|
||||
assert_allclose(zi, zi_rescaled, err_msg=msg,
|
||||
atol=1e-12)
|
||||
|
||||
def test_xi_1d(self):
|
||||
# Check that 1-D xi is interpreted as a coordinate
|
||||
x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)],
|
||||
dtype=np.double)
|
||||
y = np.arange(x.shape[0], dtype=np.double)
|
||||
y = y - 2j*y[::-1]
|
||||
|
||||
xi = np.array([0.5, 0.5])
|
||||
|
||||
for method in ('nearest', 'linear', 'cubic'):
|
||||
p1 = griddata(x, y, xi, method=method)
|
||||
p2 = griddata(x, y, xi[None,:], method=method)
|
||||
assert_allclose(p1, p2, err_msg=method)
|
||||
|
||||
xi1 = np.array([0.5])
|
||||
xi3 = np.array([0.5, 0.5, 0.5])
|
||||
assert_raises(ValueError, griddata, x, y, xi1,
|
||||
method=method)
|
||||
assert_raises(ValueError, griddata, x, y, xi3,
|
||||
method=method)
|
||||
|
||||
|
||||
def test_nearest_options():
|
||||
# smoke test that NearestNDInterpolator accept cKDTree options
|
||||
npts, nd = 4, 3
|
||||
x = np.arange(npts*nd).reshape((npts, nd))
|
||||
y = np.arange(npts)
|
||||
nndi = NearestNDInterpolator(x, y)
|
||||
|
||||
opts = {'balanced_tree': False, 'compact_nodes': False}
|
||||
nndi_o = NearestNDInterpolator(x, y, tree_options=opts)
|
||||
assert_allclose(nndi(x), nndi_o(x), atol=1e-14)
|
||||
|
||||
|
||||
def test_nearest_list_argument():
|
||||
nd = np.array([[0, 0, 0, 0, 1, 0, 1],
|
||||
[0, 0, 0, 0, 0, 1, 1],
|
||||
[0, 0, 0, 0, 1, 1, 2]])
|
||||
d = nd[:, 3:]
|
||||
|
||||
# z is np.array
|
||||
NI = NearestNDInterpolator((d[0], d[1]), d[2])
|
||||
assert_array_equal(NI([0.1, 0.9], [0.1, 0.9]), [0, 2])
|
||||
|
||||
# z is list
|
||||
NI = NearestNDInterpolator((d[0], d[1]), list(d[2]))
|
||||
assert_array_equal(NI([0.1, 0.9], [0.1, 0.9]), [0, 2])
|
101
venv/Lib/site-packages/scipy/interpolate/tests/test_pade.py
Normal file
101
venv/Lib/site-packages/scipy/interpolate/tests/test_pade.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
from numpy.testing import (assert_array_equal, assert_array_almost_equal)
|
||||
from scipy.interpolate import pade
|
||||
|
||||
def test_pade_trivial():
|
||||
nump, denomp = pade([1.0], 0)
|
||||
assert_array_equal(nump.c, [1.0])
|
||||
assert_array_equal(denomp.c, [1.0])
|
||||
|
||||
nump, denomp = pade([1.0], 0, 0)
|
||||
assert_array_equal(nump.c, [1.0])
|
||||
assert_array_equal(denomp.c, [1.0])
|
||||
|
||||
|
||||
def test_pade_4term_exp():
|
||||
# First four Taylor coefficients of exp(x).
|
||||
# Unlike poly1d, the first array element is the zero-order term.
|
||||
an = [1.0, 1.0, 0.5, 1.0/6]
|
||||
|
||||
nump, denomp = pade(an, 0)
|
||||
assert_array_almost_equal(nump.c, [1.0/6, 0.5, 1.0, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0])
|
||||
|
||||
nump, denomp = pade(an, 1)
|
||||
assert_array_almost_equal(nump.c, [1.0/6, 2.0/3, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [-1.0/3, 1.0])
|
||||
|
||||
nump, denomp = pade(an, 2)
|
||||
assert_array_almost_equal(nump.c, [1.0/3, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0/6, -2.0/3, 1.0])
|
||||
|
||||
nump, denomp = pade(an, 3)
|
||||
assert_array_almost_equal(nump.c, [1.0])
|
||||
assert_array_almost_equal(denomp.c, [-1.0/6, 0.5, -1.0, 1.0])
|
||||
|
||||
# Testing inclusion of optional parameter
|
||||
nump, denomp = pade(an, 0, 3)
|
||||
assert_array_almost_equal(nump.c, [1.0/6, 0.5, 1.0, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0])
|
||||
|
||||
nump, denomp = pade(an, 1, 2)
|
||||
assert_array_almost_equal(nump.c, [1.0/6, 2.0/3, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [-1.0/3, 1.0])
|
||||
|
||||
nump, denomp = pade(an, 2, 1)
|
||||
assert_array_almost_equal(nump.c, [1.0/3, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0/6, -2.0/3, 1.0])
|
||||
|
||||
nump, denomp = pade(an, 3, 0)
|
||||
assert_array_almost_equal(nump.c, [1.0])
|
||||
assert_array_almost_equal(denomp.c, [-1.0/6, 0.5, -1.0, 1.0])
|
||||
|
||||
# Testing reducing array.
|
||||
nump, denomp = pade(an, 0, 2)
|
||||
assert_array_almost_equal(nump.c, [0.5, 1.0, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0])
|
||||
|
||||
nump, denomp = pade(an, 1, 1)
|
||||
assert_array_almost_equal(nump.c, [1.0/2, 1.0])
|
||||
assert_array_almost_equal(denomp.c, [-1.0/2, 1.0])
|
||||
|
||||
nump, denomp = pade(an, 2, 0)
|
||||
assert_array_almost_equal(nump.c, [1.0])
|
||||
assert_array_almost_equal(denomp.c, [1.0/2, -1.0, 1.0])
|
||||
|
||||
|
||||
def test_pade_ints():
|
||||
# Simple test sequences (one of ints, one of floats).
|
||||
an_int = [1, 2, 3, 4]
|
||||
an_flt = [1.0, 2.0, 3.0, 4.0]
|
||||
|
||||
# Make sure integer arrays give the same result as float arrays with same values.
|
||||
for i in range(0, len(an_int)):
|
||||
for j in range(0, len(an_int) - i):
|
||||
|
||||
# Create float and int pade approximation for given order.
|
||||
nump_int, denomp_int = pade(an_int, i, j)
|
||||
nump_flt, denomp_flt = pade(an_flt, i, j)
|
||||
|
||||
# Check that they are the same.
|
||||
assert_array_equal(nump_int.c, nump_flt.c)
|
||||
assert_array_equal(denomp_int.c, denomp_flt.c)
|
||||
|
||||
|
||||
def test_pade_complex():
|
||||
# Test sequence with known solutions - see page 6 of 10.1109/PESGM.2012.6344759.
|
||||
# Variable x is parameter - these tests will work with any complex number.
|
||||
x = 0.2 + 0.6j
|
||||
an = [1.0, x, -x*x.conjugate(), x.conjugate()*(x**2) + x*(x.conjugate()**2),
|
||||
-(x**3)*x.conjugate() - 3*(x*x.conjugate())**2 - x*(x.conjugate()**3)]
|
||||
|
||||
nump, denomp = pade(an, 1, 1)
|
||||
assert_array_almost_equal(nump.c, [x + x.conjugate(), 1.0])
|
||||
assert_array_almost_equal(denomp.c, [x.conjugate(), 1.0])
|
||||
|
||||
nump, denomp = pade(an, 1, 2)
|
||||
assert_array_almost_equal(nump.c, [x**2, 2*x + x.conjugate(), 1.0])
|
||||
assert_array_almost_equal(denomp.c, [x + x.conjugate(), 1.0])
|
||||
|
||||
nump, denomp = pade(an, 2, 2)
|
||||
assert_array_almost_equal(nump.c, [x**2 + x*x.conjugate() + x.conjugate()**2, 2*(x + x.conjugate()), 1.0])
|
||||
assert_array_almost_equal(denomp.c, [x.conjugate()**2, x + 2*x.conjugate(), 1.0])
|
701
venv/Lib/site-packages/scipy/interpolate/tests/test_polyint.py
Normal file
701
venv/Lib/site-packages/scipy/interpolate/tests/test_polyint.py
Normal file
|
@ -0,0 +1,701 @@
|
|||
import warnings
|
||||
import io
|
||||
import numpy as np
|
||||
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_array_equal, assert_array_almost_equal,
|
||||
assert_allclose, assert_equal, assert_)
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.interpolate import (
|
||||
KroghInterpolator, krogh_interpolate,
|
||||
BarycentricInterpolator, barycentric_interpolate,
|
||||
approximate_taylor_polynomial, CubicHermiteSpline, pchip,
|
||||
PchipInterpolator, pchip_interpolate, Akima1DInterpolator, CubicSpline,
|
||||
make_interp_spline)
|
||||
|
||||
|
||||
def check_shape(interpolator_cls, x_shape, y_shape, deriv_shape=None, axis=0,
|
||||
extra_args={}):
|
||||
np.random.seed(1234)
|
||||
|
||||
x = [-1, 0, 1, 2, 3, 4]
|
||||
s = list(range(1, len(y_shape)+1))
|
||||
s.insert(axis % (len(y_shape)+1), 0)
|
||||
y = np.random.rand(*((6,) + y_shape)).transpose(s)
|
||||
|
||||
# Cython code chokes on y.shape = (0, 3) etc., skip them
|
||||
if y.size == 0:
|
||||
return
|
||||
|
||||
xi = np.zeros(x_shape)
|
||||
if interpolator_cls is CubicHermiteSpline:
|
||||
dydx = np.random.rand(*((6,) + y_shape)).transpose(s)
|
||||
yi = interpolator_cls(x, y, dydx, axis=axis, **extra_args)(xi)
|
||||
else:
|
||||
yi = interpolator_cls(x, y, axis=axis, **extra_args)(xi)
|
||||
|
||||
target_shape = ((deriv_shape or ()) + y.shape[:axis]
|
||||
+ x_shape + y.shape[axis:][1:])
|
||||
assert_equal(yi.shape, target_shape)
|
||||
|
||||
# check it works also with lists
|
||||
if x_shape and y.size > 0:
|
||||
if interpolator_cls is CubicHermiteSpline:
|
||||
interpolator_cls(list(x), list(y), list(dydx), axis=axis,
|
||||
**extra_args)(list(xi))
|
||||
else:
|
||||
interpolator_cls(list(x), list(y), axis=axis,
|
||||
**extra_args)(list(xi))
|
||||
|
||||
# check also values
|
||||
if xi.size > 0 and deriv_shape is None:
|
||||
bs_shape = y.shape[:axis] + (1,)*len(x_shape) + y.shape[axis:][1:]
|
||||
yv = y[((slice(None,),)*(axis % y.ndim)) + (1,)]
|
||||
yv = yv.reshape(bs_shape)
|
||||
|
||||
yi, y = np.broadcast_arrays(yi, yv)
|
||||
assert_allclose(yi, y)
|
||||
|
||||
|
||||
SHAPES = [(), (0,), (1,), (6, 2, 5)]
|
||||
|
||||
|
||||
def test_shapes():
|
||||
|
||||
def spl_interp(x, y, axis):
|
||||
return make_interp_spline(x, y, axis=axis)
|
||||
|
||||
for ip in [KroghInterpolator, BarycentricInterpolator, CubicHermiteSpline,
|
||||
pchip, Akima1DInterpolator, CubicSpline, spl_interp]:
|
||||
for s1 in SHAPES:
|
||||
for s2 in SHAPES:
|
||||
for axis in range(-len(s2), len(s2)):
|
||||
if ip != CubicSpline:
|
||||
check_shape(ip, s1, s2, None, axis)
|
||||
else:
|
||||
for bc in ['natural', 'clamped']:
|
||||
extra = {'bc_type': bc}
|
||||
check_shape(ip, s1, s2, None, axis, extra)
|
||||
|
||||
def test_derivs_shapes():
|
||||
def krogh_derivs(x, y, axis=0):
|
||||
return KroghInterpolator(x, y, axis).derivatives
|
||||
|
||||
for s1 in SHAPES:
|
||||
for s2 in SHAPES:
|
||||
for axis in range(-len(s2), len(s2)):
|
||||
check_shape(krogh_derivs, s1, s2, (6,), axis)
|
||||
|
||||
|
||||
def test_deriv_shapes():
|
||||
def krogh_deriv(x, y, axis=0):
|
||||
return KroghInterpolator(x, y, axis).derivative
|
||||
|
||||
def pchip_deriv(x, y, axis=0):
|
||||
return pchip(x, y, axis).derivative()
|
||||
|
||||
def pchip_deriv2(x, y, axis=0):
|
||||
return pchip(x, y, axis).derivative(2)
|
||||
|
||||
def pchip_antideriv(x, y, axis=0):
|
||||
return pchip(x, y, axis).derivative()
|
||||
|
||||
def pchip_antideriv2(x, y, axis=0):
|
||||
return pchip(x, y, axis).derivative(2)
|
||||
|
||||
def pchip_deriv_inplace(x, y, axis=0):
|
||||
class P(PchipInterpolator):
|
||||
def __call__(self, x):
|
||||
return PchipInterpolator.__call__(self, x, 1)
|
||||
pass
|
||||
return P(x, y, axis)
|
||||
|
||||
def akima_deriv(x, y, axis=0):
|
||||
return Akima1DInterpolator(x, y, axis).derivative()
|
||||
|
||||
def akima_antideriv(x, y, axis=0):
|
||||
return Akima1DInterpolator(x, y, axis).antiderivative()
|
||||
|
||||
def cspline_deriv(x, y, axis=0):
|
||||
return CubicSpline(x, y, axis).derivative()
|
||||
|
||||
def cspline_antideriv(x, y, axis=0):
|
||||
return CubicSpline(x, y, axis).antiderivative()
|
||||
|
||||
def bspl_deriv(x, y, axis=0):
|
||||
return make_interp_spline(x, y, axis=axis).derivative()
|
||||
|
||||
def bspl_antideriv(x, y, axis=0):
|
||||
return make_interp_spline(x, y, axis=axis).antiderivative()
|
||||
|
||||
for ip in [krogh_deriv, pchip_deriv, pchip_deriv2, pchip_deriv_inplace,
|
||||
pchip_antideriv, pchip_antideriv2, akima_deriv, akima_antideriv,
|
||||
cspline_deriv, cspline_antideriv, bspl_deriv, bspl_antideriv]:
|
||||
for s1 in SHAPES:
|
||||
for s2 in SHAPES:
|
||||
for axis in range(-len(s2), len(s2)):
|
||||
check_shape(ip, s1, s2, (), axis)
|
||||
|
||||
|
||||
def test_complex():
|
||||
x = [1, 2, 3, 4]
|
||||
y = [1, 2, 1j, 3]
|
||||
|
||||
for ip in [KroghInterpolator, BarycentricInterpolator, pchip, CubicSpline]:
|
||||
p = ip(x, y)
|
||||
assert_allclose(y, p(x))
|
||||
|
||||
dydx = [0, -1j, 2, 3j]
|
||||
p = CubicHermiteSpline(x, y, dydx)
|
||||
assert_allclose(y, p(x))
|
||||
assert_allclose(dydx, p(x, 1))
|
||||
|
||||
|
||||
class TestKrogh(object):
|
||||
def setup_method(self):
|
||||
self.true_poly = np.poly1d([-2,3,1,5,-4])
|
||||
self.test_xs = np.linspace(-1,1,100)
|
||||
self.xs = np.linspace(-1,1,5)
|
||||
self.ys = self.true_poly(self.xs)
|
||||
|
||||
def test_lagrange(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
assert_almost_equal(self.true_poly(self.test_xs),P(self.test_xs))
|
||||
|
||||
def test_scalar(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
assert_almost_equal(self.true_poly(7),P(7))
|
||||
assert_almost_equal(self.true_poly(np.array(7)), P(np.array(7)))
|
||||
|
||||
def test_derivatives(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
D = P.derivatives(self.test_xs)
|
||||
for i in range(D.shape[0]):
|
||||
assert_almost_equal(self.true_poly.deriv(i)(self.test_xs),
|
||||
D[i])
|
||||
|
||||
def test_low_derivatives(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
D = P.derivatives(self.test_xs,len(self.xs)+2)
|
||||
for i in range(D.shape[0]):
|
||||
assert_almost_equal(self.true_poly.deriv(i)(self.test_xs),
|
||||
D[i])
|
||||
|
||||
def test_derivative(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
m = 10
|
||||
r = P.derivatives(self.test_xs,m)
|
||||
for i in range(m):
|
||||
assert_almost_equal(P.derivative(self.test_xs,i),r[i])
|
||||
|
||||
def test_high_derivative(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
for i in range(len(self.xs), 2*len(self.xs)):
|
||||
assert_almost_equal(P.derivative(self.test_xs,i),
|
||||
np.zeros(len(self.test_xs)))
|
||||
|
||||
def test_hermite(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
assert_almost_equal(self.true_poly(self.test_xs),P(self.test_xs))
|
||||
|
||||
def test_vector(self):
|
||||
xs = [0, 1, 2]
|
||||
ys = np.array([[0,1],[1,0],[2,1]])
|
||||
P = KroghInterpolator(xs,ys)
|
||||
Pi = [KroghInterpolator(xs,ys[:,i]) for i in range(ys.shape[1])]
|
||||
test_xs = np.linspace(-1,3,100)
|
||||
assert_almost_equal(P(test_xs),
|
||||
np.rollaxis(np.asarray([p(test_xs) for p in Pi]),-1))
|
||||
assert_almost_equal(P.derivatives(test_xs),
|
||||
np.transpose(np.asarray([p.derivatives(test_xs) for p in Pi]),
|
||||
(1,2,0)))
|
||||
|
||||
def test_empty(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
assert_array_equal(P([]), [])
|
||||
|
||||
def test_shapes_scalarvalue(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
assert_array_equal(np.shape(P(0)), ())
|
||||
assert_array_equal(np.shape(P(np.array(0))), ())
|
||||
assert_array_equal(np.shape(P([0])), (1,))
|
||||
assert_array_equal(np.shape(P([0,1])), (2,))
|
||||
|
||||
def test_shapes_scalarvalue_derivative(self):
|
||||
P = KroghInterpolator(self.xs,self.ys)
|
||||
n = P.n
|
||||
assert_array_equal(np.shape(P.derivatives(0)), (n,))
|
||||
assert_array_equal(np.shape(P.derivatives(np.array(0))), (n,))
|
||||
assert_array_equal(np.shape(P.derivatives([0])), (n,1))
|
||||
assert_array_equal(np.shape(P.derivatives([0,1])), (n,2))
|
||||
|
||||
def test_shapes_vectorvalue(self):
|
||||
P = KroghInterpolator(self.xs,np.outer(self.ys,np.arange(3)))
|
||||
assert_array_equal(np.shape(P(0)), (3,))
|
||||
assert_array_equal(np.shape(P([0])), (1,3))
|
||||
assert_array_equal(np.shape(P([0,1])), (2,3))
|
||||
|
||||
def test_shapes_1d_vectorvalue(self):
|
||||
P = KroghInterpolator(self.xs,np.outer(self.ys,[1]))
|
||||
assert_array_equal(np.shape(P(0)), (1,))
|
||||
assert_array_equal(np.shape(P([0])), (1,1))
|
||||
assert_array_equal(np.shape(P([0,1])), (2,1))
|
||||
|
||||
def test_shapes_vectorvalue_derivative(self):
|
||||
P = KroghInterpolator(self.xs,np.outer(self.ys,np.arange(3)))
|
||||
n = P.n
|
||||
assert_array_equal(np.shape(P.derivatives(0)), (n,3))
|
||||
assert_array_equal(np.shape(P.derivatives([0])), (n,1,3))
|
||||
assert_array_equal(np.shape(P.derivatives([0,1])), (n,2,3))
|
||||
|
||||
def test_wrapper(self):
|
||||
P = KroghInterpolator(self.xs, self.ys)
|
||||
ki = krogh_interpolate
|
||||
assert_almost_equal(P(self.test_xs), ki(self.xs, self.ys, self.test_xs))
|
||||
assert_almost_equal(P.derivative(self.test_xs, 2),
|
||||
ki(self.xs, self.ys, self.test_xs, der=2))
|
||||
assert_almost_equal(P.derivatives(self.test_xs, 2),
|
||||
ki(self.xs, self.ys, self.test_xs, der=[0, 1]))
|
||||
|
||||
def test_int_inputs(self):
|
||||
# Check input args are cast correctly to floats, gh-3669
|
||||
x = [0, 234, 468, 702, 936, 1170, 1404, 2340, 3744, 6084, 8424,
|
||||
13104, 60000]
|
||||
offset_cdf = np.array([-0.95, -0.86114777, -0.8147762, -0.64072425,
|
||||
-0.48002351, -0.34925329, -0.26503107,
|
||||
-0.13148093, -0.12988833, -0.12979296,
|
||||
-0.12973574, -0.08582937, 0.05])
|
||||
f = KroghInterpolator(x, offset_cdf)
|
||||
|
||||
assert_allclose(abs((f(x) - offset_cdf) / f.derivative(x, 1)),
|
||||
0, atol=1e-10)
|
||||
|
||||
def test_derivatives_complex(self):
|
||||
# regression test for gh-7381: krogh.derivatives(0) fails complex y
|
||||
x, y = np.array([-1, -1, 0, 1, 1]), np.array([1, 1.0j, 0, -1, 1.0j])
|
||||
func = KroghInterpolator(x, y)
|
||||
cmplx = func.derivatives(0)
|
||||
|
||||
cmplx2 = (KroghInterpolator(x, y.real).derivatives(0) +
|
||||
1j*KroghInterpolator(x, y.imag).derivatives(0))
|
||||
assert_allclose(cmplx, cmplx2, atol=1e-15)
|
||||
|
||||
|
||||
class TestTaylor(object):
|
||||
def test_exponential(self):
|
||||
degree = 5
|
||||
p = approximate_taylor_polynomial(np.exp, 0, degree, 1, 15)
|
||||
for i in range(degree+1):
|
||||
assert_almost_equal(p(0),1)
|
||||
p = p.deriv()
|
||||
assert_almost_equal(p(0),0)
|
||||
|
||||
|
||||
class TestBarycentric(object):
|
||||
def setup_method(self):
|
||||
self.true_poly = np.poly1d([-2, 3, 1, 5, -4])
|
||||
self.test_xs = np.linspace(-1, 1, 100)
|
||||
self.xs = np.linspace(-1, 1, 5)
|
||||
self.ys = self.true_poly(self.xs)
|
||||
|
||||
def test_lagrange(self):
|
||||
P = BarycentricInterpolator(self.xs, self.ys)
|
||||
assert_almost_equal(self.true_poly(self.test_xs), P(self.test_xs))
|
||||
|
||||
def test_scalar(self):
|
||||
P = BarycentricInterpolator(self.xs, self.ys)
|
||||
assert_almost_equal(self.true_poly(7), P(7))
|
||||
assert_almost_equal(self.true_poly(np.array(7)), P(np.array(7)))
|
||||
|
||||
def test_delayed(self):
|
||||
P = BarycentricInterpolator(self.xs)
|
||||
P.set_yi(self.ys)
|
||||
assert_almost_equal(self.true_poly(self.test_xs), P(self.test_xs))
|
||||
|
||||
def test_append(self):
|
||||
P = BarycentricInterpolator(self.xs[:3], self.ys[:3])
|
||||
P.add_xi(self.xs[3:], self.ys[3:])
|
||||
assert_almost_equal(self.true_poly(self.test_xs), P(self.test_xs))
|
||||
|
||||
def test_vector(self):
|
||||
xs = [0, 1, 2]
|
||||
ys = np.array([[0, 1], [1, 0], [2, 1]])
|
||||
BI = BarycentricInterpolator
|
||||
P = BI(xs, ys)
|
||||
Pi = [BI(xs, ys[:, i]) for i in range(ys.shape[1])]
|
||||
test_xs = np.linspace(-1, 3, 100)
|
||||
assert_almost_equal(P(test_xs),
|
||||
np.rollaxis(np.asarray([p(test_xs) for p in Pi]), -1))
|
||||
|
||||
def test_shapes_scalarvalue(self):
|
||||
P = BarycentricInterpolator(self.xs, self.ys)
|
||||
assert_array_equal(np.shape(P(0)), ())
|
||||
assert_array_equal(np.shape(P(np.array(0))), ())
|
||||
assert_array_equal(np.shape(P([0])), (1,))
|
||||
assert_array_equal(np.shape(P([0, 1])), (2,))
|
||||
|
||||
def test_shapes_vectorvalue(self):
|
||||
P = BarycentricInterpolator(self.xs, np.outer(self.ys, np.arange(3)))
|
||||
assert_array_equal(np.shape(P(0)), (3,))
|
||||
assert_array_equal(np.shape(P([0])), (1, 3))
|
||||
assert_array_equal(np.shape(P([0, 1])), (2, 3))
|
||||
|
||||
def test_shapes_1d_vectorvalue(self):
|
||||
P = BarycentricInterpolator(self.xs, np.outer(self.ys, [1]))
|
||||
assert_array_equal(np.shape(P(0)), (1,))
|
||||
assert_array_equal(np.shape(P([0])), (1, 1))
|
||||
assert_array_equal(np.shape(P([0,1])), (2, 1))
|
||||
|
||||
def test_wrapper(self):
|
||||
P = BarycentricInterpolator(self.xs, self.ys)
|
||||
values = barycentric_interpolate(self.xs, self.ys, self.test_xs)
|
||||
assert_almost_equal(P(self.test_xs), values)
|
||||
|
||||
def test_int_input(self):
|
||||
x = 1000 * np.arange(1, 11) # np.prod(x[-1] - x[:-1]) overflows
|
||||
y = np.arange(1, 11)
|
||||
value = barycentric_interpolate(x, y, 1000 * 9.5)
|
||||
assert_almost_equal(value, 9.5)
|
||||
|
||||
|
||||
class TestPCHIP(object):
|
||||
def _make_random(self, npts=20):
|
||||
np.random.seed(1234)
|
||||
xi = np.sort(np.random.random(npts))
|
||||
yi = np.random.random(npts)
|
||||
return pchip(xi, yi), xi, yi
|
||||
|
||||
def test_overshoot(self):
|
||||
# PCHIP should not overshoot
|
||||
p, xi, yi = self._make_random()
|
||||
for i in range(len(xi)-1):
|
||||
x1, x2 = xi[i], xi[i+1]
|
||||
y1, y2 = yi[i], yi[i+1]
|
||||
if y1 > y2:
|
||||
y1, y2 = y2, y1
|
||||
xp = np.linspace(x1, x2, 10)
|
||||
yp = p(xp)
|
||||
assert_(((y1 <= yp + 1e-15) & (yp <= y2 + 1e-15)).all())
|
||||
|
||||
def test_monotone(self):
|
||||
# PCHIP should preserve monotonicty
|
||||
p, xi, yi = self._make_random()
|
||||
for i in range(len(xi)-1):
|
||||
x1, x2 = xi[i], xi[i+1]
|
||||
y1, y2 = yi[i], yi[i+1]
|
||||
xp = np.linspace(x1, x2, 10)
|
||||
yp = p(xp)
|
||||
assert_(((y2-y1) * (yp[1:] - yp[:1]) > 0).all())
|
||||
|
||||
def test_cast(self):
|
||||
# regression test for integer input data, see gh-3453
|
||||
data = np.array([[0, 4, 12, 27, 47, 60, 79, 87, 99, 100],
|
||||
[-33, -33, -19, -2, 12, 26, 38, 45, 53, 55]])
|
||||
xx = np.arange(100)
|
||||
curve = pchip(data[0], data[1])(xx)
|
||||
|
||||
data1 = data * 1.0
|
||||
curve1 = pchip(data1[0], data1[1])(xx)
|
||||
|
||||
assert_allclose(curve, curve1, atol=1e-14, rtol=1e-14)
|
||||
|
||||
def test_nag(self):
|
||||
# Example from NAG C implementation,
|
||||
# http://nag.com/numeric/cl/nagdoc_cl25/html/e01/e01bec.html
|
||||
# suggested in gh-5326 as a smoke test for the way the derivatives
|
||||
# are computed (see also gh-3453)
|
||||
dataStr = '''
|
||||
7.99 0.00000E+0
|
||||
8.09 0.27643E-4
|
||||
8.19 0.43750E-1
|
||||
8.70 0.16918E+0
|
||||
9.20 0.46943E+0
|
||||
10.00 0.94374E+0
|
||||
12.00 0.99864E+0
|
||||
15.00 0.99992E+0
|
||||
20.00 0.99999E+0
|
||||
'''
|
||||
data = np.loadtxt(io.StringIO(dataStr))
|
||||
pch = pchip(data[:,0], data[:,1])
|
||||
|
||||
resultStr = '''
|
||||
7.9900 0.0000
|
||||
9.1910 0.4640
|
||||
10.3920 0.9645
|
||||
11.5930 0.9965
|
||||
12.7940 0.9992
|
||||
13.9950 0.9998
|
||||
15.1960 0.9999
|
||||
16.3970 1.0000
|
||||
17.5980 1.0000
|
||||
18.7990 1.0000
|
||||
20.0000 1.0000
|
||||
'''
|
||||
result = np.loadtxt(io.StringIO(resultStr))
|
||||
assert_allclose(result[:,1], pch(result[:,0]), rtol=0., atol=5e-5)
|
||||
|
||||
def test_endslopes(self):
|
||||
# this is a smoke test for gh-3453: PCHIP interpolator should not
|
||||
# set edge slopes to zero if the data do not suggest zero edge derivatives
|
||||
x = np.array([0.0, 0.1, 0.25, 0.35])
|
||||
y1 = np.array([279.35, 0.5e3, 1.0e3, 2.5e3])
|
||||
y2 = np.array([279.35, 2.5e3, 1.50e3, 1.0e3])
|
||||
for pp in (pchip(x, y1), pchip(x, y2)):
|
||||
for t in (x[0], x[-1]):
|
||||
assert_(pp(t, 1) != 0)
|
||||
|
||||
def test_all_zeros(self):
|
||||
x = np.arange(10)
|
||||
y = np.zeros_like(x)
|
||||
|
||||
# this should work and not generate any warnings
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings('error')
|
||||
pch = pchip(x, y)
|
||||
|
||||
xx = np.linspace(0, 9, 101)
|
||||
assert_equal(pch(xx), 0.)
|
||||
|
||||
def test_two_points(self):
|
||||
# regression test for gh-6222: pchip([0, 1], [0, 1]) fails because
|
||||
# it tries to use a three-point scheme to estimate edge derivatives,
|
||||
# while there are only two points available.
|
||||
# Instead, it should construct a linear interpolator.
|
||||
x = np.linspace(0, 1, 11)
|
||||
p = pchip([0, 1], [0, 2])
|
||||
assert_allclose(p(x), 2*x, atol=1e-15)
|
||||
|
||||
def test_pchip_interpolate(self):
|
||||
assert_array_almost_equal(
|
||||
pchip_interpolate([1,2,3], [4,5,6], [0.5], der=1),
|
||||
[1.])
|
||||
|
||||
assert_array_almost_equal(
|
||||
pchip_interpolate([1,2,3], [4,5,6], [0.5], der=0),
|
||||
[3.5])
|
||||
|
||||
assert_array_almost_equal(
|
||||
pchip_interpolate([1,2,3], [4,5,6], [0.5], der=[0, 1]),
|
||||
[[3.5], [1]])
|
||||
|
||||
def test_roots(self):
|
||||
# regression test for gh-6357: .roots method should work
|
||||
p = pchip([0, 1], [-1, 1])
|
||||
r = p.roots()
|
||||
assert_allclose(r, 0.5)
|
||||
|
||||
|
||||
class TestCubicSpline(object):
|
||||
@staticmethod
|
||||
def check_correctness(S, bc_start='not-a-knot', bc_end='not-a-knot',
|
||||
tol=1e-14):
|
||||
"""Check that spline coefficients satisfy the continuity and boundary
|
||||
conditions."""
|
||||
x = S.x
|
||||
c = S.c
|
||||
dx = np.diff(x)
|
||||
dx = dx.reshape([dx.shape[0]] + [1] * (c.ndim - 2))
|
||||
dxi = dx[:-1]
|
||||
|
||||
# Check C2 continuity.
|
||||
assert_allclose(c[3, 1:], c[0, :-1] * dxi**3 + c[1, :-1] * dxi**2 +
|
||||
c[2, :-1] * dxi + c[3, :-1], rtol=tol, atol=tol)
|
||||
assert_allclose(c[2, 1:], 3 * c[0, :-1] * dxi**2 +
|
||||
2 * c[1, :-1] * dxi + c[2, :-1], rtol=tol, atol=tol)
|
||||
assert_allclose(c[1, 1:], 3 * c[0, :-1] * dxi + c[1, :-1],
|
||||
rtol=tol, atol=tol)
|
||||
|
||||
# Check that we found a parabola, the third derivative is 0.
|
||||
if x.size == 3 and bc_start == 'not-a-knot' and bc_end == 'not-a-knot':
|
||||
assert_allclose(c[0], 0, rtol=tol, atol=tol)
|
||||
return
|
||||
|
||||
# Check periodic boundary conditions.
|
||||
if bc_start == 'periodic':
|
||||
assert_allclose(S(x[0], 0), S(x[-1], 0), rtol=tol, atol=tol)
|
||||
assert_allclose(S(x[0], 1), S(x[-1], 1), rtol=tol, atol=tol)
|
||||
assert_allclose(S(x[0], 2), S(x[-1], 2), rtol=tol, atol=tol)
|
||||
return
|
||||
|
||||
# Check other boundary conditions.
|
||||
if bc_start == 'not-a-knot':
|
||||
if x.size == 2:
|
||||
slope = (S(x[1]) - S(x[0])) / dx[0]
|
||||
assert_allclose(S(x[0], 1), slope, rtol=tol, atol=tol)
|
||||
else:
|
||||
assert_allclose(c[0, 0], c[0, 1], rtol=tol, atol=tol)
|
||||
elif bc_start == 'clamped':
|
||||
assert_allclose(S(x[0], 1), 0, rtol=tol, atol=tol)
|
||||
elif bc_start == 'natural':
|
||||
assert_allclose(S(x[0], 2), 0, rtol=tol, atol=tol)
|
||||
else:
|
||||
order, value = bc_start
|
||||
assert_allclose(S(x[0], order), value, rtol=tol, atol=tol)
|
||||
|
||||
if bc_end == 'not-a-knot':
|
||||
if x.size == 2:
|
||||
slope = (S(x[1]) - S(x[0])) / dx[0]
|
||||
assert_allclose(S(x[1], 1), slope, rtol=tol, atol=tol)
|
||||
else:
|
||||
assert_allclose(c[0, -1], c[0, -2], rtol=tol, atol=tol)
|
||||
elif bc_end == 'clamped':
|
||||
assert_allclose(S(x[-1], 1), 0, rtol=tol, atol=tol)
|
||||
elif bc_end == 'natural':
|
||||
assert_allclose(S(x[-1], 2), 0, rtol=2*tol, atol=2*tol)
|
||||
else:
|
||||
order, value = bc_end
|
||||
assert_allclose(S(x[-1], order), value, rtol=tol, atol=tol)
|
||||
|
||||
def check_all_bc(self, x, y, axis):
|
||||
deriv_shape = list(y.shape)
|
||||
del deriv_shape[axis]
|
||||
first_deriv = np.empty(deriv_shape)
|
||||
first_deriv.fill(2)
|
||||
second_deriv = np.empty(deriv_shape)
|
||||
second_deriv.fill(-1)
|
||||
bc_all = [
|
||||
'not-a-knot',
|
||||
'natural',
|
||||
'clamped',
|
||||
(1, first_deriv),
|
||||
(2, second_deriv)
|
||||
]
|
||||
for bc in bc_all[:3]:
|
||||
S = CubicSpline(x, y, axis=axis, bc_type=bc)
|
||||
self.check_correctness(S, bc, bc)
|
||||
|
||||
for bc_start in bc_all:
|
||||
for bc_end in bc_all:
|
||||
S = CubicSpline(x, y, axis=axis, bc_type=(bc_start, bc_end))
|
||||
self.check_correctness(S, bc_start, bc_end, tol=2e-14)
|
||||
|
||||
def test_general(self):
|
||||
x = np.array([-1, 0, 0.5, 2, 4, 4.5, 5.5, 9])
|
||||
y = np.array([0, -0.5, 2, 3, 2.5, 1, 1, 0.5])
|
||||
for n in [2, 3, x.size]:
|
||||
self.check_all_bc(x[:n], y[:n], 0)
|
||||
|
||||
Y = np.empty((2, n, 2))
|
||||
Y[0, :, 0] = y[:n]
|
||||
Y[0, :, 1] = y[:n] - 1
|
||||
Y[1, :, 0] = y[:n] + 2
|
||||
Y[1, :, 1] = y[:n] + 3
|
||||
self.check_all_bc(x[:n], Y, 1)
|
||||
|
||||
def test_periodic(self):
|
||||
for n in [2, 3, 5]:
|
||||
x = np.linspace(0, 2 * np.pi, n)
|
||||
y = np.cos(x)
|
||||
S = CubicSpline(x, y, bc_type='periodic')
|
||||
self.check_correctness(S, 'periodic', 'periodic')
|
||||
|
||||
Y = np.empty((2, n, 2))
|
||||
Y[0, :, 0] = y
|
||||
Y[0, :, 1] = y + 2
|
||||
Y[1, :, 0] = y - 1
|
||||
Y[1, :, 1] = y + 5
|
||||
S = CubicSpline(x, Y, axis=1, bc_type='periodic')
|
||||
self.check_correctness(S, 'periodic', 'periodic')
|
||||
|
||||
def test_periodic_eval(self):
|
||||
x = np.linspace(0, 2 * np.pi, 10)
|
||||
y = np.cos(x)
|
||||
S = CubicSpline(x, y, bc_type='periodic')
|
||||
assert_almost_equal(S(1), S(1 + 2 * np.pi), decimal=15)
|
||||
|
||||
def test_dtypes(self):
|
||||
x = np.array([0, 1, 2, 3], dtype=int)
|
||||
y = np.array([-5, 2, 3, 1], dtype=int)
|
||||
S = CubicSpline(x, y)
|
||||
self.check_correctness(S)
|
||||
|
||||
y = np.array([-1+1j, 0.0, 1-1j, 0.5-1.5j])
|
||||
S = CubicSpline(x, y)
|
||||
self.check_correctness(S)
|
||||
|
||||
S = CubicSpline(x, x ** 3, bc_type=("natural", (1, 2j)))
|
||||
self.check_correctness(S, "natural", (1, 2j))
|
||||
|
||||
y = np.array([-5, 2, 3, 1])
|
||||
S = CubicSpline(x, y, bc_type=[(1, 2 + 0.5j), (2, 0.5 - 1j)])
|
||||
self.check_correctness(S, (1, 2 + 0.5j), (2, 0.5 - 1j))
|
||||
|
||||
def test_small_dx(self):
|
||||
rng = np.random.RandomState(0)
|
||||
x = np.sort(rng.uniform(size=100))
|
||||
y = 1e4 + rng.uniform(size=100)
|
||||
S = CubicSpline(x, y)
|
||||
self.check_correctness(S, tol=1e-13)
|
||||
|
||||
def test_incorrect_inputs(self):
|
||||
x = np.array([1, 2, 3, 4])
|
||||
y = np.array([1, 2, 3, 4])
|
||||
xc = np.array([1 + 1j, 2, 3, 4])
|
||||
xn = np.array([np.nan, 2, 3, 4])
|
||||
xo = np.array([2, 1, 3, 4])
|
||||
yn = np.array([np.nan, 2, 3, 4])
|
||||
y3 = [1, 2, 3]
|
||||
x1 = [1]
|
||||
y1 = [1]
|
||||
|
||||
assert_raises(ValueError, CubicSpline, xc, y)
|
||||
assert_raises(ValueError, CubicSpline, xn, y)
|
||||
assert_raises(ValueError, CubicSpline, x, yn)
|
||||
assert_raises(ValueError, CubicSpline, xo, y)
|
||||
assert_raises(ValueError, CubicSpline, x, y3)
|
||||
assert_raises(ValueError, CubicSpline, x[:, np.newaxis], y)
|
||||
assert_raises(ValueError, CubicSpline, x1, y1)
|
||||
|
||||
wrong_bc = [('periodic', 'clamped'),
|
||||
((2, 0), (3, 10)),
|
||||
((1, 0), ),
|
||||
(0., 0.),
|
||||
'not-a-typo']
|
||||
|
||||
for bc_type in wrong_bc:
|
||||
assert_raises(ValueError, CubicSpline, x, y, 0, bc_type, True)
|
||||
|
||||
# Shapes mismatch when giving arbitrary derivative values:
|
||||
Y = np.c_[y, y]
|
||||
bc1 = ('clamped', (1, 0))
|
||||
bc2 = ('clamped', (1, [0, 0, 0]))
|
||||
bc3 = ('clamped', (1, [[0, 0]]))
|
||||
assert_raises(ValueError, CubicSpline, x, Y, 0, bc1, True)
|
||||
assert_raises(ValueError, CubicSpline, x, Y, 0, bc2, True)
|
||||
assert_raises(ValueError, CubicSpline, x, Y, 0, bc3, True)
|
||||
|
||||
# periodic condition, y[-1] must be equal to y[0]:
|
||||
assert_raises(ValueError, CubicSpline, x, y, 0, 'periodic', True)
|
||||
|
||||
|
||||
def test_CubicHermiteSpline_correctness():
|
||||
x = [0, 2, 7]
|
||||
y = [-1, 2, 3]
|
||||
dydx = [0, 3, 7]
|
||||
s = CubicHermiteSpline(x, y, dydx)
|
||||
assert_allclose(s(x), y, rtol=1e-15)
|
||||
assert_allclose(s(x, 1), dydx, rtol=1e-15)
|
||||
|
||||
|
||||
def test_CubicHermiteSpline_error_handling():
|
||||
x = [1, 2, 3]
|
||||
y = [0, 3, 5]
|
||||
dydx = [1, -1, 2, 3]
|
||||
assert_raises(ValueError, CubicHermiteSpline, x, y, dydx)
|
||||
|
||||
dydx_with_nan = [1, 0, np.nan]
|
||||
assert_raises(ValueError, CubicHermiteSpline, x, y, dydx_with_nan)
|
||||
|
||||
|
||||
def test_roots_extrapolate_gh_11185():
|
||||
x = np.array([0.001, 0.002])
|
||||
y = np.array([1.66066935e-06, 1.10410807e-06])
|
||||
dy = np.array([-1.60061854, -1.600619])
|
||||
p = CubicHermiteSpline(x, y, dy)
|
||||
|
||||
# roots(extrapolate=True) for a polynomial with a single interval
|
||||
# should return all three real roots
|
||||
r = p.roots(extrapolate=True)
|
||||
assert_equal(p.c.shape[1], 1)
|
||||
assert_equal(r.size, 3)
|
221
venv/Lib/site-packages/scipy/interpolate/tests/test_rbf.py
Normal file
221
venv/Lib/site-packages/scipy/interpolate/tests/test_rbf.py
Normal file
|
@ -0,0 +1,221 @@
|
|||
# Created by John Travers, Robert Hetland, 2007
|
||||
""" Test functions for rbf module """
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import (assert_, assert_array_almost_equal,
|
||||
assert_almost_equal)
|
||||
from numpy import linspace, sin, cos, random, exp, allclose
|
||||
from scipy.interpolate.rbf import Rbf
|
||||
|
||||
FUNCTIONS = ('multiquadric', 'inverse multiquadric', 'gaussian',
|
||||
'cubic', 'quintic', 'thin-plate', 'linear')
|
||||
|
||||
|
||||
def check_rbf1d_interpolation(function):
|
||||
# Check that the Rbf function interpolates through the nodes (1D)
|
||||
x = linspace(0,10,9)
|
||||
y = sin(x)
|
||||
rbf = Rbf(x, y, function=function)
|
||||
yi = rbf(x)
|
||||
assert_array_almost_equal(y, yi)
|
||||
assert_almost_equal(rbf(float(x[0])), y[0])
|
||||
|
||||
|
||||
def check_rbf2d_interpolation(function):
|
||||
# Check that the Rbf function interpolates through the nodes (2D).
|
||||
x = random.rand(50,1)*4-2
|
||||
y = random.rand(50,1)*4-2
|
||||
z = x*exp(-x**2-1j*y**2)
|
||||
rbf = Rbf(x, y, z, epsilon=2, function=function)
|
||||
zi = rbf(x, y)
|
||||
zi.shape = x.shape
|
||||
assert_array_almost_equal(z, zi)
|
||||
|
||||
|
||||
def check_rbf3d_interpolation(function):
|
||||
# Check that the Rbf function interpolates through the nodes (3D).
|
||||
x = random.rand(50, 1)*4 - 2
|
||||
y = random.rand(50, 1)*4 - 2
|
||||
z = random.rand(50, 1)*4 - 2
|
||||
d = x*exp(-x**2 - y**2)
|
||||
rbf = Rbf(x, y, z, d, epsilon=2, function=function)
|
||||
di = rbf(x, y, z)
|
||||
di.shape = x.shape
|
||||
assert_array_almost_equal(di, d)
|
||||
|
||||
|
||||
def test_rbf_interpolation():
|
||||
for function in FUNCTIONS:
|
||||
check_rbf1d_interpolation(function)
|
||||
check_rbf2d_interpolation(function)
|
||||
check_rbf3d_interpolation(function)
|
||||
|
||||
|
||||
def check_2drbf1d_interpolation(function):
|
||||
# Check that the 2-D Rbf function interpolates through the nodes (1D)
|
||||
x = linspace(0, 10, 9)
|
||||
y0 = sin(x)
|
||||
y1 = cos(x)
|
||||
y = np.vstack([y0, y1]).T
|
||||
rbf = Rbf(x, y, function=function, mode='N-D')
|
||||
yi = rbf(x)
|
||||
assert_array_almost_equal(y, yi)
|
||||
assert_almost_equal(rbf(float(x[0])), y[0])
|
||||
|
||||
|
||||
def check_2drbf2d_interpolation(function):
|
||||
# Check that the 2-D Rbf function interpolates through the nodes (2D).
|
||||
x = random.rand(50, ) * 4 - 2
|
||||
y = random.rand(50, ) * 4 - 2
|
||||
z0 = x * exp(-x ** 2 - 1j * y ** 2)
|
||||
z1 = y * exp(-y ** 2 - 1j * x ** 2)
|
||||
z = np.vstack([z0, z1]).T
|
||||
rbf = Rbf(x, y, z, epsilon=2, function=function, mode='N-D')
|
||||
zi = rbf(x, y)
|
||||
zi.shape = z.shape
|
||||
assert_array_almost_equal(z, zi)
|
||||
|
||||
|
||||
def check_2drbf3d_interpolation(function):
|
||||
# Check that the 2-D Rbf function interpolates through the nodes (3D).
|
||||
x = random.rand(50, ) * 4 - 2
|
||||
y = random.rand(50, ) * 4 - 2
|
||||
z = random.rand(50, ) * 4 - 2
|
||||
d0 = x * exp(-x ** 2 - y ** 2)
|
||||
d1 = y * exp(-y ** 2 - x ** 2)
|
||||
d = np.vstack([d0, d1]).T
|
||||
rbf = Rbf(x, y, z, d, epsilon=2, function=function, mode='N-D')
|
||||
di = rbf(x, y, z)
|
||||
di.shape = d.shape
|
||||
assert_array_almost_equal(di, d)
|
||||
|
||||
|
||||
def test_2drbf_interpolation():
|
||||
for function in FUNCTIONS:
|
||||
check_2drbf1d_interpolation(function)
|
||||
check_2drbf2d_interpolation(function)
|
||||
check_2drbf3d_interpolation(function)
|
||||
|
||||
|
||||
def check_rbf1d_regularity(function, atol):
|
||||
# Check that the Rbf function approximates a smooth function well away
|
||||
# from the nodes.
|
||||
x = linspace(0, 10, 9)
|
||||
y = sin(x)
|
||||
rbf = Rbf(x, y, function=function)
|
||||
xi = linspace(0, 10, 100)
|
||||
yi = rbf(xi)
|
||||
msg = "abs-diff: %f" % abs(yi - sin(xi)).max()
|
||||
assert_(allclose(yi, sin(xi), atol=atol), msg)
|
||||
|
||||
|
||||
def test_rbf_regularity():
|
||||
tolerances = {
|
||||
'multiquadric': 0.1,
|
||||
'inverse multiquadric': 0.15,
|
||||
'gaussian': 0.15,
|
||||
'cubic': 0.15,
|
||||
'quintic': 0.1,
|
||||
'thin-plate': 0.1,
|
||||
'linear': 0.2
|
||||
}
|
||||
for function in FUNCTIONS:
|
||||
check_rbf1d_regularity(function, tolerances.get(function, 1e-2))
|
||||
|
||||
|
||||
def check_2drbf1d_regularity(function, atol):
|
||||
# Check that the 2-D Rbf function approximates a smooth function well away
|
||||
# from the nodes.
|
||||
x = linspace(0, 10, 9)
|
||||
y0 = sin(x)
|
||||
y1 = cos(x)
|
||||
y = np.vstack([y0, y1]).T
|
||||
rbf = Rbf(x, y, function=function, mode='N-D')
|
||||
xi = linspace(0, 10, 100)
|
||||
yi = rbf(xi)
|
||||
msg = "abs-diff: %f" % abs(yi - np.vstack([sin(xi), cos(xi)]).T).max()
|
||||
assert_(allclose(yi, np.vstack([sin(xi), cos(xi)]).T, atol=atol), msg)
|
||||
|
||||
|
||||
def test_2drbf_regularity():
|
||||
tolerances = {
|
||||
'multiquadric': 0.1,
|
||||
'inverse multiquadric': 0.15,
|
||||
'gaussian': 0.15,
|
||||
'cubic': 0.15,
|
||||
'quintic': 0.1,
|
||||
'thin-plate': 0.15,
|
||||
'linear': 0.2
|
||||
}
|
||||
for function in FUNCTIONS:
|
||||
check_2drbf1d_regularity(function, tolerances.get(function, 1e-2))
|
||||
|
||||
|
||||
def check_rbf1d_stability(function):
|
||||
# Check that the Rbf function with default epsilon is not subject
|
||||
# to overshoot. Regression for issue #4523.
|
||||
#
|
||||
# Generate some data (fixed random seed hence deterministic)
|
||||
np.random.seed(1234)
|
||||
x = np.linspace(0, 10, 50)
|
||||
z = x + 4.0 * np.random.randn(len(x))
|
||||
|
||||
rbf = Rbf(x, z, function=function)
|
||||
xi = np.linspace(0, 10, 1000)
|
||||
yi = rbf(xi)
|
||||
|
||||
# subtract the linear trend and make sure there no spikes
|
||||
assert_(np.abs(yi-xi).max() / np.abs(z-x).max() < 1.1)
|
||||
|
||||
def test_rbf_stability():
|
||||
for function in FUNCTIONS:
|
||||
check_rbf1d_stability(function)
|
||||
|
||||
|
||||
def test_default_construction():
|
||||
# Check that the Rbf class can be constructed with the default
|
||||
# multiquadric basis function. Regression test for ticket #1228.
|
||||
x = linspace(0,10,9)
|
||||
y = sin(x)
|
||||
rbf = Rbf(x, y)
|
||||
yi = rbf(x)
|
||||
assert_array_almost_equal(y, yi)
|
||||
|
||||
|
||||
def test_function_is_callable():
|
||||
# Check that the Rbf class can be constructed with function=callable.
|
||||
x = linspace(0,10,9)
|
||||
y = sin(x)
|
||||
linfunc = lambda x:x
|
||||
rbf = Rbf(x, y, function=linfunc)
|
||||
yi = rbf(x)
|
||||
assert_array_almost_equal(y, yi)
|
||||
|
||||
|
||||
def test_two_arg_function_is_callable():
|
||||
# Check that the Rbf class can be constructed with a two argument
|
||||
# function=callable.
|
||||
def _func(self, r):
|
||||
return self.epsilon + r
|
||||
|
||||
x = linspace(0,10,9)
|
||||
y = sin(x)
|
||||
rbf = Rbf(x, y, function=_func)
|
||||
yi = rbf(x)
|
||||
assert_array_almost_equal(y, yi)
|
||||
|
||||
|
||||
def test_rbf_epsilon_none():
|
||||
x = linspace(0, 10, 9)
|
||||
y = sin(x)
|
||||
Rbf(x, y, epsilon=None)
|
||||
|
||||
|
||||
def test_rbf_epsilon_none_collinear():
|
||||
# Check that collinear points in one dimension doesn't cause an error
|
||||
# due to epsilon = 0
|
||||
x = [1, 2, 3]
|
||||
y = [4, 4, 4]
|
||||
z = [5, 6, 7]
|
||||
rbf = Rbf(x, y, z, epsilon=None)
|
||||
assert_(rbf.epsilon > 0)
|
|
@ -0,0 +1,14 @@
|
|||
import numpy as np
|
||||
import scipy.interpolate as interp
|
||||
from numpy.testing import assert_almost_equal
|
||||
|
||||
|
||||
class TestRegression(object):
|
||||
def test_spalde_scalar_input(self):
|
||||
"""Ticket #629"""
|
||||
x = np.linspace(0,10)
|
||||
y = x**3
|
||||
tck = interp.splrep(x, y, k=3, t=[5])
|
||||
res = interp.spalde(np.float64(1), tck)
|
||||
des = np.array([1., 3., 6., 6.])
|
||||
assert_almost_equal(res, des)
|
Loading…
Add table
Add a link
Reference in a new issue