def test_localization_bias_free(bias_params_free, reg, pick_ori, weight_norm, use_cov, depth, lower, upper, real_filter): """Test localization bias for free-orientation DICS.""" evoked, fwd, noise_cov, data_cov, want = bias_params_free noise_csd = _cov_as_csd(noise_cov, evoked.info) data_csd = _cov_as_csd(data_cov, evoked.info) del noise_cov, data_cov if not use_cov: evoked.pick_types(meg='grad') noise_csd = None loc = apply_dics( evoked, make_dics(evoked.info, fwd, data_csd, reg, noise_csd, pick_ori=pick_ori, weight_norm=weight_norm, depth=depth, real_filter=real_filter)).data loc = np.linalg.norm(loc, axis=1) if pick_ori == 'vector' else np.abs(loc) # Compute the percentage of sources for which there is no loc bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper
def test_orientation_max_power(bias_params_fixed, bias_params_free, weight_norm, lower, upper, lower_ori, upper_ori, real_filter): """Test orientation selection for bias for max-power DICS.""" # we simulate data for the fixed orientation forward and beamform using # the free orientation forward, and check the orientation match at the end evoked, _, noise_cov, data_cov, want = bias_params_fixed noise_csd = _cov_as_csd(noise_cov, evoked.info) data_csd = _cov_as_csd(data_cov, evoked.info) del data_cov, noise_cov fwd = bias_params_free[1] filters = make_dics(evoked.info, fwd, data_csd, 0.05, noise_csd, pick_ori='max-power', weight_norm=weight_norm, depth=None, real_filter=real_filter) loc = np.abs(apply_dics(evoked, filters).data) ori = filters['max_power_ori'][0] assert ori.shape == (246, 3) loc = np.abs(loc) # Compute the percentage of sources for which there is no loc bias: max_idx = np.argmax(loc, axis=0) mask = want == max_idx # ones that localized properly perc = mask.mean() * 100 assert lower <= perc <= upper # Compute the dot products of our forward normals and # assert we get some hopefully reasonable agreement assert fwd['coord_frame'] == FIFF.FIFFV_COORD_HEAD nn = np.concatenate( [s['nn'][v] for s, v in zip(fwd['src'], filters['vertices'])]) nn = nn[want] nn = apply_trans(invert_transform(fwd['mri_head_t']), nn, move=False) assert_allclose(np.linalg.norm(nn, axis=1), 1, atol=1e-6) assert_allclose(np.linalg.norm(ori, axis=1), 1, atol=1e-12) dots = np.abs((nn[mask] * ori[mask]).sum(-1)) assert_array_less(dots, 1) assert_array_less(0, dots) got = np.mean(dots) assert lower_ori < got < upper_ori
def test_apply_dics_timeseries(): """Test DICS applied to timeseries data.""" fwd_free, fwd_surf, fwd_fixed, fwd_vol, label = _load_forward() epochs, evoked, csd, source_vertno = _simulate_data(fwd_fixed) vertices = np.intersect1d(label.vertices, fwd_free['src'][0]['vertno']) source_ind = vertices.tolist().index(source_vertno) reg = 5 # Lots of regularization for our toy dataset multiple_filters = make_dics(evoked.info, fwd_surf, csd, label=label, reg=reg) # Sanity checks on the resulting STC after applying DICS on evoked stcs = apply_dics(evoked, multiple_filters) assert isinstance(stcs, list) assert len(stcs) == len(multiple_filters['weights']) assert_array_equal(stcs[0].vertices[0], multiple_filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], multiple_filters['vertices'][1]) assert_allclose(stcs[0].times, evoked.times) # Applying filters for multiple frequencies on epoch data should fail raises(ValueError, apply_dics_epochs, epochs, multiple_filters) # From now on, only apply filters with a single frequency (20 Hz). csd20 = csd.pick_frequency(20) filters = make_dics(evoked.info, fwd_surf, csd20, label=label, reg=reg) # Sanity checks on the resulting STC after applying DICS on epochs. # Also test here that no warnings are thrown - implemented to check whether # src should not be None warning occurs with pytest.warns(None) as w: stcs = apply_dics_epochs(epochs, filters) assert len(w) == 0 assert isinstance(stcs, list) assert len(stcs) == 1 assert_array_equal(stcs[0].vertices[0], filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], filters['vertices'][1]) assert_allclose(stcs[0].times, epochs.times) # Did we find the source? stc = (stcs[0] ** 2).mean() assert np.argmax(stc.data) == source_ind # Apply filters to evoked stc = apply_dics(evoked, filters) stc = (stc ** 2).mean() assert np.argmax(stc.data) == source_ind # Test if wrong channel selection is detected in application of filter evoked_ch = cp.deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[:-1]) raises(ValueError, apply_dics, evoked_ch, filters) # Test whether projections are applied, by adding a custom projection filters_noproj = make_dics(evoked.info, fwd_surf, csd20, label=label) stc_noproj = apply_dics(evoked, filters_noproj) evoked_proj = evoked.copy() p = compute_proj_evoked(evoked_proj, n_grad=1, n_mag=0, n_eeg=0) proj_matrix = make_projector(p, evoked_proj.ch_names)[0] evoked_proj.info['projs'] += p filters_proj = make_dics(evoked_proj.info, fwd_surf, csd20, label=label) assert_array_equal(filters_proj['proj'], proj_matrix) stc_proj = apply_dics(evoked_proj, filters_proj) assert np.any(np.not_equal(stc_noproj.data, stc_proj.data)) # Test detecting incompatible projections filters_proj['proj'] = filters_proj['proj'][:-1, :-1] raises(ValueError, apply_dics, evoked_proj, filters_proj) # Test returning a generator stcs = apply_dics_epochs(epochs, filters, return_generator=False) stcs_gen = apply_dics_epochs(epochs, filters, return_generator=True) assert_array_equal(stcs[0].data, advance_iterator(stcs_gen).data) # Test computing timecourses on a volume source space filters_vol = make_dics(evoked.info, fwd_vol, csd20, reg=reg) stc = apply_dics(evoked, filters_vol) stc = (stc ** 2).mean() assert np.argmax(stc.data) == 3851 # TODO: don't make this hard coded # check whether a filters object without src_type throws expected warning del filters_vol['src_type'] # emulate 0.16 behaviour to cause warning with pytest.warns(RuntimeWarning, match='spatial filter does not contain ' 'src_type'): apply_dics_epochs(epochs, filters_vol)
def test_apply_dics_timeseries(_load_forward, idx): """Test DICS applied to timeseries data.""" fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward epochs, evoked, csd, source_vertno, label, vertices, source_ind = \ _simulate_data(fwd_fixed, idx) reg = 5 # Lots of regularization for our toy dataset with pytest.raises(ValueError, match='several sensor types'): make_dics(evoked.info, fwd_surf, csd) evoked.pick_types(meg='grad') multiple_filters = make_dics(evoked.info, fwd_surf, csd, label=label, reg=reg) # Sanity checks on the resulting STC after applying DICS on evoked stcs = apply_dics(evoked, multiple_filters) assert isinstance(stcs, list) assert len(stcs) == len(multiple_filters['weights']) assert_array_equal(stcs[0].vertices[0], multiple_filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], multiple_filters['vertices'][1]) assert_allclose(stcs[0].times, evoked.times) # Applying filters for multiple frequencies on epoch data should fail with pytest.raises(ValueError, match='computed for a single frequency'): apply_dics_epochs(epochs, multiple_filters) # From now on, only apply filters with a single frequency (20 Hz). csd20 = csd.pick_frequency(20) filters = make_dics(evoked.info, fwd_surf, csd20, label=label, reg=reg, inversion='single') # Sanity checks on the resulting STC after applying DICS on epochs. # Also test here that no warnings are thrown - implemented to check whether # src should not be None warning occurs with pytest.warns(None) as w: stcs = apply_dics_epochs(epochs, filters) assert len(w) == 0 assert isinstance(stcs, list) assert len(stcs) == 1 assert_array_equal(stcs[0].vertices[0], filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], filters['vertices'][1]) assert_allclose(stcs[0].times, epochs.times) # Did we find the source? stc = (stcs[0] ** 2).mean() dist = _fwd_dist(stc, fwd_surf, vertices, source_ind, tidx=0) assert dist == 0 # Apply filters to evoked stc = apply_dics(evoked, filters) stc = (stc ** 2).mean() dist = _fwd_dist(stc, fwd_surf, vertices, source_ind, tidx=0) assert dist == 0 # Test if wrong channel selection is detected in application of filter evoked_ch = cp.deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[:-1]) with pytest.raises(ValueError, match='MEG 2633 which is not present'): apply_dics(evoked_ch, filters) # Test whether projections are applied, by adding a custom projection filters_noproj = make_dics(evoked.info, fwd_surf, csd20, label=label) stc_noproj = apply_dics(evoked, filters_noproj) evoked_proj = evoked.copy() p = compute_proj_evoked(evoked_proj, n_grad=1, n_mag=0, n_eeg=0) proj_matrix = make_projector(p, evoked_proj.ch_names)[0] evoked_proj.info['projs'] += p filters_proj = make_dics(evoked_proj.info, fwd_surf, csd20, label=label) assert_array_equal(filters_proj['proj'], proj_matrix) stc_proj = apply_dics(evoked_proj, filters_proj) assert np.any(np.not_equal(stc_noproj.data, stc_proj.data)) # Test detecting incompatible projections filters_proj['proj'] = filters_proj['proj'][:-1, :-1] with pytest.raises(ValueError, match='operands could not be broadcast'): apply_dics(evoked_proj, filters_proj) # Test returning a generator stcs = apply_dics_epochs(epochs, filters, return_generator=False) stcs_gen = apply_dics_epochs(epochs, filters, return_generator=True) assert_array_equal(stcs[0].data, next(stcs_gen).data) # Test computing timecourses on a volume source space filters_vol = make_dics(evoked.info, fwd_vol, csd20, reg=reg, inversion='single') stc = apply_dics(evoked, filters_vol) stc = (stc ** 2).mean() assert stc.data.shape[1] == 1 vol_source_ind = _nearest_vol_ind(fwd_vol, fwd_surf, vertices, source_ind) dist = _fwd_dist(stc, fwd_vol, fwd_vol['src'][0]['vertno'], vol_source_ind, tidx=0) vol_tols = {100: 0.008, 200: 0.015} vol_tol = vol_tols.get(idx, 0.) assert dist <= vol_tol # check whether a filters object without src_type throws expected warning del filters_vol['src_type'] # emulate 0.16 behaviour to cause warning with pytest.warns(RuntimeWarning, match='filter does not contain src_typ'): apply_dics_epochs(epochs, filters_vol)
def test_apply_dics_timeseries(): """Test DICS applied to timeseries data.""" fwd_free, fwd_surf, fwd_fixed, fwd_vol, label = _load_forward() epochs, evoked, csd, source_vertno = _simulate_data(fwd_fixed) vertices = np.intersect1d(label.vertices, fwd_free['src'][0]['vertno']) source_ind = vertices.tolist().index(source_vertno) reg = 5 # Lots of regularization for our toy dataset multiple_filters = make_dics(evoked.info, fwd_surf, csd, label=label, reg=reg) # Sanity checks on the resulting STC after applying DICS on evoked stcs = apply_dics(evoked, multiple_filters) assert isinstance(stcs, list) assert len(stcs) == len(multiple_filters['weights']) assert_array_equal(stcs[0].vertices[0], multiple_filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], multiple_filters['vertices'][1]) assert_allclose(stcs[0].times, evoked.times) # Applying filters for multiple frequencies on epoch data should fail raises(ValueError, apply_dics_epochs, epochs, multiple_filters) # From now on, only apply filters with a single frequency (20 Hz). csd20 = csd.pick_frequency(20) filters = make_dics(evoked.info, fwd_surf, csd20, label=label, reg=reg) # Sanity checks on the resulting STC after applying DICS on epochs. # Also test here that no warnings are thrown - implemented to check whether # src should not be None warning occurs with pytest.warns(None) as w: stcs = apply_dics_epochs(epochs, filters) assert len(w) == 0 assert isinstance(stcs, list) assert len(stcs) == 1 assert_array_equal(stcs[0].vertices[0], filters['vertices'][0]) assert_array_equal(stcs[0].vertices[1], filters['vertices'][1]) assert_allclose(stcs[0].times, epochs.times) # Did we find the source? stc = (stcs[0] ** 2).mean() assert np.argmax(stc.data) == source_ind # Apply filters to evoked stc = apply_dics(evoked, filters) stc = (stc ** 2).mean() assert np.argmax(stc.data) == source_ind # Test if wrong channel selection is detected in application of filter evoked_ch = cp.deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[:-1]) raises(ValueError, apply_dics, evoked_ch, filters) # Test whether projections are applied, by adding a custom projection filters_noproj = make_dics(evoked.info, fwd_surf, csd20, label=label) stc_noproj = apply_dics(evoked, filters_noproj) evoked_proj = evoked.copy() p = compute_proj_evoked(evoked_proj, n_grad=1, n_mag=0, n_eeg=0) proj_matrix = make_projector(p, evoked_proj.ch_names)[0] evoked_proj.info['projs'] += p filters_proj = make_dics(evoked_proj.info, fwd_surf, csd20, label=label) assert_array_equal(filters_proj['proj'], proj_matrix) stc_proj = apply_dics(evoked_proj, filters_proj) assert np.any(np.not_equal(stc_noproj.data, stc_proj.data)) # Test detecting incompatible projections filters_proj['proj'] = filters_proj['proj'][:-1, :-1] raises(ValueError, apply_dics, evoked_proj, filters_proj) # Test returning a generator stcs = apply_dics_epochs(epochs, filters, return_generator=False) stcs_gen = apply_dics_epochs(epochs, filters, return_generator=True) assert_array_equal(stcs[0].data, next(stcs_gen).data) # Test computing timecourses on a volume source space filters_vol = make_dics(evoked.info, fwd_vol, csd20, reg=reg) stc = apply_dics(evoked, filters_vol) stc = (stc ** 2).mean() assert np.argmax(stc.data) == 3851 # TODO: don't make this hard coded # check whether a filters object without src_type throws expected warning del filters_vol['src_type'] # emulate 0.16 behaviour to cause warning with pytest.warns(RuntimeWarning, match='spatial filter does not contain ' 'src_type'): apply_dics_epochs(epochs, filters_vol)
else: raise ValueError('Invalid sensor type: %s', sensor_type) # Allow using other MNE branches without this arg use_kwargs = dict(noise_csd=noise_csd) if use_noise_cov else dict() filters = make_dics(info, fwd_disc_man, csd, reg=reg, pick_ori=pick_ori, inversion=inversion, weight_norm=weight_norm, depth=1. if normalize_fwd else None, real_filter=real_filter, reduce_rank=reduce_rank, **use_kwargs) stc_est = apply_dics(evoked, filters).crop(0.001, 1) stc_est_power = (stc_est**2).sum() peak_vertex, peak_time = stc_est_power.get_peak(vert_as_index=True, time_as_index=True) estimated_time_course = np.abs(stc_est.data[peak_vertex]) # Compute distance between true and estimated source locations pos_est = fwd_disc_man['source_rr'][peak_vertex] pos_true = fwd_disc_man['source_rr'][config.vertex] dist = np.linalg.norm(pos_est - pos_true) # Ratio between estimated peak activity and all estimated activity. focality_score = stc_est_power.data[peak_vertex, 0] / stc_est_power.data.sum()