BIDS dataset first and second level analysis

Full step-by-step example of fitting a GLM to perform a first and second level analysis in a BIDS dataset and visualizing the results. Details about the BIDS standard can be consulted at https://bids.neuroimaging.io/.

More specifically:

  1. Download an fMRI BIDS dataset with two language conditions to contrast.

  2. Extract first level model objects automatically from the BIDS dataset.

  3. Fit a second level model on the fitted first level models. Notice that in this case the preprocessed bold images were already normalized to the same MNI space.

from nilearn import plotting

Fetch example BIDS dataset

We download a simplified BIDS dataset made available for illustrative purposes. It contains only the necessary information to run a statistical analysis using Nilearn. The raw data subject folders only contain bold.json and events.tsv files, while the derivatives folder includes the preprocessed files preproc.nii and the confounds.tsv files.

[fetch_language_localizer_demo_dataset] Dataset created in
/home/runner/nilearn_data/fMRI-language-localizer-demo-dataset
[fetch_language_localizer_demo_dataset] Downloading data from
https://osf.io/3dj2a/download ...
[fetch_language_localizer_demo_dataset] Downloaded 10706944 of 749503182 bytes
(1.4%%,  1.2min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 22355968 of 749503182 bytes
(3.0%%,  1.1min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 33488896 of 749503182 bytes
(4.5%%,  1.1min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 45105152 of 749503182 bytes
(6.0%%,  1.0min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 56221696 of 749503182 bytes
(7.5%%,  1.0min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 66543616 of 749503182 bytes
(8.9%%,  1.0min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 77225984 of 749503182 bytes
(10.3%%,  1.0min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 88309760 of 749503182 bytes
(11.8%%,  1.0min remaining)
[fetch_language_localizer_demo_dataset] Downloaded 99246080 of 749503182 bytes
(13.2%%,   59.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 108486656 of 749503182 bytes
(14.5%%,   59.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 118194176 of 749503182 bytes
(15.8%%,   59.0s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 127590400 of 749503182 bytes
(17.0%%,   58.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 138764288 of 749503182 bytes
(18.5%%,   57.4s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 149110784 of 749503182 bytes
(19.9%%,   56.6s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 158523392 of 749503182 bytes
(21.2%%,   56.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 166092800 of 749503182 bytes
(22.2%%,   56.4s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 174751744 of 749503182 bytes
(23.3%%,   56.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 184164352 of 749503182 bytes
(24.6%%,   55.4s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 193994752 of 749503182 bytes
(25.9%%,   54.6s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 203464704 of 749503182 bytes
(27.1%%,   53.8s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 213123072 of 749503182 bytes
(28.4%%,   53.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 223854592 of 749503182 bytes
(29.9%%,   52.0s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 234856448 of 749503182 bytes
(31.3%%,   50.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 246906880 of 749503182 bytes
(32.9%%,   49.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 259604480 of 749503182 bytes
(34.6%%,   47.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 273661952 of 749503182 bytes
(36.5%%,   45.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 286613504 of 749503182 bytes
(38.2%%,   43.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 302727168 of 749503182 bytes
(40.4%%,   41.6s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 318480384 of 749503182 bytes
(42.5%%,   39.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 332308480 of 749503182 bytes
(44.3%%,   37.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 346054656 of 749503182 bytes
(46.2%%,   36.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 358498304 of 749503182 bytes
(47.8%%,   35.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 369934336 of 749503182 bytes
(49.4%%,   34.0s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 382107648 of 749503182 bytes
(51.0%%,   32.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 394141696 of 749503182 bytes
(52.6%%,   31.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 407126016 of 749503182 bytes
(54.3%%,   30.4s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 419733504 of 749503182 bytes
(56.0%%,   29.2s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 430448640 of 749503182 bytes
(57.4%%,   28.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 441376768 of 749503182 bytes
(58.9%%,   27.4s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 451862528 of 749503182 bytes
(60.3%%,   26.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 461611008 of 749503182 bytes
(61.6%%,   25.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 471302144 of 749503182 bytes
(62.9%%,   24.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 480813056 of 749503182 bytes
(64.2%%,   24.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 489422848 of 749503182 bytes
(65.3%%,   23.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 498180096 of 749503182 bytes
(66.5%%,   22.8s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 507674624 of 749503182 bytes
(67.7%%,   22.0s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 518651904 of 749503182 bytes
(69.2%%,   21.0s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 530219008 of 749503182 bytes
(70.7%%,   19.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 541728768 of 749503182 bytes
(72.3%%,   18.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 550199296 of 749503182 bytes
(73.4%%,   18.2s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 558661632 of 749503182 bytes
(74.5%%,   17.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 568156160 of 749503182 bytes
(75.8%%,   16.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 578723840 of 749503182 bytes
(77.2%%,   15.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 590135296 of 749503182 bytes
(78.7%%,   14.7s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 602431488 of 749503182 bytes
(80.4%%,   13.5s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 615448576 of 749503182 bytes
(82.1%%,   12.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 629841920 of 749503182 bytes
(84.0%%,   10.9s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 643596288 of 749503182 bytes
(85.9%%,    9.6s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 658669568 of 749503182 bytes
(87.9%%,    8.2s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 673734656 of 749503182 bytes
(89.9%%,    6.8s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 687226880 of 749503182 bytes
(91.7%%,    5.6s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 700768256 of 749503182 bytes
(93.5%%,    4.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 712663040 of 749503182 bytes
(95.1%%,    3.3s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 725278720 of 749503182 bytes
(96.8%%,    2.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 736583680 of 749503182 bytes
(98.3%%,    1.1s remaining)
[fetch_language_localizer_demo_dataset] Downloaded 748617728 of 749503182 bytes
(99.9%%,    0.1s remaining)
[fetch_language_localizer_demo_dataset]  ...done. (68 seconds, 1 min)

[fetch_language_localizer_demo_dataset] Extracting data from
/home/runner/nilearn_data/fMRI-language-localizer-demo-dataset/fMRI-language-loc
alizer-demo-dataset.zip...
[fetch_language_localizer_demo_dataset] .. done.

Here is the location of the dataset on disk.

/home/runner/nilearn_data/fMRI-language-localizer-demo-dataset

Obtain automatically FirstLevelModel objects and fit arguments

From the dataset directory we automatically obtain the FirstLevelModel objects with their subject_id filled from the BIDS dataset. Moreover, we obtain for each model a dictionary with run_imgs, events and confounder regressors since in this case a confounds.tsv file is available in the BIDS dataset. To get the first level models we only have to specify the dataset directory and the task_label as specified in the file names.

from nilearn.glm.first_level import first_level_from_bids

task_label = "languagelocalizer"
(
    models,
    models_run_imgs,
    models_events,
    models_confounds,
) = first_level_from_bids(
    data.data_dir,
    task_label,
    img_filters=[("desc", "preproc")],
    n_jobs=2,
    space_label="",
    smoothing_fwhm=8,
)
/home/runner/work/nilearn/nilearn/examples/07_advanced/plot_bids_analysis.py:61: RuntimeWarning: 'StartTime' not found in file /home/runner/nilearn_data/fMRI-language-localizer-demo-dataset/derivatives/sub-01/func/sub-01_task-languagelocalizer_desc-preproc_bold.json.
  ) = first_level_from_bids(
/home/runner/work/nilearn/nilearn/examples/07_advanced/plot_bids_analysis.py:61: UserWarning: 'slice_time_ref' not provided and cannot be inferred from metadata.
It will be assumed that the slice timing reference is 0.0 percent of the repetition time.
If it is not the case it will need to be set manually in the generated list of models.
  ) = first_level_from_bids(

Quick sanity check on fit arguments

Additional checks or information extraction from pre-processed data can be made here.

We just expect one run_img per subject.

from pathlib import Path

print([Path(run).name for run in models_run_imgs[0]])
['sub-01_task-languagelocalizer_desc-preproc_bold.nii.gz']

The only confounds stored are regressors obtained from motion correction. As we can verify from the column headers of the confounds table corresponding to the only run_img present.

print(models_confounds[0][0].columns)
Index(['RotX', 'RotY', 'RotZ', 'X', 'Y', 'Z'], dtype='object')

During this acquisition the subject read blocks of sentences and consonant strings. So these are our only two conditions in events. We verify there are 12 blocks for each condition.

print(models_events[0][0]["trial_type"].value_counts())
trial_type
language    12
string      12
Name: count, dtype: int64

First level model estimation

Now we simply fit each first level model and plot for each subject the contrast that reveals the language network (language - string). Notice that we can define a contrast using the names of the conditions specified in the events dataframe. Sum, subtraction and scalar multiplication are allowed.

Set the threshold as the z-variate with an uncorrected p-value of 0.001.

from scipy.stats import norm

p001_unc = norm.isf(0.001)

Prepare figure for concurrent plot of individual maps.

from math import ceil

import matplotlib.pyplot as plt
import numpy as np

ncols = 2
nrows = ceil(len(models) / ncols)

fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(10, 12))
axes = np.atleast_2d(axes)
model_and_args = zip(
    models, models_run_imgs, models_events, models_confounds, strict=False
)
for midx, (model, imgs, events, confounds) in enumerate(model_and_args):
    # fit the GLM
    model.fit(imgs, events, confounds)
    # compute the contrast of interest
    zmap = model.compute_contrast("language-string")
    plotting.plot_glass_brain(
        zmap,
        threshold=p001_unc,
        title=f"sub-{model.subject_label}",
        axes=axes[int(midx / ncols), int(midx % ncols)],
        plot_abs=False,
        colorbar=True,
        display_mode="x",
        vmin=-12,
        vmax=12,
    )
fig.suptitle("subjects z_map language network (unc p<0.001)")
plotting.show()
subjects z_map language network (unc p<0.001)

Second level model estimation

We just have to provide the list of fitted FirstLevelModel objects to the SecondLevelModel object for estimation. We can do this because all subjects share a similar design matrix (same variables reflected in column names).

from nilearn.glm.second_level import SecondLevelModel

second_level_input = models

Note that we apply a smoothing of 8mm.

Computing contrasts at the second level is as simple as at the first level. Since we are not providing confounders we are performing a one-sample test at the second level with the images determined by the specified first level contrast.

zmap = second_level_model.compute_contrast(
    first_level_contrast="language-string"
)

The group level contrast reveals a left lateralized fronto-temporal language network.

plotting.plot_glass_brain(
    zmap,
    threshold=p001_unc,
    title="Group language network (unc p<0.001)",
    plot_abs=False,
    display_mode="x",
    figure=plt.figure(figsize=(5, 4)),
)
plotting.show()
plot bids analysis

Generate and save the GLM report at the group level.

report_slm = second_level_model.generate_report(
    contrasts="intercept",
    first_level_contrast="language-string",
    threshold=p001_unc,
    display_mode="x",
)
/home/runner/work/nilearn/nilearn/examples/07_advanced/plot_bids_analysis.py:183: UserWarning: 'threshold=3.090232306167813' will not be used with 'height_control='fpr''. 'threshold' is only used when 'height_control=None'. Set 'threshold' to '3.09' to avoid this warning.
  report_slm = second_level_model.generate_report(
/home/runner/work/nilearn/nilearn/examples/07_advanced/plot_bids_analysis.py:183: UserWarning: 'threshold=3.090232306167813' will not be used with 'height_control='fpr''. 'threshold' is only used when 'height_control=None'. Set 'threshold' to '3.0' to avoid this warning.
  report_slm = second_level_model.generate_report(

View the GLM report at the group level.

Statistical Report - Second Level Model Implement the :term:`General Linear Model<GLM>` for multiple subject :term:`fMRI` data.

Description

Data were analyzed using Nilearn (version= 0.12.2.dev102+g8ff979b55; RRID:SCR_001362).

At the group level, a mass univariate analysis was performed with a linear regression at each voxel of the brain.

Input images were smoothed with gaussian kernel (full-width at half maximum=8.0 mm).

The following contrasts were computed :

  • intercept

Model details

Value
Parameter
smoothing_fwhm (mm) 8.0

Mask

Mask image

The mask includes 23640 voxels (23.1 %) of the image.

Statistical Maps

intercept

Stat map plot for the contrast: intercept
Cluster Table
Height control fpr
α 0.001
Threshold (computed) 3.09
Cluster size threshold (voxels) 0
Minimum distance (mm) 8.0
Cluster ID X Y Z Peak Stat Cluster Size (mm3)
1 -57.5 -48.5 13.5 4.43 6652
1a -71.0 -53.0 18.0 3.64
2 -62.0 -8.0 49.5 4.32 1184
2a -53.0 -8.0 45.0 4.17
2b -48.5 -3.5 54.0 3.16
3 -48.5 -30.5 -22.5 3.98 637
4 46.0 5.5 -27.0 3.91 3371
4a 50.5 23.5 -27.0 3.80
4b 55.0 14.5 -18.0 3.79
5 -71.0 -17.0 -4.5 3.89 9841
5a -53.0 -8.0 -9.0 3.82
5b -66.5 1.0 -4.5 3.82
5c -48.5 19.0 -18.0 3.69
6 -39.5 -3.5 -40.5 3.60 455
7 50.5 -12.5 -9.0 3.51 364
8 -48.5 14.5 18.0 3.43 364
9 -75.5 -35.0 4.5 3.32 91
10 32.5 -17.0 -27.0 3.26 91
11 -44.0 -17.0 -31.5 3.13 182

About

  • Date preprocessed:


Or in a separate browser window report_slm.open_in_browser()

Save the report to disk

output_dir = Path.cwd() / "results" / "plot_bids_analysis"
output_dir.mkdir(exist_ok=True, parents=True)
report_slm.save_as_html(output_dir / "report_slm.html")

Total running time of the script: (2 minutes 31.193 seconds)

Estimated memory usage: 1267 MB

Gallery generated by Sphinx-Gallery