U
    f»{jHw  ã                   @   sÔ  d dl mZ d dlZddlmZ ddlmZ ddlm	Z	m
Z
mZmZ ddlmZmZmZ ddlmZmZ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(m)Z)m*Z* ddl+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z< ddl=m>Z> dd„ Z?dd„ Z@dd„ ZAd2dd„ZBe8d3d d!„ƒZCe8d4d"d#„ƒZDe8d5d$d%„ƒZEd&d'„ ZFe8d6d(d)„ƒZGG d*d+„ d+eHƒZId7d,d-„ZJG d.d/„ d/eHƒZKd0d1„ ZLdS )8é    )ÚIterableNé   )Ú_get_stim_channel)Ú_Interp2)Ú
pick_typesÚ	pick_infoÚpick_channelsÚpick_channels_forward)Úmake_ad_hoc_covÚread_covÚ
Covariance)Úfit_sphere_to_headshapeÚmake_sphere_modelÚread_bem_solution)ÚRawArrayÚBaseRawÚInfo)Úread_head_posÚhead_pos_to_trans_rot_tÚget_chpi_infoÚ_get_hpi_initial_fit)ÚFIFF)
Ú_magnetic_dipole_field_vecÚ_merge_meg_eeg_fwdsÚ_stc_src_selÚconvert_forward_solutionÚ_prepare_for_forwardÚ_transform_orig_meg_coilsÚ_compute_forwardsÚ_to_forward_dictÚrestrict_forward_to_stcÚ_prep_meg_channels)Ú
_get_transÚtransform_surface_to)Ú_ensure_srcÚ_set_source_space_verticesÚsetup_volume_source_space)Ú_BaseSourceEstimate)Ú_CheckInside)ÚloggerÚverboseÚcheck_random_stateÚ_plÚ_validate_typeÚ_check_preloadé   )ÚSourceSimulatorc                 C   sl   t |tdttdfdƒ t|tƒsh|dkr*n>t|tƒrDt| |dd�}n$|dkr\t| ddd�}nt|dd�}|S )zECheck that the user provided a valid covariance matrix for the noise.Nz	path-likeÚcovF©r*   Úsimple)r-   r   ÚdictÚstrÚ
isinstancer
   r   )Úinfor1   © r8   úQ/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/simulation/raw.pyÚ
_check_cov%   s    
r:   c                 C   sp   t | tƒr| g} t| tdƒ t| ƒ}~ zt|ƒ}W n tk
rN   tdƒ‚Y nX t|d|d ƒ\}}}|||fS )Nz"SourceEstimate, tuple, or iterablezIterable did not provide stc[0]r/   Úsfreq)	r6   r'   r-   r   Ú	enumerateÚnextÚStopIterationÚRuntimeErrorÚ_stc_data_event)Ústcr7   Ústc_enumÚstc_countedÚ_Úvertsr8   r8   r9   Ú_check_stc_iterable4   s    
rF   c                 C   sH   |dk	r"dd|d |   }}}n
d\}}}t  | |  |¡| ¡ dS )zLog channel information.Nz stored on channel:é2   Úch_names)z not storedr   Ú )r)   r7   Úljust)Ústartr7   ÚchÚextraZjustr8   r8   r9   Ú_log_chF   s    
rN   c                    sü  ˆ d krt ƒ ‰ tˆ tƒr tˆ ƒ‰ tˆ tjƒr4tˆ ƒ‰ tˆ tƒrvˆ \}}}|ˆd  }|| }dd„ t||ƒD ƒ}~~nJtˆ t ƒr°t 	t
ˆ  ¡ ƒt¡}| ¡  ‡ fdd„|D ƒ}ntdtˆ ƒ ƒ‚|dk }	|	 ¡ rètd|	 ¡ t|	ƒf ƒ‚|d k	�r&||d k}	|	 ¡ �r&td	|d |	 ¡ t|	ƒf ƒ‚t|ƒdk�rT|d d
ˆd  k �rTd|d< n@t|ƒdk�sp|d dk�r”tjdg|f }| dˆd d ¡ ‡fdd„|D ƒ}t |ˆd  ¡ t¡}
t |
t |
¡¡�sÖt‚t|
ƒt|ƒk�sìt‚t
|
ƒ}
||
fS )Nr;   c                 S   s@   g | ]8\}}t jt j||d d …t jf f ddddggf ‘qS )Nr   r/   )ÚnpÚr_Zc_Únewaxis)Ú.0ÚrÚtr8   r8   r9   Ú
<listcomp>Z   s   ÿz#_check_head_pos.<locals>.<listcomp>c                    s   g | ]}ˆ t |ƒ ‘qS r8   )Úfloat)rR   Útt)Úhead_posr8   r9   rU   `   s     zunknown head_pos type %sr   z/All position times must be >= 0, found %s/%s< 0éÿÿÿÿz_All position times must be <= t_end (%0.1f sec), found %s/%s bad values (is this a split file?)ç      à?ç        Ú
dev_head_tÚtransc                    s(   g | ] }|ˆ d  d ˆ d  d dœ‘qS )r\   ÚtoÚfrom)r]   r^   r_   r8   )rR   Úd)r7   r8   r9   rU   t   s   þ
ÿ)r4   r6   r5   r   rO   Úndarrayr   ÚtupleÚzipÚarrayÚlistÚkeysrV   ÚsortÚ	TypeErrorÚtypeÚanyr?   ÚsumÚlenrP   ÚinsertÚroundÚastypeÚintÚarray_equalÚuniqueÚAssertionError)rX   r7   Ú
first_sampÚtimesZtranssZrotsÚtsZ
first_timeÚdev_head_tsÚbadÚoffsetsr8   )rX   r7   r9   Ú_check_head_posO   sV    


