U
    f»{j*,  ã                   @   s®   d dl 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 ddlmZmZmZmZ eddd
œdd„ƒZdd„ Zdd„ Zdd„ Zdd„ Zeƒ dd„ ƒZdd„ ZdS )é    Né   )Újit)ÚBaseRaw)ÚAnnotationsÚ_adjust_onset_meas_dateÚ_annotations_starts_stops)Ú_picks_to_idxÚ_picks_by_typeÚ_get_channel_types)Ú_validate_typeÚverboseÚloggerÚ_mask_to_onsets_offsetsé   ç{®Gázt?)r   c                   s  t ˆtdƒ tˆj|ddd�‰ t|dˆjˆ ƒ}t|dˆjˆ ƒ}|dkrV|dkrVtdƒ‚t|ƒ}t|ˆjj	d	 ˆjd
  ƒ}t
t |ˆjd
  ¡ƒ}tƒ }‡ fdd„tˆjdd�D ƒ}Š tˆddd�\}	}
t ‡fdd„t|	|
ƒD ƒ¡}t tˆjƒd	 t¡}t tˆjƒd	 t¡}t d¡ | ¡ D �]¦\}‰ tj‡ ‡fdd„t|	|
ƒD ƒd	d�}t tj|d	d�¡}|dk	�r||| k}t||ƒ}|jd	d�}|t |¡  d	7  < |ˆjj	 d }ˆ t ||k¡d  }| |¡ t d|k ||k @ ¡d }|t ||dd…f ¡d	  }d||< |dk	�r$||| k}t||ƒ}|jd	d�}|t |¡  d	7  < |ˆjj	 d }ˆ t ||k¡d  }| |¡ t d|k ||k @ ¡d }|t ||dd…f ¡d	  }d||< �q$t|dˆƒ}t|dˆƒ}|| }‡fdd„|D ƒ}||fS )uª  Annotate raw data based on peak-to-peak amplitude.

    Creates annotations ``BAD_peak`` or ``BAD_flat`` for spans of data where
    consecutive samples exceed the threshold in ``peak`` or fall below the
    threshold in ``flat`` for more than ``min_duration``.
    Channels where more than ``bad_percent`` of the total recording length
    should be annotated with either ``BAD_peak`` or ``BAD_flat`` are returned
    in ``bads`` instead.
    Note that the annotations and the bads are not automatically added to the
    :class:`~mne.io.Raw` object; use :meth:`~mne.io.Raw.set_annotations` and
    :class:`info['bads'] <mne.Info>` to do so.

    Parameters
    ----------
    raw : instance of Raw
        The raw data.
    peak : float | dict | None
        Annotate segments based on **maximum** peak-to-peak signal amplitude
        (PTP). Valid **keys** can be any channel type present in the object.
        The **values** are floats that set the maximum acceptable PTP. If the
        PTP is larger than this threshold, the segment will be annotated.
        If float, the minimum acceptable PTP is applied to all channels.
    flat : float | dict | None
        Annotate segments based on **minimum** peak-to-peak signal amplitude
        (PTP). Valid **keys** can be any channel type present in the object.
        The **values** are floats that set the minimum acceptable PTP. If the
        PTP is smaller than this threshold, the segment will be annotated.
        If float, the minimum acceptable PTP is applied to all channels.
    bad_percent : float
        The percentage of the time a channel can be above or below thresholds.
        Below this percentage, :class:`~mne.Annotations` are created.
        Above this percentage, the channel involved is return in ``bads``. Note
        the returned ``bads`` are not automatically added to
        :class:`info['bads'] <mne.Info>`.
        Defaults to ``5`` (5%%).
    min_duration : float
        The minimum duration (sec) required by consecutives samples to be above
        ``peak`` or below ``flat`` thresholds to be considered.
        to consider as above or below threshold.
        For some systems, adjacent time samples with exactly the same value are
        not totally uncommon. Defaults to ``0.005`` (5 ms).
    %(picks_good_data)s
    %(verbose)s

    Returns
    -------
    annotations : instance of Annotations
        The annotated bad segments.
    bads : list
        The channels detected as bad.

    Notes
    -----
    This function does not use a window to detect small peak-to-peak or large
    peak-to-peak amplitude changes as the ``reject`` and ``flat`` argument from
    :class:`~mne.Epochs` does. Instead, it looks at the difference between
    consecutive samples.

    - When used to detect segments below ``flat``, at least ``min_duration``
      seconds of consecutive samples must respect
      ``abs(a[i+1] - a[i]) â‰¤ flat``.
    - When used to detect segments above ``peak``, at least ``min_duration``
      seconds of consecutive samples must respect
      ``abs(a[i+1] - a[i]) â‰¥ peak``.

    Thus, this function does not detect every temporal event with large
    peak-to-peak amplitude, but only the ones where the peak-to-peak amplitude
    is supra-threshold between consecutive samples. For instance, segments
    experiencing a DC shift will not be picked up. Only the edges from the DC
    shift will be annotated (and those only if the edge transitions are longer
    than ``min_duration``).

    This function may perform faster if data is loaded in memory, as it
    loads data one channel type at a time (across all time points), which is
    typically not an efficient way to read raw data from disk.

    .. versionadded:: 1.0
    ÚrawZdata_or_icaÚbads)ÚexcludeÚpeakÚflatNz@At least one of the arguments 'peak' or 'flat' must not be None.é   Úsfreqc                    s8   i | ]0\}}t j|ˆ d d�jdkr|t j|ˆ d d�“qS )T)Zassume_uniquer   )ÚnpZintersect1dÚsize)Ú.0Úch_typeZpicks_of_type)Úpicks_© úc/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/preprocessing/annotate_amplitude.pyÚ
