U
    f»{j·÷  ã                    @   sà  d Z ddlZddlmZ ddlZddlZddlm	Z	 ddl
mZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% e &ddddgddddgddddgddddgg¡Z'e(ej)ej*ej+ej,ej-ej.ej/ej0ej1ej2d�
Z3dd„ e3 4¡ D ƒZ5ej2dej)dej6dej7dej,dej*dej+dej8dej9dej1dej0dej.dej-dej:dej;dddiZ<dd „ Z=G d!d"„ d"e(ƒZ>d#d$„ Z?d d(d)„Z@d¡d*d+„ZAd¢d-d.„ZBd£d/d0„ZCd¤d1d2„ZDd3d4„ ZEd5d6„ ZFd¥d7d8„ZGd¦d9d:„ZHd§d<d=„ZId¨d>d?„ZJd@dA„ ZKed©dCdD„ƒZLedBddEœdFdG„ƒZMdHdI„ ZNdªdJdK„ZOdLdM„ ZPd«dNdO„ZQdPdQ„ ZRdRdS„ ZSdTdU„ ZTdVdW„ ZUdXdY„ ZVdZd[„ ZWd\d]„ ZXd^d_„ ZYd`da„ ZZG dbdc„ dce[ƒZ\ddde„ Z]G dfdg„ dge[ƒZ^dhdi„ Z_djdk„ Z`eƒ dldm„ ƒZaeƒ dndo„ ƒZbdpdq„ Zcdrds„ Zdd¬dtdu„Zedvdw„ Zfdxdy„ Zgdzd{„ Zhd|d}„ Zieƒ d­d~d„ƒZjd®d€d�„Zke!d¯d‚dƒ„ƒZld„d…„ Zmd†d‡„ Zndˆd‰„ ZodŠd‹„ ZpdŒZqd�dŽ„ Zrd�d�„ Zsd‘d’„ Ztd“d”„ Zud•d–„ Zved°d˜d™„ƒZwdšd›„ Zxed±dždŸ„ƒZydS )²z$Helpers for various transformations.é    N©Údeepcopyé   )ÚjitÚmeanÚ_get_img_fdata)ÚFIFF)Ú	fiff_open)Úread_tag)Ústart_and_end_fileÚwrite_coord_trans)Ú_handle_default)Úcheck_fnameÚloggerÚverboseÚ_ensure_intÚ_validate_typeÚ
_path_likeÚget_subjects_dirÚfill_docÚ_check_fnameÚ_check_optionÚ_require_versionÚwrapped_stdoutéÿÿÿÿ)
ÚmegÚmriZ	mri_voxelÚheadÚmni_talÚrasZfs_talZctf_headZctf_megÚunknownc                 C   s   i | ]\}}||“qS © r!   )Ú.0ÚkeyÚvalr!   r!   úM/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/transforms.pyÚ
<dictcomp>+   s      r&   r    z
MEG deviceZisotrakZhpir   zMRI (surface RAS)z	MRI voxelz	MRI slicezMRI displayzCTF MEG devicezCTF/4D/KIT headzRAS (non-zero origin)zMNI TalairachzTalairach (MNI z > 0)zTalairach (MNI z < 0)c                 C   sR   t | tƒr>| tkr4td| › d�d t ¡ ¡ d ƒ‚t|  } nt| ddƒ} t| ƒS )z+Convert string or int coord frame into int.zUnknown coordinate frame z, expected "z", "ú"zcoordinate frameza str or int)Ú
isinstanceÚstrÚ_str_to_frameÚ
ValueErrorÚjoinÚkeysr   Úint)Úcfr!   r!   r%   Ú	_to_const?   s    

ÿÿÿ
r0   c                       sf   e Zd ZdZd‡ fdd„	Zdd„ Zddd	„Zdd
d„Zedd„ ƒZ	edd„ ƒZ
dd„ Zdd„ Z‡  ZS )Ú	Transforma  A transform.

    Parameters
    ----------
    fro : str | int
        The starting coordinate frame. See notes for valid coordinate frames.
    to : str | int
        The ending coordinate frame. See notes for valid coordinate frames.
    trans : array-like, shape (4, 4) | None
        The transformation matrix. If None, an identity matrix will be
        used.

    Notes
    -----
    Valid coordinate frames are 'meg','mri','mri_voxel','head','mri_tal','ras'
    'fs_tal','ctf_head','ctf_meg','unknown'
    Nc                    st   t t| ƒ ¡  t|ƒ}t|ƒ}|d kr0t d¡nt |tj¡}|jdkrXt	d|j› �ƒ‚|| d< || d< || d< d S )Né   ©r2   r2   z(Transformation must be shape (4, 4) not ÚfromÚtoÚtrans)
Úsuperr1   Ú__init__r0   ÚnpÚeyeÚasarrayZfloat64Úshaper+   )ÚselfÚfror5   r6   ©Ú	__class__r!   r%   r8   _   s     

ÿzTransform.__init__c              
   C   sH   t jdd��2 djt| d ƒt| d ƒ| d d�W  5 Q R £ S Q R X d S )NT)Úsuppressz!<Transform | {fro}->{to}>
{trans}r4   r5   r6   )r>   r5   r6   )r9   ZprintoptionsÚformatÚ_coord_frame_name©r=   r!   r!   r%   Ú__repr__l   s    

 þzTransform.__repr__ç        c                 C   sD   t |tƒoB| d |d koB| d |d koBtj| d |d ||d�S )aS  Check for equality.

        Parameter
        ---------
        other : instance of Transform
            The other transform.
        rtol : float
            Relative tolerance.
        atol : float
            Absolute tolerance.

        Returns
        -------
        eq : bool
            True if the transforms are equal.
        r4   r5   r6   )ÚrtolÚatol)r(   r1   r9   Úallclose©r=   ÚotherrG   rH   r!   r!   r%   Ú__eq__r   s    
ÿþÿýzTransform.__eq__c                 C   s
   | |k S )aY  Check for inequality.

        Parameter
        ---------
        other : instance of Transform
            The other transform.
        rtol : float
            Relative tolerance.
        atol : float
            Absolute tolerance.

        Returns
        -------
        eq : bool
            True if the transforms are not equal.
        r!   rJ   r!   r!   r%   Ú__ne__‰   s    zTransform.__ne__c                 C   s   t | d ƒS )zThe "from" frame as a string.r4   ©rC   rD   r!   r!   r%   Úfrom_strœ   s    zTransform.from_strc                 C   s   t | d ƒS )zThe "to" frame as a string.r5   rN   rD   r!   r!   r%   Úto_str¡   s    zTransform.to_strc                 C   s   t || ƒ dS )z®Save the transform as -trans.fif file.

        Parameters
        ----------
        fname : str
            The name of the file, which should end in '-trans.fif'.
        N)Úwrite_trans)r=   Úfnamer!   r!   r%   Úsave¦   s    zTransform.savec                 C   s   t | ƒS )zMake a copy of the transform.r   rD   r!   r!   r%   Úcopy°   s    zTransform.copy)N)rF   rF   )rF   rF   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r8   rE   rL   rM   ÚpropertyrO   rP   rS   rT   Ú__classcell__r!   r!   r?   r%   r1   L   s   




