U
    f»{jNe  ã                   @   sÚ   d Z ddlmZ ddlmZ ddlZddlZddlZddl	m
Z
mZmZ ddlmZmZ ddlmZmZmZ e d	¡Zd
e_G dd„ deƒZG dd„ deƒZddd„ZG dd„ deƒZdd„ Zdd„ ZG dd„ deƒZdS )zSome utility functions.é    )ÚOrderedDict)ÚdeepcopyNé   )Ú_check_pandas_installedÚ_check_preloadÚ_validate_type)ÚwarnÚverbose)Úobject_sizeÚobject_hashÚ
_time_maskÚmneFc                   @   s,   e Zd ZdZdd„ Zedd„ ƒZdd„ ZdS )	Ú	SizeMixinzEstimate MNE object sizes.c                 C   s   t |t| ƒƒot| ƒt|ƒkS )zåCompare self to other.

        Parameters
        ----------
        other : object
            The object to compare to.

        Returns
        -------
        eq : bool
            True if the two objects are equal.
        )Ú
isinstanceÚtypeÚhash)ÚselfÚother© r   úN/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/utils/mixin.pyÚ__eq__   s    zSizeMixin.__eq__c                 C   sd   zt | jƒ}W n tk
r,   tdƒ Y dS X t| dƒrH|t | jƒ7 }nt| dƒr`|t | jƒ7 }|S )zEstimate the object size.z Could not get size for self.infoéÿÿÿÿÚdataÚ_data)r
   ÚinfoÚ	Exceptionr   Úhasattrr   r   )r   Úsizer   r   r   Ú_size)   s    

zSizeMixin._sizec                 C   s‚   ddl m} ddlm} ddlm} t| |ƒrBtt| j	| j
d�ƒS t| ||fƒrnt| dƒ tt| j	| jd�ƒS tdt| ƒ ƒ‚dS )	zbHash the object.

        Returns
        -------
        hash : int
            The hash
        é   )ÚEvoked©Ú
BaseEpochs)ÚBaseRaw)r   r   zHashing zHashing unknown object type: %sN)Zevokedr    Úepochsr"   Zio.baser#   r   r   Údictr   r   r   r   ÚRuntimeErrorr   )r   r    r"   r#   r   r   r   Ú__hash__7   s    

zSizeMixin.__hash__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr   r'   r   r   r   r   r      s
   
r   c                   @   s‚   e Zd ZdZdd„ Zdd„ Zdd	d
„Zdd„ Zdd„ Zdd„ Z	ddd„Z
dd„ Ze
Zddd„Zedd„ ƒZejeddd„ƒƒZdS )ÚGetEpochsMixinz=Class to add epoch selection and metadata to certain classes.c                 C   s
   |   |¡S )a¿  Return an Epochs object with a copied subset of epochs.

        Parameters
        ----------
        item : slice, array-like, str, or list
            See below for use cases.

        Returns
        -------
        epochs : instance of Epochs
            See below for use cases.

        Notes
        -----
        Epochs can be accessed as ``epochs[...]`` in several ways:

        1. **Integer or slice:** ``epochs[idx]`` will return an `~mne.Epochs`
           object with a subset of epochs chosen by index (supports single
           index and Python-style slicing).

        2. **String:** ``epochs['name']`` will return an `~mne.Epochs` object
           comprising only the epochs labeled ``'name'`` (i.e., epochs created
           around events with the label ``'name'``).

           If there are no epochs labeled ``'name'`` but there are epochs
           labeled with /-separated tags (e.g. ``'name/left'``,
           ``'name/right'``), then ``epochs['name']`` will select the epochs
           with labels that contain that tag (e.g., ``epochs['left']`` selects
           epochs labeled ``'audio/left'`` and ``'visual/left'``, but not
           ``'audio_left'``).

           If multiple tags are provided *as a single string* (e.g.,
           ``epochs['name_1/name_2']``), this selects epochs containing *all*
           provided tags. For example, ``epochs['audio/left']`` selects
           ``'audio/left'`` and ``'audio/quiet/left'``, but not
           ``'audio/right'``. Note that tag-based selection is insensitive to
           order: tags like ``'audio/left'`` and ``'left/audio'`` will be
           treated the same way when selecting via tag.

        3. **List of strings:** ``epochs[['name_1', 'name_2', ... ]]`` will
           return an `~mne.Epochs` object comprising epochs that match *any* of
           the provided names (i.e., the list of names is treated as an
           inclusive-or condition). If *none* of the provided names match any
           epoch labels, a ``KeyError`` will be raised.

           If epoch labels are /-separated tags, then providing multiple tags
           *as separate list entries* will likewise act as an inclusive-or
           filter. For example, ``epochs[['audio', 'left']]`` would select
           ``'audio/left'``, ``'audio/right'``, and ``'visual/left'``, but not
           ``'visual/right'``.

        4. **Pandas query:** ``epochs['pandas query']`` will return an
           `~mne.Epochs` object with a subset of epochs (and matching
           metadata) selected by the query called with
           ``self.metadata.eval``, e.g.::

               epochs["col_a > 2 and col_b == 'foo'"]

           would return all epochs whose associated ``col_a`` metadata was
           greater than two, and whose ``col_b`` metadata was the string 'foo'.
           Query-based indexing only works if Pandas is installed and
           ``self.metadata`` is a :class:`pandas.DataFrame`.

           .. versionadded:: 0.16
        )Ú_getitem)r   Úitemr   r   r   Ú__getitem__N   s    BzGetEpochsMixin.__getitem__c                 C   sz   t |tƒr|g}t |ttfƒrDt|ƒdkrDt |d tƒrD|  |¡}n2t |tƒrT|}n"t |¡}t|ƒdkrvt 	g t
¡}|S ©Nr   )r   ÚstrÚlistÚtupleÚlenÚ_keys_to_idxÚsliceÚnpÚ
atleast_1dÚarrayÚint)r   r/   Úselectr   r   r   Ú_item_to_select’   s    
ÿ

zGetEpochsMixin._item_to_selectÚIGNOREDTFc                    sT  | j }| ` |r|  ¡ n| ‰ | | _ ˆ _ ~ ˆ  |¡}tˆ dƒ}	|	rŒˆ j| }
tˆ jƒ}|dk	rzt ˆ j|
¡D ]}|f||< qjt	|ƒˆ _|
ˆ _~t 
ˆ j| ¡ˆ _ˆ jdk	røtdd�}|rÐˆ jj| }|	ræˆ j|_nt ˆ jd¡|  ¡ }tjjˆ |dd� ˆ j�r|�rtjˆ j | dgd�ˆ _ |�r>‡ fd	d
„ˆ j ¡ D ƒˆ _|�rLˆ |fS ˆ S dS )a°  
        Select epochs from current object.

        Parameters
        ----------
        item: slice, array-like, str, or list
            see `__getitem__` for details.
        reason: str
            entry in `drop_log` for unselected epochs
        copy: bool
            return a copy of the current object
        drop_event_id: bool
            remove non-existing event-ids after selection
        select_data: bool
            apply selection to data
            (use `select_data=False` if subclasses do not have a
             valid `_data` field, or data has already been subselected)
        return_indices: bool
            return the indices of selected epochs from the original object
            in addition to the new `Epochs` objects
        Returns
        -------
        `Epochs` or tuple(Epochs, np.ndarray) if `return_indices` is True
            subset of epochs (and optionally array with kept epoch indices)
        Ú	selectionNF©ÚstrictÚobject)r	   ÚO)Úrequirementsc                    s,   i | ]$\}}|ˆ j d d …df kr||“qS ©Nr   )Úevents)Ú.0ÚkÚv©Úinstr   r   Ú
