o
    Ö­jb  ã                   @   sÀ   d dl Z d dlZd dlmZmZ d dlmZ d dlmZm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZ d dlZddlmZ ddlmZmZ dgZe  ¡ Z G d	d„ dƒZ!d
d„ Z"dS )é    N)ÚlinalgÚspecial)Úcheck_random_state)ÚasarrayÚ
atleast_2dÚreshapeÚzerosÚnewaxisÚexpÚpiÚsqrtÚravelÚpowerÚ
atleast_1dÚsqueezeÚsumÚ	transposeÚonesÚcové   )Ú_mvn)Úgaussian_kernel_estimateÚgaussian_kernel_estimate_logÚgaussian_kdec                   @   sº   e Zd ZdZd&dd„Zdd„ ZeZdd„ Zd	d
„ Zd'dd„Z	dd„ Z
d&dd„Zdd„ Zdd„ ZeZde_d'dd„Zdd„ Zedd„ ƒZdd„ Zdd„ Zd d!„ Zed"d#„ ƒZed$d%„ ƒZdS )(r   a&  Representation of a kernel-density estimate using Gaussian kernels.

    Kernel density estimation is a way to estimate the probability density
    function (PDF) of a random variable in a non-parametric way.
    `gaussian_kde` works for both uni-variate and multi-variate data.   It
    includes automatic bandwidth determination.  The estimation works best for
    a unimodal distribution; bimodal or multi-modal distributions tend to be
    oversmoothed.

    Parameters
    ----------
    dataset : array_like
        Datapoints to estimate from. In case of univariate data this is a 1-D
        array, otherwise a 2-D array with shape (# of dims, # of data).
    bw_method : str, scalar or callable, optional
        The method used to calculate the estimator bandwidth.  This can be
        'scott', 'silverman', a scalar constant or a callable.  If a scalar,
        this will be used directly as `kde.factor`.  If a callable, it should
        take a `gaussian_kde` instance as only parameter and return a scalar.
        If None (default), 'scott' is used.  See Notes for more details.
    weights : array_like, optional
        weights of datapoints. This must be the same shape as dataset.
        If None (default), the samples are assumed to be equally weighted

    Attributes
    ----------
    dataset : ndarray
        The dataset with which `gaussian_kde` was initialized.
    d : int
        Number of dimensions.
    n : int
        Number of datapoints.
    neff : int
        Effective number of datapoints.

        .. versionadded:: 1.2.0
    factor : float
        The bandwidth factor, obtained from `kde.covariance_factor`. The square
        of `kde.factor` multiplies the covariance matrix of the data in the kde
        estimation.
    covariance : ndarray
        The covariance matrix of `dataset`, scaled by the calculated bandwidth
        (`kde.factor`).
    inv_cov : ndarray
        The inverse of `covariance`.

    Methods
    -------
    evaluate
    __call__
    integrate_gaussian
    integrate_box_1d
    integrate_box
    integrate_kde
    pdf
    logpdf
    resample
    set_bandwidth
    covariance_factor

    Notes
    -----
    Bandwidth selection strongly influences the estimate obtained from the KDE
    (much more so than the actual shape of the kernel).  Bandwidth selection
    can be done by a "rule of thumb", by cross-validation, by "plug-in
    methods" or by other means; see [3]_, [4]_ for reviews.  `gaussian_kde`
    uses a rule of thumb, the default is Scott's Rule.

    Scott's Rule [1]_, implemented as `scotts_factor`, is::

        n**(-1./(d+4)),

    with ``n`` the number of data points and ``d`` the number of dimensions.
    In the case of unequally weighted points, `scotts_factor` becomes::

        neff**(-1./(d+4)),

    with ``neff`` the effective number of datapoints.
    Silverman's Rule [2]_, implemented as `silverman_factor`, is::

        (n * (d + 2) / 4.)**(-1. / (d + 4)).

    or in the case of unequally weighted points::

        (neff * (d + 2) / 4.)**(-1. / (d + 4)).

    Good general descriptions of kernel density estimation can be found in [1]_
    and [2]_, the mathematics for this multi-dimensional implementation can be
    found in [1]_.

    With a set of weighted samples, the effective number of datapoints ``neff``
    is defined by::

        neff = sum(weights)^2 / sum(weights^2)

    as detailed in [5]_.

    `gaussian_kde` does not currently support data that lies in a
    lower-dimensional subspace of the space in which it is expressed. For such
    data, consider performing principal component analysis / dimensionality
    reduction and using `gaussian_kde` with the transformed data.

    References
    ----------
    .. [1] D.W. Scott, "Multivariate Density Estimation: Theory, Practice, and
           Visualization", John Wiley & Sons, New York, Chicester, 1992.
    .. [2] B.W. Silverman, "Density Estimation for Statistics and Data
           Analysis", Vol. 26, Monographs on Statistics and Applied Probability,
           Chapman and Hall, London, 1986.
    .. [3] B.A. Turlach, "Bandwidth Selection in Kernel Density Estimation: A
           Review", CORE and Institut de Statistique, Vol. 19, pp. 1-33, 1993.
    .. [4] D.M. Bashtannyk and R.J. Hyndman, "Bandwidth selection for kernel
           conditional density estimation", Computational Statistics & Data
           Analysis, Vol. 36, pp. 279-298, 2001.
    .. [5] Gray P. G., 1969, Journal of the Royal Statistical Society.
           Series A (General), 132, 272

    Examples
    --------
    Generate some random two-dimensional data:

    >>> import numpy as np
    >>> from scipy import stats
    >>> def measure(n):
    ...     "Measurement model, return two coupled measurements."
    ...     m1 = np.random.normal(size=n)
    ...     m2 = np.random.normal(scale=0.5, size=n)
    ...     return m1+m2, m1-m2

    >>> m1, m2 = measure(2000)
    >>> xmin = m1.min()
    >>> xmax = m1.max()
    >>> ymin = m2.min()
    >>> ymax = m2.max()

    Perform a kernel density estimate on the data:

    >>> X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
    >>> positions = np.vstack([X.ravel(), Y.ravel()])
    >>> values = np.vstack([m1, m2])
    >>> kernel = stats.gaussian_kde(values)
    >>> Z = np.reshape(kernel(positions).T, X.shape)

    Plot the results:

    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots()
    >>> ax.imshow(np.rot90(Z), cmap=plt.cm.gist_earth_r,
    ...           extent=[xmin, xmax, ymin, ymax])
    >>> ax.plot(m1, m2, 'k.', markersize=2)
    >>> ax.set_xlim([xmin, xmax])
    >>> ax.set_ylim([ymin, ymax])
    >>> plt.show()

    Nc              
   C   sô   t t|ƒƒ| _| jjdkstdƒ‚| jj\| _| _|d urOt|ƒ 	t
¡| _|  jt| jƒ  _| jjdkr9tdƒ‚t| jƒ| jkrEtdƒ‚dt| jd ƒ | _| j| jkr[d}t|ƒ‚z	| j|d� W d S  tjyy } zd}t |¡|‚d }~ww )	Nr   z.`dataset` input should have multiple elements.z*`weights` input should be one-dimensional.z%`weights` input should be of length né   a1  Number of dimensions is greater than number of samples. This results in a singular data covariance matrix, which cannot be treated using the algorithms implemented in `gaussian_kde`. Note that `gaussian_kde` interprets each *column* of `dataset` to be a point; consider transposing the input to `dataset`.©Ú	bw_methodab  The data appears to lie in a lower-dimensional subspace of the space in which it is expressed. This has resulted in a singular data covariance matrix, which cannot be treated using the algorithms implemented in `gaussian_kde`. Consider performing principal component analysis / dimensionality reduction and using `gaussian_kde` with the transformed data.)r   r   ÚdatasetÚsizeÚ
ValueErrorÚshapeÚdÚnr   ÚastypeÚfloatÚ_weightsr   ÚweightsÚndimÚlenÚ_neffÚset_bandwidthr   ÚLinAlgError)Úselfr   r   r&   ÚmsgÚe© r/   úM/var/www/html/CropPilot/venv/lib/python3.10/site-packages/scipy/stats/_kde.pyÚ__init__Ç   s,   €øzgaussian_kde.__init__c                 C   s¬   t t|ƒƒ}|j\}}|| jkr1|dkr$|| jkr$t|| jdfƒ}d}nd|› d| j› �}t|ƒ‚t| j|ƒ\}}t| | j	j
| jdd…df |j
| j|ƒ}|dd…df S )a  Evaluate the estimated pdf on a set of points.

        Parameters
        ----------
        points : (# of dimensions, # of points)-array
            Alternatively, a (# of dimensions,) vector can be passed in and
            treated as a single point.

        Returns
        -------
        values : (# of points,)-array
            The values at each point.

        Raises
        ------
        ValueError : if the dimensionality of the input points is different than
                     the dimensionality of the KDE.

        r   úpoints have dimension ú, dataset has dimension Nr   )r   r   r    r!   r   r   Ú_get_output_dtypeÚ
covariancer   r   ÚTr&   Úcho_cov)r,   Úpointsr!   Úmr-   Úoutput_dtypeÚspecÚresultr/   r/   r0   Úevaluateí   s    

ÿ
þzgaussian_kde.evaluatec                 C   sò   t t|ƒƒ}t|ƒ}|j| jfkrtd| j› �ƒ‚|j| j| jfkr*td| j› �ƒ‚|dd…tf }| j| }t 	|¡}| j
| }t ||¡}t t |d ¡¡}tdt |jd d ƒ| }t|| dd�d }	tt|	 ƒ| j dd�| }
|
S )aW  
        Multiply estimated density by a multivariate Gaussian and integrate
        over the whole space.

        Parameters
        ----------
        mean : aray_like
            A 1-D array, specifying the mean of the Gaussian.
        cov : array_like
            A 2-D array, specifying the covariance matrix of the Gaussian.

        Returns
        -------
        result : scalar
            The value of the integral.

        Raises
        ------
        ValueError
            If the mean or covariance of the input Gaussian differs from
            the KDE's dimensionality.

        zmean does not have dimension z#covariance does not have dimension Nr   r   ç       @©Úaxis)r   r   r   r    r!   r   r	   r5   r   Ú
