def test_same_behaviour_in_init_and_set_montage(): """Test that __init__ and set_montage lead to equal results. This is a regression test to help refactor Digitization. """ montage = 'biosemi256' with pytest.warns(RuntimeWarning) as init_warns: raw_montage = read_raw_edf(edf_path, montage=montage) raw_none = read_raw_edf(edf_path, montage=None) assert raw_none.info['dig'] is None with pytest.warns((RuntimeWarning)) as set_montage_warns: raw_none.set_montage(montage) # Assert equal objects assert object_diff(raw_none.info['chs'], raw_montage.info['chs']) == '' assert object_diff(raw_none.info['dig'], raw_montage.info['dig']) == '' # Assert equal warnings assert len(init_warns) == len(set_montage_warns) for ii in range(len(init_warns)): msg_a = init_warns[ii].message.args[0] msg_b = set_montage_warns[ii].message.args[0] assert msg_a == msg_b
def test_object_diff_with_nan(): """Test object diff can handle NaNs.""" d0 = np.array([1, np.nan, 0]) d1 = np.array([1, np.nan, 0]) d2 = np.array([np.nan, 1, 0]) assert object_diff(d0, d1) == '' assert object_diff(d0, d2) != ''
def test_object_diff_with_nan(): """Test object diff can handle NaNs.""" d0 = np.array([1, np.nan, 0]) d1 = np.array([1, np.nan, 0]) d2 = np.array([np.nan, 1, 0]) assert object_diff(d0, d1) == '' assert object_diff(d0, d2) != '' assert object_diff(np.nan, np.nan) == '' assert object_diff(np.nan, 3.5) == ' value mismatch (nan, 3.5)\n'
def test_parse_impedance(): """Test case for parsing the impedances from header.""" expected_imp_meas_time = datetime.datetime(2013, 11, 13, 16, 12, 27, tzinfo=datetime.timezone.utc) expected_imp_unit = 'kOhm' expected_electrodes = [ 'FP1', 'FP2', 'F3', 'F4', 'C3', 'C4', 'P3', 'P4', 'O1', 'O2', 'F7', 'F8', 'P7', 'P8', 'Fz', 'FCz', 'Cz', 'CPz', 'Pz', 'POz', 'FC1', 'FC2', 'CP1', 'CP2', 'FC5', 'FC6', 'CP5', 'CP6', 'HL', 'HR', 'Vb', 'ReRef', 'Ref', 'Gnd' ] n_electrodes = len(expected_electrodes) expected_imps = [np.nan] * (n_electrodes - 2) + [0., 4.] expected_imp_lower_bound = 0. expected_imp_upper_bound = [100.] * (n_electrodes - 2) + [10., 10.] expected_impedances = {elec: { 'imp': expected_imps[i], 'imp_unit': expected_imp_unit, 'imp_meas_time': expected_imp_meas_time, 'imp_lower_bound': expected_imp_lower_bound, 'imp_upper_bound': expected_imp_upper_bound[i], 'imp_range_unit': expected_imp_unit, } for i, elec in enumerate(expected_electrodes)} raw = read_raw_brainvision(vhdr_path, eog=eog) assert object_diff(expected_impedances, raw.impedances) == '' # Test "Impedances Imported from actiCAP Control Software" expected_imp_meas_time = expected_imp_meas_time.replace(hour=10, minute=17, second=2) tmpidx = expected_electrodes.index('CP6') expected_electrodes = expected_electrodes[:tmpidx] + [ 'CP 6', 'ECG+', 'ECG-', 'HEOG+', 'HEOG-', 'VEOG+', 'VEOG-', 'ReRef', 'Ref', 'Gnd' ] n_electrodes = len(expected_electrodes) expected_imps = [np.nan] * (n_electrodes - 9) + [ 35., 46., 6., 8., 3., 4., 0., 8., 2.5 ] expected_impedances = {elec: { 'imp': expected_imps[i], 'imp_unit': expected_imp_unit, 'imp_meas_time': expected_imp_meas_time, } for i, elec in enumerate(expected_electrodes)} with pytest.warns(RuntimeWarning, match='different .*pass filters'): raw = read_raw_brainvision(vhdr_mixed_lowpass_path, eog=['HEOG', 'VEOG'], misc=['ECG']) assert object_diff(expected_impedances, raw.impedances) == ''
def test_montage(): """Test montage.""" fname = op.join(base_dir, 'test_raw.set') raw_none = read_raw_eeglab(input_fname=fname, montage=None, preload=False) montage = _fake_montage(raw_none.info['ch_names']) raw_montage = read_raw_eeglab(input_fname=fname, montage=montage, preload=False) raw_none.set_montage(montage) # Check they are the same assert_array_equal(raw_none.get_data(), raw_montage.get_data()) assert object_diff(raw_none.info['dig'], raw_montage.info['dig']) == '' assert object_diff(raw_none.info['chs'], raw_montage.info['chs']) == ''
def check_info_fields(expected, actual, has_raw_info, ignore_long=True): """ Check if info fields are equal. Some fields are ignored. """ expected = expected.info.copy() actual = actual.info.copy() if not has_raw_info: _remove_ignored_info_fields(expected) _remove_ignored_info_fields(actual) _remove_long_info_fields(expected) _remove_long_info_fields(actual) # we annoyingly have two ways of representing this, so just always use # an empty list here for obj in (expected, actual): if obj['dig'] is None: with obj._unlock(): obj['dig'] = [] d = object_diff(actual, expected, allclose=True) assert d == '', d
def test_io_surface(tmp_path): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = str(tmp_path) fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'sample', 'bem', 'inner_skull.surf') for fname in (fname_quad, fname_tri): with _record_warnings(): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info, overwrite=True) with _record_warnings(): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '') if fname != fname_tri: # don't bother testing wavefront for the bigger continue # Test writing/reading a Wavefront .obj file write_surface(op.join(tempdir, 'tmp.obj'), pts, tri, volume_info=None, overwrite=True) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp.obj'), read_metadata=False) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) # reading patches (just a smoke test, let the flatmap viz tests be more # complete) fname_patch = op.join( data_path, 'subjects', 'fsaverage', 'surf', 'rh.cortex.patch.flat') _read_patch(fname_patch)
def test_montage_when_reading_and_setting(read_raw, fname): """Test montage. This is a regression test to help refactor Digitization. """ raw_none = read_raw(fname, montage=None, preload=False) # raw_none_copy = deepcopy(raw_none) montage = _fake_montage(raw_none.info['ch_names']) raw_montage = read_raw(fname, montage=montage, preload=False) raw_none.set_montage(montage) # Check that reading with montage or setting the montage is the same assert_array_equal(raw_none.get_data(), raw_montage.get_data()) assert object_diff(raw_none.info['dig'], raw_montage.info['dig']) == '' assert object_diff(raw_none.info['chs'], raw_montage.info['chs']) == ''
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation""" raw = Raw(raw_fname, allow_maxshield='yes').crop(0., 1., False) raw.info['bads'] = bads sss_ctc = Raw(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert_equal(object_diff(py_ctc, mf_ctc), '') raw_ctf = Raw(fname_ctf_raw) assert_raises(ValueError, maxwell_filter, raw_ctf) # cannot fit headshape raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04)) _assert_n_free(raw_sss, 68) raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 70) raw_missing = raw.crop(0, 0.1, copy=True).load_data().pick_channels( [raw.ch_names[pi] for pi in pick_types(raw.info, meg=True, exclude=())[3:]]) with warnings.catch_warnings(record=True) as w: maxwell_filter(raw_missing, cross_talk=ctc_fname) assert_equal(len(w), 1) assert_true('Not all cross-talk channels in raw' in str(w[0].message)) # MEG channels not in cross-talk assert_raises(RuntimeError, maxwell_filter, raw_ctf, origin=(0., 0., 0.04), cross_talk=ctc_fname)
def test_snirf_write(fname, tmpdir): """Test reading NIRX files.""" raw_orig = read_raw_nirx(fname, preload=True) write_raw_snirf(raw_orig, tmpdir.join('test_raw.snirf')) raw = read_raw_snirf(tmpdir.join('test_raw.snirf')) # Check annotations are the same assert_allclose(raw.annotations.onset, raw_orig.annotations.onset) assert_allclose([float(d) for d in raw.annotations.description], [float(d) for d in raw_orig.annotations.description]) assert_allclose(raw.annotations.duration, raw_orig.annotations.duration) # Check data is the same assert_allclose(raw.get_data(), raw_orig.get_data()) assert abs(raw_orig.info["meas_date"] - raw.info["meas_date"]) < \ datetime.timedelta(seconds=1) # Check info object is the same obj_diff = object_diff(raw.info, raw_orig.info) diffs = '' for line in obj_diff.splitlines(): if ('logno' not in line) and ('scanno' not in line) and\ ('datetime mismatch' not in line): # logno and scanno are not used in processing diffs += f'\n{line}' assert diffs == ''
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation.""" raw = read_crop(raw_fname, (0., 1.)) raw.info['bads'] = bads sss_ctc = read_crop(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert_equal(object_diff(py_ctc, mf_ctc), '') raw_ctf = read_crop(fname_ctf_raw).apply_gradient_compensation(0) assert_raises(ValueError, maxwell_filter, raw_ctf) # cannot fit headshape raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04)) _assert_n_free(raw_sss, 68) raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 70) raw_missing = raw.copy().crop(0, 0.1).load_data().pick_channels( [raw.ch_names[pi] for pi in pick_types(raw.info, meg=True, exclude=())[3:]]) with warnings.catch_warnings(record=True) as w: maxwell_filter(raw_missing, cross_talk=ctc_fname) assert_equal(len(w), 1) assert_true('Not all cross-talk channels in raw' in str(w[0].message)) # MEG channels not in cross-talk assert_raises(RuntimeError, maxwell_filter, raw_ctf, origin=(0., 0., 0.04), cross_talk=ctc_fname)
def test_export_evokeds_to_mff(tmpdir, fmt, do_history): """Test exporting evoked dataset to MFF.""" evoked = read_evokeds_mff(egi_evoked_fname) export_fname = op.join(str(tmpdir), 'evoked.mff') history = [{ 'name': 'Test Segmentation', 'method': 'Segmentation', 'settings': ['Setting 1', 'Setting 2'], 'results': ['Result 1', 'Result 2'] }, { 'name': 'Test Averaging', 'method': 'Averaging', 'settings': ['Setting 1', 'Setting 2'], 'results': ['Result 1', 'Result 2'] }] if do_history: export_evokeds_mff(export_fname, evoked, history=history) else: export_evokeds(export_fname, evoked) # Drop non-EEG channels evoked = [ave.drop_channels(['ECG', 'EMG']) for ave in evoked] evoked_exported = read_evokeds_mff(export_fname) assert len(evoked) == len(evoked_exported) for ave, ave_exported in zip(evoked, evoked_exported): # Compare infos assert object_diff(ave_exported.info, ave.info) == '' # Compare data assert_allclose(ave_exported.data, ave.data) # Compare properties assert ave_exported.nave == ave.nave assert ave_exported.kind == ave.kind assert ave_exported.comment == ave.comment assert_allclose(ave_exported.times, ave.times)
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'sample', 'bem', 'inner_skull.surf') for fname in (fname_quad, fname_tri): with pytest.warns(None): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info, overwrite=True) with pytest.warns(None): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '') if fname != fname_tri: # don't bother testing wavefront for the bigger continue # Test writing/reading a Wavefront .obj file write_surface(op.join(tempdir, 'tmp.obj'), pts, tri, volume_info=None, overwrite=True) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp.obj'), read_metadata=False) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri)
def test_hash(): """Test dictionary hashing and comparison functions""" # does hashing all of these types work: # {dict, list, tuple, ndarray, str, float, int, None} d0 = dict(a=dict(a=0.1, b='fo', c=1), b=[1, 'b'], c=(), d=np.ones(3)) d0[1] = None d0[2.] = b'123' d1 = deepcopy(d0) print(object_diff(d0, d1)) assert_equal(object_hash(d0), object_hash(d1)) # change values slightly d1['data'] = np.ones(3, int) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) print(object_diff(d0, d1)) assert_equal(object_hash(d0), object_hash(d1)) d1['a']['a'] = 0.11 object_diff(d0, d1) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) print(object_diff(d0, d1)) assert_equal(object_hash(d0), object_hash(d1)) d1[1] = 2 object_diff(d0, d1) assert_not_equal(object_hash(d0), object_hash(d1)) # generators (and other types) not supported d1[1] = (x for x in d0) assert_raises(RuntimeError, object_hash, d1)
def test_montage(): """Test montage.""" raw_none = read_raw_nicolet(input_fname=fname, ch_type='eeg', montage=None, preload=False) montage = _fake_montage(raw_none.info['ch_names']) raw_montage = read_raw_nicolet(input_fname=fname, ch_type='eeg', montage=montage, preload=False) raw_none.set_montage(montage) # Check they are the same assert_array_equal(raw_none.get_data(), raw_montage.get_data()) assert object_diff(raw_none.info['dig'], raw_montage.info['dig']) == '' assert object_diff(raw_none.info['chs'], raw_montage.info['chs']) == ''
def test_montage(): """Test montage.""" base_dir = op.join(testing.data_path(download=False), 'EEGLAB') fname = op.join(base_dir, 'test_raw.set') # montage = op.join(base_dir, 'test_chans.locs') raw_none = read_raw_eeglab(input_fname=fname, montage=None, preload=False) montage = _fake_montage(raw_none.info['ch_names']) raw_montage = read_raw_eeglab(input_fname=fname, montage=montage, preload=False) raw_none.set_montage(montage) assert object_diff(raw_none.info['dig'], raw_montage.info['dig']) == '' # assert object_diff(raw_none.info['chs'], raw_montage.info['chs']) == '' diff = object_diff(raw_none.info['chs'], raw_montage.info['chs']).splitlines() for dd in diff: assert 'coord_frame' in dd
def test_export_evokeds_to_mff(tmp_path, fmt, do_history): """Test exporting evoked dataset to MFF.""" evoked = read_evokeds_mff(egi_evoked_fname) export_fname = op.join(str(tmp_path), 'evoked.mff') history = [{ 'name': 'Test Segmentation', 'method': 'Segmentation', 'settings': ['Setting 1', 'Setting 2'], 'results': ['Result 1', 'Result 2'] }, { 'name': 'Test Averaging', 'method': 'Averaging', 'settings': ['Setting 1', 'Setting 2'], 'results': ['Result 1', 'Result 2'] }] if do_history: export_evokeds_mff(export_fname, evoked, history=history) else: export_evokeds(export_fname, evoked, fmt=fmt) # Drop non-EEG channels evoked = [ave.drop_channels(['ECG', 'EMG']) for ave in evoked] evoked_exported = read_evokeds_mff(export_fname) assert len(evoked) == len(evoked_exported) for ave, ave_exported in zip(evoked, evoked_exported): # Compare infos assert object_diff(ave_exported.info, ave.info) == '' # Compare data assert_allclose(ave_exported.data, ave.data) # Compare properties assert ave_exported.nave == ave.nave assert ave_exported.kind == ave.kind assert ave_exported.comment == ave.comment assert_allclose(ave_exported.times, ave.times) # test overwrite with pytest.raises(FileExistsError, match='Destination file exists'): if do_history: export_evokeds_mff(export_fname, evoked, history=history, overwrite=False) else: export_evokeds(export_fname, evoked, overwrite=False) if do_history: export_evokeds_mff(export_fname, evoked, history=history, overwrite=True) else: export_evokeds(export_fname, evoked, overwrite=True) # test export from evoked directly evoked[0].export(export_fname, overwrite=True)
def test_fif_dig_montage(): """Test FIF dig montage support.""" with pytest.deprecated_call(): dig_montage = read_dig_montage(fif=fif_dig_montage_fname) # test round-trip IO temp_dir = _TempDir() fname_temp = op.join(temp_dir, 'test.fif') _check_roundtrip(dig_montage, fname_temp) # Make a BrainVision file like the one the user would have had raw_bv = read_raw_brainvision(bv_fname, preload=True) raw_bv_2 = raw_bv.copy() mapping = dict() for ii, ch_name in enumerate(raw_bv.ch_names): mapping[ch_name] = 'EEG%03d' % (ii + 1, ) raw_bv.rename_channels(mapping) for ii, ch_name in enumerate(raw_bv_2.ch_names): mapping[ch_name] = 'EEG%03d' % (ii + 33, ) raw_bv_2.rename_channels(mapping) raw_bv.add_channels([raw_bv_2]) for ii in range(2): # Set the montage raw_bv.set_montage(dig_montage) # Check the result evoked = read_evokeds(evoked_fname)[0] assert_equal(len(raw_bv.ch_names), len(evoked.ch_names) - 1) for ch_py, ch_c in zip(raw_bv.info['chs'], evoked.info['chs'][:-1]): assert_equal(ch_py['ch_name'], ch_c['ch_name'].replace('EEG ', 'EEG')) # C actually says it's unknown, but it's not (?): # assert_equal(ch_py['coord_frame'], ch_c['coord_frame']) assert_equal(ch_py['coord_frame'], FIFF.FIFFV_COORD_HEAD) c_loc = ch_c['loc'].copy() c_loc[c_loc == 0] = np.nan assert_allclose(ch_py['loc'], c_loc, atol=1e-7) assert_dig_allclose(raw_bv.info, evoked.info) # Roundtrip of non-FIF start names = ['nasion', 'lpa', 'rpa', '1', '2', '3', '4', '5'] montage = read_dig_montage(hsp, hpi, elp, names, transform=False) pytest.raises(RuntimeError, montage.save, fname_temp) # must be head coord montage = read_dig_montage(hsp, hpi, elp, names) _check_roundtrip(montage, fname_temp) # Test old way matches new way with pytest.deprecated_call(): dig_montage = read_dig_montage(fif=fif_dig_montage_fname) dig_montage_fif = read_dig_fif(fif_dig_montage_fname) assert dig_montage.dig == dig_montage_fif.dig assert object_diff(dig_montage.ch_names, dig_montage_fif.ch_names) == ''
def test_fine_cal_io(tmpdir, fname): """Test round trip reading/writing of fine calibration .dat file.""" temp_fname = op.join(str(tmpdir), 'fine_cal_temp.dat') # Load fine calibration file fine_cal_dict = read_fine_calibration(fname) # Save temp version of fine calibration file write_fine_calibration(temp_fname, fine_cal_dict) fine_cal_dict_reload = read_fine_calibration(temp_fname) # Load temp version of fine calibration file and compare hashes assert object_diff(fine_cal_dict, fine_cal_dict_reload) == ''
def test_io_egi_evokeds_mff(idx, cond, tmax, signals, bads): """Test reading evoked MFF file.""" # Test reading all conditions from evokeds evokeds = read_evokeds_mff(egi_mff_evoked_fname) assert len(evokeds) == 2 # Test reading list of conditions from evokeds evokeds = read_evokeds_mff(egi_mff_evoked_fname, condition=[0, 1]) assert len(evokeds) == 2 # Test invalid condition with pytest.raises(ValueError) as exc_info: read_evokeds_mff(egi_mff_evoked_fname, condition='Invalid Condition') message = "Invalid value for the 'condition' parameter provided as " \ "category name. Allowed values are 'Category 1' and " \ "'Category 2', but got 'Invalid Condition' instead." assert str(exc_info.value) == message with pytest.raises(ValueError) as exc_info: read_evokeds_mff(egi_mff_evoked_fname, condition=2) message = '"condition" parameter (2), provided as epoch index, ' \ 'is out of range for available epochs (2).' assert str(exc_info.value) == message with pytest.raises(TypeError) as exc_info: read_evokeds_mff(egi_mff_evoked_fname, condition=1.2) message = '"condition" parameter must be either int or str.' assert str(exc_info.value) == message # Test reading evoked data from single condition evoked_cond = read_evokeds_mff(egi_mff_evoked_fname, condition=cond) evoked_idx = read_evokeds_mff(egi_mff_evoked_fname, condition=idx) for evoked in [evoked_cond, evoked_idx]: assert evoked.comment == cond assert evoked.nave == 3 assert evoked.tmin == 0.0 assert evoked.tmax == tmax # Check signal data data = np.loadtxt(signals, ndmin=2).T * 1e-6 # convert to volts assert_allclose(evoked_cond.data, data, atol=1e-12) assert_allclose(evoked_idx.data, data, atol=1e-12) # Check info assert object_diff(evoked_cond.info, evoked_idx.info) == '' assert evoked_cond.info['description'] == cond assert evoked_cond.info['bads'] == bads assert len(evoked_cond.info['ch_names']) == 259 assert 'ECG' in evoked_cond.info['ch_names'] assert 'EMG' in evoked_cond.info['ch_names'] assert 'ecg' in evoked_cond assert 'emg' in evoked_cond pick_eeg = pick_types(evoked_cond.info, eeg=True, exclude=[]) assert len(pick_eeg) == 257 assert evoked_cond.info['nchan'] == 259 assert evoked_cond.info['sfreq'] == 250.0 assert not evoked_cond.info['custom_ref_applied'] assert len(evoked_cond.info['dig']) == 261 assert evoked_cond.info['device_info']['type'] == 'HydroCel GSN 256 1.0'
def test_hdf5(): """Test HDF5 IO """ test_file = op.join(tempdir, 'test.hdf5') x = dict(a=dict(b=np.zeros(3)), c=np.zeros(2, np.complex128), d=[dict(e=(1, -2., 'hello', u'goodbyeu\u2764')), None]) write_hdf5(test_file, 1) assert_equal(read_hdf5(test_file), 1) assert_raises(IOError, write_hdf5, test_file, x) # file exists write_hdf5(test_file, x, overwrite=True) assert_raises(IOError, read_hdf5, test_file + 'FOO') # not found xx = read_hdf5(test_file) assert_true(object_diff(x, xx) == '') # no assert_equal, ugly output
def test_edf_set_montage_none(): """Test that using montage=None in init and set_montage differs.""" raw = read_raw_edf(edf_path, montage=None) original_chs = deepcopy(raw.info['chs']) assert raw.info['dig'] is None raw.set_montage(None) assert object_diff(raw.info['chs'], original_chs) # They differ # read_raw_edf initializes 0s and set_montage NaNs all_loc = np.array([ch['loc'] for ch in original_chs]) assert_array_equal(all_loc, np.zeros_like(all_loc)) assert_array_equal(np.array([ch['loc'] for ch in raw.info['chs']]), np.full_like(all_loc, np.NaN))
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation.""" raw = read_crop(raw_fname, (0., 1.)) raw.info['bads'] = bads sss_ctc = read_crop(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert (len(py_ctc) > 0) pytest.raises(ValueError, maxwell_filter, raw, cross_talk=raw) pytest.raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert isinstance(py_ctc['decoupler'], sparse.csc_matrix) assert isinstance(mf_ctc['decoupler'], sparse.csc_matrix) assert_array_equal(py_ctc['decoupler'].toarray(), mf_ctc['decoupler'].toarray()) # I/O roundtrip tempdir = _TempDir() fname = op.join(tempdir, 'test_sss_raw.fif') sss_ctc.save(fname) sss_ctc_read = read_raw_fif(fname) mf_ctc_read = sss_ctc_read.info['proc_history'][0]['max_info']['sss_ctc'] assert isinstance(mf_ctc_read['decoupler'], sparse.csc_matrix) assert_array_equal(mf_ctc_read['decoupler'].toarray(), mf_ctc['decoupler'].toarray()) assert_equal(object_diff(py_ctc, mf_ctc), '') raw_ctf = read_crop(fname_ctf_raw).apply_gradient_compensation(0) pytest.raises(ValueError, maxwell_filter, raw_ctf) # cannot fit headshape raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04)) _assert_n_free(raw_sss, 68) raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 70) raw_missing = raw.copy().crop(0, 0.1).load_data().pick_channels([ raw.ch_names[pi] for pi in pick_types(raw.info, meg=True, exclude=())[3:] ]) with pytest.warns(RuntimeWarning, match='Not all cross-talk channels'): maxwell_filter(raw_missing, cross_talk=ctc_fname) # MEG channels not in cross-talk pytest.raises(RuntimeError, maxwell_filter, raw_ctf, origin=(0., 0., 0.04), cross_talk=ctc_fname)
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation""" with warnings.catch_warnings(record=True): # maxshield raw = Raw(raw_fname, allow_maxshield=True).crop(0.0, 1.0, False) raw.info["bads"] = bads sss_ctc = Raw(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition="ignore") assert_meg_snr(raw_sss, sss_ctc, 275.0) py_ctc = raw_sss.info["proc_history"][0]["max_info"]["sss_ctc"] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info["proc_history"][0]["max_info"]["sss_ctc"] del mf_ctc["block_id"] # we don't write this assert_equal(object_diff(py_ctc, mf_ctc), "")
def test_maxwell_filter_cross_talk(): """Test Maxwell filter cross-talk cancellation""" with warnings.catch_warnings(record=True): # maxshield raw = Raw(raw_fname, allow_maxshield=True).crop(0., 1., False) raw.info['bads'] = bads sss_ctc = Raw(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname) _assert_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert_equal(object_diff(py_ctc, mf_ctc), '')
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with pytest.warns(None): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with pytest.warns(None): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation.""" raw = read_crop(raw_fname, (0., 1.)) raw.info['bads'] = bads sss_ctc = read_crop(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert isinstance(py_ctc['decoupler'], sparse.csc_matrix) assert isinstance(mf_ctc['decoupler'], sparse.csc_matrix) assert_array_equal(py_ctc['decoupler'].toarray(), mf_ctc['decoupler'].toarray()) # I/O roundtrip tempdir = _TempDir() fname = op.join(tempdir, 'test_sss_raw.fif') sss_ctc.save(fname) sss_ctc_read = read_raw_fif(fname) mf_ctc_read = sss_ctc_read.info['proc_history'][0]['max_info']['sss_ctc'] assert isinstance(mf_ctc_read['decoupler'], sparse.csc_matrix) assert_array_equal(mf_ctc_read['decoupler'].toarray(), mf_ctc['decoupler'].toarray()) assert_equal(object_diff(py_ctc, mf_ctc), '') raw_ctf = read_crop(fname_ctf_raw).apply_gradient_compensation(0) assert_raises(ValueError, maxwell_filter, raw_ctf) # cannot fit headshape raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04)) _assert_n_free(raw_sss, 68) raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 70) raw_missing = raw.copy().crop(0, 0.1).load_data().pick_channels( [raw.ch_names[pi] for pi in pick_types(raw.info, meg=True, exclude=())[3:]]) with warnings.catch_warnings(record=True) as w: maxwell_filter(raw_missing, cross_talk=ctc_fname) assert_equal(len(w), 1) assert_true('Not all cross-talk channels in raw' in str(w[0].message)) # MEG channels not in cross-talk assert_raises(RuntimeError, maxwell_filter, raw_ctf, origin=(0., 0., 0.04), cross_talk=ctc_fname)
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with warnings.catch_warnings(record=True) as w: pts, tri, vol_info = read_surface(fname, read_metadata=True) assert all('No volume info' in str(ww.message) for ww in w) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with warnings.catch_warnings(record=True) as w: # No vol info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with warnings.catch_warnings(record=True) as w: pts, tri, vol_info = read_surface(fname, read_metadata=True) assert_true(all('No volume info' in str(ww.message) for ww in w)) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with warnings.catch_warnings(record=True) as w: # No vol info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def test_cross_talk(): """Test Maxwell filter cross-talk cancellation""" with warnings.catch_warnings(record=True): # maxshield raw = Raw(raw_fname, allow_maxshield=True).crop(0., 1., False) raw.info['bads'] = bads sss_ctc = Raw(sss_ctc_fname) raw_sss = maxwell_filter(raw, cross_talk=ctc_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, sss_ctc, 275.) py_ctc = raw_sss.info['proc_history'][0]['max_info']['sss_ctc'] assert_true(len(py_ctc) > 0) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw) assert_raises(ValueError, maxwell_filter, raw, cross_talk=raw_fname) mf_ctc = sss_ctc.info['proc_history'][0]['max_info']['sss_ctc'] del mf_ctc['block_id'] # we don't write this assert_equal(object_diff(py_ctc, mf_ctc), '')
def test_handle_coords_reading(): """Test reading coordinates from BIDS files.""" bids_root = _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) # ensure we are writing 'ecog'/'ieeg' data raw.set_channel_types({ch: 'ecog' for ch in raw.ch_names}) # set a `random` montage ch_names = raw.ch_names elec_locs = np.random.random((len(ch_names), 3)).astype(float) ch_pos = dict(zip(ch_names, elec_locs)) montage = mne.channels.make_dig_montage(ch_pos=ch_pos, coord_frame="mri") raw.set_montage(montage) write_raw_bids(raw, bids_basename, bids_root, overwrite=True) # read in the data and assert montage is the same bids_fname = bids_basename + "_ieeg.edf" raw_test = read_raw_bids(bids_fname, bids_root) # obtain the sensor positions orig_locs = raw.info['dig'][1] test_locs = raw_test.info['dig'][1] assert orig_locs == test_locs assert not object_diff(raw.info['chs'], raw_test.info['chs']) # test error message if electrodes don't match electrodes_fname = _find_matching_sidecar(bids_fname, bids_root, "electrodes.tsv", allow_fail=True) electrodes_dict = _from_tsv(electrodes_fname) # pop off 5 channels for key in electrodes_dict.keys(): for i in range(5): electrodes_dict[key].pop() _to_tsv(electrodes_dict, electrodes_fname) with pytest.raises(RuntimeError, match='Channels do not correspond'): raw_test = read_raw_bids(bids_fname, bids_root)
def test_params_io(tmpdir, fname): """Test params I/O round-trip.""" import yaml assert op.isfile(fname) p = read_params(fname) assert '__default__' not in p.mf_prebad temp_fname = str(tmpdir.join('test.yml')) p.save(temp_fname) assert '__default__' not in p.mf_prebad # Look at our objects p2 = read_params(temp_fname) assert object_diff(p.__dict__, p2.__dict__) == '' # Look at the YAML to check out write order in the file is preserved with open(fname, 'r') as fid: orig = yaml.load(fid, Loader=yaml.SafeLoader) for ii, key in enumerate(orig.keys()): if ii != 0: break assert key == 'general' with open(temp_fname, 'r') as fid: read = yaml.load(fid, Loader=yaml.SafeLoader) for ii, key in enumerate(read.keys()): if ii != 0: break assert key == 'general' # We can do this because we currently write only keys that differ from # defaults, but we need to exclude the ones from funloc that we include # anyway. This also helps ensure that the funloc example mostly shows # deviations from defaults. del orig['general']['subjects_dir'] del orig['scoring']['score'] for key in ('int_order', 'ext_order', 'tsss_dur', 'st_correlation'): del orig['preprocessing']['sss'][key] del orig['epoching']['decim'] del orig['forward']['bem_type'] for key in orig.keys(): assert orig[key] == read[key]
def test_egi_dig_montage(): """Test EGI MFF XML dig montage support.""" with pytest.deprecated_call(): dig_montage = read_dig_montage(egi=egi_dig_montage_fname, unit='m') # # test round-trip IO temp_dir = _TempDir() fname_temp = op.join(temp_dir, 'egi_test.fif') _check_roundtrip(dig_montage, fname_temp) with pytest.deprecated_call(): # Test coordinate transform # dig_montage.transform_to_head() # XXX: this call had no effect!! # nasion assert_almost_equal(dig_montage.nasion[0], 0) assert_almost_equal(dig_montage.nasion[2], 0) # lpa and rpa assert_allclose(dig_montage.lpa[1:], 0, atol=1e-16) assert_allclose(dig_montage.rpa[1:], 0, atol=1e-16) # Test accuracy and embedding within raw object raw_egi = read_raw_egi(egi_raw_fname, channel_naming='EEG %03d') raw_egi.set_montage(dig_montage) test_raw_egi = read_raw_fif(egi_fif_fname) assert_equal(len(raw_egi.ch_names), len(test_raw_egi.ch_names)) for ch_raw, ch_test_raw in zip(raw_egi.info['chs'], test_raw_egi.info['chs']): assert_equal(ch_raw['ch_name'], ch_test_raw['ch_name']) assert_equal(ch_raw['coord_frame'], FIFF.FIFFV_COORD_HEAD) assert_allclose(ch_raw['loc'], ch_test_raw['loc'], atol=1e-7) assert_dig_allclose(raw_egi.info, test_raw_egi.info) # Test old way matches new way with pytest.deprecated_call(): dig_montage = read_dig_montage(egi=egi_dig_montage_fname, unit='m') dig_montage_egi = read_dig_egi(egi_dig_montage_fname) dig_montage_egi = transform_to_head(dig_montage_egi) assert dig_montage.dig == dig_montage_egi.dig assert object_diff(dig_montage.ch_names, dig_montage_egi.ch_names) == ''
def test_snirf_write(fname, tmpdir): """Test reading NIRX files.""" raw_orig = read_raw_nirx(fname, preload=True) test_file = tmpdir.join('test_raw.snirf') write_raw_snirf(raw_orig, test_file) raw = read_raw_snirf(test_file) result = validateSnirf(str(test_file)) if result.is_valid(): result.display() assert result.is_valid() # Check annotations are the same assert_allclose(raw.annotations.onset, raw_orig.annotations.onset) assert_allclose([float(d) for d in raw.annotations.description], [float(d) for d in raw_orig.annotations.description]) assert_allclose(raw.annotations.duration, raw_orig.annotations.duration) # Check data is the same assert_allclose(raw.get_data(), raw_orig.get_data()) assert abs(raw_orig.info['meas_date'] - raw.info['meas_date']) < \ datetime.timedelta(seconds=1) # Check info object is the same obj_diff = object_diff(raw.info, raw_orig.info) diffs = '' for line in obj_diff.splitlines(): if ('logno' not in line) and \ ('scanno' not in line) and \ ('his_id' not in line) and\ ('datetime mismatch' not in line): # logno and scanno are not used in processing diffs += f'\n{line}' assert diffs == '' _verify_snirf_required_fields(test_file) _verify_snirf_version_str(test_file)
def test_csd_fif(): """Test applying CSD to FIF data.""" raw = read_raw_fif(raw_fname).load_data() raw.info['bads'] = [] picks = pick_types(raw.info, meg=False, eeg=True) assert 'csd' not in raw orig_eeg = raw.get_data('eeg') assert len(orig_eeg) == 60 raw_csd = compute_current_source_density(raw) assert 'eeg' not in raw_csd new_eeg = raw_csd.get_data('csd') assert not (orig_eeg == new_eeg).any() # reset the only things that should change, and assert objects are the same assert raw_csd.info['custom_ref_applied'] == FIFF.FIFFV_MNE_CUSTOM_REF_CSD raw_csd.info['custom_ref_applied'] = 0 for pick in picks: ch = raw_csd.info['chs'][pick] assert ch['coil_type'] == FIFF.FIFFV_COIL_EEG_CSD assert ch['unit'] == FIFF.FIFF_UNIT_V_M2 ch.update(coil_type=FIFF.FIFFV_COIL_EEG, unit=FIFF.FIFF_UNIT_V) raw_csd._data[pick] = raw._data[pick] assert object_diff(raw.info, raw_csd.info) == ''
def test_hash(): """Test dictionary hashing and comparison functions.""" # does hashing all of these types work: # {dict, list, tuple, ndarray, str, float, int, None} d0 = dict(a=dict(a=0.1, b='fo', c=1), b=[1, 'b'], c=(), d=np.ones(3), e=None) d0[1] = None d0[2.] = b'123' d1 = deepcopy(d0) assert_true(len(object_diff(d0, d1)) == 0) assert_true(len(object_diff(d1, d0)) == 0) assert_equal(object_hash(d0), object_hash(d1)) # change values slightly d1['data'] = np.ones(3, int) d1['d'][0] = 0 assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1['a']['a'] = 0.11 assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1['a']['d'] = 0 # non-existent key assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1['b'].append(0) # different-length lists assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1['e'] = 'foo' # non-None assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) d2 = deepcopy(d0) d1['e'] = StringIO() d2['e'] = StringIO() d2['e'].write('foo') assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) d1 = deepcopy(d0) d1[1] = 2 assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) # generators (and other types) not supported d1 = deepcopy(d0) d2 = deepcopy(d0) d1[1] = (x for x in d0) d2[1] = (x for x in d0) assert_raises(RuntimeError, object_diff, d1, d2) assert_raises(RuntimeError, object_hash, d1) x = sparse.eye(2, 2, format='csc') y = sparse.eye(2, 2, format='csr') assert_true('type mismatch' in object_diff(x, y)) y = sparse.eye(2, 2, format='csc') assert_equal(len(object_diff(x, y)), 0) y[1, 1] = 2 assert_true('elements' in object_diff(x, y)) y = sparse.eye(3, 3, format='csc') assert_true('shape' in object_diff(x, y)) y = 0 assert_true('type mismatch' in object_diff(x, y))
def test_make_lcmv(tmpdir): """Test LCMV with evoked data and single trials.""" raw, epochs, evoked, data_cov, noise_cov, label, forward,\ forward_surf_ori, forward_fixed, forward_vol = _get_data() for fwd in [forward, forward_vol]: filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov) stc = apply_lcmv(evoked, filters, max_ori_out='signed') stc.crop(0.02, None) stc_pow = np.sum(np.abs(stc.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc.data[idx] tmax = stc.times[np.argmax(max_stc)] assert 0.09 < tmax < 0.12, tmax assert 0.9 < np.max(max_stc) < 3., np.max(max_stc) if fwd is forward: # Test picking normal orientation (surface source space only). filters = make_lcmv(evoked.info, forward_surf_ori, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal', weight_norm=None) stc_normal = apply_lcmv(evoked, filters, max_ori_out='signed') stc_normal.crop(0.02, None) stc_pow = np.sum(np.abs(stc_normal.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc_normal.data[idx] tmax = stc_normal.times[np.argmax(max_stc)] assert 0.04 < tmax < 0.13, tmax assert 3e-7 < np.max(max_stc) < 5e-7, np.max(max_stc) # No weight normalization was applied, so the amplitude of normal # orientation results should always be smaller than free # orientation results. assert (np.abs(stc_normal.data) <= stc.data).all() # Test picking source orientation maximizing output source power filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power') stc_max_power = apply_lcmv(evoked, filters, max_ori_out='signed') stc_max_power.crop(0.02, None) stc_pow = np.sum(np.abs(stc_max_power.data), axis=1) idx = np.argmax(stc_pow) max_stc = np.abs(stc_max_power.data[idx]) tmax = stc.times[np.argmax(max_stc)] assert 0.08 < tmax < 0.12, tmax assert 0.8 < np.max(max_stc) < 3., np.max(max_stc) stc_max_power.data[:, :] = np.abs(stc_max_power.data) if fwd is forward: # Maximum output source power orientation results should be # similar to free orientation results in areas with channel # coverage label = mne.read_label(fname_label) mean_stc = stc.extract_label_time_course(label, fwd['src'], mode='mean') mean_stc_max_pow = \ stc_max_power.extract_label_time_course(label, fwd['src'], mode='mean') assert_array_less(np.abs(mean_stc - mean_stc_max_pow), 0.6) # Test NAI weight normalization: filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power', weight_norm='nai') stc_nai = apply_lcmv(evoked, filters, max_ori_out='signed') stc_nai.crop(0.02, None) # Test whether unit-noise-gain solution is a scaled version of NAI pearsoncorr = np.corrcoef(np.concatenate(np.abs(stc_nai.data)), np.concatenate(stc_max_power.data)) assert_almost_equal(pearsoncorr[0, 1], 1.) # Test sphere head model with unit-noise gain beamformer and orientation # selection and rank reduction of the leadfield sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd_sphere = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere, eeg=False, meg=True) # Test that we get an error if not reducing rank with pytest.raises(ValueError): # Singular matrix or complex spectrum make_lcmv( evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=False, rank='full') # Now let's reduce it filters = make_lcmv(evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=True) stc_sphere = apply_lcmv(evoked, filters, max_ori_out='signed') stc_sphere = np.abs(stc_sphere) stc_sphere.crop(0.02, None) stc_pow = np.sum(stc_sphere.data, axis=1) idx = np.argmax(stc_pow) max_stc = stc_sphere.data[idx] tmax = stc_sphere.times[np.argmax(max_stc)] assert 0.08 < tmax < 0.15, tmax assert 0.4 < np.max(max_stc) < 2., np.max(max_stc) # Test if spatial filter contains src_type assert 'src_type' in filters # __repr__ assert 'LCMV' in repr(filters) assert 'unknown subject' not in repr(filters) assert '484' in repr(filters) assert '20' in repr(filters) assert 'rank 17' in repr(filters) # I/O fname = op.join(str(tmpdir), 'filters.h5') with pytest.warns(RuntimeWarning, match='-lcmv.h5'): filters.save(fname) filters_read = read_beamformer(fname) assert isinstance(filters, Beamformer) assert isinstance(filters_read, Beamformer) # deal with object_diff strictness filters_read['rank'] = int(filters_read['rank']) filters['rank'] = int(filters['rank']) assert object_diff(filters, filters_read) == '' # Test if fixed forward operator is detected when picking normal or # max-power orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power') # Test if non-surface oriented forward operator is detected when picking # normal orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if volume forward operator is detected when picking normal # orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if missing of noise covariance matrix is detected when more than # one channel type is present in the data pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov=data_cov, reg=0.01, noise_cov=None, pick_ori='max-power') # Test if wrong channel selection is detected in application of filter evoked_ch = deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[1:]) filters = make_lcmv(evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) pytest.raises(ValueError, apply_lcmv, evoked_ch, filters, max_ori_out='signed') # Test if discrepancies in channel selection of data and fwd model are # handled correctly in apply_lcmv # make filter with data where first channel was removed filters = make_lcmv(evoked_ch.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) # applying that filter to the full data set should automatically exclude # this channel from the data # also test here that no warnings are thrown - implemented to check whether # src should not be None warning occurs with pytest.warns(None) as w: stc = apply_lcmv(evoked, filters, max_ori_out='signed') assert len(w) == 0 # the result should be equal to applying this filter to a dataset without # this channel: stc_ch = apply_lcmv(evoked_ch, filters, max_ori_out='signed') assert_array_almost_equal(stc.data, stc_ch.data) # Test if non-matching SSP projection is detected in application of filter raw_proj = deepcopy(raw) raw_proj.del_proj() pytest.raises(ValueError, apply_lcmv_raw, raw_proj, filters, max_ori_out='signed') # Test if setting reduce_rank to True returns a NotImplementedError # when no orientation selection is done or pick_ori='normal' pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_vol, data_cov, noise_cov=noise_cov, pick_ori=None, weight_norm='nai', reduce_rank=True) pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_surf_ori, data_cov, noise_cov=noise_cov, pick_ori='normal', weight_norm='nai', reduce_rank=True) # Test if spatial filter contains src_type assert 'src_type' in filters # check whether a filters object without src_type throws expected warning del filters['src_type'] # emulate 0.16 behaviour to cause warning with pytest.warns(RuntimeWarning, match='spatial filter does not contain ' 'src_type'): apply_lcmv(evoked, filters, max_ori_out='signed') # Now test single trial using fixed orientation forward solution # so we can compare it to the evoked solution filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True, max_ori_out='signed') assert_array_equal(stcs[0].data, next(stcs_).data) epochs.drop_bad() assert (len(epochs.events) == len(stcs)) # average the single trial estimates stc_avg = np.zeros_like(stcs[0].data) for this_stc in stcs: stc_avg += this_stc.data stc_avg /= len(stcs) # compare it to the solution using evoked with fixed orientation filters = make_lcmv(evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stc_fixed = apply_lcmv(evoked, filters, max_ori_out='signed') assert_array_almost_equal(stc_avg, stc_fixed.data) # use a label so we have few source vertices and delayed computation is # not used filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, label=label) stcs_label = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data) # Test condition where the filters weights are zero. There should not be # any divide-by-zero errors zero_cov = data_cov.copy() zero_cov['data'][:] = 0 filters = make_lcmv(epochs.info, forward_fixed, zero_cov, reg=0.01, noise_cov=noise_cov) assert_array_equal(filters['weights'], 0)
def test_make_dics(tmpdir): """Test making DICS beamformer filters.""" # We only test proper handling of parameters here. Testing the results is # done in test_apply_dics_timeseries and test_apply_dics_csd. fwd_free, fwd_surf, fwd_fixed, fwd_vol, label = _load_forward() epochs, _, csd, _ = _simulate_data(fwd_fixed) raises(ValueError, make_dics, epochs.info, fwd_fixed, csd, pick_ori="notexistent") with raises(ValueError, match='rank, if str'): make_dics(epochs.info, fwd_fixed, csd, rank='foo') with raises(TypeError, match='rank must be'): make_dics(epochs.info, fwd_fixed, csd, rank=1.) # Test if fixed forward operator is detected when picking normal # orientation raises(ValueError, make_dics, epochs.info, fwd_fixed, csd, pick_ori="normal") # Test if non-surface oriented forward operator is detected when picking # normal orientation raises(ValueError, make_dics, epochs.info, fwd_free, csd, pick_ori="normal") # Test if volume forward operator is detected when picking normal # orientation raises(ValueError, make_dics, epochs.info, fwd_vol, csd, pick_ori="normal") # Test invalid combinations of parameters raises(NotImplementedError, make_dics, epochs.info, fwd_free, csd, reduce_rank=True, pick_ori=None) raises(NotImplementedError, make_dics, epochs.info, fwd_free, csd, reduce_rank=True, pick_ori='max-power', inversion='single') # Sanity checks on the returned filters n_freq = len(csd.frequencies) vertices = np.intersect1d(label.vertices, fwd_free['src'][0]['vertno']) n_verts = len(vertices) n_orient = 3 n_channels = csd.n_channels # Test return values filters = make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori=None, weight_norm='unit-noise-gain') assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels) assert np.iscomplexobj(filters['weights']) assert filters['csd'] == csd assert filters['ch_names'] == csd.ch_names assert_array_equal(filters['proj'], np.eye(n_channels)) assert_array_equal(filters['vertices'][0], vertices) assert_array_equal(filters['vertices'][1], []) # Label was on the LH assert filters['subject'] == fwd_free['src'][0]['subject_his_id'] assert filters['pick_ori'] is None assert filters['n_orient'] == n_orient assert filters['inversion'] == 'single' assert filters['normalize_fwd'] assert filters['weight_norm'] == 'unit-noise-gain' assert 'DICS' in repr(filters) assert 'subject "sample"' in repr(filters) assert '13' in repr(filters) assert '62' in repr(filters) assert 'rank' not in repr(filters) _test_weight_norm(filters) # Test picking orientations. Also test weight norming under these different # conditions. filters = make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori='normal', weight_norm='unit-noise-gain') n_orient = 1 assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels) assert filters['n_orient'] == n_orient _test_weight_norm(filters) filters = make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori='max-power', weight_norm='unit-noise-gain') n_orient = 1 assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels) assert filters['n_orient'] == n_orient _test_weight_norm(filters) # From here on, only work on a single frequency csd = csd[0] # Test using a real-valued filter filters = make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori='normal', real_filter=True) assert not np.iscomplexobj(filters['weights']) # Test forward normalization. When inversion='single', the power of a # unit-noise CSD should be 1, even without weight normalization. csd_noise = csd.copy() inds = np.triu_indices(csd.n_channels) # Using [:, :] syntax for in-place broadcasting csd_noise._data[:, :] = np.eye(csd.n_channels)[inds][:, np.newaxis] filters = make_dics(epochs.info, fwd_surf, csd_noise, label=label, weight_norm=None, normalize_fwd=True) w = filters['weights'][0][:3] assert_allclose(np.diag(w.dot(w.T)), 1.0, rtol=1e-6, atol=0) # Test turning off both forward and weight normalization filters = make_dics(epochs.info, fwd_surf, csd, label=label, weight_norm=None, normalize_fwd=False) w = filters['weights'][0][:3] assert not np.allclose(np.diag(w.dot(w.T)), 1.0, rtol=1e-2, atol=0) # Test neural-activity-index weight normalization. It should be a scaled # version of the unit-noise-gain beamformer. filters_nai = make_dics(epochs.info, fwd_surf, csd, label=label, weight_norm='nai', normalize_fwd=False) w_nai = filters_nai['weights'][0] filters_ung = make_dics(epochs.info, fwd_surf, csd, label=label, weight_norm='unit-noise-gain', normalize_fwd=False) w_ung = filters_ung['weights'][0] assert np.allclose(np.corrcoef(np.abs(w_nai).ravel(), np.abs(w_ung).ravel()), 1) # Test whether spatial filter contains src_type assert 'src_type' in filters fname = op.join(str(tmpdir), 'filters-dics.h5') filters.save(fname) filters_read = read_beamformer(fname) assert isinstance(filters, Beamformer) assert isinstance(filters_read, Beamformer) for key in ['tmin', 'tmax']: # deal with strictness of object_diff setattr(filters['csd'], key, np.float(getattr(filters['csd'], key))) assert object_diff(filters, filters_read) == ''
def test_hash(): """Test dictionary hashing and comparison functions""" # does hashing all of these types work: # {dict, list, tuple, ndarray, str, float, int, None} d0 = dict(a=dict(a=0.1, b="fo", c=1), b=[1, "b"], c=(), d=np.ones(3), e=None) d0[1] = None d0[2.0] = b"123" d1 = deepcopy(d0) assert_true(len(object_diff(d0, d1)) == 0) assert_true(len(object_diff(d1, d0)) == 0) assert_equal(object_hash(d0), object_hash(d1)) # change values slightly d1["data"] = np.ones(3, int) d1["d"][0] = 0 assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1["a"]["a"] = 0.11 assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1["a"]["d"] = 0 # non-existent key assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1["b"].append(0) # different-length lists assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) assert_equal(object_hash(d0), object_hash(d1)) d1["e"] = "foo" # non-None assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) d1 = deepcopy(d0) d2 = deepcopy(d0) d1["e"] = StringIO() d2["e"] = StringIO() d2["e"].write("foo") assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) d1 = deepcopy(d0) d1[1] = 2 assert_true(len(object_diff(d0, d1)) > 0) assert_true(len(object_diff(d1, d0)) > 0) assert_not_equal(object_hash(d0), object_hash(d1)) # generators (and other types) not supported d1 = deepcopy(d0) d2 = deepcopy(d0) d1[1] = (x for x in d0) d2[1] = (x for x in d0) assert_raises(RuntimeError, object_diff, d1, d2) assert_raises(RuntimeError, object_hash, d1) x = sparse.eye(2, 2, format="csc") y = sparse.eye(2, 2, format="csr") assert_true("type mismatch" in object_diff(x, y)) y = sparse.eye(2, 2, format="csc") assert_equal(len(object_diff(x, y)), 0) y[1, 1] = 2 assert_true("elements" in object_diff(x, y)) y = sparse.eye(3, 3, format="csc") assert_true("shape" in object_diff(x, y)) y = 0 assert_true("type mismatch" in object_diff(x, y))