<dictcomp>á   s    ÿ z+GetEpochsMixin._getitem.<locals>.<dictcomp>)r   Úcopyr=   r   r?   r3   Údrop_logr8   Z	setdiff1dr4   Z
atleast_2drF   Úmetadatar   ZilocÚindexr:   Útolistr-   ÚfsetÚpreloadÚrequireÚevent_idÚitems)r   r/   ÚreasonrM   Zdrop_event_idZselect_dataZreturn_indicesr   r<   Zhas_selectionZkey_selectionrN   rH   ÚpdrO   r   rJ   r   r.   ¢   s@    







zGetEpochsMixin._getitemc           	         sR  ddl m} t|ttfƒr|n|g}z6t tjt ‡ fdd„|ˆ j	|ƒD ƒ¡dd�¡d W S  t
k
�rL } zÒt|ƒdks„ˆ jdkr†‚ t|jd ƒ}td	d
�}|�r,tˆ dƒr´ˆ jnd}ˆ j|d� z ˆ j ¡ j|d dd�jj}W n8 tk
�r } z|d|jd f 7 }W 5 d}~X Y nX | W Y ¢S n|d7 }t
|ƒ‚W 5 d}~X Y nX dS )zFind entries in event dict.r   )Úmatch_event_namesc                    s(   g | ] }ˆ j d d …df ˆ j| k‘qS rE   )rF   rU   )rG   rH   ©r   r   r   Ú
<listcomp>ñ   s   ÿz/GetEpochsMixin._keys_to_idx.<locals>.<listcomp>r   )Zaxisr   NFr@   Ú	_metadata©rO   Úpython)Zenginez? The epochs.metadata Pandas query did not yield any results: %szU The epochs.metadata Pandas query could not be performed, consider installing Pandas.)ÚeventrY   r   r3   r4   r8   ÚwhereÚanyr:   rU   ÚKeyErrorr5   rO   r2   Úargsr   r   Ú_check_metadataÚreset_indexÚqueryrP   Úvaluesr   )	r   ÚkeysrY   ÚerrÚmsgrX   ÚmdÚvalsÚexpr   rZ   r   r6   é   s>    
ÿýý