cho_factorr   Ú	cho_solveÚnpÚprodÚdiagonalr   r   r   r
   r&   )r,   Úmeanr   Úsum_covÚsum_cov_cholÚdiffÚtdiffÚsqrt_detÚ
norm_constÚenergiesr<   r/   r/   r0   Úintegrate_gaussian  s    


zgaussian_kde.integrate_gaussianc                 C   sl   | j dkr	tdƒ‚tt| jƒƒd }t|| j | ƒ}t|| j | ƒ}t | jt	 
|¡t	 
|¡  ¡}|S )a´  
        Computes the integral of a 1D pdf between two bounds.

        Parameters
        ----------
        low : scalar
            Lower bound of integration.
        high : scalar
            Upper bound of integration.

        Returns
        -------
        value : scalar
            The result of the integral.

        Raises
        ------
        ValueError
            If the KDE is over more than one dimension.

        r   z'integrate_box_1d() only handles 1D pdfsr   )r!   r   r   r   r5   r   rC   r   r&   r   Úndtr)r,   ÚlowÚhighÚstdevÚnormalized_lowÚnormalized_highÚvaluer/   r/   r0   Úintegrate_box_1dL  s   
ÿÿzgaussian_kde.integrate_box_1dc                 C   s„   |dur	d|i}ni }t � tj||| j| j| jfi |¤Ž\}}W d  ƒ n1 s*w   Y  |r@d| jd › �}tj|dd� |S )aõ  Computes the integral of a pdf over a rectangular interval.

        Parameters
        ----------
        low_bounds : array_like
            A 1-D array containing the lower bounds of integration.
        high_bounds : array_like
            A 1-D array containing the upper bounds of integration.
        maxpts : int, optional
            The maximum number of points to use for integration.

        Returns
        -------
        value : scalar
            The result of the integral.

        NÚmaxptsz4An integral in _mvn.mvnun requires more points than iè  r   )Ú
