U
    f»{jÃ
 ã                   @   sî  d dl mZ d dlmZ d dlZddlmZ ddlm	Z	 ddl
mZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZ ddlmZmZ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% ddl&m'Z'm(Z(m)Z)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z< ddl=m>Z>m?Z? ddl@mAZAmBZBmCZCmDZDmEZEmFZF ddlGmHZH ddlImJZJmKZK ddlLmMZMmNZN ddlOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZY dZZG dd„ de[ƒZ\dd„ Z]eRdd œd!d"„ƒZ^eRd#dd$œd%d&„ƒZ_d'd(„ Z`dWd)d*„Zad+d,„ ZbdXd.d/„ZceRdYd1d2„ƒZdeRdZd3d4„ƒZed[d5d6„Zfd\d7d8„Zgd9d:„ ZheRd]d<d=„ƒZid^d?d@„ZjdAdB„ ZkeRd_dCdD„ƒZld`dEdF„ZmeRdadGdH„ƒZneRdbdIdJ„ƒZodKdL„ ZpeRdcdOdP„ƒZqdQdR„ ZrdSdT„ ZseRdddUdV„ƒZtdS )eé    )Údeepcopy)ÚsqrtNé   )Ú_compute_eloretaé   )Ú	_safe_svd)ÚBaseRaw)ÚFIFF)Ú	fiff_open)Úfind_tag)Ú_read_named_matrixÚ_transpose_named_matrixÚwrite_named_matrix)Ú
_read_projÚmake_projectorÚ_write_projÚ_needs_eeg_average_ref_proj)Údir_tree_find)Ú	write_intÚwrite_float_matrixÚstart_and_end_fileÚstart_blockÚ	end_blockÚwrite_floatÚwrite_coord_transÚwrite_string)Úchannel_typeÚ	pick_infoÚ
pick_typesÚpick_channels)Úcompute_whitenerÚ	_read_covÚ
_write_covÚ
CovarianceÚprepare_noise_cov)Ú
BaseEpochs)ÚEvokedArrayÚEvoked)Úcompute_depth_priorÚ_read_forward_meas_infoÚis_fixed_orientÚcompute_orient_priorÚconvert_forward_solutionÚ_select_orient_forward)Úwrite_forward_meas_infoÚ_triage_loose)Ú_read_source_spaces_from_treeÚ_get_src_nnÚfind_source_space_hemiÚ_get_vertnoÚ_write_source_spaces_to_fidÚlabel_src_vertno_sel)Ú_normal_orth)Ú_ensure_transÚtransform_surface_to)Ú	_make_stcÚ_get_src_type)
Úcheck_fnameÚloggerÚverboseÚwarnÚ_validate_typeÚ_check_compensation_gradeÚ_check_optionÚ_check_depthÚ_check_src_normalÚ_check_fname)ÚMNEÚdSPMÚsLORETAÚeLORETAc                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚInverseOperatorz>InverseOperator class to represent info from inverse operator.c                 C   s   t t| ƒƒS )z%Return a copy of the InverseOperator.)rI   r   )Úself© rK   úW/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/minimum_norm/inverse.pyÚcopy5   s    zInverseOperator.copyc                 C   st   t t| d ddd�ƒ}t t| d ddd�ƒ}| d j› d| d › d�}tjd	tjd
tjdi}|| d  }||||fS )NÚinfoTF)ZmegÚeegÚsrcz with Únsourcez sourcesÚUnknownZFixedZFreeÚ
source_ori)Úlenr   Úkindr	   ZFIFFV_MNE_UNKNOWN_ORIZFIFFV_MNE_FIXED_ORIÚFIFFV_MNE_FREE_ORI)rJ   Ú	n_chs_megÚ	n_chs_eegÚsrc_space_descrZsrc_ori_fiff_to_name_mapÚsrc_orirK   rK   rL   Ú_get_chs_and_src_info_for_repr9   s       ýz.InverseOperator._get_chs_and_src_info_for_reprc                 C   s\   |   ¡ }|\}}}}d}|d|› �7 }|d|› �7 }|d|› �7 }|d|› �7 }|d7 }|S )z/Summarize inverse info instead of printing all.z<InverseOperatorz | MEG channels: z | EEG channels: z | Source space: z | Source orientation: ú>)r[   )rJ   Ú	repr_inforW   rX   rY   rZ   ZentrrK   rK   rL   Ú__repr__G   s    zInverseOperator.__repr__c           	      C   sJ   ddl m} |  ¡ }|\}}}}| d¡}|j|› d|› d�||d�}|S )Nr   )Úrepr_templates_envzinverse_operator.html.jinjaz MEG, z EEG)ZchannelsZsource_space_descrZsource_orientation)Zhtml_templatesr_   r[   Zget_templateÚrender)	rJ   r_   r]   rW   rX   rY   rZ   ÚtÚhtmlrK   rK   rL   Ú_repr_html_T   s    
ýzInverseOperator._repr_html_N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rM   r[   r^   rc   rK   rK   rK   rL   rI   2   s
   rI   c              	   C   sP   t ƒ }|d jD ]:}z| |  |¡¡ W q tk
rH   td| ƒ‚Y qX q|S )zŒReturn data channel indices to be used knowing an inverse operator.

    Unlike ``pick_channels``, this respects the order of ch_names.
    Ú	noise_covz£The inverse operator was computed with channel %s which is not present in the data. You should compute a new inverse operator restricted to the good data channels.)ÚlistÚch_namesÚappendÚindexÚ
ValueError)rj   ÚinvÚselÚnamerK   rK   rL   Ú_pick_channels_inverse_operatorb   s    ürq   )r=   c                C   sÂ  t | ddƒ t| ddd�} t d|  ¡ t| ƒ\}}}|��x}t|tjƒ}|dks^t|ƒdk rjt	d	|  ƒ‚|d
 }t|tj
ƒ}t|ƒd
kr–t	d|  ƒ‚|d
 }t d¡ t||tjƒ}|dkrÆt	dƒ‚tƒ }	t|jƒ|	d< t||tjƒ}|dkrøt	dƒ‚t|jƒ|	d< t||tjƒ}|dk�r&t	dƒ‚t|jƒ|	d< d
