Skip to content

Commit 62c183a

Browse files
committed
enh: add a fieldmap wrangler method.
1 parent 29f2d0b commit 62c183a

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

sdcflows/workflows/base.py

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def init_sdc_estimate_wf(fmaps, epi_meta, omp_nthreads=1, debug=False, ignore=No
6767
Outputs
6868
-------
6969
epi_file
70-
An unwarped EPI scan reference
70+
The EPI scan reference after unwarping.
7171
epi_mask
7272
The corresponding new mask after unwarping
7373
epi_brain
@@ -77,6 +77,8 @@ def init_sdc_estimate_wf(fmaps, epi_meta, omp_nthreads=1, debug=False, ignore=No
7777
syn_ref
7878
If ``--force-syn``, an unwarped EPI scan reference with this
7979
method (for reporting purposes)
80+
method : str
81+
Short description of the estimation method that was run.
8082
8183
"""
8284
workflow = Workflow(name='sdc_estimate_wf' if fmaps else 'sdc_bypass_wf')
@@ -162,23 +164,37 @@ def init_sdc_estimate_wf(fmaps, epi_meta, omp_nthreads=1, debug=False, ignore=No
162164

163165
if 'fieldmap' in fmaps:
164166
from .fmap import init_fmap_wf
167+
try:
168+
fmap, = fmaps['fieldmap']
169+
except ValueError:
170+
LOGGER.warning('Several B0 fieldmaps found for the given target, using '
171+
'the first one.')
172+
fmap = fmaps['fieldmap'][0]
173+
165174
outputnode.inputs.method = 'FMB (fieldmap-based) - directly measured B0 map'
166175
fmap_wf = init_fmap_wf(
167176
omp_nthreads=omp_nthreads,
168177
fmap_bspline=False)
169178
# set inputs
170179
fmap_wf.inputs.inputnode.magnitude = [
171-
m for m, _ in fmaps['fieldmap']['magnitude']]
180+
m for m, _ in fmap['magnitude']]
172181
fmap_wf.inputs.inputnode.fieldmap = [
173-
m for m, _ in fmaps['fieldmap']['fieldmap']]
182+
m for m, _ in fmap['fieldmap']]
174183
elif 'phasediff' in fmaps:
175184
from .phdiff import init_phdiff_wf
185+
try:
186+
fmap, = fmaps['phasediff']
187+
except ValueError:
188+
LOGGER.warning('Several phase-difference maps found for the given target, using '
189+
'the first one.')
190+
fmap = fmaps['phasediff'][0]
191+
176192
outputnode.inputs.method = 'FMB (fieldmap-based) - phase-difference map'
177193
fmap_wf = init_phdiff_wf(omp_nthreads=omp_nthreads)
178194
# set inputs
179195
fmap_wf.inputs.inputnode.magnitude = [
180-
m for m, _ in fmaps['phasediff']['magnitude']]
181-
fmap_wf.inputs.inputnode.phasediff = fmaps['phasediff']['phases']
196+
m for m, _ in fmap['magnitude']]
197+
fmap_wf.inputs.inputnode.phasediff = fmap['phases']
182198

183199
fmap2field_wf = init_fmap2field_wf(omp_nthreads=omp_nthreads, debug=debug)
184200
fmap2field_wf.inputs.inputnode.metadata = epi_meta
@@ -242,3 +258,38 @@ def init_sdc_estimate_wf(fmaps, epi_meta, omp_nthreads=1, debug=False, ignore=No
242258
])
243259

244260
return workflow
261+
262+
263+
def fieldmap_wrangler(layout, target_image, use_syn=False, force_syn=False):
264+
"""Query the BIDSLayout for fieldmaps, and arrange them for the orchestration workflow."""
265+
from collections import defaultdict
266+
fmap_bids = layout.get_fieldmap(target_image, return_list=True)
267+
fieldmaps = defaultdict(list)
268+
for fmap in fmap_bids:
269+
if fmap['suffix'] == 'epi':
270+
fieldmaps['epi'].append((fmap['epi'], layout.get_metadata(fmap['epi'])))
271+
272+
if fmap['suffix'] == 'fieldmap':
273+
fieldmaps['fieldmap'].append({
274+
'magnitude': [(fmap['magnitude'], layout.get_metadata(fmap['magnitude']))],
275+
'fieldmap': [(fmap['fieldmap'], layout.get_metadata(fmap['fieldmap']))],
276+
})
277+
278+
if fmap['suffix'] == 'phasediff':
279+
fieldmaps['phasediff'].append({
280+
'magnitude': [(fmap[k], layout.get_metadata(fmap[k]))
281+
for k in sorted(fmap.keys()) if k.startswith('magnitude')],
282+
'phases': [(fmap['phasediff'], layout.get_metadata(fmap['phasediff']))],
283+
})
284+
285+
if fmap['suffix'] == 'phase':
286+
fieldmaps['phasediff'].append({
287+
'magnitude': [(fmap[k], layout.get_metadata(fmap[k]))
288+
for k in sorted(fmap.keys()) if k.startswith('magnitude')],
289+
'phases': [(fmap[k], layout.get_metadata(fmap[k]))
290+
for k in sorted(fmap.keys()) if k.startswith('phase')],
291+
})
292+
293+
if force_syn is True or (not fieldmaps and use_syn is True):
294+
fieldmaps['syn'] = force_syn
295+
return fieldmaps

sdcflows/workflows/tests/test_base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def test_base(method):
6868
"""Check the heuristics are correctly applied."""
6969
fieldmaps = {
7070
'epi': FMAP_DICT_ELEMENTS['epi1'].copy(),
71-
'fieldmap': FMAP_DICT_ELEMENTS['fmap1'].copy(),
72-
'phasediff': FMAP_DICT_ELEMENTS['phdiff1'].copy(),
71+
'fieldmap': [FMAP_DICT_ELEMENTS['fmap1'].copy()],
72+
'phasediff': [FMAP_DICT_ELEMENTS['phdiff1'].copy()],
7373
}
7474
epi_meta = EPI_METADATA.copy()
7575

@@ -103,15 +103,15 @@ def test_base(method):
103103

104104
elif method == 'fieldmap':
105105
fieldmaps = {
106-
'fieldmap': FMAP_DICT_ELEMENTS['fmap1'].copy(),
107-
'phasediff': FMAP_DICT_ELEMENTS['phdiff1'].copy(),
106+
'fieldmap': [FMAP_DICT_ELEMENTS['fmap1'].copy()],
107+
'phasediff': [FMAP_DICT_ELEMENTS['phdiff1'].copy()],
108108
}
109109
wf = init_sdc_estimate_wf(fmaps=fieldmaps, epi_meta=epi_meta)
110110
assert 'directly measured B0 map' in wf.inputs.outputnode.method
111111

112112
elif method == 'phasediff':
113113
fieldmaps = {
114-
'phasediff': FMAP_DICT_ELEMENTS['phdiff1'].copy(),
114+
'phasediff': [FMAP_DICT_ELEMENTS['phdiff1'].copy()],
115115
}
116116

117117
wf = init_sdc_estimate_wf(fmaps=fieldmaps, epi_meta=epi_meta)

0 commit comments

Comments
 (0)