Simple package to run RSA analyses on fMRI data. Currently, it only contains 2 modules for RSA searhclight, and ROI-based RSA.
Before installation
The package uses the following dependencies:
pandas, numpy, nibabel, scipy, joblib, tqdm, collections
If you don't have them installed, simply run:
pip install pandas numpy nibabel scipy joblib tqdm collections
Installation
- Download the tar.gz file
- Go to the directory in which it was downloaded
- Run
pip install simplyRSA-[ver].tar.gz
Here is a simple example on how to use the searchlight module:
Imports
import pandas as pd, numpy as np
import nibabel as nib
from simplyRSA.searchlight import *
- Read your functional images and create a brain mask. Here, I'm reading a .BRIK file from AFNI, but you can read other files (like Nifti). The important thing is that the resulting brain image is a 4d image with 3 spatial dimensions and a 4th dimensions representing volumes (or trials)
brikpath = [path to my .BRIK file] # Define image path
brikdata = nib.load(brikpath).get_fdata() # Read and extract the data from the image
My .BRIK file is a 4d image, with volumes (or trials) as the last dimension
So I isolate 1 volume, and create a binary brain mask, with True where there is a value in the image, and False where there is no value (i.e. 0)
onevol = brikdata[...,0] # Isolate 1 volume
mask = onevol!=0 # Binary mask
- Create all possible spheres within the mask
We need 2 important values: voxel size (you can check that on your image header), and sphere radius. My voxel size is 2x2x2, and I want 5mm radius spheres
sphere_radius = 5 # Adjust the radius as needed
voxel_size_mm = 2 # Adjust the voxel size if it's different
Then we call the first function, which is searchlight_spheres_parallel as it follows:
spheres_info = searchlight_spheres_parallel(mask, sphere_radius, voxel_size_mm, jobs=36)
The jobs argument specifies how many CPUs are used in parallel for this (hence the name)
If you are unsure of how many CPUs your PC has, by providing -1 you tell the function to use ALL (the merrier the better). It defaults to 5, which is a number most PCs will have.
The function will return a list of sphereInfo objects, containing center and neighbours indices. We just need to have the variable saved to pass it to the next step
- Get brain RDMs by calling get_brain_RDMs
We need to pass the brain data we loaded earlier, the spheres extracted in step 2, and labels for the trials. In some instances, you can extract the labels from the header, as it is my case. But you can prepare the labels before-hand and load them
headpath = [path to my header]
labels = nib.brikhead.parse_AFNI_header(headpath)["BRICK_LABS"].split("~")[1:960:2] # Extract labels
labels = [element.replace("#", "").replace("_Coef", "") for element in labels] # Beautify labels
If you don't have the labels, or especially if you don't care about them, simply pass a range of numbers as long as your number of trials:
labels = np.arange(brikdata.shape[-1])
And now we can run the function
all_rdms = get_brain_RDMs(
brikdata,
spheres_info,
labels,
jobs=36
)
- Get model similarities
Now we feed the all_rdms variable we just created to the function get_model_similarities
We also need a model in pandas DataFrame format, read from whatever source. In my case, I have an excel file:
modelpath = [path to my model]
model = pd.read_excel(modelpath)
IMPORTANT: the model should be a n X n where n is your number of trials. The columns and rows should be ordered as they were ordered in the functional image.
model_simil = get_model_similarities(
brain_rdms, model,
jobs=5,
dist_method="correlation"
)
- Save the output to a Nifti file
Finally, we save the image in the original space (MNI conversion is not implemented yet)
Here we need to provide 1 volume of the original image. For this, we only need again the path to the image (the function already manages the extraction of the dimensions), provided the image is 4-dimensional. In this example, we can use the variable brikpath we defined earlier.
sims_to_nifti(
brikpath
model_simil,
prefix=[output_filename]
)
3.a. Alternatively, you can run steps 3 and 4 all in one by using get_model_sim_allin. This is the recommended way of running it, since it is way more efficient, and consumes way less memory.
In this case, we need the brain data, and spheres info. Other than that, it runs like in the 2 steps above.
model_simil = get_model_sim_allin(
brikdata,
spheres_info,
model,
labels,
jobs=36
)