Example #1
0
def _handle_picks(epochs):
    """Aux function to handle picks."""
    if any('ICA' in k for k in epochs.ch_names):
        picks = pick_types(epochs.info, misc=True, ref_meg=False,
                           exclude=[])
    else:
        picks = pick_types(epochs.info, meg=True, eeg=True, eog=True, ecg=True,
                           seeg=True, ecog=True, ref_meg=False, exclude=[])
    return picks
Example #2
0
def _interpolate_bads_meg(inst, mode='accurate', origin=None, verbose=None):
    """Interpolate bad channels from data in good channels.

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    mode : str
        Either `'accurate'` or `'fast'`, determines the quality of the
        Legendre polynomial expansion used for interpolation. `'fast'` should
        be sufficient for most applications.
    origin : None | list
        If None, origin is set to sensor center of mass, otherwise use the
        coordinates provided as origin. The old standard value is (0., 0., 0.04)
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).
    """
    from mne.channels.interpolation import _do_interp_dots

    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])
    picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')
    meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]
    bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]

    # select the bad meg channel to be interpolated
    if len(bads_meg) == 0:
        picks_bad = []
    else:
        picks_bad = pick_channels(inst.info['ch_names'], bads_meg, exclude=[])

    # return without doing anything if there are no meg channels
    if len(picks_meg) == 0 or len(picks_bad) == 0:
        return
    info_from = pick_info(inst.info, picks_good)
    info_to = pick_info(inst.info, picks_bad)

    if check_version('mne', min_version='0.21'):
        from mne.forward import _map_meg_or_eeg_channels
        mapping = _map_meg_or_eeg_channels(info_from,
                                           info_to,
                                           mode=mode,
                                           origin=origin)
    else:
        from mne.forward import _map_meg_channels
        mapping = _map_meg_channels(info_from,
                                    info_to,
                                    mode=mode,
                                    origin=origin)

    _do_interp_dots(inst, mapping, picks_good, picks_bad)
Example #3
0
def _infer_eeg_placement_scheme(raw):
    """Based on the channel names, try to infer an EEG placement scheme.

    Parameters
    ----------
    raw : instance of Raw
        The data as MNE-Python Raw object.

    Returns
    -------
    placement_scheme : str
        Description of the EEG placement scheme. Will be "n/a" for unsuccessful
        extraction.

    """
    placement_scheme = 'n/a'
    # Check if the raw data contains eeg data at all
    if 'eeg' not in raw:
        return placement_scheme

    # How many of the channels in raw are based on the extended 10/20 system
    raw.load_data()
    sel = pick_types(raw.info, meg=False, eeg=True)
    ch_names = [raw.ch_names[i] for i in sel]
    channel_names = [ch.lower() for ch in ch_names]
    montage1005 = make_standard_montage('standard_1005')
    montage1005_names = [ch.lower() for ch in montage1005.ch_names]

    if set(channel_names).issubset(set(montage1005_names)):
        placement_scheme = 'based on the extended 10/20 system'

    return placement_scheme
Example #4
0
def find_bad_channels(epochs, picks=None, method='faster', method_params=None,
                      return_by_metric=False, verbose=None):
    """Implements the first step of the FASTER algorithm.

    This function attempts to automatically mark bad EEG channels by performing
    outlier detection. It operated on epoched data, to make sure only relevant
    data is analyzed.

    Parameters
    ----------
    epochs : Instance of Epochs
        The epochs for which bad channels need to be marked
    picks : list of int | None
        Channels to operate on. Defaults to EEG channels.
    method : {'faster'}
        The detection algorithm.
    method_params : dict | None
        The method parameters in a dict.

        If ``method`` equals 'faster', and ``method_params``is None,
        defaults to the following parameters. Partial updates are supported.
        use_metrics : list of str
            List of metrics to use. Can be any combination of:
                'variance', 'correlation', 'hurst', 'kurtosis', 'line_noise'
            Defaults to all of them.
        thresh : float
            The threshold value, in standard deviations, to apply. A channel
            crossing this threshold value is marked as bad. Defaults to 3.
        max_iter : int
            The maximum number of iterations performed during outlier detection
            (defaults to 1, as in the original FASTER paper).

    return_by_metric : bool
        Whether to return the bad channels as a flat list (False, default) or
        as a dictionary with the names of the used metrics as keys and the
        bad channels found by this metric as values. Is ignored if not
        supported by method.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see mne.verbose).
        Defaults to self.verbose.

    Returns
    -------
    bads : list of str
        The names of the bad EEG channels.
    """
    if picks is None:
        picks = pick_types(epochs.info, meg=True, eeg=True, exclude=[])
    _method_params = _handle_default('bads' + '_' + method, method_params)
    if method == 'faster':
        bads = _find_bad_channels(epochs, picks, **_method_params)
    else:
        raise NotImplementedError(
            'Come back later, for now there is only "FASTER"')

    if return_by_metric:
        return bads
    else:
        return _combine_indices(bads)
Example #5
0
def make_interpolators(interp_cache, keys, bads, epochs):
    make = [k for k in keys if (bads, k) not in interp_cache]
    logger = logging.getLogger(__name__)
    logger.debug("Making %i of %i interpolators" % (len(make), len(keys)))
    for key in make:
        picks_good = pick_types(epochs.info, ref_meg=False, exclude=key)
        picks_bad = pick_channels(epochs.ch_names, key)
        interpolation = map_meg_channels(epochs, picks_good, picks_bad, 'accurate')
        interp_cache[bads, key] = picks_good, picks_bad, interpolation
Example #6
0
def make_interpolators(interp_cache, keys, bads, epochs):
    make = [k for k in keys if (bads, k) not in interp_cache]
    logger = logging.getLogger(__name__)
    logger.debug("Making %i of %i interpolators" % (len(make), len(keys)))
    for key in make:
        picks_good = pick_types(epochs.info, ref_meg=False, exclude=key)
        picks_bad = pick_channels(epochs.ch_names, key)
        interpolation = map_meg_channels(epochs, picks_good, picks_bad, 'accurate')
        interp_cache[bads, key] = picks_good, picks_bad, interpolation
Example #7
0
def get_power(raw, picks=None):
    """Helper to compute power of magnetometer channels in raw object"""

    # Grab only magnetometers for calculation (though both mags and grads
    # affect shielding factor calculation)
    if picks is None:
        picks = pick_types(raw.info, meg='mag')

    # Return norm along channel axis
    return norm(raw[picks, :][0], axis=0)
Example #8
0
def pre_whiten(data, info, picks, pre_whitener=None):
    """Aux function based on ica._pre_whiten from mne v0.15

       pre_whitener[this_picks] = np.std(data[this_picks], axis=1)[:, None]
    """

    if pre_whitener is None:
        # use standardization as whitener
        # Scale (z-score) the data by channel type
        info = pick_info(info, picks)

        pre_whitener = np.empty([len(data), 1])
        for ch_type in _DATA_CH_TYPES_SPLIT + ['eog']:
            if _contains_ch_type(info, ch_type):
                if ch_type == 'seeg':
                    this_picks = pick_types(info, meg=False, seeg=True)
                elif ch_type == 'ecog':
                    this_picks = pick_types(info, meg=False, ecog=True)
                elif ch_type == 'eeg':
                    this_picks = pick_types(info, meg=False, eeg=True)
                elif ch_type in ('mag', 'grad'):
                    this_picks = pick_types(info, meg=ch_type)
                elif ch_type == 'eog':
                    this_picks = pick_types(info, meg=False, eog=True)
                elif ch_type in ('hbo', 'hbr'):
                    this_picks = pick_types(info, meg=False, fnirs=ch_type)
                else:
                    raise RuntimeError('Should not be reached.'
                                       'Unsupported channel {0}'
                                       .format(ch_type))
                pre_whitener[this_picks] = np.std(data[this_picks], axis=1)[:, None]

    data /= pre_whitener

    return data, pre_whitener
