Have multiple AP and PA images to generate multiple fieldmaps (1 for each func run) but fmriprep claims only 1 fieldmap can be generated/is available

Summary of what happened:

I have an AP and PA that were acquired prior to each func run, but fmriprep claims that only 1 fieldmap can be generated: A total of 1 fieldmaps were found available within the input BIDS structure for this particular subject. A B0-nonuniformity map (or fieldmap) was estimated based on two (or more) echo-planar imaging (EPI) references with topup (Andersson, Skare, and Ashburner (2003); FSL 6.0.5.1:57b01774). This is copied from the html.

I have specified in each .json file of the AP and PA images which func run they are intended for like so: "IntendedFor": ["func/sub-SPIN001_task-rest_run-02_bold.nii.gz"],

Everything else with fmriprep seems quite perfect. I made sure to pass the bids-validator with no errors prior to running fmriprep.

Command used (and if a helper script was used, a link to the helper script or the command generated):

singularity run --cleanenv -B /data $sif_loc $input_dir $output_dir participant --participant-label $subject --nthreads 16 --omp-nthreads 16 --mem_mb 32000 --skip-bids-validation --output-spaces MNIPediatricAsym:cohort-4:res-2 --use-aroma --skull-strip-template NKI --fs-license-file $fs_license --work-dir $work_dir 

Version:

fMRIPrep v23.0.0rc0

Environment (Docker, Singularity, custom installation):

Singularity

Data formatted according to a validatable standard? Please provide the output of the validator:

Yes. There is one strange warning:

	1: [WARN] Not all subjects contain the same files. Each subject should contain the same number of files with the same naming unless some files are known to be missing. (code: 38 - INCONSISTENT_SUBJECTS)
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-AP_epi.json
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-AP_epi.json
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-AP_epi.nii.gz
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-AP_epi.nii.gz
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-AP_run-03_epi.json
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-AP_run-03_epi.json
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-AP_run-03_epi.nii.gz
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-AP_run-03_epi.nii.gz
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-PA_epi.json
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-PA_epi.json
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-PA_epi.nii.gz
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-PA_epi.nii.gz
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-PA_run-03_epi.json
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-PA_run-03_epi.json
		./sub-SPIN001/fmap/sub-SPIN001_acq-rest_dir-PA_run-03_epi.nii.gz
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_acq-rest_dir-PA_run-03_epi.nii.gz
		./sub-SPIN001/func/sub-SPIN001_task-rest_bold.json
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_task-rest_bold.json
		./sub-SPIN001/func/sub-SPIN001_task-rest_bold.nii.gz
			Evidence: Subject: sub-SPIN001; Missing file: sub-SPIN001_task-rest_bold.nii.gz
		... and 1592 more files having this issue (Use --verbose to see them all).

The above output is extremely weird because I don’t even have some of the above files. I did do some file cleaning/removing and ran the bids-validator after. The files should be:

ender.540> cd sub-SPIN001
ender.541> ls
anat  fmap  func
ender.542> ls -R
.:
anat  fmap  func

./anat:
sub-SPIN001_T1w.json  sub-SPIN001_T1w.nii.gz

./fmap:
sub-SPIN001_acq-rest_dir-AP_run-01_epi.json    sub-SPIN001_acq-rest_dir-PA_run-01_epi.json
sub-SPIN001_acq-rest_dir-AP_run-01_epi.nii.gz  sub-SPIN001_acq-rest_dir-PA_run-01_epi.nii.gz
sub-SPIN001_acq-rest_dir-AP_run-02_epi.json    sub-SPIN001_acq-rest_dir-PA_run-02_epi.json
sub-SPIN001_acq-rest_dir-AP_run-02_epi.nii.gz  sub-SPIN001_acq-rest_dir-PA_run-02_epi.nii.gz

./func:
sub-SPIN001_task-rest_run-01_bold.json    sub-SPIN001_task-rest_run-02_bold.json
sub-SPIN001_task-rest_run-01_bold.nii.gz  sub-SPIN001_task-rest_run-02_bold.nii.gz

Relevant log outputs (up to 20 lines):

None.

Screenshots / relevant information:

None.

Hi @Hannah.Choi,

Looks like fMRIPrep is doing SDC as intended, in that it is making a fieldmap based off of your AP/PA pair of images. Do SDC results look good?

Best,
Steven

Hi @Steven,

Yes, fMRIPrep is indeed doing SDC as intended and it looks pretty good, but I was wondering if it could make separate fieldmaps for each functional bold run since we have two pairs, one for each bold run. Our scanning protocol is so that the functional runs are acquired some time part (T2w and FLAIR are acquired in between). Does fMRIPrep only generate one fieldmap per sub despite there being 2 pairs and different IntendedFor specifications?