þ
ÿzGetEpochsMixin._keys_to_idxc                 C   s.   ddl m} t| |ƒr$| js$tdƒ‚t| jƒS )aß  Return the number of epochs.

        Returns
        -------
        n_epochs : int
            The number of remaining epochs.

        Notes
        -----
        This function only works if bad epochs have been dropped.

        Examples
        --------
        This can be used as::

            >>> epochs.drop_bad()  # doctest: +SKIP
            >>> len(epochs)  # doctest: +SKIP
            43
            >>> len(epochs.events)  # doctest: +SKIP
            43
        r   r!   zÐSince bad epochs have not been dropped, the length of the Epochs is not known. Load the Epochs with preload=True, or call Epochs.drop_bad(). To find the number of events in the Epochs, use len(Epochs.events).)r$   r"   r   Z_bad_droppedr&   r5   rF   )r   r"   r   r   r   Ú__len__  s    zGetEpochsMixin.__len__c                 C   s   d| _ | j| _| S )a�  Facilitate iteration over epochs.

        This method resets the object iteration state to the first epoch.

        Notes
        -----
        This enables the use of this Python pattern::

            >>> for epoch in epochs:  # doctest: +SKIP
            >>>     print(epoch)  # doctest: +SKIP

        Where ``epoch`` is given by successive outputs of
        :meth:`mne.Epochs.next`.
        r   )Ú_currentZ_detrend_picksÚ_current_detrend_picksrZ   r   r   r   Ú__iter__0  s    zGetEpochsMixin.__iter__c                 C   sÜ   t | dƒs|  ¡  | jrL| jt| jƒkr0|  ¡  | j| j }|  jd7  _nld}|s®| jt| jƒkrl|  ¡  |  | j¡}|  	|| j
¡}|  |¡}|  jd7  _|  |¡\}}qP| jr¸|}|sÀ|S || j| jd  d fS dS )a}  Iterate over epoch data.

        Parameters
        ----------
        return_event_id : bool
            If True, return both the epoch data and an event_id.

        Returns
        -------
        epoch : array of shape (n_channels, n_times)
            The epoch data.
        event_id : int
            The event id. Only returned if ``return_event_id`` is ``True``.
        rp   r   Fr   N)r   rq   rS   ro   r5   r   Ú