Example #9
0
    def _fit_evoked(self, raw, picks, start, stop, decim, reject, flat, tstep,
                    verbose):
        """Aux method
        """
        if self.current_fit != 'unfitted':
            self._reset()

        if picks is None:  # just use good data channels
            picks = pick_types(raw.info,
                               meg=True,
                               eeg=True,
                               eog=False,
                               ecg=False,
                               misc=False,
                               stim=False,
                               ref_meg=False,
                               exclude='bads')
        logger.info('Fitting ICA to data using %i channels. \n'
                    'Please be patient, this may take some time' % len(picks))

        if self.max_pca_components is None:
            self.max_pca_components = len(picks)
            logger.info('Inferring max_pca_components from picks.')

        self.info = pick_info(raw.info, picks)
        if self.info['comps']:
            self.info['comps'] = []
        self.ch_names = self.info['ch_names']
        start, stop = _check_start_stop(raw, start, stop)

        data = raw.data[picks, start:stop]
        print data.shape
        if decim is not None:
            data = data[:, ::decim].copy()

        if (reject is not None) or (flat is not None):
            data, self.drop_inds_ = _reject_data_segments(
                data, reject, flat, decim, self.info, tstep)

        self.n_samples_ = data.shape[1]

        data, self._pre_whitener = self._pre_whiten(data, raw.info, picks)

        self._fit(data, self.max_pca_components, 'evoked')  #'raw')

        return self
def _prep_eeg_channels(info, exclude=(), verbose=None):
    """Prepare EEG electrode definitions for forward calculation.

    Parameters
    ----------
    info : instance of Info
        The measurement information dictionary
    exclude : list of str | str
        List of channels to exclude. If 'bads', exclude channels in
        info['bads']
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    eegels : list of dict
        Information for each prepped EEG electrode
    eegnames : list of str
        Name of each prepped EEG electrode
    """
    eegnames, eegels = [], []
    info_extra = 'info'

    # Find EEG electrodes
    picks = pick_types(info,
                       meg=False,
                       eeg=True,
                       ref_meg=False,
                       exclude=exclude)

    # Make sure EEG electrodes exist
    neeg = len(picks)
    if neeg <= 0:
        raise RuntimeError('Could not find any EEG channels')

    # Get channel info and names for EEG channels
    eegchs = pick_info(info, picks)['chs']
    eegnames = [info['ch_names'][p] for p in picks]
    logger.info('Read %3d EEG channels from %s' % (len(picks), info_extra))

    # Create EEG electrode descriptions
    eegels = _create_eeg_els(eegchs)
    logger.info('Head coordinate coil definitions created.')

    return eegels, eegnames
Example #11
0
def get_channel_positions(self, picks=None):
    """Gets channel locations from info

    Parameters
    ----------
    picks : array-like of int | None
        Indices of channels to include. If None (default), all meg and eeg
        channels that are available are returned (bad channels excluded).
    """
    if picks is None:
        picks = pick_types(self.info, meg=True, eeg=True)
    chs = self.info['chs']
    pos = np.array([chs[k]['loc'][:3] for k in picks])
    n_zero = np.sum(np.sum(np.abs(pos), axis=1) == 0)
    if n_zero > 1:  # XXX some systems have origin (0, 0, 0)
        raise ValueError('Could not extract channel positions for '
                         '{} channels'.format(n_zero))
    return pos
Example #12
0
def get_channel_positions(self, picks=None):
    """Gets channel locations from info

    Parameters
    ----------
    picks : array-like of int | None
        Indices of channels to include. If None (default), all meg and eeg
        channels that are available are returned (bad channels excluded).
    """
    if picks is None:
        picks = pick_types(self.info, meg=True, eeg=True)
    chs = self.info['chs']
    pos = np.array([chs[k]['loc'][:3] for k in picks])
    n_zero = np.sum(np.sum(np.abs(pos), axis=1) == 0)
    if n_zero > 1:  # XXX some systems have origin (0, 0, 0)
        raise ValueError('Could not extract channel positions for '
                         '{} channels'.format(n_zero))
    return pos
Example #13
0
    def _pre_whiten(self, data, info, picks):
        """Aux function."""
        has_pre_whitener = hasattr(self, 'pre_whitener_')
        if not has_pre_whitener and self.noise_cov is None:
            # use standardization as whitener
            # Scale (z-score) the data by channel
            info = pick_info(info, picks)
            pre_whitener = np.empty([len(data), 1])
            for ch_type in _DATA_CH_TYPES_SPLIT + ('eog', "ref_meg"):
                if _contains_ch_type(info, ch_type):
                    if ch_type == 'seeg':
                        this_picks = pick_types(info, meg=False, seeg=True)
                    elif ch_type == 'ecog':
                        this_picks = pick_types(info, meg=False, ecog=True)
                    elif ch_type == 'eeg':
                        this_picks = pick_types(info, meg=False, eeg=True)
                    elif ch_type in ('mag', 'grad'):
                        this_picks = pick_types(info, meg=ch_type)
                    elif ch_type == 'eog':
                        this_picks = pick_types(info, meg=False, eog=True)
                    elif ch_type in ('hbo', 'hbr'):
                        this_picks = pick_types(info, meg=False, fnirs=ch_type)
                    elif ch_type == 'ref_meg':
                        this_picks = pick_types(info, meg=False, ref_meg=True)
                    else:
                        raise RuntimeError(
                            'Should not be reached.'
                            'Unsupported channel {}'.format(ch_type))

                    pre_whitener[this_picks] = np.std(data[this_picks],
                                                      axis=1)[:, None]
            data /= pre_whitener
        elif not has_pre_whitener and self.noise_cov is not None:

            from mne.cov import compute_whitener

            pre_whitener, _ = compute_whitener(self.noise_cov, info, picks)
            assert data.shape[0] == pre_whitener.shape[1]
            data = np.dot(pre_whitener, data)
        elif has_pre_whitener and self.noise_cov is None:
            data /= self.pre_whitener_
            pre_whitener = self.pre_whitener_
        else:
            data = np.dot(self.pre_whitener_, data)
            pre_whitener = self.pre_whitener_

        return data, pre_whitener
Example #14
0
def _make_interpolator(inst, bad_channels):
    """Find indexes and interpolation matrix to interpolate bad channels

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    """
    bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool)
    goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool)

    picks = pick_types(inst.info, meg=False, eeg=True, exclude=[])
    bads_idx[picks] = [inst.ch_names[ch] in bad_channels for ch in picks]
    goods_idx[picks] = True
    goods_idx[bads_idx] = False

    if bads_idx.sum() != len(bad_channels):
        logger.warning('Channel interpolation is currently only implemented '
                       'for EEG. The MEG channels marked as bad will remain '
                       'untouched.')

    pos = get_channel_positions(inst, picks)

    # Make sure only EEG are used
    bads_idx_pos = bads_idx[picks]
    goods_idx_pos = goods_idx[picks]

    pos_good = pos[goods_idx_pos]
    pos_bad = pos[bads_idx_pos]

    # test spherical fit
    radius, center = _fit_sphere(pos_good)
    distance = np.sqrt(np.sum((pos_good - center)**2, 1))
    distance = np.mean(distance / radius)
    if np.abs(1. - distance) > 0.1:
        logger.warning('Your spherical fit is poor, interpolation results are '
                       'likely to be inaccurate.')

    logger.info('Computing interpolation matrix from {0} sensor '
                'positions'.format(len(pos_good)))

    interpolation = _make_interpolation_matrix(pos_good, pos_bad)

    return goods_idx, bads_idx, interpolation
Example #15
0
def _make_interpolator(inst, bad_channels):
    """Find indexes and interpolation matrix to interpolate bad channels

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    """
    bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool)
    goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool)

    picks = pick_types(inst.info, meg=False, eeg=True, exclude=[])
    bads_idx[picks] = [inst.ch_names[ch] in bad_channels for ch in picks]
    goods_idx[picks] = True
    goods_idx[bads_idx] = False

    if bads_idx.sum() != len(bad_channels):
        logger.warning('Channel interpolation is currently only implemented '
                       'for EEG. The MEG channels marked as bad will remain '
                       'untouched.')

    pos = get_channel_positions(inst, picks)

    # Make sure only EEG are used
    bads_idx_pos = bads_idx[picks]
    goods_idx_pos = goods_idx[picks]

    pos_good = pos[goods_idx_pos]
    pos_bad = pos[bads_idx_pos]

    # test spherical fit
    radius, center = _fit_sphere(pos_good)
    distance = np.sqrt(np.sum((pos_good - center) ** 2, 1))
    distance = np.mean(distance / radius)
    if np.abs(1. - distance) > 0.1:
        logger.warning('Your spherical fit is poor, interpolation results are '
                       'likely to be inaccurate.')

    logger.info('Computing interpolation matrix from {0} sensor '
                'positions'.format(len(pos_good)))

    interpolation = _make_interpolation_matrix(pos_good, pos_bad)

    return goods_idx, bads_idx, interpolation