|	d< t||tjƒ}|dk�r\t	dƒ‚|j|	d< t||tjƒ}tjdtjdtjdi}
|
 tt|ddƒƒd¡|	d< t||tjƒ}|dk�rÆt	dƒ‚|j|	d< t d¡ t d¡ t||tjƒ}|dk�rt	d ƒ‚|j|	d!< t|	d! ƒ|	d< d"|	d#< t||tjdd$�|	d%< |	d% dk�rhd|	d#< t||tjdd$�|	d%< |	d% dk�r~td&ƒ‚t||tjƒ|	d'< t d¡ t f t!||tj"dd(�Ž|	d)< t d*¡ t!||tj#ƒ|	d+< t d,¡ t!||tj$ƒ|	d-< |	d- dk	�rt d.¡ t!||tj%ƒ|	d/< |	d/ dk	�r0t d0¡ t!||tj&ƒ|	d1< |	d1 dk	�rZt d2¡ t'||d"d3�|	d4< |	d4 D ]}t(|ƒ|d5< �qtt||tj)ƒ}|dk�r¨t	d6ƒ‚t*|jd7d8ƒ}||	d9< t+||ƒ|	d:< |	d tj,tj-fk�rêt	d;ƒ‚d|	d<< t.||ƒ|	d=< g |	d>< g |	d?< g |	d@< g |	dA< d
}t/t|	d4 ƒƒD ]p}z$t0|	d4 | |	d |ƒ|	d4 |< W n0 t	k
�rŒ } zt	dB| ƒ‚W 5 d}~X Y nX ||	d4 | dC 7 }�q4t dD¡ W 5 Q R X t1|	ƒS )Eaq  Read the inverse operator decomposition from a FIF file.

    Parameters
    ----------
    fname : str
        The name of the FIF file, which ends with -inv.fif or -inv.fif.gz.
    %(verbose)s

    Returns
    -------
    inv : instance of InverseOperator
        The inverse operator.

    See Also
    --------
    write_inverse_operator, make_inverse_operator
    úinverse operator©z-inv.fifz-inv.fif.gzz_inv.fifz_inv.fif.gzTÚread)ÚfnameZ
must_existÚ	overwritez1Reading inverse operator decomposition from %s...Nr   zNo inverse solutions in %sr   zNo parent MRI information in %sz$    Reading inverse operator info...zModalities not foundÚmethodsz(Source orientation constraints not foundrS   zNumber of sources not foundrQ   ÚnchanzCoordinate frame tag not foundÚcoord_frameÚAmúAm/m^2úAm/m^3ÚdataéÿÿÿÿÚunitsz(Source orientation information not foundÚ	source_nnú
    [done]z-    Reading inverse operator decomposition...zSingular values not foundÚsingFÚeigen_leads_weighted)Z	transposeÚeigen_leadsz*Eigen leads not found in inverse operator.Úeigen_fields)Zlimitedrh   z!    Noise covariance matrix read.Ú
source_covz"    Source covariance matrix read.Úorient_priorz    Orientation priors read.Údepth_priorz    Depth priors read.Ú
fmri_priorz    fMRI priors read.)Zpatch_statsrP   Úidz,MRI/head coordinate transformation not foundZmriÚheadÚ
mri_head_trN   zIOnly inverse solutions computed in MRI or head coordinates are acceptableÚnaveÚprojsÚprojÚwhitenerÚreginvÚ	noisenormz%Could not transform source space (%s)ÚnusezF    Source spaces transformed to the inverse solution coordinate frame)2r;   rD   r<   rN   r
   r   r	   ÚFIFFB_MNE_INVERSE_SOLUTIONrT   Ú	ExceptionÚFIFFB_MNE_PARENT_MRI_FILEr   ÚFIFF_MNE_INCLUDED_METHODSÚdictÚintr}   ÚFIFF_MNE_SOURCE_ORIENTATIONÚFIFF_MNE_SOURCE_SPACE_NPOINTSÚFIFF_MNE_COORD_FRAMEÚFIFF_MNE_INVERSE_SOURCE_UNITÚFIFF_UNIT_AMÚFIFF_UNIT_AM_M2ÚFIFF_UNIT_AM_M3ÚgetÚgetattrÚ$FIFF_MNE_INVERSE_SOURCE_ORIENTATIONSÚFIFF_MNE_INVERSE_SINGr   ÚFIFF_MNE_INVERSE_LEADSÚFIFF_MNE_INVERSE_LEADS_WEIGHTEDrm   ÚFIFF_MNE_INVERSE_FIELDSr#   r!   ZFIFFV_MNE_NOISE_COVÚFIFFV_MNE_SOURCE_COVÚFIFFV_MNE_ORIENT_PRIOR_COVÚFIFFV_MNE_DEPTH_PRIOR_COVZFIFFV_MNE_FMRI_PRIOR_COVr0   r2   ZFIFF_COORD_TRANSr7   r)   ZFIFFV_COORD_MRIZFIFFV_COORD_HEADr   Úranger8   rI   )ru   r=   ÚfÚtreeÚ_ÚfidZinvsZ
parent_mriÚtagrn   Z	unit_dictÚsrŒ   r“   ÚkÚinstrK   rK   rL   Úread_inverse_operatort   sü    ÿ



  þ





   ÿ
  þ
ÿ
ÿ

ÿ
ÿ

ÿ


ÿþr´   F)rv   r=   c             	   C   sT   t | ddƒ t| |d�} t|tdƒ t d|  ¡ t| ƒ�}t||ƒ W 5 Q R X dS )aJ  Write an inverse operator to a FIF file.

    Parameters
    ----------
    fname : str
        The name of the FIF file, which ends with -inv.fif or -inv.fif.gz.
    inv : dict
        The inverse operator.
    %(overwrite)s

        .. versionadded:: 1.0
    %(verbose)s

    See Also
    --------
    read_inverse_operator
    rr   rs   )ru   rv   rn   z-Write inverse operator decomposition in %s...N)r;   rD   r?   rI   r<   rN   r   Ú_write_inverse_operator)ru   rn   rv   r=   r¯   rK   rK   rL   Úwrite_inverse_operatorQ  s    
r¶   c                 C   s€  t | tjƒ t| |d ƒ t | tjƒ t| tj|d d ƒ t| |d ƒ t| tjƒ t	| |d ƒ d|krzt
| |d ƒ t | tjƒ t d¡ t| tj|d ƒ t| tj|d ƒ tjtjtjd	œ}d
|krð|d
 d k	rðt| tj||d
  ƒ t| tj|d ƒ t| tj|d ƒ d|k�r2t| tj|d ƒ n$d|d k�rVt| tj|d d ƒ t| tj|d ƒ t| tj|d ƒ t d¡ t| |d ƒ t d¡ t| |d ƒ t d¡ |d d k	�rÐt| |d ƒ |d d k	�rìt| |d ƒ |d d k	�rt| |d ƒ t| tj|d ƒ |d �r,tj}ntj }t!|d ƒ t| ||d ƒ t!|d ƒ t d¡ t| tjƒ t| tjƒ d S )NrN   Zmri_filerŒ   rŽ   rP   z$    Writing inverse operator info...rw   ry   )rz   r{   r|   r   rS   rQ   rx   r€   r‚   z$    Writing noise covariance matrix.rh   z%    Writing source covariance matrix.r†   z    Writing orientation priors.rˆ   r‡   r‰   r…   rƒ   r„   r�   )"r   r	   Z	FIFFB_MNEr.   r–   r   ZFIFF_MNE_FILE_NAMEr   r   r   r4   r”   r<   rN   r   r—   rœ   rž   rŸ   r    r�   rš   r›   Z
