U
    f»{jC> ã                	   @   sÊ  d dl mZ d dlmZmZ d dlmZ 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 dd
lmZmZmZmZmZ ddlmZ ddl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' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 e*dœdd„ƒZ8d�dd„Z9e*dždd„ƒZ:dd„ Z;dd„ Z<eƒ dd„ ƒZ=eƒ dd „ ƒZ>eƒ d!d"„ ƒZ?d#d$„ Z@eƒ d%d&„ ƒZAdŸd)d*„ZBd+d,„ ZCe*d dd-œd.d/„ƒZDd0d1„ ZEd2d3„ ZFG d4d5„ d5eGƒZHd¡d7d8„ZId¢d9d:„ZJG d;d<„ d<eGƒZKe*d£d=d>„ƒZLd?d@„ ZMd¤dAdB„ZNG dCdD„ dDeGƒZOdEdF„ ZPdGdH„ ZQd¥dIdJ„ZRe*d¦dLdM„ƒZSdNdO„ ZTdPdQ„ ZUdRdS„ ZVdTdU„ ZWd§dVdW„ZXd¨dYdZ„ZYd[d\„ ZZd]d^„ Z[d_d`„ Z\dadb„ Z]e*d©dd-œddde„ƒZ^dfdg„ Z_dhdi„ Z`e*dªdd-œdkdl„ƒZaeƒ dmdn„ ƒZbdodp„ Zceddq�d«drds„ƒZdeƒ dtdu„ ƒZedvdw„ Zfedxdy�d¬dzd{„ƒZgd|d}„ Zhe*d­d~d„ƒZieƒ d€d�„ ƒZjd®d‚dƒ„Zke*d¯d„d…„ƒZld†d‡„ Zmd°dˆd‰„ZndŠd‹„ Zod±dŒd�„Zpe*d²d‘d’„ƒZqd“Zre4d³d–d—„ƒZsd˜d™„ Ztd´dšd›„ZudS )µé    )Údeepcopy)ÚpartialÚ	lru_cache)ÚOrderedDict)Úglob)Úpath)ÚpackNé   )Ú_get_meg_system)Ú_serialize_volume_infoÚ_get_read_geometryÚjitÚprangeÚbincount)ÚFIFF)Ú
pick_types)Úparallel_func)Útransform_surface_toÚ_pol_to_cartÚ_cart_to_sphÚ
_get_transÚapply_transÚ	TransformÚ_frame_to_strÚapply_volume_registration)ÚloggerÚverboseÚget_subjects_dirÚwarnÚ_check_fnameÚ_check_optionÚ_ensure_intÚ_TempDirÚrun_subprocessÚ_check_freesurfer_homeÚ_hashable_ndarrayÚfill_docÚ_validate_typeÚ_require_versionÚ_pl©ÚbemÚheadÚraisec                 C   s   t | |||d�S )aN  Load the subject head surface.

    Parameters
    ----------
    subject : str
        Subject name.
    source : str | list of str
        Type to load. Common choices would be ``'bem'`` or ``'head'``. We first
        try loading ``'$SUBJECTS_DIR/$SUBJECT/bem/$SUBJECT-$SOURCE.fif'``, and
        then look for ``'$SUBJECT*$SOURCE.fif'`` in the same directory by going
        through all files matching the pattern. The head surface will be read
        from the first file containing a head surface. Can also be a list
        to try multiple strings.
    subjects_dir : str, or None
        Path to the SUBJECTS_DIR. If None, the path is obtained by using
        the environment variable SUBJECTS_DIR.
    %(on_defects)s

        .. versionadded:: 1.0
    %(verbose)s

    Returns
    -------
    surf : dict
        The head surface.
    )ÚsubjectÚsourceÚsubjects_dirÚ
on_defects)Ú_get_head_surface)r.   r/   r0   r1   r   © r3   úJ/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/surface.pyÚget_head_surf(   s     ÿr5   Tc                 C   sT  ddl m} t|dd�}t| tƒs2tdt| ƒ ƒ‚t|tƒrB|g}d}|D ]Ð}t t 	|| dd| |f ¡¡}t 
|¡rŒ||dtj|d	d
�}n€t 	|| d¡}	t |	¡s°td|	 ƒ‚ttt 	|	d| |f ¡ƒƒ}
|
D ]:}z||dtj|d	d
�}W n tk
�r   Y qÐX  �qqÐ|dk	rJ �qqJ|dk�rB|�r>td| |f ƒ‚n|S t d| ¡ |S )zLoad the subject head surface.r	   ©Úread_bem_surfacesT)Úraise_errorz!subject must be a string, not %s.Nr+   z	%s-%s.fifF)r1   r   z*Subject bem directory "%s" does not exist.z	%s*%s.fifz=No file matching "%s*%s" and containing a head surface found.zUsing surface from %s.)r+   r7   r   Ú
isinstanceÚstrÚ	TypeErrorÚtypeÚopÚrealpathÚjoinÚexistsr   ZFIFFV_BEM_SURF_ID_HEADÚisdirÚIOErrorÚsortedr   Ú
ValueErrorr   Úinfo)r.   r/   r0   r1   r8   r7   ÚsurfZthis_sourceZ	this_headr   Úfilesr3   r3   r4   r2   J   sZ    


ÿ
ý
ÿÿ
ý

ÿr2   c              	      sÌ  ddl m}m} ddlm}m} tˆ ƒ\}}|rrt d| ¡ t	 
t	 t¡d dd|d ¡}	||	d	tjd	d
�}
�nt ‡ fdd„tˆ dd	dd�D ƒ¡}t d|t|ƒf ¡ ||ƒ}|t |j¡ }||d	d�\}}t|| ƒdd…dd…f }tjd |dd…df  ¡ gg}t ||f¡}t|dd…ddd…f ƒ}||ƒj}||t|ƒd k d¡ }t||ƒ}t||d�}
t|
d	d	d� tj|
d< ˆ d }|dk�r¦tddƒ}t |
d|ƒ |dk	�rÈt |
d|ƒ |
S )a+  Load the MEG helmet associated with the MEG sensors.

    Parameters
    ----------
    %(info_not_none)s
    trans : dict
        The head<->MRI transformation, usually obtained using
        read_trans(). Can be None, in which case the surface will
        be in head coordinates instead of MRI coordinates.
    %(verbose)s

    Returns
    -------
    surf : dict
        The MEG helmet as a surface.

    Notes
    -----
    A built-in helmet is loaded if possible. If not, a helmet surface
    will be approximated based on the sensor locations.
    r   )Ú
ConvexHullÚDelaunayr	   )r7   Ú_fit_spherezGetting helmet for system %sÚdataZhelmetsz.fif.gzF©r   c                    s$   g | ]}ˆ d  | d dd… ‘qS )ZchsÚlocNé   r3   )Ú.0Úpick©rE   r3   r4   Ú
<listcomp>ž   s   ÿz'get_meg_helmet_surf.<locals>.<listcomp>Tr3   )ÚmegZref_megÚexcludezDGetting helmet for system %s (derived from %d MEG channel locations))ZdispNç       @éÿÿÿÿ©ÚrrÚtris)Úcopyr   Úcoord_frameÚ
dev_head_trS   r,   Úmri)!Úscipy.spatialrH   rI   r+   r7   rJ   r
   r   rE   r=   r?   ÚsplitÚ__file__r   ZFIFFV_MNE_SURF_MEG_HELMETÚnpÚarrayr   ÚlenÚuniqueZ	simplicesr   ÚpiÚmaxÚconcatenater   ÚallÚ_reorder_ccwÚdictÚcomplete_surface_infoZFIFFV_COORD_DEVICEr   r   )rE   Útransr   rH   rI   r7   rJ   ÚsystemZhave_helmetÚfnamerF   rX   ZhullÚRÚcenterZsphZ	front_sphZxyrY   r\   r3   rQ   r4   Úget_meg_helmet_surf}   sN    ÿ
ÿ
ÿÿ
ÿ 





rq   c              	   C   sš   t j| dd�}| | }t  t  |dd…df |dd…df  |dd…df |dd…df  ¡|dd…df |   d¡¡ t¡}t  dd„ t||ƒD ƒ¡S )	z<Reorder tris of a convex hull to be wound counter-clockwise.r   ©ÚaxisNr	   é   rV   c                 S   s   g | ]\}}|d d |… ‘qS ©Nr3   )rO   ÚdÚtr3   r3   r4   rR   Ç   s     z _reorder_ccw.<locals>.<listcomp>)	ra   ÚmeanÚsignÚcrossÚsumÚastypeÚintrb   Úzip)ÚrrsrY   ÚcomZrr_trisÚdirsr3   r3   r4   ri   ¿   s    &ÿþþþri   c                 C   s†   | j dkst‚|j dkst‚| jd dks.t‚|jd dks@t‚t| j|jƒdkrvt t | |¡j¡}t|| |ƒ |S t 	| |¡S dS )a'  Compute cross product between list of 3D vectors.

    Much faster than np.cross() when the number of cross products
    becomes large (>= 500). This is because np.cross() methods become
    less memory efficient at this stage.

    Parameters
    ----------
    x : array
        Input array 1, shape (..., 3).
    y : array
        Input array 2, shape (..., 3).

    Returns
    -------
    z : array, shape (..., 3)
        Cross product of x and y along the last dimension.

    Notes
    -----
    x and y must broadcast against each other.
    r	   rV   rN   iô  N)
ÚndimÚAssertionErrorÚshaperf   Úsizera   ÚemptyÚ	broadcastÚ
_jit_crossrz   )ÚxÚyÚoutr3   r3   r4   Úfast_cross_3dÍ   s    rŒ   c                 C   s”   |d |d  | d< | d  |d |d  8  < |d |d  | d< | d  |d |d  8  < |d |d  | d< | d  |d |d  8  < d S )N©.r	   ©.rt   ©.r   r3   )r‹   r‰   rŠ   r3   r3   r4   rˆ   ð   s    rˆ   c                 C   sx   | d |d  | d |d   |d  | d |d  | d |d   |d   | d |d  | d |d   |d   S )zFast cross and sum.r�   rŽ   r�   r3   )ÚaÚbÚcr3   r3   r4   Ú_fast_cross_nd_sumú   s
    &&ÿ&þr“   c              
   C   sl   t  |df¡}tdƒD ]P}| dd…|f }tdƒD ]2}|dd…|f  t||dd…|f |d�7  < q2q|S )z(Efficiently accumulate triangle normals.rN   N)ÚweightsZ	minlength)ra   ÚzerosÚranger   )rY   Útri_nnÚnptsÚnnÚviÚvertsÚidxr3   r3   r4   Ú_accumulate_normals  s    