Example #16
0
    def _prepare_data(self, picks, target):
        this_picks = {k: None for k in ['times', 'channels', 'epochs']}
        if picks is not None:
            if any([x not in this_picks.keys() for x in picks.keys()]):
                raise ValueError('Picking is not compatible for {}'.format(
                    self._get_title()))
        if picks is None:
            picks = {}
        this_picks.update(picks)
        to_preserve = self._get_preserve_axis(target)
        if len(to_preserve) > 0:
            for axis in to_preserve:
                this_picks[axis] = None

        # Pick Times based on original times
        time_picks = this_picks['times']
        time_mask = _time_mask(self.epochs_.times, self.tmin, self.tmax)
        if time_picks is not None:
            picks_mask = np.zeros(len(time_mask), dtype=np.bool)
            picks_mask[time_picks] = True
            time_mask = np.logical_and(time_mask, picks_mask)

        # Pick epochs based on original indices
        epochs_picks = this_picks['epochs']
        this_epochs = self.epochs_
        if epochs_picks is not None:
            this_epochs = this_epochs[epochs_picks]

        # Pick channels based on original indices
        ch_picks = this_picks['channels']
        if ch_picks is None:
            ch_picks = pick_types(this_epochs.info, eeg=True, meg=True)

        if (self.subset and self.missing_nan
                and not epochs_has_event(this_epochs, self.subset)):
            data = np.array([[[np.nan]]])
        else:
            if self.subset:
                this_epochs = this_epochs[self.subset]
            data = this_epochs.get_data()[:, ch_picks][..., time_mask]

        return data
Example #17
0
    def _fit_evoked(self, raw, picks, start, stop, decim, reject, flat, tstep, verbose):
        """Aux method
        """
        if self.current_fit != 'unfitted':
            self._reset()

        if picks is None:  # just use good data channels
            picks = pick_types(raw.info, meg=True, eeg=True, eog=False,
                               ecg=False, misc=False, stim=False,
                               ref_meg=False, exclude='bads')
        logger.info('Fitting ICA to data using %i channels. \n'
                    'Please be patient, this may take some time' % len(picks))

        if self.max_pca_components is None:
            self.max_pca_components = len(picks)
            logger.info('Inferring max_pca_components from picks.')

        self.info = pick_info(raw.info, picks)
        if self.info['comps']:
            self.info['comps'] = []
        self.ch_names = self.info['ch_names']
        start, stop = _check_start_stop(raw, start, stop)

        data = raw.data[picks, start:stop]
        print data.shape
        if decim is not None:
            data = data[:, ::decim].copy()

        if (reject is not None) or (flat is not None):
            data, self.drop_inds_ = _reject_data_segments(data, reject, flat,
                                                          decim, self.info,
                                                          tstep)

        self.n_samples_ = data.shape[1]

        data, self._pre_whitener = self._pre_whiten(data,
                                                    raw.info, picks)

        self._fit(data, self.max_pca_components, 'evoked') #'raw')

        return self
Example #18
0
def _interpolate_bads_meg(epochs, bad_channels_by_epoch, mode='fast'):
    """Interpolate bad MEG channels per epoch

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    bad_channels_by_epoch : list of list of str
        Bad channel names specified for each epoch. For example, for an Epochs
        instance containing 3 epochs: ``[['F1'], [], ['F3', 'FZ']]``

    Notes
    -----
    Based on mne 0.9.0 MEG channel interpolation.
    """
    if len(bad_channels_by_epoch) != len(epochs):
        raise ValueError("Unequal length of epochs (%i) and "
                         "bad_channels_by_epoch (%i)"
                         % (len(epochs), len(bad_channels_by_epoch)))

    interp_cache = {}
    for i, bad_channels in enumerate(bad_channels_by_epoch):
        if not bad_channels:
            continue

        # find interpolation matrix
        key = tuple(sorted(bad_channels))
        if key in interp_cache:
            picks_good, picks_bad, interpolation = interp_cache[key]
        else:
            picks_good = pick_types(epochs.info, ref_meg=False, exclude=key)
            picks_bad = pick_channels(epochs.ch_names, key)
            interpolation = _map_meg_channels(epochs, picks_good, picks_bad, mode)
            interp_cache[key] = picks_good, picks_bad, interpolation

        # apply interpolation
        logger.info('Interpolating sensors %s on epoch %s', picks_bad, i)
        epochs._data[i, picks_bad, :] = interpolation.dot(epochs._data[i, picks_good, :])
def get_sensor_pos_from_fwd(inst, info=None, picks=None, trans=None):
    from mne import SourceSpaces, Forward
    from mne.io.constants import FIFF
    from six import string_types
    from mne.transforms import read_trans, _ensure_trans, invert_transform, Transform, apply_trans
    from mne.io.pick import channel_type, pick_types

    if isinstance(inst, Forward):
        info = inst['info']
        src = inst['src']
    elif isinstance(inst, SourceSpaces):
        src = inst
        if info is None:
            raise ValueError('You need to specify an Info object with '
                             'information about the channels.')

    # Load the head<->MRI transform if necessary
    if src[0]['coord_frame'] == FIFF.FIFFV_COORD_MRI:
        if trans is None:
            raise ValueError('Source space is in MRI coordinates, but no '
                             'head<->MRI transform was given. Please specify '
                             'the full path to the appropriate *-trans.fif '
                             'file as the "trans" parameter.')
        if isinstance(trans, string_types):
            trans = read_trans(trans, return_all=True)
            for trans in trans:  # we got at least 1
                try:
                    trans = _ensure_trans(trans, 'head', 'mri')
                except Exception as exp:
                    pass
                else:
                    break
            else:
                raise exp

        src_trans = invert_transform(_ensure_trans(trans, 'head', 'mri'))
        print('Transform!')
    else:
        src_trans = Transform('head', 'head')  # Identity transform

    dev_to_head = _ensure_trans(info['dev_head_t'], 'meg', 'head')

    if picks is None:
        picks = pick_types(info, meg=True)
        if len(picks) > 0:
            print('Using MEG channels')
        else:
            print('Using EEG channels')
            picks = pick_types(info, eeg=True)

    sensor_pos = []
    for ch in picks:
        # MEG channels are in device coordinates, translate them to head
        if channel_type(info, ch) in ['mag', 'grad']:
            sensor_pos.append(
                apply_trans(dev_to_head, info['chs'][ch]['loc'][:3]))
        else:
            sensor_pos.append(info['chs'][ch]['loc'][:3])
    sensor_pos = np.array(sensor_pos)

    return sensor_pos
Example #20
0
def _estimate_line_freq(raw, verbose=False):
    """Estimate power line noise from a given BaseRaw.

    Uses 5 channels of either meg, eeg, ecog, or seeg to
    estimate the line frequency.

    Parameters
    ----------
    raw : mne.io.BaseRaw

    Returns
    -------
    line_freq : int | None
        Either 50, or 60 Hz depending if European,
        or USA data recording.
    """
    sfreq = raw.info['sfreq']

    # if sampling is not high enough, line_freq does not matter
    if sfreq < 100:
        return None

    # setup picks of the data to get at least 5 channels
    pick_dict = {"meg": True}
    picks = list(pick_types(raw.info, exclude='bads', **pick_dict))
    if len(picks) < 5:
        pick_dict = {"eeg": True}
        picks = pick_types(raw.info, exclude='bads', **pick_dict)
    if len(picks) < 5:
        pick_dict = {"ecog": True}
        picks = pick_types(raw.info, exclude='bads', **pick_dict)
    if len(picks) < 5:
        pick_dict = {"seeg": True}
        picks = pick_types(raw.info, exclude='bads', **pick_dict)
    if len(picks) < 5:
        warn("Estimation of line frequency only "
             "supports 'meg', 'eeg', 'ecog', or 'seeg'.")
        return None

    # only sample first 10 seconds, or whole time series
    tmin = 0
    tmax = int(min(len(raw.times), 10 * sfreq))

    # get just five channels of data to estimate on
    data = raw.get_data(start=tmin, stop=tmax, picks=picks,
                        return_times=False)[0:5, :]

    # run a multi-taper FFT between Power Line Frequencies of interest
    psds, freqs = psd_array_welch(data,
                                  fmin=49,
                                  fmax=61,
                                  sfreq=sfreq,
                                  average="mean")
    usa_ind = np.where(freqs == min(freqs, key=lambda x: abs(x - 60)))[0]
    eu_ind = np.where(freqs == min(freqs, key=lambda x: abs(x - 50)))[0]

    # get the average power within those frequency bands
    usa_psd = np.mean((psds[..., usa_ind]))
    eu_psd = np.mean((psds[..., eu_ind]))

    if verbose is True:
        print("EU (i.e. 50 Hz) PSD is {} and "
              "USA (i.e. 60 Hz) PSD is {}".format(eu_psd, usa_psd))

    if usa_psd > eu_psd:
        line_freq = 60
    else:
        line_freq = 50
    return line_freq