ÿ
ÿ

þ$

þrz   ç      ð?Úcos2Té'  c           %      C   sd  t | tdƒ tt| ddd�ƒdkr(d}nt| d td| ƒƒd }|
dk	ržtdd	„ ||||fD ƒƒrjtd
ƒ‚tj	|
d d d | d d dd�s–tdƒ‚|
d }t
|| |dƒ\}}t|dd�}t|tƒrÒt|dd�}t| ddg d�}t dt|ƒt|ƒ|f ¡ t|tƒ�r |j|k�r t d¡ t|| ƒ\}}}|
dk	�rNt|
|ƒ}
|
d }nt||ddd� t| ¡ |ƒ}tƒ }td| |ƒ d}t||| |||||||
|	ƒ}t|||ƒ}d}t|ƒD �]d}t|d ttfƒ�ræ|d d jj d }n|d jj d }|| }t d|| d  || d  f ¡ || }|dk�s6t!‚t "t| d ƒ|f¡}| #|¡ | $|| ¡\}}|d }t%||| d |j&|dk�rŽdn|ƒ\} }!}"|dk	�r¼|!d|… ||dd…f< t 'd|| ¡||< zt(|ƒ}W n< t)k
�r   t d|d t|d ƒf ¡ Y  �q,Y nX ~�q¶t*d|f ƒ‚tj+|dd �}#t,|#| |dd!�}$|$ -|$j.¡ t d"¡ |$S )#uÑ  Simulate raw data.

    Head movements can optionally be simulated using the ``head_pos``
    parameter.

    Parameters
    ----------
    %(info_not_none)s Used for simulation.

        .. versionchanged:: 0.18
           Support for :class:`mne.Info`.
    stc : iterable | SourceEstimate | SourceSimulator
        The source estimates to use to simulate data. Each must have the same
        sample rate as the raw data, and the vertices of all stcs in the
        iterable must match. Each entry in the iterable can also be a tuple of
        ``(SourceEstimate, ndarray)`` to allow specifying the stim channel
        (e.g., STI001) data accompany the source estimate.
        See Notes for details.

        .. versionchanged:: 0.18
           Support for tuple, iterable of tuple or `~mne.SourceEstimate`,
           or `~mne.simulation.SourceSimulator`.
    trans : dict | str | None
        Either a transformation filename (usually made using mne_analyze)
        or an info dict (usually opened using read_trans()).
        If string, an ending of ``.fif`` or ``.fif.gz`` will be assumed to
        be in FIF format, any other ending will be assumed to be a text
        file with a 4x4 transformation matrix (like the ``--trans`` MNE-C
        option). If trans is None, an identity transform will be used.
    src : str | instance of SourceSpaces | None
        Source space corresponding to the stc. If string, should be a source
        space filename. Can also be an instance of loaded or generated
        SourceSpaces. Can be None if ``forward`` is provided.
    bem : str | dict | None
        BEM solution  corresponding to the stc. If string, should be a BEM
        solution filename (e.g., "sample-5120-5120-5120-bem-sol.fif").
        Can be None if ``forward`` is provided.
    %(head_pos)s
        See for example :footcite:`LarsonTaulu2017`.
    mindist : float
        Minimum distance between sources and the inner skull boundary
        to use during forward calculation.
    %(interp)s
    %(n_jobs)s
    %(use_cps)s
    forward : instance of Forward | None
        The forward operator to use. If None (default) it will be computed
        using ``bem``, ``trans``, and ``src``. If not None,
        ``bem``, ``trans``, and ``src`` are ignored.

        .. versionadded:: 0.17
    first_samp : int
        The first_samp property in the output Raw instance.

        .. versionadded:: 0.18
    max_iter : int
        The maximum number of STC iterations to allow.
        This is a sanity parameter to prevent accidental blowups.

        .. versionadded:: 0.18
    %(verbose)s

    Returns
    -------
    raw : instance of Raw
        The simulated raw file.

    See Also
    --------
    mne.chpi.read_head_pos
    add_chpi
    add_noise
    add_ecg
    add_eog
    simulate_evoked
    simulate_stc
    simulate_sparse_stc

    Notes
    -----
    **Stim channel encoding**

    By default, the stimulus channel will have the head position number
    (starting at 1) stored in the trigger channel (if available) at the
    t=0 point in each repetition of the ``stc``. If ``stc`` is a tuple of
    ``(SourceEstimate, ndarray)`` the array values will be placed in the
    stim channel aligned with the :class:`mne.SourceEstimate`.

    **Data simulation**

    In the most advanced case where ``stc`` is an iterable of tuples the output
    will be concatenated in time as:

    .. table:: Data alignment and stim channel encoding

       +---------+--------------------------+--------------------------+---------+
       | Channel | Data                                                          |
       +=========+==========================+==========================+=========+
       | M/EEG   | ``fwd @ stc[0][0].data`` | ``fwd @ stc[1][0].data`` | ``...`` |
       +---------+--------------------------+--------------------------+---------+
       | STIM    | ``stc[0][1]``            | ``stc[1][1]``            | ``...`` |
       +---------+--------------------------+--------------------------+---------+
       |         | *time â†’*                                                      |
       +---------+--------------------------+--------------------------+---------+

    .. versionadded:: 0.10.0

    References
    ----------
    .. footbibliography::
    r7   FT)ÚmegZstimr   NrH   c                 s   s   | ]}|d k	V  qd S ©Nr8   )rR   Úxr8   r8   r9   Ú	<genexpr>ú   s     zsimulate_raw.<locals>.<genexpr>zJIf forward is not None then trans, src, bem, and head_pos must all be Noner\   r]   g�íµ ÷Æ°>)ZatolzoThe forward meg<->head transform forward["info"]["dev_head_t"] does not match the one in raw.info["dev_head_t"]Úsrcr2   ©r~   ÚeegÚexcludez<Setting up raw simulation: %s position%s, "%s" interpolationz3SourceSimulator first_samp does not match argument.ÚwarnrI   )Ú
