def test_saving_picked(): """Test saving picked CTF instances.""" temp_dir = _TempDir() out_fname = op.join(temp_dir, 'test_py_raw.fif') raw = read_raw_ctf(op.join(ctf_dir, ctf_fname_1_trial)) raw.crop(0, 1).load_data() assert raw.compensation_grade == get_current_comp(raw.info) == 0 assert len(raw.info['comps']) == 5 pick_kwargs = dict(meg=True, ref_meg=False, verbose=True) for comp_grade in [0, 1]: raw.apply_gradient_compensation(comp_grade) with catch_logging() as log: raw_pick = raw.copy().pick_types(**pick_kwargs) assert len(raw.info['comps']) == 5 assert len(raw_pick.info['comps']) == 0 log = log.getvalue() assert 'Removing 5 compensators' in log raw_pick.save(out_fname, overwrite=True) # should work raw2 = read_raw_fif(out_fname) assert (raw_pick.ch_names == raw2.ch_names) assert_array_equal(raw_pick.times, raw2.times) assert_allclose(raw2[0:20][0], raw_pick[0:20][0], rtol=1e-6, atol=1e-20) # atol is very small but > 0 raw2 = read_raw_fif(out_fname, preload=True) assert (raw_pick.ch_names == raw2.ch_names) assert_array_equal(raw_pick.times, raw2.times) assert_allclose(raw2[0:20][0], raw_pick[0:20][0], rtol=1e-6, atol=1e-20) # atol is very small but > 0
def test_calculate_chpi_positions(): """Test calculation of cHPI positions """ trans, rot, t = head_pos_to_trans_rot_t(read_head_pos(pos_fname)) with warnings.catch_warnings(record=True): raw = Raw(chpi_fif_fname, allow_maxshield=True, preload=True) t -= raw.first_samp / raw.info['sfreq'] quats = _calculate_chpi_positions(raw, verbose='debug') trans_est, rot_est, t_est = head_pos_to_trans_rot_t(quats) _compare_positions((trans, rot, t), (trans_est, rot_est, t_est), 0.003) # degenerate conditions raw_no_chpi = Raw(test_fif_fname) assert_raises(RuntimeError, _calculate_chpi_positions, raw_no_chpi) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['coord_frame'] = 999 break assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['r'] = np.ones(3) raw_bad.crop(0, 1., copy=False) with warnings.catch_warnings(record=True): # bad pos with catch_logging() as log_file: _calculate_chpi_positions(raw_bad, verbose=True) # ignore HPI info header and [done] footer for line in log_file.getvalue().strip().split('\n')[4:-1]: assert_true('0/5 good' in line)
def test_make_inverse_operator(): """Test MNE inverse computation (precomputed and non-precomputed).""" # Test old version of inverse computation starting from forward operator evoked = _get_evoked() noise_cov = read_cov(fname_cov) inverse_operator = read_inverse_operator(fname_inv) fwd_op = convert_forward_solution(read_forward_solution_meg(fname_fwd), surf_ori=True, copy=False) with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log _compare_io(my_inv_op) assert_equal(inverse_operator['units'], 'Am') _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-2, atol=1e-5, depth_atol=1e-3) # Test MNE inverse computation starting from forward operator with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log _compare_io(my_inv_op) _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-3, atol=1e-5) assert ('dev_head_t' in my_inv_op['info']) assert ('mri_head_t' in my_inv_op)
def test_chpi_subtraction(): """Test subtraction of cHPI signals.""" raw = read_raw_fif(chpi_fif_fname, allow_maxshield='yes', preload=True) raw.info['bads'] = ['MEG0111'] raw.del_proj() with catch_logging() as log: filter_chpi(raw, include_line=False, verbose=True) assert 'No average EEG' not in log.getvalue() assert '5 cHPI' in log.getvalue() # MaxFilter doesn't do quite as well as our algorithm with the last bit raw.crop(0, 16) # remove cHPI status chans raw_c = read_raw_fif(sss_hpisubt_fname).crop(0, 16).load_data() raw_c.pick_types( meg=True, eeg=True, eog=True, ecg=True, stim=True, misc=True) assert_meg_snr(raw, raw_c, 143, 624) # Degenerate cases raw_nohpi = read_raw_fif(test_fif_fname, preload=True) pytest.raises(RuntimeError, filter_chpi, raw_nohpi) # When MaxFliter downsamples, like:: # $ maxfilter -nosss -ds 2 -f test_move_anon_raw.fif \ # -o test_move_anon_ds2_raw.fif # it can strip out some values of info, which we emulate here: raw = read_raw_fif(chpi_fif_fname, allow_maxshield='yes') raw = raw.crop(0, 1).load_data().resample(600., npad='auto') raw.info['lowpass'] = 200. del raw.info['maxshield'] del raw.info['hpi_results'][0]['moments'] del raw.info['hpi_subsystem']['event_channel'] with catch_logging() as log: filter_chpi(raw, verbose=True) pytest.raises(ValueError, filter_chpi, raw, t_window=-1) assert '2 cHPI' in log.getvalue()
def test_head_translation(): """Test Maxwell filter head translation.""" raw = read_crop(raw_fname, (0., 1.)) # First try with an unchanged destination raw_sss = maxwell_filter(raw, destination=raw_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, read_crop(sss_std_fname, (0., 1.)), 200.) # Now with default with pytest.warns(RuntimeWarning, match='over 25 mm'): with catch_logging() as log: raw_sss = maxwell_filter(raw, destination=mf_head_origin, origin=mf_head_origin, regularize=None, bad_condition='ignore', verbose='warning') assert ('over 25 mm' in log.getvalue()) assert_meg_snr(raw_sss, read_crop(sss_trans_default_fname), 125.) destination = np.eye(4) destination[2, 3] = 0.04 assert_allclose(raw_sss.info['dev_head_t']['trans'], destination) # Now to sample's head pos with pytest.warns(RuntimeWarning, match='= 25.6 mm'): with catch_logging() as log: raw_sss = maxwell_filter(raw, destination=sample_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore', verbose='warning') assert ('= 25.6 mm' in log.getvalue()) assert_meg_snr(raw_sss, read_crop(sss_trans_sample_fname), 350.) assert_allclose(raw_sss.info['dev_head_t']['trans'], read_info(sample_fname)['dev_head_t']['trans']) # Degenerate cases pytest.raises(RuntimeError, maxwell_filter, raw, destination=mf_head_origin, coord_frame='meg') pytest.raises(ValueError, maxwell_filter, raw, destination=[0.] * 4)
def test_fetch_file(url, tmpdir): """Test URL retrieval.""" tempdir = str(tmpdir) archive_name = op.join(tempdir, "download_test") with catch_logging() as log: _fetch_file(url, archive_name, timeout=30., verbose='debug') log = log.getvalue() assert 'Resuming at' not in log with open(archive_name, 'rb') as fid: data = fid.read() stop = len(data) // 2 assert 0 < stop < len(data) with open(archive_name + '.part', 'wb') as fid: fid.write(data[:stop]) with catch_logging() as log: _fetch_file(url, archive_name, timeout=30., verbose='debug') log = log.getvalue() assert 'Resuming at %s' % stop in log with pytest.raises(Exception, match='unknown url type'): _fetch_file('NOT_AN_ADDRESS', op.join(tempdir, 'test'), verbose=False) resume_name = op.join(tempdir, "download_resume") # touch file with open(resume_name + '.part', 'w'): os.utime(resume_name + '.part', None) _fetch_file(url, resume_name, resume=True, timeout=30., verbose=False) with pytest.raises(ValueError, match='Bad hash value'): _fetch_file(url, archive_name, hash_='a', verbose=False) with pytest.raises(RuntimeError, match='Hash mismatch'): _fetch_file(url, archive_name, hash_='a' * 32, verbose=False)
def test_head_translation(): """Test Maxwell filter head translation""" with warnings.catch_warnings(record=True): # maxshield raw = Raw(raw_fname, allow_maxshield=True).crop(0.0, 1.0, False) # First try with an unchanged destination raw_sss = maxwell_filter(raw, destination=raw_fname, origin=mf_head_origin, regularize=None, bad_condition="ignore") assert_meg_snr(raw_sss, Raw(sss_std_fname).crop(0.0, 1.0, False), 200.0) # Now with default with catch_logging() as log: raw_sss = maxwell_filter( raw, destination=mf_head_origin, origin=mf_head_origin, regularize=None, bad_condition="ignore", verbose="warning", ) assert_true("over 25 mm" in log.getvalue()) assert_meg_snr(raw_sss, Raw(sss_trans_default_fname), 125.0) # Now to sample's head pos with catch_logging() as log: raw_sss = maxwell_filter( raw, destination=sample_fname, origin=mf_head_origin, regularize=None, bad_condition="ignore", verbose="warning", ) assert_true("= 25.6 mm" in log.getvalue()) assert_meg_snr(raw_sss, Raw(sss_trans_sample_fname), 350.0) # Degenerate cases assert_raises(RuntimeError, maxwell_filter, raw, destination=mf_head_origin, coord_frame="meg") assert_raises(ValueError, maxwell_filter, raw, destination=[0.0] * 4)
def test_thresholds(): """Test automatic threshold calculations.""" # within subjects rng = np.random.RandomState(0) X = rng.randn(10, 1, 1) + 0.08 want_thresh = -stats.t.ppf(0.025, len(X) - 1) assert 0.03 < stats.ttest_1samp(X[:, 0, 0], 0)[1] < 0.05 my_fun = partial(ttest_1samp_no_p) with catch_logging() as log: with pytest.warns(RuntimeWarning, match='threshold is only valid'): out = permutation_cluster_1samp_test(X, stat_fun=my_fun, verbose=True) log = log.getvalue() assert str(want_thresh)[:6] in log assert len(out[1]) == 1 # 1 cluster assert 0.03 < out[2] < 0.05 # between subjects Y = rng.randn(10, 1, 1) Z = rng.randn(10, 1, 1) - 0.7 X = [X, Y, Z] want_thresh = stats.f.ppf(1. - 0.05, 2, sum(len(a) for a in X) - len(X)) p = stats.f_oneway(*X)[1] assert 0.03 < p < 0.05 my_fun = partial(f_oneway) # just to make the check fail with catch_logging() as log: with pytest.warns(RuntimeWarning, match='threshold is only valid'): out = permutation_cluster_test(X, tail=1, stat_fun=my_fun, verbose=True) log = log.getvalue() assert str(want_thresh)[:6] in log assert len(out[1]) == 1 # 1 cluster assert 0.03 < out[2] < 0.05 with pytest.warns(RuntimeWarning, match='Ignoring argument "tail"'): permutation_cluster_test(X, tail=0)
def test_chpi_adjust(): """Test cHPI logging and adjustment""" raw = read_raw_fif(chpi_fif_fname, allow_maxshield='yes') with catch_logging() as log: _get_hpi_info(raw.info, adjust=True, verbose='debug') # Ran MaxFilter (with -list, -v, -movecomp, etc.), and got: msg = ['HPIFIT: 5 coils digitized in order 5 1 4 3 2', 'HPIFIT: 3 coils accepted: 1 2 4', 'Hpi coil moments (3 5):', '2.08542e-15 -1.52486e-15 -1.53484e-15', '2.14516e-15 2.09608e-15 7.30303e-16', '-3.2318e-16 -4.25666e-16 2.69997e-15', '5.21717e-16 1.28406e-15 1.95335e-15', '1.21199e-15 -1.25801e-19 1.18321e-15', 'HPIFIT errors: 0.3, 0.3, 5.3, 0.4, 3.2 mm.', 'HPI consistency of isotrak and hpifit is OK.', 'HP fitting limits: err = 5.0 mm, gval = 0.980.', 'Using 5 HPI coils: 83 143 203 263 323 Hz', # actually came earlier ] log = log.getvalue().splitlines() assert_true(set(log) == set(msg), '\n' + '\n'.join(set(msg) - set(log))) # Then took the raw file, did this: raw.info['dig'][5]['r'][2] += 1. # And checked the result in MaxFilter, which changed the logging as: msg = msg[:8] + [ 'HPIFIT errors: 0.3, 0.3, 5.3, 999.7, 3.2 mm.', 'Note: HPI coil 3 isotrak is adjusted by 5.3 mm!', 'Note: HPI coil 5 isotrak is adjusted by 3.2 mm!'] + msg[-2:] with catch_logging() as log: _get_hpi_info(raw.info, adjust=True, verbose='debug') log = log.getvalue().splitlines() assert_true(set(log) == set(msg), '\n' + '\n'.join(set(msg) - set(log)))
def test_make_inverse_operator_loose(evoked): """Test MNE inverse computation (precomputed and non-precomputed).""" # Test old version of inverse computation starting from forward operator noise_cov = read_cov(fname_cov) inverse_operator = read_inverse_operator(fname_inv) fwd_op = convert_forward_solution(read_forward_solution_meg(fname_fwd), surf_ori=True, copy=False) with catch_logging() as log: with pytest.deprecated_call(): # limit_depth_chs my_inv_op = make_inverse_operator( evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False, verbose=True) log = log.getvalue() assert 'MEG: rank 302 computed' in log assert 'limit = 1/%d' % fwd_op['nsource'] in log _compare_io(my_inv_op) assert_equal(inverse_operator['units'], 'Am') _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-2, atol=1e-5, depth_atol=1e-3) # Test MNE inverse computation starting from forward operator with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose='auto', depth=0.8, fixed=False, verbose=True) log = log.getvalue() assert 'MEG: rank 302 computed from 305' in log _compare_io(my_inv_op) _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-3, atol=1e-5) assert ('dev_head_t' in my_inv_op['info']) assert ('mri_head_t' in my_inv_op)
def test_chpi_subtraction(): """Test subtraction of cHPI signals""" raw = Raw(chpi_fif_fname, allow_maxshield="yes", preload=True) with catch_logging() as log: filter_chpi(raw, include_line=False, verbose=True) assert_true("5 cHPI" in log.getvalue()) # MaxFilter doesn't do quite as well as our algorithm with the last bit raw.crop(0, 16, copy=False) # remove cHPI status chans raw_c = Raw(sss_hpisubt_fname).crop(0, 16, copy=False).load_data() raw_c.pick_types(meg=True, eeg=True, eog=True, ecg=True, stim=True, misc=True) assert_meg_snr(raw, raw_c, 143, 624) # Degenerate cases raw_nohpi = Raw(test_fif_fname, preload=True) assert_raises(RuntimeError, filter_chpi, raw_nohpi) # When MaxFliter downsamples, like:: # $ maxfilter -nosss -ds 2 -f test_move_anon_raw.fif \ # -o test_move_anon_ds2_raw.fif # it can strip out some values of info, which we emulate here: raw = Raw(chpi_fif_fname, allow_maxshield="yes") with warnings.catch_warnings(record=True): # uint cast suggestion raw = raw.crop(0, 1).load_data().resample(600.0, npad="auto") raw.info["buffer_size_sec"] = np.float64(2.0) raw.info["lowpass"] = 200.0 del raw.info["maxshield"] del raw.info["hpi_results"][0]["moments"] del raw.info["hpi_subsystem"]["event_channel"] with catch_logging() as log: filter_chpi(raw, verbose=True) assert_true("2 cHPI" in log.getvalue())
def test_chpi_subtraction(): """Test subtraction of cHPI signals""" raw = Raw(chpi_fif_fname, allow_maxshield='yes', preload=True) with catch_logging() as log: filter_chpi(raw, include_line=False, verbose=True) assert_true('5 cHPI' in log.getvalue()) # MaxFilter doesn't do quite as well as our algorithm with the last bit raw.crop(0, 16, copy=False) raw_c = Raw(sss_hpisubt_fname, preload=True).crop(0, 16, copy=False) raw_c.pick_types(meg=True, eeg=True, eog=True, ecg=True, stim=True, misc=True, copy=False) # remove cHPI status chans assert_meg_snr(raw, raw_c, 143, 624) # Degenerate cases raw_nohpi = Raw(test_fif_fname, preload=True) assert_raises(RuntimeError, filter_chpi, raw_nohpi) # When MaxFliter downsamples, like:: # $ maxfilter -nosss -ds 2 -f test_move_anon_raw.fif \ # -o test_move_anon_ds2_raw.fif # it can strip out some values of info, which we emulate here: raw = Raw(chpi_fif_fname, allow_maxshield='yes') raw.crop(0, 1, copy=False).load_data() raw.resample(600., npad='auto') raw.info['buffer_size_sec'] = np.float64(2.) raw.info['lowpass'] = 200. del raw.info['maxshield'] del raw.info['hpi_results'][0]['moments'] del raw.info['hpi_subsystem']['event_channel'] with catch_logging() as log: filter_chpi(raw, verbose=True) assert_true('2 cHPI' in log.getvalue())
def test_head_translation(): """Test Maxwell filter head translation""" with warnings.catch_warnings(record=True): # maxshield raw = Raw(raw_fname, allow_maxshield=True).crop(0., 1., False) # First try with an unchanged destination raw_sss = maxwell_filter(raw, destination=raw_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore') assert_meg_snr(raw_sss, Raw(sss_std_fname).crop(0., 1., False), 200.) # Now with default with warnings.catch_warnings(record=True): with catch_logging() as log: raw_sss = maxwell_filter(raw, destination=mf_head_origin, origin=mf_head_origin, regularize=None, bad_condition='ignore', verbose='warning') assert_true('over 25 mm' in log.getvalue()) assert_meg_snr(raw_sss, Raw(sss_trans_default_fname), 125.) destination = np.eye(4) destination[2, 3] = 0.04 assert_allclose(raw_sss.info['dev_head_t']['trans'], destination) # Now to sample's head pos with warnings.catch_warnings(record=True): with catch_logging() as log: raw_sss = maxwell_filter(raw, destination=sample_fname, origin=mf_head_origin, regularize=None, bad_condition='ignore', verbose='warning') assert_true('= 25.6 mm' in log.getvalue()) assert_meg_snr(raw_sss, Raw(sss_trans_sample_fname), 350.) assert_allclose(raw_sss.info['dev_head_t']['trans'], read_info(sample_fname)['dev_head_t']['trans']) # Degenerate cases assert_raises(RuntimeError, maxwell_filter, raw, destination=mf_head_origin, coord_frame='meg') assert_raises(ValueError, maxwell_filter, raw, destination=[0.] * 4)
def test_calculate_chpi_positions(): """Test calculation of cHPI positions.""" # Check to make sure our fits match MF decently mf_quats = read_head_pos(pos_fname) raw = read_raw_fif(chpi_fif_fname, allow_maxshield='yes', preload=True) # This is a little hack (aliasing while decimating) to make it much faster # for testing purposes only. We can relax this later if we find it breaks # something. raw_dec = _decimate_chpi(raw, 15) with catch_logging() as log: py_quats = _calculate_chpi_positions(raw_dec, t_step_max=1., verbose='debug') assert_true(log.getvalue().startswith('HPIFIT')) _assert_quats(py_quats, mf_quats, dist_tol=0.004, angle_tol=2.5) # degenerate conditions raw_no_chpi = read_raw_fif(test_fif_fname) assert_raises(RuntimeError, _calculate_chpi_positions, raw_no_chpi) raw_bad = raw.copy() del raw_bad.info['hpi_meas'][0]['hpi_coils'][0]['coil_freq'] assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['coord_frame'] = FIFF.FIFFV_COORD_UNKNOWN break assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['coord_frame'] = FIFF.FIFFV_COORD_HEAD d['r'] = np.ones(3) raw_bad.crop(0, 1.) picks = np.concatenate([np.arange(306, len(raw_bad.ch_names)), pick_types(raw_bad.info, meg=True)[::16]]) raw_bad.pick_channels([raw_bad.ch_names[pick] for pick in picks]) with warnings.catch_warnings(record=True): # bad pos with catch_logging() as log_file: _calculate_chpi_positions(raw_bad, t_step_min=1., verbose=True) # ignore HPI info header and [done] footer assert_true('0/5 good' in log_file.getvalue().strip().split('\n')[-2]) # half the rate cuts off cHPI coils raw.info['lowpass'] /= 2. assert_raises_regex(RuntimeError, 'above the', _calculate_chpi_positions, raw) # test on 5k artemis data raw = read_raw_artemis123(art_fname, preload=True) mf_quats = read_head_pos(art_mc_fname) with catch_logging() as log: py_quats = _calculate_chpi_positions(raw, t_step_min=2., verbose='debug') _assert_quats(py_quats, mf_quats, dist_tol=0.004, angle_tol=2.5)
def test_manifest_check_download(tmpdir, n_have, monkeypatch): """Test our manifest downloader.""" monkeypatch.setattr(datasets.utils, '_fetch_file', _fake_zip_fetch) destination = op.join(str(tmpdir), 'empty') manifest_path = op.join(str(tmpdir), 'manifest.txt') with open(manifest_path, 'w') as fid: for fname in _zip_fnames: fid.write('%s\n' % fname) assert n_have in range(len(_zip_fnames) + 1) assert not op.isdir(destination) if n_have > 0: os.makedirs(op.join(destination, 'foo')) assert op.isdir(op.join(destination, 'foo')) for fname in _zip_fnames: assert not op.isfile(op.join(destination, fname)) for fname in _zip_fnames[:n_have]: with open(op.join(destination, fname), 'w'): pass with catch_logging() as log: with use_log_level(True): url = hash_ = '' # we mock the _fetch_file so these are not used _manifest_check_download(manifest_path, destination, url, hash_) log = log.getvalue() n_missing = 3 - n_have assert ('%d file%s missing from' % (n_missing, _pl(n_missing))) in log for want in ('Extracting missing', 'Successfully '): if n_missing > 0: assert want in log else: assert want not in log assert op.isdir(destination) for fname in _zip_fnames: assert op.isfile(op.join(destination, fname))
def test_helmet(): """Test loading helmet surfaces.""" base_dir = op.join(op.dirname(__file__), '..', 'io') fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif') fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data', 'test_bin_raw.fif') fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data', 'exported4D_linux_raw.fif') fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif') fname_trans = op.join(base_dir, 'tests', 'data', 'sample-audvis-raw-trans.txt') trans = _get_trans(fname_trans)[0] new_info = read_info(fname_raw) artemis_info = new_info.copy() for pick in pick_types(new_info): new_info['chs'][pick]['coil_type'] = 9999 artemis_info['chs'][pick]['coil_type'] = \ FIFF.FIFFV_COIL_ARTEMIS123_GRAD for info, n, name in [(read_info(fname_raw), 304, '306m'), (read_info(fname_kit_raw), 304, 'KIT'), (read_info(fname_bti_raw), 304, 'Magnes'), (read_info(fname_ctf_raw), 342, 'CTF'), (new_info, 102, 'unknown'), (artemis_info, 102, 'ARTEMIS123') ]: with catch_logging() as log: helmet = get_meg_helmet_surf(info, trans, verbose=True) log = log.getvalue() assert name in log assert_equal(len(helmet['rr']), n) assert_equal(len(helmet['rr']), len(helmet['nn']))
def test_calculate_chpi_positions(): """Test calculation of cHPI positions """ trans, rot, t = get_chpi_positions(pos_fname) with warnings.catch_warnings(record=True): raw = Raw(raw_fif_fname, allow_maxshield=True, preload=True) t -= raw.first_samp / raw.info['sfreq'] trans_est, rot_est, t_est = _calculate_chpi_positions(raw, verbose='debug') _compare_positions((trans, rot, t), (trans_est, rot_est, t_est)) # degenerate conditions raw_no_chpi = Raw(test_fif_fname) assert_raises(RuntimeError, _calculate_chpi_positions, raw_no_chpi) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['coord_frame'] = 999 break assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['r'] = np.ones(3) raw_bad.crop(0, 1., copy=False) with catch_logging() as log_file: _calculate_chpi_positions(raw_bad) for line in log_file.getvalue().split('\n')[:-1]: assert_true('0/5 acceptable' in line)
def test_notch_filters(): """Test notch filters """ # let's use an ugly, prime sfreq for fun sfreq = 487.0 sig_len_secs = 20 t = np.arange(0, int(sig_len_secs * sfreq)) / sfreq freqs = np.arange(60, 241, 60) # make a "signal" rng = np.random.RandomState(0) a = rng.randn(int(sig_len_secs * sfreq)) orig_power = np.sqrt(np.mean(a ** 2)) # make line noise a += np.sum([np.sin(2 * np.pi * f * t) for f in freqs], axis=0) # only allow None line_freqs with 'spectrum_fit' mode assert_raises(ValueError, notch_filter, a, sfreq, None, "fft") assert_raises(ValueError, notch_filter, a, sfreq, None, "iir") methods = ["spectrum_fit", "spectrum_fit", "fft", "fft", "iir"] filter_lengths = [None, None, None, 8192, None] line_freqs = [None, freqs, freqs, freqs, freqs] tols = [2, 1, 1, 1] for meth, lf, fl, tol in zip(methods, line_freqs, filter_lengths, tols): with catch_logging() as log_file: b = notch_filter(a, sfreq, lf, filter_length=fl, method=meth, verbose="INFO") if lf is None: out = log_file.getvalue().split("\n")[:-1] if len(out) != 2: raise ValueError("Detected frequencies not logged properly") out = np.fromstring(out[1], sep=", ") assert_array_almost_equal(out, freqs) new_power = np.sqrt(sum_squared(b) / b.size) assert_almost_equal(new_power, orig_power, tol)
def test_cache_dir(): """Test use of cache dir """ tempdir = _TempDir() orig_dir = os.getenv('MNE_CACHE_DIR', None) orig_size = os.getenv('MNE_MEMMAP_MIN_SIZE', None) rng = np.random.RandomState(0) X = rng.randn(9, 2, 10) try: os.environ['MNE_MEMMAP_MIN_SIZE'] = '1K' os.environ['MNE_CACHE_DIR'] = tempdir # Fix error for #1507: in-place when memmapping with catch_logging() as log_file: permutation_cluster_1samp_test( X, buffer_size=None, n_jobs=2, n_permutations=1, seed=0, stat_fun=ttest_1samp_no_p, verbose=False) # ensure that non-independence yields warning stat_fun = partial(ttest_1samp_no_p, sigma=1e-3) assert_true('independently' not in log_file.getvalue()) with warnings.catch_warnings(record=True): # independently permutation_cluster_1samp_test( X, buffer_size=10, n_jobs=2, n_permutations=1, seed=0, stat_fun=stat_fun, verbose=False) assert_true('independently' in log_file.getvalue()) finally: if orig_dir is not None: os.environ['MNE_CACHE_DIR'] = orig_dir else: del os.environ['MNE_CACHE_DIR'] if orig_size is not None: os.environ['MNE_MEMMAP_MIN_SIZE'] = orig_size else: del os.environ['MNE_MEMMAP_MIN_SIZE']
def test_calculate_chpi_positions(): """Test calculation of cHPI positions """ trans, rot, t = head_pos_to_trans_rot_t(read_head_pos(pos_fname)) raw = Raw(chpi_fif_fname, allow_maxshield="yes", preload=True) t -= raw.first_samp / raw.info["sfreq"] quats = _calculate_chpi_positions(raw, verbose="debug") trans_est, rot_est, t_est = head_pos_to_trans_rot_t(quats) _compare_positions((trans, rot, t), (trans_est, rot_est, t_est), 0.003) # degenerate conditions raw_no_chpi = Raw(test_fif_fname) assert_raises(RuntimeError, _calculate_chpi_positions, raw_no_chpi) raw_bad = raw.copy() for d in raw_bad.info["dig"]: if d["kind"] == FIFF.FIFFV_POINT_HPI: d["coord_frame"] = 999 break assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) raw_bad = raw.copy() for d in raw_bad.info["dig"]: if d["kind"] == FIFF.FIFFV_POINT_HPI: d["r"] = np.ones(3) raw_bad.crop(0, 1.0, copy=False) with warnings.catch_warnings(record=True): # bad pos with catch_logging() as log_file: _calculate_chpi_positions(raw_bad, verbose=True) # ignore HPI info header and [done] footer for line in log_file.getvalue().strip().split("\n")[4:-1]: assert_true("0/5 good" in line) # half the rate cuts off cHPI coils with warnings.catch_warnings(record=True): # uint cast suggestion raw.resample(300.0, npad="auto") assert_raises_regex(RuntimeError, "above the", _calculate_chpi_positions, raw)
def test_notch_filters(): """Test notch filters.""" # let's use an ugly, prime sfreq for fun sfreq = 487.0 sig_len_secs = 20 t = np.arange(0, int(sig_len_secs * sfreq)) / sfreq freqs = np.arange(60, 241, 60) # make a "signal" a = rng.randn(int(sig_len_secs * sfreq)) orig_power = np.sqrt(np.mean(a ** 2)) # make line noise a += np.sum([np.sin(2 * np.pi * f * t) for f in freqs], axis=0) # only allow None line_freqs with 'spectrum_fit' mode assert_raises(ValueError, notch_filter, a, sfreq, None, 'fft') assert_raises(ValueError, notch_filter, a, sfreq, None, 'iir') methods = ['spectrum_fit', 'spectrum_fit', 'fft', 'fft', 'iir'] filter_lengths = ['auto', 'auto', 'auto', 8192, 'auto'] line_freqs = [None, freqs, freqs, freqs, freqs] tols = [2, 1, 1, 1] for meth, lf, fl, tol in zip(methods, line_freqs, filter_lengths, tols): with catch_logging() as log_file: with warnings.catch_warnings(record=True): b = notch_filter(a, sfreq, lf, fl, method=meth, verbose=True) if lf is None: out = log_file.getvalue().split('\n')[:-1] if len(out) != 2 and len(out) != 3: # force_serial: len(out) == 3 raise ValueError('Detected frequencies not logged properly') out = np.fromstring(out[-1], sep=', ') assert_array_almost_equal(out, freqs) new_power = np.sqrt(sum_squared(b) / b.size) assert_almost_equal(new_power, orig_power, tol)
def test_check_compensation_consistency(): """Test check picks compensation.""" raw = read_raw_ctf(ctf_fname, preload=False) events = make_fixed_length_events(raw, 99999) picks = pick_types(raw.info, meg=True, exclude=[], ref_meg=True) pick_ch_names = [raw.info['ch_names'][idx] for idx in picks] for (comp, expected_result) in zip([0, 1], [False, False]): raw.apply_gradient_compensation(comp) ret, missing = _bad_chans_comp(raw.info, pick_ch_names) assert ret == expected_result assert len(missing) == 0 Epochs(raw, events, None, -0.2, 0.2, preload=False, picks=picks) picks = pick_types(raw.info, meg=True, exclude=[], ref_meg=False) pick_ch_names = [raw.info['ch_names'][idx] for idx in picks] for (comp, expected_result) in zip([0, 1], [False, True]): raw.apply_gradient_compensation(comp) ret, missing = _bad_chans_comp(raw.info, pick_ch_names) assert ret == expected_result assert len(missing) == 17 with catch_logging() as log: Epochs(raw, events, None, -0.2, 0.2, preload=False, picks=picks, verbose=True) assert'Removing 5 compensators' in log.getvalue()
def test_cuda(): """Test CUDA-based filtering""" # NOTE: don't make test_cuda() the last test, or pycuda might spew # some warnings about clean-up failing # Also, using `n_jobs='cuda'` on a non-CUDA system should be fine, # as it should fall back to using n_jobs=1. sfreq = 500 sig_len_secs = 20 a = rng.randn(sig_len_secs * sfreq) with catch_logging() as log_file: for fl in ['auto', '10s', 2048]: bp = band_pass_filter(a, sfreq, 4, 8, fl, 1.0, 1.0, n_jobs=1, phase='zero') bs = band_stop_filter(a, sfreq, 4 - 1.0, 8 + 1.0, fl, 1.0, 1.0, n_jobs=1, phase='zero') lp = low_pass_filter(a, sfreq, 8, fl, 1.0, n_jobs=1, phase='zero') hp = high_pass_filter(lp, sfreq, 4, fl, 1.0, n_jobs=1, phase='zero') bp_c = band_pass_filter(a, sfreq, 4, 8, fl, 1.0, 1.0, n_jobs='cuda', verbose='INFO', phase='zero') bs_c = band_stop_filter(a, sfreq, 4 - 1.0, 8 + 1.0, fl, 1.0, 1.0, n_jobs='cuda', verbose='INFO', phase='zero') lp_c = low_pass_filter(a, sfreq, 8, fl, 1.0, n_jobs='cuda', verbose='INFO', phase='zero') hp_c = high_pass_filter(lp, sfreq, 4, fl, 1.0, n_jobs='cuda', verbose='INFO', phase='zero') assert_array_almost_equal(bp, bp_c, 12) assert_array_almost_equal(bs, bs_c, 12) assert_array_almost_equal(lp, lp_c, 12) assert_array_almost_equal(hp, hp_c, 12) # check to make sure we actually used CUDA out = log_file.getvalue().split('\n')[:-1] # triage based on whether or not we actually expected to use CUDA from mne.cuda import _cuda_capable # allow above funs to set it tot = 12 if _cuda_capable else 0 assert_true(sum(['Using CUDA for FFT FIR filtering' in o for o in out]) == tot) # check resampling for window in ('boxcar', 'triang'): for N in (997, 1000): # one prime, one even a = rng.randn(2, N) for fro, to in ((1, 2), (2, 1), (1, 3), (3, 1)): a1 = resample(a, fro, to, n_jobs=1, npad='auto', window=window) a2 = resample(a, fro, to, n_jobs='cuda', npad='auto', window=window) assert_allclose(a1, a2, rtol=1e-7, atol=1e-14) assert_array_almost_equal(a1, a2, 14) assert_array_equal(resample([0, 0], 2, 1, n_jobs='cuda'), [0., 0., 0., 0.]) assert_array_equal(resample(np.zeros(2, np.float32), 2, 1, n_jobs='cuda'), [0., 0., 0., 0.])
def test_make_sphere_model(): """Test making a sphere model.""" info = read_info(fname_raw) pytest.raises(ValueError, make_sphere_model, 'foo', 'auto', info) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', None) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(), sigmas=()) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(1,)) # wrong number of radii # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code with catch_logging() as log: bem = make_sphere_model('auto', 'auto', info, verbose=True) log = log.getvalue() assert ' RV = ' in log for line in log.split('\n'): if ' RV = ' in line: val = float(line.split()[-2]) assert val < 0.01 # actually decent fitting break assert '3 layers' in repr(bem) assert 'Sphere ' in repr(bem) assert ' mm' in repr(bem) bem = make_sphere_model('auto', None, info) assert 'no layers' in repr(bem) assert 'Sphere ' in repr(bem) pytest.raises(ValueError, make_sphere_model, sigmas=(0.33,), relative_radii=(1.0,))
def test_calculate_chpi_positions(): """Test calculation of cHPI positions.""" trans, rot, t = head_pos_to_trans_rot_t(read_head_pos(pos_fname)) raw = read_raw_fif(chpi_fif_fname, allow_maxshield='yes', preload=True, add_eeg_ref=False) t -= raw.first_samp / raw.info['sfreq'] quats = _calculate_chpi_positions(raw, verbose='debug') trans_est, rot_est, t_est = head_pos_to_trans_rot_t(quats) _compare_positions((trans, rot, t), (trans_est, rot_est, t_est), 0.003) # degenerate conditions raw_no_chpi = read_raw_fif(test_fif_fname, add_eeg_ref=False) assert_raises(RuntimeError, _calculate_chpi_positions, raw_no_chpi) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['coord_frame'] = 999 break assert_raises(RuntimeError, _calculate_chpi_positions, raw_bad) raw_bad = raw.copy() for d in raw_bad.info['dig']: if d['kind'] == FIFF.FIFFV_POINT_HPI: d['r'] = np.ones(3) raw_bad.crop(0, 1., copy=False) with warnings.catch_warnings(record=True): # bad pos with catch_logging() as log_file: _calculate_chpi_positions(raw_bad, verbose=True) # ignore HPI info header and [done] footer assert_true('0/5 good' in log_file.getvalue().strip().split('\n')[-2]) # half the rate cuts off cHPI coils with warnings.catch_warnings(record=True): # uint cast suggestion raw.resample(300., npad='auto') assert_raises_regex(RuntimeError, 'above the', _calculate_chpi_positions, raw)
def test_reporting_fir(phase, fir_window, btype): """Test FIR filter reporting.""" l_freq = 1. if btype == 'bandpass' else None fs = 1000. with catch_logging() as log: x = create_filter(None, fs, l_freq, 40, method='fir', phase=phase, fir_window=fir_window, verbose=True) n_taps = len(x) log = log.getvalue() keys = ['FIR', btype, fir_window.capitalize(), 'Filter length: %d samples' % (n_taps,), 'passband ripple', 'stopband attenuation', ] if phase == 'minimum': keys += [' causal '] else: keys += [' non-causal ', ' dB cutoff frequency: 45.00 Hz'] if btype == 'bandpass': keys += [' dB cutoff frequency: 0.50 Hz'] for key in keys: assert key in log if phase == 'zero': assert '-6 dB cutoff' in log elif phase == 'zero-double': assert '-12 dB cutoff' in log else: # XXX Eventually we should figure out where the resulting point is, # since the minimum-phase process will change it. For now we don't # report it. assert phase == 'minimum' # Verify some of the filter properties if phase == 'zero-double': x = np.convolve(x, x) # effectively what happens w, h = freqz(x, worN=10000) w *= fs / (2 * np.pi) h = np.abs(h) # passband passes = [np.argmin(np.abs(w - f)) for f in (1, 20, 40)] # stopband stops = [np.argmin(np.abs(w - 50.))] # transition mids = [np.argmin(np.abs(w - 45.))] # put these where they belong based on filter type assert w[0] == 0. idx_0 = 0 idx_0p5 = np.argmin(np.abs(w - 0.5)) if btype == 'bandpass': stops += [idx_0] mids += [idx_0p5] else: passes += [idx_0, idx_0p5] assert_allclose(h[passes], 1., atol=0.01) attenuation = -20 if phase == 'minimum' else -50 assert_allclose(h[stops], 0., atol=10 ** (attenuation / 20.)) if phase != 'minimum': # haven't worked out the math for this yet expected = 0.25 if phase == 'zero-double' else 0.5 assert_allclose(h[mids], expected, atol=0.01)
def test_inverse_residual(): """Test MNE inverse application.""" # use fname_inv as it will be faster than fname_full (fewer verts and chs) evoked = _get_evoked().pick_types() inv = read_inverse_operator(fname_inv_fixed_depth) fwd = read_forward_solution(fname_fwd) fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True) fwd = pick_channels_forward(fwd, evoked.ch_names) matcher = re.compile(r'.* ([0-9]?[0-9]?[0-9]?\.[0-9])% variance.*') for method in ('MNE', 'dSPM', 'sLORETA'): with catch_logging() as log: stc, residual = apply_inverse( evoked, inv, method=method, return_residual=True, verbose=True) log = log.getvalue() match = matcher.match(log.replace('\n', ' ')) assert match is not None match = float(match.group(1)) assert 45 < match < 50 if method == 'MNE': # must be first! recon = apply_forward(fwd, stc, evoked.info) proj_op = make_projector(evoked.info['projs'], evoked.ch_names)[0] recon.data[:] = np.dot(proj_op, recon.data) residual_fwd = evoked.copy() residual_fwd.data -= recon.data corr = np.corrcoef(residual_fwd.data.ravel(), residual.data.ravel())[0, 1] assert corr > 0.999 with catch_logging() as log: _, residual = apply_inverse( evoked, inv, 0., 'MNE', return_residual=True, verbose=True) log = log.getvalue() match = matcher.match(log.replace('\n', ' ')) assert match is not None match = float(match.group(1)) assert match == 100. assert_array_less(np.abs(residual.data), 1e-15) # Degenerate: we don't have the right representation for eLORETA for this with pytest.raises(ValueError, match='eLORETA does not .* support .*'): apply_inverse(evoked, inv, method="eLORETA", return_residual=True)
def test_inverse_operator_channel_ordering(evoked, noise_cov): """Test MNE inverse computation is immune to channel reorderings.""" # These are with original ordering evoked_orig = evoked.copy() fwd_orig = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_orig = convert_forward_solution(fwd_orig, surf_ori=True) depth = dict(exp=0.8, limit_depth_chs=False) with catch_logging() as log: inv_orig = make_inverse_operator(evoked.info, fwd_orig, noise_cov, loose=0.2, depth=depth, verbose=True) log = log.getvalue() assert 'limit = 1/%s' % fwd_orig['nsource'] in log stc_1 = apply_inverse(evoked, inv_orig, lambda2, "dSPM") # Assume that a raw reordering applies to both evoked and noise_cov, # so we don't need to create those from scratch. Just reorder them, # then try to apply the original inverse operator new_order = np.arange(len(evoked.info['ch_names'])) randomiser = np.random.RandomState(42) randomiser.shuffle(new_order) evoked.data = evoked.data[new_order] evoked.info['chs'] = [evoked.info['chs'][n] for n in new_order] evoked.info._update_redundant() evoked.info._check_consistency() cov_ch_reorder = [c for c in evoked.info['ch_names'] if (c in noise_cov.ch_names)] new_order_cov = [noise_cov.ch_names.index(name) for name in cov_ch_reorder] noise_cov['data'] = noise_cov.data[np.ix_(new_order_cov, new_order_cov)] noise_cov['names'] = [noise_cov['names'][idx] for idx in new_order_cov] fwd_reorder = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_reorder = convert_forward_solution(fwd_reorder, surf_ori=True) inv_reorder = make_inverse_operator(evoked.info, fwd_reorder, noise_cov, loose=0.2, depth=depth) stc_2 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_equal(stc_1.subject, stc_2.subject) assert_array_equal(stc_1.times, stc_2.times) assert_allclose(stc_1.data, stc_2.data, rtol=1e-5, atol=1e-5) assert (inv_orig['units'] == inv_reorder['units']) # Reload with original ordering & apply reordered inverse evoked = evoked_orig noise_cov = read_cov(fname_cov) stc_3 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_allclose(stc_1.data, stc_3.data, rtol=1e-5, atol=1e-5)
def test_cuda(): """Test CUDA-based filtering """ # NOTE: don't make test_cuda() the last test, or pycuda might spew # some warnings about clean-up failing # Also, using `n_jobs='cuda'` on a non-CUDA system should be fine, # as it should fall back to using n_jobs=1. sfreq = 500 sig_len_secs = 20 a = rng.randn(sig_len_secs * sfreq) with catch_logging() as log_file: for fl in ['10s', None, 2048]: bp = band_pass_filter(a, sfreq, 4, 8, n_jobs=1, filter_length=fl) bs = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, n_jobs=1, filter_length=fl) lp = low_pass_filter(a, sfreq, 8, n_jobs=1, filter_length=fl) hp = high_pass_filter(lp, sfreq, 4, n_jobs=1, filter_length=fl) bp_c = band_pass_filter(a, sfreq, 4, 8, n_jobs='cuda', filter_length=fl, verbose='INFO') bs_c = band_stop_filter(a, sfreq, 4 - 0.5, 8 + 0.5, n_jobs='cuda', filter_length=fl, verbose='INFO') lp_c = low_pass_filter(a, sfreq, 8, n_jobs='cuda', filter_length=fl, verbose='INFO') hp_c = high_pass_filter(lp, sfreq, 4, n_jobs='cuda', filter_length=fl, verbose='INFO') assert_array_almost_equal(bp, bp_c, 12) assert_array_almost_equal(bs, bs_c, 12) assert_array_almost_equal(lp, lp_c, 12) assert_array_almost_equal(hp, hp_c, 12) # check to make sure we actually used CUDA out = log_file.getvalue().split('\n')[:-1] # triage based on whether or not we actually expected to use CUDA from mne.cuda import _cuda_capable # allow above funs to set it tot = 12 if _cuda_capable else 0 assert_true(sum(['Using CUDA for FFT FIR filtering' in o for o in out]) == tot) # check resampling a = rng.randn(3, sig_len_secs * sfreq) a1 = resample(a, 1, 2, n_jobs=2, npad=0) a2 = resample(a, 1, 2, n_jobs='cuda', npad=0) a3 = resample(a, 2, 1, n_jobs=2, npad=0) a4 = resample(a, 2, 1, n_jobs='cuda', npad=0) assert_array_almost_equal(a3, a4, 14) assert_array_almost_equal(a1, a2, 14) assert_array_equal(resample([0, 0], 2, 1, n_jobs='cuda'), [0., 0., 0., 0.]) assert_array_equal(resample(np.zeros(2, np.float32), 2, 1, n_jobs='cuda'), [0., 0., 0., 0.])
def test_get_data_reject(): """Test if reject_by_annotation is working correctly.""" fs = 256 ch_names = ["C3", "Cz", "C4"] info = create_info(ch_names, sfreq=fs) raw = RawArray(np.zeros((len(ch_names), 10 * fs)), info) raw.set_annotations(Annotations(onset=[2, 4], duration=[3, 2], description="bad")) with catch_logging() as log: data = raw.get_data(reject_by_annotation="omit", verbose=True) msg = ('Omitting 1024 of 2560 (40.00%) samples, retaining 1536' + ' (60.00%) samples.') assert log.getvalue().strip() == msg assert data.shape == (len(ch_names), 1536) with catch_logging() as log: data = raw.get_data(reject_by_annotation="nan", verbose=True) msg = ('Setting 1024 of 2560 (40.00%) samples to NaN, retaining 1536' + ' (60.00%) samples.') assert log.getvalue().strip() == msg assert data.shape == (len(ch_names), 2560) # shape doesn't change assert np.isnan(data).sum() == 3072 # but NaNs are introduced instead
def test_cache_dir(tmpdir, numba_conditional): """Test use of cache dir.""" tempdir = str(tmpdir) orig_dir = os.getenv('MNE_CACHE_DIR', None) orig_size = os.getenv('MNE_MEMMAP_MIN_SIZE', None) rng = np.random.RandomState(0) X = rng.randn(9, 2, 10) try: os.environ['MNE_MEMMAP_MIN_SIZE'] = '1K' os.environ['MNE_CACHE_DIR'] = tempdir # Fix error for #1507: in-place when memmapping with catch_logging() as log_file: permutation_cluster_1samp_test(X, buffer_size=None, n_jobs=2, n_permutations=1, seed=0, stat_fun=ttest_1samp_no_p, verbose=False, out_type='mask') assert 'independently' not in log_file.getvalue() # ensure that non-independence yields warning stat_fun = partial(ttest_1samp_no_p, sigma=1e-3) if check_version('numpy', '1.17'): random_state = np.random.default_rng(0) else: random_state = 0 with pytest.warns(RuntimeWarning, match='independently'): permutation_cluster_1samp_test(X, buffer_size=10, n_jobs=2, n_permutations=1, seed=random_state, stat_fun=stat_fun, verbose=False, out_type='mask') finally: if orig_dir is not None: os.environ['MNE_CACHE_DIR'] = orig_dir else: del os.environ['MNE_CACHE_DIR'] if orig_size is not None: os.environ['MNE_MEMMAP_MIN_SIZE'] = orig_size else: del os.environ['MNE_MEMMAP_MIN_SIZE']
def test_make_inverse_operator_fixed(): """Test MNE inverse computation (fixed orientation).""" fwd = read_forward_solution_meg(fname_fwd) evoked = _get_evoked() noise_cov = read_cov(fname_cov) # can't make fixed inv with depth weighting without free ori fwd fwd_fixed = convert_forward_solution(fwd, force_fixed=True, use_cps=True) pytest.raises(ValueError, make_inverse_operator, evoked.info, fwd_fixed, noise_cov, depth=0.8, fixed=True) # now compare to C solution # note that the forward solution must not be surface-oriented # to get equivalency (surf_ori=True changes the normals) with catch_logging() as log: inv_op = make_inverse_operator( # test depth=0. alias for depth=None evoked.info, fwd, noise_cov, depth=0., fixed=True, use_cps=False, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log assert 'EEG channels: 0' in repr(inv_op) assert 'MEG channels: 305' in repr(inv_op) del fwd_fixed inverse_operator_nodepth = read_inverse_operator(fname_inv_fixed_nodepth) # XXX We should have this but we don't (MNE-C doesn't restrict info): # assert 'EEG channels: 0' in repr(inverse_operator_nodepth) assert 'MEG channels: 305' in repr(inverse_operator_nodepth) _compare_inverses_approx(inverse_operator_nodepth, inv_op, evoked, rtol=1e-5, atol=1e-4) # Inverse has 306 channels - 6 proj = 302 assert (compute_rank_inverse(inverse_operator_nodepth) == 302) # Now with depth fwd_surf = convert_forward_solution(fwd, surf_ori=True) # not fixed for kwargs, use_fwd in zip([dict(fixed=True), dict(loose=0.)], [fwd, fwd_surf]): # Should be equiv. inv_op_depth = make_inverse_operator( evoked.info, use_fwd, noise_cov, depth=0.8, use_cps=True, **kwargs) inverse_operator_depth = read_inverse_operator(fname_inv_fixed_depth) # Normals should be the adjusted ones assert_allclose(inverse_operator_depth['source_nn'], fwd_surf['source_nn'][2::3], atol=1e-5) _compare_inverses_approx(inverse_operator_depth, inv_op_depth, evoked, rtol=1e-3, atol=1e-4)
def test_plot_volume_source_estimates(mode, stype, init_t, want_t, init_p, want_p, bg_img): """Test interactive plotting of volume source estimates.""" forward = read_forward_solution(fwd_fname) sample_src = forward['src'] if init_p is not None: init_p = np.array(init_p) / 1000. vertices = [s['vertno'] for s in sample_src] n_verts = sum(len(v) for v in vertices) n_time = 2 data = np.random.RandomState(0).rand(n_verts, n_time) if stype == 'vec': stc = VolVectorSourceEstimate(np.tile(data[:, np.newaxis], (1, 3, 1)), vertices, 1, 1) else: assert stype == 's' stc = VolSourceEstimate(data, vertices, 1, 1) with pytest.warns(None): # sometimes get scalars/index warning with catch_logging() as log: fig = stc.plot(sample_src, subject='sample', subjects_dir=subjects_dir, mode=mode, initial_time=init_t, initial_pos=init_p, bg_img=bg_img, verbose=True) log = log.getvalue() want_str = 't = %0.3f s' % want_t assert want_str in log, (want_str, init_t) want_str = '(%0.1f, %0.1f, %0.1f) mm' % want_p assert want_str in log, (want_str, init_p) for ax_idx in [0, 2, 3, 4]: _fake_click(fig, fig.axes[ax_idx], (0.3, 0.5)) fig.canvas.key_press_event('left') fig.canvas.key_press_event('shift+right') if bg_img is not None: with pytest.raises(FileNotFoundError, match='MRI file .* not found'): stc.plot(sample_src, subject='sample', subjects_dir=subjects_dir, mode='stat_map', bg_img='junk.mgz')
def test_make_forward_solution(): """Test making M-EEG forward solution from python.""" with catch_logging() as log: fwd_py = make_forward_solution(fname_raw, fname_trans, fname_src, fname_bem, mindist=5., verbose=True) log = log.getvalue() assert 'Total 258/258 points inside the surface' in log assert (isinstance(fwd_py, Forward)) fwd = read_forward_solution(fname_meeg) assert (isinstance(fwd, Forward)) _compare_forwards(fwd, fwd_py, 366, 1494, meg_rtol=1e-3) # Homogeneous model with pytest.raises(RuntimeError, match='homogeneous.*1-layer.*EEG'): make_forward_solution(fname_raw, fname_trans, fname_src, fname_bem_meg)
def test_plot_alignment_fnirs(renderer, tmp_path): """Test fNIRS plotting.""" # Here we use subjects_dir=tmp_path, since no surfaces should actually # be loaded! # fNIRS (default is pairs) info = read_raw_nirx(nirx_fname).info assert info['nchan'] == 26 kwargs = dict(trans='fsaverage', subject='fsaverage', surfaces=(), verbose=True, subjects_dir=tmp_path) with catch_logging() as log: fig = plot_alignment(info, **kwargs) log = log.getvalue() assert f'fnirs_cw_amplitude: {info["nchan"]}' in log _assert_n_actors(fig, renderer, info['nchan']) fig = plot_alignment( info, fnirs=['channels', 'sources', 'detectors'], **kwargs) _assert_n_actors(fig, renderer, 3)
def test_add_noise(): """Test noise addition.""" rng = np.random.RandomState(0) raw = read_raw_fif(raw_fname) raw.del_proj() picks = pick_types(raw.info, eeg=True, exclude=()) cov = compute_raw_covariance(raw, picks=picks) with pytest.raises(RuntimeError, match='to be loaded'): add_noise(raw, cov) raw.crop(0, 1).load_data() with pytest.raises(TypeError, match='Raw, Epochs, or Evoked'): add_noise(0., cov) with pytest.raises(TypeError, match='Covariance'): add_noise(raw, 0.) # test a no-op (data preserved) orig_data = raw[:][0] zero_cov = cov.copy() zero_cov['data'].fill(0) add_noise(raw, zero_cov) new_data = raw[:][0] assert_allclose(orig_data, new_data, atol=1e-30) # set to zero to make comparisons easier raw._data[:] = 0. epochs = EpochsArray(np.zeros((1, len(raw.ch_names), 100)), raw.info.copy()) epochs.info['bads'] = [] evoked = epochs.average(picks=np.arange(len(raw.ch_names))) for inst in (raw, epochs, evoked): with catch_logging() as log: add_noise(inst, cov, random_state=rng, verbose=True) log = log.getvalue() want = ('to {0}/{1} channels ({0}'.format(len(cov['names']), len(raw.ch_names))) assert want in log if inst is evoked: inst = EpochsArray(inst.data[np.newaxis], inst.info) if inst is raw: cov_new = compute_raw_covariance(inst, picks=picks) else: cov_new = compute_covariance(inst) assert cov['names'] == cov_new['names'] r = np.corrcoef(cov['data'].ravel(), cov_new['data'].ravel())[0, 1] assert r > 0.99
def test_non_convergence(): """Test non-convergence of MxNE solver to catch unexpected bugs.""" n, p, t, alpha = 30, 40, 20, 1. rng = np.random.RandomState(0) G = rng.randn(n, p) G /= np.std(G, axis=0)[None, :] X = np.zeros((p, t)) X[0] = 3 X[4] = -2 M = np.dot(G, X) # Impossible to converge with only 1 iteration and tol 1e-12 # In case of non-convegence, we test that no error is returned. args = (M, G, alpha, 1, 1e-12) with catch_logging() as log: mixed_norm_solver(*args, active_set_size=None, debias=True, solver='bcd', verbose=True) log = log.getvalue() assert 'Convergence reached' not in log
def test_make_morph_maps(): """Test reading and creating morph maps.""" # make a new fake subjects_dir tempdir = _TempDir() for subject in ('sample', 'sample_ds', 'fsaverage_ds'): os.mkdir(op.join(tempdir, subject)) os.mkdir(op.join(tempdir, subject, 'surf')) regs = ('reg', 'left_right') if subject == 'fsaverage_ds' else ('reg', ) for hemi in ['lh', 'rh']: for reg in regs: args = [subject, 'surf', hemi + '.sphere.' + reg] copyfile(op.join(subjects_dir, *args), op.join(tempdir, *args)) for subject_from, subject_to, xhemi in (('fsaverage_ds', 'sample_ds', False), ('fsaverage_ds', 'fsaverage_ds', True)): # trigger the creation of morph-maps dir and create the map with catch_logging() as log: mmap = read_morph_map(subject_from, subject_to, tempdir, xhemi=xhemi, verbose=True) log = log.getvalue() assert 'does not exist' in log assert 'Creating' in log mmap2 = read_morph_map(subject_from, subject_to, subjects_dir, xhemi=xhemi) assert_equal(len(mmap), len(mmap2)) for m1, m2 in zip(mmap, mmap2): # deal with sparse matrix stuff diff = (m1 - m2).data assert_allclose(diff, np.zeros_like(diff), atol=1e-3, rtol=0) # This will also trigger creation, but it's trivial with pytest.warns(None): mmap = read_morph_map('sample', 'sample', subjects_dir=tempdir) for mm in mmap: assert (mm - sparse.eye(mm.shape[0], mm.shape[0])).sum() == 0
def test_apply_function_verbose(): """Test apply function verbosity """ n_chan = 2 n_times = 3 ch_names = [str(ii) for ii in range(n_chan)] raw = RawArray(np.zeros((n_chan, n_times)), create_info(ch_names, 1., 'mag')) # test return types in both code paths (parallel / 1 job) assert_raises(TypeError, raw.apply_function, bad_1, None, None, 1) assert_raises(ValueError, raw.apply_function, bad_2, None, None, 1) assert_raises(TypeError, raw.apply_function, bad_1, None, None, 2) assert_raises(ValueError, raw.apply_function, bad_2, None, None, 2) # check our arguments with catch_logging() as sio: raw.apply_function(printer, None, None, 1, verbose=False) assert_equal(len(sio.getvalue()), 0) raw.apply_function(printer, None, None, 1, verbose=True) assert_equal(sio.getvalue().count('\n'), n_chan)
def test_apply_function_verbose(): """Test apply function verbosity.""" n_chan = 2 n_times = 3 ch_names = [str(ii) for ii in range(n_chan)] raw = RawArray(np.zeros((n_chan, n_times)), create_info(ch_names, 1., 'mag')) # test return types in both code paths (parallel / 1 job) pytest.raises(TypeError, raw.apply_function, bad_1) pytest.raises(ValueError, raw.apply_function, bad_2) pytest.raises(TypeError, raw.apply_function, bad_1, n_jobs=2) pytest.raises(ValueError, raw.apply_function, bad_2, n_jobs=2) # check our arguments with catch_logging() as sio: out = raw.apply_function(printer, verbose=False) assert len(sio.getvalue()) == 0 assert out is raw raw.apply_function(printer, verbose=True) assert sio.getvalue().count('\n') == n_chan
def test_cache_dir(): """Test use of cache dir """ tempdir = _TempDir() orig_dir = os.getenv('MNE_CACHE_DIR', None) orig_size = os.getenv('MNE_MEMMAP_MIN_SIZE', None) rng = np.random.RandomState(0) X = rng.randn(9, 2, 10) try: os.environ['MNE_MEMMAP_MIN_SIZE'] = '1K' os.environ['MNE_CACHE_DIR'] = tempdir # Fix error for #1507: in-place when memmapping with catch_logging() as log_file: permutation_cluster_1samp_test(X, buffer_size=None, n_jobs=2, n_permutations=1, seed=0, stat_fun=ttest_1samp_no_p, verbose=False) # ensure that non-independence yields warning stat_fun = partial(ttest_1samp_no_p, sigma=1e-3) assert_true('independently' not in log_file.getvalue()) with warnings.catch_warnings(record=True): # independently permutation_cluster_1samp_test(X, buffer_size=10, n_jobs=2, n_permutations=1, seed=0, stat_fun=stat_fun, verbose=False) assert_true('independently' in log_file.getvalue()) finally: if orig_dir is not None: os.environ['MNE_CACHE_DIR'] = orig_dir else: del os.environ['MNE_CACHE_DIR'] if orig_size is not None: os.environ['MNE_MEMMAP_MIN_SIZE'] = orig_size else: del os.environ['MNE_MEMMAP_MIN_SIZE']
def test_plot_volume_source_estimates_morph(): """Test interactive plotting of volume source estimates with morph.""" forward = read_forward_solution(fwd_fname) sample_src = forward['src'] vertices = [s['vertno'] for s in sample_src] n_verts = sum(len(v) for v in vertices) n_time = 2 data = np.random.RandomState(0).rand(n_verts, n_time) stc = VolSourceEstimate(data, vertices, 1, 1) sample_src[0]['subject_his_id'] = 'sample' # old src morph = compute_source_morph(sample_src, 'sample', 'fsaverage', zooms=5, subjects_dir=subjects_dir) initial_pos = (-0.05, -0.01, -0.006) # sometimes get scalars/index warning with _record_warnings(): with catch_logging() as log: stc.plot(morph, subjects_dir=subjects_dir, mode='glass_brain', initial_pos=initial_pos, verbose=True) log = log.getvalue() assert 't = 1.000 s' in log assert '(-52.0, -8.0, -7.0) mm' in log with pytest.raises(ValueError, match='Allowed values are'): stc.plot(sample_src, 'sample', subjects_dir, mode='abcd') vertices.append([]) surface_stc = SourceEstimate(data, vertices, 1, 1) with pytest.raises(TypeError, match='an instance of VolSourceEstimate'): plot_volume_source_estimates(surface_stc, sample_src, 'sample', subjects_dir) with pytest.raises(ValueError, match='Negative colormap limits'): stc.plot(sample_src, 'sample', subjects_dir, clim=dict(lims=[-1, 2, 3], kind='value'))
def test_notch_filters(): """Test notch filters""" # let's use an ugly, prime sfreq for fun sfreq = 487.0 sig_len_secs = 20 t = np.arange(0, int(sig_len_secs * sfreq)) / sfreq freqs = np.arange(60, 241, 60) # make a "signal" a = rng.randn(int(sig_len_secs * sfreq)) orig_power = np.sqrt(np.mean(a**2)) # make line noise a += np.sum([np.sin(2 * np.pi * f * t) for f in freqs], axis=0) # only allow None line_freqs with 'spectrum_fit' mode assert_raises(ValueError, notch_filter, a, sfreq, None, 'fft') assert_raises(ValueError, notch_filter, a, sfreq, None, 'iir') methods = ['spectrum_fit', 'spectrum_fit', 'fft', 'fft', 'iir'] filter_lengths = [None, None, None, 8192, None] line_freqs = [None, freqs, freqs, freqs, freqs] tols = [2, 1, 1, 1] for meth, lf, fl, tol in zip(methods, line_freqs, filter_lengths, tols): with catch_logging() as log_file: with warnings.catch_warnings(record=True): # filter_length=None b = notch_filter(a, sfreq, lf, filter_length=fl, method=meth, phase='zero', verbose=True) if lf is None: out = log_file.getvalue().split('\n')[:-1] if len(out) != 2 and len(out) != 3: # force_serial: len(out) == 3 raise ValueError('Detected frequencies not logged properly') out = np.fromstring(out[-1], sep=', ') assert_array_almost_equal(out, freqs) new_power = np.sqrt(sum_squared(b) / b.size) assert_almost_equal(new_power, orig_power, tol)
def test_cuda_fir(): """Test CUDA-based filtering.""" # Using `n_jobs='cuda'` on a non-CUDA system should be fine, # as it should fall back to using n_jobs=None. rng = np.random.RandomState(0) sfreq = 500 sig_len_secs = 20 a = rng.randn(sig_len_secs * sfreq) kwargs = dict(fir_design='firwin') with catch_logging() as log_file: for fl in ['auto', '10s', 2048]: args = [a, sfreq, 4, 8, None, fl, 1.0, 1.0] bp = filter_data(*args, **kwargs) bp_c = filter_data(*args, n_jobs='cuda', verbose='info', **kwargs) assert_array_almost_equal(bp, bp_c, 12) args = [a, sfreq, 8 + 1.0, 4 - 1.0, None, fl, 1.0, 1.0] bs = filter_data(*args, **kwargs) bs_c = filter_data(*args, n_jobs='cuda', verbose='info', **kwargs) assert_array_almost_equal(bs, bs_c, 12) args = [a, sfreq, None, 8, None, fl, 1.0] lp = filter_data(*args, **kwargs) lp_c = filter_data(*args, n_jobs='cuda', verbose='info', **kwargs) assert_array_almost_equal(lp, lp_c, 12) args = [lp, sfreq, 4, None, None, fl, 1.0] hp = filter_data(*args, **kwargs) hp_c = filter_data(*args, n_jobs='cuda', verbose='info', **kwargs) assert_array_almost_equal(hp, hp_c, 12) # check to make sure we actually used CUDA out = log_file.getvalue().split('\n')[:-1] # triage based on whether or not we actually expected to use CUDA from mne.cuda import _cuda_capable # allow above funs to set it tot = 12 if _cuda_capable else 0 assert sum(['Using CUDA for FFT FIR filtering' in o for o in out]) == tot if not _cuda_capable: pytest.skip('CUDA not enabled')
def test_make_sphere_model(): """Test making a sphere model.""" info = read_info(fname_raw) pytest.raises(ValueError, make_sphere_model, 'foo', 'auto', info) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', None) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(), sigmas=()) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(1, )) # wrong number of radii # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code with catch_logging() as log: bem = make_sphere_model('auto', 'auto', info, verbose=True) log = log.getvalue() assert ' RV = ' in log for line in log.split('\n'): if ' RV = ' in line: val = float(line.split()[-2]) assert val < 0.01 # actually decent fitting break assert '3 layers' in repr(bem) assert 'Sphere ' in repr(bem) assert ' mm' in repr(bem) bem = make_sphere_model('auto', None, info) assert 'no layers' in repr(bem) assert 'Sphere ' in repr(bem) pytest.raises(ValueError, make_sphere_model, sigmas=(0.33, ), relative_radii=(1.0, ))
def test_notch_filters(method, filter_length, line_freq, tol): """Test notch filters.""" # let's use an ugly, prime sfreq for fun rng = np.random.RandomState(0) sfreq = 487 sig_len_secs = 21 t = np.arange(0, int(round(sig_len_secs * sfreq))) / sfreq # make a "signal" a = rng.randn(int(sig_len_secs * sfreq)) orig_power = np.sqrt(np.mean(a**2)) # make line noise a += np.sum([np.sin(2 * np.pi * f * t) for f in line_freqs], axis=0) # only allow None line_freqs with 'spectrum_fit' mode pytest.raises(ValueError, notch_filter, a, sfreq, None, 'fft') pytest.raises(ValueError, notch_filter, a, sfreq, None, 'iir') if method == 'spectrum_fit' and filter_length == 'auto': ctx = pytest.deprecated_call(match='will change to 10.') else: ctx = nullcontext() with catch_logging() as log_file: with ctx: b = notch_filter(a, sfreq, line_freq, filter_length, method=method, verbose=True) if line_freq is None: out = [ line.strip().split(':')[0] for line in log_file.getvalue().split('\n') if line.startswith(' ') ] assert len(out) == 4, 'Detected frequencies not logged properly' out = np.array(out, float) assert_array_almost_equal(out, line_freqs) new_power = np.sqrt(sum_squared(b) / b.size) assert_almost_equal(new_power, orig_power, tol)
def test_make_bem_model(tmpdir, kwargs, fname): """Test BEM model creation from Python with I/O.""" fname_temp = tmpdir.join('temp-bem.fif') with catch_logging() as log: model = make_bem_model('sample', ico=2, subjects_dir=subjects_dir, verbose=True, **kwargs) log = log.getvalue() if len(kwargs.get('conductivity', (0, 0, 0))) == 1: assert 'distance' not in log else: assert re.search(r'urfaces is approximately *3\.4 mm', log) is not None assert re.search(r'inner skull CM is *0\.65 *-9\.62 *43\.85 mm', log) is not None model_c = read_bem_surfaces(fname) _compare_bem_surfaces(model, model_c) write_bem_surfaces(fname_temp, model) model_read = read_bem_surfaces(fname_temp) _compare_bem_surfaces(model, model_c) _compare_bem_surfaces(model_read, model_c) # bad conductivity with pytest.raises(ValueError, match='conductivity must be'): make_bem_model('sample', 4, [0.3, 0.006], subjects_dir=subjects_dir)
def test_ica_reject_buffer(): """Test ICA data raw buffer rejection.""" raw = read_raw_fif(raw_fname).crop(1.5, stop).load_data() picks = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=False, exclude='bads') ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4) raw._data[2, 1000:1005] = 5e-12 with catch_logging() as drop_log: with warnings.catch_warnings(record=True): ica.fit(raw, picks[:5], reject=dict(mag=2.5e-12), decim=2, tstep=0.01, verbose=True) assert_true(raw._data[:5, ::2].shape[1] - 4 == ica.n_samples_) log = [l for l in drop_log.getvalue().split('\n') if 'detected' in l] assert_equal(len(log), 1)
def test_saving_picked(): """Test saving picked CTF instances.""" temp_dir = _TempDir() out_fname = op.join(temp_dir, 'test_py_raw.fif') raw = read_raw_ctf(op.join(ctf_dir, ctf_fname_1_trial)) raw.crop(0, 1).load_data() assert raw.compensation_grade == get_current_comp(raw.info) == 0 assert len(raw.info['comps']) == 5 pick_kwargs = dict(meg=True, ref_meg=False, verbose=True) with catch_logging() as log: raw_pick = raw.copy().pick_types(**pick_kwargs) assert len(raw.info['comps']) == 5 assert len(raw_pick.info['comps']) == 0 log = log.getvalue() assert 'Removing 5 compensators' in log raw_pick.save(out_fname) # should work read_raw_fif(out_fname) read_raw_fif(out_fname, preload=True) # If comp is applied, picking should error raw.apply_gradient_compensation(1) assert raw.compensation_grade == get_current_comp(raw.info) == 1 with pytest.raises(RuntimeError, match='Compensation grade 1 has been'): raw.copy().pick_types(**pick_kwargs)
def test_rap_music_sphere(): """Test RAP-MUSIC with real data, sphere model, MEG only.""" evoked, noise_cov = _get_data(ch_decim=8) sphere = mne.make_sphere_model(r0=(0., 0., 0.04)) src = mne.setup_volume_source_space(subject=None, pos=10., sphere=(0.0, 0.0, 40, 65.0), mindist=5.0, exclude=0.0, sphere_units='mm') forward = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere) with catch_logging() as log: dipoles = rap_music(evoked, forward, noise_cov, n_dipoles=2, verbose=True) assert_var_exp_log(log.getvalue(), 47, 49) # Test that there is one dipole on each hemisphere pos = np.array([dip.pos[0] for dip in dipoles]) assert pos.shape == (2, 3) assert (pos[:, 0] < 0).sum() == 1 assert (pos[:, 0] > 0).sum() == 1 # Check the amplitude scale assert (1e-10 < dipoles[0].amplitude[0] < 1e-7) # Check the orientation dip_fit = mne.fit_dipole(evoked, noise_cov, sphere)[0] assert (np.max(np.abs(np.dot(dip_fit.ori, dipoles[0].ori[0]))) > 0.99) assert (np.max(np.abs(np.dot(dip_fit.ori, dipoles[1].ori[0]))) > 0.99) idx = dip_fit.gof.argmax() dist = np.linalg.norm(dipoles[0].pos[idx] - dip_fit.pos[idx]) assert 0.004 <= dist < 0.007 assert_allclose(dipoles[0].gof[idx], dip_fit.gof[idx], atol=3)
def test_read_raw_curry_rfDC(fname, tol, mock_dev_head_t, tmpdir): """Test reading CURRY files.""" if mock_dev_head_t: if 'Curry 7' in fname: # not supported yet return # copy files to tmpdir base = op.splitext(fname)[0] for ext in ('.cdt', '.cdt.dpa'): src = base + ext dst = op.join(tmpdir, op.basename(base) + ext) copyfile(src, dst) if ext == '.cdt.dpa': with open(dst, 'a') as fid: fid.write(LM_CONTENT) fname = op.join(tmpdir, op.basename(fname)) with open(fname + '.hpi', 'w') as fid: fid.write(HPI_CONTENT) # check data bti_rfDC = read_raw_bti(pdf_fname=bti_rfDC_file, head_shape_fname=None) with catch_logging() as log: raw = read_raw_curry(fname, verbose=True) log = log.getvalue() if mock_dev_head_t: assert 'Composing device' in log else: assert 'Leaving device' in log assert 'no landmark' in log # test on the eeg chans, since these were not renamed by curry eeg_names = [ ch["ch_name"] for ch in raw.info["chs"] if ch["kind"] == FIFF.FIFFV_EEG_CH ] assert_allclose(raw.get_data(eeg_names), bti_rfDC.get_data(eeg_names), rtol=tol) assert bti_rfDC.info['dev_head_t'] is not None # XXX probably a BTI bug if mock_dev_head_t: assert raw.info['dev_head_t'] is not None assert_allclose(raw.info['dev_head_t']['trans'], WANT_TRANS, atol=1e-5) else: assert raw.info['dev_head_t'] is None # check that most MEG sensors are approximately oriented outward from # the device origin n_meg = n_eeg = n_other = 0 pos = list() nn = list() for ch in raw.info['chs']: if ch['kind'] == FIFF.FIFFV_MEG_CH: assert ch['coil_type'] == FIFF.FIFFV_COIL_CTF_GRAD t = _loc_to_coil_trans(ch['loc']) pos.append(t[:3, 3]) nn.append(t[:3, 2]) assert_allclose(np.linalg.norm(nn[-1]), 1.) n_meg += 1 elif ch['kind'] == FIFF.FIFFV_EEG_CH: assert ch['coil_type'] == FIFF.FIFFV_COIL_EEG n_eeg += 1 else: assert ch['coil_type'] == FIFF.FIFFV_COIL_NONE n_other += 1 assert n_meg == 148 assert n_eeg == 31 assert n_other == 15 pos = np.array(pos) nn = np.array(nn) rad, origin = _fit_sphere(pos, disp=False) assert 0.11 < rad < 0.13 pos -= origin pos /= np.linalg.norm(pos, axis=1, keepdims=True) angles = np.abs(np.rad2deg(np.arccos((pos * nn).sum(-1)))) assert (angles < 20).sum() > 100
def test_other_systems(): """Test Maxwell filtering on KIT, BTI, and CTF files.""" # KIT kit_dir = op.join(io_dir, 'kit', 'tests', 'data') sqd_path = op.join(kit_dir, 'test.sqd') mrk_path = op.join(kit_dir, 'test_mrk.sqd') elp_path = op.join(kit_dir, 'test_elp.txt') hsp_path = op.join(kit_dir, 'test_hsp.txt') raw_kit = read_raw_kit(sqd_path, mrk_path, elp_path, hsp_path) with warnings.catch_warnings(record=True): # head fit assert_raises(RuntimeError, maxwell_filter, raw_kit) raw_sss = maxwell_filter(raw_kit, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 65, 65) raw_sss_auto = maxwell_filter(raw_kit, origin=(0., 0., 0.04), ignore_ref=True, mag_scale='auto') assert_allclose(raw_sss._data, raw_sss_auto._data) # XXX this KIT origin fit is terrible! Eventually we should get a # corrected HSP file with proper coverage with warnings.catch_warnings(record=True): with catch_logging() as log_file: assert_raises(RuntimeError, maxwell_filter, raw_kit, ignore_ref=True, regularize=None) # bad condition raw_sss = maxwell_filter(raw_kit, origin='auto', ignore_ref=True, bad_condition='warning', verbose='warning') log_file = log_file.getvalue() assert_true('badly conditioned' in log_file) assert_true('more than 20 mm from' in log_file) # fits can differ slightly based on scipy version, so be lenient here _assert_n_free(raw_sss, 28, 34) # bad origin == brutal reg # Let's set the origin with warnings.catch_warnings(record=True): with catch_logging() as log_file: raw_sss = maxwell_filter(raw_kit, origin=(0., 0., 0.04), ignore_ref=True, bad_condition='warning', regularize=None, verbose='warning') log_file = log_file.getvalue() assert_true('badly conditioned' in log_file) _assert_n_free(raw_sss, 80) # Now with reg with warnings.catch_warnings(record=True): with catch_logging() as log_file: raw_sss = maxwell_filter(raw_kit, origin=(0., 0., 0.04), ignore_ref=True, verbose=True) log_file = log_file.getvalue() assert_true('badly conditioned' not in log_file) _assert_n_free(raw_sss, 65) # BTi bti_dir = op.join(io_dir, 'bti', 'tests', 'data') bti_pdf = op.join(bti_dir, 'test_pdf_linux') bti_config = op.join(bti_dir, 'test_config_linux') bti_hs = op.join(bti_dir, 'test_hs_linux') with warnings.catch_warnings(record=True): # weght table raw_bti = read_raw_bti(bti_pdf, bti_config, bti_hs, preload=False) picks = pick_types(raw_bti.info, meg='mag', exclude=()) power = np.sqrt(np.sum(raw_bti[picks][0]**2)) raw_sss = maxwell_filter(raw_bti) _assert_n_free(raw_sss, 70) _assert_shielding(raw_sss, power, 0.5) raw_sss_auto = maxwell_filter(raw_bti, mag_scale='auto', verbose=True) _assert_shielding(raw_sss_auto, power, 0.7) # CTF raw_ctf = read_crop(fname_ctf_raw) assert_equal(raw_ctf.compensation_grade, 3) assert_raises(RuntimeError, maxwell_filter, raw_ctf) # compensated raw_ctf.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) _assert_shielding(raw_sss, raw_ctf, 1.8) raw_sss = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True) _assert_n_free(raw_sss, 70) _assert_shielding(raw_sss, raw_ctf, 12) raw_sss_auto = maxwell_filter(raw_ctf, origin=(0., 0., 0.04), ignore_ref=True, mag_scale='auto') assert_allclose(raw_sss._data, raw_sss_auto._data)
def test_plot_evoked(): """Test plotting of evoked.""" import matplotlib.pyplot as plt rng = np.random.RandomState(0) evoked = _get_epochs().average() fig = evoked.plot(proj=True, hline=[1], exclude=[], window_title='foo', time_unit='s') # Test a click ax = fig.get_axes()[0] line = ax.lines[0] _fake_click(fig, ax, [line.get_xdata()[0], line.get_ydata()[0]], 'data') _fake_click(fig, ax, [ax.get_xlim()[0], ax.get_ylim()[1]], 'data') # plot with bad channels excluded & spatial_colors & zorder evoked.plot(exclude='bads', time_unit='s') # test selective updating of dict keys is working. evoked.plot(hline=[1], units=dict(mag='femto foo'), time_unit='s') evoked_delayed_ssp = _get_epochs_delayed_ssp().average() evoked_delayed_ssp.plot(proj='interactive', time_unit='s') evoked_delayed_ssp.apply_proj() assert_raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', time_unit='s') evoked_delayed_ssp.info['projs'] = [] assert_raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', time_unit='s') assert_raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', axes='foo', time_unit='s') plt.close('all') # test GFP only evoked.plot(gfp='only', time_unit='s') assert_raises(ValueError, evoked.plot, gfp='foo', time_unit='s') evoked.plot_image(proj=True, time_unit='ms') # test mask evoked.plot_image(picks=[1, 2], mask=evoked.data > 0, time_unit='s') evoked.plot_image(picks=[1, 2], mask_cmap=None, colorbar=False, mask=np.ones(evoked.data.shape).astype(bool), time_unit='s') with warnings.catch_warnings(record=True) as w: evoked.plot_image(picks=[1, 2], mask=None, mask_style="both", time_unit='s') assert len(w) == 2 assert_raises(ValueError, evoked.plot_image, mask=evoked.data[1:, 1:] > 0, time_unit='s') # plot with bad channels excluded evoked.plot_image(exclude='bads', cmap='interactive', time_unit='s') evoked.plot_image(exclude=evoked.info['bads'], time_unit='s') # same thing plt.close('all') assert_raises(ValueError, evoked.plot_image, picks=[0, 0], time_unit='s') # duplicates evoked.plot_topo() # should auto-find layout _line_plot_onselect(0, 200, ['mag', 'grad'], evoked.info, evoked.data, evoked.times) plt.close('all') cov = read_cov(cov_fname) cov['method'] = 'empirical' cov['projs'] = [] # avoid warnings # test rank param. evoked.plot_white(cov, rank={'mag': 101, 'grad': 201}, time_unit='s') evoked.plot_white(cov, rank={'mag': 101}, time_unit='s') # test rank param evoked.plot_white(cov, rank={'grad': 201}, time_unit='s') assert_raises( ValueError, evoked.plot_white, cov, rank={'mag': 101, 'grad': 201, 'meg': 306}, time_unit='s') assert_raises( ValueError, evoked.plot_white, cov, rank={'meg': 306}, time_unit='s') evoked.plot_white([cov, cov], time_unit='s') # plot_compare_evokeds: test condition contrast, CI, color assignment plot_compare_evokeds(evoked.copy().pick_types(meg='mag')) plot_compare_evokeds( evoked.copy().pick_types(meg='grad'), picks=[1, 2], show_sensors="upper right", show_legend="upper left") evokeds = [evoked.copy() for _ in range(10)] for evoked in evokeds: evoked.data += (rng.randn(*evoked.data.shape) * np.std(evoked.data, axis=-1, keepdims=True)) for picks in ([0], [1], [2], [0, 2], [1, 2], [0, 1, 2],): figs = plot_compare_evokeds([evokeds], picks=picks, ci=0.95) if not isinstance(figs, list): figs = [figs] for fig in figs: ext = fig.axes[0].collections[0].get_paths()[0].get_extents() xs, ylim = ext.get_points().T assert_allclose(xs, evoked.times[[0, -1]]) line = fig.axes[0].lines[0] xs = line.get_xdata() assert_allclose(xs, evoked.times) ys = line.get_ydata() assert (ys < ylim[1]).all() assert (ys > ylim[0]).all() plt.close('all') evoked.rename_channels({'MEG 2142': "MEG 1642"}) assert len(plot_compare_evokeds(evoked)) == 2 colors = dict(red='r', blue='b') linestyles = dict(red='--', blue='-') red, blue = evoked.copy(), evoked.copy() red.data *= 1.1 blue.data *= 0.9 plot_compare_evokeds([red, blue], picks=3) # list of evokeds plot_compare_evokeds([red, blue], picks=3, truncate_yaxis=True) plot_compare_evokeds([[red, evoked], [blue, evoked]], picks=3) # list of lists # test picking & plotting grads contrast = dict() contrast["red/stim"] = list((evoked.copy(), red)) contrast["blue/stim"] = list((evoked.copy(), blue)) # test a bunch of params at once for evokeds_ in (evoked.copy().pick_types(meg='mag'), contrast, [red, blue], [[red, evoked], [blue, evoked]]): plot_compare_evokeds(evokeds_, picks=0, ci=True) # also tests CI plt.close('all') # test styling + a bunch of other params at once colors, linestyles = dict(red='r', blue='b'), dict(red='--', blue='-') plot_compare_evokeds(contrast, colors=colors, linestyles=linestyles, picks=[0, 2], vlines=[.01, -.04], invert_y=True, truncate_yaxis=False, ylim=dict(mag=(-10, 10)), styles={"red/stim": {"linewidth": 1}}, show_sensors=True) # various bad styles params = [dict(picks=3, colors=dict(fake=1)), dict(picks=3, styles=dict(fake=1)), dict(picks=3, gfp=True), dict(picks=3, show_sensors="a"), dict(colors=dict(red=10., blue=-2))] for param in params: assert_raises(ValueError, plot_compare_evokeds, evoked, **param) assert_raises(TypeError, plot_compare_evokeds, evoked, picks='str') assert_raises(TypeError, plot_compare_evokeds, evoked, vlines='x') plt.close('all') # `evoked` must contain Evokeds assert_raises(TypeError, plot_compare_evokeds, [[1, 2], [3, 4]]) # `ci` must be float or None assert_raises(TypeError, plot_compare_evokeds, contrast, ci='err') # test all-positive ylim contrast["red/stim"], contrast["blue/stim"] = red, blue plot_compare_evokeds(contrast, picks=[0], colors=['r', 'b'], ylim=dict(mag=(1, 10)), ci=_parametric_ci, truncate_yaxis='max_ticks', show_sensors=False, show_legend=False) # sequential colors evokeds = (evoked, blue, red) contrasts = {"a{}/b".format(ii): ev for ii, ev in enumerate(evokeds)} colors = {"a" + str(ii): ii for ii, _ in enumerate(evokeds)} contrasts["a1/c"] = evoked.copy() for split in (True, False): for linestyles in (["-"], {"b": "-", "c": ":"}): plot_compare_evokeds( contrasts, colors=colors, picks=[0], cmap='Reds', split_legend=split, linestyles=linestyles, ci=False, show_sensors=False) colors = {"a" + str(ii): ii / len(evokeds) for ii, _ in enumerate(evokeds)} plot_compare_evokeds( contrasts, colors=colors, picks=[0], cmap='Reds', split_legend=split, linestyles=linestyles, ci=False, show_sensors=False) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero plot_compare_evokeds(red, picks=[0], ci=lambda x: [x.std(axis=0), -x.std(axis=0)]) plot_compare_evokeds([red, blue], picks=[0], cmap="summer", ci=None, split_legend=None) plot_compare_evokeds([red, blue], cmap=None, split_legend=True) assert_raises(ValueError, plot_compare_evokeds, [red] * 20) assert_raises(ValueError, plot_compare_evokeds, contrasts, cmap='summer') plt.close('all') # Hack to test plotting of maxfiltered data evoked_sss = evoked.copy() sss = dict(sss_info=dict(in_order=80, components=np.arange(80))) evoked_sss.info['proc_history'] = [dict(max_info=sss)] evoked_sss.plot_white(cov, rank={'meg': 64}, time_unit='s') assert_raises( ValueError, evoked_sss.plot_white, cov, rank={'grad': 201}, time_unit='s') evoked_sss.plot_white(cov, time_unit='s') # plot with bad channels excluded, spatial_colors, zorder & pos. layout evoked.rename_channels({'MEG 0133': 'MEG 0000'}) evoked.plot(exclude=evoked.info['bads'], spatial_colors=True, gfp=True, zorder='std', time_unit='s') evoked.plot(exclude=[], spatial_colors=True, zorder='unsorted', time_unit='s') assert_raises(TypeError, evoked.plot, zorder='asdf', time_unit='s') plt.close('all') evoked.plot_sensors() # Test plot_sensors plt.close('all') evoked.pick_channels(evoked.ch_names[:4]) with catch_logging() as log_file: evoked.plot(verbose=True, time_unit='s') assert_true('Need more than one' in log_file.getvalue())
def test_plot_source_estimates(renderer_interactive, all_src_types_inv_evoked, pick_ori, kind, brain_gc): """Test plotting of scalar and vector source estimates.""" backend = renderer_interactive._get_3d_backend() is_pyvista = backend != 'mayavi' invs, evoked = all_src_types_inv_evoked inv = invs[kind] with pytest.warns(None): # PCA mag stc = apply_inverse(evoked, inv, pick_ori=pick_ori) stc.data[1] *= -1 # make it signed meth_key = 'plot_3d' if isinstance(stc, _BaseVolSourceEstimate) else 'plot' stc.subject = 'sample' meth = getattr(stc, meth_key) kwargs = dict( subjects_dir=subjects_dir, time_viewer=False, show_traces=False, # for speed smoothing_steps=1, verbose='error', src=inv['src'], volume_options=dict(resolution=None), # for speed ) if pick_ori != 'vector': kwargs['surface'] = 'white' kwargs['backend'] = backend # Mayavi can't handle non-surface if kind != 'surface' and not is_pyvista: with pytest.raises(RuntimeError, match='PyVista'): meth(**kwargs) return brain = meth(**kwargs) brain.close() del brain these_kwargs = kwargs.copy() these_kwargs['show_traces'] = 'foo' with pytest.raises(ValueError, match='show_traces'): meth(**these_kwargs) del these_kwargs if pick_ori == 'vector': with pytest.raises(ValueError, match='use "pos_lims"'): meth(**kwargs, clim=dict(pos_lims=[1, 2, 3])) if kind in ('volume', 'mixed'): with pytest.raises(TypeError, match='when stc is a mixed or vol'): these_kwargs = kwargs.copy() these_kwargs.pop('src') meth(**these_kwargs) with pytest.raises(ValueError, match='cannot be used'): these_kwargs = kwargs.copy() these_kwargs.update(show_traces=True, time_viewer=False) meth(**these_kwargs) if not is_pyvista: with pytest.raises(ValueError, match='view_layout must be'): meth(view_layout='horizontal', **kwargs) # flatmaps (mostly a lot of error checking) these_kwargs = kwargs.copy() these_kwargs.update(surface='flat', views='auto', hemi='both', verbose='debug') if kind == 'surface' and pick_ori != 'vector' and is_pyvista: with catch_logging() as log: with pytest.raises(FileNotFoundError, match='flatmap'): meth(**these_kwargs) # sample does not have them log = log.getvalue() assert 'offset: 0' in log fs_stc = stc.copy() fs_stc.subject = 'fsaverage' # this is wrong, but don't have to care flat_meth = getattr(fs_stc, meth_key) these_kwargs.pop('src') if pick_ori == 'vector': pass # can't even pass "surface" variable elif kind != 'surface': with pytest.raises(TypeError, match='SourceEstimate when a flatmap'): flat_meth(**these_kwargs) elif not is_pyvista: with pytest.raises(RuntimeError, match='PyVista 3D backend.*flatmap'): flat_meth(**these_kwargs) else: brain = flat_meth(**these_kwargs) brain.close() del brain these_kwargs.update(surface='inflated', views='flat') with pytest.raises(ValueError, match='surface="flat".*views="flat"'): flat_meth(**these_kwargs) # just test one for speed if kind != 'mixed': return assert is_pyvista brain = meth(views=['lat', 'med', 'ven'], hemi='lh', view_layout='horizontal', **kwargs) brain.close() assert brain._subplot_shape == (1, 3) del brain these_kwargs = kwargs.copy() these_kwargs['volume_options'] = dict(blending='foo') with pytest.raises(ValueError, match='mip'): meth(**these_kwargs) these_kwargs['volume_options'] = dict(badkey='foo') with pytest.raises(ValueError, match='unknown'): meth(**these_kwargs) # with resampling (actually downsampling but it's okay) these_kwargs['volume_options'] = dict(resolution=20., surface_alpha=0.) brain = meth(**these_kwargs) brain.close() del brain
def test_plot_alignment_basic(tmpdir, renderer, mixed_fwd_cov_evoked): """Test plotting of -trans.fif files and MEG sensor layouts.""" # generate fiducials file for testing tempdir = str(tmpdir) fiducials_path = op.join(tempdir, 'fiducials.fif') fid = [{ 'coord_frame': 5, 'ident': 1, 'kind': 1, 'r': [-0.08061612, -0.02908875, -0.04131077] }, { 'coord_frame': 5, 'ident': 2, 'kind': 1, 'r': [0.00146763, 0.08506715, -0.03483611] }, { 'coord_frame': 5, 'ident': 3, 'kind': 1, 'r': [0.08436285, -0.02850276, -0.04127743] }] write_dig(fiducials_path, fid, 5) evoked = read_evokeds(evoked_fname)[0] info = evoked.info sample_src = read_source_spaces(src_fname) pytest.raises(TypeError, plot_alignment, 'foo', trans_fname, subject='sample', subjects_dir=subjects_dir) pytest.raises(OSError, plot_alignment, info, trans_fname, subject='sample', subjects_dir=subjects_dir, src='foo') pytest.raises(ValueError, plot_alignment, info, trans_fname, subject='fsaverage', subjects_dir=subjects_dir, src=sample_src) sample_src.plot(subjects_dir=subjects_dir, head=True, skull=True, brain='white') # mixed source space mixed_src = mixed_fwd_cov_evoked[0]['src'] assert mixed_src.kind == 'mixed' plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame='head', trans=Path(trans_fname), subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=mixed_src) renderer.backend._close_all() # no-head version renderer.backend._close_all() # trans required with pytest.raises(ValueError, match='transformation matrix is required'): plot_alignment(info, trans=None, src=src_fname) with pytest.raises(ValueError, match='transformation matrix is required'): plot_alignment(info, trans=None, mri_fiducials=True) with pytest.raises(ValueError, match='transformation matrix is required'): plot_alignment(info, trans=None, surfaces=['brain']) # all coord frames plot_alignment(info) # works: surfaces='auto' default for coord_frame in ('meg', 'head', 'mri'): fig = plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame=coord_frame, trans=Path(trans_fname), subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=src_fname) renderer.backend._close_all() # EEG only with strange options evoked_eeg_ecog_seeg = evoked.copy().pick_types(meg=False, eeg=True) evoked_eeg_ecog_seeg.info['projs'] = [] # "remove" avg proj evoked_eeg_ecog_seeg.set_channel_types({ 'EEG 001': 'ecog', 'EEG 002': 'seeg' }) with catch_logging() as log: plot_alignment(evoked_eeg_ecog_seeg.info, subject='sample', trans=trans_fname, subjects_dir=subjects_dir, surfaces=['white', 'outer_skin', 'outer_skull'], meg=['helmet', 'sensors'], eeg=['original', 'projected'], ecog=True, seeg=True, verbose=True) log = log.getvalue() assert 'ecog: 1' in log assert 'seeg: 1' in log renderer.backend._close_all() sphere = make_sphere_model(info=info, r0='auto', head_radius='auto') bem_sol = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem-sol.fif')) bem_surfs = read_bem_surfaces( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem.fif')) sample_src[0]['coord_frame'] = 4 # hack for coverage plot_alignment( info, trans_fname, subject='sample', eeg='projected', meg='helmet', bem=sphere, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) plot_alignment(info, subject='sample', meg='helmet', subjects_dir=subjects_dir, eeg='projected', bem=sphere, surfaces=['head', 'brain'], src=sample_src) # no trans okay, no mri surfaces plot_alignment(info, bem=sphere, surfaces=['brain']) with pytest.raises(ValueError, match='A head surface is required'): plot_alignment(info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='projected', surfaces=[]) with pytest.raises(RuntimeError, match='No brain surface found'): plot_alignment(info, trans=trans_fname, subject='foo', subjects_dir=subjects_dir, surfaces=['brain']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=[], subjects_dir=subjects_dir, bem=bem_sol, eeg=True, surfaces=['head', 'inflated', 'outer_skull', 'inner_skull']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=bem_surfs) # single-layer BEM can still plot head surface assert bem_surfs[-1]['id'] == FIFF.FIFFV_BEM_SURF_ID_BRAIN bem_sol_homog = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-bem-sol.fif')) for use_bem in (bem_surfs[-1:], bem_sol_homog): with catch_logging() as log: plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=use_bem, verbose=True) log = log.getvalue() assert 'not find the surface for head in the provided BEM model' in log # sphere model sphere = make_sphere_model('auto', 'auto', info) src = setup_volume_source_space(sphere=sphere) plot_alignment( info, trans=Transform('head', 'mri'), eeg='projected', meg='helmet', bem=sphere, src=src, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) sphere = make_sphere_model('auto', None, info) # one layer # if you ask for a brain surface with a 1-layer sphere model it's an error with pytest.raises(RuntimeError, match='Sphere model does not have'): fig = plot_alignment(trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain'], bem=sphere) # but you can ask for a specific brain surface, and # no info is permitted fig = plot_alignment(trans=trans_fname, subject='sample', meg=False, coord_frame='mri', subjects_dir=subjects_dir, surfaces=['white'], bem=sphere, show_axes=True) renderer.backend._close_all() if renderer._get_3d_backend() == 'mayavi': import mayavi # noqa: F401 analysis:ignore assert isinstance(fig, mayavi.core.scene.Scene) # 3D coil with no defined draw (ConvexHull) info_cube = pick_info(info, np.arange(6)) info['dig'] = None info_cube['chs'][0]['coil_type'] = 9999 info_cube['chs'][1]['coil_type'] = 9998 with pytest.raises(RuntimeError, match='coil definition not found'): plot_alignment(info_cube, meg='sensors', surfaces=()) coil_def_fname = op.join(tempdir, 'temp') with open(coil_def_fname, 'w') as fid: fid.write(coil_3d) # make sure our other OPMs can be plotted, too for ii, kind in enumerate( ('QUSPIN_ZFOPM_MAG', 'QUSPIN_ZFOPM_MAG2', 'FIELDLINE_OPM_MAG_GEN1', 'KERNEL_OPM_MAG_GEN1'), 2): info_cube['chs'][ii]['coil_type'] = getattr(FIFF, f'FIFFV_COIL_{kind}') with use_coil_def(coil_def_fname): with catch_logging() as log: plot_alignment(info_cube, meg='sensors', surfaces=(), dig=True, verbose='debug') log = log.getvalue() assert 'planar geometry' in log # one layer bem with skull surfaces: with pytest.raises(RuntimeError, match='Sphere model does not.*boundary'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain', 'head', 'inner_skull'], bem=sphere) # wrong eeg value: with pytest.raises(ValueError, match='Invalid value for the .eeg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='foo') # wrong meg value: with pytest.raises(ValueError, match='Invalid value for the .meg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, meg='bar') # multiple brain surfaces: with pytest.raises(ValueError, match='Only one brain surface can be plot'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['white', 'pial']) with pytest.raises(TypeError, match='surfaces.*must be'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=[1]) with pytest.raises(ValueError, match='Unknown surface type'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['foo']) with pytest.raises(TypeError, match="must be an instance of "): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=dict(brain='super clear')) with pytest.raises(ValueError, match="must be between 0 and 1"): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=dict(brain=42)) fwd_fname = op.join(data_dir, 'MEG', 'sample', 'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif') fwd = read_forward_solution(fwd_fname) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') fwd = convert_forward_solution(fwd, force_fixed=True) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') fwd['coord_frame'] = FIFF.FIFFV_COORD_MRI # check required to get to MRI with pytest.raises(ValueError, match='transformation matrix is required'): plot_alignment(info, trans=None, fwd=fwd) # surfaces as dict plot_alignment(subject='sample', coord_frame='head', trans=trans_fname, subjects_dir=subjects_dir, surfaces={ 'white': 0.4, 'outer_skull': 0.6, 'head': None })
def test_plot_evoked(): """Test evoked.plot.""" epochs = _get_epochs() evoked = epochs.average() assert evoked.proj is False fig = evoked.plot(proj=True, hline=[1], exclude=[], window_title='foo', time_unit='s') amplitudes = _get_amplitudes(fig) assert len(amplitudes) == len(default_picks) assert evoked.proj is False # Test a click ax = fig.get_axes()[0] line = ax.lines[0] _fake_click(fig, ax, [line.get_xdata()[0], line.get_ydata()[0]], 'data') _fake_click(fig, ax, [ax.get_xlim()[0], ax.get_ylim()[1]], 'data') # plot with bad channels excluded & spatial_colors & zorder evoked.plot(exclude='bads', time_unit='s') # test selective updating of dict keys is working. evoked.plot(hline=[1], units=dict(mag='femto foo'), time_unit='s') evoked_delayed_ssp = _get_epochs_delayed_ssp().average() evoked_delayed_ssp.plot(proj='interactive', time_unit='s') evoked_delayed_ssp.apply_proj() pytest.raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', time_unit='s') with evoked_delayed_ssp.info._unlock(): evoked_delayed_ssp.info['projs'] = [] pytest.raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', time_unit='s') pytest.raises(RuntimeError, evoked_delayed_ssp.plot, proj='interactive', axes='foo', time_unit='s') plt.close('all') # test `gfp='only'`: GFP (EEG) and RMS (MEG) fig, ax = plt.subplots(3) evoked.plot(gfp='only', time_unit='s', axes=ax) assert len(ax[0].lines) == len(ax[1].lines) == len(ax[2].lines) == 1 assert ax[0].get_title() == 'EEG (3 channels)' assert ax[0].texts[0].get_text() == 'GFP' assert ax[1].get_title() == 'Gradiometers (9 channels)' assert ax[1].texts[0].get_text() == 'RMS' assert ax[2].get_title() == 'Magnetometers (2 channels)' assert ax[1].texts[0].get_text() == 'RMS' plt.close('all') # Test invalid `gfp` with pytest.raises(ValueError): evoked.plot(gfp='foo', time_unit='s') # plot with bad channels excluded, spatial_colors, zorder & pos. layout evoked.rename_channels({'MEG 0133': 'MEG 0000'}) evoked.plot(exclude=evoked.info['bads'], spatial_colors=True, gfp=True, zorder='std', time_unit='s') evoked.plot(exclude=[], spatial_colors=True, zorder='unsorted', time_unit='s') pytest.raises(TypeError, evoked.plot, zorder='asdf', time_unit='s') plt.close('all') evoked.plot_sensors() # Test plot_sensors plt.close('all') evoked.pick_channels(evoked.ch_names[:4]) with catch_logging() as log_file: evoked.plot(verbose=True, time_unit='s') assert 'Need more than one' in log_file.getvalue()
def test_reporting_fir(phase, fir_window, btype): """Test FIR filter reporting.""" l_freq = 1. if btype == 'bandpass' else None fs = 1000. with catch_logging() as log: x = create_filter(None, fs, l_freq, 40, method='fir', phase=phase, fir_window=fir_window, verbose=True) n_taps = len(x) log = log.getvalue() keys = [ 'FIR', btype, fir_window.capitalize(), 'Filter length: %d samples' % (n_taps, ), 'passband ripple', 'stopband attenuation', ] if phase == 'minimum': keys += [' causal '] else: keys += [' non-causal ', ' dB cutoff frequency: 45.00 Hz'] if btype == 'bandpass': keys += [' dB cutoff frequency: 0.50 Hz'] for key in keys: assert key in log if phase == 'zero': assert '-6 dB cutoff' in log elif phase == 'zero-double': assert '-12 dB cutoff' in log else: # XXX Eventually we should figure out where the resulting point is, # since the minimum-phase process will change it. For now we don't # report it. assert phase == 'minimum' # Verify some of the filter properties if phase == 'zero-double': x = np.convolve(x, x) # effectively what happens w, h = freqz(x, worN=10000) w *= fs / (2 * np.pi) h = np.abs(h) # passband passes = [np.argmin(np.abs(w - f)) for f in (1, 20, 40)] # stopband stops = [np.argmin(np.abs(w - 50.))] # transition mids = [np.argmin(np.abs(w - 45.))] # put these where they belong based on filter type assert w[0] == 0. idx_0 = 0 idx_0p5 = np.argmin(np.abs(w - 0.5)) if btype == 'bandpass': stops += [idx_0] mids += [idx_0p5] else: passes += [idx_0, idx_0p5] assert_allclose(h[passes], 1., atol=0.01) attenuation = -20 if phase == 'minimum' else -50 assert_allclose(h[stops], 0., atol=10**(attenuation / 20.)) if phase != 'minimum': # haven't worked out the math for this yet expected = 0.25 if phase == 'zero-double' else 0.5 assert_allclose(h[mids], expected, atol=0.01)
def test_reporting_iir(ftype, btype, order, output): """Test IIR filter reporting.""" fs = 1000. l_freq = 1. if btype == 'bandpass' else None iir_params = dict(ftype=ftype, order=order, output=output) rs = 20 if order == 1 else 80 if ftype == 'ellip': iir_params['rp'] = 3 # dB iir_params['rs'] = rs # attenuation pass_tol = np.log10(iir_params['rp']) + 0.01 else: pass_tol = 0.2 with catch_logging() as log: x = create_filter(None, fs, l_freq, 40., method='iir', iir_params=iir_params, verbose=True) order_eff = order * (1 + (btype == 'bandpass')) if output == 'ba': assert len(x['b']) == order_eff + 1 log = log.getvalue() keys = [ 'IIR', 'zero-phase', 'two-pass forward and reverse', 'non-causal', btype, ftype, 'Filter order %d' % (order_eff * 2, ), 'Cutoff ' if btype == 'lowpass' else 'Cutoffs ', ] dB_decade = -27.74 if ftype == 'ellip': dB_cutoff = -6.0 elif order == 1 or ftype == 'butter': dB_cutoff = -6.02 else: assert ftype == 'bessel' assert order == 4 dB_cutoff = -15.16 if btype == 'lowpass': keys += ['%0.2f dB' % (dB_cutoff, )] for key in keys: assert key.lower() in log.lower() # Verify some of the filter properties if output == 'ba': w, h = freqz(x['b'], x['a'], worN=10000) else: w, h = sosfreqz(x['sos'], worN=10000) w *= fs / (2 * np.pi) h = np.abs(h) # passband passes = [np.argmin(np.abs(w - 20))] # stopband decades = [np.argmin(np.abs(w - 400.))] # one decade # transition edges = [np.argmin(np.abs(w - 40.))] # put these where they belong based on filter type assert w[0] == 0. idx_0p1 = np.argmin(np.abs(w - 0.1)) idx_1 = np.argmin(np.abs(w - 1.)) if btype == 'bandpass': edges += [idx_1] decades += [idx_0p1] else: passes += [idx_0p1, idx_1] edge_val = 10**(dB_cutoff / 40.) assert_allclose(h[edges], edge_val, atol=0.01) assert_allclose(h[passes], 1., atol=pass_tol) if ftype == 'butter' and btype == 'lowpass': attenuation = dB_decade * order assert_allclose(h[decades], 10**(attenuation / 20.), rtol=0.01) elif ftype == 'ellip': assert_array_less(h[decades], 10**(-rs / 20))
def test_coreg_class_gui_match(): """Test that using Coregistration matches mne coreg.""" fiducials, _ = read_fiducials(fid_fname) info = read_info(raw_fname) coreg = Coregistration(info, subject='sample', subjects_dir=subjects_dir, fiducials=fiducials) assert_allclose(coreg.trans['trans'], np.eye(4), atol=1e-6) # mne coreg -s sample -d subjects -f MEG/sample/sample_audvis_trunc_raw.fif # then "Fit Fid.", Save... to get trans, read_trans: want_trans = [ [9.99428809e-01, 2.94733196e-02, 1.65350307e-02, -8.76054692e-04], [-1.92420650e-02, 8.98512006e-01, -4.38526988e-01, 9.39774036e-04], [-2.77817696e-02, 4.37958330e-01, 8.98565888e-01, -8.29207990e-03], [0, 0, 0, 1] ] coreg.set_fid_match('matched') coreg.fit_fiducials(verbose=True) assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6) # Set ICP iterations to one, click "Fit ICP" want_trans = [ [9.99512792e-01, 2.80128177e-02, 1.37659665e-02, 6.08855276e-04], [-1.91694051e-02, 8.98992002e-01, -4.37545270e-01, 9.66848747e-04], [-2.46323701e-02, 4.37068194e-01, 8.99091005e-01, -1.44129358e-02], [0, 0, 0, 1] ] coreg.fit_icp(1, verbose=True) assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6) # Set ICP iterations to 20, click "Fit ICP" with catch_logging() as log: coreg.fit_icp(20, verbose=True) log = log.getvalue() want_trans = [ [9.97582495e-01, 2.12266613e-02, 6.61706254e-02, -5.07694029e-04], [1.81089472e-02, 8.39900672e-01, -5.42437911e-01, 7.81218382e-03], [-6.70908988e-02, 5.42324841e-01, 8.37485850e-01, -2.50057746e-02], [0, 0, 0, 1] ] assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6) assert 'ICP 19' in log assert 'ICP 20' not in log # converged on 19 # Change to uniform scale mode, "Fit Fiducials" in scale UI coreg.set_scale_mode('uniform') coreg.fit_fiducials() want_scale = [0.975] * 3 want_trans = [ [9.99428809e-01, 2.94733196e-02, 1.65350307e-02, -9.25998494e-04], [-1.92420650e-02, 8.98512006e-01, -4.38526988e-01, -1.03350170e-03], [-2.77817696e-02, 4.37958330e-01, 8.98565888e-01, -9.03170835e-03], [0, 0, 0, 1] ] assert_allclose(coreg.scale, want_scale, atol=5e-4) assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6) # Click "Fit ICP" in scale UI with catch_logging() as log: coreg.fit_icp(20, verbose=True) log = log.getvalue() assert 'ICP 18' in log assert 'ICP 19' not in log want_scale = [1.036] * 3 want_trans = [ [9.98992383e-01, 1.72388796e-02, 4.14364934e-02, 6.19427126e-04], [6.80460501e-03, 8.54430079e-01, -5.19521892e-01, 5.58008114e-03], [-4.43605632e-02, 5.19280374e-01, 8.53451848e-01, -2.03358755e-02], [0, 0, 0, 1] ] assert_allclose(coreg.scale, want_scale, atol=5e-4) assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6) # Change scale mode to 3-axis, click "Fit ICP" in scale UI coreg.set_scale_mode('3-axis') with catch_logging() as log: coreg.fit_icp(20, verbose=True) log = log.getvalue() assert 'ICP 7' in log assert 'ICP 8' not in log want_scale = [1.025, 1.010, 1.121] want_trans = [ [9.98387098e-01, 2.04762165e-02, 5.29526398e-02, 4.97257097e-05], [1.13287698e-02, 8.42087150e-01, -5.39222538e-01, 7.09863892e-03], [-5.56319728e-02, 5.38952649e-01, 8.40496957e-01, -1.46372067e-02], [0, 0, 0, 1] ] assert_allclose(coreg.scale, want_scale, atol=5e-4) assert_allclose(coreg.trans['trans'], want_trans, atol=1e-6)