def test_fix_stim_artifact():
    """Test fix stim artifact."""
    events = read_events(event_fname)

    raw = read_raw_fif(raw_fname)
    pytest.raises(RuntimeError, fix_stim_artifact, raw)

    raw = read_raw_fif(raw_fname, preload=True)

    # use window before stimulus in epochs
    tmin, tmax, event_id = -0.2, 0.5, 1
    picks = pick_types(raw.info,
                       meg=True,
                       eeg=True,
                       eog=True,
                       stim=False,
                       exclude='bads')
    epochs = Epochs(raw,
                    events,
                    event_id,
                    tmin,
                    tmax,
                    picks=picks,
                    preload=True,
                    reject=None)
    e_start = int(np.ceil(epochs.info['sfreq'] * epochs.tmin))
    tmin, tmax = -0.045, -0.015
    tmin_samp = int(-0.035 * epochs.info['sfreq']) - e_start
    tmax_samp = int(-0.015 * epochs.info['sfreq']) - e_start

    epochs = fix_stim_artifact(epochs, tmin=tmin, tmax=tmax, mode='linear')
    data = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    diff_data0 = np.diff(data[0][0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    epochs = fix_stim_artifact(epochs, tmin=tmin, tmax=tmax, mode='window')
    data_from_epochs_fix = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    # XXX This is a very weird check...
    assert np.all(data_from_epochs_fix) == 0.

    # use window before stimulus in raw
    event_idx = np.where(events[:, 2] == 1)[0][0]
    tmin, tmax = -0.045, -0.015
    tmin_samp = int(-0.035 * raw.info['sfreq'])
    tmax_samp = int(-0.015 * raw.info['sfreq'])
    tidx = int(events[event_idx, 0] - raw.first_samp)

    pytest.raises(ValueError, fix_stim_artifact, raw, events=np.array([]))
    raw = fix_stim_artifact(raw,
                            events=None,
                            event_id=1,
                            tmin=tmin,
                            tmax=tmax,
                            mode='linear',
                            stim_channel='STI 014')
    data, times = raw[:, (tidx + tmin_samp):(tidx + tmax_samp)]
    diff_data0 = np.diff(data[0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    raw = fix_stim_artifact(raw,
                            events,
                            event_id=1,
                            tmin=tmin,
                            tmax=tmax,
                            mode='window')
    data, times = raw[:, (tidx + tmin_samp):(tidx + tmax_samp)]
    assert np.all(data) == 0.

    # get epochs from raw with fixed data
    tmin, tmax, event_id = -0.2, 0.5, 1
    epochs = Epochs(raw,
                    events,
                    event_id,
                    tmin,
                    tmax,
                    picks=picks,
                    preload=True,
                    reject=None,
                    baseline=None)
    e_start = int(np.ceil(epochs.info['sfreq'] * epochs.tmin))
    tmin_samp = int(-0.035 * epochs.info['sfreq']) - e_start
    tmax_samp = int(-0.015 * epochs.info['sfreq']) - e_start
    data_from_raw_fix = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    assert np.all(data_from_raw_fix) == 0.

    # use window after stimulus
    evoked = epochs.average()
    tmin, tmax = 0.005, 0.045
    tmin_samp = int(0.015 * evoked.info['sfreq']) - evoked.first
    tmax_samp = int(0.035 * evoked.info['sfreq']) - evoked.first

    evoked = fix_stim_artifact(evoked, tmin=tmin, tmax=tmax, mode='linear')
    data = evoked.data[:, tmin_samp:tmax_samp]
    diff_data0 = np.diff(data[0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    evoked = fix_stim_artifact(evoked, tmin=tmin, tmax=tmax, mode='window')
    data = evoked.data[:, tmin_samp:tmax_samp]
    assert np.all(data) == 0.
Example #22
0
def find_bad_channels_in_epochs(epochs, picks=None, method='faster',
                                method_params=None, return_by_metric=False):
    """Implements the fourth step of the FASTER algorithm.

    This function attempts to automatically mark bad channels in each epochs by
    performing outlier detection.

    Parameters
    ----------
    epochs : Instance of Epochs
        The epochs to analyze.
    picks : list of int | None
        Channels to operate on. Defaults to EEG channels.
    method : {'faster'}
        The detection algorithm.
    method_params : dict | None
        The method parameters in a dict.

        If ``method`` equals 'faster', and ``method_params``is None,
        defaults to the following parameters. Partial updates are supported.
        use_metrics : list of str
            List of metrics to use. Can be any combination of:
            'amplitude', 'variance', 'deviation', 'median_gradient'
            Defaults to all of them.
        thresh : float
            The threshold value, in standard deviations, to apply. A channel
            crossing this threshold value is marked as bad. Defaults to 3.
        max_iter : int
            The maximum number of iterations performed during outlier detection
            (defaults to 1, as in the original FASTER paper).

    return_by_metric : bool
        Whether to return the bad channels as a flat list (False, default) or
        as a dictionary with the names of the used metrics as keys and the
        bad channels found by this metric as values. Is ignored if not
        supported by method.

    Returns
    -------
    bads : list of lists of int
        For each epoch, the indices of the bad channels.
    """
    if picks is None:
        picks = pick_types(epochs.info, meg=True, eeg=True, exclude=[])

    _method_params = _handle_default('bads' + '_' + method, method_params)
    if method == 'faster':
        bads = _find_bad_channels_in_epochs(epochs, picks,
                                                    **_method_params)
    else:
        raise NotImplementedError(
            'Come back later, for now there is only "FASTER"')

    info = pick_info(epochs.info, picks, copy=True)
    if return_by_metric:
        bads = dict((m, _bad_mask_to_names(info, v)) for m, v in bads.items())
    else:
        bads = np.sum(bads.values(), axis=0).astype(bool)
        bads = _bad_mask_to_names(info, bads)

    return bads
def _prep_meg_channels(info,
                       perts,
                       accurate=True,
                       exclude=(),
                       ignore_ref=False,
                       elekta_defs=False,
                       head_frame=True,
                       do_es=False,
                       do_picking=True,
                       verbose=None):
    """Prepare MEG coil definitions for forward calculation.

    Parameters
    ----------
    info : instance of Info
        The measurement information dictionary
    perts : dict
        A dictionary containing perturbation parameters for gradiometer
        imbalance, sensor miscalibration, and misalignment
    accurate : bool
        If true (default) then use `accurate` coil definitions (more
        integration points)
    exclude : list of str | str
        List of channels to exclude. If 'bads', exclude channels in
        info['bads']
    ignore_ref : bool
        If true, ignore compensation coils
    elekta_defs : bool
        If True, use Elekta's coil definitions, which use different integration
        point geometry. False by default.
    head_frame : bool
        If True (default), use head frame coords. Otherwise, use device frame.
    do_es : bool
        If True, compute and store ex, ey, ez, and r0_exey.
    do_picking : bool
        If True, pick info and return it.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    megcoils : list of dict
        Information for each prepped MEG coil
    compcoils : list of dict
        Information for each prepped MEG coil
    megnames : list of str
        Name of each prepped MEG coil
    meginfo : instance of Info
        Information subselected for just the set of MEG coils
    """
    accuracy = 'accurate' if accurate else 'normal'
    info_extra = 'info'
    megnames, megcoils, compcoils = [], [], []

    # Find MEG channels
    picks = pick_types(info,
                       meg=True,
                       eeg=False,
                       ref_meg=False,
                       exclude=exclude)

    # Make sure MEG coils exist
    nmeg = len(picks)
    if nmeg <= 0:
        raise RuntimeError('Could not find any MEG channels')

    # Get channel info and names for MEG channels
    megchs = [info['chs'][pick] for pick in picks]
    megnames = [info['ch_names'][p] for p in picks]
    logger.info('Read %3d MEG channels from %s' % (len(picks), info_extra))

    # Get MEG compensation channels
    if not ignore_ref:
        picks = pick_types(info, meg=False, ref_meg=True, exclude=exclude)
        ncomp = len(picks)
        if (ncomp > 0):
            compchs = pick_info(info, picks)['chs']
            logger.info('Read %3d MEG compensation channels from %s' %
                        (ncomp, info_extra))
            # We need to check to make sure these are NOT KIT refs
            if _has_kit_refs(info, picks):
                raise NotImplementedError(
                    'Cannot create forward solution with KIT reference '
                    'channels. Consider using "ignore_ref=True" in '
                    'calculation')
    else:
        ncomp = 0

    # Make info structure to allow making compensator later
    ncomp_data = len(info['comps'])
    ref_meg = True if not ignore_ref else False
    picks = pick_types(info, meg=True, ref_meg=ref_meg, exclude=exclude)

    # Create coil descriptions with transformation to head or device frame
    templates = _read_coil_defs(perts, elekta_defs=elekta_defs)

    if head_frame:
        _print_coord_trans(info['dev_head_t'])
        transform = info['dev_head_t']
    else:
        transform = None

    megcoils = _create_meg_coils(megchs,
                                 accuracy,
                                 transform,
                                 templates,
                                 do_es=do_es)

    if ncomp > 0:
        logger.info('%d compensation data sets in %s' %
                    (ncomp_data, info_extra))
        compcoils = _create_meg_coils(compchs,
                                      'normal',
                                      transform,
                                      templates,
                                      do_es=do_es)

    # Check that coordinate frame is correct and log it
    if head_frame:
        assert megcoils[0]['coord_frame'] == FIFF.FIFFV_COORD_HEAD
        logger.info('MEG coil definitions created in head coordinates.')
    else:
        assert megcoils[0]['coord_frame'] == FIFF.FIFFV_COORD_DEVICE
        logger.info('MEG coil definitions created in device coordinate.')

    out = (megcoils, compcoils, megnames)
    if do_picking:
        out = out + (pick_info(info, picks) if nmeg > 0 else None, )
    return out
Example #24
0
def _prepare_mne_browse_epochs(params, projs, n_channels, n_epochs, scalings,
                               title, picks, order=None):
    """Helper for setting up the mne_browse_epochs window."""
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    from matplotlib.collections import LineCollection
    from matplotlib.colors import colorConverter
    epochs = params['epochs']

    if picks is None:
        picks = _handle_picks(epochs)
    if len(picks) < 1:
        raise RuntimeError('No appropriate channels found. Please'
                           ' check your picks')
    picks = sorted(picks)
    # Reorganize channels
    inds = list()
    types = list()
    for t in ['grad', 'mag']:
        idxs = pick_types(params['info'], meg=t, ref_meg=False, exclude=[])
        if len(idxs) < 1:
            continue
        mask = np.in1d(idxs, picks, assume_unique=True)
        inds.append(idxs[mask])
        types += [t] * len(inds[-1])
    pick_kwargs = dict(meg=False, ref_meg=False, exclude=[])
    if order is None:
        order = ['eeg', 'seeg', 'ecog', 'eog', 'ecg', 'emg', 'ref_meg', 'stim',
                 'resp', 'misc', 'chpi', 'syst', 'ias', 'exci']
    for ch_type in order:
        pick_kwargs[ch_type] = True
        idxs = pick_types(params['info'], **pick_kwargs)
        if len(idxs) < 1:
            continue
        mask = np.in1d(idxs, picks, assume_unique=True)
        inds.append(idxs[mask])
        types += [ch_type] * len(inds[-1])
        pick_kwargs[ch_type] = False
    inds = np.concatenate(inds).astype(int)
    if not len(inds) == len(picks):
        raise RuntimeError('Some channels not classified. Please'
                           ' check your picks')
    ch_names = [params['info']['ch_names'][x] for x in inds]

    # set up plotting
    size = get_config('MNE_BROWSE_RAW_SIZE')
    n_epochs = min(n_epochs, len(epochs.events))
    duration = len(epochs.times) * n_epochs
    n_channels = min(n_channels, len(picks))
    if size is not None:
        size = size.split(',')
        size = tuple(float(s) for s in size)
    if title is None:
        title = epochs.name
        if epochs.name is None or len(title) == 0:
            title = ''
    fig = figure_nobar(facecolor='w', figsize=size, dpi=80)
    fig.canvas.set_window_title('mne_browse_epochs')
    ax = plt.subplot2grid((10, 15), (0, 1), colspan=13, rowspan=9)

    ax.annotate(title, xy=(0.5, 1), xytext=(0, ax.get_ylim()[1] + 15),
                ha='center', va='bottom', size=12, xycoords='axes fraction',
                textcoords='offset points')
    color = _handle_default('color', None)

    ax.axis([0, duration, 0, 200])
    ax2 = ax.twiny()
    ax2.set_zorder(-1)
    ax2.axis([0, duration, 0, 200])
    ax_hscroll = plt.subplot2grid((10, 15), (9, 1), colspan=13)
    ax_hscroll.get_yaxis().set_visible(False)
    ax_hscroll.set_xlabel('Epochs')
    ax_vscroll = plt.subplot2grid((10, 15), (0, 14), rowspan=9)
    ax_vscroll.set_axis_off()
    ax_vscroll.add_patch(mpl.patches.Rectangle((0, 0), 1, len(picks),
                                               facecolor='w', zorder=3))

    ax_help_button = plt.subplot2grid((10, 15), (9, 0), colspan=1)
    help_button = mpl.widgets.Button(ax_help_button, 'Help')
    help_button.on_clicked(partial(_onclick_help, params=params))

    # populate vertical and horizontal scrollbars
    for ci in range(len(picks)):
        if ch_names[ci] in params['info']['bads']:
            this_color = params['bad_color']
        else:
            this_color = color[types[ci]]
        ax_vscroll.add_patch(mpl.patches.Rectangle((0, ci), 1, 1,
                                                   facecolor=this_color,
                                                   edgecolor=this_color,
                                                   zorder=4))

    vsel_patch = mpl.patches.Rectangle((0, 0), 1, n_channels, alpha=0.5,
                                       edgecolor='w', facecolor='w', zorder=5)
    ax_vscroll.add_patch(vsel_patch)

    ax_vscroll.set_ylim(len(types), 0)
    ax_vscroll.set_title('Ch.')

    # populate colors list
    type_colors = [colorConverter.to_rgba(color[c]) for c in types]
    colors = list()
    for color_idx in range(len(type_colors)):
        colors.append([type_colors[color_idx]] * len(epochs.events))
    lines = list()
    n_times = len(epochs.times)

    for ch_idx in range(n_channels):
        if len(colors) - 1 < ch_idx:
            break
        lc = LineCollection(list(), antialiased=False, linewidths=0.5,
                            zorder=3, picker=3.)
        ax.add_collection(lc)
        lines.append(lc)

    times = epochs.times
    data = np.zeros((params['info']['nchan'], len(times) * n_epochs))

    ylim = (25., 0.)  # Hardcoded 25 because butterfly has max 5 rows (5*5=25).
    # make shells for plotting traces
    offset = ylim[0] / n_channels
    offsets = np.arange(n_channels) * offset + (offset / 2.)

    times = np.arange(len(times) * len(epochs.events))
    epoch_times = np.arange(0, len(times), n_times)

    ax.set_yticks(offsets)
    ax.set_ylim(ylim)
    ticks = epoch_times + 0.5 * n_times
    ax.set_xticks(ticks)
    ax2.set_xticks(ticks[:n_epochs])
    labels = list(range(1, len(ticks) + 1))  # epoch numbers
    ax.set_xticklabels(labels)
    ax2.set_xticklabels(labels)
    xlim = epoch_times[-1] + len(epochs.times)
    ax_hscroll.set_xlim(0, xlim)
    vertline_t = ax_hscroll.text(0, 1, '', color='y', va='bottom', ha='right')

    # fit horizontal scroll bar ticks
    hscroll_ticks = np.arange(0, xlim, xlim / 7.0)
    hscroll_ticks = np.append(hscroll_ticks, epoch_times[-1])
    hticks = list()
    for tick in hscroll_ticks:
        hticks.append(epoch_times.flat[np.abs(epoch_times - tick).argmin()])
    hlabels = [x / n_times + 1 for x in hticks]
    ax_hscroll.set_xticks(hticks)
    ax_hscroll.set_xticklabels(hlabels)

    for epoch_idx in range(len(epoch_times)):
        ax_hscroll.add_patch(mpl.patches.Rectangle((epoch_idx * n_times, 0),
                                                   n_times, 1,
                                                   facecolor=(0.8, 0.8, 0.8),
                                                   edgecolor=(0.8, 0.8, 0.8),
                                                   alpha=0.5))
    hsel_patch = mpl.patches.Rectangle((0, 0), duration, 1,
                                       edgecolor='k',
                                       facecolor=(0.5, 0.5, 0.5),
                                       alpha=0.25, linewidth=1, clip_on=False)
    ax_hscroll.add_patch(hsel_patch)
    text = ax.text(0, 0, 'blank', zorder=3, verticalalignment='baseline',
                   ha='left', fontweight='bold')
    text.set_visible(False)

    params.update({'fig': fig,
                   'ax': ax,
                   'ax2': ax2,
                   'ax_hscroll': ax_hscroll,
                   'ax_vscroll': ax_vscroll,
                   'vsel_patch': vsel_patch,
                   'hsel_patch': hsel_patch,
                   'lines': lines,
                   'projs': projs,
                   'ch_names': ch_names,
                   'n_channels': n_channels,
                   'n_epochs': n_epochs,
                   'scalings': scalings,
                   'duration': duration,
                   'ch_start': 0,
                   'colors': colors,
                   'def_colors': type_colors,  # don't change at runtime
                   'picks': picks,
                   'data': data,
                   'times': times,
                   'epoch_times': epoch_times,
                   'offsets': offsets,
                   'labels': labels,
                   'scale_factor': 1.0,
                   'butterfly_scale': 1.0,
                   'fig_proj': None,
                   'types': np.array(types),
                   'inds': inds,
                   'vert_lines': list(),
                   'vertline_t': vertline_t,
                   'butterfly': False,
                   'text': text,
                   'ax_help_button': ax_help_button,  # needed for positioning
                   'help_button': help_button,  # reference needed for clicks
                   'fig_options': None,
                   'settings': [True, True, True, True],
                   'image_plot': None})

    params['plot_fun'] = partial(_plot_traces, params=params)

    # callbacks
    callback_scroll = partial(_plot_onscroll, params=params)
    fig.canvas.mpl_connect('scroll_event', callback_scroll)
    callback_click = partial(_mouse_click, params=params)
    fig.canvas.mpl_connect('button_press_event', callback_click)
    callback_key = partial(_plot_onkey, params=params)
    fig.canvas.mpl_connect('key_press_event', callback_key)
    callback_resize = partial(_resize_event, params=params)
    fig.canvas.mpl_connect('resize_event', callback_resize)
    fig.canvas.mpl_connect('pick_event', partial(_onpick, params=params))
    params['callback_key'] = callback_key

    # Draw event lines for the first time.
    _plot_vert_lines(params)

    # Plot bad epochs
    for epoch_idx in params['bads']:
        params['ax_hscroll'].patches[epoch_idx].set_color((1., 0., 0., 1.))
        params['ax_hscroll'].patches[epoch_idx].set_zorder(3)
        params['ax_hscroll'].patches[epoch_idx].set_edgecolor('w')
        for ch_idx in range(len(params['ch_names'])):
            params['colors'][ch_idx][epoch_idx] = (1., 0., 0., 1.)

    assert params['fix_log'].shape == (len(epochs.events),
                                       len(params['ch_names']))
    # Plot bad segments
    if params['fix_log'] is not None:
        for ch_idx in range(len(params['ch_names'])):
            for epoch_idx in range(len(epochs.events)):
                this_log = params['fix_log'][epoch_idx, ch_idx]
                if epoch_idx in params['bads']:
                    pass
                else:
                    if this_log == 1:
                        params['colors'][ch_idx][epoch_idx] = (1., 0., 0., 1.)
                    elif this_log == 2:
                        params['colors'][ch_idx][epoch_idx] = (0., 0., 1., 1.)

    params['plot_fun']()
Example #25
0
def test_fix_stim_artifact():
    """Test fix stim artifact."""
    events = read_events(event_fname)

    raw = read_raw_fif(raw_fname)
    assert_raises(RuntimeError, fix_stim_artifact, raw)

    raw = read_raw_fif(raw_fname, preload=True)

    # use window before stimulus in epochs
    tmin, tmax, event_id = -0.2, 0.5, 1
    picks = pick_types(raw.info, meg=True, eeg=True,
                       eog=True, stim=False, exclude='bads')
    epochs = Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    preload=True, reject=None)
    e_start = int(np.ceil(epochs.info['sfreq'] * epochs.tmin))
    tmin, tmax = -0.045, -0.015
    tmin_samp = int(-0.035 * epochs.info['sfreq']) - e_start
    tmax_samp = int(-0.015 * epochs.info['sfreq']) - e_start

    epochs = fix_stim_artifact(epochs, tmin=tmin, tmax=tmax, mode='linear')
    data = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    diff_data0 = np.diff(data[0][0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    epochs = fix_stim_artifact(epochs, tmin=tmin, tmax=tmax, mode='window')
    data_from_epochs_fix = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    assert_true(np.all(data_from_epochs_fix) == 0.)

    # use window before stimulus in raw
    event_idx = np.where(events[:, 2] == 1)[0][0]
    tmin, tmax = -0.045, -0.015
    tmin_samp = int(-0.035 * raw.info['sfreq'])
    tmax_samp = int(-0.015 * raw.info['sfreq'])
    tidx = int(events[event_idx, 0] - raw.first_samp)

    assert_raises(ValueError, fix_stim_artifact, raw, events=np.array([]))
    raw = fix_stim_artifact(raw, events=None, event_id=1, tmin=tmin,
                            tmax=tmax, mode='linear', stim_channel='STI 014')
    data, times = raw[:, (tidx + tmin_samp):(tidx + tmax_samp)]
    diff_data0 = np.diff(data[0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    raw = fix_stim_artifact(raw, events, event_id=1, tmin=tmin,
                            tmax=tmax, mode='window')
    data, times = raw[:, (tidx + tmin_samp):(tidx + tmax_samp)]
    assert_true(np.all(data) == 0.)

    # get epochs from raw with fixed data
    tmin, tmax, event_id = -0.2, 0.5, 1
    epochs = Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    preload=True, reject=None, baseline=None)
    e_start = int(np.ceil(epochs.info['sfreq'] * epochs.tmin))
    tmin_samp = int(-0.035 * epochs.info['sfreq']) - e_start
    tmax_samp = int(-0.015 * epochs.info['sfreq']) - e_start
    data_from_raw_fix = epochs.get_data()[:, :, tmin_samp:tmax_samp]
    assert_true(np.all(data_from_raw_fix) == 0.)

    # use window after stimulus
    evoked = epochs.average()
    tmin, tmax = 0.005, 0.045
    tmin_samp = int(0.015 * evoked.info['sfreq']) - evoked.first
    tmax_samp = int(0.035 * evoked.info['sfreq']) - evoked.first

    evoked = fix_stim_artifact(evoked, tmin=tmin, tmax=tmax, mode='linear')
    data = evoked.data[:, tmin_samp:tmax_samp]
    diff_data0 = np.diff(data[0])
    diff_data0 -= np.mean(diff_data0)
    assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0)))

    evoked = fix_stim_artifact(evoked, tmin=tmin, tmax=tmax, mode='window')
    data = evoked.data[:, tmin_samp:tmax_samp]
    assert_true(np.all(data) == 0.)
def _interpolate_bads_meg(inst, mode='accurate', origin=None, verbose=None):
    """Interpolate bad channels from data in good channels.

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    mode : str
        Either `'accurate'` or `'fast'`, determines the quality of the
        Legendre polynomial expansion used for interpolation. `'fast'` should
        be sufficient for most applications.
    origin : None | list
        If None, origin is set to sensor center of mass, otherwise use the
        coordinates provided as origin. The old standard value is (0., 0., 0.04)
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).
    """
    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])
    picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')
    meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]
    bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]

    # select the bad meg channel to be interpolated
    if len(bads_meg) == 0:
        picks_bad = []
    else:
        picks_bad = pick_channels(inst.info['ch_names'], bads_meg, exclude=[])

    # return without doing anything if there are no meg channels
    if len(picks_meg) == 0 or len(picks_bad) == 0:
        return
    info_from = pick_info(inst.info, picks_good)
    info_to = pick_info(inst.info, picks_bad)

    if origin is None:

        posvec = np.array([inst.info['chs'][p]['loc'][0:3] for p in picks_meg])
        norvec = np.array(
            [inst.info['chs'][p]['loc'][9:12] for p in picks_meg])
        cogpos = np.mean(posvec, axis=0)
        norsum = np.mean(norvec, axis=0)
        anorm = np.sqrt(np.dot(norsum, norsum.T))
        ndir = norsum / anorm
        # push the position slightly (4cm) away from the helmet:
        altpos = cogpos - 0.04 * ndir
        print(">_interpolate_bads_meg\\DBG> cog(sens) = [%8.5f  %8.5f  %8.5f]" % \
              (cogpos[0], cogpos[1], cogpos[2]))
        print(">_interpolate_bads_meg\\DBG> alt(sens) = [%8.5f  %8.5f  %8.5f]" % \
              (altpos[0], altpos[1], altpos[2]))
        cogposhd = apply_trans(inst.info['dev_head_t']['trans'],
                               cogpos,
                               move=True)
        altposhd = apply_trans(inst.info['dev_head_t']['trans'],
                               altpos,
                               move=True)
        print(">_interpolate_bads_meg\\DBG> cog(hdcs) = [%8.5f  %8.5f  %8.5f]" % \
              (cogposhd[0], cogposhd[1], cogposhd[2]))
        print(">_interpolate_bads_meg\\DBG> alt(hdcs) = [%8.5f  %8.5f  %8.5f]" % \
              (altposhd[0], altposhd[1], altposhd[2]))
        print(">_interpolate_bads_meg\\DBG> calling _map_meg_channels(..., origin=(%8.5f  %8.5f  %8.5f))" % \
              (altposhd[0], altposhd[1], altposhd[2]))

        origin = (altposhd[0], altposhd[1], altposhd[2])

    else:
        origin = origin

    mapping = _map_meg_channels(info_from, info_to, mode=mode, origin=origin)
    _do_interp_dots(inst, mapping, picks_good, picks_bad)
Example #27
0
def find_bad_epochs(epochs,
                    picks=None,
                    return_by_metric=False,
                    method='faster',
                    method_params=None,
                    verbose=None):
    """Implements the second step of the FASTER algorithm.

    This function attempts to automatically mark bad epochs by performing
    outlier detection.

    Parameters
    ----------
    epochs : Instance of Epochs
        The epochs to analyze.
    picks : list of int | None
        Channels to operate on. Defaults to EEG channels.
    method : {'faster'}
        The detection algorithm.
    method_params : dict | None
        The method parameters in a dict.

        If ``method`` equals 'faster', and ``method_params``is None,
        defaults to the following parameters. Partial updates are supported.
        use_metrics : list of str
            List of metrics to use. Can be any combination of:
            'amplitude', 'variance', 'deviation'. Defaults to all of them.
        thresh : float
            The threshold value, in standard deviations, to apply. A channel
            crossing this threshold value is marked as bad. Defaults to 3.
        max_iter : int
            The maximum number of iterations performed during outlier detection
            (defaults to 1, as in the original FASTER paper).

    return_by_metric : bool
        Whether to return the bad channels as a flat list (False, default) or
        as a dictionary with the names of the used metrics as keys and the
        bad channels found by this metric as values. Is ignored if not
        supported by method.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see mne.verbose).
        Defaults to self.verbose.

    Returns
    -------
    bads : list of int
        The indices of the bad epochs.
    """
    if picks is None:
        picks = pick_types(epochs.info, meg=True, eeg=True, exclude='bads')
    _method_params = _handle_default('bads' + '_' + method, method_params)
    if method == 'faster':
        bads = _find_bad_epochs(epochs, picks, **_method_params)
    else:
        raise NotImplementedError(
            'Come back later, for now there is only "FASTER"')

    if return_by_metric:
        return bads
    else:
        return _combine_indices(bads)
Example #28
0
def interpolate_bads(inst,
                     reset_bads=True,
                     mode='accurate',
                     origin=None,
                     verbose=None):
    """
    Interpolate bad MEG and EEG channels.
    We added this method since the original interpolation routine resulted
    in some interpolated channels having amplitudes being magnitudes smaller
    than the channels they are being interpolated from.

    _interpolate_bads_meg(inst, origin=None) now calculates the center of mass
    of the sensors and uses that as origin (written by Eberhard).


    Operates in place.

    Parameters
    ----------
    inst : mne.io.Raw, mne.Epochs or mne.Evoked
        The data to interpolate. Must be preloaded.
    reset_bads : bool
        If True, remove the bads from info.
    mode : str
        Either ``'accurate'`` or ``'fast'``, determines the quality of the
        Legendre polynomial expansion used for interpolation of MEG
        channels.
    origin : None | list
        If None, origin is set to sensor center of mass, otherwise use the
        coordinates provided as origin. The old standard value is (0., 0., 0.04)
    verbose : bool, str, int, or None
        If not None, override default verbose level (see
        :func:`mne.verbose` and :ref:`Logging documentation <tut_logging>`
        for more).

    Returns
    -------
    inst : instance of Raw, Epochs, or Evoked
        The modified instance.

    """

    from mne.channels.interpolation import _interpolate_bads_eeg

    if getattr(inst, 'preload', None) is False:
        raise ValueError('Data must be preloaded.')

    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])
    if len(picks_meg) != 0:
        if origin is None:
            origin = _estimate_origin(inst.info, picks_meg)
        else:
            origin = origin

    if check_version('mne', '0.20'):
        _interpolate_bads_eeg(inst, origin=origin)
    else:
        # workaround for compatibility with 0.19, should be removed soon
        import warnings
        warnings.warn(
            'EEG channels may be interpolated with an incorrect origin,'
            'leading to inaccurate interpolation. Please update mne'
            'to the latest version for best results.', Warning)
        _interpolate_bads_eeg(inst)

    _interpolate_bads_meg(inst, origin=origin, mode=mode)

    if reset_bads is True:
        inst.info['bads'] = []

    return inst
