o
    5ήc'_                     @   st   d dgZ ddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ d	d
 ZG dd  d ZddejfddZdS )RegularGridInterpolatorinterpn    N   )_ndim_coords_from_arrays)PchipInterpolatormake_interp_spline)RectBivariateSplinec           
      C   s   t dd | D }t dd t| |D }t dd |D }tdd tj| D  }tdd tj| D  }tt|}t||D ]\}}	|t |	 |t |< qI||fS )Nc                 s   s    | ]}t |V  qd S N)npargsort).0point r   =/tmp/pip-target-vg8gfxp4/lib/python/scipy/interpolate/_rgi.py	<genexpr>   s    z4_make_points_and_values_ascending.<locals>.<genexpr>c                 s   s"    | ]\}}t || V  qd S r
   r   asarray)r   r   
sort_indexr   r   r   r      s    
c                 s   s     | ]}g t t|V  qd S r
   )rangelen)r   xr   r   r   r      s    c                 S      g | ]}|  qS r   flattenr   ir   r   r   
<listcomp>       z5_make_points_and_values_ascending.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r   r      r   )tuplezipr   arraymeshgrid	transpose
zeros_liker   )
pointsvaluessorted_indexes
points_ascordered_indexesordered_indexes_arraysorted_indexes_array
values_ascosr   r   r   !_make_points_and_values_ascending   s&   r/   c                   @   s   e Zd ZdZddddZee Zddge Zdde	j
fd	d
ZdddZdd Zdd Zdd Zdd Zedd Zdd ZdS )r   a  
    Interpolation on a regular or rectilinear grid in arbitrary dimensions.

    The data must be defined on a rectilinear grid; that is, a rectangular
    grid with even or uneven spacing. Linear, nearest-neighbor, spline
    interpolations are supported. After setting up the interpolator object,
    the interpolation method may be chosen at each evaluation.

    Parameters
    ----------
    points : tuple of ndarray of float, with shapes (m1, ), ..., (mn, )
        The points defining the regular grid in n dimensions. The points in
        each dimension (i.e. every elements of the points tuple) must be
        strictly ascending or descending.

    values : array_like, shape (m1, ..., mn, ...)
        The data on the regular grid in n dimensions. Complex data can be
        acceptable.

    method : str, optional
        The method of interpolation to perform. Supported are "linear",
        "nearest", "slinear", "cubic", and "quintic". This parameter will
        become the default for the object's ``__call__`` method.
        Default is "linear".

    bounds_error : bool, optional
        If True, when interpolated values are requested outside of the
        domain of the input data, a ValueError is raised.
        If False, then `fill_value` is used.
        Default is True.

    fill_value : float or None, optional
        The value to use for points outside of the interpolation domain.
        If None, values outside the domain are extrapolated.
        Default is ``np.nan``.

    Methods
    -------
    __call__

    Attributes
    ----------
    grid : tuple of ndarrays
        The points defining the regular grid in n dimensions.
        This tuple defines the full grid via
        ``np.meshgrid(*grid, indexing='ij')``
    values : ndarray
        Data values at the grid.
    method : str
        Interpolation method.
    fill_value : float or ``None``
        Use this value for out-of-bounds arguments to `__call__`.
    bounds_error : bool
        If ``True``, out-of-bounds argument raise a ``ValueError``.

    Notes
    -----
    Contrary to `LinearNDInterpolator` and `NearestNDInterpolator`, this class
    avoids expensive triangulation of the input data by taking advantage of the
    regular grid structure.

    In other words, this class assumes that the data is defined on a
    *rectilinear* grid.

    .. versionadded:: 0.14

    The 'slinear'(k=1), 'cubic'(k=3), and 'quintic'(k=5) methods are
    tensor-product spline interpolators, where `k` is the spline degree,
    If any dimension has fewer points than `k` + 1, an error will be raised.

    .. versionadded:: 1.9

    Examples
    --------
    **Evaluate a function on the points of a 3-D grid**

    As a first example, we evaluate a simple example function on the points of
    a 3-D grid:

    >>> from scipy.interpolate import RegularGridInterpolator
    >>> def f(x, y, z):
    ...     return 2 * x**3 + 3 * y**2 - z
    >>> x = np.linspace(1, 4, 11)
    >>> y = np.linspace(4, 7, 22)
    >>> z = np.linspace(7, 9, 33)
    >>> xg, yg ,zg = np.meshgrid(x, y, z, indexing='ij', sparse=True)
    >>> data = f(xg, yg, zg)

    ``data`` is now a 3-D array with ``data[i, j, k] = f(x[i], y[j], z[k])``.
    Next, define an interpolating function from this data:

    >>> interp = RegularGridInterpolator((x, y, z), data)

    Evaluate the interpolating function at the two points
    ``(x,y,z) = (2.1, 6.2, 8.3)`` and ``(3.3, 5.2, 7.1)``:

    >>> pts = np.array([[2.1, 6.2, 8.3],
    ...                 [3.3, 5.2, 7.1]])
    >>> interp(pts)
    array([ 125.80469388,  146.30069388])

    which is indeed a close approximation to

    >>> f(2.1, 6.2, 8.3), f(3.3, 5.2, 7.1)
    (125.54200000000002, 145.894)

    **Interpolate and extrapolate a 2D dataset**

    As a second example, we interpolate and extrapolate a 2D data set:

    >>> x, y = np.array([-2, 0, 4]), np.array([-2, 0, 2, 5])
    >>> def ff(x, y):
    ...     return x**2 + y**2

    >>> xg, yg = np.meshgrid(x, y, indexing='ij')
    >>> data = ff(xg, yg)
    >>> interp = RegularGridInterpolator((x, y), data,
    ...                                  bounds_error=False, fill_value=None)

    >>> import matplotlib.pyplot as plt
    >>> fig = plt.figure()
    >>> ax = fig.add_subplot(projection='3d')
    >>> ax.scatter(xg.ravel(), yg.ravel(), data.ravel(),
    ...            s=60, c='k', label='data')

    Evaluate and plot the interpolator on a finer grid

    >>> xx = np.linspace(-4, 9, 31)
    >>> yy = np.linspace(-4, 9, 31)
    >>> X, Y = np.meshgrid(xx, yy, indexing='ij')

    >>> # interpolator
    >>> ax.plot_wireframe(X, Y, interp((X, Y)), rstride=3, cstride=3,
    ...                   alpha=0.4, color='m', label='linear interp')

    >>> # ground truth
    >>> ax.plot_wireframe(X, Y, ff(X, Y), rstride=3, cstride=3,
    ...                   alpha=0.4, label='ground truth')
    >>> plt.legend()
    >>> plt.show()

    Other examples are given
    :ref:`in the tutorial <tutorial-interpolate_regular_grid_interpolator>`.

    See Also
    --------
    NearestNDInterpolator : Nearest neighbor interpolation on *unstructured*
                            data in N dimensions

    LinearNDInterpolator : Piecewise linear interpolant on *unstructured* data
                           in N dimensions

    interpn : a convenience function which wraps `RegularGridInterpolator`

    scipy.ndimage.map_coordinates : interpolation on grids with equal spacing
                                    (suitable for e.g., N-D image resampling)

    References
    ----------
    .. [1] Python package *regulargrid* by Johannes Buchner, see
           https://pypi.python.org/pypi/regulargrid/
    .. [2] Wikipedia, "Trilinear interpolation",
           https://en.wikipedia.org/wiki/Trilinear_interpolation
    .. [3] Weiser, Alan, and Sergio E. Zarantonello. "A note on piecewise linear
           and multilinear table interpolation in many dimensions." MATH.
           COMPUT. 50.181 (1988): 189-196.
           https://www.ams.org/journals/mcom/1988-50-181/S0025-5718-1988-0917826-0/S0025-5718-1988-0917826-0.pdf
           :doi:`10.1090/S0025-5718-1988-0917826-0`

    r         )slinearcubicquinticlinearnearestTc           
      C   s  || j vrtd| || jv r| || || _|| _t|ds&t|}t	||j
