What extra metadata should I feed fMRIPrep to help it run better?

Hello! Please forgive me if I misuse some jargon - I’m new to this.

I’m currently working on preprocessing and analyzing a concurrent EEG/fMRI study. I’m trying to figure out whether fMRIPrep can clean my data better than it currently does. I’m aware that I should include SliceTiming with my functional data to get slice correction. Are there any other metadata fields I can include to get even better results? Alternatively, is there any metadata I can include to shorten fMRIPrep’s processing time? It takes an awfully long time right now :slight_smile:

Hi, sorry for the delayed response. I don’t think the answer you’re looking for is going to be from the arguments to fMRIPrep. You should still read through the options here https://fmriprep.org/en/stable/usage.html and make sure you are using everything applicable to your study.

I think the main impact on performance will be related to how you are running fMRIPrep. What operating system are you running fMRIPrep on, and are you running all subjects in one script or having one script per subject?

If you have access to an HPC/Cluster, you can create a script to submit parallel jobs for all of your subjects (I can help if that is something you haven’t done before), rather than using one job and doing all subjects individually. This way, you can run all subjects at once, and devote a lot of memory/CPUs to each job. Does this make sense?

Best,
Steven

I’m running fmriprep-docker.exe on Windows 10 with 11 cores and 24 GB RAM allocated to the container. Here’s the output from docker stats for the container:

For some reason, I haven’t seen the container hit more than 8GB RAM usage yet. I’m currently running all the subjects in one script, but my PI just bought access to a cluster, so we might start using that.

And here's the input directory structure!

C:.
│ dataset_description.json

├───sourcedata
│ sub-102_settings.txt
│ sub-102_task-gabor.dat
│ sub-104_settings.txt
│ sub-104_task-gabor.dat
│ sub-106_settings.txt
│ sub-106_task-gabor.dat
│ sub-107_settings.txt
│ sub-107_task-gabor.dat
│ sub-108_settings.txt
│ sub-108_task-gabor.dat
│ sub-109_settings.txt
│ sub-109_task-gabor.dat
│ sub-110_settings.txt
│ sub-110_task-gabor.dat
│ sub-111_settings.txt
│ sub-111_task-gabor.dat
│ sub-112_settings.txt
│ sub-112_task-gabor.dat
│ sub-113_settings.txt
│ sub-113_task-gabor.dat
│ sub-115_settings.txt
│ sub-115_task-gabor.dat
│ sub-116_settings.txt
│ sub-116_task-gabor.dat
│ sub-117_settings.txt
│ sub-117_task-gabor.dat
│ sub-120_settings.txt
│ sub-120_task-gabor.dat
│ sub-121_settings.txt
│ sub-121_task-gabor.dat
│ sub-122_settings.txt
│ sub-122_task-gabor.dat
│ sub-123_settings.txt
│ sub-123_task-gabor.dat
│ sub-124_settings.txt
│ sub-124_task-gabor.dat
│ sub-125_settings.txt
│ sub-125_task-gabor.dat
│ sub-126_settings.txt
│ sub-126_task-gabor.dat

├───sub-102
│ ├───anat
│ │ sub-102_T1w.nii
│ │
│ ├───eeg
│ │ sub-102_task-gabor_eeg.eeg
│ │ sub-102_task-gabor_eeg.vhdr
│ │ sub-102_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-102_task-gabor_bold.json
│ sub-102_task-gabor_bold.nii
│ sub-102_task-gabor_events.tsv

├───sub-104
│ ├───anat
│ │ sub-104_T1w.nii
│ │
│ ├───eeg
│ │ sub-104_task-gabor_eeg.eeg
│ │ sub-104_task-gabor_eeg.vhdr
│ │ sub-104_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-104_task-gabor_bold.json
│ sub-104_task-gabor_bold.nii
│ sub-104_task-gabor_events.tsv

├───sub-106
│ ├───anat
│ │ sub-106_T1w.nii
│ │
│ ├───eeg
│ │ sub-106_task-gabor_eeg.eeg
│ │ sub-106_task-gabor_eeg.vhdr
│ │ sub-106_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-106_task-gabor_bold.json
│ sub-106_task-gabor_bold.nii
│ sub-106_task-gabor_events.tsv