r1   c                 C   s   t  t| ƒd¡S )z/Map integers to human-readable (verbose) names.r    )Ú_verbose_framesÚgetr.   )Zcframer!   r!   r%   rC   µ   s    rC   úCoordinate transformation: ÚmÚinfoc           	   	   C   sœ   t t|ƒ}||djt| d ƒt| d ƒd� ƒ t| d ƒD ]Z\}}|dkrX|dkrXdnd	}|dkrhd
nd}|d|d |d |d ||d  |f ƒ q<d S )Nz{fro} -> {to}r4   r5   ©r>   r5   r6   é   Úmmg     @�@ç      ð?ú mmÚ z#    % 8.6f % 8.6f % 8.6f    %7.2f%sr   r   é   )Úgetattrr   rB   rC   Ú	enumerate)	ÚtÚprefixZunitsÚlevelZlog_funcÚtiÚttÚscaleÚtextr!   r!   r%   Ú_print_coord_transº   s    

 
ÿ
 ÿrp   c                 C   s|   | d kr&dt jkrt jd } ntdƒ‚t t || d¡¡}t|ƒdk rXtdj| d�ƒ‚nt|ƒdkrttdj| d�ƒ‚|d S )	NZSUBJECTz$SUBJECT environment variable not setz*-trans.fifr   z/Could not find the transformation for {subject})Úsubjectz,Found multiple transformations for {subject}r   )	ÚosÚenvironr+   ÚglobÚopr,   ÚlenÚRuntimeErrorrB   )rq   Úsubjects_dirZtrans_fnamesr!   r!   r%   Ú_find_transÇ   s    
ÿ
ÿry   Tc                 C   sh   t | tƒr| d } t |¡}|jdkr.| ¡ S t || dd…dd…f j¡}|rd|| dd…df 7 }|S )a£  Apply a transform matrix to an array of points.

    Parameters
    ----------
    trans : array, shape = (4, 4) | instance of Transform
        Transform matrix.
    pts : array, shape = (3,) | (n, 3)
        Array with coordinates for one or n points.
    move : bool
        If True (default), apply translation.

    Returns
    -------
    transformed_pts : shape = (3,) | (n, 3)
        Transformed point(s).
    r6   r   Nra   )r(   Údictr9   r;   ÚsizerT   ÚdotÚT)r6   ÚptsÚmoveZout_ptsr!   r!   r%   Úapply_transØ   s    


r€   c           
      C   sÌ   t  | ¡}t  |¡}t  |¡}t  | ¡}t  |¡}t  |¡}t j|| | | || |  || || |  dg|| || || |  | | || |  dg| || || dgddddggtd�}	|	S )zïCreate an array with a 4 dimensional rotation matrix.

    Parameters
    ----------
    x, y, z : scalar
        Rotation around the origin (in rad).

    Returns
    -------
    r : array, shape = (4, 4)
        The rotation matrix.
    r   r   ©Údtype©r9   ÚcosÚsinÚarrayÚfloat©
ÚxÚyÚzZcos_xZcos_yZcos_zZsin_xZsin_yZsin_zÚrr!   r!   r%   Úrotationø   s(    





 ÿ ÿ
ûûr�   c           
      C   s¼   t  | ¡}t  |¡}t  |¡}t  | ¡}t  |¡}t  |¡}t j|| | | || |  || || |  g|| || || |  | | || |  g| || || ggtd�}	|	S )zïCreate an array with a 3 dimensional rotation matrix.

    Parameters
    ----------
    x, y, z : scalar
        Rotation around the origin (in rad).

    Returns
    -------
    r : array, shape = (3, 3)
        The rotation matrix.
    r�   rƒ   rˆ   r!   r!   r%   Ú
rotation3d  s"    





ÿÿüürŽ   c                 C   s–  | t j | ¡ } t  d¡}d| d  dk rDd|d< d|d< d|d< nèdd| d   }dd| | d	  | d	   |d< d| | d	  | d
  |d< | d	 |d< d| | d	  | d
  |d< dd| | d
  | d
   |d< | d
 |d< | d	  |d< | d
  |d< d|| d	 | d	  | d
 | d
     |d< t  | |j¡t  d¡ dk ¡�sRt‚t j 	|¡d dk �slt‚t j | | d	d	d
g¡ ¡dk �s’t‚|S )a,  Compute a rotation matrix to align [ 0 0 1] with supplied target z axis.

    Parameters
    ----------
    target_z_axis : array, shape (1, 3)
        z axis. computed matrix (r) will map [0 0 1] to target_z_axis

    Returns
    -------
    r : array, shape (3, 3)
        The rotation matrix.
    ©ra   ra   rc   rf   gê-�™—q=©r   r   ç      ð¿©r   r   ©rf   rf   r   r   ©r   r   ©r   rf   ©r   r   ©r   rf   ©rf   r   ©rf   r   ra   )
r9   ÚlinalgÚnormÚzerosÚanyr|   r}   ÚidentityÚAssertionErrorÚdet)Ztarget_z_axisrŒ   Úfr!   r!   r%   Úrotation3d_align_z_axis/  s,    

  ÿ&&r¢   c                 C   s–   t  | d | d ¡}t  | d d | d d  ¡}t  | d  |¡}t  |¡}t  |¡}t  || d  || d   || d	  || d
   ¡}|||fS )a  Find rotation angles from a transformation matrix.

    Parameters
    ----------
    m : array, shape >= (3, 3)
        Rotation matrix. Only the top left 3 x 3 partition is accessed.

    Returns
    -------
    x, y, z : float
        Rotation around x, y and z axes.
    r™   r“   r�   rf   r–   r˜   r•   r”   r’   r—   )r9   Úarctan2Úsqrtr…   r„   )r^   r‰   Úc2rŠ   Ús1Úc1r‹   r!   r!   r%   Úrotation_anglesX  s    

4r¨   c                 C   s:   t j| dddgd|ddgdd|dgddddggtd�}|S )zËCreate an array with a scaling matrix.

    Parameters
    ----------
    x, y, z : scalar
        Scaling factors.

    Returns
    -------
    s : array, shape = (4, 4)
        The scaling matrix.
    r   r   r�   ©r9   r†   r‡   )r‰   rŠ   r‹   Úsr!   r!   r%   Úscalingn  s    


ýýr«   c                 C   s:   t jddd| gddd|gddd|gddddggtd�}|S )zÚCreate an array with a translation matrix.

    Parameters
    ----------
    x, y, z : scalar
        Translation parameters.

    Returns
    -------
    m : array, shape = (4, 4)
        The translation matrix.
    r   r   r�   r©   )r‰   rŠ   r‹   r^   r!   r!   r%   Útranslation‚  s    


ýýr¬   r   c                 C   s<  t |tƒr|}t| }nt| }|}~t |tƒr>|}t| }nt| }|}~d|› d|› d�}t | ttfƒsr| g} tƒ }tƒ }	t| ƒD ]h\}
}t |tƒs¦t|› d�ƒ‚|d |d h||hkrÊ| 	|
¡ q†|	dj
t|d  t|d  d�g7 }	q†t|ƒd	k�rt|› d
�d |	¡ ƒ‚| |d  } | d |k�r8t| ƒ} | S )z$Ensure we have the proper transform.z"trans must be a Transform between z<->z, gotz Noner4   r5   z{fro}->{to}r`   r   ú z, r   )r(   r)   r*   Ú_frame_to_strÚlistÚtuplerh   r1   r+   ÚappendrB   rv   r,   Úinvert_transform)r6   r>   r5   rO   Z
from_constrP   Zto_constZerr_strÚidxÚmissesrl   Z
this_transr!   r!   r%   Ú_ensure_trans–  sH    




ÿÿ

