def test_double_export_edf(tmp_path): """Test exporting an EDF file multiple times.""" rng = np.random.RandomState(123456) format = 'edf' ch_types = [ 'eeg', 'eeg', 'stim', 'ecog', 'ecog', 'seeg', 'eog', 'ecg', 'emg', 'dbs', 'bio' ] ch_names = np.arange(len(ch_types)).astype(str).tolist() info = create_info(ch_names, sfreq=1000, ch_types=ch_types) data = rng.random(size=(len(ch_names), 1000)) * 1.e-5 # include subject info and measurement date subject_info = dict(first_name='mne', last_name='python', birthday=(1992, 1, 20), sex=1, hand=3) info['subject_info'] = subject_info raw = RawArray(data, info) # export once temp_fname = op.join(str(tmp_path), f'test.{format}') raw.export(temp_fname, add_ch_type=True) raw_read = read_raw_edf(temp_fname, preload=True) # export again raw_read.load_data() raw_read.export(temp_fname, add_ch_type=True) raw_read = read_raw_edf(temp_fname, preload=True) # stim channel should be dropped raw.drop_channels('2') assert raw.ch_names == raw_read.ch_names # only compare the original length, since extra zeros are appended orig_raw_len = len(raw) assert_array_almost_equal(raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=4) assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) # check channel types except for 'bio', which loses its type orig_ch_types = raw.get_channel_types() read_ch_types = raw_read.get_channel_types() assert_array_equal(orig_ch_types, read_ch_types)
def test_integer_sfreq_edf(tmp_path): """Test saving a Raw array with integer sfreq to EDF.""" np.random.RandomState(12345) format = 'edf' info = create_info(['1', '2', '3'], sfreq=1000, ch_types=['eeg', 'eeg', 'stim']) data = np.random.random(size=(3, 1000)) * 1e-6 # include subject info and measurement date subject_info = dict(first_name='mne', last_name='python', birthday=(1992, 1, 20), sex=1, hand=3) info['subject_info'] = subject_info raw = RawArray(data, info) raw.set_meas_date(datetime.now(tz=timezone.utc)) temp_fname = op.join(str(tmp_path), f'test.{format}') raw.export(temp_fname) raw_read = read_raw_edf(temp_fname, preload=True) # stim channel should be dropped raw.drop_channels('3') assert raw.ch_names == raw_read.ch_names # only compare the original length, since extra zeros are appended orig_raw_len = len(raw) assert_array_almost_equal( raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=4) assert_allclose( raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) # export now by hard-coding physical range raw.export(temp_fname, physical_range=(-3200, 3200)) # include bad birthday that is non-EDF compliant bad_info = info.copy() bad_info['subject_info']['birthday'] = (1700, 1, 20) raw = RawArray(data, bad_info) with pytest.raises(RuntimeError, match='Setting patient birth date'): raw.export(temp_fname) # include bad measurement date that is non-EDF compliant raw = RawArray(data, info) meas_date = datetime(year=1984, month=1, day=1, tzinfo=timezone.utc) raw.set_meas_date(meas_date) with pytest.raises(RuntimeError, match='Setting start date time'): raw.export(temp_fname)
def test_rawarray_edf(tmp_path): """Test saving a Raw array with integer sfreq to EDF.""" rng = np.random.RandomState(12345) format = 'edf' ch_types = [ 'eeg', 'eeg', 'stim', 'ecog', 'seeg', 'eog', 'ecg', 'emg', 'dbs', 'bio' ] ch_names = np.arange(len(ch_types)).astype(str).tolist() info = create_info(ch_names, sfreq=1000, ch_types=ch_types) data = rng.random(size=(len(ch_names), 1000)) * 1e-5 # include subject info and measurement date subject_info = dict(first_name='mne', last_name='python', birthday=(1992, 1, 20), sex=1, hand=3) info['subject_info'] = subject_info raw = RawArray(data, info) time_now = datetime.now() meas_date = datetime(year=time_now.year, month=time_now.month, day=time_now.day, hour=time_now.hour, minute=time_now.minute, second=time_now.second, tzinfo=timezone.utc) raw.set_meas_date(meas_date) temp_fname = op.join(str(tmp_path), f'test.{format}') raw.export(temp_fname, add_ch_type=True) raw_read = read_raw_edf(temp_fname, preload=True) # stim channel should be dropped raw.drop_channels('2') assert raw.ch_names == raw_read.ch_names # only compare the original length, since extra zeros are appended orig_raw_len = len(raw) assert_array_almost_equal(raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=4) assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) # check channel types except for 'bio', which loses its type orig_ch_types = raw.get_channel_types() read_ch_types = raw_read.get_channel_types() assert_array_equal(orig_ch_types, read_ch_types) assert raw.info['meas_date'] == raw_read.info['meas_date'] # channel name can't be longer than 16 characters with the type added raw_bad = raw.copy() raw_bad.rename_channels({'1': 'abcdefghijklmnopqrstuvwxyz'}) with pytest.raises(RuntimeError, match='Signal label'), \ pytest.warns(RuntimeWarning, match='Data has a non-integer'): raw_bad.export(temp_fname) # include bad birthday that is non-EDF compliant bad_info = info.copy() bad_info['subject_info']['birthday'] = (1700, 1, 20) raw = RawArray(data, bad_info) with pytest.raises(RuntimeError, match='Setting patient birth date'): raw.export(temp_fname) # include bad measurement date that is non-EDF compliant raw = RawArray(data, info) meas_date = datetime(year=1984, month=1, day=1, tzinfo=timezone.utc) raw.set_meas_date(meas_date) with pytest.raises(RuntimeError, match='Setting start date time'): raw.export(temp_fname) # test that warning is raised if there are non-voltage based channels raw = RawArray(data, info) with pytest.warns(RuntimeWarning, match='The unit'): raw.set_channel_types({'9': 'hbr'}) with pytest.warns(RuntimeWarning, match='Non-voltage channels'): raw.export(temp_fname) # data should match up to the non-accepted channel raw_read = read_raw_edf(temp_fname, preload=True) orig_raw_len = len(raw) assert_array_almost_equal(raw.get_data()[:-1, :], raw_read.get_data()[:, :orig_raw_len], decimal=4) assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) # the data should still match though raw_read = read_raw_edf(temp_fname, preload=True) raw.drop_channels('2') assert raw.ch_names == raw_read.ch_names orig_raw_len = len(raw) assert_array_almost_equal(raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=4) assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5)
def bv2fif(dataf, corf, ch_order=None, eogs=('VEOG', 'HEOG'), ecg='ECG', emg='EMG', preload='default', ref_ch='Fp1', dbs=False, new_sfreq=1000.0): montage = read_dig_montage(bvct=corf) if preload == 'default': preload = os.path.dirname(dataf) + '/workfile' raw = read_raw_brainvision(dataf, preload=preload) if dbs: event_ch = get_events(raw) # save downsampled raw for multitaper spectrogram raw_data = np.zeros( (raw._data.shape[0], int(raw._data.shape[1] / raw.info['sfreq'] * new_sfreq))) raw_info = raw.info.copy() raw_info['sfreq'] = new_sfreq for i in tqdm(range(len(raw._data))): ch = raw._data[i, ::int(raw.info['sfreq'] / new_sfreq)] raw_data[i] = ch del ch raw_resampled = RawArray(raw_data, raw_info) raw_resampled.annotations = raw.annotations if dbs: old_event_ch = [ch for ch in raw.info['ch_names'] if 'STI' in ch] if old_event_ch: raw_resampled.drop_channels([old_event_ch[0]]) event_ch._data = event_ch._data[:, ::int(raw.info['sfreq'] / new_sfreq)] event_ch.info['sfreq'] = new_sfreq event_ch.__len__ = len(event_ch._data[0]) event_ch.info['lowpass'] = raw_resampled.info['lowpass'] raw_resampled.add_channels([event_ch]) prepInst(raw_resampled, dataf, 'raw', montage, ref_ch, eogs, ecg, emg) events, event_ids = events_from_annotations(raw) if len(np.unique(events[:, 2])) > 1: events = events[np.where(events[:, 2] == events[1, 2])[0]] #skip new segment epochs = Epochs(raw, events, tmin=-2, tmax=2, proj=False, preload=op.dirname(dataf) + '/workfile-epo', baseline=(-0.5, -0.1), verbose=False, detrend=1) events = events[ epochs. selection] #in case any epochs don't have data and get thrown out (poorly placed at beginning or end) epo_data = np.zeros( (epochs._data.shape[0], epochs._data.shape[1], int(np.ceil(epochs._data.shape[2] / epochs.info['sfreq'] * new_sfreq)))) for i in tqdm(range(epochs._data.shape[0])): for j in range(epochs._data.shape[1]): epo_curr = epochs._data[i, j, ::int(epochs.info['sfreq'] / new_sfreq)] epo_data[i, j] = epo_curr del epo_curr events[:, 0] = np.array(events[:, 0] * new_sfreq / raw.info['sfreq'], dtype=int) epo_resampled = EpochsArray(epo_data, epochs.info.copy(), events, tmin=-2) epo_resampled.info['sfreq'] = new_sfreq epo_resampled.events[:, 2] = np.arange(len(events)) epo_resampled.event_id = {str(i): i for i in range(len(events))} prepInst(epo_resampled, dataf, 'epo', montage, ref_ch, eogs, ecg, emg)
def test_plot_sensors(raw): """Test plotting of sensor array.""" plt.close('all') fig = raw.plot_sensors('3d') _fake_click(fig, fig.gca(), (-0.08, 0.67)) raw.plot_sensors('topomap', ch_type='mag', show_names=['MEG 0111', 'MEG 0131']) plt.close('all') ax = plt.subplot(111) raw.plot_sensors(ch_groups='position', axes=ax) raw.plot_sensors(ch_groups='selection', to_sphere=False) raw.plot_sensors(ch_groups=[[0, 1, 2], [3, 4]]) pytest.raises(ValueError, raw.plot_sensors, ch_groups='asd') pytest.raises(TypeError, plot_sensors, raw) # needs to be info pytest.raises(ValueError, plot_sensors, raw.info, kind='sasaasd') plt.close('all') fig, sels = raw.plot_sensors('select', show_names=True) ax = fig.axes[0] # Click with no sensors _fake_click(fig, ax, (0., 0.), xform='data') _fake_click(fig, ax, (0, 0.), xform='data', kind='release') assert fig.lasso.selection == [] # Lasso with 1 sensor (upper left) _fake_click(fig, ax, (0, 1), xform='ax') fig.canvas.draw() assert fig.lasso.selection == [] _fake_click(fig, ax, (0.65, 1), xform='ax', kind='motion') _fake_click(fig, ax, (0.65, 0.7), xform='ax', kind='motion') fig.canvas.key_press_event('control') _fake_click(fig, ax, (0, 0.7), xform='ax', kind='release') assert fig.lasso.selection == ['MEG 0121'] # check that point appearance changes fc = fig.lasso.collection.get_facecolors() ec = fig.lasso.collection.get_edgecolors() assert (fc[:, -1] == [0.5, 1., 0.5]).all() assert (ec[:, -1] == [0.25, 1., 0.25]).all() _fake_click(fig, ax, (0.7, 1), xform='ax', kind='motion') xy = ax.collections[0].get_offsets() _fake_click(fig, ax, xy[2], xform='data') # single selection assert fig.lasso.selection == ['MEG 0121', 'MEG 0131'] _fake_click(fig, ax, xy[2], xform='data') # deselect assert fig.lasso.selection == ['MEG 0121'] plt.close('all') raw.info['dev_head_t'] = None # like empty room with pytest.warns(RuntimeWarning, match='identity'): raw.plot_sensors() # Test plotting with sphere='eeglab' info = create_info( ch_names=['Fpz', 'Oz', 'T7', 'T8'], sfreq=100, ch_types='eeg' ) data = 1e-6 * np.random.rand(4, 100) raw_eeg = RawArray(data=data, info=info) raw_eeg.set_montage('biosemi64') raw_eeg.plot_sensors(sphere='eeglab') # Should work with "FPz" as well raw_eeg.rename_channels({'Fpz': 'FPz'}) raw_eeg.plot_sensors(sphere='eeglab') # Should still work without Fpz/FPz, as long as we still have Oz raw_eeg.drop_channels('FPz') raw_eeg.plot_sensors(sphere='eeglab') # Should raise if Oz is missing too, as we cannot reconstruct Fpz anymore raw_eeg.drop_channels('Oz') with pytest.raises(ValueError, match='could not find: Fpz'): raw_eeg.plot_sensors(sphere='eeglab') # Should raise if we don't have a montage chs = deepcopy(raw_eeg.info['chs']) raw_eeg.set_montage(None) with raw_eeg.info._unlock(): raw_eeg.info['chs'] = chs with pytest.raises(ValueError, match='No montage was set'): raw_eeg.plot_sensors(sphere='eeglab')