on_missingrM   zEvent informationr/   z    Interval %0.3f-%0.3f secr;   ú
svt,vt->stz    %d STC iteration%s providedz.Maximum number of STC iterations (%d) exceededrY   ©Úaxis)rt   r*   z[done])/r-   r   rl   r   r   r   rj   Ú
ValueErrorrO   Úallcloserz   r$   r6   r5   r   r)   r7   r,   r0   rt   rF   r    r   r%   Úcopyre   rN   Ú_SimForwardsr   Úrangerb   ÚdataÚshapers   ÚzerosÚappendÚfeedr@   r‚   Úeinsumr=   r>   r?   Úconcatenater   Zset_annotationsÚannotations)%r7   rA   r]   r‚   ÚbemrX   ÚmindistÚinterpÚn_jobsÚuse_cpsÚforwardrt   Zmax_iterr*   Zevent_chrw   ry   Ú
meeg_picksrB   rC   rE   Z	raw_datasÚnÚget_fwdÚinterperZ
this_startZthis_nZ	this_stopZn_doingZ	this_dataÚfwdÚfiÚstc_dataÚ	stim_datarD   Úraw_dataÚrawr8   r8   r9   Úsimulate_raw~   sº    sÿÿ
 ÿ
ÿ



         þ

ÿÿ
   þ