Example #29
0
std_freq_i = coil_freqs.index(std_freq)
cal_dims = [1, 3]  # dimension of calibration files to test (1 and/or 3)

###########################
# Load raw for channel info
###########################
# Construct fname
date = '160302'
file_beg = date + '_empty_room_rotating_coil_'
file_end = '_hz_raw.fif'
fname_raw = op.join(file_head_dir, 'coil_data', '160302',
                    file_beg + str(std_freq) + '_hz_raw.fif')

# Load file and get mag inds
raw = mne.io.Raw(fname_raw)
mag_picks = pick_types(raw.info, meg='mag')

loc_arr = np.zeros((len(coil_freqs), len(mag_picks), 3))

###########################################
# Loop over all combinations of frequencies
###########################################
# Fill array with normal vectors for both sets of frequencies
for ci, freq in enumerate(coil_freqs):
    freq_fname = op.join(data_dir, 'sss_' + str(freq) + 'Hz_1D_cal.dat')
    loc_arr[ci, :, :] = extract_znorm(freq_fname, mag_picks)

########################################################
# Compare all vector normals
########################################################
diff = {}
Example #30
0
def select_vertices_in_sensor_range(inst,
                                    dist,
                                    info=None,
                                    picks=None,
                                    trans=None,
                                    indices=False,
                                    verbose=None):
    """Find vertices within given distance to a sensor.

    Parameters
    ----------
    inst : instance of Forward | instance of SourceSpaces
        The object to select vertices from.
    dist : float
        The minimum distance between a vertex and the nearest sensor. All
        vertices for which the distance to the nearest sensor exceeds this
        limit are discarded.
    info : instance of Info | None
        The info structure that contains information about the channels. Only
        needs to be specified if the object to select vertices from does is
        an instance of SourceSpaces.
    picks : array-like of int | None
        Indices of sensors to include in the search for the nearest sensor. If
        ``None``, the default, only MEG channels are used.
    trans : str | instance of Transform | None
        Either the full path to the head<->MRI transform ``*-trans.fif`` file
        produced during coregistration, or the Transformation itself. If trans
        is None, an identity matrix is assumed. Only needed when ``inst`` is a
        source space in MRI coordinates.
    indices: False | True
        If ``True``, return vertex indices instead of vertex numbers. Defaults
        to ``False``.
    verbose : bool | str | int | None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    vertices : pair of lists | list of int
        Either a list of vertex numbers for the left and right hemisphere (if
        ``indices==False``) or a single list with vertex indices.

    See Also
    --------
    restrict_forward_to_vertices : restrict Forward to the given vertices
    restrict_src_to_vertices : restrict SourceSpaces to the given vertices
    """

    if isinstance(inst, Forward):
        info = inst['info']
        src = inst['src']
    elif isinstance(inst, SourceSpaces):
        src = inst
        if info is None:
            raise ValueError('You need to specify an Info object with '
                             'information about the channels.')

    # Load the head<->MRI transform if necessary
    if src[0]['coord_frame'] == FIFF.FIFFV_COORD_MRI:
        if trans is None:
            raise ValueError('Source space is in MRI coordinates, but no '
                             'head<->MRI transform was given. Please specify '
                             'the full path to the appropriate *-trans.fif '
                             'file as the "trans" parameter.')
        if isinstance(trans, string_types):
            trans = read_trans(trans, return_all=True)
            for trans in trans:  # we got at least 1
                try:
                    trans = _ensure_trans(trans, 'head', 'mri')
                except Exception as exp:
                    pass
                else:
                    break
            else:
                raise exp

        src_trans = invert_transform(_ensure_trans(trans, 'head', 'mri'))
        print('Transform!')
    else:
        src_trans = Transform('head', 'head')  # Identity transform

    dev_to_head = _ensure_trans(info['dev_head_t'], 'meg', 'head')

    if picks is None:
        picks = pick_types(info, meg=True)
        if len(picks) > 0:
            logger.info('Using MEG channels')
        else:
            logger.info('Using EEG channels')
            picks = pick_types(info, eeg=True)

    src_pos = np.vstack([
        apply_trans(src_trans, s['rr'][s['inuse'].astype(np.bool)])
        for s in src
    ])

    sensor_pos = []
    for ch in picks:
        # MEG channels are in device coordinates, translate them to head
        if channel_type(info, ch) in ['mag', 'grad']:
            sensor_pos.append(
                apply_trans(dev_to_head, info['chs'][ch]['loc'][:3]))
        else:
            sensor_pos.append(info['chs'][ch]['loc'][:3])
    sensor_pos = np.array(sensor_pos)

    # Find vertices that are within range of a sensor. We use a KD-tree for
    # speed.
    logger.info('Finding vertices within sensor range...')
    tree = cKDTree(sensor_pos)
    distances, _ = tree.query(src_pos, distance_upper_bound=dist)

    # Vertices out of range are flagged as np.inf
    src_sel = np.isfinite(distances)
    logger.info('[done]')

    if indices:
        return np.flatnonzero(src_sel)
    else:
        n_lh_verts = src[0]['nuse']
        lh_sel, rh_sel = src_sel[:n_lh_verts], src_sel[n_lh_verts:]
        vert_lh = src[0]['vertno'][lh_sel]
        vert_rh = src[1]['vertno'][rh_sel]
        return [vert_lh, vert_rh]
