Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/interpolate/_polyint.py: 15%
207 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
1import warnings
3import numpy as np
4from scipy.special import factorial
5from scipy._lib._util import _asarray_validated, float_factorial
8__all__ = ["KroghInterpolator", "krogh_interpolate", "BarycentricInterpolator",
9 "barycentric_interpolate", "approximate_taylor_polynomial"]
12def _isscalar(x):
13 """Check whether x is if a scalar type, or 0-dim"""
14 return np.isscalar(x) or hasattr(x, 'shape') and x.shape == ()
17class _Interpolator1D:
18 """
19 Common features in univariate interpolation
21 Deal with input data type and interpolation axis rolling. The
22 actual interpolator can assume the y-data is of shape (n, r) where
23 `n` is the number of x-points, and `r` the number of variables,
24 and use self.dtype as the y-data type.
26 Attributes
27 ----------
28 _y_axis
29 Axis along which the interpolation goes in the original array
30 _y_extra_shape
31 Additional trailing shape of the input arrays, excluding
32 the interpolation axis.
33 dtype
34 Dtype of the y-data arrays. Can be set via _set_dtype, which
35 forces it to be float or complex.
37 Methods
38 -------
39 __call__
40 _prepare_x
41 _finish_y
42 _reshape_yi
43 _set_yi
44 _set_dtype
45 _evaluate
47 """
49 __slots__ = ('_y_axis', '_y_extra_shape', 'dtype')
51 def __init__(self, xi=None, yi=None, axis=None):
52 self._y_axis = axis
53 self._y_extra_shape = None
54 self.dtype = None
55 if yi is not None:
56 self._set_yi(yi, xi=xi, axis=axis)
58 def __call__(self, x):
59 """
60 Evaluate the interpolant
62 Parameters
63 ----------
64 x : array_like
65 Points to evaluate the interpolant at.
67 Returns
68 -------
69 y : array_like
70 Interpolated values. Shape is determined by replacing
71 the interpolation axis in the original array with the shape of x.
73 Notes
74 -----
75 Input values `x` must be convertible to `float` values like `int`
76 or `float`.
78 """
79 x, x_shape = self._prepare_x(x)
80 y = self._evaluate(x)
81 return self._finish_y(y, x_shape)
83 def _evaluate(self, x):
84 """
85 Actually evaluate the value of the interpolator.
86 """
87 raise NotImplementedError()
89 def _prepare_x(self, x):
90 """Reshape input x array to 1-D"""
91 x = _asarray_validated(x, check_finite=False, as_inexact=True)
92 x_shape = x.shape
93 return x.ravel(), x_shape
95 def _finish_y(self, y, x_shape):
96 """Reshape interpolated y back to an N-D array similar to initial y"""
97 y = y.reshape(x_shape + self._y_extra_shape)
98 if self._y_axis != 0 and x_shape != ():
99 nx = len(x_shape)
100 ny = len(self._y_extra_shape)
101 s = (list(range(nx, nx + self._y_axis))
102 + list(range(nx)) + list(range(nx+self._y_axis, nx+ny)))
103 y = y.transpose(s)
104 return y
106 def _reshape_yi(self, yi, check=False):
107 yi = np.moveaxis(np.asarray(yi), self._y_axis, 0)
108 if check and yi.shape[1:] != self._y_extra_shape:
109 ok_shape = "%r + (N,) + %r" % (self._y_extra_shape[-self._y_axis:],
110 self._y_extra_shape[:-self._y_axis])
111 raise ValueError("Data must be of shape %s" % ok_shape)
112 return yi.reshape((yi.shape[0], -1))
114 def _set_yi(self, yi, xi=None, axis=None):
115 if axis is None:
116 axis = self._y_axis
117 if axis is None:
118 raise ValueError("no interpolation axis specified")
120 yi = np.asarray(yi)
122 shape = yi.shape
123 if shape == ():
124 shape = (1,)
125 if xi is not None and shape[axis] != len(xi):
126 raise ValueError("x and y arrays must be equal in length along "
127 "interpolation axis.")
129 self._y_axis = (axis % yi.ndim)
130 self._y_extra_shape = yi.shape[:self._y_axis]+yi.shape[self._y_axis+1:]
131 self.dtype = None
132 self._set_dtype(yi.dtype)
134 def _set_dtype(self, dtype, union=False):
135 if np.issubdtype(dtype, np.complexfloating) \
136 or np.issubdtype(self.dtype, np.complexfloating):
137 self.dtype = np.complex_
138 else:
139 if not union or self.dtype != np.complex_:
140 self.dtype = np.float_
143class _Interpolator1DWithDerivatives(_Interpolator1D):
144 def derivatives(self, x, der=None):
145 """
146 Evaluate many derivatives of the polynomial at the point x
148 Produce an array of all derivative values at the point x.
150 Parameters
151 ----------
152 x : array_like
153 Point or points at which to evaluate the derivatives
154 der : int or None, optional
155 How many derivatives to extract; None for all potentially
156 nonzero derivatives (that is a number equal to the number
157 of points). This number includes the function value as 0th
158 derivative.
160 Returns
161 -------
162 d : ndarray
163 Array with derivatives; d[j] contains the jth derivative.
164 Shape of d[j] is determined by replacing the interpolation
165 axis in the original array with the shape of x.
167 Examples
168 --------
169 >>> from scipy.interpolate import KroghInterpolator
170 >>> KroghInterpolator([0,0,0],[1,2,3]).derivatives(0)
171 array([1.0,2.0,3.0])
172 >>> KroghInterpolator([0,0,0],[1,2,3]).derivatives([0,0])
173 array([[1.0,1.0],
174 [2.0,2.0],
175 [3.0,3.0]])
177 """
178 x, x_shape = self._prepare_x(x)
179 y = self._evaluate_derivatives(x, der)
181 y = y.reshape((y.shape[0],) + x_shape + self._y_extra_shape)
182 if self._y_axis != 0 and x_shape != ():
183 nx = len(x_shape)
184 ny = len(self._y_extra_shape)
185 s = ([0] + list(range(nx+1, nx + self._y_axis+1))
186 + list(range(1, nx+1)) +
187 list(range(nx+1+self._y_axis, nx+ny+1)))
188 y = y.transpose(s)
189 return y
191 def derivative(self, x, der=1):
192 """
193 Evaluate one derivative of the polynomial at the point x
195 Parameters
196 ----------
197 x : array_like
198 Point or points at which to evaluate the derivatives
200 der : integer, optional
201 Which derivative to extract. This number includes the
202 function value as 0th derivative.
204 Returns
205 -------
206 d : ndarray
207 Derivative interpolated at the x-points. Shape of d is
208 determined by replacing the interpolation axis in the
209 original array with the shape of x.
211 Notes
212 -----
213 This is computed by evaluating all derivatives up to the desired
214 one (using self.derivatives()) and then discarding the rest.
216 """
217 x, x_shape = self._prepare_x(x)
218 y = self._evaluate_derivatives(x, der+1)
219 return self._finish_y(y[der], x_shape)
222class KroghInterpolator(_Interpolator1DWithDerivatives):
223 """
224 Interpolating polynomial for a set of points.
226 The polynomial passes through all the pairs (xi,yi). One may
227 additionally specify a number of derivatives at each point xi;
228 this is done by repeating the value xi and specifying the
229 derivatives as successive yi values.
231 Allows evaluation of the polynomial and all its derivatives.
232 For reasons of numerical stability, this function does not compute
233 the coefficients of the polynomial, although they can be obtained
234 by evaluating all the derivatives.
236 Parameters
237 ----------
238 xi : array_like, length N
239 Known x-coordinates. Must be sorted in increasing order.
240 yi : array_like
241 Known y-coordinates. When an xi occurs two or more times in
242 a row, the corresponding yi's represent derivative values.
243 axis : int, optional
244 Axis in the yi array corresponding to the x-coordinate values.
246 Notes
247 -----
248 Be aware that the algorithms implemented here are not necessarily
249 the most numerically stable known. Moreover, even in a world of
250 exact computation, unless the x coordinates are chosen very
251 carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
252 polynomial interpolation itself is a very ill-conditioned process
253 due to the Runge phenomenon. In general, even with well-chosen
254 x values, degrees higher than about thirty cause problems with
255 numerical instability in this code.
257 Based on [1]_.
259 References
260 ----------
261 .. [1] Krogh, "Efficient Algorithms for Polynomial Interpolation
262 and Numerical Differentiation", 1970.
264 Examples
265 --------
266 To produce a polynomial that is zero at 0 and 1 and has
267 derivative 2 at 0, call
269 >>> from scipy.interpolate import KroghInterpolator
270 >>> KroghInterpolator([0,0,1],[0,2,0])
272 This constructs the quadratic 2*X**2-2*X. The derivative condition
273 is indicated by the repeated zero in the xi array; the corresponding
274 yi values are 0, the function value, and 2, the derivative value.
276 For another example, given xi, yi, and a derivative ypi for each
277 point, appropriate arrays can be constructed as:
279 >>> import numpy as np
280 >>> rng = np.random.default_rng()
281 >>> xi = np.linspace(0, 1, 5)
282 >>> yi, ypi = rng.random((2, 5))
283 >>> xi_k, yi_k = np.repeat(xi, 2), np.ravel(np.dstack((yi,ypi)))
284 >>> KroghInterpolator(xi_k, yi_k)
286 To produce a vector-valued polynomial, supply a higher-dimensional
287 array for yi:
289 >>> KroghInterpolator([0,1],[[2,3],[4,5]])
291 This constructs a linear polynomial giving (2,3) at 0 and (4,5) at 1.
293 """
295 def __init__(self, xi, yi, axis=0):
296 _Interpolator1DWithDerivatives.__init__(self, xi, yi, axis)
298 self.xi = np.asarray(xi)
299 self.yi = self._reshape_yi(yi)
300 self.n, self.r = self.yi.shape
302 if (deg := self.xi.size) > 30:
303 warnings.warn(f"{deg} degrees provided, degrees higher than about"
304 " thirty cause problems with numerical instability "
305 "with 'KroghInterpolator'", stacklevel=2)
307 c = np.zeros((self.n+1, self.r), dtype=self.dtype)
308 c[0] = self.yi[0]
309 Vk = np.zeros((self.n, self.r), dtype=self.dtype)
310 for k in range(1, self.n):
311 s = 0
312 while s <= k and xi[k-s] == xi[k]:
313 s += 1
314 s -= 1
315 Vk[0] = self.yi[k]/float_factorial(s)
316 for i in range(k-s):
317 if xi[i] == xi[k]:
318 raise ValueError("Elements if `xi` can't be equal.")
319 if s == 0:
320 Vk[i+1] = (c[i]-Vk[i])/(xi[i]-xi[k])
321 else:
322 Vk[i+1] = (Vk[i+1]-Vk[i])/(xi[i]-xi[k])
323 c[k] = Vk[k-s]
324 self.c = c
326 def _evaluate(self, x):
327 pi = 1
328 p = np.zeros((len(x), self.r), dtype=self.dtype)
329 p += self.c[0,np.newaxis,:]
330 for k in range(1, self.n):
331 w = x - self.xi[k-1]
332 pi = w*pi
333 p += pi[:,np.newaxis] * self.c[k]
334 return p
336 def _evaluate_derivatives(self, x, der=None):
337 n = self.n
338 r = self.r
340 if der is None:
341 der = self.n
342 pi = np.zeros((n, len(x)))
343 w = np.zeros((n, len(x)))
344 pi[0] = 1
345 p = np.zeros((len(x), self.r), dtype=self.dtype)
346 p += self.c[0, np.newaxis, :]
348 for k in range(1, n):
349 w[k-1] = x - self.xi[k-1]
350 pi[k] = w[k-1] * pi[k-1]
351 p += pi[k, :, np.newaxis] * self.c[k]
353 cn = np.zeros((max(der, n+1), len(x), r), dtype=self.dtype)
354 cn[:n+1, :, :] += self.c[:n+1, np.newaxis, :]
355 cn[0] = p
356 for k in range(1, n):
357 for i in range(1, n-k+1):
358 pi[i] = w[k+i-1]*pi[i-1] + pi[i]
359 cn[k] = cn[k] + pi[i, :, np.newaxis]*cn[k+i]
360 cn[k] *= float_factorial(k)
362 cn[n, :, :] = 0
363 return cn[:der]
366def krogh_interpolate(xi, yi, x, der=0, axis=0):
367 """
368 Convenience function for polynomial interpolation.
370 See `KroghInterpolator` for more details.
372 Parameters
373 ----------
374 xi : array_like
375 Known x-coordinates.
376 yi : array_like
377 Known y-coordinates, of shape ``(xi.size, R)``. Interpreted as
378 vectors of length R, or scalars if R=1.
379 x : array_like
380 Point or points at which to evaluate the derivatives.
381 der : int or list, optional
382 How many derivatives to extract; None for all potentially
383 nonzero derivatives (that is a number equal to the number
384 of points), or a list of derivatives to extract. This number
385 includes the function value as 0th derivative.
386 axis : int, optional
387 Axis in the yi array corresponding to the x-coordinate values.
389 Returns
390 -------
391 d : ndarray
392 If the interpolator's values are R-D then the
393 returned array will be the number of derivatives by N by R.
394 If `x` is a scalar, the middle dimension will be dropped; if
395 the `yi` are scalars then the last dimension will be dropped.
397 See Also
398 --------
399 KroghInterpolator : Krogh interpolator
401 Notes
402 -----
403 Construction of the interpolating polynomial is a relatively expensive
404 process. If you want to evaluate it repeatedly consider using the class
405 KroghInterpolator (which is what this function uses).
407 Examples
408 --------
409 We can interpolate 2D observed data using krogh interpolation:
411 >>> import numpy as np
412 >>> import matplotlib.pyplot as plt
413 >>> from scipy.interpolate import krogh_interpolate
414 >>> x_observed = np.linspace(0.0, 10.0, 11)
415 >>> y_observed = np.sin(x_observed)
416 >>> x = np.linspace(min(x_observed), max(x_observed), num=100)
417 >>> y = krogh_interpolate(x_observed, y_observed, x)
418 >>> plt.plot(x_observed, y_observed, "o", label="observation")
419 >>> plt.plot(x, y, label="krogh interpolation")
420 >>> plt.legend()
421 >>> plt.show()
423 """
424 P = KroghInterpolator(xi, yi, axis=axis)
425 if der == 0:
426 return P(x)
427 elif _isscalar(der):
428 return P.derivative(x,der=der)
429 else:
430 return P.derivatives(x,der=np.amax(der)+1)[der]
433def approximate_taylor_polynomial(f,x,degree,scale,order=None):
434 """
435 Estimate the Taylor polynomial of f at x by polynomial fitting.
437 Parameters
438 ----------
439 f : callable
440 The function whose Taylor polynomial is sought. Should accept
441 a vector of `x` values.
442 x : scalar
443 The point at which the polynomial is to be evaluated.
444 degree : int
445 The degree of the Taylor polynomial
446 scale : scalar
447 The width of the interval to use to evaluate the Taylor polynomial.
448 Function values spread over a range this wide are used to fit the
449 polynomial. Must be chosen carefully.
450 order : int or None, optional
451 The order of the polynomial to be used in the fitting; `f` will be
452 evaluated ``order+1`` times. If None, use `degree`.
454 Returns
455 -------
456 p : poly1d instance
457 The Taylor polynomial (translated to the origin, so that
458 for example p(0)=f(x)).
460 Notes
461 -----
462 The appropriate choice of "scale" is a trade-off; too large and the
463 function differs from its Taylor polynomial too much to get a good
464 answer, too small and round-off errors overwhelm the higher-order terms.
465 The algorithm used becomes numerically unstable around order 30 even
466 under ideal circumstances.
468 Choosing order somewhat larger than degree may improve the higher-order
469 terms.
471 Examples
472 --------
473 We can calculate Taylor approximation polynomials of sin function with
474 various degrees:
476 >>> import numpy as np
477 >>> import matplotlib.pyplot as plt
478 >>> from scipy.interpolate import approximate_taylor_polynomial
479 >>> x = np.linspace(-10.0, 10.0, num=100)
480 >>> plt.plot(x, np.sin(x), label="sin curve")
481 >>> for degree in np.arange(1, 15, step=2):
482 ... sin_taylor = approximate_taylor_polynomial(np.sin, 0, degree, 1,
483 ... order=degree + 2)
484 ... plt.plot(x, sin_taylor(x), label=f"degree={degree}")
485 >>> plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left',
486 ... borderaxespad=0.0, shadow=True)
487 >>> plt.tight_layout()
488 >>> plt.axis([-10, 10, -10, 10])
489 >>> plt.show()
491 """
492 if order is None:
493 order = degree
495 n = order+1
496 # Choose n points that cluster near the endpoints of the interval in
497 # a way that avoids the Runge phenomenon. Ensure, by including the
498 # endpoint or not as appropriate, that one point always falls at x
499 # exactly.
500 xs = scale*np.cos(np.linspace(0,np.pi,n,endpoint=n % 1)) + x
502 P = KroghInterpolator(xs, f(xs))
503 d = P.derivatives(x,der=degree+1)
505 return np.poly1d((d/factorial(np.arange(degree+1)))[::-1])
508class BarycentricInterpolator(_Interpolator1D):
509 """The interpolating polynomial for a set of points
511 Constructs a polynomial that passes through a given set of points.
512 Allows evaluation of the polynomial, efficient changing of the y
513 values to be interpolated, and updating by adding more x values.
514 For reasons of numerical stability, this function does not compute
515 the coefficients of the polynomial.
517 The values yi need to be provided before the function is
518 evaluated, but none of the preprocessing depends on them, so rapid
519 updates are possible.
521 Parameters
522 ----------
523 xi : array_like
524 1-D array of x coordinates of the points the polynomial
525 should pass through
526 yi : array_like, optional
527 The y coordinates of the points the polynomial should pass through.
528 If None, the y values will be supplied later via the `set_y` method.
529 axis : int, optional
530 Axis in the yi array corresponding to the x-coordinate values.
532 Notes
533 -----
534 This class uses a "barycentric interpolation" method that treats
535 the problem as a special case of rational function interpolation.
536 This algorithm is quite stable, numerically, but even in a world of
537 exact computation, unless the x coordinates are chosen very
538 carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
539 polynomial interpolation itself is a very ill-conditioned process
540 due to the Runge phenomenon.
542 Based on Berrut and Trefethen 2004, "Barycentric Lagrange Interpolation".
544 """
546 def __init__(self, xi, yi=None, axis=0):
547 _Interpolator1D.__init__(self, xi, yi, axis)
549 self.xi = np.asfarray(xi)
550 self.set_yi(yi)
551 self.n = len(self.xi)
553 # See page 510 of Berrut and Trefethen 2004 for an explanation of the
554 # capacity scaling and the suggestion of using a random permutation of
555 # the input factors.
556 # At the moment, the permutation is not performed for xi that are
557 # appended later through the add_xi interface. It's not clear to me how
558 # to implement that and it seems that most situations that require
559 # these numerical stability improvements will be able to provide all
560 # the points to the constructor.
561 self._inv_capacity = 4.0 / (np.max(self.xi) - np.min(self.xi))
562 permute = np.random.permutation(self.n)
563 inv_permute = np.zeros(self.n, dtype=np.int32)
564 inv_permute[permute] = np.arange(self.n)
566 self.wi = np.zeros(self.n)
567 for i in range(self.n):
568 dist = self._inv_capacity * (self.xi[i] - self.xi[permute])
569 dist[inv_permute[i]] = 1.0
570 self.wi[i] = 1.0 / np.prod(dist)
572 def set_yi(self, yi, axis=None):
573 """
574 Update the y values to be interpolated
576 The barycentric interpolation algorithm requires the calculation
577 of weights, but these depend only on the xi. The yi can be changed
578 at any time.
580 Parameters
581 ----------
582 yi : array_like
583 The y coordinates of the points the polynomial should pass through.
584 If None, the y values will be supplied later.
585 axis : int, optional
586 Axis in the yi array corresponding to the x-coordinate values.
588 """
589 if yi is None:
590 self.yi = None
591 return
592 self._set_yi(yi, xi=self.xi, axis=axis)
593 self.yi = self._reshape_yi(yi)
594 self.n, self.r = self.yi.shape
596 def add_xi(self, xi, yi=None):
597 """
598 Add more x values to the set to be interpolated
600 The barycentric interpolation algorithm allows easy updating by
601 adding more points for the polynomial to pass through.
603 Parameters
604 ----------
605 xi : array_like
606 The x coordinates of the points that the polynomial should pass
607 through.
608 yi : array_like, optional
609 The y coordinates of the points the polynomial should pass through.
610 Should have shape ``(xi.size, R)``; if R > 1 then the polynomial is
611 vector-valued.
612 If `yi` is not given, the y values will be supplied later. `yi`
613 should be given if and only if the interpolator has y values
614 specified.
616 """
617 if yi is not None:
618 if self.yi is None:
619 raise ValueError("No previous yi value to update!")
620 yi = self._reshape_yi(yi, check=True)
621 self.yi = np.vstack((self.yi,yi))
622 else:
623 if self.yi is not None:
624 raise ValueError("No update to yi provided!")
625 old_n = self.n
626 self.xi = np.concatenate((self.xi,xi))
627 self.n = len(self.xi)
628 self.wi **= -1
629 old_wi = self.wi
630 self.wi = np.zeros(self.n)
631 self.wi[:old_n] = old_wi
632 for j in range(old_n, self.n):
633 self.wi[:j] *= self._inv_capacity * (self.xi[j]-self.xi[:j])
634 self.wi[j] = np.multiply.reduce(
635 self._inv_capacity * (self.xi[:j]-self.xi[j])
636 )
637 self.wi **= -1
639 def __call__(self, x):
640 """Evaluate the interpolating polynomial at the points x
642 Parameters
643 ----------
644 x : array_like
645 Points to evaluate the interpolant at.
647 Returns
648 -------
649 y : array_like
650 Interpolated values. Shape is determined by replacing
651 the interpolation axis in the original array with the shape of x.
653 Notes
654 -----
655 Currently the code computes an outer product between x and the
656 weights, that is, it constructs an intermediate array of size
657 N by len(x), where N is the degree of the polynomial.
658 """
659 return _Interpolator1D.__call__(self, x)
661 def _evaluate(self, x):
662 if x.size == 0:
663 p = np.zeros((0, self.r), dtype=self.dtype)
664 else:
665 c = x[..., np.newaxis] - self.xi
666 z = c == 0
667 c[z] = 1
668 c = self.wi/c
669 with np.errstate(divide='ignore'):
670 p = np.dot(c, self.yi) / np.sum(c, axis=-1)[..., np.newaxis]
671 # Now fix where x==some xi
672 r = np.nonzero(z)
673 if len(r) == 1: # evaluation at a scalar
674 if len(r[0]) > 0: # equals one of the points
675 p = self.yi[r[0][0]]
676 else:
677 p[r[:-1]] = self.yi[r[-1]]
678 return p
681def barycentric_interpolate(xi, yi, x, axis=0):
682 """
683 Convenience function for polynomial interpolation.
685 Constructs a polynomial that passes through a given set of points,
686 then evaluates the polynomial. For reasons of numerical stability,
687 this function does not compute the coefficients of the polynomial.
689 This function uses a "barycentric interpolation" method that treats
690 the problem as a special case of rational function interpolation.
691 This algorithm is quite stable, numerically, but even in a world of
692 exact computation, unless the `x` coordinates are chosen very
693 carefully - Chebyshev zeros (e.g., cos(i*pi/n)) are a good choice -
694 polynomial interpolation itself is a very ill-conditioned process
695 due to the Runge phenomenon.
697 Parameters
698 ----------
699 xi : array_like
700 1-D array of x coordinates of the points the polynomial should
701 pass through
702 yi : array_like
703 The y coordinates of the points the polynomial should pass through.
704 x : scalar or array_like
705 Points to evaluate the interpolator at.
706 axis : int, optional
707 Axis in the yi array corresponding to the x-coordinate values.
709 Returns
710 -------
711 y : scalar or array_like
712 Interpolated values. Shape is determined by replacing
713 the interpolation axis in the original array with the shape of x.
715 See Also
716 --------
717 BarycentricInterpolator : Bary centric interpolator
719 Notes
720 -----
721 Construction of the interpolation weights is a relatively slow process.
722 If you want to call this many times with the same xi (but possibly
723 varying yi or x) you should use the class `BarycentricInterpolator`.
724 This is what this function uses internally.
726 Examples
727 --------
728 We can interpolate 2D observed data using barycentric interpolation:
730 >>> import numpy as np
731 >>> import matplotlib.pyplot as plt
732 >>> from scipy.interpolate import barycentric_interpolate
733 >>> x_observed = np.linspace(0.0, 10.0, 11)
734 >>> y_observed = np.sin(x_observed)
735 >>> x = np.linspace(min(x_observed), max(x_observed), num=100)
736 >>> y = barycentric_interpolate(x_observed, y_observed, x)
737 >>> plt.plot(x_observed, y_observed, "o", label="observation")
738 >>> plt.plot(x, y, label="barycentric interpolation")
739 >>> plt.legend()
740 >>> plt.show()
742 """
743 return BarycentricInterpolator(xi, yi, axis=axis)(x)