U
    vId                     @   sX  d dl mZ d dlmZ d dlmZ d dlZd dlZ	d dl
Z
d dlmZmZmZmZmZmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZ ddlmZ ddlm Z  dddgZ!dd Z"d"ddZ#dd Z$G dd dZ%G dd dZ&G dd dZ'G dd de%e&Z(ee)ef Z*eee*ee)e*f f Z+G dd de%e&Z,G d d! d!e&Z-dS )#    )Mapping)reduce)DatasetN)DictUnionOptionalSequenceCallableLiteral   )AnnData)_normalize_indices_normalize_indexIndex)_resolve_idx)concat_arraysinner_concat_aligned_mapping)SparseDataset)
AxisArraysobsobsmlayersc                 C   s   dd gt |  }t| |S )Nc                 S   s   | S N )xZ
fill_valueaxisr   r   h/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/anndata/experimental/multi_files/_anncollection.py<lambda>       z_merge.<locals>.<lambda>)lenr   )arrsZrxersr   r   r   _merge   s    r!   c                 C   sP   d }t |r|}nt|tr,| |kr,||  }|d k	rH|d k	rD||S |S |S d S r   )callable
isinstancedict)keyconvertarrZkey_convertr   r   r   _select_convert   s    r(   c                    sf   i }d fdd	}|   D ]:\}}t|dkr0qi ||< |D ]}||||| |< q<q|d|d< |S )Nc                    sx   g } D ](}t || }|d k	r&|| }|| qztdd |D j}W n( tk
rr   tdd |D j}Y nX |S )Nc                 S   s   g | ]}|d d qS N   r   .0r'   r   r   r   
<listcomp>3   s     z8_harmonize_types.<locals>.check_type.<locals>.<listcomp>c                 S   s    g | ]}|d dd df qS r)   r   r+   r   r   r   r-   5   s     )getattrappendr!   dtype
ValueError)attrr%   r    aattr_arrr0   adatasr   r   
check_type*   s    
z$_harmonize_types.<locals>.check_typer   X)N)itemsr   )
attrs_keysr6   Zattrs_keys_typesr7   r2   keysr%   r   r5   r   _harmonize_types'   s    r<   c                   @   s   e Zd Zdd ZdS )_ConcatViewMixinc                 C   s  g }d }t | dd }|d k	r.t||| jd }t|tr^|| jd \}}}t|||}nt|trtt	|gn|}|}	t
| jdkr|	g|||fS ttdg| j | j}
d}|
D ]&\}}t|	|k|	|k @ r|d7 }q| jo|dko|	jdkot|	d d |	dd  k}|r4tj|	dd\}	}|
D ]:\}}|	|k|	|k @ }|| rj|	| | nd  q8t | dd }|d k	rt||| jd j}t|trt	|g}||||fS )Noidxr*   r   TZreturn_inversevidx)r.   r   limitsr#   sliceindicesnparangeintarrayr   r6   listzipanyindices_strictsizeuniquer/   n_vars)selfr>   rA   adatas_oidxreverseZold_oidxstartstopstepZu_oidxZiter_limitsZn_adatas_usedlowerupperZneed_reversemaskZold_vidxr   r   r   r   E   sF    

$
z_ConcatViewMixin._resolve_idxN)__name__
__module____qualname__r   r   r   r   r   r=   D   s   r=   c                   @   s&   e Zd Zdeed eedddZdS )	_IterateViewMixinr   Fr   r*   )
batch_sizer   shuffle	drop_lastc           
      c   s   |dkrt d| j| }|r0tj| }ntt|}td||D ]X}||t|| | }|dkr|| dd|f }	n| | }	t	|	|k r|rqH|	|fV  qHdS )a  Iterate the lazy object over an axis.

        Parameters
        ----------
        batch_size
            How many samples to put into a batch when iterating.
        axis
            The axis to iterate over.
        shuffle
            Set to `True` to have the indices reshuffled before iterating.
        drop_last
            Set to `True` to drop a batch with the length lower than `batch_size`.
        r]   zAxis should be either 0 or 1.r   r*   N)