þrµ   c                 C   s  t df}|r|d7 }t| |dƒ t| ƒrÀt| ƒ} | dkrNt t t¡ddd¡} t | ¡sht	d| › d�ƒ‚t 
| ¡d	 d
kr„t| ƒ}qît | ¡}|jdks¢|jdkr²td| › d�ƒ‚t |||ƒ}n.t| t ƒrÔ| }d} n| dksàt‚t ||ƒ}d} t|||ƒ}|| fS )z5Get mri_head_t (from=mri, to=head) from mri filename.z	path-like©Nr6   Z	fsaverageÚdatazfsaverage-trans.fifztrans file "z" not foundr   )z.fifz.gzrf   r3   zFile "z" did not have 4x4 entrieszinstance of TransformNrž   )r1   r   r   r)   ru   r,   ÚdirnameÚ__file__ÚisfileÚIOErrorÚsplitextÚ
read_transr9   Z
genfromtxtÚndimr<   rw   r(   rŸ   rµ   )r6   r>   r5   Ú
allow_noneÚtypesZfro_to_tri   r!   r!   r%   Ú
_get_trans¿  s4    ÿ




rÁ   c                 C   sÎ   t |ƒ}t |ƒ}| d |krBtdj| d t| d ƒ|t|ƒd�ƒ‚| d |d kr€tdj| d t| d ƒ|d t|d ƒd�ƒ‚|d |kr²tdj|d t|d ƒ|t|ƒd�ƒ‚t||t |d	 | d	 ¡ƒS )
a7  Combine two transforms.

    Parameters
    ----------
    t_first : dict
        First transform.
    t_second : dict
        Second transform.
    fro : int
        From coordinate frame.
    to : int
        To coordinate frame.

    Returns
    -------
    trans : dict
        Combined transformation.
    r4   z3From mismatch: {fro1} ("{cf1}") != {fro2} ("{cf2}"))Zfro1Úcf1Úfro2Úcf2r5   zMTransform mismatch: t1["to"] = {to1} ("{cf1}"), t2["from"] = {fro2} ("{cf2}"))Úto1rÂ   rÃ   rÄ   z/To mismatch: {to1} ("{cf1}") != {to2} ("{cf2}"))rÅ   rÂ   Zto2rÄ   r6   )r0   rw   rB   rC   r1   r9   r|   )Zt_firstZt_secondr>   r5   r!   r!   r%   Úcombine_transformsá  s8     
 þÿ

û 
 þÿrÆ   Fc              	   C   sˆ   t | ddd�} t| ƒ\}}}tƒ }|�8 |D ],}|jtjkr,| t||jƒj	¡ |s, qZq,W 5 Q R X t
|ƒdkrxtdƒ‚|r€|S |d S )aà  Read a ``-trans.fif`` file.

    Parameters
    ----------
    fname : path-like
        The name of the file.
    return_all : bool
        If True, return all transformations in the file.
        False (default) will only return the first.

        .. versionadded:: 0.15
    %(verbose)s

    Returns
    -------
    trans : dict | list of dict
        The transformation dictionary from the fif file.

    See Also
    --------
    write_trans
    mne.transforms.Transform
    ÚreadT)Ú	overwriteZ
must_existr   z+This does not seem to be a -trans.fif file.)r   r	   r¯   Úkindr   ZFIFF_COORD_TRANSr±   r
   Úposr·   rv   r»   )rR   Z
return_allr   ÚfidÚtreeÚ	directoryr6   ri   r!   r!   r%   r½   
  s    r½   )rÈ   r   c             	   C   s:   t | ddƒ t| |d�} t| ƒ�}t||ƒ W 5 Q R X dS )a%  Write a -trans.fif file.

    Parameters
    ----------
    fname : path-like
        The name of the file, which should end in ``-trans.fif``.
    trans : dict
        Trans file data, as returned by read_trans.
    %(overwrite)s
    %(verbose)s

    See Also
    --------
    read_trans
    r6   )z
-trans.fifz-trans.fif.gzz
_trans.fifz_trans.fif.gz)rR   rÈ   N)r   r   r   r   )rR   r6   rÈ   r   rË   r!   r!   r%   rQ   2  s    
rQ   c                 C   s    t | d | d tj | d ¡ƒS )zÎInvert a transformation between coordinate systems.

    Parameters
    ----------
    trans : dict
        Transform to invert.

    Returns
    -------
    inv_trans : dict
        Inverse transform.
    r5   r4   r6   )r1   r9   rš   Úinv)r6   r!   r!   r%   r²   J  s    r²   c                 C   s¢   |rt | ƒn| } t|tƒrB|tkr:tdtt ¡ ƒ|f ƒ‚t| }| d |krR| S t|t| d ƒ|ƒ}|| d< t	|| d ƒ| d< d| kržt	|| d dd�| d< | S )a÷  Transform surface to the desired coordinate system.

    Parameters
    ----------
    surf : dict
        Surface.
    dest : 'meg' | 'mri' | 'head' | int
        Destination coordinate system. Can be an integer for using
        FIFF types.
    trans : dict | list of dict
        Transformation to use (or a list of possible transformations to
        check).
    copy : bool
        If False (default), operate in-place.

    Returns
    -------
    res : dict
        Transformed source space.
    z dest must be one of %s, not "%s"Úcoord_frameÚrrÚnnF)r   )
r   r(   r)   r*   ÚKeyErrorr¯   r-   rµ   r.   r€   )ZsurfÚdestr6   rT   r!   r!   r%   Útransform_surface_toZ  s    
ÿrÔ   c                 C   s  t  | ¡} t  |¡}t  |¡}| ||fD ]"}|jdksBt|ƒdkr(tdƒ‚q(|| }|t j |¡ }|t  | | |¡|  }| | }|t j |¡ }t  ||¡}	| \}
}}t	|
||ƒ}t  
|||	dddgf¡}t  ddddgd¡}t  ||f¡}t  ||¡}|S )aÛ  Construct a transformation matrix to the MNE head coordinate system.

    Construct a transformation matrix from an arbitrary RAS coordinate system
    to the MNE head coordinate system, in which the x axis passes through the
    two preauricular points, and the y axis passes through the nasion and is
    normal to the x axis. (see mne manual, pg. 97)

    Parameters
    ----------
    nasion : array_like, shape (3,)
        Nasion point coordinate.
    lpa : array_like, shape (3,)
        Left peri-auricular point coordinate.
    rpa : array_like, shape (3,)
        Right peri-auricular point coordinate.

    Returns
    -------
    trans : numpy.array, shape = (4, 4)
        Transformation matrix to MNE head space.
    r   ra   zAPoints have to be provided as one dimensional arrays of length 3.r   )r2   r   )r9   r;   r¾   rv   r+   rš   r›   r|   Úcrossr¬   ÚvstackÚreshapeÚhstack)ZnasionZlpaZrpaÚptÚrightZ
right_unitÚoriginZanteriorZanterior_unitZsuperior_unitr‰   rŠ   r‹   Zorigin_transZtrans_lZtrans_rZ	rot_transr6   r!   r!   r%   Úget_ras_to_neuromag_trans€  s&    