ÿÿ
r¨   c                 C   s   t | d||||ƒS )uv  Add blink noise to raw data.

    Parameters
    ----------
    raw : instance of Raw
        The raw instance to modify.
    %(head_pos)s
    %(interp)s
    %(n_jobs)s
    %(random_state)s
        The random generator state used for blink, ECG, and sensor noise
        randomization.
    %(verbose)s

    Returns
    -------
    raw : instance of Raw
        The instance, modified in place.

    See Also
    --------
    add_chpi
    add_ecg
    add_noise
    simulate_raw

    Notes
    -----
    The blink artifacts are generated by:

    1. Random activation times are drawn from an inhomogeneous poisson
       process whose blink rate oscillates between 4.5 blinks/minute
       and 17 blinks/minute based on the low (reading) and high (resting)
       blink rates from :footcite:`BentivoglioEtAl1997`.
    2. The activation kernel is a 250 ms Hanning window.
    3. Two activated dipoles are located in the z=0 plane (in head
       coordinates) at Â±30 degrees away from the y axis (nasion).
    4. Activations affect MEG and EEG channels.

    The scale-factor of the activation function was chosen based on
    visual inspection to yield amplitudes generally consistent with those
    seen in experimental data. Noisy versions of the activation will be
    stored in the first EOG channel in the raw instance, if it exists.

    References
    ----------
    .. footbibliography::
    Úblink©Ú_add_exg©r§   rX   rš   r›   Úrandom_stater*   r8   r8   r9   Úadd_eogL  s    3r®   c                 C   s   t | d||||ƒS )ab  Add ECG noise to raw data.

    Parameters
    ----------
    raw : instance of Raw
        The raw instance to modify.
    %(head_pos)s
    %(interp)s
    %(n_jobs)s
    %(random_state)s
        The random generator state used for blink, ECG, and sensor noise
        randomization.
    %(verbose)s

    Returns
    -------
    raw : instance of Raw
        The instance, modified in place.

    See Also
    --------
    add_chpi
    add_eog
    add_noise
    simulate_raw

    Notes
    -----
    The ECG artifacts are generated by:

    1. Random inter-beat intervals are drawn from a uniform distribution
       of times corresponding to 40 and 80 beats per minute.
    2. The activation function is the sum of three Hanning windows with
       varying durations and scales to make a more complex waveform.
    3. The activated dipole is located one (estimated) head radius to
       the left (-x) of head center and three head radii below (+z)
       head center; this dipole is oriented in the +x direction.
    4. Activations only affect MEG channels.

    The scale-factor of the activation function was chosen based on
    visual inspection to yield amplitudes generally consistent with those
    seen in experimental data. Noisy versions of the activation will be
    stored in the first EOG channel in the raw instance, if it exists.

    .. versionadded:: 0.18
    Úecgrª   r¬   r8   r8   r9   Úadd_ecg‚  s    1r°   c           )      C   s¾  t |tƒr|dkst‚t| tdƒ t| d|f ƒ t|ƒ}| j| j| j	  }}}	| j
}
t|dddd�}t|dddd�}t|ddd	�d d
… \}}t||dddd�}d }t|||	|ƒ\}}|dk�rt t tjd ¡t tjd ¡dgt tjd ¡ t tjd ¡dgg¡}|t tj|| ddd�¡ }|d| 9 }||7 }t dddgdddgg¡}dt d
tj d d | ¡ d }|d9 }|d7 }|jt|ƒd�||d  k }||jt|ƒd�d  }t td|d  ƒ¡}t ||d¡tjd d …f d }t|dddd �}|}~~~�n<t|ƒd!k�r,td"ƒ‚t | d!d#| gg¡}tt |d$ d% d ¡ƒ}t | d&d'|¡|d  ¡ t¡}||t|ƒk  }t  t|ƒ¡}d||< tj!d
t td(|d  ƒ¡ d)t td*|d  ƒ¡ d+t td,|d  ƒ¡ gd$d-�}t ||d¡tjd d …f d. }t|dddd/�}|}~~~~t "|¡}d|d d …d!f< ~~| #|j$d ¡d0 }t|ƒdk�rš|d$ }|d1 | |
|d d …f< nd }t%t&||d2�d3d4�} t'd5| ||ƒ ~~~t  t| jƒt(¡}!t)||||| |d6||ƒ	}"t*||"|ƒ}#t !t +d!t|!ƒd7¡t|!ƒgg¡}$t,|$d d$… |$dd … ƒD ]p\}%}&|# -|&|% ¡\}'}(|
||%|&…f  t .d8|'|d d …|%|&…f ¡7  < |!|%|&…  /¡ �rœt‚d|!|%|&…< �q:|! 0¡ �sºt‚d S )9N)r¯   r©   r§   zAdding %s noise TFr8   rƒ   Úm)Zunitsr*   r   )g
×£p=
ï?g\�Âõ(\ï?g®Gáz®ï?r{   )ç…ëQ¸Õ?r{   gü©ñÒMbp?r²   )Zhead_radiusZrelative_radiiZsigmasr*   r©   g      @r[   é   r/   )rŠ   Zkeepdimsg¸…ëQ¸î?r{   g      N@g       @g«ªªªªªÊ?g333333³?)Úsizer;   rZ   g      Ð?ZsamegH¯¼šò×z>)r~   r„   Zeogr   z;Can only add ECG artifacts if MEG data channels are presentéýÿÿÿrY   g      T@g      è?g      ø?g{®Gáz¤?g333333Ó¿gš™™™™™©?gš™™™™™É?g¤p=
×£Ð?r‰   gvƒôõ!„>)r~   r„   r¯   gñhãˆµøÔ>g     @�@)ÚrrÚnnÚmm)ÚposZsphere_unitsz%s simulated and traceg{®Gázt?r}   rˆ   )1r6   r5   rs   r-   r   r.   r+   r7   ru   rt   Ú_datar   r   r   rz   rO   rd   ÚcosÚpiÚsinÚsqrtrk   Úuniformrl   Zhanningrp   ZconvolverQ   r?   ÚceilZcumsumro   r’   r–   Z
zeros_likeZstandard_normalr‘   r&   r4   rN   ÚboolrŽ   r   Úarangerc   r”   r•   rj   Úall))r§   ÚkindrX   rš   r›   r­   Úrngr7   ru   rt   r�   Ú	meg_picksrž   ÚRÚr0r˜   r]   rw   ry   Zexg_rrr·   Z
blink_rateZ
blink_dataZblink_kernelZexg_datarL   ÚpicksZ	max_beatsZcardiac_idxZcardiac_dataZcardiac_kernelÚnoiser‚   Úusedr    r¡   Z	proc_limsrK   Ústopr¢   rD   r8   r8   r9   r«   ¶  sÔ     þ
$"ÿ$ÿÿ
ÿ
ÿÿýýÿÿ
ÿ
ÿ        ÿ""  ÿr«   c                 C   s:  t | tdƒ t| dƒ | j| j| j  }}}t|ddg d�}t|ƒdkrPtdƒ‚t	||||ƒ\}	}
t
|dd	�\}}}t|d
d�}|t tj|| dd�¡dd…tjf  }| j}| ¡ ||dd…f< td||ƒ dt dtj |dd…tjf  t t|ƒ¡|d   ¡ }t||ƒ}| ¡ � |jg g d� W 5 Q R X t|dd�\}}}}t t| jƒt¡}|	 |	d ¡ t|
|	|||ƒ}t|
||ƒ}t |
t| jƒgg¡}t|dd… |dd… ƒD ]n\}}|  || ¡\}||||…f  t !d||dd…||…f ¡7  < |||…  "¡ �rt#‚d|||…< �q¸| $¡ �s6t#‚| S )aS  Add cHPI activations to raw data.

    Parameters
    ----------
    raw : instance of Raw
        The raw instance to be modified.
    %(head_pos)s
    %(interp)s
    %(n_jobs)s
    %(verbose)s

    Returns
    -------
    raw : instance of Raw
        The instance, modified in place.

    Notes
    -----
    .. versionadded:: 0.18
    r§   zAdding cHPI signals TFrƒ   r   z+Cannot add cHPI if no MEG picks are presentÚraise©r‡   Úerrorr2   r/   r‰   NzcHPI status bits enbled andg³zê]Êr>r   r;   ©ZprojsZbads)Z