r1   shaperE   randomZpermutationtolistrI   rangeminr   )
rP   r^   r   r_   r`   nrD   iidxbatchr   r   r   iterate_axisu   s    
z_IterateViewMixin.iterate_axisN)r   FF)rY   rZ   r[   rG   r
   boolrj   r   r   r   r   r\   t   s      r\   c                   @   sF   e Zd ZdddZdddZdd Zdd	d
Zedd Zdd Z	dS )
MapObsViewNc
           
      C   s:   || _ || _|| _|| _|| _|| _|| _|| _|	| _d S r   )	r6   _keysrQ   adatas_vidxr2   r&   rR   dtypes	obs_names)
rP   r2   r6   r;   rQ   rn   r&   rR   ro   rp   r   r   r   __init__   s    zMapObsView.__init__Tc           
      C   sb  | j d k	r,|| j kr,td| d| j dg }t| jD ]\}}|d krLq:t| j| | j| }| jd k	rx| j| }nd }|d k	r||f}n|}t|t	j
r||j|  q:|d k	rt|d tstj| n|}|||  q:t|dkrt|}	| jd kr
|	n|	| j }	n(|d }	| jd k	r>|	j| j| dd}	| jd k	r^|r^t|| j|	}	|	S )NzNo z in z viewr*   r   Fcopy)rm   KeyErrorr2   	enumeraterQ   r.   r6   rn   r#   pd	DataFramer/   ZilocrC   rE   ix_r   r!   rR   ro   astyper&   r(   )
rP   r%   use_convertr    rg   r>   r'   rA   rh   Z_arrr   r   r   __getitem__   s6    

zMapObsView.__getitem__c                 C   s.   | j d k	r| j S tt| jd | j S d S Nr   )rm   rI   r.   r6   r2   r;   rP   r   r   r   r;      s    
zMapObsView.keysc                 C   s6   i }|d kr|   n|}|D ]}| ||||< q|S r   )r;   r{   )rP   r;   rz   dctr%   r   r   r   to_dict   s
    zMapObsView.to_dictc                 C   s&   | j dkrd S tj| jdd| jdS )Nr   Frz   index)r2   rv   rw   r   rp   r}   r   r   r   df   s    
zMapObsView.dfc                 C   s&   d| j  dt|  dd  }|S )NzView of z with keys: r*   r?   )r2   strr;   )rP   descrr   r   r   __repr__   s    "zMapObsView.__repr__)NNNNN)T)NT)
rY   rZ   r[   rq   r{   r;   r   propertyr   r   r   r   r   r   rl      s        

*

rl   c                   @   s   e Zd ZdZdd Zd-ddZdd Zed	d
 Zedd Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zejdd Zdd Zed d!d"Zed#d$ Zd%d& Zd.eed'd(d)Zed*d+ Zd,S )/AnnCollectionViewa      An object to access the observation attributes of `adatas` in AnnCollection.

    Created as a result of subsetting an :class:`~anndata.experimental.AnnCollection` object.
    An object of this class can have `.obs`, `.obsm`, `.layers`, `.X` depending on the
    results of joins in the reference AnnCollection object.

    Notes
    -----
    Nothing is copied until keys of the attributes or `.X` are accessed.
    c                 C   s   || _ | j j| _| j j| _| j j| _|\| _| _| _| _g | _t	| j jD ]B\}}|d krj| j
| j qJt|| j| j| j}| j
| qJ| j j| _| j j| _| j j| _d\| _| _| _d | _d | _d | _|| _d S )N)NNN)	referencerL   r6   rB   rQ   r>   rA   rR   rn   ru   r/   r   rO   _view_attrs_keys_attrs_dtypes_layers_view
_obsm_view	_obs_view_X_convert
_convert_Xr&   )rP   r   r&   resolved_idxrg   rA   Znew_vidxr   r   r   rq     s&    





zAnnCollectionView.__init__Fc                 C   s   t | d| dd k	rd S d }d }|| jkrn| j}| j| }t|dkrLd S | j}| j}| jd k	r| j| }nd }| jg}| jg}|r| j	nd }d }	| j
d k	rt|| j
}	|dkr| j}
nd }
t| d| dt||||||	|||
	 d S )N__viewr   r   )r.   r   rR   r   r6   rQ   r   r   r>   rn   r&   r(   rp   setattrrl   )rP   r2   set_vidxr;   Zattr_dtypesrR   r6   rQ   rn   Zattr_convertrp   r   r   r   _lazy_init_attr%  sL    




z!AnnCollectionView._lazy_init_attrc                 C   s  | j d k	r| j S g }t| jD ]B\}}|d kr2q| j| }|j}| j| }t|trd }|jdkrt	
|d d |dd  krt	j|dd\}}t|tr|||f }n|| d d |f }||d kr|n||  qt|tr2t|tst|dkr||||f  n||| d d |f  q||f}	t|tsPt	j|	 n|	}	|||	  qt|dkrt|}
| jd kr|
n|
| j }
n(|d }
| jd k	r|
j| jd dd	}
|
| _ |
S )
Nr*   r?   Tr@   i  r   r8   Frr   )r   ru   rQ   r6   r8   rn   r#   r   rM   rE   rK   rN   rC   r/   r   r   rx   r!   rR   r   ry   )rP   ZXsrg   r>   adatar8   rA   rR   r'   rh   r   r   r   r   	_gather_XR  s@    



(
zAnnCollectionView._gather_Xc                 C   s    |   }| jdk	r| |S |S )a!  Lazy subset of data matrix.

        The data matrix formed from the `.X` attributes of the underlying `adatas`,
        properly reindexed and lazily merged.
        Nothing is copied until `.X` is accessed, no real concatenation of the
        unerlying `.X` attributes is done.
        N)r   r   )rP   r   r   r   r   r8     s    zAnnCollectionView.Xc                 C   s   | j ddd | jS )a   Lazy subset of layers.

        The layers attribute formed from lazy inner join and subsetting of the `.layers`
        of the underlying `adatas`. No copy is made until you access a key from `.layers`,
        only the subset of the accessed key is copied.

        To get `.layers` as a dictionary, use `.layers.to_dict()`. You can also specify keys
        to include in the dict `.layers.to_dict(keys=['key1', 'key2'])` and if you want
        converters to be turned off when copying to dict `.layers.to_dict(use_convert=False)`.
        r   T)r   )r   r   r}   r   r   r   r     s    zAnnCollectionView.layersc                 C   s   |  d | jS )a  Lazy subset of multi-dimensional annotation of observations.

        Points to the `.obsm` attributes of the underlying adatas ot to `.obsm` of the parent
        AnnCollection object depending on the `join_obsm` option of the AnnCollection object.
        See the docs of :class:`~anndata.experimental.AnnCollection` for details.
        Copy rules are the same as for `.layers`, i.e. everything is lazy.

        To get `.obsm` as a dictionary, use `.obsm.to_dict()`. You can also specify keys
        to include in the dict `.obsm.to_dict(keys=['key1', 'key2'])` and if you want
        converters to be turned off when copying to dict `.obsm.to_dict(use_convert=False)`.
        r   )r   r   r}   r   r   r   r     s    
zAnnCollectionView.obsmc                 C   s   |  d | jS )a  Lazy suset of one-dimensional annotation of observations.

        Points to the `.obs` attributes of the underlying adatas ot to `.obs` of the parent
        AnnCollection object depending on the `join_obs` option of the AnnCollection object.
        See the docs of `~anndata.experimental.AnnCollection` for details.
        Copy rules are the same as for `.layers`, i.e. everything is lazy.

        To get `.obs` as a DataFrame, use `.obs.df`.
        To get `.obs` as a dictionary, use `.obs.to_dict()`. You can also specify keys
        to include in the dict `.obs.to_dict(keys=['key1', 'key2'])` and if you want
        converters to be truned off when copying to dict `.obs.to_dict(use_convert=False)`.
        r   )r   r   r}   r   r   r   r     s    
zAnnCollectionView.obsc                 C   s   | j j| j S )z,Names of observations of this subset object.)r   rp   r>   r}   r   r   r   rp     s    zAnnCollectionView.obs_namesc                 C   s   | j j| j S )z)Names of variables of this subset object.)r   	var_namesrA   r}   r   r   r   r     s    zAnnCollectionView.var_namesc                 C   s   t | jt | jfS )z;Shape of the lazily concatenated subset of the data matrix.)r   rp   r   r}   r   r   r   ra     s    zAnnCollectionView.shapec                 C   s
   | j d S zNumber of observations.r   ra   r}   r   r   r   n_obs  s    zAnnCollectionView.n_obsc                 C   s
   | j d S zNumber of variables/features.r*   r   r}   r   r   r   rO     s    zAnnCollectionView.n_varsc                 C   s   | j S )a  On the fly converters for keys of attributes and data matrix.

        A function or a Mapping of functions which will be applied
        to the values of attributes (`.X`) or to specific keys of these attributes
        (`.obs`, `.obsm`, `.layers`).
        The keys of the Mapping should correspond to the attributes or keys of the
        attributes (hierarchically) and the values should be functions used for conversion.

        Examples
        ----------
        ::

            {
                'X': lambda a: a.toarray() if issparse(a) else a, # densify .X
                'obsm': lambda a: np.asarray(a, dtype='float32'), # change dtype for all keys of .obsm
                'obs': dict(key1 = lambda c: c.astype(str)) # change type only for one key of .obs
            }
        r   r}   r   r   r   r&     s    zAnnCollectionView.convertc                 C   s6   || _ td| j | _tD ]}t| d| dd  qd S )Nr8   r   r   )r   r(   r   ATTRSr   )rP   valuer2   r   r   r   r&     s    c                 C   s
   t | jS r   )r   rp   r}   r   r   r   __len__  s    zAnnCollectionView.__len__r   c                 C   s0   t || j| j\}}| ||}t| j| j|S r   )r   rp   r   r   r   r   r&   rP   r   r>   rA   r   r   r   r   r{     s    zAnnCollectionView.__getitem__c                 C   s2   t | jD ]"\}}|jr
| j| dk	r
 dS q
dS )zO`True` if the current subset of `adatas` has backed objects, `False` otherwise.NTF)ru   r6   isbackedrQ   )rP   rg   r   r   r   r   
has_backed  s    zAnnCollectionView.has_backedc                 C   s   | j \}}d| d| }| j }| jD ]}tt| j| ||< q*| D ]4\}}t	|dkrP|d| dt
|dd  7 }qP|S )Nu0   AnnCollectionView object with n_obs × n_vars =     × r   
    : r*   r?   )ra   r   rs   r   rI   r.   r   r;   r9   r   r   )rP   r   rO   r   Zall_attrs_keysr2   r;   r   r   r   r     s    


"zAnnCollectionView.__repr__)ignore_Xignore_layersc           	      C   s   |s| j dkrd}n| j jdd}| jdkr0dn| jjdd}| jdkrLdnt| jjdd}|rpd}| j}n|  }d}t|||||d}| j	|_	| j
|_
|S )a	  Convert this AnnCollectionView object to an AnnData object.

        Parameters
        ----------
        ignore_X
            if `True`, adds `.X` to the AnnData object.
        ignore_layers
            if `True`, copies `.layers` to the AnnData object.
        NFr   )r   r   r   ra   )r   r   r   r   rv   rw   ra   r   r   rp   r   )	rP   r   r   r   r   r   r8   ra   r   r   r   r   to_adata  s"    
zAnnCollectionView.to_adatac                 C   s   | j jS z1Dict of all accessible attributes and their keys.)r   r:   r}   r   r   r   r:   8  s    zAnnCollectionView.attrs_keysN)F)FF)rY   rZ   r[   __doc__rq   r   r   r   r8   r   r   r   rp   r   ra   r   rO   r&   setterr   r   r{   r   r   rk   r   r:   r   r   r   r   r      sD   
-2











!r   c                   @   s  e Zd ZdZd%eee eeef f e	e
d  e	e
d  e	e
d  e	e e	ee  e	e e	e eed
ddZed	d
dZedd Zejdd Zedd Zedd Zedd Zedd Zedd Zdd Zdd Zd&ddZedd  Zed!d" Zd#d$ ZdS )'AnnCollectionu      Lazily concatenate AnnData objects along the `obs` axis.

    This class doesn't copy data from underlying AnnData objects, but lazily subsets using a joint
    index of observations and variables. It also allows on-the-fly application of prespecified
    converters to `.obs` attributes of the AnnData objects.

    Subsetting of this object returns an `AnnCollectionView`, which provides views of `.obs`,
    `.obsm`, `.layers`, `.X` from the underlying AnnData objects.

    Parameters
    ----------
    adatas
        The objects to be lazily concatenated.
        If a Mapping is passed, keys are used for the `keys` argument and values are concatenated.
    join_obs
        If "inner" specified all `.obs` attributes from `adatas` will be inner joined
        and copied to this object.
        If "outer" specified all `.obsm` attributes from `adatas` will be outer joined
        and copied to this object.
        For "inner" and "outer" subset objects will access `.obs` of this object,
        not the original `.obs` attributes of `adatas`.
        If `None`, nothing is copied to this object's `.obs`, a subset object will directly
        access `.obs` attributes of `adatas` (with proper reindexing and dtype conversions).
        For `None`the inner join rule is used to select columns of `.obs` of `adatas`.
    join_obsm
        If "inner" specified all `.obsm` attributes from `adatas` will be inner joined
        and copied to this object. Subset objects will access `.obsm` of this object,
        not the original `.obsm` attributes of `adatas`.
        If `None`, nothing is copied to this object's `.obsm`, a subset object will directly
        access `.obsm` attributes of `adatas` (with proper reindexing and dtype conversions).
        For both options the inner join rule for the underlying `.obsm` attributes is used.
    join_vars
        Specify how to join `adatas` along the var axis. If `None`, assumes all `adatas`
        have the same variables. If "inner", the intersection of all variables in
        `adatas` will be used.
    label
        Column in `.obs` to place batch information in.
        If it's None, no column is added.
    keys
        Names for each object being added. These values are used for column values for
        `label` or appended to the index if `index_unique` is not `None`. Defaults to
        incrementing integer labels.
    index_unique
        Whether to make the index unique by using the keys. If provided, this
        is the delimeter between "{orig_idx}{index_unique}{key}". When `None`,
        the original indices are kept.
    convert
        You can pass a function or a Mapping of functions which will be applied
        to the values of attributes (`.obs`, `.obsm`, `.layers`, `.X`) or to specific
        keys of these attributes in the subset object.
        Specify an attribute and a key (if needed) as keys of the passed Mapping
        and a function to be applied as a value.
    harmonize_dtypes
        If `True`, all retrieved arrays from subset objects will have the same dtype.
    indices_strict
        If  `True`, arrays from the subset objects will always have the same order
        of indices as in selection used to subset.
        This parameter can be set to `False` if the order in the returned arrays
        is not important, for example, when using them for stochastic gradient descent.
        In this case the performance of subsetting can be a bit better.

    Examples
    ----------
    >>> from scanpy.datasets import pbmc68k_reduced, pbmc3k_processed
    >>> adata1, adata2 = pbmc68k_reduced(), pbmc3k_processed()
    >>> adata1.shape
    (700, 765)
    >>> adata2.shape
    (2638, 1838)
    >>> dc = AnnCollection([adata1, adata2], join_vars='inner')
    >>> dc
    AnnCollection object with n_obs × n_vars = 3338 × 208
      constructed from 2 AnnData objects
        view of obsm: 'X_pca', 'X_umap'
        obs: 'n_genes', 'percent_mito', 'n_counts', 'louvain'
    >>> batch = dc[100:200] # AnnCollectionView
    >>> batch
    AnnCollectionView object with n_obs × n_vars = 100 × 208
        obsm: 'X_pca', 'X_umap'
        obs: 'n_genes', 'percent_mito', 'n_counts', 'louvain'
    >>> batch.X.shape
    (100, 208)
    >>> len(batch.obs['louvain'])
    100
    innerNT)r   outer)
r6   join_obs	join_obsm	join_varslabelr;   index_uniquer&   harmonize_dtypesrL   c                    s  t  tr6|d k	rtdt  t   } nt  dd  D | _dd  D }t fdd|dd  D }|r d j| _nh|dkrt	t
jj|}g | _ D ]6}||jr| jd  qt||j}| j| q|| _ntd	t
jd
d  D dd}|d kr*tt t}t
jjttt dd  D |d}|d k	rv|jj|t|d}t
|| _| jjstdt  t!" }g | _#|d k	r|$d | j#d t
jdd  D |dd}| j|_%|| _&nt
j'| jd| _&|d k	r|| j&|< d | _(|dkrt|$d | j#d t)dd  D | jd| _(| j(i krlt*| ddn| j(| _(i | _+|D ]"}tt, d | | j+|< q~ dd  D ]}| j+- D ]\}}t,||}t, d |}g }|D ]\}|| kr|| j.}|| j.}t|dk s4|d |d ks4|dkr|| q|| j+|< qq | _/ d j0g| _1t2t d D ]&}| j1| j1|  |d  j0  qx|| _3d | _4t dkr|	rt5| j+| j/| _4|
| _6d S )NzXCannot specify categories in both mapping keys and using `keys`. Only specify this once.c                 S   s   g | ]}d qS r   r   r,   r   r   r   r   r-     s     z*AnnCollection.__init__.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   )r   r   r   r   r   r-     s     c                    s   g | ]} d  j |qS r   )r   equals)r,   Zvrsr5   r   r   r-     s     r*   r   r   zSAdatas have different variables. Please specify join_vars='inner' for intersection.c                 S   s   g | ]}t |jqS r   )rv   ZSeriesrp   r,   r3   r   r   r   r-     s     T)ignore_indexc                 S   s   g | ]}|j d  qS r   r   r   r   r   r   r-     s     )
categories)sepz!Observation names are not unique.r   c                 S   s   g | ]
}|j qS r   )r   r   r   r   r   r-     s     )joinr   r   r   c                 S   s   g | ]
}|j qS r   )r   r   r   r   r   r-     s     )r      r   )7r#   r   	TypeErrorrI   r;   valuesrn   allr   r   rv   r   intersectionr   r/   r   r1   concatrE   rF   r   ry   r   ZCategoricalZ
from_codesrepeatcatmaprp   Z	is_uniquewarningswarnUserWarningr   rs   r   remover   _obsrw   _obsmr   r   r   r.   r9   ra   r6   r   rB   rd   r   r   r<   rL   )rP   r6   r   r   r   r   r;   r   r&   r   rL   Zvars_names_listZvars_eqr   r   Z
adata_vidxZconcat_indicesZ	label_colZ
view_attrsZconcat_annotr2   r3   Zai_attrZa0_attrZnew_keysr%   Z	a0_ashapeZ	ai_ashaperg   r   r5   r   rq     s    
 

 


  



   



$zAnnCollection.__init__r   c                 C   s.   t || j| j\}}| ||}t| | j|S r   )r   rp   r   r   r   r&   r   r   r   r   r{     s    zAnnCollection.__getitem__c                 C   s   | j S )a  On the fly converters for keys of attributes and data matrix.

        A function or a Mapping of functions which will be applied
        to the values of attributes (`.X`) or to specific keys of these attributes
        (`.obs`, `.obsm`, `.layers`) of subset objects. The converters are not
        applied to `.obs` and `.obsm` (if present) of this object, only to the attributes
        of subset objects.
        The keys of the Mapping should correspond to the attributes or keys of the
        attributes (hierarchically) and the values should be functions used for conversion.

        Examples
        --------
        ::

            {
                'X': lambda a: a.toarray() if issparse(a) else a, # densify .X
                'obsm': lambda a: np.asarray(a, dtype='float32'), # change dtype for all keys of .obsm
                'obs': dict(key1 = lambda c: c.astype(str)) # change type only for one key of .obs
            }
        r   r}   r   r   r   r&      s    zAnnCollection.convertc                 C   s
   || _ d S r   r   )rP   r   r   r   r   r&   8  s    c                 C   s   | j S )zOne-dimensional annotation of observations.

        If `join_obs` was set to "inner" and "outer", subset objects' `.obs`
        will point to this `.obs`; otherwise, to `.obs` of the underlying objects (`adatas`).
        )r   r}   r   r   r   r   <  s    zAnnCollection.obsc                 C   s   | j S )a  Multi-dimensional annotation of observations.

        If `join_obsm` was set to "inner", subset objects' `.obsm`
        will point to this `.obsm`; otherwise, to `.obsm` of the underlying objects (`adatas`).
        In the latter case, `.obsm` of this object will be `None`.
        )r   r}   r   r   r   r   E  s    zAnnCollection.obsmc                 C   s   | j d t| jfS )z,Shape of the lazily concatenated data matrixr?   )rB   r   r   r}   r   r   r   ra   O  s    zAnnCollection.shapec                 C   s
   | j d S r   r   r}   r   r   r   r   T  s    zAnnCollection.n_obsc                 C   s
   | j d S r   r   r}   r   r   r   rO   Y  s    zAnnCollection.n_varsc                 C   s
   | j d S )Nr?   )rB   r}   r   r   r   r   ^  s    zAnnCollection.__len__c                 C   s   d| j ksd| j kr| | j }d| j krF|jdk	r@|jjddnd}n
| j }| j }d| j kr|jdk	r|jjdd D ]\}}|||< qtd||| jd}| j|_| j	|_	|S )zConvert this AnnCollection object to an AnnData object.

        The AnnData object won't have `.X`, only `.obs` and `.obsm`.
        r   r   NFr   )r8   r   r   ra   )
r   rp   r   r   rs   r   r9   r   ra   r   )rP   Zconcat_viewr   r   r%   r   r   r   r   r   r   a  s     




zAnnCollection.to_adatac                 C   s   t | ||S )a   Get a subsettable key from an attribute (array-like) or an attribute.

        Returns a LazyAttrData object which provides subsetting over the specified
        attribute (`.obs` or `.obsm`) or over a key from this attribute.
        In the latter case, it acts as a lazy array.
        )LazyAttrData)rP   r2   r%   r   r   r   	lazy_attr|  s    zAnnCollection.lazy_attrc                 C   s   t dd | jD S )zB`True` if `adatas` have backed AnnData objects, `False` otherwise.c                 S   s   g | ]
}|j qS r   )r   r   r   r   r   r-     s     z,AnnCollection.has_backed.<locals>.<listcomp>)rK   r6   r}   r   r   r   r     s    zAnnCollection.has_backedc                 C   s:   i }| j D ]}tt| | }|||< q
|| j |S r   )r   rI   r.   r;   updater   )rP   Z_attrs_keysr2   r;   r   r   r   r:     s    

zAnnCollection.attrs_keysc                 C   s   | j \}}d| d| }|dt| j d7 }| j D ]4\}}t|dkr:|d| dt|dd	  7 }q:| jD ]B}tt| |	 }t|dkrv|d
| dt|dd	  7 }qvd| jkrt| j
	 }t|dkr|dt|dd	  7 }|S )Nu,   AnnCollection object with n_obs × n_vars = r   z
  constructed from z AnnData objectsr   z
    view of r   r*   r?   r   r   z
    own obs: )ra   r   r6   r   r9   r   r   rI   r.   r;   r   )rP   r   rO   r   r2   r;   r   r   r   r     s    
"
"
zAnnCollection.__repr__)	r   NNNNNNTT)N)rY   rZ   r[   r   r   r   r   r   r   r   r
   ConvertTyperk   rq   r   r{   r   r&   r   r   r   ra   r   rO   r   r   r   r   r:   r   r   r   r   r   r   B  s\   Z         



 



	



	

	r   c                   @   sP   e Zd Zdeeee dddZdd Zedd Z	ed	d
 Z
edd ZdS )r   Nadsetr2   r%   c                 C   s   || _ || _|| _d S r   r   )rP   r   r2   r%   r   r   r   rq     s    zLazyAttrData.__init__c                 C   s   d }d }t |tr8| jdkr8|d }t|dkr8|d }|d krL| j| }n
| j| }t|| j}| jd k	rv|| j }|d kr|S |d d |f S )N)r   r   r   r*   )r#   tupler2   r   r   r.   r%   )rP   r   r>   rA   viewr4   r   r   r   r{     s    


zLazyAttrData.__getitem__c                 C   s`   | j j}| jdkr|S | jdkr*|d fS | jdkrX| jd k	rX|d | d d jd fS d S d S )N)r8   r   r   r   r   r*   )r   ra   r2   r%   )rP   ra   r   r   r   ra     s    


zLazyAttrData.shapec                 C   s   | j d k	rt| j S dS r|   )ra   r   r}   r   r   r   ndim  s    zLazyAttrData.ndimc                 C   sN   | j j}|d k	r*| j|kr*|| j | j S | d d }t|drF|jS d S d S )Nr*   r0   )r   r   r2   r%   hasattrr0   )rP   r   r2   r   r   r   r0     s    
zLazyAttrData.dtype)N)rY   rZ   r[   r   r   r   rq   r{   r   ra   r   r0   r   r   r   r   r     s   

r   )N).collections.abcr   	functoolsr   Zh5pyr   numpyrE   Zpandasrv   r   typingr   r   r   r   r	   r
   Z_core.anndatar   Z_core.indexr   r   r   Z_core.viewsr   Z_core.merger   r   Z_core.sparse_datasetr   Z_core.aligned_mappingr   r   r!   r(   r<   r=   r\   rl   r   r   ZDictCallabler   r   r   r   r   r   r   <module>   s8    

0,Y  G  g