Output resolution of sMRIPrep and fMRIPrep

@ltetrel and @yohanchatelain have hit a common issue with fMRIPrep’s and sMRIPrep’s default outputs. Sometimes, minimal variations in the original image’s resolution would end up with slightly different NIfTI orientation prescriptions and matrix, making direct aggregation of results in some standardized space impossible.

The default prescription replicates the resolution of the original image (T1w or BOLD) that is going to be resampled into standard space, and then samples the FoV of the target template with that resolution. This is useful when images have large voxels and it feels unnecessary to impose, e.g., 2mm cubic; or very high-res images that should not be rounded to 1mm or 2mm cubic.

To avoid this, one can specify an existing resolution of the template with, e.g., --output-spaces MNI152NLin6Asym:res-2. One side issue is that we don’t know if this works for sMRIPrep outputs ATM.

What would be the most adequate way of coming up with an efficient new convention for this?

Some other considerations to note include that for BOLD datasets it would make sense to try to reduce the FoV of the outputs to a bounding box that contains only the brain (plus some safety padding). This would reduce the size of the output data, esp. for very long datasets.

1 Like

Here is an example with two functional images that uses the same template (MNI152NLin2009cAsym):

>>> file1 = "(...)/fmriprep/sub-3002498/ses-V10/func/sub-3002498_ses-V10_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
>>> nibabel.load(file1).affine
array([[   3.5,    0. ,    0. ,  -96.5],
       [   0. ,    3.5,    0. , -132.5],
       [   0. ,    0. ,    3.5,  -78.5],
       [   0. ,    0. ,    0. ,    1. ]])
>>> file2 = "(...)/fmriprep/sub-3002498/ses-V10/func/sub-3002498_ses-V10_task-memory_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
>>> nibabel.load(file2).affine
array([[   3.       ,    0.       ,    0.       ,  -96.5      ],
       [   0.       ,    3.       ,    0.       , -132.5      ],
       [   0.       ,    0.       ,    3.8499999,  -78.5      ],
       [   0.       ,    0.       ,    0.       ,    1.       ]])

For another participant:

>>> file1 = "(...)/fmriprep/sub-3025432/ses-V10/func/sub-3025432_ses-V10_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
>>> nibabel.load(file1).affine
array([[   3.5,    0. ,    0. ,  -96.5],
       [   0. ,    3.5,    0. , -132.5],
       [   0. ,    0. ,    3.5,  -78.5],
       [   0. ,    0. ,    0. ,    1. ]])
>>> file2 = "(...)/fmriprep/sub-3025432/ses-V10/func/sub-3025432_ses-V10_task-memory_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
>>> nibabel.load(file2).affine
array([[   3.        ,    0.        ,    0.        ,  -96.5       ],
       [   0.        ,    3.        ,    0.        , -132.5       ],
       [   0.        ,    0.        ,    3.29999995,  -78.5       ],
       [   0.        ,    0.        ,    0.        ,    1.        ]])

I would need to double check the ethics to share the raw volumes if needed.

Here is the fMRIPrep command that was used to preprocess:
singularity run --cleanenv -B $SLURM_TMPDIR:/DATA -B /home/ltetrel/.cache/templateflow:/templateflow -B /etc/pki:/etc/pki/ -B /scratch/ltetrel/cima-q/1636990190:/OUTPUT /lustre03/project/6003287/containers/fmriprep-20.2.1lts.sif -w /DATA/fmriprep_work --participant-label 3002498 --bids-filter-file /OUTPUT/bids_filters.json --output-spaces MNI152NLin2009cAsym MNI152NLin6Asym anat fsnative --output-layout bids --notrack --skip_bids_validation --write-graph --omp-nthreads 8 --nprocs 16 --mem_mb 65536 --resource-monitor /DATA/cima-q /DATA/cima-q/derivatives/fmriprep participant

Thanks,