ignore_refrY   rˆ   )%r-   r   r.   r7   rt   ru   r   rl   r?   rz   r   r   rO   r¾   rk   rQ   rº   rN   r½   r¼   rÂ   r   Ú_unlockÚupdater!   r’   rÁ   r“   Ú_HPIForwardsr   r–   rc   r”   r•   rj   rs   rÃ   )r§   rX   rš   r›   r*   r7   rt   ru   rÆ   rw   ry   Z	hpi_freqsZhpi_pickZhpi_onsÚhpi_rrsÚhpi_nnsr�   Z	sinusoidsÚmegcoilsrD   rË   r    r¡   ZlimsrK   rÌ   r¢   r8   r8   r9   Úadd_chpi  sP    
ÿÿ ÿ

"  ÿr×   c                   @   s   e Zd Zdd„ Zdd„ ZdS )rÓ   c                 C   s(   || _ || _|| _|| _|| _d| _d S ©Nr   )ry   rw   rÔ   rÕ   rÖ   Úidx)Úselfry   rw   rÖ   rÔ   rÕ   r8   r8   r9   Ú__init__M  s    z_HPIForwards.__init__c                    sr   |ˆj ˆj kst‚tˆjˆjˆj ƒ tˆjˆjƒj‰ t	 
‡ ‡fdd„ttˆjƒƒD ƒ¡j‰ ˆ jd7  _ˆ fS )Nc              
      s:   g | ]2}t  ˆ d d …d| d|d  …f ˆj| ¡‘qS )Nr³   r/   )rO   ÚdotrÕ   )rR   Úii©r¢   rÚ   r8   r9   rU   Z  s   ÿz)_HPIForwards.__call__.<locals>.<listcomp>r/   )ry   rÙ   rs   r   rÖ   rw   r   rÔ   ÚTrO   rd   r�   rl   )rÚ   Úoffsetr8   rÞ   r9   Ú__call__U  s    ÿ
