U
    md                  
   @   s   d dl mZmZmZmZ d dl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mZ dd	d
Zdeeeeeee eee dddZG dd deZdS )    )TupleOptionalSequenceListN)AnnData)	natsorted   )logging)	NeighborsOnFlySymMatrix   c                 C   s`   t d| d}t| |d}|  |j||d |j| jd< |j| jd< t jd|dd	 d S )
Nz'computing Diffusion Maps using n_comps=z(=n_dcs)neighbors_key)n_compsrandom_state	X_diffmapZdiffmap_evals    finishedzyadded
    'X_diffmap', diffmap coordinates (adata.obsm)
    'diffmap_evals', eigenvalues of transition matrix (adata.uns)timedeep)	logginfoDPTZcompute_transitionsZcompute_eigenZeigen_basisobsmZeigen_valuesuns)adatar   r   r   startdpt r   J/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/scanpy/tools/_dpt.py_diffmap   s    r    
   {Gz?TF)r   n_dcsn_branchingsmin_group_sizeallow_kendall_tau_shiftr   copyreturnc                 C   s  |r|   n| } |dkrd}|| jkr.tdd| jkrLd| jkrLtd d| j krptd t| |d	 t	| |||||d
}t
d| }|dkrt
d |jdk	r|  |j| jd< |j| jd< |dkrl|  tj|jdtt|jdd| jd< |j| jd< |j| jd< tj| jtd}	t|jD ]\}
}|
|	|< qB|	| jd< |j| jd< tj
d|d|jdk	rdnd |dkrdnd d |r| S dS )a      Infer progression of cells through geodesic distance along the graph
    [Haghverdi16]_ [Wolf19]_.

    Reconstruct the progression of a biological process from snapshot
    data. `Diffusion Pseudotime` has been introduced by [Haghverdi16]_ and
    implemented within Scanpy [Wolf18]_. Here, we use a further developed
    version, which is able to deal with disconnected graphs [Wolf19]_ and can
    be run in a `hierarchical` mode by setting the parameter
    `n_branchings>1`. We recommend, however, to only use
    :func:`~scanpy.tl.dpt` for computing pseudotime (`n_branchings=0`) and
    to detect branchings via :func:`~scanpy.tl.paga`. For pseudotime, you need
    to annotate your data with a root cell. For instance::

        adata.uns['iroot'] = np.flatnonzero(adata.obs['cell_types'] == 'Stem')[0]

    This requires to run :func:`~scanpy.pp.neighbors`, first. In order to
    reproduce the original implementation of DPT, use `method=='gauss'` in
    this. Using the default `method=='umap'` only leads to minor quantitative
    differences, though.

    .. versionadded:: 1.1

    :func:`~scanpy.tl.dpt` also requires to run
    :func:`~scanpy.tl.diffmap` first. As previously,
    :func:`~scanpy.tl.dpt` came with a default parameter of ``n_dcs=10`` but
    :func:`~scanpy.tl.diffmap` has a default parameter of ``n_comps=15``,
    you need to pass ``n_comps=10`` in :func:`~scanpy.tl.diffmap` in order
    to exactly reproduce previous :func:`~scanpy.tl.dpt` results.

    Parameters
    ----------
    adata
        Annotated data matrix.
    n_dcs
        The number of diffusion components to use.
    n_branchings
        Number of branchings to detect.
    min_group_size
        During recursive splitting of branches ('dpt groups') for `n_branchings`
        > 1, do not consider groups that contain less than `min_group_size` data
        points. If a float, `min_group_size` refers to a fraction of the total
        number of data points.
    allow_kendall_tau_shift
        If a very small branch is detected upon splitting, shift away from
        maximum correlation in Kendall tau criterion of [Haghverdi16]_ to
        stabilize the splitting.
    neighbors_key
        If not specified, dpt looks .uns['neighbors'] for neighbors settings
        and .obsp['connectivities'], .obsp['distances'] for connectivities and
        distances respectively (default storage places for pp.neighbors).
        If specified, dpt looks .uns[neighbors_key] for neighbors settings and
        .obsp[.uns[neighbors_key]['connectivities_key']],
        .obsp[.uns[neighbors_key]['distances_key']] for connectivities and distances
        respectively.
    copy
        Copy instance before computation and return a copy.
        Otherwise, perform computation inplace and return `None`.

    Returns
    -------
    Depending on `copy`, returns or updates `adata` with the following fields.

    If `n_branchings==0`, no field `dpt_groups` will be written.

    `dpt_pseudotime` : :class:`pandas.Series` (`adata.obs`, dtype `float`)
        Array of dim (number of samples) that stores the pseudotime of each
        cell, that is, the DPT distance with respect to the root cell.
    `dpt_groups` : :class:`pandas.Series` (`adata.obs`, dtype `category`)
        Array of dim (number of samples) that stores the subgroup id ('0',
        '1', ...) for each cell. The groups  typically correspond to
        'progenitor cells', 'undecided cells' or 'branches' of a process.

    Notes
    -----
    The tool is similar to the R package `destiny` of [Angerer16]_.
    N	neighborsz6You need to run `pp.neighbors` and `tl.diffmap` first.irootZxrootzNo root cell found. To compute pseudotime, pass the index or expression vector of a root cell, one of:
    adata.uns['iroot'] = root_cell_index
    adata.var['xroot'] = adata[root_cell_name, :].Xr   zpTrying to run `tl.dpt` without prior call of `tl.diffmap`. Falling back to `tl.diffmap` with default parameters.r   )r#   r%   r$   r&   r   z+computing Diffusion Pseudotime using n_dcs=   z+    this uses a hierarchical implementationZdpt_pseudotimer   U)values
categoriesZ
dpt_groupsZdpt_changepointsZdpt_grouptipsZdtypeZ	dpt_orderZdpt_order_indicesr   zadded
z0    'dpt_pseudotime', the pseudotime (adata.obs) ze
    'dpt_groups', the branching subgroups of dpt (adata.obs)
    'dpt_order', cell order (adata.obs)r   )r'   r   
ValueErrorvarr   warningr   keysr    r   r   r*   Z_set_pseudotime
pseudotimeZobsbranchings_segmentspdZCategorical
segs_namesastyper   nparraysegs_names_uniquechangepoints	segs_tipszerosZn_obsint	enumerateindices)r   r#   r$   r%   r&   r   r'   r   r   Zordering_idcountidxr   r   r   r      sv    W





	r   c                
       sL  e Zd ZdZd0 fdd	Zdd	 Zd
d Zdd Zee	e	f dddZ
dd Zdd Zdd Zeej eej e	ejdddZd1ejejeeej eej eee	  eee	  e	f dddZdd Zdd  Zd!d" Zejejejdd#d$Ze	dd%d&Ze	e	ed'd(d)Ze	e	ed*d+d,Zejejee	e	f d-d.d/Z  ZS )2r   z+    Hierarchical Diffusion Pseudotime.
    Nr"   r   Fc                    sV   t  j|||d d| _|| _|dkr*|nt|| jjd  | _|| _d| _	|| _
d S )N)r#   r   haghverdi16r+   r   F)super__init__flavorr$   r@   _adatashaper%   Zpassed_adatachoose_largest_segmentr&   )selfr   r#   r%   r$   r&   r   	__class__r   r   rG      s    	zDPT.__init__c                 C   s$   |    |   |   |   dS )u          Detect branchings and partition the data into corresponding segments.

        Detect all branchings up to `n_branchings`.

        Writes
        ------
        segs : np.ndarray
            Array of dimension (number of segments) × (number of data
            points). Each row stores a mask array that defines a segment.
        segs_tips : np.ndarray
            Array of dimension (number of segments) × 2. Each row stores the
            indices of the two tip points of each segment.
        segs_names : np.ndarray
            Array of dimension (number of data points). Stores an integer label
            for each segment.
        N)detect_branchingspostprocess_segmentsset_segs_namesorder_pseudotime)rL   r   r   r   r6      s    zDPT.branchings_segmentsc              
   C   s  t d| j d| jdkrdnd  tj| jjd td}|g}| jdk	r`t	| j
