Tutorial part 2: RSA on sourse-level MEG data#

In this tutorial, we will perform source-level RSA analysis on MEG data.

If you haven’t done so, I recommend first completing Tutorial part 1: RSA on sensor-level MEG data.

While sensor-level RSA is useful to get a first impression of how neural representations unfold over time, it is not really suited to study differences between brain regions. For this, you want to so RSA in a searchlight pattern across the cortex.

The knowledge you have gained from your sensor-level analysis will serve you well for this part, as the API of MNE-RSA is mostly the same across sensor- and source-level analysis. However, performing a searchlight analysis is a heavy computation that can take a lot of time. Hence, we will also learn about the API regarding restricting the analysis to parts of the data in several ways.

In the cell below, update the data_path variable to point to where you have extracted the rsa-data.zip file to.

# ruff: noqa: E402
# sphinx_gallery_thumbnail_number=3

# Set this to where you've extracted `data.zip` to
data_path = "data"

We’ll start by loading the epochs again, but this time, we will restrict them to only two experimental conditions: the first presentations of famous faces versus scrambled faces. This will reduce the number of rows/columns in our RDMs and hence speed up computing and comparing them.

import mne

epochs = mne.read_epochs(f"{data_path}/sub-02/sub-02-epo.fif")
epochs = epochs[["face/famous/first", "scrambled/first"]]
epochs
Reading /home/vanvlm1/projects/mne-rsa/examples/tutorials/data/sub-02/sub-02-epo.fif ...
    Found the data of interest:
        t =    -200.00 ...    2900.00 ms
        0 CTF compensation matrices available
Adding metadata with 2 columns
879 matching events found
No baseline correction applied
0 projection items activated
General
Filename(s) sub-02-epo.fif
MNE object type EpochsFIF
Measurement date 2009-04-09 at 11:04:14 UTC
Participant
Experimenter MEG
Acquisition
Total number of events 297
Events counts face/famous/first: 147
scrambled/first: 150
Time range -0.200 – 2.900 s
Baseline -0.200 – 0.000 s
Sampling frequency 220.00 Hz
Time points 683
Metadata 297 rows × 2 columns
Channels
Magnetometers
Gradiometers
EOG
ECG
Stimulus
Head & sensor digitization 137 points
Filters
Highpass 1.00 Hz
Lowpass 40.00 Hz


When we select a subset of epochs, the epochs.metadata field is likewise updated to match the new selection. This feature is one of the main reasons to use the .metadata field instead of keeping a separate pandas.DataFrame manually.

