<commit_before># Authors: <NAME> <<EMAIL>>
#          <NAME> <<EMAIL>>
#          <NAME> <<EMAIL>>
#
# License: BSD (3-clause)

import copy as cp
from warnings import warn
import numpy as np

import logging
logger = logging.getLogger('mne')

from .. import Epochs, compute_proj_evoked, compute_proj_epochs, verbose
from ..fiff import pick_types, make_eeg_average_ref_proj
from .ecg import find_ecg_events
from .eog import find_eog_events


@verbose
def _compute_exg_proj(mode, raw, raw_event, tmin, tmax,
                      n_grad, n_mag, n_eeg, l_freq, h_freq,
                      average, filter_length, n_jobs, ch_name,
                      reject, flat, bads, avg_ref, no_proj, event_id,
                      exg_l_freq, exg_h_freq, tstart, qrs_threshold,
                      filter_method, iir_params=dict(order=4, ftype='butter'),
                      verbose=None):
    """Compute SSP/PCA projections for ECG or EOG artifacts

    Note: raw has to be constructed with preload=True (or string)
    Warning: raw will be modified by this function

    Parameters
    ----------
    mode : string ('ECG', or 'EOG')
        What type of events to detect.
    raw : mne.fiff.Raw
        Raw input file.
    raw_event : mne.fiff.Raw or None
        Raw file to use for event detection (if None, raw is used).
    tmin : float
        Time before event in seconds.
    tmax : float
        Time after event in seconds.
    n_grad : int
        Number of SSP vectors for gradiometers.
    n_mag : int
        Number of SSP vectors for magnetometers.
    n_eeg : int
        Number of SSP vectors for EEG.
    l_freq : float | None
        Filter low cut-off frequency in Hz.
    h_freq : float | None
        Filter high cut-off frequency in Hz.
    average : bool
        Compute SSP after averaging.
    filter_length : str | int | None
        Number of taps to use for filtering.
    n_jobs : int
        Number of jobs to run in parallel.
    ch_name : string (or None)
        Channel to use for ECG event detection.
    reject : dict
        Epoch rejection configuration (see Epochs).
    flat : dict
        Epoch flat configuration (see Epochs).
    bads : list
        List with (additional) bad channels.
    avg_ref : bool
        Add EEG average reference proj.
    no_proj : bool
        Exclude the SSP projectors currently in the fiff file.
    event_id : int
        ID to use for events.
    exg_l_freq : float
        Low pass frequency applied for filtering EXG channel.
    exg_h_freq : float
        High pass frequency applied for filtering EXG channel.
    tstart : float
        Start artifact detection after tstart seconds.
    qrs_threshold : float
        Between 0 and 1. qrs detection threshold (only for ECG).
    filter_method : str
        Method for filtering ('iir' or 'fft').
    iir_params : dict
        Dictionary of parameters to use for IIR filtering.
        See mne.filter.construct_iir_filter for details.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see mne.verbose).

    Returns
    -------
    proj : list
        Computed SSP projectors.
    events : ndarray
        Detected events.
    """
    if not raw._preloaded:
        raise ValueError('raw needs to be preloaded, '
                         'use preload=True in constructor')

    if no_proj:
        projs = []
    else:
        projs = cp.deepcopy(raw.info['projs'])
        logger.info('Including %d SSP projectors from raw file'
                    % len(projs))

    if avg_ref:
        eeg_proj = make_eeg_average_ref_proj(raw.info)
        projs.append(eeg_proj)

    if raw_event is None:
        raw_event = raw

    if mode == 'ECG':
        logger.info('Running ECG SSP computation')
        events, _, _ = find_ecg_events(raw_event, ch_name=ch_name,
                                       event_id=event_id, l_freq=exg_l_freq,
                                       h_freq=exg_h_freq, tstart=tstart,
                                       qrs_threshold=qrs_threshold,
                                       filter_length=filter_length)
    elif mode == 'EOG':
        logger.info('Running EOG SSP computation')
        events = find_eog_events(raw_event, event_id=event_id,
                           l_freq=exg_l_freq, h_freq=exg_h_freq,
                           filter_length=filter_length)
    else:
        raise ValueError("mode must be 'ECG' or 'EOG'")

    # Check to make sure we actually got at least one useable event
    if events.shape[0] < 1:
        warn('No %s events found, returning None for projs' % mode)
        return None, events

    logger.info('Computing projector')
    my_info = cp.deepcopy(raw.info)
    my_info['bads'] += bads

    # Handler rejection parameters
    if reject is not None:  # make sure they didn't pass None
        if len(pick_types(my_info, meg='grad', eeg=False, eog=False,
                          exclude='bads')) == 0:
            del reject['grad']
        if len(pick_types(my_info, meg='mag', eeg=False, eog=False,
                          exclude='bads')) == 0:
            del reject['mag']
        if len(pick_types(my_info, meg=False, eeg=True, eog=False,
                          exclude='bads')) == 0:
            del reject['eeg']
        if len(pick_types(my_info, meg=False, eeg=False, eog=True,
                          exclude='bads')) == 0:
            del reject['eog']
    if flat is not None:  # make sure they didn't pass None
        if len(pick_types(my_info, meg='grad', eeg=False, eog=False,
                          exclude='bads')) == 0:
            del flat['grad']
        if len(pick_types(my_info, meg='mag', eeg=False, eog=False,
                          exclude='bads')) == 0:
            del flat['mag']
        if len(pick_types(my_info, meg=False, eeg=True, eog=False,
                          exclude='bads')) == 0:
            del flat['eeg']
        if len(pick_types(my_info, meg=False, eeg=False, eog=True,
                          exclude='bads')) == 0:
            del flat['eog']

    # exclude bad channels from projection
    picks = pick_types(my_info, meg=True, eeg=True, eog=True, exclude='bads')
    raw.filter(l_freq, h_freq, picks=picks, filter_length=filter_length,
               n_jobs=n_jobs, method=filter_method, iir_params=iir_params)

    epochs = Epochs(raw, events, None, tmin, tmax, baseline=None, preload=True,
                    picks=picks, reject=reject, flat=flat, proj=True)

    epochs.drop_bad_epochs()
    if epochs.events.shape[0] < 1:
        warn('No good epochs found, returning None for projs')
        return None, events

    if average:
        evoked = epochs.average()<commit_msg>ENH: adding safe reject delete<commit_after># Authors: <NAME> <<EMAIL>>