rÜ   c              	   C   sŠ   t |ddƒd }t | d ddƒd }tt||ddƒƒ}tt||tddƒgd|d�t||tddƒgd|d�t||tddƒgd|d�d�}|S )zCGet the transforms to a coordinate frame from device, head and mri.r   r   r   Ú
dev_head_tr   r`   )r   r   r   )rÁ   r²   rÆ   rz   rµ   r1   )r_   r6   rÏ   Z
head_mri_trÝ   Z	mri_dev_tZto_cf_tr!   r!   r%   Ú_get_transforms_to_coord_frame´  s.       ÿ ÿ ÿ ÿûrÞ   c                 C   sê   t  | ¡} | jdkr"| jd dks&t‚t  t| ƒdf¡}t  t j| |  dd�¡|dd…df< t  	|dd…df dk|dd…df d¡}t  
| dd…df | dd…df ¡|dd…df< t  | dd…df | ¡|dd…df< t  |¡}|S )a]  Convert Cartesian coordinates to spherical coordinates.

    Parameters
    ----------
    cart_pts : ndarray, shape (n_points, 3)
        Array containing points in Cartesian coordinates (x, y, z)

    Returns
    -------
    sph_pts : ndarray, shape (n_points, 3)
        Array containing points in spherical coordinates (rad, azimuth, polar)
    rf   r   ra   ©ZaxisNr   )r9   Ú
atleast_2dr¾   r<   rŸ   Úemptyrv   r¤   ÚsumÚwherer£   ZarccosZ
nan_to_num)ZcartÚoutr›   r!   r!   r%   Ú_cart_to_sphÇ  s    
$*0&
rå   c                 C   sà   t  | ¡} | jdkr"| jd dks&t‚t  t| ƒdf¡}| dd…df t  | dd…df ¡ |dd…df< | dd…df t  | dd…df ¡ }|t  | dd…df ¡ |dd…df< |t  | dd…df ¡ |dd…df< |S )a^  Convert spherical coordinates to Cartesion coordinates.

    Parameters
    ----------
    sph_pts : ndarray, shape (n_points, 3)
        Array containing points in spherical coordinates (rad, azimuth, polar)

    Returns
    -------
    cart_pts : ndarray, shape (n_points, 3)
        Array containing points in Cartesian coordinates (x, y, z)

    rf   r   ra   Nr   )	r9   rà   r¾   r<   rŸ   rá   rv   r„   r…   )Zsph_ptsZcart_ptsZxyr!   r!   r%   Ú_sph_to_cartß  s    
2&&&ræ   c                 C   s   t  | t¡} | d |  S )a…  Compute the number of multipolar moments (spherical harmonics).

    Equivalent to :footcite:`DarvasEtAl2006` Eq. 32.

    .. note:: This count excludes ``degree=0`` (for ``order=0``).

    Parameters
    ----------
    order : array-like
        Expansion orders, often ``[int_order, ext_order]``.

    Returns
    -------
    M : ndarray
        Number of moments due to each order.
    rf   )r9   r;   r.   )Úorderr!   r!   r%   Ú_get_n_moments÷  s    rè   c                 C   sŠ   t j|||f }t  | ¡t  | ¡ }}t  |¡t  |¡ }}	t  ||	 | || g||	 ||| g|t  |¡|	 gg¡}
t  d|
|¡}|S )aœ  Convert spherical partial derivatives to cartesian coords.

    Note: Because we are dealing with partial derivatives, this calculation is
    not a static transformation. The transformation matrix itself is dependent
    on azimuth and polar coord.

    See the 'Spherical coordinate sytem' section here:
    wikipedia.org/wiki/Vector_fields_in_cylindrical_and_spherical_coordinates

    Parameters
    ----------
    az : ndarray, shape (n_points,)
        Array containing spherical coordinates points (azimuth).
    pol : ndarray, shape (n_points,)
        Array containing spherical coordinates points (polar).
    sph_grads : ndarray, shape (n_points, 3)
        Array containing partial derivatives at each spherical coordinate
        (radius, azimuth, polar).

    Returns
    -------
    cart_grads : ndarray, shape (n_points, 3)
        Array containing partial derivatives in Cartesian coordinates (x, y, z)
    z
ijk,kj->ki)r9   Zc_r„   r…   r†   Ú
zeros_likeÚeinsum)ÚazÚpolZg_radZg_azZg_polZ	sph_gradsZc_asZs_asZc_psZs_psr6   Z
cart_gradsr!   r!   r%   Ú_sph_to_cart_partials  s    þrí   c                 C   s   | |  |  | d S )z:Get the index into S_in or S_out given a degree and order.r   r!   )Údegrç   r!   r!   r%   Ú_deg_ord_idx/  s    rï   c                 C   s$   |dkst ‚|  ¡ |d rdnd S )z8Get the negative spherical harmonic from a positive one.r   rf   r‘   rc   )rŸ   Zconj©Úshrç   r!   r!   r%   Ú
_sh_negate5  s    rò   c                 C   s8   |dkrt  | ¡S t  d¡|dkr(t jnt j| ƒ S dS )a±  Convert complex to real basis functions.

    Parameters
    ----------
    sh : array-like
        Spherical harmonics. Must be from order >=0 even if negative orders
        are used.
    order : int
        Order (usually 'm') of multipolar moment.

    Returns
    -------
    real_sh : array-like
        The real version of the spherical harmonics.

    Notes
    -----
    This does not include the Condon-Shortely phase.
    r   ç       @N)r9   Úrealr¤   Úimagrð   r!   r!   r%   Ú_sh_complex_to_real;  s    
rö   c                 C   s<   |dkr| d S | d dt  |¡ | d   t  d¡ S dS )ag  Convert real spherical harmonic pair to complex.

    Parameters
    ----------
    shs : ndarray, shape (2, ...)
        The real spherical harmonics at ``[order, -order]``.
    order : int
        Order (usually 'm') of multipolar moment.

    Returns
    -------
    sh : array-like, shape (...)
        The complex version of the spherical harmonics.
    r   y              ð?r   ró   N)r9   Úsignr¤   )Zshsrç   r!   r!   r%   Ú_sh_real_to_complexU  s    rø   c                 C   s¦   ddl m} t t|ƒt| ƒd f¡}t| d ƒD ]n}t|d ƒD ]\}|||||ƒ}t||ƒ|dd…t||ƒf< |dkrBtt	||ƒ| ƒ|dd…t|| ƒf< qBq2|S )z=Compute complex spherical harmonics of spherical coordinates.r   )Úsph_harmr   N)
Zscipy.specialrù   r9   rá   rv   rè   Úrangerö   rï   rò   )rç   rë   rì   rù   rä   ZdegreeZorder_Úsphr!   r!   r%   Ú_compute_sph_harmj  s    ÿÿrü   c                   @   s(   e Zd ZdZddd„Zed	dd„ƒZdS )
Ú_TPSWarpa   Transform points using thin-plate spline (TPS) warping.

    Notes
    -----
    Based on the method by :footcite:`Bookstein1989` and
    adapted from code by Wang Lin (wanglin193@hotmail.com>).

    References
    ----------
    .. footbibliography::
    çü©ñÒMbP?c           
   	   C   s  ddl m} ddlm} |jd |jd   kr8dks>n t‚|jd |jd ksVt‚t|||dƒƒ}tjt 	|jd df¡|fdd�}t 
t ||g¡t |jt d	¡g¡g¡}tj|t d
¡fdd�}	||t |jd ¡ 7 }| ¡ | _| ||	¡d | _| S )Nr   ©rš   ©Úcdistr   ra   Úsqeuclideanr   rß   r3   )r2   ra   )Úscipyrš   Úscipy.spatial.distancer  r<   rŸ   Ú_tpsr9   ÚconcatenateÚonesrÖ   rØ   r}   rœ   r:   rT   Ú_destinationÚlstsqÚ_weights)
r=   ÚsourceÚdestinationÚregrš   r  ÚdistsÚPÚLÚYr!   r!   r%   Úfitª  s    &"ÿ
z_TPSWarp.fitNc           
      C   sà   t  dt|ƒf ¡ ddlm} |jd dks2t‚t |¡}t	t
|jd | jjd  d ƒdƒ}tt ||¡t ||¡ƒD ]P\}}t||| jdƒƒ}t |t |jd df¡|f¡}	t |	| j¡|dd…< qz|dk ¡ rÜt‚|S )	a  Apply the warp.

        Parameters
        ----------
        pts : shape (n_transform, 3)
            Source points to warp to the destination.

        Returns
        -------
        dest : shape (n_transform, 3)
            The transformed points.
        zTransforming %s pointsr   r   r   ra   g    „×gAr  N)r   r_   rv   r  r  r<   rŸ   r9   ré   Úmaxr.   r  ÚzipZarray_splitr  rØ   r  r|   r
  r�   )
r=   r~   r   r  rä   Zn_splitsZthis_outZthis_ptsr  r  r!   r!   r%   Ú	transform¾  s"    
ÿÿ
ÿ z_TPSWarp.transform)rþ   )N)rU   rV   rW   rX   r  r   r  r!   r!   r!   r%   rý   �  s   
rý   c                 C   s0   t  | ¡}| dk}| | }|t  |¡ ||< |S )z)Thin-plate function (r ** 2) * np.log(r).r   )r9   ré   Úlog)Zdistsqrä   ÚmaskZvalidr!   r!   r%   r  Ü  s
    
r  c                   @   s4   e Zd ZdZdd„ Zedd	d
„ƒZeddd„ƒZdS )Ú_SphericalSurfaceWarpaB  Warp surfaces via spherical harmonic smoothing and thin-plate splines.

    Notes
    -----
    This class can be used to warp data from a source subject to
    a destination subject, as described in :footcite:`DarvasEtAl2006`.

    The procedure is:

        1. Perform a spherical harmonic approximation to the source and
           destination surfaces, which smooths them and allows arbitrary
           interpolation.
        2. Choose a set of matched points on the two surfaces.
        3. Use thin-plate spline warping (common in 2D image manipulation)
           to generate transformation coefficients.
        4. Warp points from the source subject (which should be inside the
           original surface) to the destination subject.

    .. versionadded:: 0.14

    References
    ----------
    .. footbibliography::
    c                    s:   d}t ˆ dƒs|d7 }n|dt‡ fdd„dD ƒƒ 7 }|S )Nz<SphericalSurfaceWarp : Ú_warpzno fitting done >z9fit %d->%d pts using match=%s (%d pts), order=%s, reg=%s>c                 3   s   | ]}ˆ j | V  qd S r¶   )Ú_fit_params)r"   r#   rD   r!   r%   Ú	<genexpr>
  s   ÿz1_SphericalSurfaceWarp.__repr__.<locals>.<genexpr>©Zn_srcZn_destÚmatchZn_matchrç   r  )Úhasattrr°   )r=   Úrepr!   rD   r%   rE     s    

ÿÿz_SphericalSurfaceWarp.__repr__r2   çñhãˆµøä>TÚoct5Nc              	   C   sz  ddl m} ddlm}	 ddlm}
 |
|dd�d d	 }t d
¡ t 	d¡ }}|rÜt d¡ t 
dd„ |D ƒ¡}|	|dd�d }|| }t 
dd„ |D ƒ¡}|	|dd�d }|| }t dt |dd¡t |dd¡f ¡ tt|ƒt|ƒ|t|ƒ||d�| _|jd |jd   k�r"dk�s(n t‚| ¡ | _t d¡ t|ƒj}t|ƒj}t|ƒj}~t d| ¡ t|f|dd… žŽ }t|f|dd… žŽ }t|f|dd… žŽ }| ||d ¡d }| ||d ¡d }t dt|ƒ|f ¡ | ¡ }t t ||¡¡|d< | ¡ }t t ||¡¡|d< t|jƒ}||7 }t|jƒ}||7 }tƒ  |||¡| _t 
||g¡| _t d¡ | S )ar  Fit the warp from source points to destination points.

        Parameters
        ----------
        source : array, shape (n_src, 3)
            The source points.
        destination : array, shape (n_dest, 3)
            The destination points.
        order : int
            Order of the spherical harmonic fit.
        reg : float
            Regularization of the TPS warp.
        center : bool
            If True, center the points by fitting a sphere to points
            that are in a reasonable region for head digitization.
        match : str
            The uniformly-spaced points to match on the two surfaces.
            Can be "ico#" or "oct#" where "#" is an integer.
            The default is "oct5".
        %(verbose)s

        Returns
        -------
        inst : instance of SphericalSurfaceWarp
            The warping object (for chaining).
        r   rÿ   r   )Ú_fit_sphere)Ú_check_spacingF)r   rf   rÐ   zComputing TPS warpra   z    Centering datac                 S   s(   g | ] }|d  dk r |d dks|‘qS )rf   g�íµ ÷Æ°¾r   g�íµ ÷Æ°>r!   ©r"   Úpr!   r!   r%   Ú
<listcomp>4  s     ÿz-_SphericalSurfaceWarp.fit.<locals>.<listcomp>)Zdispc                 S   s(   g | ] }|d  dk r |d dks|‘qS )rf   r   r   r!   r$  r!   r!   r%   r&  8  s     ÿz    Using centers %s -> %sNr  z'    Converting to spherical coordinatesz<    Computing spherical harmonic approximation with order %sz0    Matching %d points (%s) on smoothed surfacesú[done])r  rš   Zbemr"  Zsource_spacer#  r   r_   r9   rœ   r†   Z	array_strrz   rv   r  r<   rŸ   rT   r  rå   r}   rü   r	  Úabsr|   ræ   rý   r  r  Z_matched)r=   r  r  rç   r  Úcenterr  r   rš   r"  r#  Zmatch_rrZ
src_centerZdest_centerZhspZsrc_rad_az_polZdest_rad_az_polZmatch_rad_az_polZsrc_sphZdest_sphZ	match_sphZ
src_coeffsZdest_coeffsr!   r!   r%   r    sr    

ÿÿ    þ*




ÿ
ÿ


z_SphericalSurfaceWarp.fitc                 C   s   | j  |¡S )a&  Transform arbitrary source points to the destination.

        Parameters
        ----------
        source : ndarray, shape (n_pts, 3)
            Source points to transform. They do not need to be the same
            points that were used to generate the model, although ideally
            they will be inside the convex hull formed by the original
            source points.
        %(verbose)s

        Returns
        -------
        destination : ndarray, shape (n_pts, 3)
            The points transformed to the destination space.
        )r  r  )r=   r  r   r!   r!   r%   r  f  s    z_SphericalSurfaceWarp.transform)r2   r   Tr!  N)N)rU   rV   rW   rX   rE   r   r  r  r!   r!   r!   r%   r  ê  s       ÿVr  c                 C   sü   t  t| ƒdf¡}| jd dkr†| dd…df t  | dd…df ¡ |dd…df< | dd…df t  | dd…df ¡ |dd…df< nr| dd…df t  | dd…df ¡ }|t  | dd…df ¡ |dd…df< |t  | dd…df ¡ |dd…df< |S )z)Transform polar coordinates to cartesian.rf   r   Nr   )r9   rá   rv   r<   r„   r…   )rì   rä   Údr!   r!   r%   Ú_pol_to_cart~  s    24&&&r+  c                 C   sx   | j dkr| jd dkst‚t t| ƒdf¡}t | dd…df ¡ |dd…df< tj| dd…df  |dd…df< |S )z5Convert 2D topo coordinates to spherical coordinates.rf   r   ra   Nr   )r¾   r<   rŸ   r9   r  rv   Zdeg2radÚpi)Ztoporû   r!   r!   r%   Ú_topo_to_sph‹  s
    $"r-  c                 C   sB  | d | d | d   }}}|| || ||   }}}t  d| | | d¡}t  |¡}d| | }	d| | }
d| | }d| | }d| | }d| | }t  | jdd… d	 ¡}|| | | |d
< || |d< ||
 |d< || |d< || | | |d< ||	 |d< ||
 |d< ||	 |d< || | | |d< |S )aI  Convert a set of quaternions to rotations.

    Parameters
    ----------
    quat : array, shape (..., 3)
        The q1, q2, and q3 (x, y, z) parameters of a unit quaternion.

    Returns
    -------
    rot : array, shape (..., 3, 3)
        The corresponding rotation matrices.

    See Also
    --------
    rot_to_quat
    ©.r   ©.r   ©.rf   rc   rF   rf   Nr   r�   ).r   r   ).r   r   ).r   rf   ).r   r   ).r   r   ).r   rf   ).rf   r   ).rf   r   ).rf   rf   )r9   Úmaximumr¤   rá   r<   )ÚquatÚbÚcr*  ZbbÚccÚddZaaÚaZab_2Zac_2Zad_2Zbc_2Zbd_2Zcd_2r�   r!   r!   r%   Úquat_to_rot—  s*    
r8  c                 C   sö  t j t  | d¡¡}t  |d ¡dkr.tdƒ‚d| d  | d  | d  }|t  | j¡jkrªt  	|¡d }| d	 | d
  | }| d | d  | }| d | d  | }�n<| d | d k�r&| d | d k�r&t  	d| d  | d  | d  ¡d }d| }| d | d  | }| d | d  | }nÀ| d | d k�r�t  	d| d  | d  | d  ¡d }| d | d  | }d| }| d
 | d	  | }nVt  	d| d  | d  | d  ¡d }| d | d  | }| d
 | d	  | }d| }t  
|||f¡S )z)Convert a rotation matrix to quaternions.r�   rc   rþ   z3Matrix is not a pure rotation, got determinant != 1r   r2   é   ró   é   é   rf   é   ra   r   g      Ð?)r9   rš   r    r×   r(  r+   Zfinfor‚   Úepsr¤   r†   )Úrotr    ri   rª   ZqxZqyZqzr!   r!   r%   Ú_one_rot_to_quatÂ  s0    $&&&r?  c                 C   s&   |   | jdd… d ¡} t td| ¡S )a_  Convert a set of rotations to quaternions.

    Parameters
    ----------
    rot : array, shape (..., 3, 3)
        The rotation matrices to convert.

    Returns
    -------
    quat : array, shape (..., 3)
        The q1, q2, and q3 (x, y, z) parameters of the corresponding
        unit quaternions.

    See Also
    --------
    quat_to_rot
    Néþÿÿÿ)é	   r   )r×   r<   r9   Zapply_along_axisr?  )r>  r!   r!   r%   Úrot_to_quatæ  s    rB  c                 C   sT   | j dkst‚t d¡}t| d d… ƒ|d d…d d…f< | dd … |d d…df< |S )N)r<  r2   ra   )r<   rŸ   r9   r:   r8  )r2  Úaffiner!   r!   r%   Ú_quat_to_affineü  s
    
 rD  c                 C   sF   |dkrt  d¡n|}t|  |ƒ}t|ƒ}dt  t jj|dd�|¡ S )zDCompute the ang between two quaternions w/3-element representations.Nra   rf   r   rß   )r9   rœ   Ú
_quat_multÚ
_quat_realr£   rš   r›   )r‰   rŠ   r‹   Zz0r!   r!   r%   Ú_angle_between_quats  s    rG  c                 C   s^   | j d dkst| j d ƒ‚t t d| d | d   | d | d   | d | d   d¡¡S )z(Get the real part of our 3-element quat.r   ra   rc   r.  r/  r0  rF   )r<   rŸ   r9   r¤   r1  )r2  r!   r!   r%   rF    s    
ÿþýýrF  c                 C   s:  | j d |j d   kr dks&n t‚t| ƒ}t|ƒ}t t | |¡j ¡}| d |d  }}| d |d  }}| d |d  }	}
|| ||  ||
  |	|  |d< || ||
  ||  |	|  |d< ||
 ||  ||  |	|  |d< || ||  ||  |	|
  }t |¡}t ||d¡}||dtjf 9 }|S )Nr   ra   r.  r/  r0  r   .)	r<   rŸ   rF  r9   rá   Ú	broadcastr÷   rã   Únewaxis)ÚoneÚtwoZw1Zw2rä   Úx1Zx2Úy1Úy2Zz1Zz2ÚwZsignsr!   r!   r%   rE    s    &$$$ 
rE  c                 C   s@   t  d| d  | d g| d d| d  g| d  | d dgg¡S )z5Compute the skew-symmetric cross product of a vector.rF   rf   r   r   )r9   r†   )r7  r!   r!   r%   Ú_skew_symmetric_cross,  s    rP  c                 C   sj   t  d¡}t  | |¡}t  |d¡r&|S t  ||¡}t  | |¡}t|ƒ}||t  ||¡d|  |  7 }|S )z6Find the rotation matrix that maps unit vector a to b.ra   rF   r   )r9   r:   rÕ   rI   r|   rP  )r7  r3  ÚRÚvrª   r4  Zvxr!   r!   r%   Ú_find_vector_rotation1  s    
 rS  c                 C   sJ  | j |j kst‚| jdkst‚| j d dks0t‚|dkrnt| dd�}t|dd�}t | j|¡}|| j d  }nPt || ¡  |j	df¡}t |j| ¡d }t |j|¡d }t | j|| ¡}|t 
||¡ }||j }	t |	d |	d |	d	 g¡}
t |¡}t d
¡}||d< |
|ddd…f< |
|dd…df< ||j |t d¡  |dd…dd…f< tj |¡\}}t d¡}|dd…df |dd…< |d dk�r¶|dd…  t |d ¡9  < t|dd… ƒ}|�r"|| }| | }||9 }||9 }|dk	�r||9 }||9 }t t |¡t |¡ ¡}nd}||t ||¡  |dd…< ||fS )z/Fit matched points using an analytical formula.rf   r   ra   Nr   rß   r—   r˜   r”   r3   r�   r<  r   )r   r   rc   )r<   rŸ   r¾   r   r9   r|   r}   r×   râ   r{   Úouterr†   Útracerá   r:   rš   Úeighr÷   r8  r¤   )r%  r‰   Úweightsrn   Zmu_pZmu_xÚdotsZweights_ZSigma_pxZA_ijÚDeltaZtr_Sigma_pxÚQÚ_rR  r2  r>  Zdev_xZdev_prª   r!   r!   r%   Ú_fit_matched_pointsA  sN    


(

r\  c                 C   sü   ddl m} | jdkr$| jd dks(t‚|dkr@t | jd ¡}|dk ¡ sPt‚| ¡ }| ¡ dkrnt 	d¡S || }t 
t| ƒdtjf | fd	¡} | |dd…tjf 9 } t d
| | ¡}| |¡d dd…d	f }|t ||dk d ¡9 }|dd… }|S )z"Average unit quaternions properly.r   rÿ   rf   r   )ra   r2   Nra   .r   z	ij,ik->jk)r  rš   r¾   r<   rŸ   r9   r  Úallrâ   rœ   r  rF  rI  rê   rV  r÷   )ZquatsrW  rš   r›   ÚAZavg_quatr!   r!   r%   Ú_average_quatsƒ  s     
	r_  c                 C   sL   t |dd�}t| ddƒ t || ddd¡}t|ddd	ƒ}td
dt|ƒd ƒS )zôRead a subject's RAS to MNI transform.

    Parameters
    ----------
    subject : str
        The subject.
    %(subjects_dir)s

    Returns
    -------
    ras_mni_t : instance of Transform
        The transform from RAS to MNI (in mm).
    T)rx   Zraise_errorr)   rq   r   Z
transformsztalairach.xfmrÇ   z(FreeSurfer Talairach transformation filer   r   r   )r   r   ru   r,   r   r1   Ú_read_fs_xfm)rq   rx   rR   r!   r!   r%   Úread_ras_mni_t«  s    ÿÿ   ÿra  c           	   	   C   s  |   d¡st‚t| dƒ�¼}t d|  ¡ d}t|ƒD ]@\}}|dkr\| ¡ }t d|f ¡ |dt|ƒ… |kr4 q‚q4td|  ƒ‚t	ƒ }t|ƒD ]6\}}d	d
„ | d¡ 
¡ D ƒ}| |¡ |dkr� qÐq�tdƒ‚W 5 Q R X | ddddg¡ tj|td�}||fS )z-Read a Freesurfer transform from a .xfm file.z.xfmrŒ   z)Reading FreeSurfer talairach.xfm file:
%sZLinear_Transformr   z	Found: %rNz8Failed to find "Linear_Transform" string in xfm file:
%sc                 S   s   g | ]}t |ƒ‘qS r!   ©r‡   )r"   rª   r!   r!   r%   r&  Û  s     z _read_fs_xfm.<locals>.<listcomp>z
;rf   z,Could not find enough linear transform linesrF   rc   r�   )ÚendswithrŸ   Úopenr   Údebugrh   Ústriprv   r+   r¯   Úsplitr±   r9   r†   r‡   )	rR   rË   ÚcompÚliÚlinerÉ   ÚxfmÚiiZdigsr!   r!   r%   r`  Ä  s.    ÿ
r`  c              	   C   s�   t | dƒ�|}| |d  d¡¡ | d d¡¡ t|dd… ƒD ]@\}}d dd	„ |D ƒ¡}||d
k rjdnd7 }| | d¡¡ q@W 5 Q R X dS )z,Write a Freesurfer transform to a .xfm file.Úwbz

Ttransform_Type = Linear;
ÚasciizLinear_Transform =
Nr   r­   c                 S   s   g | ]}d | ‘qS )z%0.6fr!   )r"   Úpartr!   r!   r%   r&  ì  s     z!_write_fs_xfm.<locals>.<listcomp>rf   Ú
z;
)rd  ÚwriteÚencoderh   r,   )rR   rk  rÉ   rË   ri  rj  r!   r!   r%   Ú_write_fs_xfmæ  s    rs  c                 C   sÆ   t  | j¡}| d | d | d   }}}t| ƒ}t jd|| ||   dd|| ||    |d d� t jd|| ||   |d d� t jd|| ||   dd|| ||    |d d� |S )Nr.  r/  r0  rf   r   )rä   )r9   rá   r<   rF  r£   Zarcsin)r2  Úeulerr‰   rŠ   r‹   rO  r!   r!   r%   Ú_quat_to_eulerñ  s    8"8ru  c                 C   s0  t  | j¡}| d d | d d | d d   }}}t  |¡t  |¡ }}~t  |¡t  |¡ }}~t  |¡t  |¡ }	}
~t  || |	 || |
  ¡}t  |¡r¶|dkr°dn|}nd||dk< |dt jf }|| |	 || |
  |d< || |	 || |
  |d< || |
 || |	  |d< ||9 }|S )Nr.  rf   r/  r0  r   rc   .)r9   rá   r<   r„   r…   r÷   ZisscalarrI  )rt  r2  ÚphiÚthetaÚpsiZcphiZsphiZcthetaZsthetaZcpsiZspsiZmultr!   r!   r%   Ú_euler_to_quatû  s$    (
ry  )r¬   ÚrigidrC  Úsdrc                 C   sÂ   t | tttdd fdƒ td| ƒ} |  ¡ D ]”\}}td|tƒ |d k	r(tdd„ tj	|t
d� ¡ D ƒƒ}tdt|ƒ› d	�t|ƒd
ƒ t|ƒdkr”|d }|D ]}|dkr˜td|› �ƒ‚q˜|| |< q(| S )NÚnumericÚzoomsZtransform_zoomsz	zooms keyc                 s   s   | ]}t |ƒV  qd S r¶   rb  )r"   r‰   r!   r!   r%   r    s    z"_validate_zooms.<locals>.<genexpr>r�   z
len(zooms[ú))r   ra   r   ra   zZooms must be > 1, got )r   rz   r¯   r°   r   Úitemsr   Ú_ORDERED_STEPSr9   r†   r‡   ÚravelÚreprrv   r+   )r}  r#   r$   Z	this_zoomr!   r!   r%   Ú_validate_zooms  s     
ÿ
rƒ  c                 C   s\   t | tttd fdƒ td| ƒ} |  ¡ D ]0\}}td|tƒ tdt|ƒ› d�t	|ƒdƒ q&| S )NÚniterZtransform_niterz	niter keyz
len(niter[z]))r   rf   ra   )
r   rz   r¯   r°   r   r  r   r€  r‚  rv   )r„  r#   Úvaluer!   r!   r%   Ú_validate_niter)  s    
r†  c                 C   sö   t | tttfdƒ tttd t d¡d … td t d¡d … d�}t| tƒrftd| ddd� ||  } t	| ƒD ],\}}d|› d	�}t |t|ƒ t||tƒ qntt
| d
d„ d�ƒ}t| ƒ|krÒtd|› d| › d�ƒ‚tt| ƒƒt| ƒkrîtdƒ‚t| ƒS )NÚpipelinerz  r   rC  )r]  ZrigidsZaffineszwhen str)Úextraz	pipeline[ú]c                 S   s
   t  | ¡S r¶   )r€  Úindex)r‰   r!   r!   r%   Ú<lambda>A  ó    z$_validate_pipeline.<locals>.<lambda>)r#   z-Steps in pipeline are out of order, expected z	 but got z insteadz(Steps in pipeline should not be repeated)r   r)   r¯   r°   rz   r€  rŠ  r(   r   rh   Úsortedr+   rv   Úset)r‡  Zpipeline_defaultsrl  ÚstepÚnameZordered_pipeliner!   r!   r%   Ú_validate_pipeline2  s4    ý
ÿ ÿÿr‘  c                 C   s,   d|   ¡ |  ¡   tj | ¡tj |¡  S )Néd   )r�  r9   rš   r›   )r7  r3  r!   r!   r%   Ú_compute_r2K  s    ÿr“  c                 C   sZ   ddl m} | j ¡ d d… }| j}t| ƒ} |d k	rF|| |||ƒ\} }| |  ¡  } | |fS )Nr   )Úreslicera   )Zdipy.align.reslicer”  ÚheaderÚ	get_zoomsrC  r   r  )Zimgr}  r”  Z	img_zoomsZ
img_affiner!   r!   r%   Ú_reslice_normalizeP  s    r—  r]  c                 C   s   t | ||||ƒdd… S )am  Align two volumes using an affine and, optionally, SDR.

    Parameters
    ----------
    %(moving)s
    %(static)s
    %(pipeline)s
    zooms : float | tuple | dict | None
        The voxel size of volume for each spatial dimension in mm.
        If None (default), MRIs won't be resliced (slow, but most accurate).
        Can be a tuple to provide separate zooms for each dimension (X/Y/Z),
        or a dict with keys ``['translation', 'rigid', 'affine', 'sdr']``
        (each with values that are float`, tuple, or None) to provide separate
        reslicing/accuracy for the steps.
    %(niter)s
    %(verbose)s

    Returns
    -------
    %(reg_affine)s
    %(sdr_morph)s

    Notes
    -----
    This function is heavily inspired by and extends
    :func:`dipy.align.affine_registration
    <dipy.align._public.affine_registration>`.

    .. versionadded:: 0.24
    Nrf   )Ú_compute_volume_registration)ÚmovingÚstaticr‡  r}  r„  r   r!   r!   r%   Úcompute_volume_registration[  s    !    ÿÿr›  c           %      C   sl  t dddƒ t dddƒ dd l}tj ¡ �6 ddlm} ddlm}m	}m
}	m}
m}m}m} W 5 Q R X t| |jjd	ƒ t||jjd
ƒ t | j ¡ d d… ¡}t|ƒ}t|ƒ}t|ƒ}t d¡ d }d }t||	g|
g|gd�}t dddg¡}d}dddg}d }t|ƒD �]L\}}|dk�s6|| |||d   k�rª|| d k	�rpt d|| › d|› d�¡ t || ¡}nt d|› d�¡ |}t||| ƒ\}}t| || ƒ\}}t d|› d�¡ |dk�rT|| }|||j||j|ƒ}| |¡}|j d|t!t"t #d| ¡ƒdƒd�}| $||| ¡}t%ddd�� | &||||¡}W 5 Q R X | |¡} nÌt'|| ƒ}!t%ddd��0 |||||d d!|| || |!||d"�\} }W 5 Q R X |d#k�r tj( )|d d…df ¡}"t *t+t ,d¡t-|d d…d d…f ƒƒ¡}#t d$|"d%›d&�¡ |d'k�r t d(|#d%›d)�¡ | j|jk�s6t.|ƒ‚t/|| ƒ}$t d*|$d%›d+�¡ �q|||j||j|fS ),NÚnibabelú	SDR morphú2.1.0Údipyú0.10.1r   ©Ú	AffineMap)Úaffine_registrationÚcenter_of_massr¬   rz  rC  ÚimwarpÚmetricsr™  rš  ra   zComputing registration...)r¬   rz  rC  g      @rc   rF   ró   r2   rf   r   zReslicing to zooms=z for z ...zUsing original zooms for zOptimizing ú:r{  )ÚdimZ
sigma_diffZradiusz    T)ÚindentZcull_newlinesé    ZMI)ZnbinsÚmetricr‡  Zlevel_itersZsigmasÚfactorsZstarting_affine)r¬   rz  z    Translation: z6.1frd   rz  z    Rotation:    õ   Â°u       RÂ²:          ú%)0r   rœ  r9   ZtestingZsuppress_warningsÚdipy.align.imaffiner¢  Z
dipy.alignr£  r¤  r¬   rz  rC  r¥  r¦  r   ZspatialimagesÚSpatialImager   r•  r–  rƒ  r†  r‘  r   r_   rz   r†   rh   r—  r<   r  ZCCMetricr  r.   ÚceilZ"SymmetricDiffeomorphicRegistrationr   Úoptimizer¯   rš   r›   Zrad2degrG  rœ   rB  rŸ   r“  )%r™  rš  r‡  r}  r„  Znibr¢  r£  r¤  r¬   rz  rC  r¥  r¦  Zoriginal_zoomÚ
reg_affineÚ	sdr_morphZpipeline_optionsZ	sigmas_mmZsigma_diff_mmr¬  Zcurrent_zoomÚir�  Zstatic_zoomedÚstatic_affineZmoving_zoomedÚmoving_affineZsigma_diff_voxÚ
affine_mapr«  r{  Zmoved_zoomedZ
sigmas_voxÚdistZangleÚr2r!   r!   r%   r˜  €  s¼    .
 ÿ
$ ÿ ÿ
  þ
 þ ÿ ÿ       ü
 ÿ


 ÿr˜  ÚlinearrF   c                 C   s¢  t dddƒ t dddƒ ddlm} ddlm} dd	lm}	 t| |d
