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
_dwiand_boldcandidates to pair with a_T1wanatomical reference. For more complicated heuristics (for instance, using_T2wimages or_sbrefimages,) theFieldmapEstimationobject 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 (
listor None) – One of more session identifiers. If None, all sessions will be used.fmapless (
boolorset) – Indicates if fieldmap-less heuristics should be executed. Whenfmaplessis aset, it can contain valid BIDS suffices for EPI images (namely,"dwi","bold", or"sbref"). WhenfmaplessisTrue, 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_fmaplessisTrue.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
FieldmapEstimationobjects that have successfully been built (meaning, all necessary inputs and corresponding metadata are present in the given layout.)- Return type
Examples
Our
ds000054dataset, created for fMRIPrep, only has one phasediff type of fieldmap withmagnitude1andmagnitude2files:>>> 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
ds001600is 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
B0FieldIdentifiermetadata is set for one or more fieldmaps, then the heuristics that useIntendedForare 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
B0FieldIdentifieris when fieldmaps are searched with theforce_fmaplessargument 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')]