"ÿr�   c                    s˜   ddl m} |  ¡ }t t t| ƒ¡d¡}t t|ƒ¡}||||ff|t| ƒfd� ¡ ‰ ‡ fdd„t	ˆ j
dd… ˆ j
d	d… ƒD ƒ}t|ƒ|ks”t‚|S )
z1Efficiently compute vertex neighboring triangles.r   ©Ú
coo_matrixrN   ©r„   c                    s   g | ]\}}ˆ j ||… ‘qS r3   )Úindices)rO   ÚstartÚstop©Zcsrr3   r4   rR   !  s   ÿz'_triangle_neighbors.<locals>.<listcomp>NrV   r	   )Úscipy.sparserŸ   Úravelra   ÚrepeatÚarangerc   ÚonesÚtocsrr~   Zindptrrƒ   )rY   r˜   rŸ   ÚrowsÚcolsrK   Úneighbor_trir3   r¤   r4   Ú_triangle_neighbors  s     
ÿr®   c	                 C   s¬   || }|| }	|| }|| }|| }|| }|| }| | }
t  |
|	 ¡}t  |
| ¡}t  |
| ¡}|| ||  }|| ||  | }|| ||  | }|||fS )z4Get coordinates of a vertex projected to a triangle.)ra   r{   )ÚrÚbestÚr1r™   Úr12Úr13r�   r‘   r’   r—   rX   ÚzÚv1Úv2Zdetr‰   rŠ   r3   r3   r4   Ú_triangle_coords'  s    r·   FÚaccuratec              	   C   s
  |dkr”t |ƒ}t dt¡}t t| ƒd t¡}t| ||fddi|—Ž}|rx|t d|d |d |d	 |d   ¡f7 }|r’||d
 |d  f7 }nr|sœt‚t	|d | ƒ}	dd|d |	 f}|�rt |ƒ}t
|d	  t¡|d
 t|d ƒƒ}
|
|	 }
t|
ƒ ||
f7 }|S )z$Project points onto (scalp) surface.r¸   )r   r	   Ú	reprojectTz
ij,ijk->ikr   rX   rY   r™   N)Ú_get_tri_supp_geomra   r†   r}   r•   rc   Ú_find_nearest_tri_ptsÚeinsumrƒ   Ú_compute_nearestr�   r|   Ú_normalize_vectors)r   rF   Zproject_rrsZ	return_nnÚmethodZ	surf_geomÚpt_trisÚpt_lensr‹   rœ   r™   r3   r3   r4   Ú_project_onto_surface;  s6    ÿÿÿ
ÿ
rÂ   c              	   C   sž   | j dd… dkst‚t d| | ¡}tj t d¡| ¡\}}|dddd…f }t t | dtj	dd…f |ddd…f ¡¡}d||dk< ||9 }| 
dd	¡S )
z(Compute orthogonal basis given a normal.rV   N)rN   z...i,...j->...ijrN   .r	   r   éþÿÿÿ)r„   rƒ   ra   r¼   ÚlinalgZeighÚeyery   ÚmatmulÚnewaxisÚswapaxes)r™   ÚprodÚ_ÚuZsignsr3   r3   r4   Ú_normal_orthW  s    .rÌ   rL   c                   sx  |rt ˆ ƒ‰ ˆ  dtˆ d ƒ¡ˆ d< ˆ  dtˆ d ƒ¡ˆ d< t ˆ d ¡ˆ d< ˆ d ˆ d dd…df dd…f }ˆ d ˆ d dd…df dd…f }ˆ d ˆ d dd…d	f dd…f }|| | d
 ˆ d< t|| || ƒˆ d< tˆ d ƒd ˆ d< t ˆ d dk¡d }t|ƒdk�r*t 	d| ¡ t 	d¡ t
ˆ d  t¡ˆ d ˆ d ƒˆ d< tˆ d ƒ |�rBtˆ d ˆ d ƒˆ d< tƒ tƒ  }	}
tˆ d ƒD ]P\}}t|ƒdk �r˜t|ƒdk�rÈ|	 |¡ n|
 |¡ t g t¡ˆ d |< �q˜t|	ƒdk�rt 	dd dd„ |	D ƒ¡ ¡ t|
ƒdk�rBt 	dd dd„ |
D ƒ¡ ¡ |dk�rtt 	d¡ ‡ fdd„tˆ d ƒD ƒˆ d< ˆ S )aÄ  Complete surface information.

    Parameters
    ----------
    surf : dict
        The surface.
    do_neighbor_vert : bool
        If True (default False), add neighbor vertex information.
    copy : bool
        If True (default), make a copy. If False, operate in-place.
    do_neighbor_tri : bool
        If True (default), compute triangle neighbors.
    %(verbose)s

    Returns
    -------
    surf : dict
        The transformed surface.
    ÚntrirY   ra   rX   Ztri_areaNr   r	   rt   g      @Ztri_centr—   rU   z$    Warning: zero size triangles: %sz,    Triangle neighbors and vertex normals...r™   r­   rN   z8    Vertices do not have any neighboring triangles: [%s]ú, c                 s   s   | ]}t |ƒV  qd S ru   ©r:   )rO   r´   r3   r3   r4   Ú	<genexpr>¡  s     z(complete_surface_info.<locals>.<genexpr>zR    Vertices have fewer than three neighboring triangles, removing neighbors: [%s]c                 s   s   | ]}t |ƒV  qd S ru   rÏ   )rO   Úfr3   r3   r4   rÐ   ¥  s     Tz    Vertex neighbors...c                    s   g | ]}t ˆ |ƒ‘qS r3   )Ú_get_surf_neighbors)rO   Úk©rF   r3   r4   rR   ª  s   ÿz)complete_surface_info.<locals>.<listcomp>Úneighbor_vert)r   Úgetrc   ra   r•   rŒ   r¾   Úwherer   rE   r�   r|   r}   r®   ÚlistÚ	enumerateÚappendrb   r?   r–   )rF   Údo_neighbor_vertrZ   Zdo_neighbor_trir   r±   Úr2Zr3ZzidxÚzeroZfewerÚniÚnr3   rÔ   r4   rk   d  sV    $$$
 ÿ
ÿþ



ÿ
rk   c                 C   s¨   t ƒ }| d | d |  jD ]}| |¡ q| |¡ t t|ƒ¡}t || d k ¡sZt‚t	|ƒ}t	| d | ƒ}||krˆt
d| ƒ‚n||kr¤t d|||f ¡ |S )z7Calculate the surface neighbors based on triangulation.rY   r­   ra   z Too many neighbors for vertex %dzT    Incorrect number of distinct neighbors for vertex %d (%d instead of %d) [fixed].)ÚsetZflatÚaddÚremovera   rb   rC   rh   rƒ   rc   ÚRuntimeErrorr   rE   )rF   rÓ   r›   ÚvZ
nneighborsZ
nneigh_maxr3   r3   r4   rÒ   °  s"    
ÿÿrÒ   c                 C   s6   t jj| dd�}|dk}| |  ||t jf   < |S )zNormalize surface vertices.r	   rr   r   )ra   rÄ   ÚnormrÇ   )rX   r…   Úmaskr3   r3   r4   r¾   Ã  s    r¾   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )Ú_CDistz0Wrapper for cdist that uses a Tree-like pattern.c                 C   s
   || _ d S ru   )Ú_xhs)ÚselfÚxhsr3   r3   r4   Ú__init__Î  s    z_CDist.__init__c                 C   sv   ddl m} tƒ }tƒ }|D ]D}||tjd d …f | jƒ}t |¡}| |¡ | |d|f ¡ qt |¡t |¡fS )Nr   )Úcdist)	Zscipy.spatial.distancerì   rØ   ra   rÇ   rè   ÚargminrÚ   rb   )ré   rX   rì   ÚnearestÚdistsr¯   rv   rœ   r3   r3   r4   ÚqueryÑ  s    

z_CDist.queryN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rë   rð   r3   r3   r3   r4   rç   Ë  s   rç   ÚBallTreec                 C   sj   | j dks|j dkr:|r.t g t¡t g ¡fS t g t¡S t| |d�}| |¡}|rb|ddd… S |d S )a“  Find nearest neighbors.

    Parameters
    ----------
    xhs : array, shape=(n_samples, n_dim)
        Points of data set.
    rr : array, shape=(n_query, n_dim)
        Points to find nearest neighbors for.
    method : str
        The query method. If scikit-learn and scipy<1.0 are installed,
        it will fall back to the slow brute-force search.
    return_dists : bool
        If True, return associated distances.

    Returns
    -------
    nearest : array, shape=(n_query,)
        Index of nearest neighbor in xhs for every point in rr.
    distances : array, shape=(n_query,)
        The distances. Only returned if return_dists is True.
    r   ©r¿   NrV   r	   )r…   ra   rb   r}   Ú_DistanceQueryrð   )rê   rX   r¿   Úreturn_distsÚtreer‹   r3   r3   r4   r½   Ý  s    
r½   c                 K   s^   t | ƒdkr"t g ¡t g t¡fS || ƒ}|rV|d d d …df |d d d …df gn|}|S )Nr   r	   )rc   ra   rb   r}   )rX   ÚfuncÚreduceÚkwargsr‹   r3   r3   r4   Ú_safe_queryü  s
    0rý   c                   @   s   e Zd ZdZddd„ZdS )r÷   z"Wrapper for fast distance queries.rõ   Fc                 C   s¼   |dkst ‚|dkr`zddlm} W n" tk
