FmriPrep SDC Fails to Associate To Bold Image, Preprocess Working

I’m struggling to get SDC working with case 1 from BIDS spec v1.7.

When fmriPrep runs, I get:

 220512-10:54:01,254 nipype.workflow INFO:
         B0 field inhomogeneity map will be estimated with  the following 1 estimators: [<EstimatorType.PHASEDIFF: 3>].
220512-10:54:01,444 nipype.workflow INFO:
         Using single-band reference file(s) sub-DPOP006_ses-1_task-rest_run-7_sbref.nii.gz.
220512-10:54:01,444 nipype.workflow CRITICAL:
         None of the available B0 fieldmaps are associated to </bidsdir/sub-DPOP006/ses-1/func/sub-DPOP006_ses-1_task-rest_run-7_bold.nii.gz>

My bidsdir passes validation and I have setup IntendedFor for all three fmap images.
I have the echo times included and added the B0FieldIdentifier.

It looks to me like the preprocessing of fieldmaps is working. It’s just not getting associated with my bold image.

Both mag (1 and 2) images and phasediff image, side cars have IntendedFor:

'IntendedFor' :  'ses-1/func/sub-DPOP006_ses-1_task-rest_run-7_bold.nii.gz'
'B0FieldIdentifier':  'phaseddiff_fmap0'

This is my BIDS directory, bidsdir.

β”œβ”€β”€ dataset_description.json
β”œβ”€β”€ participants.tsv
└── sub-DPOP006
└── ses-1
β”œβ”€β”€ anat
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_T1w.json
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_T1w.nii.gz
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_T2w.json
β”‚ └── sub-DPOP006_ses-1_run-7_T2w.nii.gz
β”œβ”€β”€ fmap
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_magnitude1.json
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_magnitude1.nii.gz
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_magnitude2.json
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_magnitude2.nii.gz
β”‚ β”œβ”€β”€ sub-DPOP006_ses-1_run-7_phasediff.json
β”‚ └── sub-DPOP006_ses-1_run-7_phasediff.nii.gz
└── func
β”œβ”€β”€ sub-DPOP006_ses-1_task-rest_run-7_bold.json
β”œβ”€β”€ sub-DPOP006_ses-1_task-rest_run-7_bold.nii.gz
β”œβ”€β”€ sub-DPOP006_ses-1_task-rest_run-7_sbref.json
└── sub-DPOP006_ses-1_task-rest_run-7_sbref.nii.gz

Not sure if this will do the trick, but can you try to put the IntendedFor argment in brackets? That is, [β€˜ses-1…nii.gz’]. Otherwise, could you post your full command you are using to call fMRIPrep?

Best,
Steven

I recently encountered this ! If you drop B0FieldIdentifier, it will use the IntendedFor field appropriately. Otherwise, It prioritizes B0FieldIdentifier which requires B0FieldSource:

https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/01-magnetic-resonance-imaging-data.html#echo-planar-imaging-and-b0-mapping

3 Likes

Oh that makes sense sort of. I don’t understand the B0FieldIndentifier and B0FieldSource and found it odd that I needed to include IntendedFor. I’ll read the doc you linked.

Cheers

There’s a nice distinction between the two here:

https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/01-magnetic-resonance-imaging-data.html#using-b0fieldidentifier-metadata

Specifically,

B0FieldIdentifier and B0FieldSource duplicate the capabilities of the original IntendedFor approach (see below), while permitting more complex use cases. It is RECOMMENDED to use both approaches to maintain compatibility with tools that support older datasets.

I think @emdupre answer is going to work for me. However, for completeness, I’ve added my call.

#!/bin/bash
singularity run \
    --cleanenv \
    --bind /m/Dev/Dev_FmriPrep/pijp-fmriprep/DPOP006/raw:/bidsdir \
    --bind /m/Dev/Dev_FmriPrep/pijp-fmriprep/DPOP006/results:/out \
    --bind /tmp/DPOP006-1a7_work:/work \
    --bind /opt/freesurfer/6.0.0/license.txt:/fslicense.txt:ro \
    --bind /m/Dev/Dev_FmriPrep/pijp-fmriprep/DPOP006/freesurfer:/fs \
    /m/Dev/Dev_FmriPrep/fmriprep-21.0.2.simg \
    /bidsdir/ /out participant \
    --participant-label DPOP006 \
    -w /work/ \
    --ignore slicetiming \
    --fs-license-file /fslicense.txt \
    --mem  16000 \
    --low-mem \
    --bids-database-dir /tmp/DPOP006_bids_db \
    --nprocs 4 \
    --omp-nthreads 4 \
    --debug all \
    --fs-subjects-dir /fs

Do let us know if adding that additional metadata field works for you or if we should be looking elsewhere !

Elizabeth

I’ve been reading the PDF doc for BIDS spec v1.7, page 98. I found it difficult to search for topics in the BIDS html pages.

I’m confused since your first link talks about using the DICOM tag ( 0018,1030) which is different from the PDF.

Maybe I do not truly have a case 1 series of maps ??

Removing the B0FieldIdentifer key from my fmaps and keeping only IntendedFor did the trick.

However, I’d like to not use that system if possible. It makes my code more complex to have to know the associated bolds in advance of making the BIDS structure.

I don’t understand how the B0FieldIdentifer and B0FieldSource are supposed to work.

My guess, is that I add to the 3 field maps files (mag1, mag2, phase_diff) "B-FieldIdentifer": "phasediff_fmap0"

Then to the BOLD image’s json, I add "B0FieldSource": "phasediff_fmap0".

That idea did not work as I received the same message to stdout, that no fieldmap was associated with the bold image.

