Skip to content

Commit 3373280

Browse files
committed
ENH: add PET mask generation workflow
1 parent d17cdf7 commit 3373280

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

fmriprep/workflows/pet/fit.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from .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,
@@ -352,6 +353,43 @@ def init_pet_fit_wf(
352353
else:
353354
outputnode.inputs.petref2anat_xfm = petref2anat_xform
354355

356+
# Stage 4: Estimate PET brain mask
357+
from niworkflows.interfaces.fixes import FixHeaderApplyTransforms as ApplyTransforms
358+
from niworkflows.interfaces.nibabel import Binarize
359+
360+
from .confounds import _binary_union
361+
362+
t1w_mask_tfm = pe.Node(
363+
ApplyTransforms(interpolation='MultiLabel', invert_transform_flags=[True]),
364+
name='t1w_mask_tfm',
365+
)
366+
petref_mask = pe.Node(Binarize(thresh_low=0.2), name='petref_mask')
367+
merge_mask = pe.Node(niu.Function(function=_binary_union), name='merge_mask')
368+
369+
if not petref2anat_xform:
370+
workflow.connect(
371+
[(pet_reg_wf, t1w_mask_tfm, [('outputnode.itk_pet_to_t1', 'transforms')])]
372+
)
373+
else:
374+
t1w_mask_tfm.inputs.transforms = petref2anat_xform
375+
376+
workflow.connect([
377+
(inputnode, t1w_mask_tfm, [('t1w_mask', 'input_image')]),
378+
(petref_buffer, t1w_mask_tfm, [('petref', 'reference_image')]),
379+
(petref_buffer, petref_mask, [('petref', 'in_file')]),
380+
(petref_mask, merge_mask, [('out_mask', 'mask1')]),
381+
(t1w_mask_tfm, merge_mask, [('output_image', 'mask2')]),
382+
(merge_mask, petref_buffer, [('out', 'pet_mask')]),
383+
])
384+
385+
ds_petmask_wf = init_ds_petmask_wf(
386+
output_dir=config.execution.petprep_dir,
387+
desc='brain',
388+
name='ds_petmask_wf',
389+
)
390+
ds_petmask_wf.inputs.inputnode.source_files = [pet_file]
391+
workflow.connect([(merge_mask, ds_petmask_wf, [('out', 'inputnode.petmask')])])
392+
355393
return workflow
356394

357395

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import nibabel as nb
2+
import numpy as np
3+
from niworkflows.utils.testing import generate_bids_skeleton
4+
5+
from ...tests import mock_config
6+
from ...tests.test_base import BASE_LAYOUT
7+
from ..base import init_pet_wf
8+
9+
10+
def test_pet_mask_flow(tmp_path):
11+
bids_dir = tmp_path / 'bids'
12+
generate_bids_skeleton(bids_dir, BASE_LAYOUT)
13+
img = nb.Nifti1Image(np.zeros((2, 2, 2, 10)), np.eye(4))
14+
pet_file = bids_dir / 'sub-01' / 'pet' / 'sub-01_task-rest_run-1_pet.nii.gz'
15+
img.to_filename(pet_file)
16+
17+
with mock_config(bids_dir=bids_dir):
18+
wf = init_pet_wf(pet_series=str(pet_file), precomputed={})
19+
20+
edge = wf._graph.get_edge_data(
21+
wf.get_node('pet_fit_wf'), wf.get_node('pet_confounds_wf')
22+
)
23+
assert ('pet_mask', 'inputnode.pet_mask') in edge['connect']
24+
25+
conf_wf = wf.get_node('pet_confounds_wf')
26+
conf_edge = conf_wf._graph.get_edge_data(
27+
conf_wf.get_node('inputnode'), conf_wf.get_node('dvars')
28+
)
29+
assert ('pet_mask', 'in_mask') in conf_edge['connect']

0 commit comments

Comments
 (0)