rF   t d¡ d}Y nX tt||ƒjddd�| _|dkržzdd	l	m
} W n tk
r�   d
}Y nX ||ƒj| _|d
kr²t|ƒj| _|| _d S )N)rõ   ÚcKDTreerì   rõ   r   )rõ   zTNearest-neighbor searches will be significantly faster if scikit-learn is installed.rþ   T)rú   rû   Zreturn_distance)rþ   rì   )rƒ   Zsklearn.neighborsrõ   ÚImportErrorr   rE   r   rý   rð   r^   rþ   rç   rK   )ré   rê   r¿   Zallow_kdtreerõ   rþ   r3   r3   r4   rë     s(    

 ÿ
z_DistanceQuery.__init__N)rõ   F)rñ   rò   ró   rô   rë   r3   r3   r3   r4   r÷     s   r÷   c                    sx   t  ˆ¡‰ˆjd dkst‚tt|ƒ\}‰ }|‡ ‡‡fdd„t  ˆd |¡D ƒƒ}t  t j|dd�dt j	  d	 ¡d
kS )a@  Check whether points are outside a surface.

    Parameters
    ----------
    rr : ndarray
        Nx3 array of points to check.
    surf : dict
        Surface with entries "rr" and "tris".

    Returns
    -------
    outside : ndarray
        1D logical array of size N for which points are outside the surface.
    r	   rN   c                 3   s    | ]}ˆ ˆd  | ˆƒV  qdS )rX   Nr3   )rO   rY   ©Zp_funrX   rF   r3   r4   rÐ   =  s   ÿz*_points_outside_surface.<locals>.<genexpr>rY   r   rr   rt   ç      ð?gñhãˆµøä>)
ra   Z
atleast_2dr„   rƒ   r   Ú_get_solidsZarray_splitÚabsr{   re   )rX   rF   Ún_jobsr   ÚparallelZ
tot_anglesr3   r   r4   Ú_points_outside_surface*  s    
ÿr  c                 C   s`   dd l }t | d ¡}d| kr(| |¡S t | d ¡}tjt t|ƒd¡|f }| ||¡S d S )Nr   rX   rY   rN   )Úpyvistara   rb   ÚPolyDataÚc_Úfullrc   )rF   ÚpvZverticesÚ	trianglesr3   r3   r4   Ú_surface_to_polydataB  s    
r  c                 C   sX   ddl m} t| |ƒs|| ƒ} t| j| j dd¡d d …dd …f d�}|rT| j|d< |S )Nr   )r  rV   é   r	   rW   r™   )r  r  r9   rj   ÚpointsÚfacesÚreshapeZpoint_normals)ÚpdÚnormalsr  r‹   r3   r3   r4   Ú_polydata_to_surfaceM  s    
(
r  c                   @   sR   e Zd ZdZedddœdd„ƒZdd„ Zd	d
„ Zeddd„ƒZdd„ Z	dd„ Z
dS )Ú_CheckInsidez1Efficiently check if points are inside a surface.ÚoldN)Úmoder   c             	   C   sv   |dkst ‚|| _t ¡ }|| _| jdkr4|  ¡  n|  ¡  t d|› dt| jd ƒ› dt ¡ | d d›d	�¡ d S )
N)r  r  r  zSetting up z interior check for rX   z points took éè  ú0.1fú ms)	rƒ   r  ÚtimerF   Ú_init_pyvistaÚ	_init_oldr   Údebugrc   )ré   rF   r  r   Út0r3   r3   r4   rë   Z  s    

.ÿz_CheckInside.__init__c                 C   sz   ddl m} d | _| jd  d¡| _|| jd ƒ| _| j | j¡dkrvtj	j
| jd | j dd�}| ¡ | _| ¡ | _d S )Nr   )rI   rX   rV   rr   )r^   rI   Úinner_rrF   rx   ÚcmÚdel_triÚfind_simplexra   rÄ   rå   Úminrf   Úouter_r)ré   rI   rï   r3   r3   r4   r  h  s    
z_CheckInside._init_oldc                 C   s6   t | jtƒs"| j| _t| jƒ| _nt| jƒ ¡ | _d S ru   )r9   rF   rj   Úpdatar  r  Úclean)ré   r3   r3   r4   r  v  s    z_CheckInside._init_pyvistac              
   C   s    t |ƒ}t d|› dt|dƒ› d�¡ t ¡ }| jdkrD|  |¡}n|  ||¡}| ¡ }t d|› d|› dt|dƒ› d�¡ t d	t ¡ | d
 d›d�¡ |S )Nz%Checking surface interior status for ú pointú z...r  z
    Total ú/z inside the surfacezInterior check completed in r  r  r  )	rc   r   rE   r)   r  r  Ú_call_pyvistaÚ	_call_oldr{   )ré   rX   r  r   Ún_origr  Úinsiderß   r3   r3   r4   Ú__call__}  s    
ÿÿz_CheckInside.__call__c                 C   s,   t t|d�ƒ}|j| jdd�}|d  t¡S )N)rX   F)Zcheck_surfaceZSelectedPoints)r  rj   Zselect_enclosed_pointsr&  r|   Úbool)ré   rX   r&  r‹   r3   r3   r4   r+  Ž  s    z_CheckInside._call_pyvistac                 C   s
  t |ƒ}tt t t|dƒ¡¡ƒ}t |t¡}t |¡}| j	d k	�r"tj
j|| j dd�}|| j	k }| ¡ }	t|	ƒ |¡}
t d|
› d|› dt|	dƒ› dd	| j	 d
›d�	¡ || jk}d||< | ¡ }	t|	ƒ |¡}
t d|
› d|› dt|	dƒ› dd	| j d
›d�	¡ | | @ }|| }|| }| j |¡dk }t|ƒ}	d||| < ||  }||  }t|	ƒ |¡}
tt |ƒƒ |¡}t d|
› d|› dt|	dƒ› d�¡ t|| j|ƒ}t |¡}	t|	ƒ |¡}
tt |ƒƒ |¡}t d|
› d|› dt|	dƒ› d�¡ d||| < |S )Né
   rV   rr   z
    Found r*  r(  r)  z& inside  an interior sphere of radius r  z6.1fz mmFz& outside an exterior sphere of radius r   z outside using surface Qhullz outside using solid angles)rc   r}   ra   ÚceilÚlog10rf   r©   r0  r¨   r   rÄ   rå   r!  r{   r:   Úrjustr   rE   r)   r%  r"  r#  r  rF   )ré   rX   r  r-  Úprecr.  rœ   rï   Zin_maskrß   Zn_padZout_maskræ   Zdel_outsideZ	check_padZsolid_outsider3   r3   r4   r,  “  sR    

*ÿ
*ÿ

ÿ
ÿz_CheckInside._call_old)NN)rñ   rò   ró   rô   r   rë   r  r  r/  r+  r,  r3   r3   r3   r4   r  W  s   r  c                 C   s(   t  | dd¡\}}}|d> |d>  | S )zRead 3 bytes and adjust.ú>u1rN   é   é   )ra   Úfromfile)ÚfobjÚb1Úb2Úb3r3   r3   r4   Ú_fread3Ê  s    r>  c                 C   s>   t  | dd| ¡ dd¡ t j¡j\}}}|d> |d>  | S )z1Read 3-byte ints from an open binary file object.r6  rN   rV   r7  r8  )ra   r9  r  r|   Úint64ÚT)r:  rß   r;  r<  r=  r3   r3   r4   Ú_fread3_manyÐ  s    ÿ ÿÿrA  c              	   C   sˆ   t | dƒ�V}t|ƒ}|dkr>t |dd¡d }t |d|¡}n|}t|ƒ t |d|¡d }W 5 Q R X |r€d	t |dktj¡ S |S d
S )ak  Load in curvature values from the ?h.curv file.

    Parameters
    ----------
    filepath : str
        Input path to the .curv file.
    binary : bool
        Specify if the output array is to hold binary values. Defaults to True.

    Returns
    -------
    curv : array, shape=(n_vertices,)
        The curvature values loaded from the user given file.
    Úrbiÿÿÿ ú>i4rN   r   ú>f4z>i2éd   r	   N)Úopenr>  ra   r9  rb   r?  )ÚfilepathÚbinaryr:  ÚmagicÚvnumZcurvr3   r3   r4   Úread_curvature×  s    rK  Úautoc                 C   s¢   t | ddƒ} td|dddgƒ |dkrJt | ¡\}}| ¡ dkrFd}nd}|dkrbtƒ | |d�}n |dkr‚t| ƒ}|r‚|tƒ f7 }|rž|t|d	 |d
 ƒf7 }|S )aÀ  Load a Freesurfer surface mesh in triangular format.

    Parameters
    ----------
    fname : str
        The name of the file containing the surface.
    read_metadata : bool
        Read metadata as key-value pairs. Only works when reading a FreeSurfer
        surface file. For .obj files this dictionary will be empty.

        Valid keys:

            * 'head' : array of int
            * 'valid' : str
            * 'filename' : str
            * 'volume' : array of int, shape (3,)
            * 'voxelsize' : array of float, shape (3,)
            * 'xras' : array of float, shape (3,)
            * 'yras' : array of float, shape (3,)
            * 'zras' : array of float, shape (3,)
            * 'cras' : array of float, shape (3,)

        .. versionadded:: 0.13.0

    return_dict : bool
        If True, a dictionary with surface parameters is returned.
    file_format : 'auto' | 'freesurfer' | 'obj'
        File format to use. Can be 'freesurfer' to read a FreeSurfer surface
        file, or 'obj' to read a Wavefront .obj file (common format for
        importing in other software), or 'auto' to attempt to infer from the
        file name. Defaults to 'auto'.

        .. versionadded:: 0.21.0
    %(verbose)s

    Returns
    -------
    rr : array, shape=(n_vertices, 3)
        Coordinate points.
    tris : int array, shape=(n_faces, 3)
        Triangulation (each line contains indices for three points which
        together form a face).
    volume_info : dict-like
        If read_metadata is true, key-value pairs found in the geometry file.
    surf : dict
        The surface parameters. Only returned if ``return_dict`` is True.

    See Also
    --------
    write_surface
    read_tri
    ÚreadTÚfile_formatrL  Ú
freesurferÚobjú.obj)Úread_metadatar   r	   )	r   r    r=   ÚsplitextÚlowerr   Ú_read_wavefront_objrj   Ú_rr_tris_dict)rn   rR  Úreturn_dictrN  r   rÊ   ÚextÚretr3   r3   r4   Úread_surfaceõ  s     7rZ  c                 C   s   t | |t|ƒ|t| ƒd�S )N)rX   rY   rÍ   Úuse_trisra   )rj   rc   rW   r3   r3   r4   rV  B  s    rV  c                 C   s2   t | dd�d }|d  d  < |jtjd� |S )NT©rW  rt   rX   g     @�@©r[   )rZ  Úupdater   ZFIFFV_COORD_MRI)rn   rF   r3   r3   r4   Ú_read_mri_surfaceF  s    r_  c              	   C   sØ   g }g }t | ƒ�®}|D ]¢}| ¡ }t|ƒdks|d dkr<q| ¡ }|d dkrn| dd„ |dd… D ƒ¡ q|d dkrd	d„ |dd… D ƒ}t|ƒd
kr¤tdƒ‚| dd„ |D ƒ¡ qW 5 Q R X t |¡t |¡fS )a‚  Read a surface form a Wavefront .obj file.

    Parameters
    ----------
    fname : str
        Name of the .obj file to read.

    Returns
    -------
    coords : ndarray, shape (n_points, 3)
        The XYZ coordinates of each vertex.
    faces : ndarray, shape (n_faces, 3)
        For each face of the mesh, the integer indices of the vertices that
        make up the face.
    r   ú#rä   c                 S   s   g | ]}t |ƒ‘qS r3   ©Úfloat©rO   Úitemr3   r3   r4   rR   f  s     z'_read_wavefront_obj.<locals>.<listcomp>r	   NrÑ   c                 S   s   g | ]}t | d ¡d ƒ‘qS )r*  r   )r}   r_   rc  r3   r3   r4   rR   h  s     rN   zOnly triangle faces allowed.c                 S   s   g | ]}|d  ‘qS ©r	   r3   ©rO   rv   r3   r3   r4   rR   l  s     )rF  Ústriprc   r_   rÚ   rã   ra   rb   )rn   Úcoordsr  rÑ   Úliner_   Zdatr3   r3   r4   rU  M  s     
 rU  c              	      s^  t ƒ }t| dƒ�h}tj|ddd�d }|dkr>td|› d�ƒ‚tj|ddd�d }t d	d
ddg¡}tj|||d�‰ W 5 Q R X ‡ fdd„|j ¡ D ƒ}|d  d8  < tt	 
t	 | ¡t	 | ¡dd… d ¡ƒ\}}|}|d dk}	|d |	 }
tjt|ƒftd�}d||
< d|| < |||  d¡ }tdddgƒD ]\}}|| |	 ||
|f< �q4|||fS )a!  Load a FreeSurfer binary patch file.

    Parameters
    ----------
    fname : str
        The filename.

    Returns
    -------
    rrs : ndarray, shape (n_vertices, 3)
        The points.
    tris : ndarray, shape (n_tris, 3)
        The patches. Not all vertices will be present.
    r¯   rC  r	   )ÚdtypeÚcountr   rV   zincorrect version # z (not -1) found)ÚvertnorC  )r‰   ú>f)rŠ   rm  )r´   rm  c                    s   i | ]}|ˆ | “qS r3   r3   )rO   Úkey©Zrecsr3   r4   Ú
<dictcomp>‹  s      z_read_patch.<locals>.<dictcomp>rl  NrN   Úsphere©rj  Tç        r‰   rŠ   r´   )rj   rF  ra   r9  rã   rj  ÚfieldsÚkeysrZ  r=   r?   ÚdirnameÚbasenamer•   rc   r0  rh   rÙ   )rn   ÚpatchÚfidÚverr˜   rj  r   rY   Z	orig_trisZis_vertr›   ræ   Úiirn  r3   ro  r4   Ú_read_patchp  s2    
ÿ"ÿ
r|  c                 C   s8   ddl m} t t t¡dd¡}|||d|  dd�}|S )z3Return an icosahedral surface of the desired grade.r	   r6   rK   zicos.fif.gzi(#  F)Zs_idr   )r+   r7   r=   r?   rv  r`   )ZgradeZpatch_statsr7   Zico_file_nameÚicor3   r3   r4   Ú_get_ico_surface¢  s    ÿÿr~  r  c                 C   sP   t | ƒ\}}t|ƒ}t|ƒ}| ¡ }||9 }t|||||||t |t¡d�}|S )z2Return a surface structure instead of the details.)rX   ra   rY   r[  rÍ   Únuser™   Úinuse)Ú_tessellate_sphererc   rZ   rj   ra   r©   r}   )ÚlevelÚradrX   rY   ZnptrÍ   r™   Úsr3   r3   r4   Ú_tessellate_sphere_surf®  s     
ÿr…  c                 C   s    ||  }||| 7 }t |ƒ |S )zGet normalized midpoint.)r¾   )ZaiZbirX   r’   r3   r3   r4   Ú_norm_midptº  s    r†  c                 C   sè  t  dddgdddgdddgdddgdddgdddggt¡}t  dddgdddgdddgdddgdddgdddgdddgdddggt¡}| dk r˜tdƒ‚|d	d	…dddgf }td| ƒD �]p}t|d	d	…df |d	d	…df |ƒ}t|d	d	…df |d	d	…df |ƒ}t|d	d	…df |d	d	…df |ƒ}t  t|ƒt|ƒt|ƒt|ƒg¡}t  	|d |d ¡}t  	|d |d ¡}	t  	|d |d ¡}
t  
||||f¡}t  t j|d	d	…df |	|f t j|	|d	d	…df |
f t j||	|
f t j||
|d	d	…df f ft¡ dd¡}t  |t  |jd	d… ¡df¡}q¸|}t  |¡}d}t|ƒD ]ˆ\}}tdƒD ]t}|||  }t  |d	|… |¡}t  |d
k¡d }t|ƒdk�r¬|d |||f< n|||< ||||f< |d7 }�qV�qF|d	|…  ¡ }||fS )z'Create a tessellation of a unit sphere.r	   r   rV   r  rt   rN   é   zoct subdivision must be >= 1NgwJëÿï?)ra   rb   rb  r}   rD   r–   r†  Zcumsumrc   r¨   rg   r	  rÈ   r  rÉ   r„   Z
empty_likerÙ   Údotr×   rZ   )ZmylevelrX   rY   rÊ   r�   r‘   r’   ZlimsZaidxZbidxZcidxZrr_origZnnoderÓ   ZtriÚjZcoordZ
similarityrœ   r3   r3   r4   r�  Â  sl      þþ$   ÿÿ$$$"ýý ý"
r�  c                    s’  t | dd�d } |dk}t| |dd� |dkrNt | d t¡| d	< d
| d< �nº|dkrrt| |ƒ d
| d< | d= �n–t ||d|d ¡}t 	d| ¡ t |dd�d }t
|d ƒ |d | d krÈtdƒ‚t
|d ƒ t|d |d ƒ‰ tˆ ƒ}	t | d t¡| d	< t|	ƒD ]Î}
| d	 ˆ |
  �r–t| ˆ |
 ƒ}ˆ |
 }t t | d	 | ¡¡d }t|ƒdk�rrtd|