_stop_iterrF   Z_get_epoch_from_rawZ_detrend_offset_decimrp   Z_project_epochZ_is_good_epochZ_do_delayed_proj)r   Zreturn_event_idÚepochZis_goodZepoch_noprojÚ_r   r   r   Ú__next__C  s0    
 ÿ
zGetEpochsMixin.__next__c                 C   s   | ` | `t‚d S )N)ro   rp   ÚStopIterationrZ   r   r   r   rr   m  s    zGetEpochsMixin._stop_iterNc                 C   s¢   |dkrdS t dd�}|r„t||jdd� t|ƒt| jƒkrVtdt|ƒt| jƒf ƒ‚|ržt| dƒrz|jdd	�}| j|_	qžt
|ƒ}nt|tdd� |ržt
|ƒ}|S )
zCheck metadata consistency.NFr@   rO   )ÚtypesÚ	item_namez>metadata must have the same number of rows (%d) as events (%d)r?   T)Zdrop)r   r   Ú	DataFramer5   rF   Ú
ValueErrorr   re   r?   rP   r   r3   )r   rO   re   rX   r   r   r   rd   t  s,    
ÿþ


ÿzGetEpochsMixin._check_metadatac                 C   s   | j S )zGet the metadata.)r\   rZ   r   r   r   rO   �  s    zGetEpochsMixin.metadatac                 C   s    | j |dd�}|d k	rBtdd�r,|jd }nt|d ƒ}d| }nd}t| d	ƒrt| jd k	rt|d krfd
nd}|d7 }n|d kr€dnd}t d||f ¡ || _d S )NT)re   Fr@   r   r   z with %d columnsÚ r\   ZRemovingZ	Replacingz	 existingzNot settingÚAddingz%s metadata%s)rd   r   Úshaper5   r   r\   Úloggerr   )r   rO   r	   Zn_colÚactionr   r   r   rO   •  s    


)r>   TTTF)F)NF)N)r(   r)   r*   r+   r0   r=   r.   r6   rn   rq   ru   rr   Únextrd   r,   rO   Úsetterr	   r   r   r   r   r-   K   s&   D    ÿ
G' 
*

r-   Tc                 C   sÔ   |dk s|t |ƒkrtdƒ‚t |ƒ}| d t|ƒ }t |ƒ}d|  krP|k sfn td|› d|› �ƒ‚|rÊ| d }|dkrš|dkrštd	|› d
|› d�ƒ n0|dkrÊ|d| k rÊtd|› d|› d
|› d�ƒ |||fS )zCheck decimation parameters.r   zdecim must be an integer > 0Úsfreqr   z'decim must be at least 0 and less than z, got ÚlowpassNzOThe measurement information indicates data is not low-pass filtered. The decim=z2 parameter will result in a sampling frequency of z( Hz, which can cause aliasing artifacts.é   z>The measurement information indicates a low-pass frequency of z Hz. The decim=)r;   rz   Úfloatr   )r   ÚdecimÚoffsetÚcheck_filterÚ	new_sfreqrƒ   r   r   r   Ú_check_decimª  s    rŠ   c                   @   s|   e Zd ZdZedd„ ƒZdd„ Zedd„ ƒZedd	„ ƒZe	ddd„ƒZ
e	ddd„ƒZddd„Zdd„ Zddd„Zdd„ Zd
S )Ú	TimeMixinz3Class to handle operations on time for MNE objects.c                 C   s   | j S )zTime vector in seconds.)Ú_times_readonlyrZ   r   r   r   ÚtimesÆ  s    zTimeMixin.timesc                 C   s   |  ¡ | _d| jjd< dS )z1Set self._times_readonly (and make it read only).FZ	WRITEABLEN)rM   rŒ   Úflags)r   r�   r   r   r   Ú
_set_timesË  s    
zTimeMixin._set_timesc                 C   s
   | j d S )zFirst time point.r   ©r�   rZ   r   r   r   ÚtminÒ  s    zTimeMixin.tminc                 C   s
   | j d S )zLast time point.r   r�   rZ   r   r   r   Útmax×  s    zTimeMixin.tmaxNTc                 C   sÒ   |dkr| j }n.|| j k r>tdt| ƒ› d| j d›d�ƒ | j }|dkrN| j}n2|| jkr€tdt| ƒ› d| jd›d�ƒ | j}d}t| j||| jd	 |d
