def test_find_bad_by_ransac(raw_tmp): """Test the RANSAC component of NoisyChannels.""" # Set a consistent random seed for all RANSAC runs RANSAC_RNG = 435656 # RANSAC identifies channels that go bad together and are highly correlated. # Inserting highly correlated signal in channels 0 through 6 at 30 Hz raw_tmp._data[0:6, :] = _generate_signal(30, 30, raw_tmp.times) # Run different variations of RANSAC on the same data test_matrix = { # List items represent [matlab_strict, channel_wise, max_chunk_size] "by_window": [False, False, None], "by_channel": [False, True, None], "by_channel_maxchunk": [False, True, 2], "by_window_strict": [True, False, None], "by_channel_strict": [True, True, None], } bads = {} corr = {} for name, args in test_matrix.items(): nd = NoisyChannels(raw_tmp, do_detrend=False, random_state=RANSAC_RNG, matlab_strict=args[0]) nd.find_bad_by_ransac(channel_wise=args[1], max_chunk_size=args[2]) # Save bad channels and RANSAC correlation matrix for later comparison bads[name] = nd.bad_by_ransac corr[name] = nd._extra_info["bad_by_ransac"]["ransac_correlations"] # Test whether all methods detected bad channels properly assert bads["by_window"] == raw_tmp.ch_names[0:6] assert bads["by_channel"] == raw_tmp.ch_names[0:6] assert bads["by_channel_maxchunk"] == raw_tmp.ch_names[0:6] assert bads["by_window_strict"] == raw_tmp.ch_names[0:6] assert bads["by_channel_strict"] == raw_tmp.ch_names[0:6] # Make sure non-strict correlation matrices all match assert np.allclose(corr["by_window"], corr["by_channel"]) assert np.allclose(corr["by_window"], corr["by_channel_maxchunk"]) # Make sure MATLAB-strict correlation matrices match assert np.allclose(corr["by_window_strict"], corr["by_channel_strict"]) # Make sure strict and non-strict matrices differ assert not np.allclose(corr["by_window"], corr["by_window_strict"]) # Ensure that RANSAC doesn't change random state if in MATLAB-strict mode rng = RandomState(RANSAC_RNG) init_state = rng.get_state()[2] nd = NoisyChannels(raw_tmp, do_detrend=False, random_state=rng, matlab_strict=True) nd.find_bad_by_ransac() assert rng.get_state()[2] == init_state
def test_find_bad_by_ransac_err(raw_tmp): """Test error handling in the `find_bad_by_ransac` method.""" # Set n_samples very very high to trigger a memory error n_samples = int(1e100) nd = NoisyChannels(raw_tmp, do_detrend=False) with pytest.raises(MemoryError): nd.find_bad_by_ransac(n_samples=n_samples) # Set n_samples to a float to trigger a type error n_samples = 35.5 nd = NoisyChannels(raw_tmp, do_detrend=False) with pytest.raises(TypeError): nd.find_bad_by_ransac(n_samples=n_samples) # Test IOError when too few good channels for RANSAC sample size n_chans = raw_tmp._data.shape[0] nd = NoisyChannels(raw_tmp, do_detrend=False) nd.bad_by_deviation = raw_tmp.info["ch_names"][0:int(n_chans * 0.8)] with pytest.raises(IOError): nd.find_bad_by_ransac() # Test IOError when not enough channels for RANSAC predictions raw_tmp._data[0:(n_chans - 2), :] = 0 # make all channels flat except 2 nd = NoisyChannels(raw_tmp, do_detrend=False) with pytest.raises(IOError): nd.find_bad_by_ransac()
raw = mne.io.RawArray(X, info) raw.set_montage(montage, verbose=False) ############################################################################### # Assign the mne object to the :class:`NoisyChannels` class. The resulting object # will be the place where all following methods are performed. nd = NoisyChannels(raw, random_state=1337) nd2 = NoisyChannels(raw, random_state=1337) ############################################################################### # Find all bad channels using channel-wise RANSAC and print a summary start_time = perf_counter() nd.find_bad_by_ransac(channel_wise=True) print("--- %s seconds ---" % (perf_counter() - start_time)) # Repeat channel-wise RANSAC using a single channel at a time. This is slower # but needs less memory. start_time = perf_counter() nd2.find_bad_by_ransac(channel_wise=True, max_chunk_size=1) print("--- %s seconds ---" % (perf_counter() - start_time)) ############################################################################### # Now the bad channels are saved in `bads` and we can continue processing our # `raw` object. For more information, we can access attributes of the ``nd`` # instance: # Check channels that go bad together by correlation (RANSAC) print(nd.bad_by_ransac)
def test_findnoisychannels(raw, montage): raw.set_montage(montage) nd = NoisyChannels(raw) nd.find_all_bads(ransac=True) bads = nd.get_bads() iterations = ( 10 # remove any noisy channels by interpolating the bads for 10 iterations ) for iter in range(0, iterations): raw.info["bads"] = bads raw.interpolate_bads() nd = NoisyChannels(raw) nd.find_all_bads(ransac=True) bads = nd.get_bads() # make sure no bad channels exist in the data raw.drop_channels(ch_names=bads) # Test for NaN and flat channels raw_tmp = raw.copy() m, n = raw_tmp._data.shape # Insert a nan value for a random channel rand_chn_idx1 = int(np.random.randint(0, m, 1)) rand_chn_idx2 = int(np.random.randint(0, m, 1)) rand_chn_lab1 = raw_tmp.ch_names[rand_chn_idx1] rand_chn_lab2 = raw_tmp.ch_names[rand_chn_idx2] raw_tmp._data[rand_chn_idx1, n - 1] = np.nan raw_tmp._data[rand_chn_idx2, :] = np.ones(n) nd = NoisyChannels(raw_tmp) nd.find_bad_by_nan_flat() assert nd.bad_by_nan == [rand_chn_lab1] assert nd.bad_by_flat == [rand_chn_lab2] # Test for high and low deviations in EEG data raw_tmp = raw.copy() m, n = raw_tmp._data.shape # Now insert one random channel with very low deviations rand_chn_idx = int(np.random.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] raw_tmp._data[rand_chn_idx, :] = raw_tmp._data[rand_chn_idx, :] / 10 nd = NoisyChannels(raw_tmp) nd.find_bad_by_deviation() assert rand_chn_lab in nd.bad_by_deviation # Inserting one random channel with a high deviation raw_tmp = raw.copy() rand_chn_idx = int(np.random.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] arbitrary_scaling = 5 raw_tmp._data[rand_chn_idx, :] *= arbitrary_scaling nd = NoisyChannels(raw_tmp) nd.find_bad_by_deviation() assert rand_chn_lab in nd.bad_by_deviation # Test for correlation between EEG channels raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(np.random.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # Use cosine instead of sine to create a signal low = 10 high = 30 n_freq = 5 signal = np.zeros((1, n)) for freq_i in range(n_freq): freq = np.random.randint(low, high, n) signal[0, :] += np.cos(2 * np.pi * raw.times * freq) raw_tmp._data[rand_chn_idx, :] = signal * 1e-6 nd = NoisyChannels(raw_tmp) nd.find_bad_by_correlation() assert rand_chn_lab in nd.bad_by_correlation # Test for high freq noise detection raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(np.random.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # Use freqs between 90 and 100 Hz to insert hf noise signal = np.zeros((1, n)) for freq_i in range(n_freq): freq = np.random.randint(90, 100, n) signal[0, :] += np.sin(2 * np.pi * raw.times * freq) raw_tmp._data[rand_chn_idx, :] = signal * 1e-6 nd = NoisyChannels(raw_tmp) nd.find_bad_by_hfnoise() assert rand_chn_lab in nd.bad_by_hf_noise # Test for signal to noise ratio in EEG data raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(np.random.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # inserting an uncorrelated high frequency (90 Hz) signal in one channel raw_tmp[rand_chn_idx, :] = np.sin(2 * np.pi * raw.times * 90) * 1e-6 nd = NoisyChannels(raw_tmp) nd.find_bad_by_SNR() assert rand_chn_lab in nd.bad_by_SNR # Test for finding bad channels by RANSAC raw_tmp = raw.copy() # Ransac identifies channels that go bad together and are highly correlated. # Inserting highly correlated signal in channels 0 through 3 at 30 Hz raw_tmp._data[0:6, :] = np.cos(2 * np.pi * raw.times * 30) * 1e-6 nd = NoisyChannels(raw_tmp) np.random.seed(30) nd.find_bad_by_ransac() bads = nd.bad_by_ransac assert bads == raw_tmp.ch_names[0:6]
def test_findnoisychannels(raw, montage): """Test find noisy channels.""" # Set a random state for the test rng = np.random.RandomState(30) raw.set_montage(montage) nd = NoisyChannels(raw, random_state=rng) nd.find_all_bads(ransac=True) bads = nd.get_bads() iterations = ( 10 # remove any noisy channels by interpolating the bads for 10 iterations ) for iter in range(0, iterations): if len(bads) == 0: continue raw.info["bads"] = bads raw.interpolate_bads() nd = NoisyChannels(raw, random_state=rng) nd.find_all_bads(ransac=True) bads = nd.get_bads() # make sure no bad channels exist in the data raw.drop_channels(ch_names=bads) # Test for NaN and flat channels raw_tmp = raw.copy() m, n = raw_tmp._data.shape # Insert a nan value for a random channel and make another random channel # completely flat (ones) idxs = rng.choice(np.arange(m), size=2, replace=False) rand_chn_idx1 = idxs[0] rand_chn_idx2 = idxs[1] rand_chn_lab1 = raw_tmp.ch_names[rand_chn_idx1] rand_chn_lab2 = raw_tmp.ch_names[rand_chn_idx2] raw_tmp._data[rand_chn_idx1, n - 1] = np.nan raw_tmp._data[rand_chn_idx2, :] = np.ones(n) nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_nan_flat() assert nd.bad_by_nan == [rand_chn_lab1] assert nd.bad_by_flat == [rand_chn_lab2] # Test for high and low deviations in EEG data raw_tmp = raw.copy() m, n = raw_tmp._data.shape # Now insert one random channel with very low deviations rand_chn_idx = int(rng.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] raw_tmp._data[rand_chn_idx, :] = raw_tmp._data[rand_chn_idx, :] / 10 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_deviation() assert rand_chn_lab in nd.bad_by_deviation # Inserting one random channel with a high deviation raw_tmp = raw.copy() rand_chn_idx = int(rng.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] arbitrary_scaling = 5 raw_tmp._data[rand_chn_idx, :] *= arbitrary_scaling nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_deviation() assert rand_chn_lab in nd.bad_by_deviation # Test for correlation between EEG channels raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(rng.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # Use cosine instead of sine to create a signal low = 10 high = 30 n_freq = 5 signal = np.zeros((1, n)) for freq_i in range(n_freq): freq = rng.randint(low, high, n) signal[0, :] += np.cos(2 * np.pi * raw.times * freq) raw_tmp._data[rand_chn_idx, :] = signal * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_correlation() assert rand_chn_lab in nd.bad_by_correlation # Test for high freq noise detection raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(rng.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # Use freqs between 90 and 100 Hz to insert hf noise signal = np.zeros((1, n)) for freq_i in range(n_freq): freq = rng.randint(90, 100, n) signal[0, :] += np.sin(2 * np.pi * raw.times * freq) raw_tmp._data[rand_chn_idx, :] = signal * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_hfnoise() assert rand_chn_lab in nd.bad_by_hf_noise # Test for signal to noise ratio in EEG data raw_tmp = raw.copy() m, n = raw_tmp._data.shape rand_chn_idx = int(rng.randint(0, m, 1)) rand_chn_lab = raw_tmp.ch_names[rand_chn_idx] # inserting an uncorrelated high frequency (90 Hz) signal in one channel raw_tmp[rand_chn_idx, :] = np.sin(2 * np.pi * raw.times * 90) * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_SNR() assert rand_chn_lab in nd.bad_by_SNR # Test for finding bad channels by RANSAC raw_tmp = raw.copy() # Ransac identifies channels that go bad together and are highly correlated. # Inserting highly correlated signal in channels 0 through 3 at 30 Hz raw_tmp._data[0:6, :] = np.cos(2 * np.pi * raw.times * 30) * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_ransac() bads = nd.bad_by_ransac assert bads == raw_tmp.ch_names[0:6] # Test for finding bad channels by channel-wise RANSAC raw_tmp = raw.copy() # Ransac identifies channels that go bad together and are highly correlated. # Inserting highly correlated signal in channels 0 through 3 at 30 Hz raw_tmp._data[0:6, :] = np.cos(2 * np.pi * raw.times * 30) * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_bad_by_ransac(channel_wise=True) bads = nd.bad_by_ransac assert bads == raw_tmp.ch_names[0:6] # Test not-enough-memory and n_samples type exceptions raw_tmp = raw.copy() raw_tmp._data[0:6, :] = np.cos(2 * np.pi * raw.times * 30) * 1e-6 nd = NoisyChannels(raw_tmp, random_state=rng) # Set n_samples very very high to trigger a memory error n_samples = int(1e100) with pytest.raises(MemoryError): nd.find_bad_by_ransac(n_samples=n_samples) # Set n_samples to a float to trigger a type error n_samples = 35.5 with pytest.raises(TypeError): nd.find_bad_by_ransac(n_samples=n_samples) # Test IOError when not enough channels for ransac predictions raw_tmp = raw.copy() # Make flat all channels except 2 num_bad_channels = raw._data.shape[0] - 2 raw_tmp._data[0:num_bad_channels, :] = np.zeros_like( raw_tmp._data[0:num_bad_channels, :] ) nd = NoisyChannels(raw_tmp, random_state=rng) nd.find_all_bads(ransac=False) with pytest.raises(IOError): nd.find_bad_by_ransac()
datatype='eeg', suffix='eeg') raw = read_raw_bids(bids_path=bids_path, extra_params=dict(preload=True)) raw.info['bads'] = [ 'FT7', 'FT8', 'T7', 'T8', 'TP7', 'TP8', 'AF7', 'AF8', 'M1', 'M2', 'BIP1', 'BIP2', 'BIP3', 'BIP4', 'BIP5', 'BIP6', 'BIP7', 'BIP8', 'BIP9', 'BIP10', 'BIP11', 'BIP12', 'BIP13', 'BIP14', 'BIP15', 'BIP16', 'BIP17', 'BIP18', 'BIP19', 'BIP20', 'BIP21', 'BIP22', 'BIP23', 'BIP24' ] raw.drop_channels(ch_names=raw.info['bads']) montage = mne.channels.make_standard_montage('standard_1020') raw.set_montage(montage) filt_raw = raw.copy() filt_raw.drop_channels('EOG') nd = NoisyChannels(filt_raw) nd.find_bad_by_ransac(n_samples=50, channel_wise=True) raw.info['bads'] = nd.bad_by_ransac raw.notch_filter(np.arange(50, 250, 50)) filt_raw.notch_filter(np.arange(50, 250, 50)) raw.filter(l_freq=settings.high_filter, h_freq=settings.low_filter, fir_design='firwin') filt_raw.filter(l_freq=1, h_freq=settings.low_filter) filt_raw.info['bads'] = raw.info['bads'] raw.interpolate_bads(reset_bads=True, mode='accurate') filt_raw.interpolate_bads(reset_bads=True, mode='accurate') raw.resample(200, npad='auto') filt_raw.resample(200, npad='auto') raw.set_eeg_reference('average') filt_raw.set_eeg_reference('average') eog_evoked = create_eog_epochs(raw).average()
raw = mne.io.RawArray(X, info) raw.set_montage(montage, verbose=False) ############################################################################### # Assign the mne object to the :class:`NoisyChannels` class. The resulting object # will be the place where all following methods are performed. nd = NoisyChannels(raw) nd2 = NoisyChannels(raw) ############################################################################### # Find all bad channels and print a summary start_time = perf_counter() nd.find_bad_by_ransac() print("--- %s seconds ---" % (perf_counter() - start_time)) # Repeat RANSAC in a channel wise manner. This is slower but needs less memory. start_time = perf_counter() nd2.find_bad_by_ransac(channel_wise=True) print("--- %s seconds ---" % (perf_counter() - start_time)) ############################################################################### # Now the bad channels are saved in `bads` and we can continue processing our # `raw` object. For more information, we can access attributes of the ``nd`` # instance: # Check channels that go bad together by correlation (RANSAC) print(nd.bad_by_ransac) assert set(bad_ch_names) == set(nd.bad_by_ransac)
freq_good * time) for i in range(n_chans) ] # Scale the signal amplitude and add noise. X = 2e-5 * np.array(X) + 1e-5 * np.random.random((n_chans, time.shape[0])) raw = mne.io.RawArray(X, info) raw.set_montage(montage, verbose=False) ############################################################################### # Assign the mne object to the :class:`NoisyChannels` class. The resulting object # will be the place where all following methods are performed. nd = NoisyChannels(raw) ############################################################################### # Find all bad channels and print a summary start_time = perf_counter() nd.find_bad_by_ransac() print("--- %s seconds ---" % (perf_counter() - start_time)) ############################################################################### # Now the bad channels are saved in `bads` and we can continue processing our # `raw` object. For more information, we can access attributes of the ``nd`` # instance: # Check channels that go bad together by correlation (RANSAC) print(nd.bad_by_ransac) assert set(bad_ch_names) == set(nd.bad_by_ransac)