|	f ƒ‚n||d  ˆ |
< t 	d|ˆ |
 ¡ n0ˆ |
 dk �s¶ˆ |
 | d k�rÆtdˆ |
  ƒ‚d| d	 ˆ |
 < �q
t 	d¡ t ‡ fdd„|d D ƒtj¡| d< | d d
k	�r(t| d ƒ| d< nd| d< t | d	 ¡| d< t | d	 ¡d | d< t
| d ƒ}d| d	 |dk< t | d	 ¡| d< || d< | S )z=Load a surf and use the subdivided icosahedron to get points.Tr\  rV   ÚspacingF©rZ   rh   ra   r€  Nr[  rÕ   rF   z.spherezLoading geometry from %s...rX   zIMismatch between number of surface vertices, possible parcellation error?r   z*Could not find neighbor for vertex %d / %dzH    Source space vertex moved from %d to %d because of double occupationz†Map number out of range (%d), this is probably due to inconsistent surfaces. Parts of the FreeSurfer reconstruction need to be redone.z9Setting up the triangulation for the decimated surface...c                    s   g | ]}ˆ | ‘qS r3   r3   )rO   Zist©Úmmapr3   r4   rR   B  s     z(_create_surf_spacing.<locals>.<listcomp>rY   Znuse_trir  rl  r™   Zsubject_his_id)rZ  rk   ra   r©   r}   Ú_decimate_surface_spacingr=   r?   r   rE   r¾   rã   r½   rc   r•   r–   rÒ   r×   Zlogical_notrb   Zint32r{   )rF   Zhemir.   ÚstypeÚico_surfr0   rÛ   Z	surf_nameZ	from_surfZnmaprÓ   ÚneighÚwasÚindsÚsizesr3   rŒ  r4   Ú_create_surf_spacing  sj    

ÿ ÿ ý
ÿr•  c                 C   s¤  t |tƒst‚|dkst‚t d¡ t | d dt¡}t| d ƒD ]`}| d | }tt || ¡d || ƒ||< || |kr†d||< t 	|| || d ¡||< qB|dk�r|t| d d ddƒD ]J}| d | D ]8}t|| || d ƒ||< t|| || d ƒ||< qÒqÂt| d ƒD ]`}|| dk�r| d | }t 
|| dk¡}|d	k�r\d||< t 	|| || d ¡||< �qt | d t¡| d
< d| d
 |dk< | S )Nr   z    Decimating...ra   i'  rÕ   r	   rU   rV   rt   r€  )r9   r}   rƒ   r   rE   ra   r
  r–   r$  Úminimumr{   r•   )rF   rŠ  rv   rÓ   r‘  rß   r3   r3   r4   rŽ  S  s2    
 

 rŽ  Ú c                C   s<  t | |d�} td|dddgƒ |dkrJt | ¡\}}	|	 ¡ dkrFd}nd}|dk�r~zddl}
