def test_inspect_bads_and_annotations(tmp_path): """Test adding bads and Annotations in one go.""" from mne.utils._testing import _click_ch_name import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') plt.close('all') bids_root = setup_bids_test_dir(tmp_path) bids_path = _bids_path.copy().update(root=bids_root) raw = read_raw_bids(bids_path=bids_path, verbose='error') orig_bads = raw.info['bads'].copy() inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] # Mark some channels as bad by clicking on their name. _click_ch_name(raw_fig, ch_index=0, button=1) # Add custom Annotation. _add_annotation(raw_fig) # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # Check that the changes were saved. raw = read_raw_bids(bids_path=bids_path, verbose='error') new_bads = raw.info['bads'] expected_bads = orig_bads + ['MEG 0113'] assert set(new_bads) == set(expected_bads) assert 'BAD_test' in raw.annotations.description
def test_handle_info_reading(): """Test reading information from a BIDS sidecar.json file.""" bids_root = _TempDir() # read in USA dataset, so it should find 50 Hz raw = mne.io.read_raw_fif(raw_fname) raw.info['line_freq'] = 60 # write copy of raw with line freq of 60 # bids basename and fname bids_basename = make_bids_basename(subject='01', session='01', task='audiovisual', run='01') kind = "meg" bids_fname = bids_basename + '_{}.fif'.format(kind) write_raw_bids(raw, bids_basename, bids_root, overwrite=True) # find sidecar JSON fname sidecar_fname = _find_matching_sidecar(bids_fname, bids_root, '{}.json'.format(kind), allow_fail=True) # assert that we get the same line frequency set raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert raw.info['line_freq'] == 60 # 2. if line frequency is not set in raw file, then default to sidecar raw.info['line_freq'] = None write_raw_bids(raw, bids_basename, bids_root, overwrite=True) _update_sidecar(sidecar_fname, "PowerLineFrequency", 55) raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert raw.info['line_freq'] == 55 # make a copy of the sidecar in "derivatives/" # to check that we make sure we always get the right sidecar # in addition, it should not break the sidecar reading # in `read_raw_bids` deriv_dir = op.join(bids_root, "derivatives") sidecar_copy = op.join(deriv_dir, op.basename(sidecar_fname)) os.mkdir(deriv_dir) with open(sidecar_fname, "r") as fin: sidecar_json = json.load(fin) sidecar_json["PowerLineFrequency"] = 45 _write_json(sidecar_copy, sidecar_json) raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert raw.info['line_freq'] == 55 # 3. if line frequency is set in raw file, but not sidecar raw.info['line_freq'] = 60 write_raw_bids(raw, bids_basename, bids_root, overwrite=True) _update_sidecar(sidecar_fname, "PowerLineFrequency", "n/a") raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert raw.info['line_freq'] == 60 # 4. assert that we get an error when sidecar json doesn't match _update_sidecar(sidecar_fname, "PowerLineFrequency", 55) with pytest.raises(ValueError, match="Line frequency in sidecar json"): raw = mne_bids.read_raw_bids(bids_fname, bids_root)
def test_inspect_single_file(return_bids_test_dir, save_changes): from mne.utils._testing import _click_ch_name import matplotlib matplotlib.use('Agg') bids_path = _bids_path.copy().update(root=return_bids_test_dir) raw = read_raw_bids(bids_path=bids_path, verbose='error') old_bads = raw.info['bads'].copy() inspect_dataset(bids_path) raw_fig = mne_bids.inspect._global_vars['raw_fig'] # Mark some channels as bad by clicking on their name. _click_ch_name(raw_fig, ch_index=0, button=1) _click_ch_name(raw_fig, ch_index=1, button=1) _click_ch_name(raw_fig, ch_index=4, button=1) # Closing the window should open a dialog box. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] if save_changes: key = 'return' else: key = 'escape' fig_dialog.canvas.key_press_event(key) raw = read_raw_bids(bids_path=bids_path, verbose='error') new_bads = raw.info['bads'].copy() if save_changes: assert len(new_bads) > len(old_bads) else: assert old_bads == new_bads
def test_bti(_bids_validate): """Test functionality of the write_raw_bids conversion for BTi data.""" output_path = _TempDir() data_path = op.join(base_path, 'bti', 'tests', 'data') raw_fname = op.join(data_path, 'test_pdf_linux') config_fname = op.join(data_path, 'test_config_linux') headshape_fname = op.join(data_path, 'test_hs_linux') raw = mne.io.read_raw_bti(raw_fname, config_fname=config_fname, head_shape_fname=headshape_fname) write_raw_bids(raw, bids_basename, output_path, verbose=True) assert op.exists(op.join(output_path, 'participants.tsv')) _bids_validate(output_path) raw = read_raw_bids(bids_basename + '_meg', output_path) with pytest.raises(TypeError, match="unexpected keyword argument 'foo'"): read_raw_bids(bids_basename + '_meg', output_path, extra_params=dict(foo='bar')) # test anonymize raw = mne.io.read_raw_bti(raw_fname, config_fname=config_fname, head_shape_fname=headshape_fname) with pytest.warns(UserWarning, match='Converting to FIF for anonymization'): output_path = _test_anonymize(raw, bids_basename) _bids_validate(output_path)
def test_vhdr(_bids_validate): """Test write_raw_bids conversion for BrainVision data.""" output_path = _TempDir() data_path = op.join(base_path, 'brainvision', 'tests', 'data') raw_fname = op.join(data_path, 'test.vhdr') raw = mne.io.read_raw_brainvision(raw_fname) # inject a bad channel assert not raw.info['bads'] injected_bad = ['FP1'] raw.info['bads'] = injected_bad # write with injected bad channels write_raw_bids(raw, bids_basename_minimal, output_path, overwrite=False) _bids_validate(output_path) # read and also get the bad channels raw = read_raw_bids(bids_basename_minimal + '_eeg.vhdr', output_path) with pytest.raises(TypeError, match="unexpected keyword argument 'foo'"): read_raw_bids(bids_basename_minimal + '_eeg.vhdr', output_path, extra_params=dict(foo='bar')) # Check that injected bad channel shows up in raw after reading np.testing.assert_array_equal(np.asarray(raw.info['bads']), np.asarray(injected_bad)) # Test that correct channel units are written ... and that bad channel # is in channels.tsv channels_tsv_name = op.join(output_path, 'sub-{}'.format(subject_id), 'eeg', bids_basename_minimal + '_channels.tsv') data = _from_tsv(channels_tsv_name) assert data['units'][data['name'].index('FP1')] == 'µV' assert data['units'][data['name'].index('CP5')] == 'n/a' assert data['status'][data['name'].index(injected_bad[0])] == 'bad' # check events.tsv is written events_tsv_fname = channels_tsv_name.replace('channels', 'events') assert op.exists(events_tsv_fname) # create another bids folder with the overwrite command and check # no files are in the folder data_path = make_bids_folders(subject=subject_id, kind='eeg', output_path=output_path, overwrite=True) assert len([f for f in os.listdir(data_path) if op.isfile(f)]) == 0 # test anonymize and convert raw = mne.io.read_raw_brainvision(raw_fname) _test_anonymize(raw, bids_basename) # Also cover iEEG # We use the same data and pretend that eeg channels are ecog raw = mne.io.read_raw_brainvision(raw_fname) raw.set_channel_types({raw.ch_names[i]: 'ecog' for i in mne.pick_types(raw.info, eeg=True)}) output_path = _TempDir() write_raw_bids(raw, bids_basename, output_path, overwrite=False) _bids_validate(output_path)
def test_edf(_bids_validate): """Test write_raw_bids conversion for European Data Format data.""" output_path = _TempDir() data_path = op.join(testing.data_path(), 'EDF') raw_fname = op.join(data_path, 'test_reduced.edf') raw = mne.io.read_raw_edf(raw_fname, preload=True) # XXX: hack that should be fixed later. Annotation reading is # broken for this file with preload=False and read_annotations_edf raw.preload = False raw.rename_channels({raw.info['ch_names'][0]: 'EOG'}) raw.info['chs'][0]['coil_type'] = FIFF.FIFFV_COIL_EEG_BIPOLAR raw.rename_channels({raw.info['ch_names'][1]: 'EMG'}) raw.set_channel_types({'EMG': 'emg'}) write_raw_bids(raw, bids_basename, output_path) # Reading the file back should raise an error, because we renamed channels # in `raw` and used that information to write a channels.tsv. Yet, we # saved the unchanged `raw` in the BIDS folder, so channels in the TSV and # in raw clash with pytest.raises(RuntimeError, match='Channels do not correspond'): read_raw_bids(bids_basename + '_eeg.edf', output_path) bids_fname = bids_basename.replace('run-01', 'run-%s' % run2) write_raw_bids(raw, bids_fname, output_path, overwrite=True) _bids_validate(output_path) # ensure there is an EMG channel in the channels.tsv: channels_tsv = make_bids_basename(subject=subject_id, session=session_id, task=task, run=run, suffix='channels.tsv', acquisition=acq, prefix=op.join(output_path, 'sub-01', 'ses-01', 'eeg')) data = _from_tsv(channels_tsv) assert 'ElectroMyoGram' in data['description'] # check that the scans list contains two scans scans_tsv = make_bids_basename(subject=subject_id, session=session_id, suffix='scans.tsv', prefix=op.join(output_path, 'sub-01', 'ses-01')) data = _from_tsv(scans_tsv) assert len(list(data.values())[0]) == 2 # Also cover iEEG # We use the same data and pretend that eeg channels are ecog raw.set_channel_types( {raw.ch_names[i]: 'ecog' for i in mne.pick_types(raw.info, eeg=True)}) output_path = _TempDir() write_raw_bids(raw, bids_basename, output_path) _bids_validate(output_path)
def test_set(_bids_validate): """Test write_raw_bids conversion for EEGLAB data.""" # standalone .set file output_path = _TempDir() data_path = op.join(testing.data_path(), 'EEGLAB') # .set with associated .fdt output_path = _TempDir() data_path = op.join(testing.data_path(), 'EEGLAB') raw_fname = op.join(data_path, 'test_raw.set') raw = mne.io.read_raw_eeglab(raw_fname) # embedded - test mne-version assertion tmp_version = mne.__version__ mne.__version__ = '0.16' with pytest.raises(ValueError, match='Your version of MNE is too old.'): write_raw_bids(raw, bids_basename, output_path) mne.__version__ = tmp_version # proceed with the actual test for EEGLAB data write_raw_bids(raw, bids_basename, output_path, overwrite=False) read_raw_bids(bids_basename + '_eeg.set', output_path) with pytest.raises(TypeError, match="unexpected keyword argument 'foo'"): read_raw_bids(bids_basename + '_eeg.set', output_path, extra_params=dict(foo='bar')) with pytest.raises(FileExistsError, match="already exists"): # noqa: F821 write_raw_bids(raw, bids_basename, output_path=output_path, overwrite=False) _bids_validate(output_path) # check events.tsv is written # XXX: only from 0.18 onwards because events_from_annotations # is broken for earlier versions events_tsv_fname = op.join(output_path, 'sub-' + subject_id, 'ses-' + session_id, 'eeg', bids_basename + '_events.tsv') if check_version('mne', '0.18'): assert op.exists(events_tsv_fname) # Also cover iEEG # We use the same data and pretend that eeg channels are ecog raw.set_channel_types( {raw.ch_names[i]: 'ecog' for i in mne.pick_types(raw.info, eeg=True)}) output_path = _TempDir() write_raw_bids(raw, bids_basename, output_path) _bids_validate(output_path) # test anonymize and convert if check_version('mne', '0.20') and check_version('pybv', '0.2.0'): output_path = _test_anonymize(raw, bids_basename) _bids_validate(output_path)
def test_mark_bad_chanels_single_file(tmpdir): """Test mne_bids mark_channels.""" # Check that help is printed check_usage(mne_bids_mark_channels) # Create test dataset. output_path = str(tmpdir) data_path = testing.data_path() raw_fname = op.join(data_path, 'MEG', 'sample', 'sample_audvis_trunc_raw.fif') old_bads = mne.io.read_raw_fif(raw_fname).info['bads'] bids_path = BIDSPath(subject=subject_id, task=task, root=output_path, datatype=datatype) with ArgvSetter( ('--subject_id', subject_id, '--task', task, '--raw', raw_fname, '--bids_root', output_path, '--line_freq', 60)): mne_bids_raw_to_bids.run() # Update the dataset. ch_names = ['MEG 0112', 'MEG 0131'] descriptions = ['Really bad!', 'Even worse.'] args = [ '--subject_id', subject_id, '--task', task, '--bids_root', output_path, '--type', datatype ] for ch_name, description in zip(ch_names, descriptions): args.extend(['--ch_name', ch_name]) args.extend(['--description', description]) args = tuple(args) with ArgvSetter(args): mne_bids_mark_channels.run() # Check the data was properly written with pytest.warns(RuntimeWarning, match='The unit for chann*'): raw = read_raw_bids(bids_path=bids_path, verbose=False) assert set(old_bads + ch_names) == set(raw.info['bads']) # Test resetting bad channels. args = ('--subject_id', subject_id, '--task', task, '--bids_root', output_path, '--type', datatype, '--status', 'good', '--ch_name', '') with ArgvSetter(args): mne_bids_mark_channels.run() print('Finished running the reset...') # Check the data was properly written with pytest.warns(RuntimeWarning, match='The unit for chann*'): raw = read_raw_bids(bids_path=bids_path) assert raw.info['bads'] == []
def test_inspect_auto_flats(tmp_path, save_changes): """Test flat channel & segment detection.""" import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') plt.close('all') bids_root = setup_bids_test_dir(tmp_path) bids_path = _bids_path.copy().update(root=bids_root) channels_tsv_fname = bids_path.copy().update(suffix='channels', extension='.tsv') raw = read_raw_bids(bids_path=bids_path, verbose='error') # Inject an entirely flat channel. raw.load_data() raw._data[10] = np.zeros_like(raw._data[10], dtype=raw._data.dtype) # Add a a flat time segment (approx. 100 ms) to another channel raw._data[20, 500:500 + int(np.ceil(0.1 * raw.info['sfreq']))] = 0 raw.save(raw.filenames[0], overwrite=True) old_bads = raw.info['bads'].copy() inspect_dataset(bids_path) raw_fig = mne_bids.inspect._global_vars['raw_fig'] # Closing the window should open a dialog box. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] if save_changes: key = 'return' else: key = 'escape' fig_dialog.canvas.key_press_event(key) raw = read_raw_bids(bids_path=bids_path, verbose='error') if save_changes: assert old_bads != raw.info['bads'] assert raw.ch_names[10] in raw.info['bads'] channels_tsv_data = _from_tsv(channels_tsv_fname) assert (channels_tsv_data['status_description'][10] == 'Flat channel, auto-detected via MNE-BIDS') # This channel should not have been added to `bads`, but produced a # flat annotation. assert raw.ch_names[20] not in raw.info['bads'] assert 'BAD_flat' in raw.annotations.description else: assert old_bads == raw.info['bads'] assert 'BAD_flat' not in raw.annotations.description
def test_line_freq_estimation(): """Test estimating line frequency.""" bids_root = _TempDir() # read in USA dataset, so it should find 50 Hz raw = mne.io.read_raw_fif(raw_fname) kind = "meg" # assert that we get the same line frequency set bids_fname = bids_basename + '_{}.fif'.format(kind) # find sidecar JSON fname write_raw_bids(raw, bids_basename, bids_root, overwrite=True) sidecar_fname = _find_matching_sidecar(bids_fname, bids_root, '{}.json'.format(kind), allow_fail=True) # 1. when nothing is set, default to use PSD estimation -> should be 60 # for `sample` dataset raw.info['line_freq'] = None write_raw_bids(raw, bids_basename, bids_root, overwrite=True) _update_sidecar(sidecar_fname, "PowerLineFrequency", "n/a") with pytest.warns(UserWarning, match="No line frequency found"): raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert raw.info['line_freq'] == 60 # test that `somato` dataset finds 50 Hz (EU dataset) somato_raw = mne.io.read_raw_fif(somato_raw_fname) somato_raw.info['line_freq'] = None write_raw_bids(somato_raw, bids_basename, bids_root, overwrite=True) sidecar_fname = _find_matching_sidecar(bids_fname, bids_root, '{}.json'.format(kind), allow_fail=True) _update_sidecar(sidecar_fname, "PowerLineFrequency", "n/a") with pytest.warns(UserWarning, match="No line frequency found"): somato_raw = mne_bids.read_raw_bids(bids_fname, bids_root) assert somato_raw.info['line_freq'] == 50 # assert that line_freq should be None when # all picks are not meg/eeg/ecog/seeg somato_raw.info['line_freq'] = None somato_raw.set_channel_types({ somato_raw.ch_names[i]: 'bio' for i in range(len(somato_raw.ch_names)) }) somato_raw = _handle_info_reading(sidecar_fname, somato_raw, verbose=True) assert somato_raw.info['line_freq'] is None
def epoch_preprocessing(bids_path): with open(os.devnull, "w") as f, contextlib.redirect_stdout(f): raw_intensity = read_raw_bids(bids_path=bids_path).load_data() raw_od = optical_density(raw_intensity) raw_od.resample(1.5) raw_haemo = beer_lambert_law(raw_od, ppf=6) raw_haemo = raw_haemo.filter(None, 0.6, h_trans_bandwidth=0.05, l_trans_bandwidth=0.01, verbose=False) events, event_dict = events_from_annotations(raw_haemo, verbose=False) epochs = Epochs(raw_haemo, events, event_id=event_dict, tmin=-5, tmax=30, reject=dict(hbo=100e-6), reject_by_annotation=True, proj=True, baseline=(None, 0), detrend=1, preload=True, verbose=False) epochs = epochs[["Control", "Audio"]] return raw_haemo, epochs
def test_ctf(_bids_validate): """Test functionality of the write_raw_bids conversion for CTF data.""" output_path = _TempDir() data_path = op.join(testing.data_path(download=False), 'CTF') raw_fname = op.join(data_path, 'testdata_ctf.ds') raw = mne.io.read_raw_ctf(raw_fname) with pytest.warns(UserWarning, match='No line frequency'): write_raw_bids(raw, bids_basename, output_path=output_path) _bids_validate(output_path) with pytest.warns(UserWarning, match='Did not find any events'): raw = read_raw_bids(bids_basename + '_meg.ds', output_path, extra_params=dict(clean_names=False)) # test to check that running again with overwrite == False raises an error with pytest.raises(FileExistsError, match="already exists"): # noqa: F821 write_raw_bids(raw, bids_basename, output_path=output_path) assert op.exists(op.join(output_path, 'participants.tsv')) # test anonymize raw = mne.io.read_raw_ctf(raw_fname) with pytest.warns(UserWarning, match='Converting to FIF for anonymization'): output_path = _test_anonymize(raw, bids_basename) _bids_validate(output_path) # XXX: change the next two lines once raw.set_meas_date() is # available. raw.info['meas_date'] = None raw.anonymize() with pytest.raises(ValueError, match='All measurement dates are None'): get_anonymization_daysback(raw)
def test_return_values(default_param, select_subjects, select_tasks): default_param["load_data"]["subjects"] = select_subjects default_param["load_data"]["tasks"] = select_tasks # Load data using the selected subjects & tasks data = load.load_files(default_param["load_data"]) # get the pipeline steps feature_params = default_param["preprocess"] interp_param = feature_params["interpolate_data"] for file in data: eeg_obj = mne_bids.read_raw_bids(file) # generate epoched object to be interpolated epo, _ = pre.segment_data(eeg_obj, **feature_params["segment_data"]) # interpolate data interp_eeg, output_dict = pre.interpolate_data(epo, **interp_param) # assert that None does not exist in final reject assert None not in output_dict.values() # assert object returned is epoch object assert isinstance(interp_eeg, Epochs)
def test_bdf(_bids_validate): """Test write_raw_bids conversion for Biosemi data.""" output_path = _TempDir() data_path = op.join(base_path, 'edf', 'tests', 'data') raw_fname = op.join(data_path, 'test.bdf') raw = mne.io.read_raw_bdf(raw_fname) with pytest.warns(UserWarning, match='No line frequency found'): write_raw_bids(raw, bids_basename, output_path, overwrite=False) _bids_validate(output_path) # Test also the reading of channel types from channels.tsv # the first channel in the raw data is not MISC right now test_ch_idx = 0 assert coil_type(raw.info, test_ch_idx) != 'misc' # we will change the channel type to MISC and overwrite the channels file bids_fname = bids_basename + '_eeg.bdf' channels_fname = _find_matching_sidecar(bids_fname, output_path, 'channels.tsv') channels_dict = _from_tsv(channels_fname) channels_dict['type'][test_ch_idx] = 'MISC' _to_tsv(channels_dict, channels_fname) # Now read the raw data back from BIDS, with the tampered TSV, to show # that the channels.tsv truly influences how read_raw_bids sets ch_types # in the raw data object raw = read_raw_bids(bids_fname, output_path) assert coil_type(raw.info, test_ch_idx) == 'misc' # Test cropped assertion error raw = mne.io.read_raw_bdf(raw_fname) raw.crop(0, raw.times[-2]) with pytest.raises(AssertionError, match='cropped'): write_raw_bids(raw, bids_basename, output_path)
def _save_annotations(*, annotations, bids_path, verbose): # Attach the new Annotations to our raw data so we can easily convert them # to events, which will be stored in the *_events.tsv sidecar. extra_params = dict() if bids_path.extension == '.fif': extra_params['allow_maxshield'] = True raw = read_raw_bids(bids_path=bids_path, extra_params=extra_params, verbose='warning') raw.set_annotations(annotations) events, durs, descrs = _read_events(events_data=None, event_id=None, raw=raw, verbose=False) # Write sidecar – or remove it if no events are left. events_tsv_fname = (bids_path.copy().update(suffix='events', extension='.tsv').fpath) if len(events) > 0: _events_tsv(events=events, durations=durs, raw=raw, fname=events_tsv_fname, trial_type=descrs, overwrite=True, verbose=verbose) elif events_tsv_fname.exists(): logger.info(f'No events remaining after interactive inspection, ' f'removing {events_tsv_fname.name}') events_tsv_fname.unlink()
def test_inspect_annotations(tmp_path): """Test inspection of Annotations.""" import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') plt.close('all') bids_root = setup_bids_test_dir(tmp_path) bids_path = _bids_path.copy().update(root=bids_root) raw = read_raw_bids(bids_path=bids_path, verbose='error') orig_annotations = raw.annotations.copy() inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] _add_annotation(raw_fig) # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # Ensure changes were saved. raw = read_raw_bids(bids_path=bids_path, verbose='error') assert 'BAD_test' in raw.annotations.description annot_idx = raw.annotations.description == 'BAD_test' assert raw.annotations.duration[annot_idx].squeeze() == 4 # Remove the Annotation. inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] data_ax = raw_fig.mne.ax_main raw_fig.canvas.key_press_event('a') # Toggle Annotation mode _fake_click(raw_fig, data_ax, [1., 1.], xform='data', button=3, kind='press') # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # Ensure changes were saved. raw = read_raw_bids(bids_path=bids_path, verbose='error') assert 'BAD_test' not in raw.annotations.description assert raw.annotations == orig_annotations
def individual_analysis(bids_path, ID): raw_intensity = read_raw_bids(bids_path=bids_path, verbose=False) # Convert signal to haemoglobin and resample raw_od = optical_density(raw_intensity) raw_haemo = beer_lambert_law(raw_od) raw_haemo.resample(0.3) # Cut out just the short channels for creating a GLM repressor sht_chans = get_short_channels(raw_haemo) raw_haemo = get_long_channels(raw_haemo) # Create a design matrix design_matrix = make_first_level_design_matrix(raw_haemo, stim_dur=5.0) # Append short channels mean to design matrix design_matrix["ShortHbO"] = np.mean(sht_chans.copy().pick(picks="hbo").get_data(), axis=0) design_matrix["ShortHbR"] = np.mean(sht_chans.copy().pick(picks="hbr").get_data(), axis=0) # Run GLM glm_est = run_GLM(raw_haemo, design_matrix) # Define channels in each region of interest # List the channel pairs manually left = [[4, 3], [1, 3], [3, 3], [1, 2], [2, 3], [1, 1]] right = [[6, 7], [5, 7], [7, 7], [5, 6], [6, 7], [5, 5]] # Then generate the correct indices for each pair groups = dict( Left_Hemisphere=picks_pair_to_idx(raw_haemo, left, on_missing='ignore'), Right_Hemisphere=picks_pair_to_idx(raw_haemo, right, on_missing='ignore')) # Extract channel metrics cha = glm_to_tidy(raw_haemo, glm_est, design_matrix) cha["ID"] = ID # Add the participant ID to the dataframe # Compute region of interest results from channel data roi = pd.DataFrame() for idx, col in enumerate(design_matrix.columns): roi = roi.append(glm_region_of_interest(glm_est, groups, idx, col)) roi["ID"] = ID # Add the participant ID to the dataframe # Contrast left vs right tapping contrast_matrix = np.eye(design_matrix.shape[1]) basic_conts = dict([(column, contrast_matrix[i]) for i, column in enumerate(design_matrix.columns)]) contrast_LvR = basic_conts['Tapping/Left'] - basic_conts['Tapping/Right'] contrast = compute_contrast(glm_est, contrast_LvR) con = glm_to_tidy(raw_haemo, contrast, design_matrix) con["ID"] = ID # Add the participant ID to the dataframe # Convert to uM for nicer plotting below. cha["theta"] = [t * 1.e6 for t in cha["theta"]] roi["theta"] = [t * 1.e6 for t in roi["theta"]] con["effect"] = [t * 1.e6 for t in con["effect"]] return raw_haemo, roi, cha, con
def individual_analysis(bids_path): raw_intensity = read_raw_bids(bids_path=bids_path, verbose=False) raw_intensity.pick(picks=range(20)).crop(200).resample(0.3) # Reduce load raw_haemo = beer_lambert_law(optical_density(raw_intensity), ppf=0.1) design_matrix = make_first_level_design_matrix(raw_haemo) glm_est = run_glm(raw_haemo, design_matrix) return glm_est
def test_inspect_set_and_unset_bads(tmp_path): """Test marking channels as bad and later marking them as good again.""" from mne.utils._testing import _click_ch_name import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') plt.close('all') bids_root = setup_bids_test_dir(tmp_path) bids_path = _bids_path.copy().update(root=bids_root) raw = read_raw_bids(bids_path=bids_path, verbose='error') orig_bads = raw.info['bads'].copy() # Mark some channels as bad by clicking on their name. inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] _click_ch_name(raw_fig, ch_index=0, button=1) _click_ch_name(raw_fig, ch_index=1, button=1) _click_ch_name(raw_fig, ch_index=4, button=1) # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # Inspect the data again, click on two of the bad channels to mark them as # good. inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] _click_ch_name(raw_fig, ch_index=1, button=1) _click_ch_name(raw_fig, ch_index=4, button=1) # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # Check marking the channels as good has actually worked. expected_bads = orig_bads + ['MEG 0113'] raw = read_raw_bids(bids_path=bids_path, verbose='error') new_bads = raw.info['bads'] assert set(new_bads) == set(expected_bads)
def test_bids_setup(self, tmp_bids_root, edf_fpath): """ Integration test for setting up a bids directory from scratch. Should test: 1. Initial setup 2. loading runs 3. loading patients Parameters ---------- bids_root : Returns ------- """ # create the BIDS dirctory structure test_subjectid = "0002" modality = "eeg" test_sessionid = "seizure" test_runid = "01" task = "monitor" line_freq = 60 # create the BIDS directory structure if not os.path.exists(tmp_bids_root): print("Making bids root directory.") make_bids_folders( output_path=tmp_bids_root, session=test_sessionid, subject=test_subjectid, kind=modality, ) # add a bids run bids_basename = make_bids_basename( subject=test_subjectid, acquisition=modality, session=test_sessionid, run=test_runid, task=task, ) # call bidsbuilder pipeline tmp_bids_root = BidsConverter.convert_to_bids( edf_fpath=edf_fpath, bids_root=tmp_bids_root, bids_basename=bids_basename, line_freq=line_freq, overwrite=True, ) # load it in using mne_bids again bids_fname = bids_basename + f"_{modality}.fif" raw = mne_bids.read_raw_bids(bids_fname, tmp_bids_root)
def read_bids_data(bids_root, subject, datatype="meg", task="memento", suffix="meg"): """ Read in a BIDS directory. :param subject: str, subject identifier, takes the form '001' :param bids_root: str, path to the root of a BIDS directory to read from :param datatype: str, descriptor of the data type, e.g., 'meg' :param task: str, descriptor of the task name ('memento') :param suffix: str, BIDS suffix for the data, e.g., 'meg' """ bids_path = BIDSPath(root=bids_root, datatype=datatype, subject=subject, task=task, suffix=suffix) try: # Only now (Apr. 2021) MNE python gained the ability to read in split # annexed data. Until this is released and established, we're making # sure files are read fully, and if not, we attempt to unlock them first raw = read_raw_bids( bids_path=bids_path, extra_params=dict(on_split_missing="raise"), ) except ValueError: logging.warn( "Ooops! I can't load all splits of the data. This may be because " "you run a version of MNE-python that does not read in annexed " "data automatically. I will try to datalad-unlock them for you.") import datalad.api as dl dl.unlock(bids_path.directory) raw = read_raw_bids( bids_path=bids_path, extra_params=dict(on_split_missing="raise"), ) # return the raw data, and also the bids path as it has return raw, bids_path
def create_elec_labels_subject(bids_path, output_fpath): """Help create a mat file for fieldtrip toolbox with electrode names.""" # read in the actual file raw = read_raw_bids(bids_path) # get the channels ch_names = raw.ch_names # save this to a output file elec_dict = {"elec_name": np.array(ch_names).astype(np.object)} Path(output_fpath).parent.mkdir(exist_ok=True, parents=True) savemat(output_fpath, elec_dict)
def individual_analysis(bids_path): raw_intensity = read_raw_bids(bids_path=bids_path, verbose=False) # Delete annotation labeled 15, as these just signify the start and end of experiment. raw_intensity.annotations.delete( raw_intensity.annotations.description == '15.0') raw_intensity.pick(picks=range(20)).crop(200).resample(0.3) # Reduce load raw_haemo = beer_lambert_law(optical_density(raw_intensity), ppf=0.1) design_matrix = make_first_level_design_matrix(raw_haemo) glm_est = run_glm(raw_haemo, design_matrix) return glm_est
def test_inspect_annotations_remove_all(tmp_path): """Test behavior if all Annotations are removed by the user.""" import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') plt.close('all') bids_root = setup_bids_test_dir(tmp_path) bids_path = _bids_path.copy().update(root=bids_root) events_tsv_fpath = (bids_path.copy().update(suffix='events', extension='.tsv').fpath) # Remove all Annotations. raw = read_raw_bids(bids_path=bids_path, verbose='error') raw.set_annotations(None) raw.load_data() raw.save(raw.filenames[0], overwrite=True) # Delete events.tsv sidecar. (bids_path.copy().update(suffix='events', extension='.tsv').fpath.unlink()) # Add custom Annotation. inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] _add_annotation(raw_fig) # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # events.tsv sidecar should have been created. assert events_tsv_fpath.exists() # Remove the Annotation. inspect_dataset(bids_path, find_flat=False) raw_fig = mne_bids.inspect._global_vars['raw_fig'] data_ax = raw_fig.mne.ax_main raw_fig.canvas.key_press_event('a') # Toggle Annotation mode _fake_click(raw_fig, data_ax, [1., 1.], xform='data', button=3, kind='press') # Close window and save changes. raw_fig.canvas.key_press_event(raw_fig.mne.close_key) fig_dialog = mne_bids.inspect._global_vars['dialog_fig'] fig_dialog.canvas.key_press_event('return') # events.tsv sidecar should not exist anymore. assert not events_tsv_fpath.exists()
def test_return_values(default_param, select_subjects, select_tasks): default_param["load_data"]["subjects"] = select_subjects default_param["load_data"]["tasks"] = select_tasks # Load data using the selected subjects & tasks data = load.load_files(default_param["load_data"]) for file in data: eeg_obj = mne_bids.read_raw_bids(file) # reject epochs badchans_raw, output_dict = pre.identify_badchans_raw(eeg_obj) # assert that None does not exist in bad chans assert None not in output_dict.values()
def test_inspect_multiple_files(return_bids_test_dir): import matplotlib matplotlib.use('Agg') bids_path = _bids_path.copy().update(root=return_bids_test_dir) # Create a second subject raw = read_raw_bids(bids_path=bids_path, verbose='error') write_raw_bids(raw, bids_path.copy().update(subject='02')) del raw # Inspection should end with the second subject. inspect_dataset(bids_path.copy().update(subject=None)) raw_fig = mne_bids.inspect._global_vars['raw_fig'] assert raw_fig.mne.info['subject_info']['participant_id'] == 'sub-02' raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
def analysis(fname, ID): raw_intensity = read_raw_bids(bids_path=fname, verbose=False) # Delete annotation labeled 15, as these just signify the start and end of experiment. raw_intensity.annotations.delete( raw_intensity.annotations.description == '15.0') # sanitize event names raw_intensity.annotations.description[:] = [ d.replace('/', '_') for d in raw_intensity.annotations.description ] # Convert signal to haemoglobin and just keep hbo raw_od = optical_density(raw_intensity) raw_haemo = beer_lambert_law(raw_od, ppf=0.1) raw_haemo.resample(0.5, npad="auto") # Cut out just the short channels for creating a GLM regressor short_chans = get_short_channels(raw_haemo) raw_haemo = get_long_channels(raw_haemo) # Create a design matrix design_matrix = make_first_level_design_matrix(raw_haemo, hrf_model='fir', stim_dur=1.0, fir_delays=range(10), drift_model='cosine', high_pass=0.01, oversampling=1) # Add short channels as regressor in GLM for chan in range(len(short_chans.ch_names)): design_matrix[f"short_{chan}"] = short_chans.get_data(chan).T # Run GLM glm_est = run_glm(raw_haemo, design_matrix) # Create a single ROI that includes all channels for example rois = dict(AllChannels=range(len(raw_haemo.ch_names))) # Calculate ROI for all conditions conditions = design_matrix.columns # Compute output metrics by ROI df_ind = glm_est.to_dataframe_region_of_interest(rois, conditions) df_ind["ID"] = ID df_ind["theta"] = [t * 1.e6 for t in df_ind["theta"]] return df_ind, raw_haemo, design_matrix
def individual_analysis(bids_path): # Read data with annotations in BIDS format raw_intensity = read_raw_bids(bids_path=bids_path, verbose=False) raw_intensity = get_long_channels(raw_intensity, min_dist=0.01) # Convert signal to optical density and determine bad channels raw_od = optical_density(raw_intensity) sci = scalp_coupling_index(raw_od, h_freq=1.35, h_trans_bandwidth=0.1) raw_od.info["bads"] = list(compress(raw_od.ch_names, sci < 0.5)) raw_od.interpolate_bads() # Downsample and apply signal cleaning techniques raw_od.resample(0.8) raw_od = temporal_derivative_distribution_repair(raw_od) # Convert to haemoglobin and filter raw_haemo = beer_lambert_law(raw_od, ppf=0.1) raw_haemo = raw_haemo.filter(0.02, 0.3, h_trans_bandwidth=0.1, l_trans_bandwidth=0.01, verbose=False) # Apply further data cleaning techniques and extract epochs raw_haemo = enhance_negative_correlation(raw_haemo) # Extract events but ignore those with # the word Ends (i.e. drop ExperimentEnds events) events, event_dict = events_from_annotations(raw_haemo, verbose=False, regexp='^(?![Ends]).*$') epochs = Epochs(raw_haemo, events, event_id=event_dict, tmin=-5, tmax=20, reject=dict(hbo=200e-6), reject_by_annotation=True, proj=True, baseline=(None, 0), detrend=0, preload=True, verbose=False) return raw_haemo, epochs
def load_data(bids_basename): # read_raw_bids automatically # - populates bad channels using the BIDS channels.tsv # - sets channels types according to BIDS channels.tsv `type` column # - sets raw.annotations using the BIDS events.tsv params = get_entities_from_fname(bids_basename) subject = params['subject'] session = params['session'] extra_params = dict() if config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield raw = read_raw_bids(bids_basename=bids_basename, bids_root=config.bids_root, extra_params=extra_params, kind=config.get_kind()) if config.daysback is not None: raw.anonymize(daysback=config.daysback) if subject != 'emptyroom': # Crop the data. if config.crop is not None: raw.crop(*config.crop) # Rename events. if config.rename_events: rename_events(raw=raw, subject=subject, session=session) raw.load_data() if hasattr(raw, 'fix_mag_coil_types'): raw.fix_mag_coil_types() montage_name = config.eeg_template_montage if config.get_kind() == 'eeg' and montage_name: msg = (f'Setting EEG channel locatiions to template montage: ' f'{montage_name}.') logger.info(gen_log_message(message=msg, step=1, subject=subject, session=session)) montage = mne.channels.make_standard_montage(montage_name) raw.set_montage(montage, on_missing='warn') return raw
def test_bti(_bids_validate): """Test functionality of the write_raw_bids conversion for BTi data.""" output_path = _TempDir() data_path = op.join(base_path, 'bti', 'tests', 'data') raw_fname = op.join(data_path, 'test_pdf_linux') config_fname = op.join(data_path, 'test_config_linux') headshape_fname = op.join(data_path, 'test_hs_linux') raw = mne.io.read_raw_bti(raw_fname, config_fname=config_fname, head_shape_fname=headshape_fname) write_raw_bids(raw, bids_basename, output_path, verbose=True) assert op.exists(op.join(output_path, 'participants.tsv')) _bids_validate(output_path) raw = read_raw_bids(bids_basename + '_meg', output_path)