Skip to content

Commit 4597c7d

Browse files
committed
enh: better handling of sbrefs and the workflow's description
validates incoming sbrefs as suggested in nipreps/fmriprep#1803 (comment)
1 parent 3065fd5 commit 4597c7d

File tree

1 file changed

+52
-30
lines changed

1 file changed

+52
-30
lines changed

niworkflows/func/util.py

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
def init_bold_reference_wf(
3131
omp_nthreads,
3232
bold_file=None,
33+
sbref_files=None,
3334
brainmask_thresh=0.85,
3435
pre_mask=False,
3536
multiecho=False,
@@ -57,6 +58,10 @@ def init_bold_reference_wf(
5758
Maximum number of threads an individual process may use
5859
bold_file : :obj:`str`
5960
BOLD series NIfTI file
61+
sbref_files : :obj:`list` or :obj:`bool`
62+
Single band (as opposed to multi band) reference NIfTI file.
63+
If ``True`` is passed, the workflow is built to accommodate SBRefs,
64+
but the input is left undefined (i.e., it is left open for connection)
6065
brainmask_thresh: :obj:`float`
6166
Lower threshold for the probabilistic brainmask to obtain
6267
the final binary mask (default: 0.85).
@@ -109,16 +114,12 @@ def init_bold_reference_wf(
109114
110115
"""
111116
workflow = Workflow(name=name)
112-
if multiecho:
113-
workflow.__desc__ = """\
117+
workflow.__desc__ = f"""\
114118
First, a reference volume and its skull-stripped version were generated
115-
from the first echo using a custom methodology of *fMRIPrep*.
116-
"""
117-
else:
118-
workflow.__desc__ = """\
119-
First, a reference volume and its skull-stripped version were generated
120-
using a custom methodology of *fMRIPrep*.
119+
{'from the shortest echo of the BOLD run' * multiecho} using a custom
120+
methodology of *fMRIPrep*.
121121
"""
122+
122123
inputnode = pe.Node(
123124
niu.IdentityInterface(
124125
fields=["bold_file", "bold_mask", "dummy_scans", "sbref_file"]
@@ -146,17 +147,12 @@ def init_bold_reference_wf(
146147
if bold_file is not None:
147148
inputnode.inputs.bold_file = bold_file
148149

149-
if multiecho:
150-
validate = pe.MapNode(
151-
ValidateImage(),
152-
name="validate",
153-
mem_gb=DEFAULT_MEMORY_MIN_GB,
154-
iterfield=["in_file"],
155-
)
156-
else:
157-
validate = pe.Node(
158-
ValidateImage(), name="validate", mem_gb=DEFAULT_MEMORY_MIN_GB
159-
)
150+
val_bold = pe.MapNode(
151+
ValidateImage(),
152+
name="val_bold",
153+
mem_gb=DEFAULT_MEMORY_MIN_GB,
154+
iterfield=["in_file"],
155+
)
160156

161157
gen_ref = pe.Node(
162158
EstimateReferenceImage(multiecho=multiecho), name="gen_ref", mem_gb=1
@@ -173,25 +169,23 @@ def init_bold_reference_wf(
173169
run_without_submitting=True,
174170
mem_gb=DEFAULT_MEMORY_MIN_GB,
175171
)
176-
sel_1st = pe.Node(niu.Select(index=[0]),
177-
name="sel_1st", run_without_submitting=True)
172+
bold_1st = pe.Node(niu.Select(index=[0]),
173+
name="bold_1st", run_without_submitting=True)
174+
validate_1st = pe.Node(niu.Select(index=[0]),
175+
name="validate_1st", run_without_submitting=True)
178176

179177
# fmt: off
180178
workflow.connect([
181-
(inputnode, validate, [
182-
(("bold_file", ensure_list) if multiecho else "bold_file",
183-
"in_file"),
184-
]),
179+
(inputnode, val_bold, [(("bold_file", ensure_list), "in_file")]),
185180
(inputnode, enhance_and_skullstrip_bold_wf, [
186181
("bold_mask", "inputnode.pre_mask"),
187182
]),
188-
(inputnode, gen_ref, [("sbref_file", "sbref_file")]),
189183
(inputnode, calc_dummy_scans, [("dummy_scans", "dummy_scans")]),
190-
(validate, gen_ref, [("out_file", "in_file")]),
184+
(val_bold, gen_ref, [("out_file", "in_file")]),
191185
(gen_ref, enhance_and_skullstrip_bold_wf, [
192186
("ref_image", "inputnode.in_file"),
193187
]),
194-
(validate, sel_1st, [(("out_file", ensure_list), "inlist")]),
188+
(val_bold, bold_1st, [(("out_file", ensure_list), "inlist")]),
195189
(gen_ref, calc_dummy_scans, [("n_volumes_to_discard", "algo_dummy_scans")]),
196190
(calc_dummy_scans, outputnode, [("skip_vols_num", "skip_vols")]),
197191
(gen_ref, outputnode, [
@@ -203,11 +197,39 @@ def init_bold_reference_wf(
203197
("outputnode.mask_file", "bold_mask"),
204198
("outputnode.skull_stripped_file", "ref_image_brain"),
205199
]),
206-
(validate, outputnode, [("out_report", "validation_report")]),
207-
(sel_1st, outputnode, [("out", "bold_file")]),
200+
(val_bold, validate_1st, [(("out_report", ensure_list), "inlist")]),
201+
(bold_1st, outputnode, [("out", "bold_file")]),
202+
(validate_1st, outputnode, [("out", "validation_report")]),
208203
])
209204
# fmt: on
210205

206+
if sbref_files:
207+
nsbrefs = 0
208+
if sbref_files is not True:
209+
# If not boolean, then it is a list-of or pathlike.
210+
inputnode.inputs.sbref_file = sbref_files
211+
nsbrefs = 1 if isinstance(sbref_files, str) else len(sbref_files)
212+
213+
val_sbref = pe.MapNode(
214+
ValidateImage(),
215+
name="val_sbref",
216+
mem_gb=DEFAULT_MEMORY_MIN_GB,
217+
iterfield=["in_file"],
218+
)
219+
# fmt: off
220+
workflow.connect([
221+
(inputnode, val_sbref, [(("sbref_file", ensure_list), "in_file")]),
222+
(val_sbref, gen_ref, [("sbref_file", "sbref_file")]),
223+
])
224+
# fmt: on
225+
226+
# Edit the boilerplate as the SBRef will be the reference
227+
workflow.__desc__ = f"""\
228+
First, a reference volume and its skull-stripped version were generated
229+
by aligning and averaging{' the first echo of' * multiecho}
230+
{nsbrefs or ''} single-band references (SBRefs).
231+
"""
232+
211233
if gen_report:
212234
mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet")
213235
# fmt: off

0 commit comments

Comments
 (0)