epochs.metadata.info()
<class 'pandas.core.frame.DataFrame'>
Index: 297 entries, 4 to 884
Data columns (total 2 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   trigger  297 non-null    int64
 1   file     297 non-null    object
dtypes: int64(1), object(1)
memory usage: 7.0+ KB

This means we can use the epochs.metadata["file"] column to restrict the pixel and FaceNet RDMs to just those images still present in the MEG data.

In the cell below, we read the images and FaceNet embeddings and select the proper rows from the data matrices and use compute_dsm to compute the appropriate RDMs.

from glob import glob

import numpy as np
from PIL import Image

files = sorted(glob(f"{data_path}/stimuli/*.bmp"))
pixels = np.array([np.array(Image.open(f)) for f in files])

store = np.load(f"{data_path}/stimuli/facenet_embeddings.npz")
filenames = store["filenames"]
embeddings = store["embeddings"]

# Select the proper filenames
epochs_filenames = set(epochs.metadata["file"])
selection = [f in epochs_filenames for f in filenames]
filenames = filenames[selection]

# Select the proper rows from `pixels` and `embeddings` and compute the RDMs.
from mne_rsa import compute_rdm

pixel_rdm = compute_rdm(pixels[selection])
facenet_rdm = compute_rdm(embeddings[selection])

Executing the cell below will test whether the RDMs have been properly constructed and plot them.

from mne_rsa import plot_rdms
from scipy.spatial.distance import squareform

if len(pixel_rdm) != len(facenet_rdm):
    print("The pixel and FaceNet RDMs are of difference sizes, that can't be right. 🤔")
elif len(pixel_rdm) != 43956:
    print("Looks like the RDMs do not have the correct rows. 🤔")
elif (
    squareform(pixel_rdm)[:150, :150].mean() >= squareform(pixel_rdm)[150:, 150:].mean()
):
    print(
        "The pixels RDM doesn't look quite right. Make sure the rows are in alphabetical filename order. 🤔"
    )
elif (
    squareform(facenet_rdm)[:150, :150].mean()
    <= squareform(facenet_rdm)[150:, 150:].mean()
):
    print(
        "The FaceNet RDM doesn't look quite right. Make sure the rows are in alphabetical filename order. 🤔"
    )
else:
    print("The RDMs look just right! 😊")
    plot_rdms([pixel_rdm, facenet_rdm], names=["pixels", "facenet"])
pixels, facenet
The RDMs look just right! 😊

As was the case with the sensor-level RSA, we also need the y array that assigns a number to each epoch indicating which one of the 297 images was shown, taking care to assign numbers that respect the order in which the images appear in pixel_dsm and facenet_dsm.

y = np.searchsorted(filenames, epochs.metadata.file)

To source space!#

In order to perform RSA in source space, we must create source estimates for the epochs. There’s many different ways to do this, for example you’ll learn about beamformers during this workshop, but here we’re going to use the one that is fastest. If we use MNE, we can use a pre-computed inverse operator and apply it to the epochs to quickly get source estimates.

from mne.minimum_norm import apply_inverse_epochs, read_inverse_operator

inv = read_inverse_operator(f"{data_path}/sub-02/sub-02-inv.fif")
stcs = apply_inverse_epochs(epochs, inv, lambda2=1 / 9)
Reading inverse operator decomposition from /home/vanvlm1/projects/mne-rsa/examples/tutorials/data/sub-02/sub-02-inv.fif...
    Reading inverse operator info...
    [done]
    Reading inverse operator decomposition...
    [done]
    204 x 204 full covariance (kind = 1) found.
    Noise covariance matrix read.
    6150 x 6150 diagonal covariance (kind = 2) found.
    Source covariance matrix read.
    6150 x 6150 diagonal covariance (kind = 6) found.
    Orientation priors read.
    6150 x 6150 diagonal covariance (kind = 5) found.
    Depth priors read.
    Did not find the desired covariance matrix (kind = 3)
    Reading a source space...
    Computing patch statistics...
    Patch information added...
    Distance information added...
    [done]
    Reading a source space...
    Computing patch statistics...
    Patch information added...
    Distance information added...
    [done]
    2 source spaces read
    Source spaces transformed to the inverse solution coordinate frame
Preparing the inverse operator for use...
    Scaled noise and source covariance from nave = 1 to nave = 1
    Created the regularized inverter
    The projection vectors do not apply to these channels.
    Created the whitener using a noise covariance matrix with rank 68 (136 small eigenvalues omitted)
    Computing noise-normalization factors (dSPM)...
[done]
Picked 204 channels from the data
Computing inverse...
    Eigenleads need to be weighted ...
Processing epoch : 1 / 297
combining the current components...
Processing epoch : 2 / 297
combining the current components...
Processing epoch : 3 / 297
combining the current components...
Processing epoch : 4 / 297
combining the current components...
Processing epoch : 5 / 297
combining the current components...
Processing epoch : 6 / 297
combining the current components...
Processing epoch : 7 / 297
combining the current components...
Processing epoch : 8 / 297
combining the current components...
Processing epoch : 9 / 297
combining the current components...
Processing epoch : 10 / 297
combining the current components...
Processing epoch : 11 / 297
combining the current components...
Processing epoch : 12 / 297
combining the current components...
Processing epoch : 13 / 297
combining the current components...
Processing epoch : 14 / 297
combining the current components...
Processing epoch : 15 / 297
combining the current components...
Processing epoch : 16 / 297
combining the current components...
Processing epoch : 17 / 297
combining the current components...
Processing epoch : 18 / 297
combining the current components...
Processing epoch : 19 / 297
combining the current components...
Processing epoch : 20 / 297
combining the current components...
Processing epoch : 21 / 297
combining the current components...
Processing epoch : 22 / 297
combining the current components...
Processing epoch : 23 / 297
combining the current components...
Processing epoch : 24 / 297
combining the current components...
Processing epoch : 25 / 297
combining the current components...
Processing epoch : 26 / 297
combining the current components...
Processing epoch : 27 / 297
combining the current components...
Processing epoch : 28 / 297
combining the current components...
Processing epoch : 29 / 297
combining the current components...
Processing epoch : 30 / 297
combining the current components...
Processing epoch : 31 / 297
combining the current components...
Processing epoch : 32 / 297
combining the current components...
Processing epoch : 33 / 297
combining the current components...
Processing epoch : 34 / 297
combining the current components...
Processing epoch : 35 / 297
combining the current components...
Processing epoch : 36 / 297
combining the current components...
Processing epoch : 37 / 297
combining the current components...
Processing epoch : 38 / 297
combining the current components...
Processing epoch : 39 / 297
combining the current components...
Processing epoch : 40 / 297
combining the current components...
Processing epoch : 41 / 297
combining the current components...
Processing epoch : 42 / 297
combining the current components...
Processing epoch : 43 / 297
combining the current components...
Processing epoch : 44 / 297
combining the current components...
Processing epoch : 45 / 297
combining the current components...
Processing epoch : 46 / 297
combining the current components...
Processing epoch : 47 / 297
combining the current components...
Processing epoch : 48 / 297
combining the current components...
Processing epoch : 49 / 297
combining the current components...
Processing epoch : 50 / 297
combining the current components...
Processing epoch : 51 / 297
combining the current components...
Processing epoch : 52 / 297
combining the current components...
Processing epoch : 53 / 297
combining the current components...
Processing epoch : 54 / 297
combining the current components...
Processing epoch : 55 / 297
combining the current components...
Processing epoch : 56 / 297
combining the current components...
Processing epoch : 57 / 297
combining the current components...
Processing epoch : 58 / 297
combining the current components...
Processing epoch : 59 / 297
combining the current components...
Processing epoch : 60 / 297
combining the current components...
Processing epoch : 61 / 297
combining the current components...
Processing epoch : 62 / 297
combining the current components...
Processing epoch : 63 / 297
combining the current components...
Processing epoch : 64 / 297
combining the current components...
Processing epoch : 65 / 297
combining the current components...
Processing epoch : 66 / 297
combining the current components...
Processing epoch : 67 / 297
combining the current components...
Processing epoch : 68 / 297
combining the current components...
Processing epoch : 69 / 297
combining the current components...
Processing epoch : 70 / 297
combining the current components...
Processing epoch : 71 / 297
combining the current components...
Processing epoch : 72 / 297
combining the current components...
Processing epoch : 73 / 297
combining the current components...
Processing epoch : 74 / 297
combining the current components...
Processing epoch : 75 / 297
combining the current components...
Processing epoch : 76 / 297
combining the current components...
Processing epoch : 77 / 297
combining the current components...
Processing epoch : 78 / 297
combining the current components...
Processing epoch : 79 / 297
combining the current components...
Processing epoch : 80 / 297
combining the current components...
Processing epoch : 81 / 297
combining the current components...
Processing epoch : 82 / 297
combining the current components...
Processing epoch : 83 / 297
combining the current components...
Processing epoch : 84 / 297
combining the current components...
Processing epoch : 85 / 297
combining the current components...
Processing epoch : 86 / 297
combining the current components...
Processing epoch : 87 / 297
combining the current components...
Processing epoch : 88 / 297
combining the current components...
Processing epoch : 89 / 297
combining the current components...
Processing epoch : 90 / 297
combining the current components...
Processing epoch : 91 / 297
combining the current components...
Processing epoch : 92 / 297
combining the current components...
Processing epoch : 93 / 297
combining the current components...
Processing epoch : 94 / 297
combining the current components...
Processing epoch : 95 / 297
combining the current components...
Processing epoch : 96 / 297
combining the current components...
Processing epoch : 97 / 297
combining the current components...
Processing epoch : 98 / 297
combining the current components...
Processing epoch : 99 / 297
combining the current components...
Processing epoch : 100 / 297
combining the current components...
Processing epoch : 101 / 297
combining the current components...
Processing epoch : 102 / 297
combining the current components...
Processing epoch : 103 / 297
combining the current components...
Processing epoch : 104 / 297
combining the current components...
Processing epoch : 105 / 297
combining the current components...
Processing epoch : 106 / 297
combining the current components...
Processing epoch : 107 / 297
combining the current components...
Processing epoch : 108 / 297
combining the current components...
Processing epoch : 109 / 297
combining the current components...
Processing epoch : 110 / 297
combining the current components...
Processing epoch : 111 / 297
combining the current components...
Processing epoch : 112 / 297
combining the current components...
Processing epoch : 113 / 297
combining the current components...
Processing epoch : 114 / 297
combining the current components...
Processing epoch : 115 / 297
combining the current components...
Processing epoch : 116 / 297
combining the current components...
Processing epoch : 117 / 297
combining the current components...
Processing epoch : 118 / 297
combining the current components...
Processing epoch : 119 / 297
combining the current components...
Processing epoch : 120 / 297
combining the current components...
Processing epoch : 121 / 297
combining the current components...
Processing epoch : 122 / 297
combining the current components...
Processing epoch : 123 / 297
combining the current components...
Processing epoch : 124 / 297
combining the current components...
Processing epoch : 125 / 297
combining the current components...
Processing epoch : 126 / 297
combining the current components...
Processing epoch : 127 / 297
combining the current components...
Processing epoch : 128 / 297
combining the current components...
Processing epoch : 129 / 297
combining the current components...
Processing epoch : 130 / 297
combining the current components...
Processing epoch : 131 / 297
combining the current components...
Processing epoch : 132 / 297
combining the current components...
Processing epoch : 133 / 297
combining the current components...
Processing epoch : 134 / 297
combining the current components...
Processing epoch : 135 / 297
combining the current components...
Processing epoch : 136 / 297
combining the current components...
Processing epoch : 137 / 297
combining the current components...
Processing epoch : 138 / 297
combining the current components...
Processing epoch : 139 / 297
combining the current components...
Processing epoch : 140 / 297
combining the current components...
Processing epoch : 141 / 297
combining the current components...
Processing epoch : 142 / 297
combining the current components...
Processing epoch : 143 / 297
combining the current components...
Processing epoch : 144 / 297
combining the current components...
Processing epoch : 145 / 297
combining the current components...
Processing epoch : 146 / 297
combining the current components...
Processing epoch : 147 / 297
combining the current components...
Processing epoch : 148 / 297
combining the current components...
Processing epoch : 149 / 297
combining the current components...
Processing epoch : 150 / 297
combining the current components...
Processing epoch : 151 / 297
combining the current components...
Processing epoch : 152 / 297
combining the current components...
Processing epoch : 153 / 297
combining the current components...
Processing epoch : 154 / 297
combining the current components...
Processing epoch : 155 / 297
combining the current components...
Processing epoch : 156 / 297
combining the current components...
Processing epoch : 157 / 297
combining the current components...
Processing epoch : 158 / 297
combining the current components...
Processing epoch : 159 / 297
combining the current components...
Processing epoch : 160 / 297
combining the current components...
Processing epoch : 161 / 297
combining the current components...
Processing epoch : 162 / 297
combining the current components...
Processing epoch : 163 / 297
combining the current components...
Processing epoch : 164 / 297
combining the current components...
Processing epoch : 165 / 297
combining the current components...
Processing epoch : 166 / 297
combining the current components...
Processing epoch : 167 / 297
combining the current components...
Processing epoch : 168 / 297
combining the current components...
Processing epoch : 169 / 297
combining the current components...
Processing epoch : 170 / 297
combining the current components...
Processing epoch : 171 / 297
combining the current components...
Processing epoch : 172 / 297
combining the current components...
Processing epoch : 173 / 297
combining the current components...
Processing epoch : 174 / 297
combining the current components...
Processing epoch : 175 / 297
combining the current components...
Processing epoch : 176 / 297
combining the current components...
Processing epoch : 177 / 297
combining the current components...
Processing epoch : 178 / 297
combining the current components...
Processing epoch : 179 / 297
combining the current components...
Processing epoch : 180 / 297
combining the current components...
Processing epoch : 181 / 297
combining the current components...
Processing epoch : 182 / 297
combining the current components...
Processing epoch : 183 / 297
combining the current components...
Processing epoch : 184 / 297
combining the current components...
Processing epoch : 185 / 297
combining the current components...
Processing epoch : 186 / 297
combining the current components...
Processing epoch : 187 / 297
combining the current components...
Processing epoch : 188 / 297
combining the current components...
Processing epoch : 189 / 297
combining the current components...
Processing epoch : 190 / 297
combining the current components...
Processing epoch : 191 / 297
combining the current components...
Processing epoch : 192 / 297
combining the current components...
Processing epoch : 193 / 297
combining the current components...
Processing epoch : 194 / 297
combining the current components...
Processing epoch : 195 / 297
combining the current components...
Processing epoch : 196 / 297
combining the current components...
Processing epoch : 197 / 297
combining the current components...
Processing epoch : 198 / 297
combining the current components...
Processing epoch : 199 / 297
combining the current components...
Processing epoch : 200 / 297
combining the current components...
Processing epoch : 201 / 297
combining the current components...
Processing epoch : 202 / 297
combining the current components...
Processing epoch : 203 / 297
combining the current components...
Processing epoch : 204 / 297
combining the current components...
Processing epoch : 205 / 297
combining the current components...
Processing epoch : 206 / 297
combining the current components...
Processing epoch : 207 / 297
combining the current components...
Processing epoch : 208 / 297
combining the current components...
Processing epoch : 209 / 297
combining the current components...
Processing epoch : 210 / 297
combining the current components...
Processing epoch : 211 / 297
combining the current components...
Processing epoch : 212 / 297
combining the current components...
Processing epoch : 213 / 297
combining the current components...
Processing epoch : 214 / 297
combining the current components...
Processing epoch : 215 / 297
combining the current components...
Processing epoch : 216 / 297
combining the current components...
Processing epoch : 217 / 297
combining the current components...
Processing epoch : 218 / 297
combining the current components...
Processing epoch : 219 / 297
combining the current components...
Processing epoch : 220 / 297
combining the current components...
Processing epoch : 221 / 297
combining the current components...
Processing epoch : 222 / 297
combining the current components...
Processing epoch : 223 / 297
combining the current components...
Processing epoch : 224 / 297
combining the current components...
Processing epoch : 225 / 297
combining the current components...
Processing epoch : 226 / 297
combining the current components...
Processing epoch : 227 / 297
combining the current components...
Processing epoch : 228 / 297
combining the current components...
Processing epoch : 229 / 297
combining the current components...
Processing epoch : 230 / 297
combining the current components...
Processing epoch : 231 / 297
combining the current components...
Processing epoch : 232 / 297
combining the current components...
Processing epoch : 233 / 297
combining the current components...
Processing epoch : 234 / 297
combining the current components...
Processing epoch : 235 / 297
combining the current components...
Processing epoch : 236 / 297
combining the current components...
Processing epoch : 237 / 297
combining the current components...
Processing epoch : 238 / 297
combining the current components...
Processing epoch : 239 / 297
combining the current components...
Processing epoch : 240 / 297
combining the current components...
Processing epoch : 241 / 297
combining the current components...
Processing epoch : 242 / 297
combining the current components...
Processing epoch : 243 / 297
combining the current components...
Processing epoch : 244 / 297
combining the current components...
Processing epoch : 245 / 297
combining the current components...
Processing epoch : 246 / 297
combining the current components...
Processing epoch : 247 / 297
combining the current components...
Processing epoch : 248 / 297
combining the current components...
Processing epoch : 249 / 297
combining the current components...
Processing epoch : 250 / 297
combining the current components...
Processing epoch : 251 / 297
combining the current components...
Processing epoch : 252 / 297
combining the current components...
Processing epoch : 253 / 297
combining the current components...
Processing epoch : 254 / 297
combining the current components...
Processing epoch : 255 / 297
combining the current components...
Processing epoch : 256 / 297
combining the current components...
Processing epoch : 257 / 297
combining the current components...
Processing epoch : 258 / 297
combining the current components...
Processing epoch : 259 / 297
combining the current components...
Processing epoch : 260 / 297
combining the current components...
Processing epoch : 261 / 297
combining the current components...
Processing epoch : 262 / 297
combining the current components...
Processing epoch : 263 / 297
combining the current components...
Processing epoch : 264 / 297
combining the current components...
Processing epoch : 265 / 297
combining the current components...
Processing epoch : 266 / 297
combining the current components...
Processing epoch : 267 / 297
combining the current components...
Processing epoch : 268 / 297
combining the current components...
Processing epoch : 269 / 297
combining the current components...
Processing epoch : 270 / 297
combining the current components...
Processing epoch : 271 / 297
combining the current components...
Processing epoch : 272 / 297
combining the current components...
Processing epoch : 273 / 297
combining the current components...
Processing epoch : 274 / 297
combining the current components...
Processing epoch : 275 / 297
combining the current components...
Processing epoch : 276 / 297
combining the current components...
Processing epoch : 277 / 297
combining the current components...
Processing epoch : 278 / 297
combining the current components...
Processing epoch : 279 / 297
combining the current components...
Processing epoch : 280 / 297
combining the current components...
Processing epoch : 281 / 297
combining the current components...
Processing epoch : 282 / 297
combining the current components...
Processing epoch : 283 / 297
combining the current components...
Processing epoch : 284 / 297
combining the current components...
Processing epoch : 285 / 297
combining the current components...
Processing epoch : 286 / 297
combining the current components...
Processing epoch : 287 / 297
combining the current components...
Processing epoch : 288 / 297
combining the current components...
Processing epoch : 289 / 297
combining the current components...
Processing epoch : 290 / 297
combining the current components...
Processing epoch : 291 / 297
combining the current components...
Processing epoch : 292 / 297
combining the current components...
Processing epoch : 293 / 297
combining the current components...
Processing epoch : 294 / 297
combining the current components...
Processing epoch : 295 / 297
combining the current components...
Processing epoch : 296 / 297
combining the current components...
Processing epoch : 297 / 297
combining the current components...
[done]

The result is a list of 297 SourceEstimate objects. Here are the first 5 of them:

stcs[:5]
[<SourceEstimate | 2050 vertices, subject : sub-02, tmin : -200.0 (ms), tmax : 2899.9999999999995 (ms), tstep : 4.545454545454545 (ms), data shape : (2050, 683), ~10.7 MiB>, <SourceEstimate | 2050 vertices, subject : sub-02, tmin : -200.0 (ms), tmax : 2899.9999999999995 (ms), tstep : 4.545454545454545 (ms), data shape : (2050, 683), ~10.7 MiB>, <SourceEstimate | 2050 vertices, subject : sub-02, tmin : -200.0 (ms), tmax : 2899.9999999999995 (ms), tstep : 4.545454545454545 (ms), data shape : (2050, 683), ~10.7 MiB>, <SourceEstimate | 2050 vertices, subject : sub-02, tmin : -200.0 (ms), tmax : 2899.9999999999995 (ms), tstep : 4.545454545454545 (ms), data shape : (2050, 683), ~10.7 MiB>, <SourceEstimate | 2050 vertices, subject : sub-02, tmin : -200.0 (ms), tmax : 2899.9999999999995 (ms), tstep : 4.545454545454545 (ms), data shape : (2050, 683), ~10.7 MiB>]

The plan is to perform RSA in a searchlight pattern, not only as a sliding window through time, but also sliding across different locations across the cortex. To this end, we’ll define spatial patches with a certain radius, and only source points that fall within a patch are taken into account when computing the RDM for that patch. The cortex is heavily folded and ideally we define distances between source point as the shortest path along the cortex, what is known as the geodesic distance, rather than straight euclidean distance between the XYZ coordinates. MNE-Python is here to help us out in this regard, as it contains a function to compute such distances and store them within the mne.SourceSpaces object (through the mne.add_source_space_distances() function).

Let’s load the file containing the proper source space with pre-computed geodesic distances between source points:

from mne import read_source_spaces

src = read_source_spaces(f"{data_path}/freesurfer/sub-02/bem/sub-02-oct5-src.fif")
Reading a source space...
Computing patch statistics...
Patch information added...
Distance information added...
[done]
Reading a source space...
Computing patch statistics...
Patch information added...
Distance information added...
[done]
2 source spaces read

To speed things up, let’s restrict the analysis to only the occipital, parietal and temporal areas on the left hemisphere. There are several ways to tell MNE-RSA which source points to use, and one of the most convenient ones is to use mne.Label objects. This allows us to define the desired areas using the “aparc” atlas that FreeSurfer has constructed for us:

rois = mne.read_labels_from_annot(
    "sub-02", parc="aparc", subjects_dir=f"{data_path}/freesurfer", hemi="lh"
)

# These are the regions we're interested in
roi_sel = [
    "inferiortemporal-lh",
    "middletemporal-lh",
    "fusiform-lh",
    "bankssts-lh",
    "inferiorparietal-lh",
    "lateraloccipital-lh",
    "lingual-lh",
    "pericalcarine-lh",
    "cuneus-lh",
    "supramarginal-lh",
    "superiorparietal-lh",
]
rois = [r for r in rois if r.name in roi_sel]
Reading labels from parcellation...
   read 34 labels from /home/vanvlm1/projects/mne-rsa/examples/tutorials/data/freesurfer/sub-02/label/lh.aparc.annot

Source-space RSA#

Time to actually perform the RSA in source space. The function you need is mne_rsa.rsa_stcs() Take a look at the documentation of that function, which should look familiar is it is very similar to mne_rsa.rsa_epochs() that you have used before.

We will perform RSA on the source estimates, using the pixel and FaceNet RDMs as model RDMs. Searchlight patches swill have a spatial radius of 2cm (=0.02 meters) and a temporal radius of 50 ms (=0.05 seconds). We will restrict the analysis to 0.0 to 0.5 seconds after stimulus onset and to the cortical regions (rois) we’ve selected above. We can optionally set n_jobs=-1 to use all CPU cores and verbose=True to show a progress bar.

Depending on the speed of your computer, this may take anywhere from a few seconds to a few minutes to complete.

from mne_rsa import rsa_stcs

stc_rsa = rsa_stcs(
    stcs,
    [pixel_rdm, facenet_rdm],
    src=src,
    y=y,
    tmin=0,
    tmax=0.5,
    sel_vertices=rois,
    spatial_radius=0.02,
    temporal_radius=0.05,
    verbose=True,
    n_jobs=-1,
)
Restricting source space to 2050 out of [1026 1026] vertices.
Restricting source space to 2050 out of [1025 1025] vertices.
Performing RSA between SourceEstimates and 2 model RDM(s)
    Spatial radius: 0.02 meters
    Using 373 vertices
    Temporal radius: 11 samples
    Time interval: 0-0.5 seconds
    Number of searchlight patches: 41030

  0%|          | 0/41030 [00:00<?, ?patch/s]Creating spatio-temporal searchlight patches

  0%|          | 64/41030 [00:02<25:47, 26.47patch/s]
  0%|          | 96/41030 [00:02<17:06, 39.88patch/s]
  0%|          | 160/41030 [00:02<08:25, 80.82patch/s]
  1%|          | 416/41030 [00:02<02:21, 287.58patch/s]
  2%|▏         | 989/41030 [00:03<00:45, 876.65patch/s]
  4%|▍         | 1568/41030 [00:03<00:27, 1457.54patch/s]
  5%|▌         | 2080/41030 [00:03<00:19, 1986.62patch/s]
  8%|▊         | 3104/41030 [00:03<00:11, 3193.15patch/s]
 10%|█         | 4128/41030 [00:03<00:10, 3644.63patch/s]
 13%|█▎        | 5152/41030 [00:03<00:09, 3602.02patch/s]
 15%|█▌        | 6176/41030 [00:04<00:09, 3592.36patch/s]
 18%|█▊        | 7200/41030 [00:04<00:10, 3360.48patch/s]
 20%|██        | 8224/41030 [00:04<00:09, 3370.04patch/s]
 23%|██▎       | 9248/41030 [00:05<00:09, 3403.92patch/s]
 25%|██▌       | 10272/41030 [00:05<00:09, 3366.17patch/s]
 28%|██▊       | 11296/41030 [00:05<00:09, 3291.42patch/s]
 30%|███       | 12320/41030 [00:06<00:09, 3164.42patch/s]
 33%|███▎      | 13344/41030 [00:06<00:08, 3320.79patch/s]
 35%|███▌      | 14368/41030 [00:06<00:08, 3170.52patch/s]
 38%|███▊      | 15392/41030 [00:07<00:08, 3169.55patch/s]
 40%|████      | 16416/41030 [00:07<00:07, 3177.35patch/s]
 43%|████▎     | 17440/41030 [00:07<00:06, 3384.69patch/s]
 45%|████▌     | 18464/41030 [00:08<00:07, 3092.95patch/s]
 47%|████▋     | 19488/41030 [00:08<00:06, 3082.48patch/s]
 50%|████▉     | 20512/41030 [00:08<00:06, 3022.29patch/s]
 52%|█████▏    | 21536/41030 [00:09<00:06, 3067.88patch/s]
 55%|█████▍    | 22560/41030 [00:09<00:05, 3277.28patch/s]
 57%|█████▋    | 23584/41030 [00:09<00:05, 3121.85patch/s]
 60%|█████▉    | 24608/41030 [00:10<00:05, 3050.61patch/s]
 62%|██████▏   | 25632/41030 [00:10<00:04, 3106.86patch/s]
 65%|██████▍   | 26656/41030 [00:10<00:04, 3031.34patch/s]
 66%|██████▌   | 27024/41030 [00:10<00:04, 2915.85patch/s]
 67%|██████▋   | 27680/41030 [00:11<00:04, 2863.18patch/s]
 70%|██████▉   | 28704/41030 [00:11<00:04, 3027.62patch/s]
 72%|███████▏  | 29728/41030 [00:11<00:03, 2827.62patch/s]
 75%|███████▍  | 30752/41030 [00:12<00:03, 2775.25patch/s]
 77%|███████▋  | 31776/41030 [00:12<00:03, 2857.50patch/s]
 80%|███████▉  | 32800/41030 [00:13<00:03, 2589.59patch/s]
 82%|████████▏ | 33824/41030 [00:13<00:02, 2590.14patch/s]
 85%|████████▍ | 34848/41030 [00:13<00:02, 2710.28patch/s]
 87%|████████▋ | 35872/41030 [00:14<00:01, 2694.94patch/s]
 90%|████████▉ | 36896/41030 [00:14<00:01, 2651.90patch/s]
 92%|█████████▏| 37920/41030 [00:14<00:01, 2728.25patch/s]
 95%|█████████▍| 38944/41030 [00:15<00:00, 2867.68patch/s]
 97%|█████████▋| 39968/41030 [00:15<00:00, 2977.24patch/s]
100%|█████████▉| 40992/41030 [00:15<00:00, 3086.86patch/s]
100%|██████████| 41030/41030 [00:15<00:00, 2588.99patch/s]

If everyting went as planned, executing the cell below will plot the result.

# For clarity, only show positive RSA scores
stc_rsa[0].data[stc_rsa[0].data < 0] = 0
stc_rsa[1].data[stc_rsa[1].data < 0] = 0

# Show the RSA maps for both the pixel and FaceNet RDMs
brain_pixels = stc_rsa[0].plot(
    "sub-02",
    subjects_dir=f"{data_path}/freesurfer",
    hemi="both",
    initial_time=0.081,
    views="ventral",
    title="pixels",
)
brain_facenet = stc_rsa[1].plot(
    "sub-02",
    subjects_dir=f"{data_path}/freesurfer",
    hemi="both",
    initial_time=0.180,
    views="parietal",
    title="FaceNet",
)
02 source level tutorial02 source level tutorial
Using pyvistaqt 3d backend.
Using control points [0.02692218 0.03490713 0.07436469]
False
Could not estimate rigid Talairach alignment, using identity matrix
Using control points [0.03274756 0.04136883 0.110632  ]
False
Could not estimate rigid Talairach alignment, using identity matrix

If you’ve made it this far, you have successfully completed your first sensor-level RSA! 🎉 This is the end of this tutorial. In the next tutorial, we will discuss group-level analysis and statistics: Tutorial part 3: statistical analysis of group-level RSA results.

Total running time of the script: (0 minutes 28.382 seconds)

Gallery generated by Sphinx-Gallery