kr8tdt	||j
f t|drOt|drOt|jtjsO|t}|| _|d urnt|j}t|drntj||jddsntdt|D ]J\}}t|}	t|	d	kst|	d	k rt||\}}ntd
| t|j
dkstd| |j| t	|kstdt	||j| |f qrtdd |D | _|| _d S )NMethod '%s' is not definedndim7There are %d point arrays, but values has %d dimensionsdtypeastype	same_kind)castingzDfill_value must be either 'None' or of a type compatible with values        CThe points in dimension %d must be strictly ascending or descendingr   0The points in dimension %d must be 1-dimensional1There are %d points and %d values in dimension %dc                 S      g | ]}t |qS r   r   r   pr   r   r   r         z4RegularGridInterpolator.__init__.<locals>.<listcomp>)_ALL_METHODS
ValueError_SPLINE_METHODS_validate_grid_dimensionsmethodbounds_errorhasattrr   r   r   r8   
issubdtyper:   inexactr;   float
fill_valuecan_cast	enumeratediffallr/   shaper   gridr&   )
selfr%   r&   rJ   rK   rP   fill_value_dtyper   rD   diff_pr   r   r   __init__   s^   









z RegularGridInterpolator.__init__Nc              	   C   s  | j |k}|du r| j n|}|| jvrtd| t| j}t||d}|jd t| jkr9td|jd |f |j}|d|d }tj	t
|dd}| jr{t|jD ]$\}}tt| j| d |kt|| j| d ksztd	| qV| |j\}	}
}|d
kr| |	|
|}n&|dkr| |	|
|}n|| jv r|r| | j| | | jj|| j| }| js| jdur| j||< t	|rtj||< ||dd | jj|d  S )aV  
        Interpolation at coordinates.

        Parameters
        ----------
        xi : ndarray of shape (..., ndim)
            The coordinates to evaluate the interpolator at.

        method : str
            The method of interpolation to perform. Supported are "linear" and
            "nearest".

        Examples
        --------
        Here we define a nearest-neighbor interpolator of a simple function

        >>> x, y = np.array([0, 1, 2]), np.array([1, 3, 7])
        >>> def f(x, y):
        ...     return x**2 + y**2
        >>> data = f(*np.meshgrid(x, y, indexing='ij', sparse=True))
        >>> from scipy.interpolate import RegularGridInterpolator
        >>> interp = RegularGridInterpolator((x, y), data, method='nearest')

        By construction, the interpolator uses the nearest-neighbor
        interpolation

        >>> interp([[1.5, 1.3], [0.3, 4.5]])
        array([2., 9.])

        We can however evaluate the linear interpolant by overriding the
        `method` parameter

        >>> interp([[1.5, 1.3], [0.3, 4.5]], method='linear')
        array([ 4.7, 24.3])
        Nr7   r8   cThe requested sample points xi have dimension %d, but this RegularGridInterpolator has dimension %dr   axisr   8One of the requested xi is out of bounds in dimension %dr5   r6   )rJ   rF   rG   r   rV   r   rU   reshaper   anyisnanrK   rR   Tlogical_andrT   _find_indices_evaluate_linear_evaluate_nearestrH   rI   _evaluate_spliner&   _SPLINE_DEGREE_MAPrP   nan)rW   xirJ   is_method_changedr8   xi_shapenansr   rD   indicesnorm_distancesout_of_boundsresultr   r   r   __call__  sX   
