20
20
from ..interfaces .masks import SimpleShowMaskRPT
21
21
from ..interfaces .registration import EstimateReferenceImage
22
22
from ..interfaces .utils import CopyXForm
23
+ from ..utils .connections import listify
23
24
from ..utils .misc import pass_dummy_scans as _pass_dummy_scans
24
25
25
26
29
30
def init_bold_reference_wf (
30
31
omp_nthreads ,
31
32
bold_file = None ,
33
+ sbref_files = None ,
32
34
brainmask_thresh = 0.85 ,
33
35
pre_mask = False ,
36
+ multiecho = False ,
34
37
name = "bold_reference_wf" ,
35
38
gen_report = False ,
36
39
):
@@ -51,19 +54,26 @@ def init_bold_reference_wf(
51
54
52
55
Parameters
53
56
----------
54
- omp_nthreads : int
57
+ omp_nthreads : :obj:` int`
55
58
Maximum number of threads an individual process may use
56
- bold_file : str
59
+ bold_file : :obj:` str`
57
60
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)
58
65
brainmask_thresh: :obj:`float`
59
66
Lower threshold for the probabilistic brainmask to obtain
60
67
the final binary mask (default: 0.85).
61
- pre_mask : bool
68
+ pre_mask : :obj:` bool`
62
69
Indicates whether the ``pre_mask`` input will be set (and thus, step 1
63
70
should be skipped).
64
- name : str
71
+ multiecho : :obj:`bool`
72
+ If multiecho data was supplied, data from the first echo
73
+ will be selected
74
+ name : :obj:`str`
65
75
Name of workflow (default: ``bold_reference_wf``)
66
- gen_report : bool
76
+ gen_report : :obj:` bool`
67
77
Whether a mask report node should be appended in the end
68
78
69
79
Inputs
@@ -104,10 +114,12 @@ def init_bold_reference_wf(
104
114
105
115
"""
106
116
workflow = Workflow (name = name )
107
- workflow .__desc__ = """\
117
+ workflow .__desc__ = f """\
108
118
First, a reference volume and its skull-stripped version were generated
109
- using a custom methodology of *fMRIPrep*.
119
+ { 'from the shortest echo of the BOLD run' * multiecho } using a custom
120
+ methodology of *fMRIPrep*.
110
121
"""
122
+
111
123
inputnode = pe .Node (
112
124
niu .IdentityInterface (
113
125
fields = ["bold_file" , "bold_mask" , "dummy_scans" , "sbref_file" ]
@@ -125,6 +137,7 @@ def init_bold_reference_wf(
125
137
"ref_image_brain" ,
126
138
"bold_mask" ,
127
139
"validation_report" ,
140
+ "mask_report" ,
128
141
]
129
142
),
130
143
name = "outputnode" ,
@@ -134,10 +147,15 @@ def init_bold_reference_wf(
134
147
if bold_file is not None :
135
148
inputnode .inputs .bold_file = bold_file
136
149
137
- validate = pe .Node (ValidateImage (), name = "validate" , mem_gb = DEFAULT_MEMORY_MIN_GB )
150
+ val_bold = pe .MapNode (
151
+ ValidateImage (),
152
+ name = "val_bold" ,
153
+ mem_gb = DEFAULT_MEMORY_MIN_GB ,
154
+ iterfield = ["in_file" ],
155
+ )
138
156
139
157
gen_ref = pe .Node (
140
- EstimateReferenceImage (), name = "gen_ref" , mem_gb = 1
158
+ EstimateReferenceImage (multiecho = multiecho ), name = "gen_ref" , mem_gb = 1
141
159
) # OE: 128x128x128x50 * 64 / 8 ~ 900MB.
142
160
enhance_and_skullstrip_bold_wf = init_enhance_and_skullstrip_bold_wf (
143
161
brainmask_thresh = brainmask_thresh ,
@@ -151,23 +169,23 @@ def init_bold_reference_wf(
151
169
run_without_submitting = True ,
152
170
mem_gb = DEFAULT_MEMORY_MIN_GB ,
153
171
)
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 )
154
176
155
177
# fmt: off
156
178
workflow .connect ([
179
+ (inputnode , val_bold , [(("bold_file" , listify ), "in_file" )]),
157
180
(inputnode , enhance_and_skullstrip_bold_wf , [
158
181
("bold_mask" , "inputnode.pre_mask" ),
159
182
]),
160
- (inputnode , validate , [("bold_file" , "in_file" )]),
161
- (inputnode , gen_ref , [("sbref_file" , "sbref_file" )]),
162
183
(inputnode , calc_dummy_scans , [("dummy_scans" , "dummy_scans" )]),
163
- (validate , gen_ref , [("out_file" , "in_file" )]),
184
+ (val_bold , gen_ref , [("out_file" , "in_file" )]),
164
185
(gen_ref , enhance_and_skullstrip_bold_wf , [
165
186
("ref_image" , "inputnode.in_file" ),
166
187
]),
167
- (validate , outputnode , [
168
- ("out_file" , "bold_file" ),
169
- ("out_report" , "validation_report" ),
170
- ]),
188
+ (val_bold , bold_1st , [(("out_file" , listify ), "inlist" )]),
171
189
(gen_ref , calc_dummy_scans , [("n_volumes_to_discard" , "algo_dummy_scans" )]),
172
190
(calc_dummy_scans , outputnode , [("skip_vols_num" , "skip_vols" )]),
173
191
(gen_ref , outputnode , [
@@ -179,9 +197,39 @@ def init_bold_reference_wf(
179
197
("outputnode.mask_file" , "bold_mask" ),
180
198
("outputnode.skull_stripped_file" , "ref_image_brain" ),
181
199
]),
200
+ (val_bold , validate_1st , [(("out_report" , listify ), "inlist" )]),
201
+ (bold_1st , outputnode , [("out" , "bold_file" )]),
202
+ (validate_1st , outputnode , [("out" , "validation_report" )]),
182
203
])
183
204
# fmt: on
184
205
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" , listify ), "in_file" )]),
222
+ (val_sbref , gen_ref , [("out_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
+
185
233
if gen_report :
186
234
mask_reportlet = pe .Node (SimpleShowMaskRPT (), name = "mask_reportlet" )
187
235
# fmt: off
0 commit comments