def _prepare_for_forward(src,
                         mri_head_t,
                         info,
                         bem,
                         mindist,
                         n_jobs,
                         perts,
                         bem_extra='',
                         trans='',
                         info_extra='',
                         meg=True,
                         eeg=True,
                         ignore_ref=False,
                         verbose=None):
    """Prepare for forward computation."""
    # Read the source locations
    logger.info('')
    # let's make a copy in case we modify something
    src = _ensure_src(src).copy()
    nsource = sum(s['nuse'] for s in src)
    if nsource == 0:
        raise RuntimeError('No sources are active in these source spaces. '
                           '"do_all" option should be used.')
    logger.info('Read %d source spaces a total of %d active source locations' %
                (len(src), nsource))
    # Delete some keys to clean up the source space:
    for key in ['working_dir', 'command_line']:
        if key in src.info:
            del src.info[key]

    # Read the MRI -> head coordinate transformation
    logger.info('')
    _print_coord_trans(mri_head_t)

    # make a new dict with the relevant information
    arg_list = [
        info_extra, trans, src, bem_extra, meg, eeg, mindist, n_jobs, verbose
    ]
    cmd = 'make_forward_solution(%s)' % (', '.join([str(a) for a in arg_list]))
    mri_id = dict(machid=np.zeros(2, np.int32), version=0, secs=0, usecs=0)
    info = Info(chs=info['chs'],
                comps=info['comps'],
                dev_head_t=info['dev_head_t'],
                mri_file=trans,
                mri_id=mri_id,
                meas_file=info_extra,
                meas_id=None,
                working_dir=os.getcwd(),
                command_line=cmd,
                bads=info['bads'],
                mri_head_t=mri_head_t)
    info._update_redundant()
    info._check_consistency()
    logger.info('')

    megcoils, compcoils, megnames, meg_info = [], [], [], []
    eegels, eegnames = [], []

    if meg and len(pick_types(info, ref_meg=False, exclude=[])) > 0:
        megcoils, compcoils, megnames, meg_info = \
            _prep_meg_channels(info, perts, ignore_ref=ignore_ref)
    if eeg and len(
            pick_types(info, meg=False, eeg=True, ref_meg=False,
                       exclude=[])) > 0:
        eegels, eegnames = _prep_eeg_channels(info)

    # Check that some channels were found
    if len(megcoils + eegels) == 0:
        raise RuntimeError('No MEG or EEG channels found.')

    # pick out final info
    info = pick_info(
        info, pick_types(info, meg=meg, eeg=eeg, ref_meg=False, exclude=[]))

    # Transform the source spaces into the appropriate coordinates
    # (will either be HEAD or MRI)
    for s in src:
        transform_surface_to(s, 'head', mri_head_t)
    logger.info('Source spaces are now in %s coordinates.' %
                _coord_frame_name(s['coord_frame']))

    # Prepare the BEM model
    bem = _setup_bem(bem, bem_extra, len(eegnames), mri_head_t)

    # Circumvent numerical problems by excluding points too close to the skull
    if not bem['is_sphere']:
        inner_skull = _bem_find_surface(bem, 'inner_skull')
        _filter_source_spaces(inner_skull, mindist, mri_head_t, src, n_jobs)
        logger.info('')

    rr = np.concatenate([s['rr'][s['vertno']] for s in src])
    if len(rr) < 1:
        raise RuntimeError('No points left in source space after excluding '
                           'points close to inner skull.')

    # deal with free orientations:
    source_nn = np.tile(np.eye(3), (len(rr), 1))
    update_kwargs = dict(nchan=len(info['ch_names']),
                         nsource=len(rr),
                         info=info,
                         src=src,
                         source_nn=source_nn,
                         source_rr=rr,
                         surf_ori=False,
                         mri_head_t=mri_head_t)
    return megcoils, meg_info, compcoils, megnames, eegels, eegnames, rr, \
        info, update_kwargs, bem