FIFF_NCHANr   r£   r   r¤   r"   r   r§   r¦   r¥   r   )r¯   rn   ZudictrU   rK   rK   rL   rµ   t  sd    
þ
ÿ




rµ   c                 C   s�   | j dkrtdƒ‚| jd d dkr,tdƒ‚t | ¡r@t | ¡} | ddd… d }|| ddd… d 7 }|| ddd… d 7 }|sŒt |¡}|S )aX  Compute the three Cartesian components of a vector or matrix together.

    Parameters
    ----------
    vec : 2d array of shape [3 n x p]
        Input [ x1 y1 z1 ... x_n y_n z_n ] where x1 ... z_n
        can be vectors

    Returns
    -------
    comb : array
        Output vector [sqrt(x1^2+y1^2+z1^2), ..., sqrt(x_n^2+y_n^2+z_n^2)]
    r   zInput must be 2Dr   é   zInput must have 3N rowsNr   )Úndimrm   ÚshapeÚnpZiscomplexobjÚabsr   )ZvecZsquareÚcombrK   rK   rL   Úcombine_xyzÓ  s    



r½   c                 C   sv   | d d }| d j |kr"tdƒ‚|d }tt|ƒt|ƒ ƒ}t|ƒ}|dkrbtd| d|  ƒ‚t| d	 |d
ƒ dS )z9Check that channels in inverse operator are measurements.r…   Ú	col_namesrh   zQChannels in inverse operator eigen fields do not match noise covariance channels.rj   r   z %d channels in inverse operator z are not present in the data (%s)rN   ZinverseN)rj   rm   ÚsortedÚsetrT   r@   )rn   rN   Zinv_ch_namesZdata_ch_namesZmissing_ch_namesZ	n_missingrK   rK   rL   Ú_check_ch_namesï  s    ÿrÁ   Tc                 C   s.   |st | |||||d�} nd| kr*tdƒ‚| S )z-Check if inverse was prepared, or prepare it.©rM   Úcolorerzƒinverse operator has not been prepared, but got argument prepared=True. Either pass prepared=False or use prepare_inverse_operator.)Úprepare_inverse_operatorrm   )rn   r�   Úlambda2ÚmethodÚmethod_paramsÚpreparedrM   rK   rK   rL   Ú_check_or_prepare   s         ÿrÉ   rF   c              	   C   s”  ddl m} |dkrtdƒ‚t|ttfdƒ t|tƒrFtd|ddd� t 	d¡ | }|r˜| d	 }	|d
krpd| d	< z|  
¡ }W 5 |	| d	< X |d
kr˜|	|d	< ~ t|d ƒ| }
|
|d d  |d d< |d d jdk�rt 	d¡ |d d |d d< t t|d d ƒ¡|d d< |
|d d  |d d< |
|d d  |d d< |d �rht|
ƒ|d d  |d d< t 	d|d |f ¡ ||d< t||ƒ|d< t 	d¡ t|d |d d ƒ\|d< }}|dk�rØt 	d| ¡ n
t 	d¡ t|d ddd �\|d!< }|d"< g |d#< |d$k�r$t|||ƒ �nh|d%k�r„t 	d&| ¡ |d'k�rP|d }n,|d(k�r||d t d)|d* d+ |  ¡ }t |d d, ¡}| d-|f¡\}|d �rêt|d d, ƒD ].}|d d |dd…f | }||ƒ||< �q¸nTt|d d, ƒD ]B}t|d d | ƒ|d d |dd…f  | }||ƒ||< �qú|d. tjk�rft|dd…df ƒ ¡ }d)t |¡ |d#< t 	d/¡ ng |d#< t|ƒS )0a³  Prepare an inverse operator for actually computing the inverse.

    Parameters
    ----------
    orig : dict
        The inverse operator structure read from a file.
    nave : int
        Number of averages (scales the noise covariance).
    lambda2 : float
        The regularization factor. Recommended to be 1 / SNR**2.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm, dSPM (default), sLORETA, or eLORETA.
    method_params : dict | None
        Additional options for eLORETA. See Notes of :func:`apply_inverse`.

        .. versionadded:: 0.16
    copy : bool | str
        If True (default), copy the inverse. False will not copy.
        Can be "non-src" to avoid copying the source space, which typically
        is not modified and can be large in memory.

        .. versionadded:: 0.21
    %(verbose)s

    Returns
    -------
    inv : instance of InverseOperator
        Prepared inverse operator.
    r   )Úlinalgz)The number of averages should be positiverM   )únon-srczwhen a string)Úextraz)Preparing the inverse operator for use...rP   rË   Nr�   rh   r}   r   z#    Diagonal noise covariance foundÚeigÚeigvecr†   rƒ   r„   zB    Scaled noise and source covariance from nave = %d to nave = %dr‘   z$    Created the regularized inverterrŽ   Únamesr�   z5    Created an SSP operator (subspace dimension = %d)z:    The projection vectors do not apply to these channels.ÚwhiteT)ÚpcaZreturn_colorerr�   rÃ   r’   rH   rE   z1    Computing noise-normalization factors (%s)...rF   rG   ç      ð?r‚   r   Únrow)Únrm2rS   ú[done])ZscipyrÊ   rm   r?   ÚboolÚstrÚ
isinstancerA   r<   rN   rM   Úfloatr¸   rº   ÚeyerT   r   Ú_compute_reginvr   r    r   ZzerosZget_blas_funcsr«   r	   rV   r½   Úravelr»   rI   )Úorigr�   rÅ   rÆ   rÇ   rM   r=   rÊ   rn   rP   ÚscaleÚncompr®   Znoise_weightÚ
noise_normrÔ   r²   ÚonerK   rK   rL   rÄ     sž     





ÿ

ÿ
ÿ
  ÿ

ÿ


ÿ
ÿÿ	rÄ   c                 C   s®  | d d }| d d }|dkr8| d dd…t jf }nd}| d }	t|	ƒ}
| d }|dk	rÈt||	ƒ\}
}|d	krz|| }| d
 tjkr°d| }t j||d |d f }| ¡ }|| }|| }|| }|dk�r°tdd„ |	D ƒƒ�r°t j	| d  
| d dd¡t  d¡dd��r°d}t  
|dd|jd f¡ ¡ }t  
|d¡ ¡ }t|	|
ƒD ]N\}}t||t|ƒ ƒ}tt|||ƒƒ||< t  || || ¡||< |j}�qJd|jd f|_d|_|dk�r| d
 tjk�sÒtdƒ‚d| d d d   k �oòdkn  }|�stdƒ‚t  | d d t  | d | d ¡¡}|| d dd…df 9 }t  ||¡}| d �rdt d ¡ n&t d!¡ |t  |¡dd…t jf 9 }|dk�r¢|ddd… }|||
