Issue with Vertices in Source Localization Analysis

Hello everyone,

Iā€™ve been working on a source localization analysis using mne-Python, and I need some help with an issue that is probably related to the vertices. Hereā€™s the context:

Iā€™m examining the difference in neural activity between two conditions. Using cluster-based permutation tests on ERP levels, I found a significant cluster over both hemispheres in occipital regions between 200 and 380 ms after stimulus onset. Now, I aim to identify brain areas contributing to this ERP difference by testing whether the mean activity within specific, preselected ROIs differs in my detected time window. Iā€™m using a standard source space model for all analyses. After making the forward solution, computing the covariance matrix, creating the inverse operators, and applying the inverse operators to get the source estimates, I get the following array Y (Vertices, Time Points in ms, Subjects, Conditions). In my case, Y(20484, 180, 38, 2).

So far so goodā€¦

In the next step, I selected an atlas (HCPMMP1) and a specific ROI (e.g., V1), extracted the relevant vertices for V1, and filtered these vertices from all my vertices in Y. I then summarized the activity over the time series for each person in the selected vertices to get the mean activity within the 180 ms of interest in V1. Now, it is possible to test the differences of the mean activity between both conditions in my ROI with a t-test, for example.

Additionally, I tried to visualize the mean activity in my ROI over the time course of 180 ms. But the problem is that regardless of the region I select, I always find a significant difference in the time window. Also, the mean activity plots always show the same patterns regardless of the ROI selected. It doesnā€™t matter if Iā€™m analyzing a frontal region or a visual region. Based on the task, there should be no difference in the mean activity between both conditions in frontal regions.

I suspect there is an issue with the vertices or how they are selected from my source estimates. The standard brain has 20484 vertices, which I believe donā€™t match those of the HCPMMP1 atlas. Is this possible? When selecting a sample region (e.g., V1), it might have, for example, 9300 vertices, but their numbering ranges from 36 to 162,000. But Iā€™m only selecting vertices up to 20484 from my array Y because it only contains 20484 vertices, meaning Iā€™m not selecting the relevant 9300 vertices of the ROI but only 1100.

Here is an example of the relevant part of my code:

# Extract ROI region vertices
ROI_labels = mne.read_labels_from_annot('fsaverage', parc='HCPMMP1', 
subjects_dir=subjects_dir, verbose=False) #HCPMMP1
selected_ROIs = ['V1']
ROI_vertices = [label.vertices for label in ROI_labels if any(roi in label.name 
for roi in selected_ROIs)]

# Flatten the list of ROI vertices
ROI_vertices = np.concatenate(ROI_vertices)

# Mask data to include only ROI vertices
ROI_indices = np.in1d(np.concatenate([src[0]['vertno'], src[1]['vertno']]), 
ROI_vertices)
X_ROI = Y[ROI_indices, :, :, :]

# Extract and save source activation data
condition1_data = X_ROI[:, :, :, 0]
condition2_data = X_ROI[:, :, :, 1]

# Calculate the mean over the first and second dimensions
mean_condition1_data = np.mean(condition1_data, axis=(0, 1))
mean_condition2_data = np.mean(condition2_data, axis=(0, 1))

Does my suspicion make sense, and could this lead to the same pattern? Does anyone have any suggestions to resolve this issue?

I hope I was able to explain my problem sufficiently.

Thanks for your time!

Best regards, Chris

Not sure if it is revelant to your quiestion. While i was extracting time course for a particular ROI extracted from mne.read_labels_from_annot, I used mne.extract_label_time_course. You will have to input your source estimates, labels and your source space.

Perhaps 20484 is the number of sources, but not the number of vertices? See the ā€œsetting up source spaceā€ session: The typical M/EEG workflow ā€” MNE 1.7.1 documentation

1 Like

It depends how you constructed your matrix X_ROI. if it has len(src[0]['vertno']) + len(src[1]['vertno']) rows and the first row contains the activity of the vertex with the number: src[0]['vertno'][0] I think your masking should work. :thinking:

Itā€™s true that the numbering will differ, because not every vertex of the atlas has an associated source point (depends on the setup of the source space). It may be better to use the mne.extract_label_time_course function or similar, as the poster above suggested.

For verifying the ROI_vertices, I like:

brain = mne.viz.Brain('fsaverage', 'lh', 'pial', subjects_dir=subjects_dir)
brain.add_foci(ROI_vertices, hemi='lh', coords_as_verts=True, color='r', scale_factor=0.1)

which letā€™s you check whether the points you wanted have been selected. (I think for HCPMMP1 you would select more, because more stuff has V1 in the label.name.)

1 Like