Example #32
0
def find_bad_channels_in_epochs(epochs,
                                picks=None,
                                method='faster',
                                method_params=None,
                                return_by_metric=False):
    """Implements the fourth step of the FASTER algorithm.

    This function attempts to automatically mark bad channels in each epochs by
    performing outlier detection.

    Parameters
    ----------
    epochs : Instance of Epochs
        The epochs to analyze.
    picks : list of int | None
        Channels to operate on. Defaults to EEG channels.
    method : {'faster'}
        The detection algorithm.
    method_params : dict | None
        The method parameters in a dict.

        If ``method`` equals 'faster', and ``method_params``is None,
        defaults to the following parameters. Partial updates are supported.
        use_metrics : list of str
            List of metrics to use. Can be any combination of:
            'amplitude', 'variance', 'deviation', 'median_gradient'
            Defaults to all of them.
        thresh : float
            The threshold value, in standard deviations, to apply. A channel
            crossing this threshold value is marked as bad. Defaults to 3.
        max_iter : int
            The maximum number of iterations performed during outlier detection
            (defaults to 1, as in the original FASTER paper).

    return_by_metric : bool
        Whether to return the bad channels as a flat list (False, default) or
        as a dictionary with the names of the used metrics as keys and the
        bad channels found by this metric as values. Is ignored if not
        supported by method.

    Returns
    -------
    bads : list of lists of int
        For each epoch, the indices of the bad channels.
    """
    if picks is None:
        picks = pick_types(epochs.info, meg=True, eeg=True, exclude=[])

    _method_params = _handle_default('bads' + '_' + method, method_params)
    if method == 'faster':
        bads = _find_bad_channels_in_epochs(epochs, picks, **_method_params)
    else:
        raise NotImplementedError(
            'Come back later, for now there is only "FASTER"')

    info = pick_info(epochs.info, picks, copy=True)
    if return_by_metric:
        bads = dict((m, _bad_mask_to_names(info, v)) for m, v in bads.items())
    else:
        bads = np.sum(bads.values(), axis=0).astype(bool)
        bads = _bad_mask_to_names(info, bads)

    return bads