|fS )"a]  Assemble the kernel.

    Simple matrix multiplication followed by combination of the current
    components. This does all the data transformations to compute the weights
    for the eigenleads.

    Parameters
    ----------
    inv : instance of InverseOperator
        The inverse operator to use. This object contains the matrices that
        will be multiplied to assemble the kernel.
    label : Label | None
        Restricts the source estimates to a given label. If None,
        source estimates will be computed for the entire source space.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm, dSPM, sLORETA, or eLORETA.
    pick_ori : None | "normal" | "vector"
        Which orientation to pick (only matters in the case of 'normal').
    %(use_cps_restricted)s

    Returns
    -------
    K : array, shape (n_vertices, n_channels) | (3 * n_vertices, n_channels)
        The kernel matrix. Multiply this with the data to obtain the source
        estimate.
    noise_norm : array, shape (n_vertices, n_samples) | (3 * n_vertices, n_samples)
        Normalization to apply to the source estimate in order to obtain dSPM
        or sLORETA solutions.
    vertices : list of length 2
        Vertex numbers for lh and rh hemispheres that correspond to the
        vertices in the source estimate. When the label parameter has been
        set, these correspond to the vertices in the label. Otherwise, all
        vertex numbers are returned.
    source_nn : array, shape (3 * n_vertices, 3)
        The direction in cartesian coordicates of the direction of the source
        dipoles.
    r„   r}   r†   )rF   rG   r’   NrP   r€   )rE   rH   rS   r·   r   r   Únormalc                 s   s   | ]}|d  dkV  qdS )ÚtypeZsurfNrK   )Ú.0r±   rK   rK   rL   Ú	<genexpr>ì  s     z#_assemble_kernel.<locals>.<genexpr>rQ   g�íµ ÷Æ°>)Zatolr   r~   )r~   r·   r·   )r~   r·   zUPicking normal orientation can only be done with a free orientation inverse operator.r‡   zQPicking normal orientation can only be done when working with loose orientations.r…   r�   r�   r‘   rƒ   z$    Eigenleads already weighted ... z&    Eigenleads need to be weighted ...)rº   Únewaxisr3   r5   r	   rV   Zc_rÜ   ÚallZallcloseÚreshaperÚ   r¹   rM   ÚzipÚslicerT   r6   r1   ÚmatmulÚstoprm   Údotr<   rN   r   )rn   ÚlabelrÆ   Úpick_oriÚuse_cpsr=   r„   r†   rà   rP   Úvertnor€   Zsrc_selÚoffsetr±   ÚvÚslZis_looseZtransÚKrK   rK   rL   Ú_assemble_kernelª  sp    ' ÿÿ ÿ

&ÿ


rö   c                 C   s    t d| dddgƒ t| |ƒ dS )zCheck pick_ori.rï   Nrâ   Úvector)rA   rC   )rï   rS   rP   Zallow_vectorrK   rK   rL   Ú
_check_ori"  s    rø   c                    s\   | j }ˆ dk	r4‡ fdd„t|d ƒD ƒ}t||d�}t|ƒrDtdƒ‚| dd¡rXtd	ƒ‚dS )
zCheck for EEG ref.Nc                    s   g | ]\}}|ˆ kr|‘qS rK   rK   )rä   ÚciZch_name©rj   rK   rL   Ú
<listcomp>,  s    ÿz$_check_reference.<locals>.<listcomp>rj   )ro   zvEEG average reference (using a projector) is mandatory for modeling, use the method set_eeg_reference(projection=True)Zcustom_ref_appliedFz9Custom EEG reference is not allowed for inverse modeling.)rN   Ú	enumerater   r   rm   r¡   )r³   rj   rN   ZpicksrK   rú   rL   Ú_check_reference(  s    ÿrý   c                 C   s
   | d j S )z%Get subject id from inverse operator.rP   )Z_subject)Úinverse_operatorrK   rK   rL   Ú_subject_from_inverse8  s    rÿ   çÇqÇq¼?c                 C   s(   t | |||||||||	ƒ
}t d¡ |S )a’  Apply inverse operator to evoked data.

    Parameters
    ----------
    evoked : Evoked object
        Evoked data.
    inverse_operator : instance of InverseOperator
        Inverse operator.
    lambda2 : float
        The regularization parameter.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm :footcite:`HamalainenIlmoniemi1994`,
        dSPM (default) :footcite:`DaleEtAl2000`,
        sLORETA :footcite:`Pascual-Marqui2002`, or
        eLORETA :footcite:`Pascual-Marqui2011`.
    %(pick_ori)s
    prepared : bool
        If True, do not call :func:`prepare_inverse_operator`.
    label : Label | None
        Restricts the source estimates to a given label. If None,
        source estimates will be computed for the entire source space.
    method_params : dict | None
        Additional options for eLORETA. See Notes for details.

        .. versionadded:: 0.16
    return_residual : bool
        If True (default False), return the residual evoked data.
        Cannot be used with ``method=='eLORETA'``.

        .. versionadded:: 0.17
    %(use_cps_restricted)s

        .. versionadded:: 0.20
    %(verbose)s

    Returns
    -------
    stc : SourceEstimate | VectorSourceEstimate | VolSourceEstimate
        The source estimates.
    residual : instance of Evoked
        The residual evoked data, only returned if return_residual is True.

    See Also
    --------
    apply_inverse_raw : Apply inverse operator to raw object.
    apply_inverse_epochs : Apply inverse operator to epochs object.

    Notes
    -----
    Currently only the ``method='eLORETA'`` has additional options.
    It performs an iterative fit with a convergence criterion, so you can
    pass a ``method_params`` :class:`dict` with string keys mapping to values
    for:

        'eps' : float
            The convergence epsilon (default 1e-6).
        'max_iter' : int
            The maximum number of iterations (default 20).
            If less regularization is applied, more iterations may be
            necessary.
        'force_equal' : bool
            Force all eLORETA weights for each direction for a given
            location equal. The default is None, which means ``True`` for
            loose-orientation inverses and ``False`` for free- and
            fixed-orientation inverses. See below.

    The eLORETA paper :footcite:`Pascual-Marqui2011` defines how to compute
    inverses for fixed- and
    free-orientation inverses. In the free orientation case, the X/Y/Z
    orientation triplet for each location is effectively multiplied by a
    3x3 weight matrix. This is the behavior obtained with
    ``force_equal=False`` parameter.

    However, other noise normalization methods (dSPM, sLORETA) multiply all
    orientations for a given location by a single value.
    Using ``force_equal=True`` mimics this behavior by modifying the iterative
    algorithm to choose uniform weights (equivalent to a 3x3 diagonal matrix
    with equal entries).

    It is necessary to use ``force_equal=True``
    with loose orientation inverses (e.g., ``loose=0.2``), otherwise the
    solution resembles a free-orientation inverse (``loose=1.0``).
    It is thus recommended to use ``force_equal=True`` for loose orientation
    and ``force_equal=False`` for free orientation inverses. This is the
    behavior used when the parameter ``force_equal=None`` (default behavior).

    References
    ----------
    .. footbibliography::
    rÕ   )Ú_apply_inverser<   rN   )Úevokedrþ   rÅ   rÆ   rï   rÈ   rî   rÇ   Úreturn_residualrð   r=   ÚoutrK   rK   rL   Úapply_inverse=  s    _        þ