d	}W n tk
r|   d
}Y nX |rž|
jjj	| ||||d� dS t
| ¡ ƒdkr¶tdƒ‚t| dƒ�¶}| tddddƒ¡ d| dg}dd„ |D ƒ}| |¡ t
|ƒ}t
|ƒ}| td||ƒ¡ | tj|dd� ¡ ¡ | tj|dd� ¡ ¡ |dk	�rrt
|ƒdk�rr| t|ƒ¡ W 5 Q R X nº|dk�r8t| dƒ� }| ¡ D ]}| d|› d�¡ �qœ|D ]0}| d|d › d|d › d|d › d�¡ �qº|D ]<}| d|d d › d|d d › d|d d › d�¡ �qðW 5 Q R X dS ) aè  Write a triangular Freesurfer surface mesh.

    Accepts the same data format as is returned by read_surface().

    Parameters
    ----------
    fname : str
        File to write.
    coords : array, shape=(n_vertices, 3)
        Coordinate points.
    faces : int array, shape=(n_faces, 3)
        Triangulation (each line contains indices for three points which
        together form a face).
    create_stamp : str
        Comment that is written to the beginning of the file. Can not contain
        line breaks.
    volume_info : dict-like or None
        Key-value pairs to encode at the end of the file.
        Valid keys:

            * 'head' : array of int
            * 'valid' : str
            * 'filename' : str
            * 'volume' : array of int, shape (3,)
            * 'voxelsize' : array of float, shape (3,)
            * 'xras' : array of float, shape (3,)
            * 'yras' : array of float, shape (3,)
            * 'zras' : array of float, shape (3,)
            * 'cras' : array of float, shape (3,)

        .. versionadded:: 0.13.0
    file_format : 'auto' | 'freesurfer' | 'obj'
        File format to use. Can be 'freesurfer' to write a FreeSurfer surface
        file, or 'obj' to write a Wavefront .obj file (common format for
        importing in other software), or 'auto' to attempt to infer from the
        file name. Defaults to 'auto'.

        .. versionadded:: 0.21.0
    %(overwrite)s
    %(verbose)s

    See Also
    --------
    read_surface
    read_tri
    )Ú	overwriterN  rL  rO  rP  rQ  r   NTF)Úcreate_stampÚvolume_infor	   z&create_stamp can only contain one lineÚwbz>3Béÿ   éþ   z%s
Ú
c                 S   s   g | ]}|  d ¡‘qS )zutf-8)Úencode)rO   r„  r3   r3   r4   rR   ¿  s     z!write_surface.<locals>.<listcomp>z>2irD  rr  rC  Úwz# zv r)  rt   zf )r   r    r=   rS  rT  Únibabelrÿ   rO  ÚioZwrite_geometryrc   Ú
splitlinesrD   rF  Úwriter   Ú
writelinesra   rb   Útobytesr   )rn   rh  r  r™  rš  rN  r˜  r   rÊ   rX  ÚnibZhas_nibabelry  ÚstrsrJ  Zfnumri  rä   rÑ   r3   r3   r4   Úwrite_surfaces  sR    1

þ

.r©  c              	   C   sŒ  z<ddl m}m} ddlm}m} ddlm} ddlm	} W n t
k
rX   tdƒ‚Y nX | ¡ t| ƒd krvtdƒ‚|ƒ }	|ƒ }
tjd	d
��& t d¡ |
 ||  tj¡ƒ¡ W 5 Q R X |	 |
¡ |ƒ }tj|dddd�}tjd	d
��$ t d¡ || ¡  tj¡ƒ}W 5 Q R X | |jd |¡ |	 |¡ |ƒ }| ¡  | |	¡ dt|ƒt|ƒ  }| |¡ |  ¡  t!| "¡ dd�}|d |d fS )zAux function.r   )Únumpy_to_vtkÚnumpy_to_vtkIdTypeArray)ÚvtkPolyDataÚvtkCellArray)Ú	vtkPoints)ÚvtkQuadricDecimationz6This function requires the VTK package to be installedr	   z@The triangles refer to undefined points. Please check your mesh.T)ÚrecordÚignore))r   r   )r	   r   ZconstantrN   )Zconstant_valuesF©r  rX   rY   )#Úvtkmodules.util.numpy_supportrª  r«  Úvtkmodules.vtkCommonDataModelr¬  r­  Zvtkmodules.vtkCommonCorer®  Úvtkmodules.vtkFiltersCorer¯  rÿ   rD   rf   rc   ÚwarningsÚcatch_warningsÚsimplefilterZSetDatar|   ra   Úfloat64Z	SetPointsÚpadr¦   r?  ZSetCellsr„   ZSetPolysZVolumePreservationOnÚSetInputDatarb  ZSetTargetReductionÚUpdater  Ú	GetOutput)r  r  Ún_trianglesrª  r«  r¬  r­  r®  r¯  ÚsrcZ	vtkpointsZvtkcellsZ
triangles_ZidarrZdecimateZ	reductionr‹   r3   r3   r4   Ú_decimate_surface_vtkØ  sF    
 
   ÿ



rÀ  c                 C   sð  t ƒ  i }ddddddg}| dd„ t|ƒD ƒ¡ d	d	t d
¡ d  }| dd„ t|dƒD ƒ¡ td|t|ƒdd� ttt	d�}|| \}}t
 d||f ¡ || |ƒ}	t|	d ƒ|ksÀt‚tƒ }
t |
d¡}t|| |ƒ t
 d¡ td||gdd� t
 d¡ |d }tdd||gdd� t
 d¡ |d }tdd ||gdd� t
 d!¡ |d" }td#d$||gdd� t|ƒ\}}tjj|dd%d&�}|| }t||	d' d(d)�}t|ƒtt |¡ƒ }|�rÖtd*||t|ƒf ƒ‚t
 d+¡ | | |	d fS ),Né   éP   i@  i   i   i P  c                 S   s   i | ]\}}|d |f“qS )r}  r3   ©rO   r{  Zn_trir3   r3   r4   rp    s      z,_decimate_surface_sphere.<locals>.<dictcomp>rt   é   rN   c                 S   s   i | ]\}}|d |f“qS )Úoctr3   rÃ  r3   r3   r4   rp    s      r	   r¾  z when method="sphere")Úextra)r}  rÅ  z7Decimating using Freesurfer spherical %s%s downsamplingrY   zlh.tempz&    Extracting main mesh component ...Zmris_extract_main_componentÚerrorrL   z    Smoothing ...z.smoothZmris_smoothz-nwz    Inflating ...z	.inflatedZmris_inflatez-no-save-sulcz    Sphere ...z.qsphereZmris_spherez-qT)rs   ZkeepdimsrX   rþ   rö   zJCould not reduce to %d triangles using ico, %d/%d vertices were duplicatesz[done])r$   r^  rÙ   ra   r¨   r    rC   rj   r~  r…  r   rE   rc   rƒ   r"   r=   r?   r©  r#   rZ  rÄ   rå   r½   rd   rã   )rX   rY   r¾  Zmap_Z
ico_levelsZ
oct_levelsZfunc_mapÚkindr‚  r�  ÚtempdirÚorigÚsmoothZinflatedZqsphereZ	sphere_rrrÊ   Znormsrœ   Zn_dupr3   r3   r4   Ú_decimate_surface_sphere  sj    ÿÿ
þ

þ

þ

 ÿþ
rÌ  Úquadricc                C   sT   t |ƒ}tttd�}td|t|ƒƒ |t|ƒkrDtd|t|ƒf ƒ‚|| | ||ƒS )a§  Decimate surface data.

    Parameters
    ----------
    points : ndarray
        The surface to be decimated, a 3 x number of points array.
    triangles : ndarray
        The surface to be decimated, a 3 x number of triangles array.
    n_triangles : int
        The desired number of triangles.
    method : str
        Can be "quadric" or "sphere". "sphere" will inflate the surface to a
        sphere using Freesurfer and downsample to an icosahedral or
        octahedral mesh.

        .. versionadded:: 0.20
    %(verbose)s

    Returns
    -------
    points : ndarray
        The decimated points.
    triangles : ndarray
        The decimated triangles.

    Notes
    -----
    **"quadric" mode**

    This requires VTK. If an odd target number was requested,
    the ``'decimation'`` algorithm used results in the
    next even number of triangles. For example a reduction request
    to 30001 triangles may result in 30000 triangles.

    **"sphere" mode**

    This requires Freesurfer to be installed and available in the
    environment. The destination number of triangles must be one of
    ``[20, 80, 320, 1280, 5120, 20480]`` for ico (0-5) downsampling or one of
    ``[8, 32, 128, 512, 2048, 8192, 32768]`` for oct (1-7) downsampling.

    This mode is slower, but could be more suitable for decimating meshes for
    BEM creation (recommended ``n_triangles=5120``) due to better topological
    property preservation.
    )rÍ  rq  r¿   zDRequested n_triangles (%s) exceeds number of original triangles (%s))r!   rj   rÀ  rÌ  r    rC   rc   rD   )r  r  r¾  r¿   r   Z
