def _get_mappings(self, inst): from .utils import _fast_map_meg_channels ch_subsets = self.ch_subsets_ pos = np.array([ch['loc'][:3] for ch in inst.info['chs']]) ch_names = inst.info['ch_names'] n_channels = len(ch_names) pick_to = range(n_channels) mappings = [] # Try different channel subsets for idx in range(len(ch_subsets)): # don't do the following as it will sort the channels! # pick_from = pick_channels(ch_names, ch_subsets[idx]) pick_from = np.array( [ch_names.index(name) for name in ch_subsets[idx]]) mapping = np.zeros((n_channels, n_channels)) if self.ch_type == 'meg': mapping[:, pick_from] = _fast_map_meg_channels( inst, pick_from, pick_to) elif self.ch_type == 'eeg': mapping[:, pick_from] = _make_interpolation_matrix(pos[pick_from], pos[pick_to], alpha=1e-5) mappings.append(mapping) mappings = np.concatenate(mappings) return mappings
def _get_mappings(self, inst): from .utils import _fast_map_meg_channels ch_subsets = self.ch_subsets_ picked_info = mne.io.pick.pick_info(inst.info, self.picks) pos = np.array([ch['loc'][:3] for ch in picked_info['chs']]) ch_names = picked_info['ch_names'] n_channels = len(ch_names) pick_to = range(n_channels) mappings = [] # Try different channel subsets for idx in range(len(ch_subsets)): # don't do the following as it will sort the channels! # pick_from = pick_channels(ch_names, ch_subsets[idx]) pick_from = np.array([ch_names.index(name) for name in ch_subsets[idx]]) mapping = np.zeros((n_channels, n_channels)) if self.ch_type == 'meg': mapping[:, pick_from] = _fast_map_meg_channels( picked_info.copy(), pick_from, pick_to) elif self.ch_type == 'eeg': mapping[:, pick_from] = _make_interpolation_matrix( pos[pick_from], pos[pick_to], alpha=1e-5) mappings.append(mapping) mappings = np.concatenate(mappings) return mappings
def get_ransac_pred(self, chn_pos, chn_pos_good, good_chn_labs, n_pred_chns, data, random_state=None): """Perform RANSAC prediction. Parameters ---------- chn_pos : ndarray 3-D coordinates of the electrode position chn_pos_good : ndarray 3-D coordinates of all the channels not detected noisy so far good_chn_labs : array_like channel labels for the ch_pos_good channels n_pred_chns : int channel numbers used for interpolation for RANSAC data : ndarray 2-D EEG data random_state : int | None | np.random.mtrand.RandomState If random_state is an int, it will be used as a seed for RandomState. If None, the seed will be obtained from the operating system (see RandomState for details). Default is None. Returns ------- ransac_pred : ndarray Single RANSAC prediction Title: noisy Author: Stefan Appelhoff Date: 2018 Availability: https://github.com/sappelhoff/pyprep/blob/master/pyprep/noisy.py """ rng = check_random_state(random_state) # Pick a subset of clean channels for reconstruction reconstr_idx = rng.choice(np.arange(chn_pos_good.shape[0]), size=n_pred_chns, replace=False) # Get positions and according labels reconstr_labels = good_chn_labs[reconstr_idx] reconstr_pos = chn_pos_good[reconstr_idx, :] # Map the labels to their indices within the complete data # Do not use mne.pick_channels, because it will return a sorted list. reconstr_picks = [ list(self.ch_names_new).index(chn_lab) for chn_lab in reconstr_labels ] # Interpolate interpol_mat = _make_interpolation_matrix(reconstr_pos, chn_pos) ransac_pred = np.matmul(interpol_mat, data[reconstr_picks, :]) return ransac_pred
def _interpolate_bads_eeg(inst, picks=None, verbose=None): """ Interpolate bad EEG channels. Operates in place. Parameters ---------- inst : mne.io.Raw, mne.Epochs or mne.Evoked The data to interpolate. Must be preloaded. picks: np.ndarray, shape(n_channels, ) | list | None The channel indices to be used for interpolation. """ from mne.bem import _fit_sphere from mne.utils import logger, warn from mne.channels.interpolation import _do_interp_dots from mne.channels.interpolation import _make_interpolation_matrix import numpy as np if picks is None: picks = pick_types(inst.info, meg=False, eeg=True, exclude=[]) bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool) goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool) inst.info._check_consistency() bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks] if len(picks) == 0 or bads_idx.sum() == 0: return goods_idx[picks] = True goods_idx[bads_idx] = False pos = inst._get_channel_positions(picks) # Make sure only good 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: warn('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) logger.info('Interpolating {0} sensors'.format(len(pos_bad))) _do_interp_dots(inst, interpolation, goods_idx, bads_idx)
def _interpolate_bads_eeg(inst, picks=None, verbose=None): """ Interpolate bad EEG channels. Operates in place. Parameters ---------- inst : mne.io.Raw, mne.Epochs or mne.Evoked The data to interpolate. Must be preloaded. picks: np.ndarray, shape(n_channels, ) | list | None The channel indices to be used for interpolation. """ from mne.bem import _fit_sphere from mne.utils import logger, warn from mne.channels.interpolation import _do_interp_dots from mne.channels.interpolation import _make_interpolation_matrix import numpy as np if picks is None: picks = pick_types(inst.info, meg=False, eeg=True, exclude=[]) bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool) goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool) inst.info._check_consistency() bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks] if len(picks) == 0 or bads_idx.sum() == 0: return goods_idx[picks] = True goods_idx[bads_idx] = False pos = inst._get_channel_positions(picks) # Make sure only good 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: warn('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) logger.info('Interpolating {0} sensors'.format(len(pos_bad))) _do_interp_dots(inst, interpolation, goods_idx, bads_idx)
def _get_ransac_pred(self, chn_pos, chn_pos_good, good_chn_labs, n_pred_chns, data): """Make a single ransac prediction. Parameters ---------- chn_pos : ndarray, shape(n_chns, 3) 3D coordinates of the electrodes used to collect the EEG data. chn_pos_good : ndarray, shape(n_good_chns, 3) 3D coordinates of only the "clean" electrodes used to collect the EEG data. good_chn_labs : array_like, shape(n_good_chns,) The channel labels of the channels in `chn_good_pos`. n_pred_chns : int Number of channels used for each interpolation during ransac. data : ndarray, shape(n_chns, n_timepoints) The EEG data. Returns ------- ransac_pred : ndarray of shape(n_chns, n_timepts) A single prediction based on ransac. Several of these should be averaged (e.g., median) to get `ransac_eeg` See Also -------- _run_ransac, find_bad_by_ransac """ # Pick a subset of clean channels for reconstruction reconstr_idx = np.random.choice(np.arange(chn_pos_good.shape[0]), size=n_pred_chns, replace=False) # Get positions and according labels reconstr_labels = good_chn_labs[reconstr_idx] reconstr_pos = chn_pos_good[reconstr_idx, :] # Map the labels to their indices within the complete data # Do not use mne.pick_channels, because it will return a sorted list. reconstr_picks = [ list(self.ch_names).index(chn_lab) for chn_lab in reconstr_labels ] # Interpolate interpol_mat = _make_interpolation_matrix(reconstr_pos, chn_pos) ransac_pred = np.matmul(interpol_mat, data[reconstr_picks, :]) return ransac_pred
def test_interplation(): """Test interpolation""" epochs.info['bads'] = [] goods_idx = np.ones(len(epochs.ch_names), dtype=bool) goods_idx[epochs.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked = epochs.average() ave_before = evoked.data[bads_idx] pos = epochs.get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert_equal(interpolation.shape, (1, len(epochs.ch_names) - 1)) ave_after = np.dot(interpolation, evoked.data[goods_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) epochs.info['bads'] = [] assert_raises(ValueError, epochs.interpolate_bads_eeg) epochs.info['bads'] = ['EEG 012'] epochs.preload = False assert_raises(ValueError, epochs.interpolate_bads_eeg) epochs.preload = True epochs2.info['bads'] = ['EEG 012', 'MEG 1711'] epochs2.interpolate_bads_eeg() ave_after2 = epochs2.average().data[n_meg + np.where(bads_idx)[0]] assert_array_almost_equal(ave_after, ave_after2, decimal=16) raw = io.RawArray(data=epochs._data[0], info=epochs.info) raw_before = raw._data[bads_idx] raw.interpolate_bads_eeg() raw_after = raw._data[bads_idx] assert_equal(np.all(raw_before == raw_after), False) evoked = epochs.average() evoked.interpolate_bads_eeg() assert_array_equal(ave_after, evoked.data[bads_idx]) for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] assert_raises(ValueError, inst.interpolate_bads_eeg)
def get_ransac_pred(self, chn_pos, chn_pos_good, good_chn_labs, n_pred_chns, data): """Perform RANSAC prediction. Parameters ---------- chn_pos : ndarray 3-D coordinates of the electrode position chn_pos_good : ndarray 3-D coordinates of all the channels not detected noisy so far good_chn_labs : array_like channel labels for the ch_pos_good channels n_pred_chns : int channel numbers used for interpolation for RANSAC data : ndarray 2-D EEG data Returns ------- ransac_pred : ndarray Single RANSAC prediction """ rng = check_random_state(self.random_state) # Pick a subset of clean channels for reconstruction reconstr_idx = rng.choice(np.arange(chn_pos_good.shape[0]), size=n_pred_chns, replace=False) # Get positions and according labels reconstr_labels = good_chn_labs[reconstr_idx] reconstr_pos = chn_pos_good[reconstr_idx, :] # Map the labels to their indices within the complete data # Do not use mne.pick_channels, because it will return a sorted list. reconstr_picks = [ list(self.ch_names_new).index(chn_lab) for chn_lab in reconstr_labels ] # Interpolate interpol_mat = _make_interpolation_matrix(reconstr_pos, chn_pos) ransac_pred = np.matmul(interpol_mat, data[reconstr_picks, :]) return ransac_pred
def get_ransac_pred(chn_pos, chn_pos_good, good_chn_labs, n_pred_chns, raw, data): """Performs RANSAC prediction Parameters __________ chn_pos: ndarray 3-D coordinates of the electrode position chn_pos_good: ndarray 3-D coordinates of all the channels not detected noisy so far good_chn_labs: array_like channel labels for the ch_pos_good channels n_pred_chns: int channel numbers used for interpolation for RANSAC data: ndarry 2-D EEG data raw: raw mne object contains the EEG data and information associated with it Returns _______ ransac_pred: ndarray Single RANSAC prediction Title: noisy Author: Stefan Appelhoff Date: 2018 Availability: https://github.com/sappelhoff/pyprep/blob/master/pyprep/noisy.py """ ch_names = raw.info["ch_names"] reconstr_idx = np.random.choice( np.arange(chn_pos_good.shape[0]), size=n_pred_chns, replace=False) reconstr_labels = list() reconstr_pos = np.zeros((len(reconstr_idx), 3)) for i in range(0, len(reconstr_idx)): reconstr_labels.append(good_chn_labs[reconstr_idx[i]]) reconstr_pos[i, :] = chn_pos_good[reconstr_idx[i], :] reconstr_picks = [list(ch_names).index(chn_lab) for chn_lab in reconstr_labels] interpol_mat = _make_interpolation_matrix(reconstr_pos, chn_pos) ransac_pred = np.matmul(interpol_mat, data[reconstr_picks, :]) return ransac_pred
def _get_ransac_pred(chn_pos, chn_pos_good, good_chn_labs, complete_chn_labs, reconstr_idx, data): """Perform RANSAC prediction. Parameters ---------- chn_pos : np.ndarray 3-D coordinates of the electrode position chn_pos_good : np.ndarray 3-D coordinates of all the channels not detected noisy so far good_chn_labs : array_like channel labels for the ch_pos_good channels complete_chn_labs : array_like labels of the channels in data in the same order reconstr_idx : array_like indexes of the channels in good_chn_labs to use for reconstruction data : np.ndarray 2-D EEG data Returns ------- ransac_pred : np.ndarray Single RANSAC prediction """ # Get positions and according labels reconstr_labels = good_chn_labs[reconstr_idx] reconstr_pos = chn_pos_good[reconstr_idx, :] # Map the labels to their indices within the complete data # Do not use mne.pick_channels, because it will return a sorted list. reconstr_picks = [ list(complete_chn_labs).index(chn_lab) for chn_lab in reconstr_labels ] # Interpolate interpol_mat = _make_interpolation_matrix(reconstr_pos, chn_pos) ransac_pred = np.matmul(interpol_mat, data[reconstr_picks, :]) return ransac_pred
def _make_interpolation_matrices(random_ch_picks, chn_pos_good): """Create an interpolation matrix for each RANSAC sample of channels. This function takes the spatial coordinates of random subsets of currently-good channels and uses them to predict what the signal will be at the spatial coordinates of all other currently-good channels. The results of this process are returned as matrices that can be multiplied with EEG data to generate predicted signals. Parameters ---------- random_ch_picks : list of list of int A list containing multiple random subsets of currently-good channels. chn_pos_good : np.ndarray 3-D spatial coordinates of all currently-good channels. Returns ------- interpolation_mats : list of np.ndarray A list of interpolation matrices, one for each random subset of channels. Each matrix has the shape `[num_good_channels, num_good_channels]`, with the number of good channels being inferred from the size of `ch_pos_good`. Notes ----- This function currently makes use of a private MNE function, ``mne.channels.interpolation._make_interpolation_matrix``, to generate matrices. """ n_chans_good = chn_pos_good.shape[0] interpolation_mats = [] for sample in random_ch_picks: mat = np.zeros((n_chans_good, n_chans_good)) subset_pos = chn_pos_good[sample, :] mat[:, sample] = _make_interpolation_matrix(subset_pos, chn_pos_good) interpolation_mats.append(mat) return interpolation_mats
def test_interpolation(): """Test interpolation""" raw, epochs, epochs_eeg, epochs_meg = _load_data() # It's a trade of between speed and accuracy. If every second channel is # selected the tests are more than 3x faster but the correlation # drops to 0.8 thresh = 0.80 # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert_equal(interpolation.shape, (1, len(epochs_eeg.ch_names) - 1)) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False assert_raises(ValueError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert_equal(np.all(raw_before == raw_after), False) # check that interpolation fails when preload is False for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] assert_raises(ValueError, inst.interpolate_bads) # check that interpolation works for MEG epochs_meg.info['bads'] = ['MEG 0141'] evoked = epochs_meg.average() pick = pick_channels(epochs_meg.info['ch_names'], epochs_meg.info['bads']) # MEG -- raw raw_meg = io.RawArray(data=epochs_meg._data[0], info=epochs_meg.info) raw_meg.info['bads'] = ['MEG 0141'] data1 = raw_meg[pick, :][0][0] # reset_bads=False here because epochs_meg appears to share the same info # dict with raw and we want to test the epochs functionality too data2 = raw_meg.interpolate_bads(reset_bads=False)[pick, :][0][0] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) # the same number of bads as before assert_true(len(raw_meg.info['bads']) == len(raw_meg.info['bads'])) # MEG -- epochs data1 = epochs_meg.get_data()[:, pick, :].ravel() epochs_meg.interpolate_bads() data2 = epochs_meg.get_data()[:, pick, :].ravel() assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) assert_true(len(raw_meg.info['bads']) == 0) # MEG -- evoked data1 = evoked.data[pick] data2 = evoked.interpolate_bads().data[pick] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh)
def test_interpolation(): """Test interpolation.""" raw, epochs, epochs_eeg, epochs_meg = _load_data() # speed accuracy tradeoff: channel subselection is faster but the # correlation drops thresh = 0.7 # check that interpolation does nothing if no bads are marked epochs_eeg.info['bads'] = [] evoked_eeg = epochs_eeg.average() with pytest.warns(RuntimeWarning, match='Doing nothing'): evoked_eeg.interpolate_bads() # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert interpolation.shape == (1, len(epochs_eeg.ch_names) - 1) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False pytest.raises(RuntimeError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert not np.all(raw_before == raw_after) # check that interpolation fails when preload is False for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] pytest.raises(RuntimeError, inst.interpolate_bads) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert len(raw_few.ch_names) == 2 raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] with pytest.warns(None) as w: raw_few.interpolate_bads(reset_bads=False) assert len(w) == 0 new_data = raw_few[1][0] assert (new_data == 0).mean() < 0.5 assert np.corrcoef(new_data, orig_data)[0, 1] > 0.1 # check that interpolation works when non M/EEG channels are present # before MEG channels raw.rename_channels({'MEG 0113': 'TRIGGER'}) with pytest.warns(RuntimeWarning, match='unit .* changed from .* to .*'): raw.set_channel_types({'TRIGGER': 'stim'}) raw.info['bads'] = [raw.info['ch_names'][1]] raw.load_data() raw.interpolate_bads(mode='fast') # check that interpolation works for MEG epochs_meg.info['bads'] = ['MEG 0141'] evoked = epochs_meg.average() pick = pick_channels(epochs_meg.info['ch_names'], epochs_meg.info['bads']) # MEG -- raw raw_meg = io.RawArray(data=epochs_meg._data[0], info=epochs_meg.info) raw_meg.info['bads'] = ['MEG 0141'] data1 = raw_meg[pick, :][0][0] raw_meg.info.normalize_proj() data2 = raw_meg.interpolate_bads(reset_bads=False, mode='fast')[pick, :][0][0] assert np.corrcoef(data1, data2)[0, 1] > thresh # the same number of bads as before assert len(raw_meg.info['bads']) == len(raw_meg.info['bads']) # MEG -- epochs data1 = epochs_meg.get_data()[:, pick, :].ravel() epochs_meg.info.normalize_proj() epochs_meg.interpolate_bads(mode='fast') data2 = epochs_meg.get_data()[:, pick, :].ravel() assert np.corrcoef(data1, data2)[0, 1] > thresh assert len(epochs_meg.info['bads']) == 0 # MEG -- evoked (plus auto origin) data1 = evoked.data[pick] evoked.info.normalize_proj() data2 = evoked.interpolate_bads(origin='auto').data[pick] assert np.corrcoef(data1, data2)[0, 1] > thresh
def test_interpolation_eeg(offset, avg_proj, ctol, atol, method): """Test interpolation of EEG channels.""" raw, epochs_eeg = _load_data('eeg') epochs_eeg = epochs_eeg.copy() assert not _has_eeg_average_ref_proj(epochs_eeg.info['projs']) # Offsetting the coordinate frame should have no effect on the output for inst in (raw, epochs_eeg): for ch in inst.info['chs']: if ch['kind'] == io.constants.FIFF.FIFFV_EEG_CH: ch['loc'][:3] += offset ch['loc'][3:6] += offset for d in inst.info['dig']: d['r'] += offset # check that interpolation does nothing if no bads are marked epochs_eeg.info['bads'] = [] evoked_eeg = epochs_eeg.average() kw = dict(method=method) with pytest.warns(RuntimeWarning, match='Doing nothing'): evoked_eeg.interpolate_bads(**kw) # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx pos = epochs_eeg._get_channel_positions() evoked_eeg = epochs_eeg.average() if avg_proj: evoked_eeg.set_eeg_reference(projection=True).apply_proj() assert_allclose(evoked_eeg.data.mean(0), 0., atol=1e-20) ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() if avg_proj: evoked_eeg.set_eeg_reference(projection=True).apply_proj() good_picks = pick_types(evoked_eeg.info, meg=False, eeg=True) assert_allclose(evoked_eeg.data[good_picks].mean(0), 0., atol=1e-20) evoked_eeg_bad = evoked_eeg.copy() bads_picks = pick_channels(epochs_eeg.ch_names, include=epochs_eeg.info['bads'], ordered=True) evoked_eeg_bad.data[bads_picks, :] = 1e10 # Test first the exclude parameter evoked_eeg_2_bads = evoked_eeg_bad.copy() evoked_eeg_2_bads.info['bads'] = ['EEG 004', 'EEG 012'] evoked_eeg_2_bads.data[pick_channels(evoked_eeg_bad.ch_names, ['EEG 004', 'EEG 012'])] = 1e10 evoked_eeg_interp = evoked_eeg_2_bads.interpolate_bads(origin=(0., 0., 0.), exclude=['EEG 004'], **kw) assert evoked_eeg_interp.info['bads'] == ['EEG 004'] assert np.all(evoked_eeg_interp.get_data('EEG 004') == 1e10) assert np.all(evoked_eeg_interp.get_data('EEG 012') != 1e10) # Now test without exclude parameter evoked_eeg_bad.info['bads'] = ['EEG 012'] evoked_eeg_interp = evoked_eeg_bad.copy().interpolate_bads(origin=(0., 0., 0.), **kw) if avg_proj: assert_allclose(evoked_eeg_interp.data.mean(0), 0., atol=1e-6) interp_zero = evoked_eeg_interp.data[bads_idx] if method is None: # using pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert interpolation.shape == (1, len(epochs_eeg.ch_names) - 1) interp_manual = np.dot(interpolation, evoked_eeg_bad.data[goods_idx]) assert_array_equal(interp_manual, interp_zero) del interp_manual, interpolation, pos, pos_good, pos_bad assert_allclose(ave_before, interp_zero, atol=atol) assert ctol[0] < np.corrcoef(ave_before, interp_zero)[0, 1] < ctol[1] interp_fit = evoked_eeg_bad.copy().interpolate_bads(**kw).data[bads_idx] assert_allclose(ave_before, interp_fit, atol=2.5e-6) assert ctol[1] < np.corrcoef(ave_before, interp_fit)[0, 1] # better # check that interpolation fails when preload is False epochs_eeg.preload = False with pytest.raises(RuntimeError, match='requires epochs data to be loade'): epochs_eeg.interpolate_bads(**kw) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads(**kw)._data[bads_idx] assert not np.all(raw_before == raw_after) # check that interpolation fails when preload is False for inst in [raw, epochs_eeg]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] with pytest.raises(RuntimeError, match='requires.*data to be loaded'): inst.interpolate_bads(**kw) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert len(raw_few.ch_names) == 2 raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] with _record_warnings() as w: raw_few.interpolate_bads(reset_bads=False, **kw) assert len([ww for ww in w if 'more than' not in str(ww.message)]) == 0 new_data = raw_few[1][0] assert (new_data == 0).mean() < 0.5 assert np.corrcoef(new_data, orig_data)[0, 1] > 0.2
def test_interpolation(): """Test interpolation""" raw, epochs, epochs_eeg, epochs_meg = _load_data() # It's a trade of between speed and accuracy. If every second channel is # selected the tests are more than 3x faster but the correlation # drops to 0.8 thresh = 0.80 # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert_equal(interpolation.shape, (1, len(epochs_eeg.ch_names) - 1)) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False assert_raises(ValueError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert_equal(np.all(raw_before == raw_after), False) # check that interpolation fails when preload is False for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] assert_raises(ValueError, inst.interpolate_bads) # check that interpolation works for MEG epochs_meg.info['bads'] = ['MEG 0141'] evoked = epochs_meg.average() pick = pick_channels(epochs_meg.info['ch_names'], epochs_meg.info['bads']) # MEG -- raw raw_meg = io.RawArray(data=epochs_meg._data[0], info=epochs_meg.info) raw_meg.info['bads'] = ['MEG 0141'] data1 = raw_meg[pick, :][0][0] # reset_bads=False here because epochs_meg appears to share the same info # dict with raw and we want to test the epochs functionality too raw_meg.info.normalize_proj() data2 = raw_meg.interpolate_bads(reset_bads=False)[pick, :][0][0] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) # the same number of bads as before assert_true(len(raw_meg.info['bads']) == len(raw_meg.info['bads'])) # MEG -- epochs data1 = epochs_meg.get_data()[:, pick, :].ravel() epochs_meg.info.normalize_proj() epochs_meg.interpolate_bads() data2 = epochs_meg.get_data()[:, pick, :].ravel() assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) assert_true(len(raw_meg.info['bads']) == 0) # MEG -- evoked data1 = evoked.data[pick] evoked.info.normalize_proj() data2 = evoked.interpolate_bads().data[pick] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh)
def test_interpolation_eeg(): """Test interpolation of EEG channels.""" raw, epochs_eeg = _load_data('eeg') # check that interpolation does nothing if no bads are marked epochs_eeg.info['bads'] = [] evoked_eeg = epochs_eeg.average() with pytest.warns(RuntimeWarning, match='Doing nothing'): evoked_eeg.interpolate_bads() # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert interpolation.shape == (1, len(epochs_eeg.ch_names) - 1) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False pytest.raises(RuntimeError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert not np.all(raw_before == raw_after) # check that interpolation fails when preload is False for inst in [raw, epochs_eeg]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] pytest.raises(RuntimeError, inst.interpolate_bads) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert len(raw_few.ch_names) == 2 raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] with pytest.warns(None) as w: raw_few.interpolate_bads(reset_bads=False) assert len(w) == 0 new_data = raw_few[1][0] assert (new_data == 0).mean() < 0.5 assert np.corrcoef(new_data, orig_data)[0, 1] > 0.1
def test_interpolation_eeg(offset): """Test interpolation of EEG channels.""" raw, epochs_eeg = _load_data('eeg') epochs_eeg = epochs_eeg.copy() # Offsetting the coordinate frame should have no effect on the output for inst in (raw, epochs_eeg): for ch in inst.info['chs']: if ch['kind'] == io.constants.FIFF.FIFFV_EEG_CH: ch['loc'][:3] += offset ch['loc'][3:6] += offset for d in inst.info['dig']: d['r'] += offset # check that interpolation does nothing if no bads are marked epochs_eeg.info['bads'] = [] evoked_eeg = epochs_eeg.average() with pytest.warns(RuntimeWarning, match='Doing nothing'): evoked_eeg.interpolate_bads() # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert interpolation.shape == (1, len(epochs_eeg.ch_names) - 1) interp_manual = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() interp_zero = evoked_eeg.interpolate_bads( origin=(0., 0., 0.)).data[bads_idx] assert_array_equal(interp_manual, interp_zero) assert_allclose(ave_before, interp_zero, atol=3e-6) assert 0.985 < np.corrcoef(ave_before, interp_zero)[0, 1] < 0.99 evoked_eeg.info['bads'] = ['EEG 012'] interp_fit = evoked_eeg.interpolate_bads().data[bads_idx] assert_allclose(ave_before, interp_fit, atol=2e-6) assert 0.99 < np.corrcoef(ave_before, interp_fit)[0, 1] # better # check that interpolation fails when preload is False epochs_eeg.preload = False pytest.raises(RuntimeError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert not np.all(raw_before == raw_after) # check that interpolation fails when preload is False for inst in [raw, epochs_eeg]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] pytest.raises(RuntimeError, inst.interpolate_bads) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert len(raw_few.ch_names) == 2 raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] with pytest.warns(None) as w: raw_few.interpolate_bads(reset_bads=False) assert len([ww for ww in w if 'more than' not in str(ww.message)]) == 0 new_data = raw_few[1][0] assert (new_data == 0).mean() < 0.5 assert np.corrcoef(new_data, orig_data)[0, 1] > 0.2
def test_interpolation(): """Test interpolation""" raw, epochs, epochs_eeg, epochs_meg = _load_data() # It's a trade of between speed and accuracy. If every second channel is # selected the tests are more than 3x faster but the correlation # drops to 0.8 thresh = 0.80 # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert_equal(interpolation.shape, (1, len(epochs_eeg.ch_names) - 1)) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False assert_raises(ValueError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert_equal(np.all(raw_before == raw_after), False) # check that interpolation fails when preload is False for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] assert_raises(ValueError, inst.interpolate_bads) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert_equal(len(raw_few.ch_names), 2) raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] raw_few.interpolate_bads(reset_bads=False) new_data = raw_few[1][0] assert_true((new_data == 0).mean() < 0.5) assert_true(np.corrcoef(new_data, orig_data)[0, 1] > 0.1) # check that interpolation works when non M/EEG channels are present # before MEG channels with warnings.catch_warnings(record=True): # change of units raw.rename_channels({'MEG 0113': 'TRIGGER'}) raw.set_channel_types({'TRIGGER': 'stim'}) raw.info['bads'] = [raw.info['ch_names'][1]] raw.load_data() raw.interpolate_bads() # check that interpolation works for MEG epochs_meg.info['bads'] = ['MEG 0141'] evoked = epochs_meg.average() pick = pick_channels(epochs_meg.info['ch_names'], epochs_meg.info['bads']) # MEG -- raw raw_meg = io.RawArray(data=epochs_meg._data[0], info=epochs_meg.info) raw_meg.info['bads'] = ['MEG 0141'] data1 = raw_meg[pick, :][0][0] raw_meg.info.normalize_proj() data2 = raw_meg.interpolate_bads(reset_bads=False)[pick, :][0][0] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) # the same number of bads as before assert_true(len(raw_meg.info['bads']) == len(raw_meg.info['bads'])) # MEG -- epochs data1 = epochs_meg.get_data()[:, pick, :].ravel() epochs_meg.info.normalize_proj() epochs_meg.interpolate_bads() data2 = epochs_meg.get_data()[:, pick, :].ravel() assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) assert_true(len(epochs_meg.info['bads']) == 0) # MEG -- evoked data1 = evoked.data[pick] evoked.info.normalize_proj() data2 = evoked.interpolate_bads().data[pick] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh)
def test_interpolation(): """Test interpolation""" raw, epochs, epochs_eeg, epochs_meg = _load_data() # It's a trade of between speed and accuracy. If every second channel is # selected the tests are more than 3x faster but the correlation # drops to 0.8 thresh = 0.80 # check that interpolation does nothing if no bads are marked epochs_eeg.info['bads'] = [] evoked_eeg = epochs_eeg.average() with warnings.catch_warnings(record=True) as w: evoked_eeg.interpolate_bads() assert_true(any('Doing nothing' in str(ww.message) for ww in w)) # create good and bad channels for EEG epochs_eeg.info['bads'] = [] goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) goods_idx[epochs_eeg.ch_names.index('EEG 012')] = False bads_idx = ~goods_idx evoked_eeg = epochs_eeg.average() ave_before = evoked_eeg.data[bads_idx] # interpolate bad channels for EEG pos = epochs_eeg._get_channel_positions() pos_good = pos[goods_idx] pos_bad = pos[bads_idx] interpolation = _make_interpolation_matrix(pos_good, pos_bad) assert_equal(interpolation.shape, (1, len(epochs_eeg.ch_names) - 1)) ave_after = np.dot(interpolation, evoked_eeg.data[goods_idx]) epochs_eeg.info['bads'] = ['EEG 012'] evoked_eeg = epochs_eeg.average() assert_array_equal(ave_after, evoked_eeg.interpolate_bads().data[bads_idx]) assert_allclose(ave_before, ave_after, atol=2e-6) # check that interpolation fails when preload is False epochs_eeg.preload = False assert_raises(RuntimeError, epochs_eeg.interpolate_bads) epochs_eeg.preload = True # check that interpolation changes the data in raw raw_eeg = io.RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) raw_before = raw_eeg._data[bads_idx] raw_after = raw_eeg.interpolate_bads()._data[bads_idx] assert_equal(np.all(raw_before == raw_after), False) # check that interpolation fails when preload is False for inst in [raw, epochs]: assert hasattr(inst, 'preload') inst.preload = False inst.info['bads'] = [inst.ch_names[1]] assert_raises(RuntimeError, inst.interpolate_bads) # check that interpolation works with few channels raw_few = raw.copy().crop(0, 0.1).load_data() raw_few.pick_channels(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) assert_equal(len(raw_few.ch_names), 2) raw_few.del_proj() raw_few.info['bads'] = [raw_few.ch_names[-1]] orig_data = raw_few[1][0] with warnings.catch_warnings(record=True) as w: raw_few.interpolate_bads(reset_bads=False) assert len(w) == 0 new_data = raw_few[1][0] assert_true((new_data == 0).mean() < 0.5) assert_true(np.corrcoef(new_data, orig_data)[0, 1] > 0.1) # check that interpolation works when non M/EEG channels are present # before MEG channels with warnings.catch_warnings(record=True): # change of units raw.rename_channels({'MEG 0113': 'TRIGGER'}) raw.set_channel_types({'TRIGGER': 'stim'}) raw.info['bads'] = [raw.info['ch_names'][1]] raw.load_data() raw.interpolate_bads() # check that interpolation works for MEG epochs_meg.info['bads'] = ['MEG 0141'] evoked = epochs_meg.average() pick = pick_channels(epochs_meg.info['ch_names'], epochs_meg.info['bads']) # MEG -- raw raw_meg = io.RawArray(data=epochs_meg._data[0], info=epochs_meg.info) raw_meg.info['bads'] = ['MEG 0141'] data1 = raw_meg[pick, :][0][0] raw_meg.info.normalize_proj() data2 = raw_meg.interpolate_bads(reset_bads=False)[pick, :][0][0] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) # the same number of bads as before assert_true(len(raw_meg.info['bads']) == len(raw_meg.info['bads'])) # MEG -- epochs data1 = epochs_meg.get_data()[:, pick, :].ravel() epochs_meg.info.normalize_proj() epochs_meg.interpolate_bads() data2 = epochs_meg.get_data()[:, pick, :].ravel() assert_true(np.corrcoef(data1, data2)[0, 1] > thresh) assert_true(len(epochs_meg.info['bads']) == 0) # MEG -- evoked data1 = evoked.data[pick] evoked.info.normalize_proj() data2 = evoked.interpolate_bads().data[pick] assert_true(np.corrcoef(data1, data2)[0, 1] > thresh)
def _interpolate_bads_eeg(inst, picks=None, verbose=False): """ Interpolate bad EEG channels. Operates in place. Parameters ---------- inst : mne.io.Raw, mne.Epochs or mne.Evoked The data to interpolate. Must be preloaded. picks : str | list | slice | None Channels to include for interpolation. Slices and lists of integers will be interpreted as channel indices. In lists, channel *name* strings (e.g., ``['EEG 01', 'EEG 02']``) will pick the given channels. None (default) will pick all EEG channels. Note that channels in ``info['bads']`` *will be included* if their names or indices are explicitly provided. """ from mne.bem import _fit_sphere from mne.utils import logger, warn from mne.channels.interpolation import _do_interp_dots from mne.channels.interpolation import _make_interpolation_matrix import numpy as np inst.info._check_consistency() if picks is None: picks = pick_types(inst.info, meg=False, eeg=True, exclude=[]) else: picks = _handle_picks(inst.info, picks) bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool) goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool) bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks] if len(picks) == 0 or bads_idx.sum() == 0: return goods_idx[picks] = True goods_idx[bads_idx] = False pos = inst._get_channel_positions(picks) # Make sure only good 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: warn('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) logger.info('Interpolating {0} sensors'.format(len(pos_bad))) _do_interp_dots(inst, interpolation, goods_idx, bads_idx)