Note
Go to the end to download the full example code. or to run this example in your browser via Binder
Pairwise functional alignment.¶
In this tutorial, we show how to better predict new contrasts for a target subject using source subject corresponding contrasts and data in common.
We mostly rely on python common packages and on nilearn to handle functional data in a clean fashion.
To run this example, you must launch IPython via ipython
--matplotlib
in a terminal, or use jupyter-notebook
.
Retrieve the data¶
In this example we use the IBC dataset, which include a large number of different contrasts maps for 12 subjects. We download the images for subjects sub-01 and sub-02 (or retrieve them if they were already downloaded) Files is the list of paths for each subjects. df is a dataframe with metadata about each of them. mask is an appropriate nifti image to select the data.
Added README.md to /home/runner/nilearn_data
Dataset created in /home/runner/nilearn_data/ibc
Downloading data from https://osf.io/pcvje/download ...
...done. (2 seconds, 0 min)
Extracting data from /home/runner/nilearn_data/ibc/8e275a34345802c5c273312d85957d6c/download..... done.
Downloading data from https://osf.io/yvju3/download ...
...done. (2 seconds, 0 min)
Extracting data from /home/runner/nilearn_data/ibc/fe06df963fcb3fd454f63a33f0864e8d/download..... done.
Downloading data from https://osf.io/8z23h/download ...
Downloaded 9150464 of 21185337 bytes (43.2%, 1.3s remaining) ...done. (3 seconds, 0 min)
Extracting data from /home/runner/nilearn_data/ibc/100352739b7501f0ed04920933b4be36/download..... done.
Downloading data from https://osf.io/e9kbm/download ...
Downloaded 16908288 of 21196887 bytes (79.8%, 0.3s remaining) ...done. (3 seconds, 0 min)
Extracting data from /home/runner/nilearn_data/ibc/331a0a579c6e46c0911502a96215b358/download..... done.
Define a masker¶
- We define a nilearn masker that will be used to handle relevant data.
For more information, visit : ‘http://nilearn.github.io/manipulating_images/masker_objects.html’
from nilearn.maskers import NiftiMasker
masker = NiftiMasker(mask_img=mask)
mask
masker.fit()
Prepare the data¶
For each subject, for each task and conditions, our dataset contains two independent acquisitions, similar except for one acquisition parameter, the encoding phase used that was either Antero-Posterior (AP) or Postero-Anterior (PA).
Although this induces small differences in the final data, we will take advantage of these “duplicates to create a training and a testing set that contains roughly the same signals but acquired totally independently.
# The training fold, used to learn alignment from source subject toward target:
# * source train: AP contrasts for subject sub-01
# * target train: AP contrasts for subject sub-02
source_train = df[df.subject == "sub-01"][df.acquisition == "ap"].path.values
target_train = df[df.subject == "sub-02"][df.acquisition == "ap"].path.values
# The testing fold:
# * source test: PA contrasts for subject sub-01, used to predict
# the corresponding contrasts of subject sub-02
# * target test: PA contrasts for subject sub-02, used as a ground truth
# to score our predictions
source_test = df[df.subject == "sub-01"][df.acquisition == "pa"].path.values
target_test = df[df.subject == "sub-02"][df.acquisition == "pa"].path.values
/home/runner/work/fmralign/fmralign/examples/plot_pairwise_alignment.py:62: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
source_train = df[df.subject == "sub-01"][df.acquisition == "ap"].path.values
/home/runner/work/fmralign/fmralign/examples/plot_pairwise_alignment.py:63: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
target_train = df[df.subject == "sub-02"][df.acquisition == "ap"].path.values
/home/runner/work/fmralign/fmralign/examples/plot_pairwise_alignment.py:71: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
source_test = df[df.subject == "sub-01"][df.acquisition == "pa"].path.values
/home/runner/work/fmralign/fmralign/examples/plot_pairwise_alignment.py:72: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
target_test = df[df.subject == "sub-02"][df.acquisition == "pa"].path.values
Define the estimator, fit it and predict¶
To proceed with alignment we use PairwiseAlignment class. We will use the common model proposed in the literature: * we will align the whole brain through multiple local alignments. * these alignments are calculated on a parcellation of the brain in 150
pieces, this parcellation creates group of functionnally similar voxels.
from fmralign.pairwise_alignment import PairwiseAlignment
alignment_estimator = PairwiseAlignment(
alignment_method="scaled_orthogonal", n_pieces=150, mask=masker
)
# Learn alignment operator from subject 1 to subject 2 on training data
alignment_estimator.fit(source_train, target_train)
# Predict test data for subject 2 from subject 1
target_pred = alignment_estimator.transform(source_test)
/opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/nilearn/_utils/masker_validation.py:113: UserWarning: Overriding provided-default estimator parameters with provided masker parameters :
Parameter mask_strategy :
Masker parameter background - overriding estimator parameter epi
Parameter smoothing_fwhm :
Masker parameter None - overriding estimator parameter 4.0
warnings.warn(warn_str)
Score the baseline and the prediction¶
We use a utility scoring function to measure the voxelwise correlation between the prediction and the ground truth. That is, for each voxel, we measure the correlation between its profile of activation without and with alignment, to see if alignment was able to predict a signal more alike the ground truth.
from fmralign.metrics import score_voxelwise
# Now we use this scoring function to compare the correlation of aligned and
# original data from sub-01 made with the real PA contrasts of sub-02.
baseline_score = masker.inverse_transform(
score_voxelwise(target_test, source_test, masker, loss="corr")
)
aligned_score = masker.inverse_transform(
score_voxelwise(target_test, target_pred, masker, loss="corr")
)
Plotting the measures¶
Finally we plot both scores
from nilearn import plotting
baseline_display = plotting.plot_stat_map(
baseline_score, display_mode="z", vmax=1, cut_coords=[-15, -5]
)
baseline_display.title("Baseline correlation wt ground truth")
display = plotting.plot_stat_map(
aligned_score, display_mode="z", cut_coords=[-15, -5], vmax=1
)
display.title("Prediction correlation wt ground truth")
We can see on the plot that after alignment the prediction made for one subject data, informed by another subject are greatly improved.
Total running time of the script: (1 minutes 41.767 seconds)