method_mapr3   r3   r4   Údecimate_surface2  s    0ÿ
þrÎ  c                 C   sR   | | }|| }	|| | }
|
|	|	 | 7 }
|
||	 | 7 }
|
|| 7 }
t  |
¡S )z$Get the distance to a triangle edge.)ra   Úsqrt)ÚpÚqÚp0Úq0r�   r‘   r’   ÚdistÚp1Úq1r‹   r3   r3   r4   Ú_get_tri_distp  s    r×  c                 C   sD  | d | d dd…df dd…f }| d | d dd…df dd…f | }| d | d dd…df dd…f | }t  t  ||g¡ dd¡¡}t  d||¡}t  d||¡}t  d||¡}t  t  t  || g| |gg¡d¡¡}|| ||  }	d|	|	dk< ||	dd…t jt jf  }t||ƒ}
t|
ƒ t	|||||||||
d	�	S )
z=Create supplementary geometry information using tris and rrs.rX   rY   Nr   r	   rt   zij,ij->ir  )	r±   r²   r³   Úr1213r�   r‘   r’   Úmatr™   )
ra   Úascontiguousarrayrb   rÈ   r¼   ZrollaxisrÇ   rŒ   r¾   rj   )rF   r±   r²   r³   rØ  r�   r‘   r’   rÙ  rå   r™   r3   r3   r4   rº   |  s(    $(((

    ÿrº   )r  c           +      C   s  t  t| ƒdf¡}t  t| ƒt j¡}tt| ƒƒD �]Æ}t  | | d¡}|||d … \}}||  krndkrŒn n|| }|}|}|
}d}n4|||… }|||  }|| }|| }|
| }d}t  t|ƒt j¡}t  t|ƒdf¡}t  t|ƒ¡}t j}t  d¡t  d¡t  d¡  }}} d}!t	t|ƒƒD ]Â}"t  
||" t  
||" ||" ¡¡||"< t  
||" ||" ¡||"< ||" \}#}$|#dk�r*|$dk�r*|#d	k�r*|$d	k�r*|#|$ d	k �r*d}!d||"< t  ||" ¡t  |¡k �r*|#|$|"||" f\}}} }�q*|!�r|�r||  } |!�r|�r’t  |¡d }%|�r4||%  t j¡}&n|% t j¡}&t|&|d ||% ||% |||ƒ\}#}$}'}(t  |(¡t  |¡k �r’|#|$|'|(f\}}} }d	| | ||f})|�rèt|d | ||||	|||ƒ	}*d|*d  |*d	  |*d |*d	 f})|)||< | ||< q0||fS )
zäFind nearest point mapping to a set of triangles.

    If run_all is False, if the point lies within a triangle, it stops.
    If run_all is True, edges of other triangles are checked in case
    those (somehow) are closer.
    rN   )r	   rN   rt   r   FTrs  r  r	   )ra   r†   rc   r?  r   r  r©   Úinfr¹  r–   rˆ  r  r×   r|   Ú_nearest_tri_edger·   )+r   Zpt_trissrÁ   r�   r‘   r’   r™   r±   r²   r³   rØ  rÙ  Zrun_allr¹   r”   Ztri_idxÚrirX   r¢   r£   Zdrsr—   ZmatsZr1213sZreindexrÀ   ZuseÚpqsrï   rÔ  rÐ  rÑ  ÚptÚfoundr{  ÚppÚqqr„  Zuse_pt_trisZpttZdisttr   rh  r3   r3   r4   r»   �  sr    "$6      ÿ"
r»   c              	   C   s¢  ||  }||  }||  }	|dd…df }
|dd…df }t  t  |
d||	  |  d¡d¡}t  |¡}dd| |	 d|
  d| |	 |   || |	  }t  t  |d¡d¡}d| }|}t  t  |d|
|	  |  d¡d¡}t  |¡}t|
||||||	|ƒ}t|
||||||	|ƒ}t|
||||||	|ƒ}t  |||f¡}
t  |||f¡}t  |||f¡}t  t  |¡¡}|
| || | |t| ƒ  || f\}}}}||||fS )zDGet nearest location from a point to the edge of a set of triangles.Nr   r	   ç      à?rs  r  rU   )	ra   r–  ÚmaximumZ
zeros_liker×  rg   rí   r  rc   )rÀ   Zto_ptrÞ  rÔ  r�   r‘   r’   ZaaZbbÚccrá  râ  rÒ  rÓ  Út1rÕ  rÖ  Úq2Zp2Zdist0Zdist1Zdist2rï   r{  rÐ  rÑ  rß  r3   r3   r4   rÜ  ã  s4    $
ÿ
ÿ$
,rÜ  c                 C   s   t | ƒ} t| d�S )z÷Return sparse matrix with edges as an adjacency matrix.

    Parameters
    ----------
    tris : array of shape [n_triangles x 3]
        The triangles.

    Returns
    -------
    edges : scipy.sparse.spmatrix
        The adjacency matrix.
    ©rY   )r%   Ú_mesh_edgesrè  r3   r3   r4   Ú
mesh_edges  s    rê  r1  )Úmaxsizec           
      C   s¦   ddl m} t | ¡tt | ¡ƒkr,tdƒ‚t | ¡d }t dt| ƒ ¡}| j\}}}t 	|||f¡}t 	|||f¡}||||ff||fd�}	|	 
¡ }	|	|	j }	|	S )Nr   rž   z5Cannot compute adjacency on a selection of triangles.r	   rN   r    )r¥   rŸ   ra   rf   rc   rd   rD   r©   r@  rg   rª   )
rY   rŸ   ZnpointsZ
ones_ntrisr�   r‘   r’   r‰   rŠ   Úedgesr3   r3   r4   ré    s    ÿ
ré  c                 C   sf   ddl m} t| ƒ ¡ }tjj||jdd…f ||jdd…f  dd�}|||j|jff|j	d�}|S )a´  Compute adjacency matrix weighted by distances.

    It generates an adjacency matrix where the entries are the distances
    between neighboring vertices.

    Parameters
    ----------
    tris : array (n_tris x 3)
        Mesh triangulation.
    vert : array (n_vert x 3)
        Vertex locations.

    Returns
    -------
    dist_matrix : scipy.sparse.csr_matrix
        Sparse matrix with distances between adjacent vertices.
    r   )Ú
csr_matrixNr	   rr   r    )
r¥   rí  rê  Útocoora   rÄ   rå   ÚrowÚcolr„   )rY   Zvertrí  rì  rÔ  Zdist_matrixr3   r3   r4   Ú	mesh_dist+  s
    0rñ  c           
   	      s2  t | dƒ�}| ¡ }W 5 Q R X t|d ƒ}t||d  ƒ}t|d  ¡ ƒ}|dkr\tdƒ‰ n|dkrptddƒ‰ ntdƒ‚t ‡ fd	d
„|d|d … D ƒ¡}t ‡ fdd
„||d |d | … D ƒ¡}	|rð|	dd…ddgf |	dd…ddgf< |	d8 }	t	 
d| ||f ¡ |dk�r"t	 
d¡ ntdƒ ||	fS )ax  Read triangle definitions from an ascii file.

    Parameters
    ----------
    fname_in : str
        Path to surface ASCII file (ending with '.tri').
    swap : bool
        Assume the ASCII file vertex ordering is clockwise instead of
        counterclockwise.
    %(verbose)s

    Returns
    -------
    rr : array, shape=(n_vertices, 3)
        Coordinate points.
    tris : int array, shape=(n_faces, 3)
        Triangulation (each line contains indices for three points which
        together form a face).

    See Also
    --------
    read_surface
    write_surface

    Notes
    -----
    .. versionadded:: 0.13.0
    r¯   r   r	   )rN   é   é   é   rN   )r  rÄ  r  zUnrecognized format of data.c                    s(   g | ] }t  d d„ | ¡ D ƒ¡ˆ  ‘qS )c                 S   s   g | ]}t |ƒ‘qS r3   ra  ©rO   rä   r3   r3   r4   rR   o  s     ú'read_tri.<locals>.<listcomp>.<listcomp>©ra   rb   r_   ©rO   ri  ©r“  r3   r4   rR   o  s   ÿzread_tri.<locals>.<listcomp>c                    s(   g | ] }t  d d„ | ¡ D ƒ¡ˆ  ‘qS )c                 S   s   g | ]}t |ƒ‘qS r3   )r}   rõ  r3   r3   r4   rR   q  s     rö  r÷  rø  rù  r3   r4   rR   q  s   ÿrt   Nz6Loaded surface from %s with %s nodes and %s triangles.)rN   r  z2Node normals were not included in the source file.zNode normals were not read.)rF  Ú	readlinesr}   rc   r_   r–   rB   ra   rb   r   rE   r   )
Zfname_inZswapr   ry  ÚlinesZn_nodesZn_trisZn_itemsrX   rY   r3   rù  r4   Úread_triF  s4    
ÿÿ$ÿ
rü  c                 C   s*  t  t|ƒ¡}tt| ƒƒD �]}| | }||d  }||d  }||d  }t  |jd df¡}t|||ƒ t j|| dd�}	t  t j|| dd�¡}
t  t j|| dd�¡}t  t j|| dd�¡}|
| | t j|| dd�|  t j|| dd�|  t j|| dd�|
  }|t  	|	|¡8 }q|S )z.Compute _sum_solids_div total angle in chunks.r   r	   rt   rN   rr   )
