def test_flat_acq_skip(): """Test that acquisition skips are handled properly.""" raw = read_raw_fif(skip_fname).load_data() annot, bads = annotate_flat(raw) assert len(annot) == 0 assert bads == [ # MaxFilter finds the same 21 channels 'MEG%04d' % (int(num),) for num in '141 331 421 431 611 641 1011 1021 1031 1241 1421 ' '1741 1841 2011 2131 2141 2241 2531 2541 2611 2621'.split()]
def test_annotate_flat(first_samp): """Test marking flat segments.""" # Test if ECG analysis will work on data that is not preloaded n_ch, n_times = 11, 1000 data = np.random.RandomState(0).randn(n_ch, n_times) assert not (np.diff(data, axis=-1) == 0).any() # nothing flat at first info = create_info(n_ch, 1000., 'eeg') info['meas_date'] = (1, 2) # test first_samp != for gh-6295 raw = RawArray(data, info, first_samp=first_samp) raw.info['bads'] = [raw.ch_names[-1]] # # First make a channel flat the whole time # raw_0 = raw.copy() raw_0._data[0] = 0. for kwargs, bads, want_times in [ # Anything < 1 will mark spatially (dict(bad_percent=100.), [], 0), (dict(bad_percent=99.9), [raw.ch_names[0]], n_times), (dict(), [raw.ch_names[0]], n_times) ]: # default (1) raw_time = raw_0.copy() annot, got_bads = annotate_flat(raw_0, verbose='debug', **kwargs) assert got_bads == bads raw_time.set_annotations(raw_time.annotations + annot) raw_time.info['bads'] += got_bads n_good_times = raw_time.get_data(reject_by_annotation='omit').shape[1] assert n_good_times == want_times with pytest.deprecated_call(match='annotate_flat'): raw_time_2 = mark_flat(raw_0.copy(), verbose='debug', **kwargs) _assert_annotations_equal(raw_time_2.annotations, raw_time.annotations) assert raw_time_2.info['bads'] == raw_time.info['bads'] # # Now make a channel flat for 20% of the time points # raw_0 = raw.copy() n_good_times = int(round(0.8 * n_times)) raw_0._data[0, n_good_times:] = 0. threshold = 100 * (n_times - n_good_times) / n_times for kwargs, bads, want_times in [ # Should change behavior at bad_percent=20 (dict(bad_percent=100), [], n_good_times), (dict(bad_percent=threshold), [], n_good_times), (dict(bad_percent=threshold - 1e-5), [raw.ch_names[0]], n_times), (dict(), [raw.ch_names[0]], n_times) ]: annot, got_bads = annotate_flat(raw_0, verbose='debug', **kwargs) assert got_bads == bads raw_time = raw_0.copy() raw_time.set_annotations(raw_time.annotations + annot) raw_time.info['bads'] += got_bads n_good_times = raw_time.get_data(reject_by_annotation='omit').shape[1] assert n_good_times == want_times with pytest.raises(TypeError, match='must be an instance of BaseRaw'): annotate_flat(0.) with pytest.raises(ValueError, match='not convert string to float'): annotate_flat(raw, 'x')
def _inspect_raw(*, bids_path, l_freq, h_freq, find_flat, show_annotations, verbose=None): """Raw data inspection.""" # Delay the import import matplotlib import matplotlib.pyplot as plt extra_params = dict() if bids_path.extension == '.fif': extra_params['allow_maxshield'] = True raw = read_raw_bids(bids_path, extra_params=extra_params, verbose='error') old_bads = raw.info['bads'].copy() old_annotations = raw.annotations.copy() if find_flat: raw.load_data() # Speeds up processing dramatically flat_annot, flat_chans = annotate_flat(raw=raw, min_duration=0.05, verbose=verbose) new_annot = raw.annotations + flat_annot raw.set_annotations(new_annot) raw.info['bads'] = list(set(raw.info['bads'] + flat_chans)) del new_annot, flat_annot else: flat_chans = [] fig = raw.plot(title=f'{bids_path.root.name}: {bids_path.basename}', highpass=l_freq, lowpass=h_freq, show_options=True, block=False, show=False, verbose='warning') # Add our own event handlers so that when the MNE Raw Browser is being # closed, our dialog box will pop up, asking whether to save changes. def _handle_close(event): mne_raw_fig = event.canvas.figure # Bads alterations are only transferred to `inst` once the figure is # closed; Annotation changes are immediately reflected in `inst` new_bads = mne_raw_fig.mne.info['bads'].copy() new_annotations = mne_raw_fig.mne.inst.annotations.copy() if not new_annotations: # Ensure it's not an empty list, but an empty set of Annotations. new_annotations = mne.Annotations( onset=[], duration=[], description=[], orig_time=mne_raw_fig.mne.info['meas_date']) _save_raw_if_changed(old_bads=old_bads, new_bads=new_bads, flat_chans=flat_chans, old_annotations=old_annotations, new_annotations=new_annotations, bids_path=bids_path, verbose=verbose) _global_vars['raw_fig'] = None def _keypress_callback(event): if event.key == _global_vars['mne_close_key']: _handle_close(event) fig.canvas.mpl_connect('close_event', _handle_close) fig.canvas.mpl_connect('key_press_event', _keypress_callback) if not show_annotations: # Remove annotations and kill `_toggle_annotation_fig` method, since # we cannot directly and easily remove the associated `a` keyboard # event callback. fig._clear_annotations() fig._toggle_annotation_fig = lambda: None # Ensure it's not an empty list, but an empty set of Annotations. old_annotations = mne.Annotations(onset=[], duration=[], description=[], orig_time=raw.info['meas_date']) if matplotlib.get_backend() != 'agg': plt.show(block=True) _global_vars['raw_fig'] = fig _global_vars['mne_close_key'] = fig.mne.close_key