#          <NAME> <<EMAIL>>
#          <NAME> <<EMAIL>>
#
# License: BSD (3-clause)

import copy as cp
from warnings import warn
import numpy as np

import logging
logger = logging.getLogger('mne')

from .. import Epochs, compute_proj_evoked, compute_proj_epochs, verbose
from ..fiff import pick_types, make_eeg_average_ref_proj
from .ecg import find_ecg_events
from .eog import find_eog_events


def _safe_del_key(dict_, key):
    """ Aux function

    Use this function when preparing rejection parameters
    instead of directly deleting keys.
    """
    if key in dict_:
        del dict_[key]


@verbose
def _compute_exg_proj(mode, raw, raw_event, tmin, tmax,
                      n_grad, n_mag, n_eeg, l_freq, h_freq,
                      average, filter_length, n_jobs, ch_name,
                      reject, flat, bads, avg_ref, no_proj, event_id,
                      exg_l_freq, exg_h_freq, tstart, qrs_threshold,
                      filter_method, iir_params=dict(order=4, ftype='butter'),
                      verbose=None):
    """Compute SSP/PCA projections for ECG or EOG artifacts

    Note: raw has to be constructed with preload=True (or string)
    Warning: raw will be modified by this function

    Parameters
    ----------
    mode : string ('ECG', or 'EOG')
        What type of events to detect.
    raw : mne.fiff.Raw
        Raw input file.
    raw_event : mne.fiff.Raw or None
        Raw file to use for event detection (if None, raw is used).
    tmin : float
        Time before event in seconds.
    tmax : float
        Time after event in seconds.
    n_grad : int
        Number of SSP vectors for gradiometers.
    n_mag : int
        Number of SSP vectors for magnetometers.
    n_eeg : int
        Number of SSP vectors for EEG.
    l_freq : float | None
        Filter low cut-off frequency in Hz.
    h_freq : float | None
        Filter high cut-off frequency in Hz.
    average : bool
        Compute SSP after averaging.
    filter_length : str | int | None
        Number of taps to use for filtering.
    n_jobs : int
        Number of jobs to run in parallel.
    ch_name : string (or None)
        Channel to use for ECG event detection.
    reject : dict
        Epoch rejection configuration (see Epochs).
    flat : dict
        Epoch flat configuration (see Epochs).
    bads : list
        List with (additional) bad channels.
    avg_ref : bool
        Add EEG average reference proj.
    no_proj : bool
        Exclude the SSP projectors currently in the fiff file.
    event_id : int
        ID to use for events.
    exg_l_freq : float
        Low pass frequency applied for filtering EXG channel.
    exg_h_freq : float
        High pass frequency applied for filtering EXG channel.
    tstart : float
        Start artifact detection after tstart seconds.
    qrs_threshold : float
        Between 0 and 1. qrs detection threshold (only for ECG).
    filter_method : str
        Method for filtering ('iir' or 'fft').
    iir_params : dict
        Dictionary of parameters to use for IIR filtering.
        See mne.filter.construct_iir_filter for details.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see mne.verbose).

    Returns
    -------
    proj : list
        Computed SSP projectors.
    events : ndarray
        Detected events.
    """
    if not raw._preloaded:
        raise ValueError('raw needs to be preloaded, '
                         'use preload=True in constructor')

    if no_proj:
        projs = []
    else:
        projs = cp.deepcopy(raw.info['projs'])
        logger.info('Including %d SSP projectors from raw file'
                    % len(projs))

    if avg_ref:
        eeg_proj = make_eeg_average_ref_proj(raw.info)
        projs.append(eeg_proj)

    if raw_event is None:
        raw_event = raw

    if mode == 'ECG':
        logger.info('Running ECG SSP computation')
        events, _, _ = find_ecg_events(raw_event, ch_name=ch_name,
                                       event_id=event_id, l_freq=exg_l_freq,
                                       h_freq=exg_h_freq, tstart=tstart,
                                       qrs_threshold=qrs_threshold,
                                       filter_length=filter_length)
    elif mode == 'EOG':
        logger.info('Running EOG SSP computation')
        events = find_eog_events(raw_event, event_id=event_id,
                           l_freq=exg_l_freq, h_freq=exg_h_freq,
                           filter_length=filter_length)
    else:
        raise ValueError("mode must be 'ECG' or 'EOG'")

    # Check to make sure we actually got at least one useable event
    if events.shape[0] < 1:
        warn('No %s events found, returning None for projs' % mode)
        return None, events

    logger.info('Computing projector')
    my_info = cp.deepcopy(raw.info)
    my_info['bads'] += bads

    # Handler rejection parameters
    if reject is not None:  # make sure they didn't pass None
        if len(pick_types(my_info, meg='grad', eeg=False, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(reject, 'grad')
        if len(pick_types(my_info, meg='mag', eeg=False, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(reject, 'mag')
        if len(pick_types(my_info, meg=False, eeg=True, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(reject, 'eeg')
        if len(pick_types(my_info, meg=False, eeg=False, eog=True,
                          exclude='bads')) == 0:
            _safe_del_key(reject, 'eog')
    if flat is not None:  # make sure they didn't pass None
        if len(pick_types(my_info, meg='grad', eeg=False, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(flat, 'grad')
        if len(pick_types(my_info, meg='mag', eeg=False, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(flat, 'mag')
        if len(pick_types(my_info, meg=False, eeg=True, eog=False,
                          exclude='bads')) == 0:
            _safe_del_key(flat, 'eeg')
        if len(pick_types(my_info, meg=False, eeg=False, eog=True,
                          exclude='bads')) == 0:
            _safe_del_key(flat, 'eog')

    # exclude bad channels from projection
    picks = pick_types(my_info, meg=True, eeg=True, eog=True, exclude='bads')
    raw.filter(l_freq, h_freq, picks=picks, filter_length=filter_length,
               n_jobs=n_jobs, method=filter_method, iir_params=iir_params)

    epochs = Epochs(raw, events, None, tmin, tmax, baseline=None, preload=True,
                    picks=picks, reject=reject, flat=flat, proj=True)

    epochs.drop_bad_epochs()
    if epochs.events.shape[0] < 1:
        warn('No good epochs found, returning None for projs')
        return None, events

    if average:
        evoked = epochs.average()
{'fraction_non_alphanumeric': 0.08952936884348778, 'fraction_numerical': 0.002334914264866837, 'mean_word_length': 2.0471320586927524, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2098674', 'n_tokens_mistral': 4284, 'n_tokens_neox': 4106, 'n_words': 1256}