r  ú    c                 C   sT   | | }d||  ¡   ¡ j| |   ¡   ¡ j  }|d9 }t |› d|d›d�¡ |S )Nr   éd   z
Explained z5.1fz
% variance)ZconjÚsumÚrealr<   rN   )r}   ZestÚprefixÚresZvar_exprK   rK   rL   Ú_log_exp_var£  s    ÿr  c
              
   C   sr  t | tdƒ t| |d d ƒ td|tƒ t||d |d ƒ | j}
t|| jƒ t	||
||||dd�}~t
| j|ƒ}t d	| jf ¡ t d
t|ƒ ¡ t d¡ t|||||	d�\}}}}t || j| ¡}t d¡ |d |d  }t |d t |d | j| ¡¡}t |d d |¡}t |d t |d d j|d d …tjf | ¡¡}t |d t |d |¡¡}t||ƒ |�r˜|  ¡ }|j|  |8  < |d tjk�o®|dk}|�rÒ|dk�rÒt d¡ t|ƒ}|d k	�rt d|f ¡ |�r
|dk�r
|jddd�}||9 }d| jd  }t| jd ƒ}t|ƒ}t|d |ƒ}t||||||dk||d�}|�rn||fS |S )Nr  rN   rj   rÆ   rS   rP   rË   rÂ   z$Applying inverse operator to "%s"...ú$    Picked %d channels from the dataú    Computing inverse...)rð   z    Computing residual...r‚   r‘   r�   r�   r…   r}   rÃ   râ   r÷   ú'    Combining the current components...z	    %s...r·   r   ©ÚaxisrÒ   Úsfreq©ÚtminÚtstepÚsubjectr÷   r€   Úsrc_type) r?   r'   rý   rA   ÚINVERSE_METHODSrø   r�   rÁ   rN   rÉ   rq   rj   r<   ÚcommentrT   rö   rº   rí   r}   ÚTræ   r  rM   r	   rV   r½   ÚrepeatrÙ   Útimesrÿ   r:   r9   )r  rþ   rÅ   rÆ   rï   rÈ   rî   rÇ   r  rð   r�   rn   ro   rõ   rà   rñ   r€   ÚsolÚPiZdata_wZw_tZdata_estZ
data_est_wZresidualÚis_free_orir  r  r  r  ÚstcrK   rK   rL   r  ¬  s~    
ÿ
  ÿ
    ÿ

ÿ
ÿÿ
ÿ

 þr  c           #   
   C   s’  t | tdƒ t| |d d ƒ td|tƒ t|	|d |d ƒ t|| jƒ t||||||ƒ}t	| j
|ƒ}t d¡ t dt|ƒ ¡ t d	¡ | |||…f \}}|d
k	r²||ƒ}t||||	|ƒ\}}}}|d tjkoÞ|	dk}|
d
k	�rÚ|�rÚtt |jd t|
ƒ ¡ƒ}t d| ¡ |jd }|	dk�r8|jd n|jd d }tj||ft ||¡d�}td||
ƒD ]j}t ||d
d
…|||
 …f ¡}|	dk�r¢t|ƒ}||d
d
…|||
 …f< t d||
 d |f ¡ �qln.t ||¡}|�r|	dk�rt d¡ t|ƒ}|d
k	�r8|	dk�r0|�r0|jddd�}||9 }t|d ƒ}d| jd  }t|ƒ} t|d |ƒ}!t||||| |	dk||!d�}"t d¡ |"S )aˆ  Apply inverse operator to Raw data.

    Parameters
    ----------
    raw : Raw object
        Raw data.
    inverse_operator : dict
        Inverse operator.
    lambda2 : float
        The regularization parameter.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm, dSPM (default), sLORETA, or eLORETA.
    label : Label | None
        Restricts the source estimates to a given label. If None,
        source estimates will be computed for the entire source space.
    start : int
        Index of first time sample (index not time is seconds).
    stop : int
        Index of first time sample not to include (index not time is seconds).
    nave : int
        Number of averages used to regularize the solution.
        Set to 1 on raw data.
    time_func : callable
        Linear function applied to sensor space time series.
    %(pick_ori)s
    buffer_size : int (or None)
        If not None, the computation of the inverse and the combination of the
        current components is performed in segments of length buffer_size
        samples. While slightly slower, this is useful for long datasets as it
        reduces the memory requirements by approx. a factor of 3 (assuming
        buffer_size << data length).
        Note that this setting has no effect for fixed-orientation inverse
        operators.
    prepared : bool
        If True, do not call :func:`prepare_inverse_operator`.
    method_params : dict | None
        Additional options for eLORETA. See Notes of :func:`apply_inverse`.

        .. versionadded:: 0.16
    %(use_cps_restricted)s

        .. versionadded:: 0.20
    %(verbose)s

    Returns
    -------
    stc : SourceEstimate | VectorSourceEstimate | VolSourceEstimate
        The source estimates.

    See Also
    --------
    apply_inverse_epochs : Apply inverse operator to epochs object.
    apply_inverse : Apply inverse operator to evoked object.
    ÚrawrN   rj   rÆ   rS   rP   zApplying inverse to raw...r  r  Nrâ   r   zQ    computing inverse and combining the current components (using %d segments)...r÷   r   r·   ©Údtypez        segment %d / %d done..z'    combining the current components...r  rÒ   r  r  rÕ   )r?   r   rý   rA   r  rø   rÁ   rN   rÉ   rq   rj   r<   rT   rö   r	   rV   r™   rº   Úceilr¹   rÙ   ÚemptyZresult_typer«   rí   r½   r  rÿ   r:   r9   )#r!  rþ   rÅ   rÆ   rî   Ústartrì   r�   Z	time_funcrï   Úbuffer_sizerÈ   rÇ   rð   r=   rn   ro   r}   r  rõ   rà   rñ   r€   r  Zn_segÚn_timesZ	n_dipolesr  ÚposZ	sol_chunkr  r  r  r  r   rK   rK   rL   Úapply_inverse_rawï  s‚    <
ÿ
 ÿ

    ÿÿÿÿ
" 
ÿ

 þ
r*  c                 c   s  t | tdƒ td|tƒ t||d |d ƒ t|| jƒ t||||||ƒ}t| j	|ƒ}t
 dt|ƒ ¡ t
 d¡ t|||||	ƒ\}}}}d| jd  }| jd	 }t|ƒp°|d