�}|  | j| ¡ | j| | _|  	¡  | j
d|f | _
| S )a  Crop data to a given time interval.

        Parameters
        ----------
        tmin : float | None
            Start time of selection in seconds.
        tmax : float | None
            End time of selection in seconds.
        %(include_tmax)s
        %(verbose)s

        Returns
        -------
        inst : instance of Raw, Epochs, Evoked, AverageTFR, or SourceEstimate
            The cropped time-series object, modified in-place.

        Notes
        -----
        %(notes_tmax_included_by_default)s
        Nz-tmin is not in time interval. tmin is set to z.tmin (Úgz sec)z-tmax is not in time interval. tmax is set to z.tmax (Tr‚   )r‚   Úinclude_tmax.)r‘   r   r   r’   r   r�   r   r�   Ú
_raw_timesÚ_update_first_lastr   )r   r‘   r’   r”   r	   Úmaskr   r   r   ÚcropÜ  s&    

ÿzTimeMixin.cropr   c              	   C   s  t | j||t| dƒ d�\}}}tt| jd  | jd | j  ƒƒ}|  j|9  _|| j | }t|d| jƒ}| j ¡ � || jd< W 5 Q R X | j	râ|dkrÂ| j
d|f  ¡ | _
| j|  ¡ | _nt | j
¡| _
tdƒ| _d| _n|| _|  | j| j ¡ |  ¡  | S )a,  Decimate the time-series data.

        Parameters
        ----------
        %(decim)s
        %(offset_decim)s
        %(verbose)s

        Returns
        -------
        inst : MNE-object
            The decimated object.

        See Also
        --------
        mne.Epochs.resample
        mne.io.Raw.resample

        Notes
        -----
        %(decim_notes)s

        If ``decim`` is 1, this method does not copy the underlying data.

        .. versionadded:: 0.10.0

        References
        ----------
        .. footbibliography::
        Zfreqs)rˆ   r   r‚   Nr   .)rŠ   r   r   r;   Úroundr•   Z_decimr7   Z_unlockrS   r   rM   r8   ZascontiguousarrayZ_decim_slicer�   r–   )r   r†   r‡   r	   r‰   Z	start_idxZi_startZdecim_slicer   r   r   Údecimate
  s2    #   
ÿÿ

zTimeMixin.decimateFc                 C   s\   ddl m} t| |ƒr"d| j }n
| jd }t |¡| jd  | }|rRt |¡}| 	t
¡S )aÓ  Convert time to indices.

        Parameters
        ----------
        times : list-like | float | int
            List of numbers or a number representing points in time.
        use_rounding : bool
            If True, use rounding (instead of truncation) when converting
            times to indices. This can help avoid non-unique indices.

        Returns
        -------
        index : ndarray
            Indices corresponding to the times supplied.
        r   )Ú_BaseSourceEstimateg      ð?r‚   r   )Zsource_estimater›   r   Ztstepr   r8   r9   r�   r™   Zastyper;   )r   r�   Zuse_roundingr›   r‚   rP   r   r   r   Útime_as_indexF  s    