├───sub-107
│ ├───anat
│ │ sub-107_T1w.nii
│ │
│ ├───eeg
│ │ sub-107_task-gabor_eeg.eeg
│ │ sub-107_task-gabor_eeg.vhdr
│ │ sub-107_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-107_task-gabor_bold.json
│ sub-107_task-gabor_bold.nii
│ sub-107_task-gabor_events.tsv

├───sub-108
│ ├───anat
│ │ sub-108_T1w.nii
│ │
│ ├───eeg
│ │ sub-108_task-gabor_eeg.eeg
│ │ sub-108_task-gabor_eeg.vhdr
│ │ sub-108_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-108_task-gabor_bold.json
│ sub-108_task-gabor_bold.nii
│ sub-108_task-gabor_events.tsv

├───sub-109
│ ├───anat
│ │ sub-109_T1w.nii
│ │
│ ├───eeg
│ │ sub-109_task-gabor_eeg.eeg
│ │ sub-109_task-gabor_eeg.vhdr
│ │ sub-109_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-109_task-gabor_bold.json
│ sub-109_task-gabor_bold.nii
│ sub-109_task-gabor_events.tsv

├───sub-110
│ ├───anat
│ │ sub-110_T1w.nii
│ │
│ ├───eeg
│ │ sub-110_task-gabor_eeg.eeg
│ │ sub-110_task-gabor_eeg.vhdr
│ │ sub-110_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-110_task-gabor_bold.json
│ sub-110_task-gabor_bold.nii
│ sub-110_task-gabor_events.tsv

├───sub-111
│ ├───anat
│ │ sub-111_T1w.nii
│ │
│ ├───eeg
│ │ sub-111_task-gabor_eeg.eeg
│ │ sub-111_task-gabor_eeg.vhdr
│ │ sub-111_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-111_task-gabor_bold.json
│ sub-111_task-gabor_bold.nii
│ sub-111_task-gabor_events.tsv

├───sub-112
│ ├───anat
│ │ sub-112_T1w.nii
│ │
│ ├───eeg
│ │ sub-112_task-gabor_eeg.eeg
│ │ sub-112_task-gabor_eeg.vhdr
│ │ sub-112_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-112_task-gabor_bold.json
│ sub-112_task-gabor_bold.nii
│ sub-112_task-gabor_events.tsv

├───sub-113
│ ├───anat
│ │ sub-113_T1w.nii
│ │
│ ├───eeg
│ │ sub-113_task-gabor_eeg.eeg
│ │ sub-113_task-gabor_eeg.vhdr
│ │ sub-113_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-113_task-gabor_bold.json
│ sub-113_task-gabor_bold.nii
│ sub-113_task-gabor_events.tsv

├───sub-115
│ ├───anat
│ │ sub-115_T1w.nii
│ │
│ ├───eeg
│ │ sub-115_task-gabor_eeg.eeg
│ │ sub-115_task-gabor_eeg.vhdr
│ │ sub-115_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-115_task-gabor_bold.json
│ sub-115_task-gabor_bold.nii
│ sub-115_task-gabor_events.tsv

├───sub-116
│ ├───anat
│ │ sub-116_T1w.nii
│ │
│ ├───eeg
│ │ sub-116_task-gabor_eeg.eeg
│ │ sub-116_task-gabor_eeg.vhdr
│ │ sub-116_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-116_task-gabor_bold.json
│ sub-116_task-gabor_bold.nii
│ sub-116_task-gabor_events.tsv

├───sub-117
│ ├───anat
│ │ sub-117_T1w.nii
│ │
│ ├───eeg
│ │ sub-117_task-gabor_eeg.eeg
│ │ sub-117_task-gabor_eeg.vhdr
│ │ sub-117_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-117_task-gabor_bold.json
│ sub-117_task-gabor_bold.nii
│ sub-117_task-gabor_events.tsv

├───sub-120
│ ├───anat
│ │ sub-120_T1w.nii
│ │
│ ├───eeg
│ │ sub-120_task-gabor_eeg.eeg
│ │ sub-120_task-gabor_eeg.vhdr
│ │ sub-120_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-120_task-gabor_bold.json
│ sub-120_task-gabor_bold.nii
│ sub-120_task-gabor_events.tsv