k }|dkrÒ|dk	rÒ|jdd	d�}|sæ|dk	ræ||9 }t|ƒ}zdt| ƒf }W n& tk
�r&   dt| jƒf }Y nX t| ƒD ]È\}}t
 d|d |f ¡ |�r”t ||| ¡}|dk�r€t
 d¡ t|ƒ}|dk	�rÆ||9 }n2t|ƒ|jd k �r¶||| f}nt ||| ¡}t|d |ƒ}t||||||dk||d�}|V  �q0t
 d¡ dS )zDGenerate inverse solutions for epochs. Used in apply_inverse_epochs.ÚepochsrÆ   rS   rP   ú Picked %d channels from the datazComputing inverse...rÒ   r  r   râ   r÷   Nr·   r  z / %dz / %d (at most)zProcessing epoch : %d%sr   z#combining the current components...r  rÕ   )r?   r%   rA   r  rø   rÁ   rN   rÉ   rq   rj   r<   rT   rö   r  r*   r  rÿ   ÚRuntimeErrorÚeventsrü   rº   rí   r½   r¹   r:   r9   )r+  rþ   rÅ   rÆ   rî   r�   rï   rÈ   rÇ   rð   r=   rn   ro   rõ   rà   rñ   r€   r  r  r  r  Útotalr²   Úer  r  r   rK   rK   rL   Ú_apply_inverse_epochs_genu  sl    
ÿ
 ÿ
    ÿ
ÿ



 þ
r1  c                 C   s4   t | |||||||||	|
d�}|s0dd„ |D ƒ}|S )a‡  Apply inverse operator to Epochs.

    Parameters
    ----------
    epochs : Epochs object
        Single trial epochs.
    inverse_operator : dict
        Inverse operator.
    lambda2 : float
        The regularization parameter.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm, dSPM (default), sLORETA, or eLORETA.
    label : Label | None
        Restricts the source estimates to a given label. If None,
        source estimates will be computed for the entire source space.
    nave : int
        Number of averages used to regularize the solution.
        Set to 1 on single Epoch by default.
    %(pick_ori)s
    return_generator : bool
        Return a generator object instead of a list. This allows iterating
        over the stcs without having to keep them all in memory.
    prepared : bool
        If True, do not call :func:`prepare_inverse_operator`.
    method_params : dict | None
        Additional options for eLORETA. See Notes of :func:`apply_inverse`.

        .. versionadded:: 0.16
    %(use_cps_restricted)s

        .. versionadded:: 0.20
    %(verbose)s

    Returns
    -------
    stc : list of (SourceEstimate | VectorSourceEstimate | VolSourceEstimate)
        The source estimates for all epochs.

    See Also
    --------
    apply_inverse_raw : Apply inverse operator to raw object.
    apply_inverse : Apply inverse operator to evoked object.
    )rÆ   rî   r�   rï   r=   rÈ   rÇ   rð   c                 S   s   g | ]}|‘qS rK   rK   )rä   r   rK   rK   rL   rû   õ  s     z(apply_inverse_epochs.<locals>.<listcomp>)r1  )r+  rþ   rÅ   rÆ   rî   r�   rï   Zreturn_generatorrÈ   rÇ   rð   r=   ZstcsrK   rK   rL   Úapply_inverse_epochs¾  s     0        ýr2  c                    s†  t ˆ tˆ ƒ t |tdƒ tˆ d |ƒ}‡ fdd„|D ƒ}t|t|d |dd�ƒ}tt t	|d ƒ¡||dd	�}|d
 t
jk}td|dƒ |rž|dkržd}d}n|}d}t||||||||	d|
d�
}t |jd|jjd f¡}ˆ j| dd…|f |j }tj||j ddd�}|jjdd… d |_| ||j|j|j|j¡}|�rxt d¡ tj|j|jd� | ¡ }| j|j9  _t d¡ |S )aq  Apply inverse operator to covariance data.

    Parameters
    ----------
    cov : instance of Covariance
        Covariance data, computed on the time segment for which to compute
        source power.
    %(info_not_none)s Used specify the channels to include.
    inverse_operator : instance of InverseOperator
        Inverse operator.
    nave : int
        Number of averages used to regularize the solution.
    lambda2 : float
        The regularization parameter.
    method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
        Use minimum norm, dSPM (default), sLORETA, or eLORETA.
    %(pick_ori_novec)s
    prepared : bool
        If True, do not call :func:`prepare_inverse_operator`.
    label : Label | None
        Restricts the source estimates to a given label. If None,
        source estimates will be computed for the entire source space.
    method_params : dict | None
        Additional options for eLORETA. See Notes for details.
    %(use_cps)s
    %(verbose)s

    Returns
    -------
    stc : SourceEstimate | VectorSourceEstimate | VolSourceEstimate
        The source estimates.

    See Also
    --------
    apply_inverse : Apply inverse operator to evoked object.
    apply_inverse_raw : Apply inverse operator to raw object.
    apply_inverse_epochs : Apply inverse operator to epochs object.

    Notes
    -----
    .. versionadded:: 0.20

    This code is based on the original research code from
    :footcite:`Sabbagh2020` and has been useful to correct for individual field
    spread using source localization in the context of predictive modeling.

    References
    ----------
    .. footbibliography::
    rþ   rÏ   c                    s   g | ]}ˆ d  | ‘qS )rÏ   rK   )rä   Úidx©ÚcovrK   rL   rû   4  s     z%apply_inverse_cov.<locals>.<listcomp>rj   T)Úorderedr5  )r�   r  rS   rï   )Nrâ   Nr÷   F)r  rð   r~   r   )r  Zkeepdims)r   r  ©r  rÕ   )r?   r#   rI   rq   r   r   r&   rº   rÚ   rT   r	   rV   rA   r  rè   r}   r¹   r  r  Ú	__class__Zverticesr  r  r  r<   rN   r   Z	magnitude)r5  rN   rþ   r�   rÅ   rÆ   rï   rÈ   rî   rÇ   rð   r=   ro   Z	use_namesr  r  Zuse_oriÚcombiner   rõ   r  rK   r4  rL   Úapply_inverse_covú  sf    7 ÿ   ÿ        þ    ÿ

r:  c              
   C   sö  |   ¡ } t| d ||ƒ}~tdd„ | ¡ D ƒƒ}tdd„ | ¡ D ƒƒ}|rnt|ƒdkr^tdƒ‚d|krntdƒ‚| dd¡dk r†td	ƒ‚|d
k	r´t|ƒ}|dk r¬td|› �ƒ‚|p²d
}|röt	| ƒsà|rôt
 d¡ t| dddd� n|d
k	rô|sôtdƒ‚n<t	| ƒ�rtdƒ‚|�r2| d �s2t
 d¡ t| d|dd� t| ||dd�\} }t
 dt|d ƒ ¡ |d
k�rld
}nt| |||	|
|||d�}|�rÎd
}t	| ƒ�sî|d
k	�rºt
 d¡ |dd
