def test_find_ch_adjacency(): """Test computing the adjacency matrix.""" data_path = testing.data_path() raw = read_raw_fif(raw_fname, preload=True) sizes = {'mag': 828, 'grad': 1700, 'eeg': 384} nchans = {'mag': 102, 'grad': 204, 'eeg': 60} for ch_type in ['mag', 'grad', 'eeg']: conn, ch_names = find_ch_adjacency(raw.info, ch_type) # Silly test for checking the number of neighbors. assert_equal(conn.getnnz(), sizes[ch_type]) assert_equal(len(ch_names), nchans[ch_type]) pytest.raises(ValueError, find_ch_adjacency, raw.info, None) # Test computing the conn matrix with gradiometers. conn, ch_names = _compute_ch_adjacency(raw.info, 'grad') assert_equal(conn.getnnz(), 2680) # Test ch_type=None. raw.pick_types(meg='mag') find_ch_adjacency(raw.info, None) bti_fname = op.join(data_path, 'BTi', 'erm_HFH', 'c,rfDC') bti_config_name = op.join(data_path, 'BTi', 'erm_HFH', 'config') raw = read_raw_bti(bti_fname, bti_config_name, None) _, ch_names = find_ch_adjacency(raw.info, 'mag') assert 'A1' in ch_names ctf_fname = op.join(data_path, 'CTF', 'testdata_ctf_short.ds') raw = read_raw_ctf(ctf_fname) _, ch_names = find_ch_adjacency(raw.info, 'mag') assert 'MLC11' in ch_names pytest.raises(ValueError, find_ch_adjacency, raw.info, 'eog') raw_kit = read_raw_kit(fname_kit_157) neighb, ch_names = find_ch_adjacency(raw_kit.info, 'mag') assert neighb.data.size == 1329 assert ch_names[0] == 'MEG 001'
from mne.channels import find_ch_adjacency import matplotlib.pyplot as plt from metacog.config_parser import cfg from metacog import bp from metacog.utils import plot_temporal_clusters LOW_CONF_EPOCH = 24 HIGH_CONF_EPOCH = 44 ep_type = "answer" n_channels = 204 n_times = 1001 info_src = bp.epochs.fpath(subject="01") info = read_info(info_src) adjacency, ch_names = find_ch_adjacency(info, ch_type="grad") X = np.empty((0, n_channels, n_times)) y = np.empty(0) for subj in tqdm(cfg.subjects[1:], desc="Loading epochs"): ep_path = bp.epochs.fpath(subject=subj) ep = ( read_epochs(ep_path) .interpolate_bads() .pick_types(meg="grad")[ep_type] ) ep.apply_baseline() # required to merge epochs from differen subjects together ep.info["dev_head_t"] = None X_low = ep["low"].get_data().transpose([0, 2, 1]) y_low = ep["low"].events[:, 2]
tmax=tmax, df=len(epochs.events) - 2, t_val=t, p=p) print(report.format(**format_dict)) ############################################################################## # Absent specific hypotheses, we can also conduct an exploratory # mass-univariate analysis at all sensors and time points. This requires # correcting for multiple tests. # MNE offers various methods for this; amongst them, cluster-based permutation # methods allow deriving power from the spatio-temoral correlation structure # of the data. Here, we use TFCE. # Calculate adjacency matrix between sensors from their locations adjacency, _ = find_ch_adjacency(epochs.info, "eeg") # Extract data: transpose because the cluster test requires channels to be last # In this case, inference is done over items. In the same manner, we could # also conduct the test over, e.g., subjects. X = [ long_words.get_data().transpose(0, 2, 1), short_words.get_data().transpose(0, 2, 1) ] tfce = dict(start=.4, step=.4) # ideally start and step would be smaller # Calculate statistical thresholds t_obs, clusters, cluster_pv, h0 = spatio_temporal_cluster_test( X, tfce, adjacency=adjacency, n_permutations=100) # a more standard number would be 1000+ significant_points = cluster_pv.reshape(t_obs.shape).T < .05
tmax, picks=picks, baseline=None, reject=reject, preload=True) epochs.drop_channels(['EOG 061']) epochs.equalize_event_counts(event_id) X = [epochs[k].get_data() for k in event_id] # as 3D matrix X = [np.transpose(x, (0, 2, 1)) for x in X] # transpose for clustering ############################################################################### # Find the FieldTrip neighbor definition to setup sensor adjacency # ---------------------------------------------------------------- adjacency, ch_names = find_ch_adjacency(epochs.info, ch_type='mag') print(type(adjacency)) # it's a sparse matrix! plt.imshow(adjacency.toarray(), cmap='gray', origin='lower', interpolation='nearest') plt.xlabel('{} Magnetometers'.format(len(ch_names))) plt.ylabel('{} Magnetometers'.format(len(ch_names))) plt.title('Between-sensor adjacency') ############################################################################### # Compute permutation statistic # ----------------------------- #
# # inspect topomaps # group_t['effect of cue (B-A)'].plot_topomap(times=[0.20, 0.50, 1.3], # average=0.1, # mask=sig_mask, # units=None, # scalings=dict(eeg=1), # outlines='head', # sensors=True) # ############################################################################### # 7) Plot results # set up channel adjacency matrix n_tests = betas.shape[1] adjacency, ch_names = find_ch_adjacency(epochs_info, ch_type='eeg') adjacency = _setup_adjacency(adjacency, n_tests, n_times) # threshold parameters for clustering threshold = dict(start=0.2, step=0.2) clusters, cluster_stats = _find_clusters(t_clust, t_power=1, threshold=threshold, adjacency=adjacency, tail=0) # get significant clusters cl_sig_mask = cluster_stats > cluster_thresh cl_sig_mask = np.transpose(cl_sig_mask.reshape((n_times, n_channels)), (1, 0))
def test_plot_ch_adjacency(): """Test plotting of adjacency matrix.""" xyz_pos = np.array([[-0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0., 0., 0.12], [-0.1, -0.1, 0.1], [0.1, -0.1, 0.1]]) info = create_info(list('abcde'), 23, ch_types='eeg') montage = make_dig_montage( ch_pos={ch: pos for ch, pos in zip(info.ch_names, xyz_pos)}, coord_frame='head') info.set_montage(montage) # construct adjacency adj_sparse, ch_names = find_ch_adjacency(info, 'eeg') # plot adjacency fig = plot_ch_adjacency(info, adj_sparse, ch_names, kind='2d', edit=True) # find channel positions collection = fig.axes[0].collections[0] pos = collection.get_offsets().data # get adjacency lines lines = fig.axes[0].lines[4:] # (first four lines are head outlines) # make sure lines match adjacency relations in the matrix for line in lines: x, y = line.get_data() ch_idx = [np.where((pos == [[x[ix], y[ix]]]).all(axis=1))[0][0] for ix in range(2)] assert adj_sparse[ch_idx[0], ch_idx[1]] # make sure additional point is generated after clicking a channel _fake_click(fig, fig.axes[0], pos[0], xform='data') collections = fig.axes[0].collections assert len(collections) == 2 # make sure the point is green green = matplotlib.colors.to_rgba('tab:green') assert (collections[1].get_facecolor() == green).all() # make sure adjacency entry is modified after second click on another node assert adj_sparse[0, 1] assert adj_sparse[1, 0] n_lines_before = len(lines) _fake_click(fig, fig.axes[0], pos[1], xform='data') assert not adj_sparse[0, 1] assert not adj_sparse[1, 0] # and there is one line less lines = fig.axes[0].lines[4:] n_lines_after = len(lines) assert n_lines_after == n_lines_before - 1 # make sure there is still one green point ... collections = fig.axes[0].collections assert len(collections) == 2 assert (collections[1].get_facecolor() == green).all() # ... but its at a different location point_pos = collections[1].get_offsets().data assert (point_pos == pos[1]).all() # check that clicking again removes the green selection point _fake_click(fig, fig.axes[0], pos[1], xform='data') collections = fig.axes[0].collections assert len(collections) == 1 # clicking the points again adds a green line _fake_click(fig, fig.axes[0], pos[1], xform='data') _fake_click(fig, fig.axes[0], pos[0], xform='data') lines = fig.axes[0].lines[4:] assert len(lines) == n_lines_after + 1 assert lines[-1].get_color() == 'tab:green' # smoke test for 3d option adj = adj_sparse.toarray() fig = plot_ch_adjacency(info, adj, ch_names, kind='3d') # test errors # ----------- # number of channels in the adjacency matrix and info must match msg = ("``adjacency`` must have the same number of rows as the number of " "channels in ``info``") with pytest.raises(ValueError, match=msg): plot_ch_adjacency(info, adj_sparse, ch_names[:3], kind='2d') # edition mode only available for 2d plot msg = "Editing a 3d adjacency plot is not supported." with pytest.raises(ValueError, match=msg): plot_ch_adjacency(info, adj, ch_names, kind='3d', edit=True)
# set_log_level(verbose="ERROR") ch_type = "mag" # load the data X, y = assemble_epochs("answer", True, ch_type=ch_type) info_src = bp.epochs.fpath(subject="01") info = read_info(info_src) sel_idx = pick_types(info, meg=ch_type) info.pick_channels([info.ch_names[s] for s in sel_idx]) erf_low = EpochsArray(X[y == LOW_CONF_EPOCH, ...], info, tmin=-1).average() erf_high = EpochsArray(X[y == HIGH_CONF_EPOCH, ...], info, tmin=-1).average() erf_diff = combine_evoked([erf_low, -erf_high], weights="equal") adjacency, ch_names = find_ch_adjacency(info, ch_type=ch_type) # set cluster threshold # threshold = 1.0 # set family-wise p-value # p_accept = 0.05 p_accept = 0.14 X_low = X[y == LOW_CONF_EPOCH, ...].transpose(0, 2, 1) X_high = X[y == HIGH_CONF_EPOCH, ...].transpose(0, 2, 1) X_diff = X_high - X_low cluster_stats = spatio_temporal_cluster_1samp_test( X_diff, n_permutations=100, # threshold=threshold, # tail=1,