| j }nt	| j
d }t|t	| j
| g}|g}g g}d	g}g g}t d
| j d t| jD ]^}	| |||\}
}|
dkrt d  q t d|	d  d|
  | ||||||
| q|| _|| _|| _tjjt|t|ftd| _tjjt|t|ftd| _t|D ]\}}|| | j||f< qvtt|D ]F}tt|D ]2}| j
| j||f | j||f f | j||f< qq| j | _| j | _dS )a	          Detect all branchings up to `n_branchings`.

        Writes Attributes
        -----------------
        segs : np.ndarray
            List of integer index arrays.
        segs_tips : np.ndarray
            List of indices of the tips of segments.
        z    detect z
 branchingr+   r0   sr   r/   NTz*    do not consider groups with less than z points for splittingz    partitioning convergedz    branching z: split group )r   debugr$   r:   arangerI   rJ   r@   r*   argmaxdistances_dptr;   r%   rangeselect_segmentdetect_branchingsegsr>   segs_undecidedspsparse
lil_matrixlenfloatsegs_adjacencysegs_connectsrA   Ztocsr)rL   Zindices_allr\   tip_0Ztips_allr>   rd   r]   rc   ibranchisegtips3iseg_adjacencyjr   r   r   rO      s^    


zDPT.detect_branchingsc                    s   t jjdkddj}tdt |d D ]}tjjd D ]| |kr>j  j}fddjD  j fddj	D } fddt
|D }t |d|d  }t|| q>q*d S )Nr   r+   Zaxisc                    s.   g | ]&}|t jj  d  |f  qS r   )r:   argminrX   r>   ).0seg)rg   rL   r   r   
<listcomp>\  s   z'DPT.check_adjacency.<locals>.<listcomp>c                    s(   g | ] } t j|d   f  qS rm   )r:   rn   rX   )ro   tips)rp   rL   r   r   rq   a  s   c                    s"   g | ]\}}j  | |f qS r   )rX   )ro   Zipointpoint)closest_points_other_segsrL   r   r   rq   e  s   )r:   sumrc   A1rY   maxrJ   Ztodenser\   r>   rA   argsortprint)rL   Zn_edges_per_segZn_edgesZneighbor_segsZclosest_points_in_segsZdistance_segsZclosest_segsr   )rt   rg   rp   rL   r   check_adjacencyT  s$    
zDPT.check_adjacency)r(   c              
      s  t t|df}t j| jjd td t|D ]\}|| d dkrLq0t| j	t