d… }t| dd|dd� n |�râ| d �sât‚t| |d�}t
 d¡ t|||d |ƒ}t|||d |d|d �\}}t || d! d" ¡}t
 d#¡ tj|jd |jd$�}|d
k	�rl||9 }|d
k	�r~||9 }tj||d%� ||9 }t
 d&¡ tjj|d'd(�d }|d) dk ¡ }t || ¡}||9 }||9 }| ||||||||f	S )*z<Prepare a gain matrix and noise covariance for localization.rP   c                 s   s   | ]}|d kV  qdS )g        NrK   ©rä   ró   rK   rK   rL   rå   w  s     z#_prepare_forward.<locals>.<genexpr>c                 s   s   | ]}|d k V  qdS )rÒ   NrK   r;  rK   rK   rL   rå   x  s     r   z]Computing inverse solutions for mixed source spaces with fixed orientations is not supported.Úvolumez^Computing inverse solutions for volume source spaces with fixed orientations is not supported.zoComputing inverse solutions with restricted orientations (loose < 1) is not supported for volume source spaces.Nr   z9depth exponent should be greater than or equal to 0, got z0Converting forward solution to fixed orientationTF)Úforce_fixedrð   rM   z‡For a fixed orientation inverse solution with depth weighting, the forward solution must be free-orientation and in surface orientationziForward operator has fixed orientation and can only be used to make a fixed-orientation inverse operator.Úsurf_oriz2Converting forward solution to surface orientation)r>  rð   rM   rÂ   zSelected %d channelsrj   )ÚexpÚlimit_depth_chsr½   Úlimitrh   Úrankz`    Picked elements from a free-orientation depth-weighting prior into the fixed-orientation oner   r·   )r>  r=  rð   rM   )ÚloosezWhitening the forward solution.)rÑ   r=   rB  r  r}   z%Creating the source covariance matrixr"  r7  z#Adjusting source covariance matrix.Zfro)ÚordrÍ   )rM   r/   rç   ÚvaluesÚanyrT   rm   r¡   rÙ   r*   r<   rN   r,   r-   r(   ÚAssertionErrorr+   r$   r    rº   rí   Úonesr¹   r#  r   rÊ   Znormr  )ÚforwardrN   rh   ÚfixedrC  rB  rÑ   rð   r?  r@  r½   Zallow_fixed_depthrA  Zfixed_inverseZconstrained_inverseZinfo_pickedrˆ   r‡   r�   r®   ÚgainÚ
source_stdÚ
trace_GRGTÚn_nzerorÞ   rK   rK   rL   Ú_prepare_forwardZ  sÜ    
   ÿÿ
ÿ
   ÿÿ

     ý


   þ
   ÿ    þ




  ÿrO  Úautoçš™™™™™é?c	                    sn  t |dƒ}tˆ | ||||fd|dœ|—Ž\	‰ }	}
}}}}}}tt|	d ƒdˆ d ˆ d ˆ d d	ˆ d
 ˆ d ˆ d dtˆ d ƒd�}‡ fdd„| d D ƒ|d d< |d  ¡  ~~~~Š t d¡ t|
dd�\}}}~
t dt 	|¡ ¡ t d|d›d|j
d › d|d dk ¡ › d�¡ t|j|	d g |j
d |j
d d�}t|j|j
d |j
d g g d �}d}d}t|	d! ƒD ]6}t|	|ƒ}|d"k�rŽd#}|d$k�s¢|d%k�rrd#}�qr|�r¾|�r¾tj}n|�rÌtj}ntj}|dk	�rüt|tjg d#g dd|jdg d&�
}|dk	�r&t|tjg d#g dd|jdg d&�
}t|| |jtjd#g g dddg d'�
}|j|||d(|||||d)�	 t|ƒS )*aÿ  Assemble inverse operator.

    Parameters
    ----------
    %(info_not_none)s
        Specifies the channels to include. Bad channels (in ``info['bads']``)
        are not used.
    forward : dict
        Forward operator.
    noise_cov : instance of Covariance
        The noise covariance matrix.
    %(loose)s
    %(depth)s
    fixed : bool | 'auto'
        Use fixed source orientations normal to the cortical mantle. If True,
        the loose parameter must be "auto" or 0. If 'auto', the loose value
        is used.
    %(rank_none)s
    %(use_cps)s
    %(verbose)s

    Returns
    -------
    inv : instance of InverseOperator
        Inverse operator.

    Notes
    -----
    For different sets of options (**loose**, **depth**, **fixed**) to work,
    the forward operator must have been loaded using a certain configuration
    (i.e., with **force_fixed** and **surf_ori** set appropriately). For
    example, given the desired inverse type (with representative choices
    of **loose** = 0.2 and **depth** = 0.8 shown in the table in various
    places, as these are the defaults for those parameters):

        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | Inverse desired                             | Forward parameters allowed                 |
        +=====================+===========+===========+===========+=================+==============+
        |                     | **loose** | **depth** | **fixed** | **force_fixed** | **surf_ori** |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Loose constraint, | 0.2       | 0.8       | False     | False           | True         |
        | | Depth weighted    |           |           |           |                 |              |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Loose constraint  | 0.2       | None      | False     | False           | True         |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Free orientation, | 1.0       | 0.8       | False     | False           | True         |
        | | Depth weighted    |           |           |           |                 |              |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Free orientation  | 1.0       | None      | False     | False           | True | False |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Fixed constraint, | 0.0       | 0.8       | True      | False           | True         |
        | | Depth weighted    |           |           |           |                 |              |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+
        | | Fixed constraint  | 0.0       | None      | True      | True            | True         |
        +---------------------+-----------+-----------+-----------+-----------------+--------------+

    Also note that, if the source space (as stored in the forward solution)
    has patch statistics computed, these are used to improve the depth
    weighting. Thus slightly different results are to be expected with
    and without this information.

    For depth weighting, 0.8 is generally good for MEG, and between 2 and 5
    is good for EEG, see :footcite:`LinEtAl2006a`.

    References
    ----------
    .. footbibliography::
    Z	depth_mnerÐ   )rÑ   rð   rŽ   FrS   rŒ   rQ   rz   ry   r€   rP   NrN   )rŽ   rƒ   rS   rŒ   rQ   r   ry   r€   rP   r‰   rN   c                    s    g | ]}|ˆ d  d kr|‘qS )rN   rj   rK   )rä   Úbad©rI  rK   rL   rû   ?  s    ÿz)make_inverse_operator.<locals>.<listcomp>Úbadsz9Computing SVD of whitened and weighted lead field matrix.)Zfull_matricesz    largest singular value = %gz)    scaling factor to adjust the trace = Úgz
 (nchan = r   z	 nzero = rÍ   ú)rj   r   )r}   r¾   Ú	row_namesrÓ   Úncol)r}   rÓ   rX  rW  r¾   rx   rO   TÚmagZgrad)