z_HPIForwards.__call__N©Ú__name__Ú
__module__Ú__qualname__rÛ   rá   r8   r8   r8   r9   rÓ   K  s   rÓ   c                 C   sÔ  | \}}t |ttfƒr>t|ƒdkr4tdt|ƒf ƒ‚|\}}nd }t|tddƒ |d kr€t t|j	ƒt
¡}||t t |j	¡¡< ~t|tjdƒ |jjdkr¬td|jf ƒ‚|jt|j	ƒfkrÖtd|jt|j	ƒf ƒ‚t |d	|j ¡sþtd
d	|j |f ƒ‚t|j	ƒdk�r"tdt|j	ƒf ƒ‚|j}|d k�rB|dk�s|t‚n:t|ƒt|ƒk�sntdd„ t||ƒD ƒƒ�s|td|f ƒ‚|j}	|d k�rœ|dk�sÊt‚n.|d k�rªdnd}
t|||
d�\}}}|	| }	|	||fS )Nr   z'stc, if tuple, must be length 2, got %srA   z7SourceEstimate or tuple with first entry SourceEstimater¥   ÚizAstim_data in a stc tuple must be an integer ndarray, got dtype %sz:event data had shape %s but needed to be (%s,) tomatch stcr{   z6stc and info must have same sample rate, got %s and %sz0stc must have at least three time points, got %sr   c                 s   s   | ]\}}t  ||¡V  qd S r   )rO   rq   )rR   ÚaÚbr8   r8   r9   r�   ‚  s    z"_stc_data_event.<locals>.<genexpr>z8Vertex mismatch for stc[%d], all stc.vertices must matchr†   ÚignorerÎ   )r6   re   rb   rl   r‹   r-   r'   rO   r’   ru   rp   ZargminÚabsra   ZdtyperÄ   r‘   rŒ   ZtstepZverticesrs   rÃ   rc   r?   r�   r   )rC   Zhead_idxr;   r‚   rE   Zstc_idxrA   r¥   Zverts_r¤   r‡   rD   Zstc_selr8   r8   r9   r@   `  s`    ÿ
ÿÿÿÿ
ÿ
ÿ
ÿ
r@   c                   @   s   e Zd Zddd„Zdd„ ZdS )rŽ   NTc                 C   s4   d| _ || _|| _tt||||||||
|	ƒ	ƒ| _d S rØ   )rÙ   ry   rœ   ÚiterÚ_iter_forward_solutions)rÚ   rw   ry   r7   r]   r‚   r˜   r™   r›   rž   r�   rœ   r8   r8   r9   rÛ   “  s           þz_SimForwards.__init__c                 C   sf   | j | j |kst‚|  jd7  _t| jƒ}|d | _t|dd| jddd� |d d t 	| jt
¡fS )Nr/   r‚   TF)Zsurf_oriZforce_fixedrœ   r�   r*   Zsolr�   )ry   rÙ   rs   r=   rë   r‚   r   rœ   rO   rd   rV   )rÚ   rà   r¢   r8   r8   r9   rá   œ  s    

 þz_SimForwards.__call__)NTrâ   r8   r8   r8   r9   rŽ   ‘  s      ÿ
	rŽ   c	                 c   sÊ  t  d¡ t| |ƒ} |  ¡ � | jg g d� W 5 Q R X t|ƒ\}	}t||	| |||ddd�\
}
}}}}}}} }}~~|dkrªt|||gdgdgdg|dd�d	 }t||ƒ}n t	|ƒd	krÆt
||dd�}nd}t	t| dd
�ƒd	k�r|jf |Ž |D ]
}|V  qð|V  dS tj}|dk	�rv|d �svt t dd„ |d D ƒ¡tjk¡d	 }t	|ƒdk�sZt‚t|d |d	  ||	dd�}t|ƒD �]>\}}t  d|d t	|ƒf ¡ t|
|ƒ t||ƒ t dd„ |
D ƒ¡}|dk�rŽ|d �sôt|ƒ||dd� }nH|jdk	�r,||d  }t tj|| dd�¡|jk}nt t	|ƒt¡}| ¡ �s^tdt | ¡|f ƒ‚t|||
g|g|gdg|dd�d	 }t||ƒ}nt
||dd�}t||dd�}|jf |Ž |V  �q~|V  dS )z+Calculate a forward solution for a subject.zSetting up forward solutionsrÐ   TF)Zallow_bem_noner*   Nr„   r2   r   )r~   Z	is_spherec                 S   s   g | ]}|d  ‘qS )Úidr8   )rR   Úsr8   r8   r9   rU   Ë  s     z+_iter_forward_solutions.<locals>.<listcomp>Zsurfsr/   )r�   z*Computing gain matrix for transform #%s/%sc                 S   s   g | ]}|d  ‘qS )rÈ   r8   )rR   Zcoilr8   r8   r9   rU   Ú  s     rÈ   r‰   zA%s MEG sensors collided with inner skull surface for transform %sr~   )r)   r7   r   rÑ   rÒ   r"   r   r   r   rl   r	   r   r   ZFIFFV_COORD_HEADrO   Úwhererd   ZFIFFV_BEM_SURF_ID_BRAINrs   r#   r<   r   r(   Zradiusr¾   rk   ZonesrÁ   rÃ   r?   r   )r7   r]   r‚   r˜   rw   r™   r›   r�   rÉ   Z
mri_head_trÖ   Zmeg_infoZ	compcoilsZmegnamesZeegelsZeegnamesr¶   Zupdate_kwargsZeegfwdrD   Zcoord_framerÙ   Zbem_surfÚtir\   Zcoil_rrZoutsider`   Zmegfwdr¢   r8   r8   r9   rì   ©  s¨    


      þÿ    ÿÿÿÿ ÿÿ




ÿ
 
þ  þþ
rì   )N)NNNNNr{   r|   NTNr   r}   N)Nr|   NNN)Nr|   NNN)Nr|   NN)NN)MÚcollections.abcr   ÚnumpyrO   Úeventr   Z_olar   Zio.pickr   r   r   r	   r1   r
   r   r   r˜   r   r   r   Úior   r   r   Zchpir   r   r   r   Zio.constantsr   r�   r   r   r   r   r   r   r   r   r    r!   Z
transformsr"   r#   Zsource_spacer$   r%   r&   Zsource_estimater'   Zsurfacer(   Úutilsr)   r*   r+   r,   r-   r.   Úsourcer0   r:   rF   rN   rz   r¨   r®   r°   r«   r×   ÚobjectrÓ   r@   rŽ   rì   r8   r8   r8   r9   Ú<module>   s^   0 	
/               þ N  ÿ5  ÿ3[9
1