zTimeMixin.time_as_indexc                 C   s„   t |dddd� t |dddd� | jj}|dkr4dn|  |¡d }|dkrN|n|  |¡d }ttd|ƒ|ƒ}ttd|ƒ|ƒ}||fS )a¸  Convert seconds to index into data.

        Parameters
        ----------
        tmin : int | float | None
            Start time of data to get in seconds.
        tmax : int | float | None
            End time of data to get in seconds.

        Returns
        -------
        start : int
            Integer index into data corresponding to tmin.
        stop : int
            Integer index into data corresponding to tmax.

        )ÚnumericNr‘   zint, float, None)rw   rx   Ú	type_namer’   Nr   )r   r�   r   rœ   ÚminÚmax)r   r‘   r’   Zn_timesÚstartÚstopr   r   r   Ú_handle_tmin_tmax`  s    ÿÿzTimeMixin._handle_tmin_tmaxc                 C   sT   t | dƒ ||r| jd nd }|t t| jƒ¡| jd   }|  |¡ |  ¡  | S )am  Shift time scale in epoched or evoked data.

        Parameters
        ----------
        tshift : float
            The (absolute or relative) time shift in seconds. If ``relative``
            is True, positive tshift increases the time value associated with
            each sample, while negative tshift decreases it.
        relative : bool
            If True, increase or decrease time values by ``tshift`` seconds.
            Otherwise, shift the time values such that the time of the first
            sample equals ``tshift``.

        Returns
        -------
        epochs : MNE-object
            The modified instance.

        Notes
        -----
        This method allows you to shift the *time* values associated with each
        data sample by an arbitrary amount. It does *not* resample the signal
        or change the *data* values in any way.
        Ú
shift_timer   g        r‚   )r   r�   r8   Zaranger5   r   r�   r–   )r   ZtshiftÚrelativer¡   Z	new_timesr   r   r   r¤   ‚  s    

zTimeMixin.shift_timec                 C   s8   t t| jd | jd  ƒƒ| _t| jƒ| j d | _dS )z1Update self.first and self.last (sample indices).r   r‚   r   N)r;   r™   r�   r   Úfirstr5   ÚlastrZ   r   r   r   r–   ¢  s    zTimeMixin._update_first_last)NNTN)r   N)F)T)r(   r)   r*   r+   r,   r�   r�   r‘   r’   r	   r˜   rš   rœ   r£   r¤   r–   r   r   r   r   r‹   Ã  s    


-;
"
 r‹   c                 C   s<   | dk	r8t | tƒs | jdd�} n
t | ¡} t | tƒs8t‚| S )z$Convert metadata to JSON for saving.NÚrecords)Zorient)r   r3   Úto_jsonÚjsonÚdumpsr2   ÚAssertionErrorr]   r   r   r   Ú_prepare_write_metadata¨  s    

r­   c                 C   sR   | dk	rNt dd�}tj| td�} t| tƒs.t‚|rN|j | ¡} t| |jƒsNt‚| S )z&Convert saved metadata back from JSON.NFr@   )Úobject_pairs_hook)	r   rª   Úloadsr   r   r3   r¬   ry   Zfrom_records)rO   rX   r   r   r   Ú_prepare_read_metadata³  s    
r°   c                   @   s   e Zd Zdd„ Zdd„ ZdS )Ú_FakeNoPandasc                 C   s.   ddd„}dd l }t| _||j_||jj_d S )NTc                 S   s   | rt dƒ‚ndS d S )NzPandas not installedF)r&   r@   r   r   r   Ú_checkÄ  s    
z'_FakeNoPandas.__enter__.<locals>._checkr   )T)r   r   Ú
_old_checkr$   ÚutilsÚmixin)r   r²   r   r   r   r   Ú	__enter__Â  s
    
z_FakeNoPandas.__enter__c                 G   s"   dd l }| j|j_| j|jj_d S r1   )r   r³   r$   r   r´   rµ   )r   rc   r   r   r   r   Ú__exit__Ï  s    
z_FakeNoPandas.__exit__N)r(   r)   r*   r¶   r·   r   r   r   r   r±   Á  s   r±   )T)r+   Úcollectionsr   rM   r   Úloggingrª   Únumpyr8   Úcheckr   r   r   Z_loggingr   r	   Znumericsr
   r   r   Ú	getLoggerr~   Ú	propagaterB   r   r-   rŠ   r‹   r­   r°   r±   r   r   r   r   Ú<module>   s(   
4  a
 f