Sdcfows find_estimators unable to find PEPolar epi maps

Summary of what happened:

I am trying to diagnose an error in sdcflows that’s preventing fMRIprep from detecting pepolar estimators for my data. Going off of a previous thread, I verified that all metadata was correctly specified. (details in last section)

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

sdcflows was invoked via the python interpreter from an fmriprep 21.0.4 singularity container.

Version:

sdcflows: 2.0.11
fmriprep: 21.0.4

Environment (Docker, Singularity, custom installation):

fmriprep singularity image based off of official docker image.

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

BIDS only outputted warnings about inconsistent scan parameters (piloting, so parameters are changing).

Relevant log outputs (up to 20 lines):

>>> find_estimators(layout, subject="Pat01")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/lib/python3.8/site-packages/sdcflows/utils/wrangler.py", line 271, in find_estimators
    _e = fm.FieldmapEstimation([
  File "<attrs generated init sdcflows.fieldmaps.FieldmapEstimation>", line 7, in __init__
  File "/opt/conda/lib/python3.8/site-packages/sdcflows/fieldmaps.py", line 398, in __attrs_post_init__
    raise ValueError("Insufficient sources to estimate a fieldmap.")

Screenshots / relevant information:

Pat01 Files

| sub-Pat01/
| | ses-1/
| | | anat/
| | | dwi/
| | | fmap/
| | | | sub-Pat01_ses-1_acq-dmri_dir-AP_epi.json
| | | | sub-Pat01_ses-1_acq-dmri_dir-AP_epi.nii.gz
| | | | sub-Pat01_ses-1_acq-fmri_dir-AP_epi.json
| | | | sub-Pat01_ses-1_acq-fmri_dir-AP_epi.nii.gz
| | | | sub-Pat01_ses-1_acq-fmri_dir-PA_epi.json
| | | | sub-Pat01_ses-1_acq-fmri_dir-PA_epi.nii.gz
| | | func/
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-1_bold.json
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-1_bold.nii.gz
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-1_sbref.json
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-1_sbref.nii.gz
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-2_bold.json
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-2_bold.nii.gz
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-2_sbref.json
| | | | sub-Pat01_ses-1_task-facename_dir-PA_run-2_sbref.nii.gz
| | | | sub-Pat01_ses-1_task-rest_dir-PA_bold.json
| | | | sub-Pat01_ses-1_task-rest_dir-PA_bold.nii.gz
| | | | sub-Pat01_ses-1_task-rest_dir-PA_sbref.json
| | | | sub-Pat01_ses-1_task-rest_dir-PA_sbref.nii.gz

Metadata for fieldmaps

$ grep 'B0Field' sub-Pat01/ses-1/func/*json
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-dmri_dir-AP_epi.json:    "B0FieldIdentifier": "pepolar_dmri"
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-fmri_dir-AP_epi.json:    "B0FieldIdentifier": "pepolar_facename"
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-fmri_dir-PA_epi.json:    "B0FieldIdentifier": "pepolar_facename"

$ grep 'PhaseEncodingDirection\"' sub-Pat01/ses-1/fmap/*json
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-dmri_dir-AP_epi.json:    "PhaseEncodingDirection": "j-",
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-fmri_dir-AP_epi.json:    "PhaseEncodingDirection": "j-",
sub-Pat01/ses-1/fmap/sub-Pat01_ses-1_acq-fmri_dir-PA_epi.json:    "PhaseEncodingDirection": "j",

IntendedFor is set for all fieldmaps and points to either a single diffusion or all bold + sbref runs.

Metadata for bold + sbref

$ grep 'B0Field' sub-Pat01/ses-1/func/*json
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-1_bold.json:    "B0FieldSource": "pepolar_facename"
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-1_sbref.json:    "B0FieldSource": "pepolar_facename"
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-2_bold.json:    "B0FieldSource": "pepolar_facename"
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-2_sbref.json:    "B0FieldSource": "pepolar_facename"
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-rest_dir-PA_bold.json:    "B0FieldSource": "pepolar_facename"
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-rest_dir-PA_sbref.json:    "B0FieldSource": "pepolar_facename"

$ grep 'PhaseEncodingDirection\"' sub-Pat01/ses-1/func/*json
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-1_bold.json:    "PhaseEncodingDirection": "j",
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-1_sbref.json:    "PhaseEncodingDirection": "j",
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-2_bold.json:    "PhaseEncodingDirection": "j",
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-facename_dir-PA_run-2_sbref.json:    "PhaseEncodingDirection": "j",
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-rest_dir-PA_bold.json:    "PhaseEncodingDirection": "j",
sub-Pat01/ses-1/func/sub-Pat01_ses-1_task-rest_dir-PA_sbref.json:    "PhaseEncodingDirection": "j",

N.B. IntendedFor points to bold + sbref; B0FieldSource is also set for both bold + sbref.

Nice report with a lot of details!

Everything looks mostly fine to me. One thing perhaps, since there is only one direction present for acq-dmri_dir-AP_epi in fmap/, perhaps the fieldmap estimator is complaining about that?
For testing could you remove (or filter out) sub-Pat01_ses-1_acq-dmri_dir-AP_epi.json and sub-Pat01_ses-1_acq-dmri_dir-AP_epi.nii.gz and try again to launch fmriprep (removing all temporary files from previous run before launching)?
It would be also helpful to see you fmriprep command.

Good luck!

Assuming it’s the presence of the DWI fieldmap that’s causing issues, this is a bug. We should be dropping incomplete fieldmaps (possibly with a warning), rather than raising an error.

I think I might have found the solution:

The “incomplete” fieldmap is meant to be paired with a dwi scan. I included B0FieldSource but I did not include B0FieldIdentifier in sub-Pat01_ses-1_dir-PA_dwi.json. Including B0FieldIdentifier seemed to do the trick.

Strange though. I included the dwi scan in the IntendedFor for sub-Pat01_ses-1_acq-dmri_dir-AP_epi.json. If both IntendedFor and B0Field* tags are included, does sdcflows use the other as fallback?

If B0FieldIdentifier is present in a fieldmap, then IntendedFor is ignored and no associations are attempted. If both are present and no BOLD file specifies B0FieldSource, then a fieldmap could be estimated, but not applied.

Still sounds like a bug. A warning sounds reasonable and might help you catch the issue. A crash means that a misconfigured DWI scan could break fMRI tools.

Interestingly enough, when I ran sdcflows on the corrected set, find_estimators was able to correctly guess the fieldmaps.

However, when I ran fmriprep 21.0.4, I was still getting ValueError: "Insufficient sources to estimate a fieldmap."

When I removed all B0Field* tags, fmriprep 21.0.4 was finally able to find the estimators. Might have been inconsistent tagging on my part.

21.0.4 will be using an older version of sdcflows. Bug fixes march ever on.

1 Like

Updated to 22.1.1, unfortunately the extra dMRI images are still throwing off find_estimators(). Had to split off a b0 and save as a separate epi image.

For personal reference, is this scheme not supported by sdcflows? That is, one diffusion sequence paired with one reverse-PE as a separate image?

I don’t think there’s any BOLD-specific logic that would keep SDCFlows from finding a diffusion+reverse fieldmap pair. However, we exclude dwi from indexing for efficiency in fmriprep. I suspect this is causing sdcflows to fail to find the matched fieldmaps in dwi.

@ajschadler If you are able to patch in an experimental copy of sdcflows, I have a PR that might fix this: FIX: Log incomplete fieldmaps, rather than erroring by effigies · Pull Request #341 · nipreps/sdcflows · GitHub

Using fmriprep-docker:

git clone https://github.com/effigies/sdcflows.git
git -C sdcflows checkout fix/log_incomplete
fmriprep-docker -i nipreps/fmriprep:unstable --patch sdcflows=sdcflows/sdcflows \
    bids_dir output_dir participant [...]

Looks like your fix worked! Ran swimmingly.

1 Like