ƒ t||dƒ t|tj	dƒ t
d|jdƒ t||dfdƒ t|dtfdƒ d}
t|tƒrÆ| d¡s¶td|› �ƒ‚t|dd… ƒ}
t d¡ | j}tj| jtd�} |
dk	�rt | |
¡}t d|
› d|› �¡ | |8 } t |j¡|j }}|	||j|| j|ƒ}|j| |d�}|dk	�r‚t d¡ |j||tj |¡|j|d�}||7 }|||ƒ}t d¡ |S )a   Apply volume registration.

    Uses registration parameters computed by
    :func:`~mne.transforms.compute_volume_registration`.

    Parameters
    ----------
    %(moving)s
    %(static)s
    %(reg_affine)s
    %(sdr_morph)s
    interpolation : str
        Interpolation to be used during the interpolation.
        Can be "linear" (default) or "nearest".
    cval : float | str
        The constant value to assume exists outside the bounds of the
        ``moving`` image domain. Can be a string percentage like ``'1%%'``
        to use the given percentile of image data as the constant value.
    %(verbose)s

    Returns
    -------
    reg_img : instance of SpatialImage
        The image after affine (and SDR, if provided) registration.

    Notes
    -----
    .. versionadded:: 0.24
    rœ  r�  rž  rŸ  r   r   )r°  )ÚDiffeomorphicMapr¡  r™  rš  r³  zreg_affine.shape)r3   Nr´  r|  Úcvalr®  z!cval must end with % if str, got r   z Applying affine registration ...r�   zUsing a lower bound at the z percentile: )ÚinterpolationzAppling SDR warp ...)r¾  Zimage_world2gridZ	out_shapeZout_grid2worldr'  )r   Znibabel.spatialimagesr°  Zdipy.align.imwarpr¼  r¯  r¢  r   r9   Zndarrayr   r<   r)   r(   rc  r+   r‡   r   r_   rC  r;   ZdataobjZ
percentiler  rš   rÎ   )r™  rš  r³  r´  r¾  r½  r   r°  r¼  r¢  Úpercr·  r¶  r¸  Zreg_dataZreg_imgr!   r!   r%   Úapply_volume_registrationÒ  sX    !



  þ

 
 ý

rÀ  )r]   r^   r_   )N)T)r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   )r   r   T)FN)F)r   )N)NF)N)N)r]  NNN)Nr»  rF   N)zrX   rr   Úos.pathÚpathru   rt   Únumpyr9   rT   r   Úfixesr   r   r   Zio.constantsr   Zio.openr	   Zio.tagr
   Zio.writer   r   Údefaultsr   Úutilsr   r   r   r   r   r   r   r   r   r   r   r   r†   Zals_ras_transrz   ZFIFFV_COORD_DEVICEZFIFFV_COORD_MRIZFIFFV_MNE_COORD_MRI_VOXELZFIFFV_COORD_HEADZFIFFV_MNE_COORD_MNI_TALZFIFFV_MNE_COORD_RASZFIFFV_MNE_COORD_FS_TALZFIFFV_MNE_COORD_CTF_HEADZFIFFV_MNE_COORD_CTF_DEVICEZFIFFV_COORD_UNKNOWNr*   r  r®   ZFIFFV_COORD_ISOTRAKZFIFFV_COORD_HPIZFIFFV_COORD_MRI_SLICEZFIFFV_COORD_MRI_DISPLAYZFIFFV_MNE_COORD_FS_TAL_GTZZFIFFV_MNE_COORD_FS_TAL_LTZr[   r0   r1   rC   rp   ry   r€   r�   rŽ   r¢   r¨   r«   r¬   rµ   rÁ   rÆ   r½   rQ   r²   rÔ   rÜ   rÞ   rå   ræ   rè   rí   rï   rò   rö   rø   rü   Úobjectrý   r  r  r+  r-  r8  r?  rB  rD  rG  rF  rE  rP  rS  r\  r_  ra  r`  rs  ru  ry  r€  rƒ  r†  r‘  r“  r—  r›  r˜  rÀ  r!   r!   r!   r%   Ú<module>   s  8"
ÿ÷
               ñi  ÿ


 

)


)
")'
&4
#3? 
*
#
	A
("
	    ÿ$R     þ