sl| j	t  }n| j	}d}|| rtt|D ]`}||krtdD ]J}	| j	|| d || |	 f d| j	|| |	  || |	 f  k r|	}qq fd	d
|| D }
||
d  ||
d   }t | s4q0t |}|dk	r||| 7 }t |}||
d kr||kr||
d< |||
d  8 }n||| 8 }t |
|}||d  ||d |d f  }| jrtn|}tt| jk rd| d| dt dd nd t| jkr*d}|||df< |||ddf< q0t |dddf }||df dkrtdS ||ddf t}||fS )a          Out of a list of line segments, choose segment that has the most
        distant second data point.

        Assume the distance matrix Ddiff is sorted according to seg_idcs.
        Compute all the distances.

        Returns
        -------
        iseg
            Index identifying the position within the list of line segments.
        tips3
            Positions of tips within chosen segment.
           r   r/   rT   Nr   r+   g      ?c                    s&   g | ]}t   |kd  d  qS rm   )r:   where)ro   ZtipZ
allindicesrp   r   r   rq     s     z&DPT.select_segment.<locals>.<listcomp>
    group z score z
 n_points  z(too small)r0   )rT   N)r:   r?   ra   rV   rI   rJ   r@   rA   
isinstancerX   r   ix_restrictrY   isfiniteanyrW   appendrK   r   rU   r%   r9   )rL   r\   r>   r]   Zscores_tipsrg   DsegZthird_maximizerjsegZitiprr   ZdsegZ	third_tipZ
fourth_tiprh   Zscorer   r}   r   rZ   u  sl    


 $zDPT.select_segmentc                 C   s\   t | jD ]0\}}tj| jjd td}d||< || j|< q
t| j| _t| j| _dS )z0Convert the format of the segment class members.r   r/   TN)	rA   r\   r:   r?   rI   rJ   boolr;   r>   )rL   rg   rp   maskr   r   r   rP     s    zDPT.postprocess_segmentsc                 C   sP   t j| jjd t jd}g | _t| jD ]\}}|||< | j| q(|| _	dS )z9Return a single array that stores integer segment labels.r   r/   N)
r:   r?   rI   rJ   Zint8r<   rA   r\   r   r8   )rL   r8   rg   rp   r   r   r   rQ     s    zDPT.set_segs_namesc                 C   s   | j dk	rbt| jD ]L\}}|d dkrNt| j| }| j| | | j|< qtd| d qt| j}| j| }t	|j
d t|dk d }| j dk	r| j| }t| jD ].\}}|| }	t||	 }
||	 |
 ||	< q|| _|| _dS )a          Define indices that reflect segment and pseudotime order.

        Writes
        ------
        indices : np.ndarray
            Index array of shape n, which stores an ordering of the data points
            with respect to increasing segment index and increasing pseudotime.
        changepoints : np.ndarray
            Index array of shape len(ssegs)-1, which stores the indices of
            points where the segment index changes, with respect to the ordering
            of indices.
        Nr   rT   r~   z is very smallr+   )r*   rA   r>   r:   rx   r5   r   rU   r8   rV   sizediffr\   rB   r=   )rL   Zitipsrr   rB   r8   r=   r5   rg   rp   Z
seg_sortedZseg_indicesr   r   r   rR     s"    

"

zDPT.order_pseudotime)r\   r>   rg   rh   c           *         sP  |  }t | jts(| jt|| }	n| j|}	| |	||}
|
\}}}}t|D ]8\}}|| ||< |||  ||< t|||  ||< qX|	  |	  |
 |  |
 |  |fddt|D 7 }|fddt|D 7 }t|dkr|	  |
 d t|d }|   | jdkr| fddt|D 7 }|fd	dt|D 7 }|  }tD ]\}}d
}t|D ]\}}|kr||  }|| | }||kr8t|| | || |< |  |}|  	| |  	|}| | | |  q|d7 }qq|   ttt|| t|7  < |   | 7  < nd
dl}|dd t|D 7 }|dd t|D 7 } gttt|| t| }D ] }||  }g }g }g }|D ]| d
 }||| t| j||| f   |d } || t| j| | f   || j|d |d f  qt|}|| }!|!|| |< || || |< |  |}|  	| |  	| ||! | ||! ||  qd}"|D ](g }g }g }fddtt|D }#|#D ]}| d
 }||| t| j||| f   |d } || t| j| | f   || j|d |d f  q<t|}|#| }$|$|krtjjt|t|ftd}%t|D ]\}&}'d|%|&|'f< q ||%}(|j|(d})|$|)kr||$  ||$ ||  | |$ | ||  td d|$  d}"nFtd d|$ d |d krtd q
ntd  q6|$|kr
|"s
||$  ||$ ||  | |$ | ||   q6q
|dd t|D 7 }dS )a          Detect branching on given segment.

        Updates all list parameters inplace.

        Call function _detect_branching and perform bookkeeping on segs and
        segs_tips.

        Parameters
        ----------
        segs
            Dchosen distance matrix restricted to segment.
        segs_tips
            Stores all tip points for the segments in segs.
        iseg
            Position of segment under study in segs.
        tips3
            The three tip points. They form a 'triangle' that contains the data.
        c                    s   g | ]\}}| kr|qS r   r   )ro   rg   rp   trunkr   r   rq   D  s      z(DPT.detect_branching.<locals>.<listcomp>c                    s   g | ]\}}| kr|qS r   r   )ro   rg   Zseg_tipsr   r   r   rq   E  s     r{   Tr+   rE   c                    s   g | ]
} gqS r   r   ro   ri   )rg   r   r   rq   P  s     c                    s   g | ]\}}| kr|qS r   r   )ro   rg   Zseg_connectsr   r   r   rq   Q  s   r   Nc                 S   s   g | ]}g qS r   r   r   r   r   r   rq   p  s     c                 S   s   g | ]}g qS r   r   r   r   r   r   rq   q  s     rT   Fc                    s    g | ]}| kr|kr|qS r   r   )ro   r   )ksegprev_connecting_segmentsr   r   rq     s    r/   )sourcez    attaching new segment z at z    cannot attach new segment z (would produce cycle)z        continuez        do not add another linkc                 S   s   g | ]}d qS )Fr   r   r   r   r   rq     s     )r   rX   r   r:   r   r   _detect_branchingrA   listpopinsertra   r'   rH   rY   indexr   Znetworkxrn   r^   r_   r`   rb   ZGraphZsingle_source_dijkstra_pathr   rU   )*rL   r\   r>   rd   r]   rc   rg   rh   rp   r   resultssegs
ssegs_tipsssegs_adjacencyssegs_connectsZiseg_newZseg_newZn_addZprev_connecting_pointsZjseg_cntr   Ziseg_cntposZconnection_to_isegZpos_2rD   nxZ	kseg_listZ	distancesZclosest_points_in_jsegZclosest_points_in_ksegZreference_point_in_kZreference_point_in_jZkseg_minZdo_not_attach_ksegZ	jseg_listZjseg_minZsegs_adjacency_sparseri   rj   GZ	paths_allr   )rg   r   r   r   r   r[     s<   





 





 




zDPT.detect_branching)r   rr   r(   c                    s  | j dkr| ||}nB| j dkr0| ||}n*| j dksD| j dkrR| ||}ntdtjt||jd ft	d}t
|D ]\}}d|| |< q~tj|dd	d
k}g }t
|D ].\}}	d|	|< |tj|jd td|	  qg }
t
|D ]`\}}tt|d
kr"tdt| d |t|||  |  }|
|| |g qtj|jd td| }t|dkrV|| g g g g g}t
|
D ]b\}}|d }|t|| |  }|| | || t|| ||   }|d | q|t||d  |  }|t|| |  }|
||g dgdgdgdd
dgg}dnnt|dkr\tjdtd}|
d d |d< |
d
 d |d
< |
d d |d< tjdtd |d
 t||d  |d
    d< |d t||d
  |d    d< |d t||d  |d    d< |d t||d  |d    d< |d t||d
  |d    d< |d
 t||d  |d
    d< td}| d  d f | d  d f  |d< | d  d f | d  d f  |d
< | d  d f | d  d f  |d< t|fddtdD } fddtdD }nhdd
gdgg}|
d d }|d
 t|| |d
   }|}|d t|| |d   }|g|gg}||
||fS )as          Detect branching on given segment.

        Call function __detect_branching three times for all three orderings of
        tips. Points that do not belong to the same segment in all three
        orderings are assigned to a fourth segment. The latter is, by Haghverdi
        et al. (2016) referred to as 'undecided cells'.

        Parameters
        ----------
        Dseg
            Dchosen distance matrix restricted to segment.
        tips
            The three tip points. They form a 'triangle' that contains the data.

        Returns
        -------
        ssegs
            List of segments obtained from splitting the single segment defined
            via the first two tip cells.
        ssegs_tips
            List of tips of segments in ssegs.
        ssegs_adjacency
            ?
        ssegs_connects
            ?
        trunk
            ?
        rE   Z
wolf17_triZ	wolf17_biZwolf17_bi_unzC`flavor` needs to be in {"haghverdi16", "wolf17_tri", "wolf17_bi"}.r   r/   Trl   r+   Fzdetected group with only z cellsrT      r   )r   r   )r   r+   )r+   r   )r   r   )r   r   )r+   r   )r   r+   c                    s0   g | ](}| kr gn fd dt dD qS )c                    s   g | ]}| kr|qS r   r   ro   rk   r   r   r   rq   n  s      4DPT._detect_branching.<locals>.<listcomp>.<listcomp>r   rY   r   r   r   r   rq   m  s   z)DPT._detect_branching.<locals>.<listcomp>c                    s:   g | ]2}|kr |f gn fd dt dD qS )c                    s    g | ]}|kr |f qS r   r   r   Zclosest_pointsr   r   r   rq   t  s      r   r   r   r   r   r   r   rq   q  s   )rH   $_detect_branching_single_haghverdi16#_detect_branching_single_wolf17_tri"_detect_branching_single_wolf17_bir1   r:   r?   ra   rJ   r   rA   ru   r   rV   r@   Zflatnonzeror   r3   rW   rn   rY   )rL   r   rr   Zseg_referencer   masksrg   rp   Z	nonuniquer   r   ZinewsegZnewsegZ	secondtipZundecided_cellsr   Znewseg_tipsZreference_pointZclosest_cellre   Ztip_1r   Z
added_distZreference_point_in_0Zclosest_point_in_1Zreference_point_in_1Zclosest_point_in_0r   r   r   r     s    )

 



zDPT._detect_branchingc                 C   sL   g }dddgdddgdddgg}t |D ]\}}|| |||  q(|S )z"Detect branching on given segment.r   r+   r   )rA   r   "_DPT__detect_branching_haghverdi16)rL   r   rr   r   Zpsri   pr   r   r   r     s    z(DPT._detect_branching_single_haghverdi16c                 C   s   ||d  }||d  }||d  }||k }||k }||k }t jd|jd ftd}	||	d< ||	d< t j|	dddk}
t jd|jd ftd}	| |	d< ||	d< t j|	dddk}t jd|jd ftd}	| |	d< | |	d< t j|	dddk}|
||g}|S )Nr   r+   r   r/   rl   )r:   r?   rJ   r   ru   )rL   r   rr   dist_from_0dist_from_1Zdist_from_2closer_to_0_than_to_1Zcloser_to_0_than_to_2Zcloser_to_1_than_to_2r   Z	segment_0Z	segment_1Z	segment_2r   r   r   r   r     s(    



z'DPT._detect_branching_single_wolf17_tric                 C   s.   ||d  }||d  }||k }|| g}|S )Nr   r+   r   )rL   r   rr   r   r   r   r   r   r   r   r     s
    
z&DPT._detect_branching_single_wolf17_bic                 C   s|   t ||d  }| ||d  | ||d  | }g }|dt| krh| jrhtd td| }n|d }|d| S )a          Detect branching on given segment.

        Compute point that maximizes kendall tau correlation of the sequences of
        distances to the second and the third tip, respectively, when 'moving
        away' from the first tip: tips[0]. 'Moving away' means moving in the
        direction of increasing distance from the first tip.

        Parameters
        ----------
        Dseg
            Dchosen distance matrix restricted to segment.
        tips
            The three tip points. They form a 'triangle' that contains the data.

        Returns
        -------
        Segments obtained from "splitting away the first tip cell".
        r   r+   r   gffffff?zwshifting branching point away from maximal kendall-tau correlation (suppress this with `allow_kendall_tau_shift=False`)N)r:   rx   kendall_tau_splitra   r&   r   r3   r@   )rL   r   rr   Zidcsimaxr   rf   r   r   r   Z__detect_branching_haghverdi16  s    z"DPT.__detect_branching_haghverdi16c                 C   sF  |j |j krtd|j|j  kr,dkr8n ntdddl}d}|j }tj||j | d td}t|j }|j	|d| |d| d }|j	||d ||d d }	t
|D ]V\}
}| |||\}}|| ||| }|	| || ||	 }|}|}	|| ||
< qt|}|| }|| }|dk rBtd	 |S )
ak  Return splitting index that maximizes correlation in the sequences.

        Compute difference in Kendall tau for all splitted sequences.

        For each splitting index i, compute the difference of the two
        correlation measures kendalltau(a[:i], b[:i]) and
        kendalltau(a[i:], b[i:]).

        Returns the splitting index that maximizes
            kendalltau(a[:i], b[:i]) - kendalltau(a[i:], b[i:])

        Parameters
        ----------
        a, b : np.ndarray
            One dimensional sequences.

        Returns
        -------
        Splitting index according to above description.
        z"a and b need to have the same sizer+   z)a and b need to be one-dimensional arraysr   N   r/   g333333?z8    is root itself, never obtain significant correlation)r   r1   ndimscipyr:   rV   r@   r?   statsZ
kendalltaurA   _kendall_tau_diff_kendall_tau_add_kendall_tau_subtractrW   r   rU   )rL   abr^   Z
min_lengthnZ	idx_rangeZ
corr_coeffZpos_oldZneg_oldiiri   diff_posdiff_negr   negZiimaxr   Zcorr_coeff_maxr   r   r   r     s0    ""


zDPT.kendall_tau_split)len_oldr   tau_oldc                 C   s   d|d  t || |  S )ap  Compute Kendall tau delta.

        The new sequence has length len_old + 1.

        Parameters
        ----------
        len_old
            The length of the old sequence, used to compute tau_old.
        diff_pos
            Difference between concordant and non-concordant pairs.
        tau_old
            Kendall rank correlation of the old sequence.
               @r+   rb   )rL   r   r   r   r   r   r   r   1  s    zDPT._kendall_tau_add)r   r   r   c                 C   s"   d|d  t | |d  |  S )ap  Compute Kendall tau delta.

        The new sequence has length len_old - 1.

        Parameters
        ----------
        len_old
            The length of the old sequence, used to compute tau_old.
        diff_neg
            Difference between concordant and non-concordant pairs.
        tau_old
            Kendall rank correlation of the old sequence.
        r   r   r+   r   )rL   r   r   r   r   r   r   r   A  s    zDPT._kendall_tau_subtract)r   r   r(   c           
      C   sF  t j|d| jtd}d||d| || k< d||d| || k < t j|d| jtd}d||d| || k< d||d| || k < t ||t}t j||d jtd}d|||d || k< d|||d || k < t j||d jtd}d|||d || k< d|||d || k < t ||}	||	fS )a  Compute difference in concordance of pairs in split sequences.

        Consider splitting a and b at index i.

        Parameters
        ----------
        a
            ?
        b
            ?

        Returns
        -------
        diff_pos
            Difference between concordant pairs for both subsequences.
        diff_neg
            Difference between non-concordant pairs for both subsequences.
        Nr/   r+   rT   )r:   r?   r   r@   dotr9   rb   )
rL   r   r   ri   Za_posZb_posr   Za_negZb_negr   r   r   r   r   Q  s    zDPT._kendall_tau_diff)Nr"   r   FN)N)__name__
__module____qualname____doc__rG   r6   rO   rz   r   r@   rZ   rP   rQ   rR   r   r:   Zndarrayr[   r   r   r   r   r   r   r   rb   r   r   r   __classcell__r   r   rM   r   r      sZ        b!^	* ] 

  >@r   )r   Nr   )r!   r   r"   TNF)typingr   r   r   r   numpyr:   Zpandasr7   r   r^   Zanndatar   Znatsortr   r0   r	   r   r)   r
   r   r    r@   rb   r   strr   r   r   r   r   r   <module>   s4   
       #