stacklevel)	ÚMVN_LOCKr   Úmvnun_weightedr   r&   r5   r!   ÚwarningsÚwarn)r,   Ú
low_boundsÚhigh_boundsrW   Ú
extra_kwdsrU   Úinformr-   r/   r/   r0   Úintegrate_boxo  s   
þþÿzgaussian_kde.integrate_boxc                 C   sü   |j | j kr
tdƒ‚|j| jk r|}| }n| }|}|j|j }t |¡}d}t|jƒD ]4}|jdd…|tf }|j| }	t 	||	¡}
t
|	|
 dd�d }|t
t| ƒ|j dd�|j|  7 }q+t t |d ¡¡}tdt |jd d ƒ| }|| }|S )aŸ  
        Computes the integral of the product of this  kernel density estimate
        with another.

        Parameters
        ----------
        other : gaussian_kde instance
            The other kde.

        Returns
        -------
        value : scalar
            The result of the integral.

        Raises
        ------
        ValueError
            If the KDEs have different dimensionality.

        z$KDEs are not the same dimensionalityg        Nr   r?   r>   r   )r!   r   r"   r5   r   rA   Úranger   r	   rB   r   r
   r&   rC   rD   rE   r   r   r    )r,   ÚotherÚsmallÚlargerG   rH   r<   ÚirF   rI   rJ   rM   rK   rL   r/   r/   r0   Úintegrate_kde�  s(   

(zgaussian_kde.integrate_kdec                 C   sh   |du r	t | jƒ}t|ƒ}t|jt| jftƒ| j|d�ƒ}|j	| j
|| jd�}| jdd…|f }|| S )aA  Randomly sample a dataset from the estimated pdf.

        Parameters
        ----------
        size : int, optional
            The number of samples to draw.  If not provided, then the size is
            the same as the effective number of samples in the underlying
            dataset.
        seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
            If `seed` is None (or `np.random`), the `numpy.random.RandomState`
            singleton is used.
            If `seed` is an int, a new ``RandomState`` instance is used,
            seeded with `seed`.
            If `seed` is already a ``Generator`` or ``RandomState`` instance then
            that instance is used.

        Returns
        -------
        resample : (self.d, `size`) ndarray
            The sampled dataset.

        N)r   )r   Úp)ÚintÚneffr   r   Úmultivariate_normalr   r!   r$   r5   Úchoicer"   r&   r   )r,   r   ÚseedÚrandom_stateÚnormÚindicesÚmeansr/   r/   r0   ÚresampleÂ  s   
ÿzgaussian_kde.resamplec                 C   s   t | jd| jd  ƒS )zoCompute Scott's factor.

        Returns
        -------
        s : float
            Scott's factor.
        ç      ð¿é   ©r   rj   r!   ©r,   r/   r/   r0   Úscotts_factorå  s   zgaussian_kde.scotts_factorc                 C   s$   t | j| jd  d d| jd  ƒS )z{Compute the Silverman factor.

        Returns
        -------
        s : float
            The silverman factor.
        r>   g      @rs   rt   ru   rv   r/   r/   r0   Úsilverman_factorï  s   $zgaussian_kde.silverman_factora0  Computes the coefficient (`kde.factor`) that
        multiplies the data covariance matrix to obtain the kernel covariance
        matrix. The default is `scotts_factor`.  A subclass can overwrite this
        method to provide a different method, or set it through a call to
        `kde.set_bandwidth`.c                    sŽ   ˆ du rn<ˆ dkrˆj ˆ_n3ˆ dkrˆjˆ_n*t ˆ ¡r,tˆ tƒs,dˆ_‡ fdd„ˆ_ntˆ ƒr;ˆ ˆ_‡fdd„ˆ_nd}t	|ƒ‚ˆ 
¡  dS )	aX  Compute the estimator bandwidth with given method.

        The new bandwidth calculated after a call to `set_bandwidth` is used
        for subsequent evaluations of the estimated density.

        Parameters
        ----------
        bw_method : str, scalar or callable, optional
            The method used to calculate the estimator bandwidth.  This can be
            'scott', 'silverman', a scalar constant or a callable.  If a
            scalar, this will be used directly as `kde.factor`.  If a callable,
            it should take a `gaussian_kde` instance as only parameter and
            return a scalar.  If None (default), nothing happens; the current
            `kde.covariance_factor` method is kept.

        Notes
        -----
        .. versionadded:: 0.11

        Examples
        --------
        >>> import numpy as np
        >>> import scipy.stats as stats
        >>> x1 = np.array([-7, -5, 1, 4, 5.])
        >>> kde = stats.gaussian_kde(x1)
        >>> xs = np.linspace(-10, 10, num=50)
        >>> y1 = kde(xs)
        >>> kde.set_bandwidth(bw_method='silverman')
        >>> y2 = kde(xs)
        >>> kde.set_bandwidth(bw_method=kde.factor / 3.)
        >>> y3 = kde(xs)

        >>> import matplotlib.pyplot as plt
        >>> fig, ax = plt.subplots()
        >>> ax.plot(x1, np.full(x1.shape, 1 / (4. * x1.size)), 'bo',
        ...         label='Data points (rescaled)')
        >>> ax.plot(xs, y1, label='Scott (default)')
        >>> ax.plot(xs, y2, label='Silverman')
        >>> ax.plot(xs, y3, label='Const (1/3 * Silverman)')
        >>> ax.legend()
        >>> plt.show()

        NÚscottÚ	silvermanzuse constantc                      s   ˆ S ©Nr/   r/   r   r/   r0   Ú<lambda>5  s    z,gaussian_kde.set_bandwidth.<locals>.<lambda>c                      s
   ˆ   ˆ ¡S r{   )Ú
_bw_methodr/   rv   r/   r0   r|   8  s   
 zC`bw_method` should be 'scott', 'silverman', a scalar or a callable.)rw   Úcovariance_factorrx   rC   ÚisscalarÚ
isinstanceÚstrr}   Úcallabler   Ú_compute_covariance)r,   r   r-   r/   )r   r,   r0   r*     s   ,

zgaussian_kde.set_bandwidthc              
   C   s–   |   ¡ | _t| dƒs tt| jdd| jd�ƒ| _tj	| jdd�| _
| j| jd  | _| j
| j  tj¡| _dt t | jt dt ¡ ¡¡ ¡  | _dS )	zcComputes the covariance matrix for each Gaussian kernel using
        covariance_factor().
        Ú_data_cho_covr   F©ÚrowvarÚbiasÚaweightsT)Úlowerr   N)r~   ÚfactorÚhasattrr   r   r   r&   Ú_data_covariancer   Úcholeskyr„   r5   r#   rC   Úfloat64r7   ÚlogÚdiagr   r   r   Úlog_detrv   r/   r/   r0   rƒ   @  s    



þÿÿ
ÿz gaussian_kde._compute_covariancec                 C   s:   |   ¡ | _tt| jdd| jd�ƒ| _t | j¡| jd  S )Nr   Fr…   r   )	r~   rŠ   r   r   r   r&   rŒ   r   Úinvrv   r/   r/   r0   Úinv_covR  s
   


ÿzgaussian_kde.inv_covc                 C   s
   |   |¡S )z×
        Evaluate the estimated pdf on a provided set of points.

        Notes
        -----
        This is an alias for `gaussian_kde.evaluate`.  See the ``evaluate``
        docstring for more details.

        )r=   )r,   Úxr/   r/   r0   Úpdf^  s   

zgaussian_kde.pdfc           	      C   s¨   t |ƒ}|j\}}|| jkr/|dkr"|| jkr"t|| jdfƒ}d}nd|› d| j› �}t|ƒ‚t| j|ƒ\}}t| | jj	| j
dd…df |j	| j|ƒ}|dd…df S )zT
        Evaluate the log of the estimated pdf on a provided set of points.
        r   r2   r3   Nr   )r   r    r!   r   r   r4   r5   r   r   r6   r&   r7   )	r,   r”   r8   r!   r9   r-   r:   r;   r<   r/   r/   r0   Úlogpdfj  s    

ÿ
þzgaussian_kde.logpdfc           	      C   sÌ   t  |¡}t  |jt j¡sd}t|ƒ‚t| jƒ}| ¡ }|||dk   ||dk < tt  	|¡ƒt|ƒkr9d}t|ƒ‚|dk ||kB }t  
|¡rUd|| › d|› d�}t|ƒ‚| j| }| j}t||  ¡ |d�S )a)  Return a marginal KDE distribution

        Parameters
        ----------
        dimensions : int or 1-d array_like
            The dimensions of the multivariate distribution corresponding
            with the marginal variables, that is, the indices of the dimensions
            that are being retained. The other dimensions are marginalized out.

        Returns
        -------
        marginal_kde : gaussian_kde
            An object representing the marginal distribution.

        Notes
        -----
        .. versionadded:: 1.10.0

        zaElements of `dimensions` must be integers - the indices of the marginal variables being retained.r   z,All elements of `dimensions` must be unique.zDimensions z# are invalid for a distribution in z dimensions.)r   r&   )rC   r   Ú
issubdtypeÚdtypeÚintegerr   r(   r   ÚcopyÚuniqueÚanyr&   r   r~   )	r,   Ú
dimensionsÚdimsr-   r"   Úoriginal_dimsÚ	i_invalidr   r&   r/   r/   r0   Úmarginal‚  s*   


ÿ

ÿzgaussian_kde.marginalc                 C   s4   z| j W S  ty   t| jƒ| j | _ | j  Y S w r{   )r%   ÚAttributeErrorr   r"   rv   r/   r/   r0   r&   ³  s   
þzgaussian_kde.weightsc                 C   s6   z| j W S  ty   dt| jd ƒ | _ | j  Y S w )Nr   r   )r)   r¢   r   r&   rv   r/   r/   r0   rj   »  s   
þzgaussian_kde.neff)NNr{   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r1   r=   Ú__call__rN   rV   ra   rg   rr   rw   rx   r~   r*   rƒ   Úpropertyr“   r•   r–   r¡   r&   rj   r/   r/   r/   r0   r   +   s4     
&(5
#!
2#

?
1
c                 C   sf   t  | |¡}t  |¡j}|dkrd}||fS |dkr d}||fS |dv r*d}||fS t|› d|› �ƒ‚)zÒ
    Calculates the output dtype and the "spec" (=C type name).

    This was necessary in order to deal with the fused types in the Cython
    routine `gaussian_kernel_estimate`. See gh-10824 for details.
    rt   r$   é   Údouble)é   é   zlong doublez has unexpected item size: )rC   Úcommon_typer˜   Úitemsizer   )r5   r8   r:   r®   r;   r/   r/   r0   r4   Ä  s   
÷ùüÿr4   )#Ú	threadingr[   Úscipyr   r   Úscipy._lib._utilr   Únumpyr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   rC   Ú r   Ú_statsr   r   Ú__all__ÚLockrY   r   r4   r/   r/   r/   r0   Ú<module>   s"   H     