To confirm: the first link is to common MR metadata fields for inclusion in the sidecar JSON files, rather than DICOM fields. It references relevant DICOM fields in the field description, to help in populating the field.

EDIT: The link corresponds to page 311 in the provided PDF.

There is some work in HeudiConv on automatically populating the IntendedFor field correctly, but this is still certainly something that you’d want to check.

To your question of using B0FieldIdentifier and B0FieldSource: Yes, you’d want to place the B0FieldSource field in the BOLD images’ JSON sidecar ! The _phasediff.json sidecar should look like this example

{
   "EchoTime1": 0.00600,
   "EchoTime2": 0.00746,
   "B0FieldIdentifier": "phasediff_fmap0"
}

I’d expect that to work appropriately. There have been previous reports of the reverse situation (i.e., not working with IntendedFor only), but since these reports occur sporadically, I’m wondering if the working directory wasn’t accidentally re-used. Can you confirm that you re-ran both cases in a clean environment ?

1 Like

Awesome… I was putting not only the β€œkey” but also the value phasediff_fmap0 in the BOLD’s json.

The run with IntendedFor properly associated but then I got the dreaded error:
KeyError: "Metadata term 'RepetitionTime' unavailable for file /bidsdir/sub-DPOP007/ses-2/func/sub-DPOP007_ses-2_task-rest_run-7_bold.nii.gz."

Of course that TR time is there perfectly from dcm2niix. Perhaps this is a bug that will go away.

Sorry this is confusing…

Great example of B0FieldIndentifier but it’s never clear what the BOLD’s B0FieldSource is.

In your case, it should correspond to what you had suggested previously:

{
    "B0FieldSource": "phasediff_fmap0"
}

I agree, though, that there could be more relevant examples here! I imagine the challenge is that these B0Field fields can handle more complexity; i.e., an image being its own B0FieldSource, as alluded to in the current definitions.

Yeah that’s what I tried…no love. Same critical error of no association and a new one about missing TR time.

I’m about to jump out the window…

Proof I’m not crazy

The error I get from stdout.

220512-17:23:33,390 nipype.workflow INFO:
         B0 field inhomogeneity map will be estimated with  the following 1 estimators: [<EstimatorType.PHASEDIFF: 3>].
220512-17:23:33,600 nipype.workflow INFO:
         Using single-band reference file(s) sub-DPOP007_ses-2_task-rest_run-7_sbref.nii.gz.
220512-17:23:33,600 nipype.workflow CRITICAL:
         None of the available B0 fieldmaps are associated to </bidsdir/sub-DPOP007/ses-2/func/sub-DPOP007_ses-2_task-rest_run-7_bold.nii.gz>

My BIDSDIR

β”œβ”€β”€ dataset_description.json
β”œβ”€β”€ participants.tsv
└── sub-DPOP007
    └── ses-2
        β”œβ”€β”€ anat
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_T1w.json
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_T1w.nii.gz
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_T2w.json
        β”‚   └── sub-DPOP007_ses-2_run-7_T2w.nii.gz
        β”œβ”€β”€ fmap
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_magnitude1.json
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_magnitude1.nii.gz
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_magnitude2.json
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_magnitude2.nii.gz
        β”‚   β”œβ”€β”€ sub-DPOP007_ses-2_run-7_phasediff.json
        β”‚   └── sub-DPOP007_ses-2_run-7_phasediff.nii.gz
        └── func
            β”œβ”€β”€ sub-DPOP007_ses-2_task-rest_run-7_bold.json
            β”œβ”€β”€ sub-DPOP007_ses-2_task-rest_run-7_bold.nii.gz
            β”œβ”€β”€ sub-DPOP007_ses-2_task-rest_run-7_sbref.json
            └── sub-DPOP007_ses-2_task-rest_run-7_sbref.nii.gz

BOLD sidecar

 grep -oP '\"B0FieldSource\":.*\}' sub-DPOP007/ses-2/func/sub-DPOP007_ses-2_task-rest_run-7_bold.json
"B0FieldSource": "phasediff_fmap0"}

fmap sidecars

 grep -oP '\"B0FieldIdentifier\":.*\}' sub-DPOP007/ses-2/fmap/*.json
sub-DPOP007/ses-2/fmap/sub-DPOP007_ses-2_run-7_magnitude1.json:"B0FieldIdentifier": "phasediff_fmap0"}
sub-DPOP007/ses-2/fmap/sub-DPOP007_ses-2_run-7_magnitude2.json:"B0FieldIdentifier": "phasediff_fmap0"}
sub-DPOP007/ses-2/fmap/sub-DPOP007_ses-2_run-7_phasediff.json:"B0FieldIdentifier": "phasediff_fmap0"}

New error I also get:

KeyError: "Metadata term 'RepetitionTime' unavailable for file /bidsdir/sub-DPOP007/ses-2/func/sub-DPOP007_ses-2_task-rest_run-7_bold.nii.gz."

 grep -Po '\"RepetitionTime\":.*?,' sub-DPOP007_ses-2_task-rest_run-7_bold.json
"RepetitionTime": 0.82,

Can you confirm that you’re not re-using an existing working directory?

Also, based on previous questions, I’d guess this might be a file permissions issue. But to confirm: if you include the IntendedFor field, you see neither of the described issues ?

I wipe out the whole working directory for every test.
I stopped trying with IntendedFor because I was able to greatly simplify some code.

File permissions sounds very possible. I’m working with NFSv4 and it’s causing a lot of issues with this pipeline.

AntsApplyTransforms has been borking due to failure to get a file lock. I had to put the /work dir into my /tmp and move it back.

The sqlalchemy driver for sqlite wasn’t working until I moved the db to /tmp.