r}   rU   rT  ÚdiagrÏ   rÍ   rÎ   ÚdimÚnfreerŽ   )
r}   r[  rU   rZ  rÏ   rŽ   rÍ   rÎ   r\  rT  rÒ   )	r…   r„   r‚   r�   rˆ   r†   rh   r‡   rw   )rB   rO  r˜   r   Z_check_consistencyr<   rN   r   rº   Úmaxr¹   r  r  r«   r   r	   ZFIFFV_MNE_MEG_EEGZFIFFV_MNE_MEGZFIFFV_MNE_EEGr©   Úsizerª   r¨   ÚupdaterI   )rN   rI  rh   rC  ÚdepthrJ  rB  rð   r=   Z	gain_inforK  rˆ   r‡   rL  rM  r®   rn   r…   r‚   r„   Zhas_megZhas_eegr3  Zch_typerw   r†   rK   rS  rL   Úmake_inverse_operatoré  sØ    I
     ÿþþÿ  
      
û

2 þ þ


     ü
     ü     ý      ýra  c              	   C   st   t j| d t jd�}t  |¡}t| ƒ}|d|… }t jdd��, t  |dk||d |  d¡|d|…< W 5 Q R X |S )z Safely compute reginv from sing.r‚   r"  NÚignore)Úinvalidr   r   )rº   ÚarrayZfloat64Z
zeros_likeÚcompute_rank_inverseZerrstateÚwhere)rn   rÅ   r‚   r‘   rN  rK   rK   rL   rÛ   z  s    
  ÿrÛ   c                 C   sV   | d d }| d d s(t  |dk¡}n*t| d | d d ƒd }| d d | }|S )	zúCompute the rank of a linear inverse operator (MNE, dSPM, etc.).

    Parameters
    ----------
    inv : instance of InverseOperator
        The inverse operator.

    Returns
    -------
    rank : int
        The rank of the inverse operator.
    rh   rÍ   rZ  r   rŽ   rÏ   r   r[  )rº   r  r   )rn   rÍ   rB  rß   rK   rK   rL   re  †  s    re  c                 C   s  ddl m} t| |d d ƒ t|| jƒ t|| jdddd�}t| j|ƒ}t	 d	t
|ƒ ¡ t |d
 t |d | j| ¡¡}t |d d |¡}|j\}}t|ƒ}	||	 }
t	 d||
|	f ¡ ~tj|d dd�}||	 }t |¡}| d¡ t |t¡}|dk}tj||< d||< d}|d |d  dd…tjf }| d|	¡}tdƒD ]˜}|||tj dd…|f   }d||d dk< |dd…|f d|  }tj|| dd�}d|t |¡d ||k  < | ¡ �sÒ �qî||  |9  < �qLtdƒ dt |¡ }t |¡}||fS )a-  Estimate the SNR as a function of time for evoked data.

    Parameters
    ----------
    evoked : instance of Evoked
        Evoked instance.
    inv : instance of InverseOperator
        The inverse operator.
    %(verbose)s

    Returns
    -------
    snr : ndarray, shape (n_times,)
        The SNR estimated from the whitened data (i.e., GFP of whitened data).
    snr_est : ndarray, shape (n_times,)
        The SNR estimated using the mismatch between the unregularized
        solution and the regularized solution.

    Notes
    -----
    ``snr_est`` is estimated by using different amounts of inverse
    regularization and checking the mismatch between predicted and
    measured whitened data.

    In more detail, given our whitened inverse obtained from SVD:

    .. math::

        \tilde{M} = R^\frac{1}{2}V\Gamma U^T

    The values in the diagonal matrix :math:`\Gamma` are expressed in terms
    of the chosen regularization :math:`\lambda^2 \sim 1/\rm{SNR}^2`
    and singular values :math:`\lambda_k` as:

    .. math::

        \gamma_k = \frac{1}{\lambda_k}\frac{\lambda_k^2}{\lambda_k^2 + \lambda^2}

    We also know that our predicted data is given by:

    .. math::

        \hat{x}(t) = G\hat{j}(t)=C^\frac{1}{2}U\Pi w(t)

    And thus our predicted whitened data is just:

    .. math::

        \hat{w}(t) = U\Pi w(t)

    Where :math:`\Pi` is diagonal with entries entries:

    .. math::

        \lambda_k\gamma_k = \frac{\lambda_k^2}{\lambda_k^2 + \lambda^2}

    If we use no regularization, note that :math:`\Pi` is just the
    identity matrix. Here we test the squared magnitude of the difference
    between unregularized solution and regularized solutions, choosing the
    biggest regularization that achieves a :math:`\chi^2`-test significance
    of 0.001.

    .. versionadded:: 0.9.0
    r   )Úchi2rN   rj   r   rE   rË   rÂ   r,  r�   r�   r…   r}   zEffective nchan = %d - %d = %dr   r  g      $@r   Fg®Gáz®ï?r‚   Ngü©ñÒMbP?iè  rÒ   zSNR estimation did not converge)Zscipy.statsrg  rý   rÁ   rN   rÄ   r�   rq   rj   r<   rT   rº   rí   r}   r¹   re  r  r%  ÚfillrH  rÖ   Úinfræ   Zisfr«   rf  rF  r>   r   )r  rn   r=   rg  ro   Z
data_whiteZdata_white_efZn_chr(  Zn_ch_effZn_zeroÚsignalZsnrZlambda2_estÚ	remainingrR  Zlambda_multZsing2ÚvalZn_iterr¬   ÚewÚerrZsnr_estrK   rK   rL   Úestimate_snr   sR    Bÿ"
ÿ




ro  )F)T)rF   NTN)TN)T)N)	r   rF   NFNNFTN)r  )rF   NNNr   NNNFNTN)rF   Nr   NFNTN)	rF   Nr   NFFNTN)	r   r   rF   NFNNTN)rP  rQ  rP  NTN)N)urM   r   Úmathr   Únumpyrº   Z_eloretar   Úfixesr   Zio.baser   Zio.constantsr	   Zio.openr
   Zio.tagr   Z	io.matrixr   r   r   Zio.projr   r   r   r   Zio.treer   Zio.writer   r   r   r   r   r   r   r   Zio.pickr   r   r   r   r5  r    r!   r"   r#   r$   r+  r%   r  r&   r'   rI  r(   r)   r*   r+   r,   r-   Zforward.forwardr.   r/   Zsource_spacer0   r1   r2   r3   r4   r5   Zsurfacer6   Z
transformsr7   r8   Zsource_estimater9   r:   Úutilsr;   r<   r=   r>   r?   r@   rA   rB   rC   rD   r  r˜   rI   rq   r´   r¶   rµ   r½   rÁ   rÉ   rÄ   rö   rø   rý   rÿ   r  r  r  r*  r1  r2  r:  rO  ra  rÛ   re  ro  rK   rK   rK   rL   Ú<module>   sî   (  00 ]"_
 ÿ
      ÿ w

            ýe
	C                   ü             ý
I              ý;            ý_         ÿ 