Skip to content

Commit 82fd9b2

Browse files
committed
enh: add doctests to exercise the B0FieldIdentifier implementation
1 parent c87e5a3 commit 82fd9b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+108
-3
lines changed

sdcflows/conftest.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@
4040
}
4141

4242
data_dir = Path(__file__).parent / "tests" / "data"
43-
44-
layouts["dsA"] = BIDSLayout(data_dir / "dsA", validate=False, derivatives=False)
45-
layouts["dsB"] = BIDSLayout(data_dir / "dsB", validate=False, derivatives=False)
43+
layouts.update({
44+
folder.name: BIDSLayout(folder, validate=False, derivatives=False)
45+
for folder in data_dir.glob("ds*") if folder.is_dir()
46+
})
4647

4748

4849
def pytest_report_header(config):
@@ -66,6 +67,7 @@ def add_np(doctest_namespace):
6667

6768
doctest_namespace["dsA_dir"] = data_dir / "dsA"
6869
doctest_namespace["dsB_dir"] = data_dir / "dsB"
70+
doctest_namespace["dsC_dir"] = data_dir / "dsC"
6971

7072

7173
@pytest.fixture
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"Name": "Test Dataset A, only empty files",
3+
"BIDSVersion": "",
4+
"License": "CC0",
5+
"Authors": ["Esteban O."],
6+
"Acknowledgements": "",
7+
"HowToAcknowledge": "",
8+
"Funding": "",
9+
"ReferencesAndLinks": [""],
10+
"DatasetDOI": ""
11+
}

sdcflows/tests/data/dsC/sub-01/anat/sub-01_FLAIR.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/anat/sub-01_T1w.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/anat/sub-01_T2w.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-AP_dwi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"PhaseEncodingDirection": "j-",
3+
"TotalReadoutTime": 0.005
4+
}

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-AP_sbref.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-LR_dwi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"PhaseEncodingDirection": "i",
3+
"TotalReadoutTime": 0.005
4+
}

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-LR_sbref.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-PA_dwi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"PhaseEncodingDirection": "j",
3+
"TotalReadoutTime": 0.005
4+
}

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-PA_sbref.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-RL_dwi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"PhaseEncodingDirection": "i-",
3+
"TotalReadoutTime": 0.005
4+
}

sdcflows/tests/data/dsC/sub-01/dwi/sub-01_dir-RL_sbref.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"PhaseEncodingDirection": "j",
3+
"TotalReadoutTime": 0.005,
4+
"IntendedFor": [
5+
"dwi/sub-01_dir-AP_dwi.nii.gz",
6+
"dwi/sub-01_dir-AP_sbref.nii.gz",
7+
"func/sub-01_task-rest_bold.nii.gz",
8+
"func/sub-01_task-rest_sbref.nii.gz"
9+
]
10+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_acq-single_dir-PA_epi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"B0FieldIdentifier": "pepolar4pe",
3+
"PhaseEncodingDirection": "j-",
4+
"TotalReadoutTime": 0.005
5+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_dir-AP_epi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"B0FieldIdentifier": "pepolar4pe",
3+
"PhaseEncodingDirection": "i",
4+
"TotalReadoutTime": 0.005
5+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_dir-LR_epi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"B0FieldIdentifier": "pepolar4pe",
3+
"PhaseEncodingDirection": "j",
4+
"TotalReadoutTime": 0.005
5+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_dir-PA_epi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"B0FieldIdentifier": "pepolar4pe",
3+
"PhaseEncodingDirection": "i-",
4+
"TotalReadoutTime": 0.005
5+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_dir-RL_epi.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Units": "rad/s"
3+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_fieldmap.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_magnitude.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_magnitude1.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_magnitude2.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"EchoTime": 0.005
3+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_phase1.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"EchoTime": 0.00746
3+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_phase2.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"EchoTime1": 0.00500,
3+
"EchoTime2": 0.00746
4+
}

sdcflows/tests/data/dsC/sub-01/fmap/sub-01_phasediff.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/func/sub-01_task-rest_bold.nii.gz

Whitespace-only changes.

sdcflows/tests/data/dsC/sub-01/func/sub-01_task-rest_sbref.nii.gz

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"TaskName": "Rest",
3+
"PhaseEncodingDirection": "j-",
4+
"TotalReadoutTime": 0.05
5+
}

sdcflows/utils/wrangler.py

+28
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,31 @@ def find_estimators(*, layout, subject, fmapless=True, force_fmapless=False):
214214
FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>,
215215
bids_id='auto_00012')]
216216
217+
When the ``B0FieldIdentifier`` metadata is set for one or more fieldmaps, then
218+
the heuristics that use ``IntendedFor`` are dismissed:
219+
220+
>>> find_estimators(
221+
... layout=layouts['dsC'],
222+
... subject="01",
223+
... ) # doctest: +ELLIPSIS
224+
[FieldmapEstimation(sources=<5 files>, method=<EstimatorType.PEPOLAR: 2>,
225+
bids_id='pepolar4pe')]
226+
227+
The only exception to the priority of ``B0FieldIdentifier`` is when fieldmaps
228+
are searched with the ``force_fmapless`` argument on:
229+
230+
>>> fm.clear_registry() # Necessary as `pepolar4pe` is not changing.
231+
>>> find_estimators(
232+
... layout=layouts['dsC'],
233+
... subject="01",
234+
... fmapless=True,
235+
... force_fmapless=True,
236+
... ) # doctest: +ELLIPSIS
237+
[FieldmapEstimation(sources=<5 files>, method=<EstimatorType.PEPOLAR: 2>,
238+
bids_id='pepolar4pe'),
239+
FieldmapEstimation(sources=<2 files>, method=<EstimatorType.ANAT: 5>,
240+
bids_id='auto_00000')]
241+
217242
"""
218243
from .. import fieldmaps as fm
219244
from bids.layout import Query
@@ -313,6 +338,8 @@ def find_estimators(*, layout, subject, fmapless=True, force_fmapless=False):
313338

314339
from .epimanip import get_trt
315340

341+
# Sessions may not be defined at this point if some id was found.
342+
sessions = layout.get_sessions()
316343
for ses, suffix in sorted(product(sessions or (None,), fmapless)):
317344
candidates = layout.get(suffix=suffix, session=ses, **base_entities)
318345

@@ -324,6 +351,7 @@ def find_estimators(*, layout, subject, fmapless=True, force_fmapless=False):
324351
for candidate in candidates:
325352
meta = candidate.get_metadata()
326353
pe_dir = meta.get("PhaseEncodingDirection")
354+
327355
if not pe_dir:
328356
continue
329357

0 commit comments

Comments
 (0)