ra   r•   rc   r–   r†   r„   rˆ   r{   rÏ  Zarctan2)Ztri_rrsZfrosZ	tot_angleÚtiZtri_rrrµ   r¶   Zv3Zv4ZtripleÚl1Úl2Úl3r„  r3   r3   r4   r    s*    
ÿþýr  c                 C   sT   | d | d }| d }t ||d�}|d  |7  < |rDt|dd� | d |d< |S )	z*Convert sphere conductor model to surface.Zlayersrƒ  Úr0)rƒ  rX   Fr‹  r[   )r…  rk   )rq  rœ   r‚  Zcompleterƒ  r  rF   r3   r3   r4   Ú_complete_sphere_surf—  s    r  c                 C   s`   ddl m} t|d||d�d }	t|ddd�d	 }t||	ƒ}	|| ||d
�}
t|	|
dd�d }|S )añ  Compute distances between head shape points and the scalp surface.

    This function is useful to check that coregistration is correct.
    Unless outliers are present in the head shape points,
    one can assume an average distance around 2-3 mm.

    Parameters
    ----------
    %(info_not_none)s Must contain the head shape points in ``info['dig']``.
    trans : str | instance of Transform
        The head<->MRI transform. If str is passed it is the
        path to file on disk.
    subject : str
        The name of the subject.
    subjects_dir : str | None
        Directory containing subjects data. If None use
        the Freesurfer SUBJECTS_DIR environment variable.
    %(dig_kinds)s
    %(exclude_frontal)s
        Default is False.
    %(on_defects)s

        .. versionadded:: 1.0
    %(verbose)s

    Returns
    -------
    dists : array, shape (n_points,)
        The distances.

    See Also
    --------
    mne.bem.get_fitting_dig

    Notes
    -----
    .. versionadded:: 0.19
    r	   )Úget_fitting_dig)z
head-denser,   r+   )r0   r1   rX   r]   r,   )ZfroÚtor   )Úexclude_frontalT)rø   )r+   r  r5   r   r   r½   )rE   rl   r.   r0   Z	dig_kindsr  r1   r   r  ZptsZinfo_digrï   r3   r3   r4   Údig_mri_distances£  s     * ÿÿ
  ÿr  c                 C   sN   t |tjƒr|jdkst‚t| ƒ}| ¡ }||j ||j k}t 	|j| ¡S )Nr	   )
r9   ra   Zndarrayr‚   rƒ   rê  rî  rï  rð  rd   )rY   ræ   rì  Zborder_edgesr3   r3   r4   Ú_mesh_bordersØ  s
    r  c              	   C   s¼  ddl m}m} ddlm} ddlm} ddlm} ddl	m
}	m}
 ddlm} | jdkrjtd	| j› �ƒ‚t |¡}|jd
ks”|jdks”|jjdkr¶td|j› d|j› d|j› d�ƒ‚|dk	rö|  ¡ } |D ]*}| |k}| dk}||||d�}|| |< qÊ| j}|
|  ¡  t¡dd�}~ |ƒ }|ƒ }| |¡ | d
d
d
g¡ | dddg¡ | ¡  |¡ |  t!|ƒ¡ t"|ƒD ]\}}| #||¡ �qn| $|¡ | %¡  t&| '¡ |ƒ}|ƒ }| $|¡ |ƒ }| (ddd|j)|j*¡ |ƒ }| +| ,¡ ¡ t-ƒ }|D ]Æ}z
|j. W n" t/k
�r    | 0||¡ Y nX | .|¡ | 1|¡ | %¡  | '¡ }|	| 2¡  3¡ ƒ}|	| 4¡  5¡ ƒ 6dd¡}t 7|dd…ddd…f ¡}t 7|dd…ddd…f ¡}| 8||f¡ �qð|S )z%Compute marching cubes on a 3D image.r   )ÚvtkImageDataÚvtkDataSetAttributes)ÚvtkThreshold)ÚvtkDiscreteFlyingEdges3D)ÚvtkGeometryFilter)Úvtk_to_numpyrª  )Úbinary_dilationrN   z3D data must be supplied, got r	   Zuiz=level must be non-empty numeric or 1D array-like of int, got zD array-like of z with z	 elementsN)Z
iterationsræ   T)ÚdeeprV   )9r´  r  r	  rµ  r
  Zvtkmodules.vtkFiltersGeneralr  Zvtkmodules.vtkFiltersGeometryr  r³  r  rª  Zscipy.ndimager  r‚   rD   r„   ra   rb   r…   rj  rÈ  r;   rZ   r¦   r|   rb  ZSetDimensionsZ
SetSpacingZ	SetOriginZGetPointDataZ
SetScalarsZSetNumberOfContoursrc   rÙ   ZSetValuer»  r¼  Ú_vtk_smoothr½  ZSetInputArrayToProcessZFIELD_ASSOCIATION_POINTSZSCALARSZSetInputConnectionZGetOutputPortrØ   ZSetLowerThresholdÚAttributeErrorZThresholdBetweenZSetUpperThresholdZ	GetPointsZGetDataZGetPolysZGetConnectivityArrayr  rÚ  rÚ   )Úimager‚  rË  Zfill_hole_sizer  r	  r
  r  r  r  rª  r  ÚvalZ	bin_imageræ   Zimage_shapeZdata_vtkZmcZimdataZliZlevÚselectorZdsaZgeometryr‹   ZpolydatarX   rY   r3   r3   r4   Ú_marching_cubesà  sŒ    

 ÿÿ



    ÿ



ÿ ÿr  c                 C   sð   t |d|ƒ t|ƒ}d|  kr(dk s8n td|› �ƒ‚|dkrD| S ddlm} t d|› �¡ d}t| tƒrzt	| ƒ} d}|ƒ }| 
| ¡ | d	¡ | ¡  | ¡  | d
¡ | d| ¡ | ¡  | ¡  | ¡  | ¡ }|rìt|dd�}|S )NÚnumericr   r	   zFsmoothing factor must be between 0 (inclusive) and 1 (exclusive), got )ÚvtkWindowedSincPolyDataFilterz    Smoothing by a factor of FTrE  g      ^@r²  )r'   rb  rD   rµ  r  r   rE   r9   rj   r  r»  ZSetNumberOfIterationsZBoundarySmoothingOffZFeatureEdgeSmoothingOffZSetFeatureAngleZSetPassBandZNonManifoldSmoothingOnZNormalizeCoordinatesOffr¼  r½  r  )r  rË  r  Zreturn_ndarrayZsmootherr‹   r3   r3   r4   r  7  s4    



r  c                    s�   t t dtˆ jƒd ¡ƒ t t t |j¡¡ƒ¡}‡ fdd„|D ƒ}|rŒ|dkrŒt	dt
|ƒ› dd dd	„ |D ƒ¡› d
�|r„d|› �nd ƒ dS )zWarn that channels are missing.r	   c                    s   g | ]}ˆ j |d   ‘qS re  )Úch_names©rO   rœ   rQ   r3   r4   rR   Z  s     z%_warn_missing_chs.<locals>.<listcomp>rÇ  ZChannelr)  rÎ   c                 s   s   | ]}t |ƒV  qd S ru   )Úrepr)rO   Úchr3   r3   r4   rÐ   \  s     z$_warn_missing_chs.<locals>.<genexpr>z not assigned voxels z after applying r—  N)rà   ra   r¨   rc   r  Ú
differencerd   rb   Údataobjr   r)   r?   )rE   Z	dig_imageÚ
after_warpr   ÚmissingZ
missing_chr3   rQ   r4   Ú_warn_missing_chsU  s    ÿ&ýr   Ú	fsaveragerã  rE  c           $         sp  t dddƒ t dddƒ ddlm}m} ddlm} d	d
l}t| |dƒ t||jj	dƒ t|t
dƒ |d	k st|dkr‚td|› �ƒ‚t|	tdƒ t|
tdƒ t|tdƒ |||ƒ |d
kr¼|}|||ƒ t||jj	ƒsÞ| |¡}| t ||dd¡¡}tj|j|jdd��stdƒ‚|  ¡ ‰ ˆ d dk�r`t dd„ | jD ƒ¡}d dd„ |D ƒ¡}td|› �ƒ‚tˆ d  ¡ ƒ}t ‡ fdd„|D ƒ¡}ttj |j  ¡ ¡|d ƒ}t |j!¡}|�r¾|d 9 }tj"|j#td!�}t$|ƒD ]¦\}}t %|¡ &¡ �rò�qÖt'||||	|
d"�}|D ]p}|| d	k�rjt (||| d  | d# ¡ )¡ }t (|| d# ¡ )¡ }||k �rv|d ||< n|d ||< �q�qÖ|j 	||j¡}t*| |d$d%� | t ||dd¡¡}t+||||d&d'�}|d
k	�rÒd(nd)}t*| ||d%� t ,|j!¡} t$|dƒD ]*\}!}tj-t .| |!k¡dd*�|d
d
…< �qú| t ||dd¡¡}"t|"j  ¡ |ƒd }|t/t0||ƒƒdd+�}#|#||fS ),az
  Warp a montage to a template with image volumes using SDR.

    Find areas of the input volume with intensity greater than
    a threshold surrounding local extrema near the channel location.
    Monotonicity from the peak is enforced to prevent channels
    bleeding into each other.

    .. note:: This is likely only applicable for channels inside the brain
              (intracranial electrodes).

    Parameters
    ----------
    montage : instance of mne.channels.DigMontage
        The montage object containing the channels.
    base_image : path-like | nibabel.spatialimages.SpatialImage
        Path to a volumetric scan (e.g. CT) of the subject. Can be in any
        format readable by nibabel. Can also be a nibabel image object.
        Local extrema (max or min) should be nearby montage channel locations.
    %(reg_affine)s
    %(sdr_morph)s
    subject_from : str
        The name of the subject used for the Freesurfer reconstruction.
    subject_to : str
        The name of the subject to use as a template to morph to
        (e.g. 'fsaverage').
    subjects_dir_from : path-like | None
        The path to the Freesurfer ``recon-all`` directory for the
        ``subject_from`` subject. The ``SUBJECTS_DIR`` environment
        variable will be used when ``None``.
    subjects_dir_to : path-like | None
        The path to the Freesurfer ``recon-all`` directory for the
        ``subject_to`` subject. ``subject_dir_from`` will be used
        when ``None``.
    thresh : float
        The threshold relative to the peak to determine the size
        of the sensors on the volume.
    max_peak_dist : int
        The number of voxels away from the channel location to
        look in the ``image``. This will depend on the accuracy of
        the channel locations, the default (one voxel in all directions)
        will work only with localizations that are that accurate.
    voxels_max : int
        The maximum number of voxels for each channel.
    use_min : bool
        Whether to hypointensities in the volume as channel locations.
        Default False uses hyperintensities.
    %(verbose)s

    Returns
    -------
    montage_warped : mne.channels.DigMontage
        The modified montage object containing the channels.
    image_from : nibabel.spatialimages.SpatialImage
        An image in Freesurfer surface RAS space with voxel values
        corresponding to the index of the channel. The background
        is 0s and this index starts at 1.
    image_to : nibabel.spatialimages.SpatialImage
        The warped image with voxel values corresponding to the index
        of the channel. The background is 0s and this index starts at 1.
    r¡  z	SDR morphz2.1.0Zdipyz0.10.1r	   )Ú