$





"z RegularGridInterpolator.__call__c                 C   s   t d fd| jjt|   }tjdd |D  }d}|D ]+}d}t|||D ]\}	}
}|t|	|
kd| |9 }q'|t	| j| ||  7 }q|S )Nr
   c                 S   s   g | ]}||d  gqS )r   r   r   r   r   r   r   `  s    z<RegularGridInterpolator._evaluate_linear.<locals>.<listcomp>r>   g      ?r   )
slicer&   r8   r   	itertoolsproductr    r   wherer   )rW   rp   rq   rr   vsliceedgesr&   edge_indicesweighteir   yir   r   r   rg   Z  s   z(RegularGridInterpolator._evaluate_linearc                 C   s"   dd t ||D }| jt| S )Nc                 S   s&   g | ]\}}t |d k||d qS )g      ?r   )r   rx   )r   r   r~   r   r   r   r   j  s    z=RegularGridInterpolator._evaluate_nearest.<locals>.<listcomp>)r    r&   r   )rW   rp   rq   rr   idx_resr   r   r   rh   i  s   z)RegularGridInterpolator._evaluate_nearestc                 C   s\   | j | }t|D ]"\}}tt|}||kr+td| d| d| d|d  d	q	d S )Nz
There are z points in dimension z, but method z requires at least  r   z points per dimension.)rj   rR   r   r   
atleast_1drG   )rW   r%   rJ   kr   r   r8   r   r   r   rI   n  s   

z1RegularGridInterpolator._validate_grid_dimensionsc              	   C   s   |j dkr|d|jf}|j\}}|d }| | j| ||d d |f |}tj|| jj	d}t
|D ]$}	||	 }
t
|d ddD ]}| | j| |
||	|f |}
qB|
||	< q4|S )Nr   r:   r\   )r8   ra   sizerU   _do_spline_fitrV   r   emptyr&   r:   r   )rW   r&   rl   spline_degreemnlast_dimfirst_valuesrs   jfolded_valuesr   r   r   r   ri   w  s(   



z(RegularGridInterpolator._evaluate_splinec                 C   s   t | ||dd}||}|S )Nr   )r   r_   r   )r   yptr   local_interpr&   r   r   r   r     s   z&RegularGridInterpolator._do_spline_fitc           
   	   C   s
  g }g }t j|jd td}t|| jD ]k\}}t ||d }d||dk < |jd |||jd k< || ||d  ||  }t j	ddd t 
|dk|||  | d}	W d    n1 sbw   Y  ||	 | js|||d k 7 }|||d k7 }q|||fS )Nr   r   r      ignore)divideinvalidr\   )r   zerosrU   boolr    rV   searchsortedr   appenderrstaterx   rK   )
rW   rl   rp   rq   rr   r   rV   r   denom	norm_distr   r   r   rf     s$   
 

z%RegularGridInterpolator._find_indicesr
   )__name__
__module____qualname____doc__rj   listkeysrH   rF   r   rk   rZ   rt   rg   rh   rI   ri   staticmethodr   rf   r   r   r   r   r   "   s"     .

2T	%
r5   Tc              	   C   s4  |dvr
t d| t|dst|}|j}|dkr#|dkr#t d|s1|du r1|dkr1t dt| |krAt d	t| |f t| |krO|dkrOt d
t| D ]J\}}t|}	t|	dksxt|	dk rrt	| |\} }nt d| t|jdkst d| |j
| t|kst dt||j
| |f qStdd | D }
t|t|
d}|j
d t|
krt d|j
d t|
f |rt|jD ]"\}}tt|
| d |kt||
| d kst d| q|dkrt| |d||d}||S |dkrt| |d||d}||S |dkr|j
}|d|j
d }tj|
d d |dddf k|dddf |
d d k|
d d |dddf k|dddf |
d d kfdd}t|dddf }t| d | d |dd }|||df ||df ||< ||t|< ||dd S dS )a[  
    Multidimensional interpolation on regular or rectilinear grids.

    Strictly speaking, not all regular grids are supported - this function
    works on *rectilinear* grids, that is, a rectangular grid with even or
    uneven spacing.

    Parameters
    ----------
    points : tuple of ndarray of float, with shapes (m1, ), ..., (mn, )
        The points defining the regular grid in n dimensions. The points in
        each dimension (i.e. every elements of the points tuple) must be
        strictly ascending or descending.

    values : array_like, shape (m1, ..., mn, ...)
        The data on the regular grid in n dimensions. Complex data can be
        acceptable.

    xi : ndarray of shape (..., ndim)
        The coordinates to sample the gridded data at

    method : str, optional
        The method of interpolation to perform. Supported are "linear" and
        "nearest", and "splinef2d". "splinef2d" is only supported for
        2-dimensional data.

    bounds_error : bool, optional
        If True, when interpolated values are requested outside of the
        domain of the input data, a ValueError is raised.
        If False, then `fill_value` is used.

    fill_value : number, optional
        If provided, the value to use for points outside of the
        interpolation domain. If None, values outside
        the domain are extrapolated.  Extrapolation is not supported by method
        "splinef2d".

    Returns
    -------
    values_x : ndarray, shape xi.shape[:-1] + values.shape[ndim:]
        Interpolated values at input coordinates.

    Notes
    -----

    .. versionadded:: 0.14

    Examples
    --------
    Evaluate a simple example function on the points of a regular 3-D grid:

    >>> from scipy.interpolate import interpn
    >>> def value_func_3d(x, y, z):
    ...     return 2 * x + 3 * y - z
    >>> x = np.linspace(0, 4, 5)
    >>> y = np.linspace(0, 5, 6)
    >>> z = np.linspace(0, 6, 7)
    >>> points = (x, y, z)
    >>> values = value_func_3d(*np.meshgrid(*points, indexing='ij'))

    Evaluate the interpolating function at a point

    >>> point = np.array([2.21, 3.12, 1.15])
    >>> print(interpn(points, values, point))
    [12.63]

    See Also
    --------
    NearestNDInterpolator : Nearest neighbor interpolation on unstructured
                            data in N dimensions

    LinearNDInterpolator : Piecewise linear interpolant on unstructured data
                           in N dimensions

    RegularGridInterpolator : interpolation on a regular or rectilinear grid
                              in arbitrary dimensions (`interpn` wraps this
                              class).

    RectBivariateSpline : Bivariate spline approximation over a rectangular mesh

    scipy.ndimage.map_coordinates : interpolation on grids with equal spacing
                                    (suitable for e.g., N-D image resampling)

    )r5   r6   	splinef2dz[interpn only understands the methods 'linear', 'nearest', and 'splinef2d'. You provided %s.r8   r   r   zBThe method splinef2d can only be used for 2-dimensional input dataNz4The method splinef2d does not support extrapolation.r9   zSThe method splinef2d can only be used for scalar data with one point per coordinater>   r?   r   r@   rA   c                 S   rB   r   r   rC   r   r   r   r   <  rE   zinterpn.<locals>.<listcomp>r[   r\   r]   r   r`   r5   )rJ   rK   rP   r6   r^   )rG   rL   r   r   r8   r   rR   rS   rT   r/   rU   r   r   rd   re   r   ra   
empty_liker	   evlogical_not)r%   r&   rl   rJ   rK   rP   r8   r   rD   rY   rV   interprn   	idx_validrs   r   r   r   r     s   W







84 )__all__rv   numpyr   interpndr   _cubicr   	_bsplinesr   	_fitpack2r	   r/   r   rk   r   r   r   r   r   <module>   s       