Thanks again,
Hannah

Ah sorry I misunderstood your original post, I thought you were asking one distortion performance for AP and PA separately, my bad.

Do you get this result for all of your subjects? Just in case can you try upgrading to the stable release?

Best,
Steven

No worries! I tested for a single 2-run subject, so I will try to test more subs. I will first make sure to upgrade to the stable release. I will let you know how it goes - probably sometime tomorrow.

Thanks for the suggestions,
Hannah

The most reliable approach is using B0FieldIdentifier/B0FieldSource. 23.1.0 will do a better job of respecting IntendedFor, with RF: Split PEPolar fieldmaps by intent, if available by effigies · Pull Request #342 · nipreps/sdcflows · GitHub.

@Steven @effigies
Thank you again for your suggestions. I tried the upgrade to 23.0.2 and handpicked some subjects with 2 runs. Everything runs great.
I just checked/learned something. I went to the fmap directory and opened up the .json.

{
  "AnatomicalReference": "sub-SPIN039_acq-rest_fmapid-auto00000_desc-epi_fieldmap.nii.gz",
  "AssociatedCoefficients": [
    "sub-SPIN039_acq-rest_fmapid-auto00000_desc-coeff_fieldmap.nii.gz"
  ],
  "B0FieldIdentifier": "auto_00000",
  "IntendedFor": [
    "func/sub-SPIN039_task-rest_run-01_bold.nii.gz",
    "func/sub-SPIN039_task-rest_run-02_bold.nii.gz"
  ],
  "RawSources": [
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-AP_run-01_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-AP_run-02_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-PA_run-01_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-PA_run-02_epi.nii.gz"
  ],
  "Units": "Hz"
}

So, I’m assuming fmriprep is using all AP and PA images to generate a single fieldmap. I guess it is not the worst thing ever because the images are all for the subject, but I’m guessing that it is more appropriate to have the fieldmaps generated according to run (especially since the AP and PA pairs were acquired prior to each func run).

@effigies I looked into B0FieldIdentifier /B0FieldSource. I also chatted a bit with ChatGPT to see if I understood correctly. Would the following be an appropriate way to handle it?

hmm that shouldn’t be happening. I just looked at my own data run on v23 and it makes different fieldmaps for each bold run as intended. Can you share the contents of the JSON files?

Best,
Steven

@Steven I tried experimenting with B0FieldIdentifier and B0FieldSource and believe I have something working. Say for a run, the jsons of the AP and PA images have:

"B0FieldIdentifier": "sub-SPIN117_run-01",
"IntendedFor": ["func/sub-SPIN117_task-rest_run-01_bold.nii.gz"],

and the func image has:

"B0FieldSource": "sub-SPIN117_run-01",

Then, we get a fieldmap json from fmriprep looking like:

{
  "AnatomicalReference": "sub-SPIN117_acq-rest_run-01_fmapid-sub-SPIN117run-01_desc-epi_fieldmap.nii.gz",
  "AssociatedCoefficients": [
    "sub-SPIN117_acq-rest_run-01_fmapid-sub-SPIN117run-01_desc-coeff_fieldmap.nii.gz"
  ],
  "B0FieldIdentifier": "sub-SPIN117_run-01",
  "IntendedFor": [
    "func/sub-SPIN117_task-rest_run-01_bold.nii.gz"
  ],
  "RawSources": [
    "/data/ncl-mb13/SPIN_REST/sub-SPIN117/fmap/sub-SPIN117_acq-rest_dir-AP_run-01_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN117/fmap/sub-SPIN117_acq-rest_dir-PA_run-01_epi.nii.gz"
  ],
  "Units": "Hz"
}

Also, the final report html mentions that 2 fieldmaps have been produced and used, which is great.

If I just used intended for, like I did before, I get the above json. I’ll just copy it over here again:

{
  "AnatomicalReference": "sub-SPIN039_acq-rest_fmapid-auto00000_desc-epi_fieldmap.nii.gz",
  "AssociatedCoefficients": [
    "sub-SPIN039_acq-rest_fmapid-auto00000_desc-coeff_fieldmap.nii.gz"
  ],
  "B0FieldIdentifier": "auto_00000",
  "IntendedFor": [
    "func/sub-SPIN039_task-rest_run-01_bold.nii.gz",
    "func/sub-SPIN039_task-rest_run-02_bold.nii.gz"
  ],
  "RawSources": [
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-AP_run-01_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-AP_run-02_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-PA_run-01_epi.nii.gz",
    "/data/ncl-mb13/SPIN_REST/sub-SPIN039/fmap/sub-SPIN039_acq-rest_dir-PA_run-02_epi.nii.gz"
  ],
  "Units": "Hz"
}

Thanks again for the helpful suggestions!