U
    md3                     @   s  d Z ddlmZmZ ddlmZ ddlmZ ddlZ	ddl
mZ ddlmZmZ ddlmZ dd	lmZmZ edddddd
deeee	jejf  ee ee ee ee eee	jef dddZedde	je	je	je	je	jee	jedddZedde	je	je	je	je	jedddZeddde	je	je	je	jedddZeddde	je	je	je	je	jdddZeddde	je	je	je	je	je	je e	jddd Z!e"ej#e	jd!d"d#Z$dS )$z)Moran's I global spatial autocorrelation.    )UnionOptional)singledispatch)AnnDataN)sparse)njitprange)_get_obs_rep)_resolve_vals_check_valsF)vals	use_graphlayerobsmobspuse_raw)adatar   r   r   r   r   r   returnc                C   sx   |dkrLt | dr(d| jkr(| jd }qRd| jkrB| jd d }qRtdnt |dkrnt| ||||dj}t||S )uc  
    Calculate Moran’s I Global Autocorrelation Statistic.

    Moran’s I is a global autocorrelation statistic for some measure on a graph. It is commonly used in
    spatial data analysis to assess autocorrelation on a 2D grid. It is closely related to Geary's C,
    but not identical. More info can be found `here <https://en.wikipedia.org/wiki/Moran%27s_I>`_.

    .. math::

        I =
            \frac{
                N \sum_{i, j} w_{i, j} z_{i} z_{j}
            }{
                S_{0} \sum_{i} z_{i}^{2}
            }

    Params
    ------
    adata
    vals
        Values to calculate Moran's I for. If this is two dimensional, should
        be of shape `(n_features, n_cells)`. Otherwise should be of shape
        `(n_cells,)`. This matrix can be selected from elements of the anndata
        object by using key word arguments: `layer`, `obsm`, `obsp`, or
        `use_raw`.
    use_graph
        Key to use for graph in anndata object. If not provided, default
        neighbors connectivities will be used instead.
    layer
        Key for `adata.layers` to choose `vals`.
    obsm
        Key for `adata.obsm` to choose `vals`.
    obsp
        Key for `adata.obsp` to choose `vals`.
    use_raw
        Whether to use `adata.raw.X` for `vals`.


    This function can also be called on the graph and values directly. In this case
    the signature looks like:

    Params
    ------
    g
        The graph
    vals
        The values


    See the examples for more info.

    Returns
    -------
    If vals is two dimensional, returns a 1 dimensional ndarray array. Returns
    a scalar if `vals` is 1d.


    Examples
    --------

    Calculate Morans I for each components of a dimensionality reduction:

    .. code:: python

        import scanpy as sc, numpy as np

        pbmc = sc.datasets.pbmc68k_processed()
        pc_c = sc.metrics.morans_i(pbmc, obsm="X_pca")


    It's equivalent to call the function directly on the underlying arrays:

    .. code:: python

        alt = sc.metrics.morans_i(pbmc.obsp["connectivities"], pbmc.obsm["X_pca"].T)
        np.testing.assert_array_equal(pc_c, alt)
    Nr   ZconnectivitiesZ	neighborszMust run neighbors first.)r   r   r   r   )hasattrr   Zuns
ValueErrorNotImplementedErrorr	   Tmorans_i)r   r   r   r   r   r   r   g r   Q/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/scanpy/metrics/_morans_i.pyr      s    X

r   T)cache)g_data	g_indicesg_indptrx_data	x_indicesNWr   c                 C   s(   t j||jd}|||< t| ||||S )Ndtype)npzerosr%   _morans_i_vec_W)r   r   r   r    r!   r"   r#   xr   r   r   _morans_i_vec_W_sparse{   s    
r*   )r   r   r   r)   r#   r   c                 C   s   ||   }||  }t|}d}t|D ]F}	t||	 ||	d  }
||
 }| |
 }||||   ||	  7 }q,t|| | | S )Ng           )Zmeansumlenr   slice)r   r   r   r)   r#   zZz2ssr"   ZinumisZ	i_indicesZi_datar   r   r   r(      s    r(   )r   parallel)r   r   r   r)   r   c                 C   s   |   }t| ||||S )N)r,   r(   )r   r   r   r)   r#   r   r   r   _morans_i_vec   s    r3   )r   r   r   Xr   c           
      C   sl   |j \}}|t|d kst|  }tj|tjd}t|D ](}||d d f }	t| |||	|||< q>|S )Nr+   r$   )	shaper-   AssertionErrorr,   r&   r'   float_r   r(   )
r   r   r   r4   Mr"   r#   outkr)   r   r   r   _morans_i_mtx   s    
r;   )r   r   r   X_data	X_indicesX_indptrX_shaper   c              	   C   sz   |\}}|   }	tj|tjd}
t||dd }t||dd }t|D ]$}t| |||| || ||	|
|< qP|
S )Nr$   r+   )r,   r&   r'   r7   splitr   r*   )r   r   r   r<   r=   r>   r?   r8   r"   r#   r9   Zx_data_listZx_indices_listr:   r   r   r   _morans_i_mtx_csr   s     
	rB   )r   c                 C   sV  | j d | j d kstdt|}| jjtjdd}t|tj	r| j d |j d ksZtt
|\}}}t|| j| j|jjtjdd|j|j|j }|||< |S t|tjr|jdkr| j d |j d kstt|| j| j|S t|tjrL|jdkrL| j d |j d kstt
|\}}}t|| j| j|jtjdd}|||< |S t d S )Nr   r+   z'`g` should be a square adjacency matrixF)copy   )r5   r6   r
   dataZastyper&   r7   
isinstancer   
csr_matrixr   rB   indicesZindptrndarrayndimr3   r;   r   )r   r   r   new_valsZidxerZfull_resultresultr   r   r   	_morans_i   s@    	rM   )%__doc__typingr   r   	functoolsr   Zanndatar   numpyr&   Zscipyr   Znumbar   r   Z
scanpy.getr	   Zscanpy.metrics._gearys_cr
   r   rI   Zspmatrixstrboolfloatr   intr7   r*   r(   r3   r;   tuplerB   registerrG   rM   r   r   r   r   <module>   s   l


 