<dictcomp>o   s   þ z&annotate_amplitude.<locals>.<dictcomp>Zbad_acq_skipT)Úinvertc                    s&   g | ]\}}t  ˆ jj¡||… ‘qS r   )r   ZarangeÚtimesr   ©r   ZonsetÚend©r   r   r   Ú
<listcomp>x   s   ÿz&annotate_amplitude.<locals>.<listcomp>z.Finding segments below or above PTP threshold.c                    s$   g | ]\}}ˆˆ ||…f d  ‘qS )r   r   r"   ©r   r   r   r   r%   ‚   s   ÿ)Zaxiséd   r   c                    s$   g | ]}|ˆ j d  krˆ j| ‘qS )r   )ÚinfoZch_names)r   Úbadr$   r   r   r%   ¯   s      )r   r   r   r(   Ú
_check_ptpÚ
ValueErrorÚ_check_bad_percentÚ_check_min_durationr!   r   Úintr   ÚroundÚlistr	   r   ZconcatenateÚzipZzerosÚlenÚboolr   ÚitemsÚabsÚdiffÚ_reject_short_segmentsÚsumZnonzeroÚwhereÚextendÚ_create_annotations)r   r   r   Úbad_percentÚmin_durationÚpicksr   Úmin_duration_samplesr   ÚonsetsZendsÚindexZany_flatZany_peakr   Údatar6   Zflat_Z
flat_countZ	flat_meanZflat_ch_to_set_badZflat_ch_to_annotateÚidxZpeak_Z
peak_countZ	peak_meanZpeak_ch_to_set_badZpeak_ch_to_annotateZannotation_flatZannotation_peakÚannotationsr   r&   r   Úannotate_amplitude   sz    Qÿÿ
þÿ
ÿÿ


ÿ


ÿrE   c              	      s¦   t ˆ dtdfƒ ˆ dk	rbtˆ tƒsbˆ dk r@td|› dˆ › d�ƒ‚tt||ƒƒ}‡ fdd„|D ƒ‰ n@tˆ tƒr¢ˆ  ¡ D ],\}}|dk rttd|› d	|› d
|› d�ƒ‚qtˆ S )zDCheck the PTP threhsold argument, and converts it to dict if needed.ÚnumericNr   z
Argument 'z1' should define a positive threshold. Provided: 'z'.c                    s   i | ]
}|ˆ “qS r   r   )r   r   ©Úptpr   r   r   ¾   s      z_check_ptp.<locals>.<dictcomp>z@' should define positive thresholds. Provided for channel type 'z': ')r   ÚdictÚ
isinstancer+   Úsetr
   r4   )rH   Únamer(   r>   Zch_typesÚkeyÚvaluer   rG   r   r*   ´   s    ÿ
ÿr*   c                 C   s>   t | ddƒ t| ƒ} d|   kr(dks:n td| › d�ƒ‚| S )zCCheck that bad_percent is a valid percentage and converts to float.rF   r<   r   r'   zQArgument 'bad_percent' should define a percentage between 0% and 100%. Provided: z%.©r   Úfloatr+   )r<   r   r   r   r,   È   s    
ÿr,   c                 C   sN   t | ddƒ t| ƒ} | dk r,td| › d�ƒ‚| |krJtd|› d| › d�ƒ‚| S )zBCheck that min_duration is a valid duration and converts to float.rF   r=   r   zQArgument 'min_duration' should define a positive duration in seconds. Provided: 'z
' seconds.zdArgument 'min_duration' should define a positive duration in seconds shorter than the raw duration (z seconds). Provided: 'rO   )r=   Zraw_durationr   r   r   r-   Ó   s    
ÿÿr-   c                 C   sL   | j tkr| jdkst‚t| ƒD ]&\}}t|ƒ\}}t| | |||ƒ q | S )zDCheck if flat or peak segments are longer than the minimum duration.r   )Zdtyper3   ÚndimÚAssertionErrorÚ	enumerater   Ú_mark_inner)Zarrr?   ÚkÚchr@   Úoffsetsr   r   r   r7   ã   s
    r7   c                 C   s0   t ||ƒD ] \}}|| |k r
d| ||…< q
dS )z'Inner loop of _reject_short_segments().FN)r1   )Zarr_kr@   rW   r?   ÚstartÚstopr   r   r   rT   ì   s    rT   c                 C   s‚   |dkst ‚t| ƒ\}}t |¡t |¡ }}||jd  }|| |jd  }t||d|› �gt|ƒ |jd d�}t||ƒ |S )z5Create the peak of flat annotations from the any_arr.)r   r   r   ZBAD_Z	meas_date)Z	orig_time)rR   r   r   Úarrayr(   r   r2   r   )Zany_arrÚkindr   ZstartsZstopsr@   Z	durationsZannotr   r   r   r;   ô   s    ÿ
r;   )NNr   r   N)Únumpyr   Úfixesr   Úior   rD   r   r   r   Zio.pickr   r	   r
   Úutilsr   r   r   r   rE   r*   r,   r-   r7   rT   r;   r   r   r   r   Ú<module>   s(       ÿÿ %	
