sdcflows.utils.wrangler module¶
Find fieldmaps on the BIDS inputs for SDC.
- sdcflows.utils.wrangler.find_estimators(*, layout: bids.layout.layout.BIDSLayout, subject: str, sessions: Optional[List[str]] = None, fmapless: Union[bool, set] = True, force_fmapless: bool = False, logger: Optional[logging.Logger] = None, bids_filters: Optional[dict] = None) 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 suffices for EPI images (namely,"dwi"
,"bold"
, or"sbref"
). Whenfmapless
isTrue
, heuristics will use the{"bold", "dwi"}
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.
- 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')]
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_00000'), FieldmapEstimation(sources=<3 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_00001')]
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_00002'), FieldmapEstimation(sources=<7 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_00003'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_00004'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_00005')]
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_00011'), FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>, bids_id='auto_00012')]
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_00000')]