DigMontageÚmake_dig_montage)Ú_check_subject_dirr   NÚmontageÚ
base_imageÚthreshz&`thresh` must be between 0 and 1, got Úmax_peak_distÚ
voxels_maxÚuse_minr]   z	brain.mgzg�íµ ÷Æ°>)Zatolz«The `base_image` is not aligned to Freesurfer surface RAS space. This space is required as it is the space where the anatomical segmentation and reconstructed surfaces arer[   c                 S   s   g | ]}|d  ‘qS r]  r3   rf  r3   r3   r4   rR   Ç  s     z'warp_montage_volume.<locals>.<listcomp>rÎ   c                 S   s$   g | ]}|t krt | nt|ƒ‘qS r3   )r   r:   )rO   Úcfr3   r3   r4   rR   È  s   ÿú4Coordinate frame not supported, expected "mri", got Úch_posc                    s   g | ]}ˆ d  | ‘qS )r-  r3   )rO   Úname©Úch_dictr3   r4   rR   Î  s     r  rV   rr  )r'  r(  r)  rt   F)r  rî   )ÚinterpolationzSDR warpzaffine transformationrr   r]  )1r(   Úchannelsr"  r#  Ú_freesurferr$  r¡  r'   ZspatialimagesZSpatialImagerb  rD   r}   r0  r9   Úloadr=   r?   ra   ZallcloseZaffinerã   Úget_positionsrd   ÚdigrØ   ru  rb   r   rÄ   ÚinvÚheaderÚget_vox2ras_tkrr  r•   r„   rÙ   ÚisnanÚanyÚ_voxel_neighborsrÏ  r{   r   r   Z
asanyarrayrx   r×   rj   r~   )$r%  r&  Z
reg_affineZ	sdr_morphZsubject_fromZ
subject_toZsubjects_dir_fromZsubjects_dir_tor'  r(  r)  r*  r   r"  r#  r$  r§  Zfs_from_imgZbad_coord_framesr  Ú	ch_coordsZ
image_dataZ
image_fromÚiÚch_coordÚvolumeÚvoxelZdist_oldZdist_newZtemplate_brainZimage_tor  Zwarped_datar  Z	fs_to_imgZmontage_warpedr3   r/  r4   Úwarp_montage_volumeb  s²    B


ÿ
þ ÿþÿ
ÿ   þÿ$ÿ ÿÿ ÿrB  r  ú
aparc+asegrt   c                    s¨  ddl m} ddlm}m} t| |dƒ t|ttfdƒ |dk sH|dkrPtdƒ‚||||ƒ\}‰ |ƒ \}‰d	d
„ | 	¡ D ƒ‰t
‡fdd„t ˆ ¡D ƒƒsœt‚|j ¡ }	|  ¡ }
|
d dkrÎtdt|
d ƒ ƒ‚t t|
d  ¡ ƒ¡}ttj |j ¡ ¡|d ƒ}tƒ }t| j|ƒD ]d\}}t |¡ ¡ �r6tƒ ||< n>t|ˆ ||	td�}t ‡ fdd„|D ƒƒ}‡fdd„|D ƒ||< �qt dd„ | ¡ D ƒƒ}‡fdd
„|D ƒ}||fS )a,  Get regions of interest near channels from a Freesurfer parcellation.

    .. note:: This is applicable for channels inside the brain
              (intracranial electrodes).

    Parameters
    ----------
    %(montage)s
    %(subject)s
    %(subjects_dir)s
    %(aseg)s
    dist : float
        The distance in mm to use for identifying regions of interest.

    Returns
    -------
    labels : dict
        The regions of interest labels within ``dist`` of each channel.
    colors : dict
        The Freesurfer lookup table colors for the labels.
    r	   )r"  )Úread_freesurfer_lutÚ	_get_asegr%  rÔ  r   r1  z`dist` must be between 0 and 10c                 S   s   i | ]\}}||“qS r3   r3   )rO   rÓ   rä   r3   r3   r4   rp  6  s      z-get_montage_volume_labels.<locals>.<dictcomp>c                    s   g | ]}|ˆ k‘qS r3   r3   r  ©Ú	label_lutr3   r4   rR   9  s     z-get_montage_volume_labels.<locals>.<listcomp>r[   r]   r,  r-  r  )rÔ  Úvox2ras_tkrr)  c                    s   g | ]}ˆ t |ƒ  t¡‘qS r3   )Útupler|   r}   )rO   rA  )Ú	aseg_datar3   r4   rR   O  s   ÿc                    s   g | ]}ˆ | ‘qS r3   r3   r  rF  r3   r4   rR   Q  s     c                 S   s   g | ]}|D ]}|‘qqS r3   r3   )rO   r  Úlabelr3   r3   r4   rR   S  s       c                    s*   i | ]"}|t ˆ | d d… d ƒd “qS )NrN   rœ  )r  )rI  )rO   rK  )Ú	fs_colorsr3   r4   rp  T  s   ÿ )!r2  r"  r3  rD  rE  r'   r}   rb  rD   Úitemsrh   ra   rd   rƒ   r8  r9  r5  rã   r:   rb   rØ   Úvaluesr   rÄ   r7  r   r~   r  r:  r;  r<  Ú_VOXELS_MAXrà   )r%  r.   r0   ZasegrÔ  r"  rD  rE  ZlutrH  r0  r=  ÚlabelsZch_namer?  ÚvoxelsZ
label_idxsZ
all_labelsÚcolorsr3   )rJ  rL  rG  r4   Úget_montage_volume_labels  sR    
 

ÿ ÿ   þÿ
ÿrS  c                 C   sÒ   t ƒ }tt| ƒƒD ]º}dD ]°}t | ¡}||  |7  < |dk	r„|dksLt‚t|ƒ}|| |krÊ|| ||  k rÊ||krÊ| |¡ q|dks�t‚|\}	}
}t||d ƒ}tj	 
|
| ¡|	kr| t|ƒ¡ qq|S )z6Find all the neighbors above a threshold near a voxel.)rV   r	   Nrã  )rà   r–   rc   ra   rb   rƒ   rI  rá   r   rÄ   rå   )rM   r  rQ  r'  Údist_paramsÚ	neighborsrs   r>  Únext_locrÔ  Úseed_fs_rasrH  Znext_loc_fs_rasr3   r3   r4   Ú_get_neighborsY  s(    
ÿþ
rX  c                    s@  t  | ¡ ¡  t¡} |dk	|dk	 dks,t‚|dk	rœd}|t‡ fdd„| D ƒƒ }	t  t  t  |	¡|	j	¡¡ˆ  |  }
t
t|
ƒgƒ }}|rÒ||t|
ƒ 9 }n6|dk	s¨t‚t|| d ƒ}|||f}t
t| ƒgƒ }}|�r<t|ƒ|k�r<t
ƒ }|D ]D}t|||||ƒ}| |¡}| |¡}| |¡}t|ƒ|krð �q6qð|}qÒ|S )aŸ  Find voxels above a threshold contiguous with a seed location.

    Parameters
    ----------
    seed : tuple | ndarray
        The location in image coordinated to seed the algorithm.
    image : ndarray
        The image to search.
    thresh : float
        The threshold to use as a cutoff for what qualifies as a neighbor.
        Will be relative to the peak if ``use_relative`` or absolute if not.
    max_peak_dist : int
        The maximum number of voxels to search for the peak near
        the seed location.
    use_relative : bool
        If ``True``, the threshold will be relative to the peak, if
        ``False``, the threshold will be absolute.
    dist : float
        The distance in mm to include surrounding voxels.
    vox2ras_tkr : ndarray
        The voxel to surface RAS affine. Must not be None if ``dist``
        if not None.
    voxels_max : int
        The maximum size of the output ``voxels``.

    Returns
    -------
    voxels : set
        The set of locations including the ``seed`` voxel and
        surrounding that meet the criteria.

    .. note:: Either ``dist`` or ``thesh`` may be used but not both.
              When ``thresh`` is used, first a peak nearby the seed
              location is found and then voxels are only included if they
              decrease monotonically from the peak. When ``dist`` is used,
              only voxels within ``dist`` mm of the seed are included.
    Nr	   c                    s"   g | ]}t |ˆ  |ˆ  d  ƒ‘qS re  )Úslicer  ©r(  r3   r4   rR   ž  s   ÿz$_voxel_neighbors.<locals>.<listcomp>rã  )ra   rb   Úroundr|   r}   rƒ   rI  Zunravel_indexZargmaxr„   rà   r   rc   rX  r  Úunion)Úseedr  r'  r(  Zuse_relativerÔ  rH  r)  rT  Z
check_gridZpeakrQ  rU  rW  Znext_neighborsrV  Zvoxel_neighborsr3   rZ  r4   r<  r  sH    (þ
 ÿÿÿ
 ÿ


r<  )r*   Nr-   N)T)NN)FFr¸   )FTT)rõ   F)F)NN)T)T)FFrL  N)F)r  )r—  NrL  F)rÍ  )TF)N)FN)T)NrL  Fr-   N)r   N)N)r!  NNrã  r	   rE  FN)NrC  rt   )Nr	   TNNrE  )vrZ   r   Ú	functoolsr   r   Úcollectionsr   r   Úosr   r=   Ústructr   r  r¶  Únumpyra   Zchannels.channelsr
   Úfixesr   r   r   r   r   Zio.constantsr   Zio.pickr   r  r   Z
transformsr   r   r   r   r   r   r   r   Úutilsr   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r5   r2   rq   ri   rŒ   rˆ   r“   r�   r®   r·   rÂ   rÌ   rk   rÒ   r¾   Úobjectrç   r½   rý   r÷   r  r  r  r  r>  rA  rK  rZ  rV  r_  rU  r|  r~  r…  r†  r�  r•  rŽ  r©  rÀ  rÌ  rÎ  r×  rº   r»   rÜ  rê  ré  rñ  rü  r  r  r  r  r  r  r   rB  rO  rS  rX  r<  r3   r3   r3   r4   Ú<module>   s  (D	    ÿ" ÿ
3A#
	


  ÿ
  ÿÿK

&

s
    ÿL#2

NC     ÿÿd)1ÿ=
   þS
#8

       þ4
W
            ü ,    ÿG       þ