├───sub-121
│ ├───anat
│ │ sub-121_T1w.nii
│ │
│ ├───eeg
│ │ sub-121_task-gabor_eeg.eeg
│ │ sub-121_task-gabor_eeg.vhdr
│ │ sub-121_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-121_task-gabor_bold.json
│ sub-121_task-gabor_bold.nii
│ sub-121_task-gabor_events.tsv

├───sub-122
│ ├───anat
│ │ sub-122_T1w.nii
│ │
│ ├───eeg
│ │ sub-122_task-gabor_eeg.eeg
│ │ sub-122_task-gabor_eeg.vhdr
│ │ sub-122_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-122_task-gabor_bold.json
│ sub-122_task-gabor_bold.nii
│ sub-122_task-gabor_events.tsv

├───sub-123
│ ├───anat
│ │ sub-123_T1w.nii
│ │
│ ├───eeg
│ │ sub-123_task-gabor_eeg.eeg
│ │ sub-123_task-gabor_eeg.vhdr
│ │ sub-123_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-123_task-gabor_bold.json
│ sub-123_task-gabor_bold.nii
│ sub-123_task-gabor_events.tsv

├───sub-124
│ ├───anat
│ │ sub-124_T1w.nii
│ │
│ ├───eeg
│ │ sub-124_task-gabor_eeg.eeg
│ │ sub-124_task-gabor_eeg.vhdr
│ │ sub-124_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-124_task-gabor_bold.json
│ sub-124_task-gabor_bold.nii
│ sub-124_task-gabor_events.tsv

├───sub-125
│ ├───anat
│ │ sub-125_T1w.nii
│ │
│ ├───eeg
│ │ sub-125_task-gabor_eeg.eeg
│ │ sub-125_task-gabor_eeg.vhdr
│ │ sub-125_task-gabor_eeg.vmrk
│ │
│ └───func
│ sub-125_task-gabor_bold.json
│ sub-125_task-gabor_bold.nii
│ sub-125_task-gabor_events.tsv

└───sub-126
├───anat
│ sub-126_T1w.nii

├───eeg
│ sub-126_task-gabor_eeg.eeg
│ sub-126_task-gabor_eeg.vhdr
│ sub-126_task-gabor_eeg.vmrk

└───func
sub-126_task-gabor_bold.json
sub-126_task-gabor_bold.nii
sub-126_task-gabor_events.tsv

I’m definitely interested in learning how to submit parallel jobs for my subjects. You’re really kind for reaching out to me. What’s the best way to learn how?

Input structure looks BIDS-y enough to work, and memory usage doesn’t seem to be the limiting factor, so I think parallelizing it should address your problems!

  1. Usually on clusters, Singularity is preferred over Docker for executing programs from containers.
    With singularity installed, you can use the following command to download the singularity container: singularity build fmriprep.img docker://poldracklab/fmriprep:latest

  2. To submit jobs, we can prepare an sbatch script. You can put in the following text, and save as something like fmriprep_sbatch.sh. You can adjust the header to edit how much memory/CPUs are devoted to the task, and change the arguments to fmriprep as necessary.

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --cpus-per-task=2
#SBATCH --mem=8000 #MEMORY IN MB, THIS IS 8 GB
#SBATCH --time=72:00:00 #TIME OUT IN 3 DAYS

singularity exec -e /path/to/fmriprep.img fmriprep data/bids_root/ out/ participant -w work/ --participant_label $1 ADD ANY MORE ARGUMENTS HERE

  1. The $1 after the participant_label argument indicates that this is a variable that is passed into the script. To do this, we can create a for-loop to loop over subjects and pass individual subjects to their own job.

In terminal, navigate to your bids folder, and then the following loop (or something like it) should do the trick

for sub in sub*/; do sbatch /path/to/fmriprep_sbatch.sh $sub; done

If you still want to use Windows, I suppose a Cygwin terminal would have similar enough syntax that these steps would not require much adaptation, but I think cluster would be the way to go.

Great! I’ll suggest that to my PI. Thanks a bunch :slightly_smiling_face: