sdcflows.utils.wrangler module¶
Find fieldmaps on the BIDS inputs for SDC.
- sdcflows.utils.wrangler.find_anatomical_estimators(*, anat_file: BIDSFile, layout: BIDSLayout, subject: str, sessions: List[str], base_entities: Dict[str, Any], suffixes: List[str]) List[List[FieldmapFile]] [source]¶
Find anatomical estimators
Given an anatomical reference image, create lists of files for estimating susceptibility distortion for the EPI images in a dataset.
- Parameters:
anat_file (
bids.layout.BIDSFile
) – Anatomical reference image to use in estimators.layout (
bids.layout.BIDSLayout
) – An initialized PyBIDS layout.subject (
str
) – Participant label for this single-subject workflow.sessions (
list
) – One of more session identifiers. To use all, pass[None]
.base_entities (
dict
) – Entities to use to query for images. These should include any filters.suffixes (
list
) – EPI suffixes, for example["bold", "dwi", "asl"]
. Associated"sbref"
s will be found and used in place of BOLD/diffusion EPIs. Similarly,"m0scan"
s associated with ASL runs with theIntendedFor
orB0FieldIdentifier
metadata will be used in place of ASL runs.
- sdcflows.utils.wrangler.find_estimators(*, layout: BIDSLayout, subject: str, sessions: List[str] | None = None, fmapless: bool | set = True, force_fmapless: bool = False, logger: Logger | None = None, bids_filters: dict | None = None, anat_suffix: str | List[str] = 'T1w') list [source]¶
Apply basic heuristics to automatically find available data for fieldmap estimation.
The “fieldmap-less” heuristics only attempt to find
_dwi
and_bold
candidates to pair with a_T1w
anatomical reference. For more complicated heuristics (for instance, using_T2w
images or_sbref
images,) theFieldmapEstimation
object must be created manually by the user.- Parameters:
layout (
bids.layout.BIDSLayout
) – An initialized PyBIDS layout.subject (
str
) – Participant label for this single-subject workflow.sessions (
list
or None) – One of more session identifiers. If None, all sessions will be used.fmapless (
bool
orset
) – Indicates if fieldmap-less heuristics should be executed. Whenfmapless
is aset
, it can contain valid BIDS suffixes for EPI images (namely,"dwi"
,"bold"
,"asl"
, or"sbref"
). Whenfmapless
isTrue
, heuristics will use the{"bold", "dwi", "asl"}
set.force_fmapless (
bool
) – When some other fieldmap estimation methods have been found, fieldmap-less estimation will be skipped except ifforce_fmapless
isTrue
.logger – The logger used to relay messages. If not provided, one will be created.
bids_filters – Optional dictionary of key/values to filter the entities on. This allows lower level file inclusion/exclusion.
anat_suffix (
str
orlist
) – String or list of strings to filter anatomical images for fieldmap-less approaches. If not provided,T1w
is used.
- Returns:
estimators – The list of
FieldmapEstimation
objects that have successfully been built (meaning, all necessary inputs and corresponding metadata are present in the given layout.)- Return type:
Examples
Our
ds000054
dataset, created for fMRIPrep, only has one phasediff type of fieldmap withmagnitude1
andmagnitude2
files:>>> find_estimators( ... layout=layouts['ds000054'], ... subject="100185", ... fmapless=False, ... ) [FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_00000')]
OpenNeuro’s dataset with four PEPOLAR EPI files, two runs per phase-encoding direction (AP, PA):
>>> find_estimators( ... layout=layouts['ds001771'], ... subject="36", ... ) [FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_00001')]
OpenNeuro’s
ds001600
is an SDC test-dataset containing many different possibilities for fieldmap estimation:>>> find_estimators( ... layout=layouts['ds001600'], ... subject="1", ... ) [FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_00002'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_00003'), FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_00004'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_00005')]
We can also pick one (simplified) HCP subject for testing purposes:
>>> find_estimators( ... layout=layouts['HCP101006'], ... subject="101006", ... ) [FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_00006'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_00007'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_00008')]
Finally, SDCFlows’ “dataset A” and “dataset B” contain BIDS structures with zero-byte NIfTI files and some corresponding metadata:
>>> find_estimators( ... layout=layouts['dsA'], ... subject="01", ... ) [FieldmapEstimation(sources=<2 files>, method=<EstimatorType.MAPPED: 4>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...')]
>>> find_estimators( ... layout=layouts['dsB'], ... subject="01", ... ) [FieldmapEstimation(sources=<2 files>, method=<EstimatorType.MAPPED: 4>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...')]
After cleaning the registry, we can see how the “fieldmap-less” estimation can be forced:
>>> from .. import fieldmaps as fm >>> fm.clear_registry() >>> find_estimators( ... layout=layouts['ds000054'], ... subject="100185", ... fmapless={"bold"}, ... force_fmapless=True, ... ) [FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...')]
Likewise in a more comprehensive dataset:
>>> find_estimators( ... layout=layouts['ds001771'], ... subject="36", ... force_fmapless=True, ... ) [FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...')]
Because “dataset A” contains very few metadata fields available, “fieldmap-less” heuristics come back empty (BOLD and DWI files are missing the mandatory
PhaseEncodingDirection
, in this case):>>> find_estimators( ... layout=layouts['dsA'], ... subject="01", ... force_fmapless=True, ... ) [FieldmapEstimation(sources=<2 files>, method=<EstimatorType.MAPPED: 4>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<3 files>, method=<EstimatorType.PHASEDIFF: 3>, bids_id='auto_...'), FieldmapEstimation(sources=<4 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='auto_...')]
This function should also correctly investigate multi-session datasets:
>>> find_estimators( ... layout=layouts['ds000206'], ... subject="05", ... fmapless=False, ... force_fmapless=False, ... ) []
>>> find_estimators( ... layout=layouts['ds000206'], ... subject="05", ... fmapless=True, ... force_fmapless=False, ... ) [FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...')]
When the
B0FieldIdentifier
metadata is set for one or more fieldmaps, then the heuristics that useIntendedFor
are dismissed:>>> find_estimators( ... layout=layouts['dsC'], ... subject="01", ... ) [FieldmapEstimation(sources=<5 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='pepolar4pe')]
The only exception to the priority of
B0FieldIdentifier
is when fieldmaps are searched with theforce_fmapless
argument on:>>> fm.clear_registry() # Necessary as `pepolar4pe` is not changing. >>> find_estimators( ... layout=layouts['dsC'], ... subject="01", ... fmapless=True, ... force_fmapless=True, ... ) [FieldmapEstimation(sources=<5 files>, method=<EstimatorType.PEPOLAR: 2>, bids_id='pepolar4pe'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_...')]