3737from .outputs import (
3838 init_ds_hmc_wf ,
3939 init_ds_petref_wf ,
40+ init_ds_petmask_wf ,
4041 init_ds_registration_wf ,
4142 init_func_fit_reports_wf ,
4243 prepare_timing_parameters ,
@@ -176,7 +177,7 @@ def init_pet_fit_wf(
176177 workflow .add_nodes ([inputnode ])
177178
178179 petref_buffer = pe .Node (
179- niu .IdentityInterface (fields = ['petref' , 'pet_file' , 'pet_mask' ]),
180+ niu .IdentityInterface (fields = ['petref' , 'pet_file' ]),
180181 name = 'petref_buffer' ,
181182 )
182183 hmc_buffer = pe .Node (niu .IdentityInterface (fields = ['hmc_xforms' ]), name = 'hmc_buffer' )
@@ -197,11 +198,7 @@ def init_pet_fit_wf(
197198
198199 summary = pe .Node (
199200 FunctionalSummary (
200- registration = (
201- 'Precomputed'
202- if petref2anat_xform
203- else 'mri_coreg'
204- ),
201+ registration = ('Precomputed' if petref2anat_xform else 'mri_coreg' ),
205202 registration_dof = config .workflow .pet2anat_dof ,
206203 orientation = orientation ,
207204 ),
@@ -218,7 +215,6 @@ def init_pet_fit_wf(
218215 workflow .connect ([
219216 (petref_buffer , outputnode , [
220217 ('petref' , 'petref' ),
221- ('pet_mask' , 'pet_mask' ),
222218 ]),
223219 (hmc_buffer , outputnode , [
224220 ('hmc_xforms' , 'motion_xfm' ),
@@ -252,7 +248,6 @@ def init_pet_fit_wf(
252248 pet_file = pet_file ,
253249 reference_frame = config .workflow .reference_frame ,
254250 )
255- petref_wf .inputs .inputnode .dummy_scans = config .workflow .dummy_scans
256251
257252 ds_petref_wf = init_ds_petref_wf (
258253 bids_root = layout .root ,
@@ -262,6 +257,21 @@ def init_pet_fit_wf(
262257 )
263258 ds_petref_wf .inputs .inputnode .source_files = [pet_file ]
264259
260+ # Ensure all stage-1 workflows were created successfully before
261+ # attempting to connect them. Nipype's ``connect`` call will fail
262+ # with a ``NoneType`` error if any node is undefined.
263+ stage1_nodes = [
264+ petref_wf ,
265+ petref_buffer ,
266+ ds_petref_wf ,
267+ func_fit_reports_wf ,
268+ petref_source_buffer ,
269+ ]
270+ if any (node is None for node in stage1_nodes ):
271+ raise RuntimeError (
272+ 'PET reference stage could not be built - check inputs and configuration.'
273+ )
274+
265275 workflow .connect ([
266276 (petref_wf , petref_buffer , [
267277 ('outputnode.pet_file' , 'pet_file' ),
@@ -344,6 +354,45 @@ def init_pet_fit_wf(
344354 else :
345355 outputnode .inputs .petref2anat_xfm = petref2anat_xform
346356
357+ # Stage 4: Estimate PET brain mask
358+ from niworkflows .interfaces .fixes import FixHeaderApplyTransforms as ApplyTransforms
359+ from niworkflows .interfaces .nibabel import Binarize
360+
361+ from .confounds import _binary_union
362+
363+ t1w_mask_tfm = pe .Node (
364+ ApplyTransforms (interpolation = 'MultiLabel' , invert_transform_flags = [True ]),
365+ name = 't1w_mask_tfm' ,
366+ )
367+ petref_mask = pe .Node (Binarize (thresh_low = 0.2 ), name = 'petref_mask' )
368+ merge_mask = pe .Node (niu .Function (function = _binary_union ), name = 'merge_mask' )
369+
370+ if not petref2anat_xform :
371+ workflow .connect (
372+ [(pet_reg_wf , t1w_mask_tfm , [('outputnode.itk_pet_to_t1' , 'transforms' )])]
373+ )
374+ else :
375+ t1w_mask_tfm .inputs .transforms = petref2anat_xform
376+
377+ workflow .connect (
378+ [
379+ (inputnode , t1w_mask_tfm , [('t1w_mask' , 'input_image' )]),
380+ (petref_buffer , t1w_mask_tfm , [('petref' , 'reference_image' )]),
381+ (petref_buffer , petref_mask , [('petref' , 'in_file' )]),
382+ (petref_mask , merge_mask , [('out_mask' , 'mask1' )]),
383+ (t1w_mask_tfm , merge_mask , [('output_image' , 'mask2' )]),
384+ (merge_mask , outputnode , [('out' , 'pet_mask' )]),
385+ ]
386+ )
387+
388+ ds_petmask_wf = init_ds_petmask_wf (
389+ output_dir = config .execution .petprep_dir ,
390+ desc = 'brain' ,
391+ name = 'ds_petmask_wf' ,
392+ )
393+ ds_petmask_wf .inputs .inputnode .source_files = [pet_file ]
394+ workflow .connect ([(merge_mask , ds_petmask_wf , [('out' , 'inputnode.petmask' )])])
395+
347396 return workflow
348397
349398
@@ -436,18 +485,13 @@ def init_pet_native_wf(
436485 )
437486 outputnode .inputs .metadata = metadata
438487
439- petbuffer = pe .Node (
440- niu .IdentityInterface (fields = ['pet_file' ]), name = 'petbuffer'
441- )
488+ petbuffer = pe .Node (niu .IdentityInterface (fields = ['pet_file' ]), name = 'petbuffer' )
442489
443490 # PET source: track original PET file(s)
444491 # The Select interface requires an index to choose from ``inlist``. Since
445492 # ``pet_file`` is a single path, explicitly set the index to ``0`` to avoid
446493 # missing mandatory input errors when the node runs.
447- pet_source = pe .Node (
448- niu .Select (inlist = [pet_file ], index = 0 ),
449- name = 'pet_source'
450- )
494+ pet_source = pe .Node (niu .Select (inlist = [pet_file ], index = 0 ), name = 'pet_source' )
451495 validate_pet = pe .Node (ValidateImage (), name = 'validate_pet' )
452496 workflow .connect ([
453497 (pet_source , validate_pet , [('out' , 'in_file' )]),
0 commit comments