Skip to content

Commit 45ab13e

Browse files
authored
Merge pull request #714 from nipreps/restore-707
FIX: Address some reliability issues of the functional masking workflow
2 parents 2c4b75e + 57f27b0 commit 45ab13e

File tree

2 files changed

+20
-41
lines changed

2 files changed

+20
-41
lines changed

niworkflows/data/epi_atlasbased_brainmask.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"winsorize_upper_quantile": 0.98,
33
"winsorize_lower_quantile": 0.05,
4-
"float": true,
54
"metric": ["Mattes"],
65
"metric_weight": [1],
76
"radius_or_number_of_bins": [64],

niworkflows/func/util.py

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ def init_enhance_and_skullstrip_bold_wf(
363363
reportlet for the skull-stripping
364364
365365
"""
366+
from niworkflows.interfaces.nibabel import ApplyMask, BinaryDilation
367+
366368
workflow = Workflow(name=name)
367369
inputnode = pe.Node(
368370
niu.IdentityInterface(fields=["in_file", "pre_mask"]), name="inputnode"
@@ -374,20 +376,6 @@ def init_enhance_and_skullstrip_bold_wf(
374376
name="outputnode",
375377
)
376378

377-
# Dilate pre_mask
378-
pre_dilate = pe.Node(
379-
fsl.DilateImage(
380-
operation="max",
381-
kernel_shape="sphere",
382-
kernel_size=3.0,
383-
internal_datatype="char",
384-
),
385-
name="pre_mask_dilate",
386-
)
387-
388-
# Ensure mask's header matches reference's
389-
check_hdr = pe.Node(MatchHeader(), name="check_hdr", run_without_submitting=True)
390-
391379
# Run N4 normally, force num_threads=1 for stability (images are small, no need for >1)
392380
n4_correct = pe.Node(
393381
N4BiasFieldCorrection(
@@ -403,16 +391,8 @@ def init_enhance_and_skullstrip_bold_wf(
403391
skullstrip_first_pass = pe.Node(
404392
fsl.BET(frac=0.2, mask=True), name="skullstrip_first_pass"
405393
)
406-
bet_dilate = pe.Node(
407-
fsl.DilateImage(
408-
operation="max",
409-
kernel_shape="sphere",
410-
kernel_size=6.0,
411-
internal_datatype="char",
412-
),
413-
name="skullstrip_first_dilate",
414-
)
415-
bet_mask = pe.Node(fsl.ApplyMask(), name="skullstrip_first_mask")
394+
first_dilate = pe.Node(BinaryDilation(radius=6), name="first_dilate")
395+
first_mask = pe.Node(ApplyMask(), name="first_mask")
416396

417397
# Use AFNI's unifize for T2 constrast & fix header
418398
unifize = pe.Node(
@@ -438,11 +418,10 @@ def init_enhance_and_skullstrip_bold_wf(
438418
combine_masks = pe.Node(fsl.BinaryMaths(operation="mul"), name="combine_masks")
439419

440420
# Compute masked brain
441-
apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask")
421+
apply_mask = pe.Node(ApplyMask(), name="apply_mask")
442422

443423
if not pre_mask:
444424
from nipype.interfaces.ants.utils import AI
445-
from ..interfaces.nibabel import Binarize
446425

447426
bold_template = get_template(
448427
"MNI152NLin2009cAsym", resolution=2, desc="fMRIPrep", suffix="boldref"
@@ -495,10 +474,12 @@ def init_enhance_and_skullstrip_bold_wf(
495474
),
496475
name="map_brainmask",
497476
)
498-
binarize_mask = pe.Node(Binarize(thresh_low=brainmask_thresh), name="binarize_mask")
477+
# Ensure mask's header matches reference's
478+
check_hdr = pe.Node(MatchHeader(), name="check_hdr", run_without_submitting=True)
499479

500480
# fmt: off
501481
workflow.connect([
482+
(inputnode, check_hdr, [("in_file", "reference")]),
502483
(inputnode, init_aff, [("in_file", "moving_image")]),
503484
(inputnode, map_brainmask, [("in_file", "reference_image")]),
504485
(inputnode, norm, [("in_file", "moving_image")]),
@@ -507,37 +488,34 @@ def init_enhance_and_skullstrip_bold_wf(
507488
("reverse_invert_flags", "invert_transform_flags"),
508489
("reverse_transforms", "transforms"),
509490
]),
510-
(map_brainmask, binarize_mask, [("output_image", "in_file")]),
511-
(binarize_mask, pre_dilate, [("out_mask", "in_file")]),
491+
(map_brainmask, check_hdr, [("output_image", "in_file")]),
492+
(check_hdr, n4_correct, [("out_file", "weight_image")]),
512493
])
513494
# fmt: on
514495
else:
515496
# fmt: off
516497
workflow.connect([
517-
(inputnode, pre_dilate, [("pre_mask", "in_file")]),
498+
(inputnode, n4_correct, [("pre_mask", "weight_image")]),
518499
])
519500
# fmt: on
520501

521502
# fmt: off
522503
workflow.connect([
523-
(inputnode, check_hdr, [("in_file", "reference")]),
524-
(pre_dilate, check_hdr, [("out_file", "in_file")]),
525-
(check_hdr, n4_correct, [("out_file", "weight_image")]),
526504
(inputnode, n4_correct, [("in_file", "input_image")]),
527505
(inputnode, fixhdr_unifize, [("in_file", "hdr_file")]),
528506
(inputnode, fixhdr_skullstrip2, [("in_file", "hdr_file")]),
529507
(n4_correct, skullstrip_first_pass, [("output_image", "in_file")]),
530-
(skullstrip_first_pass, bet_dilate, [("mask_file", "in_file")]),
531-
(bet_dilate, bet_mask, [("out_file", "mask_file")]),
532-
(skullstrip_first_pass, bet_mask, [("out_file", "in_file")]),
533-
(bet_mask, unifize, [("out_file", "in_file")]),
508+
(skullstrip_first_pass, first_dilate, [("mask_file", "in_file")]),
509+
(first_dilate, first_mask, [("out_file", "in_mask")]),
510+
(skullstrip_first_pass, first_mask, [("out_file", "in_file")]),
511+
(first_mask, unifize, [("out_file", "in_file")]),
534512
(unifize, fixhdr_unifize, [("out_file", "in_file")]),
535513
(fixhdr_unifize, skullstrip_second_pass, [("out_file", "in_file")]),
536514
(skullstrip_first_pass, combine_masks, [("mask_file", "in_file")]),
537515
(skullstrip_second_pass, fixhdr_skullstrip2, [("out_file", "in_file")]),
538516
(fixhdr_skullstrip2, combine_masks, [("out_file", "operand_file")]),
539517
(fixhdr_unifize, apply_mask, [("out_file", "in_file")]),
540-
(combine_masks, apply_mask, [("out_file", "mask_file")]),
518+
(combine_masks, apply_mask, [("out_file", "in_mask")]),
541519
(combine_masks, outputnode, [("out_file", "mask_file")]),
542520
(apply_mask, outputnode, [("out_file", "skull_stripped_file")]),
543521
(n4_correct, outputnode, [("output_image", "bias_corrected_file")]),
@@ -579,6 +557,8 @@ def init_skullstrip_bold_wf(name="skullstrip_bold_wf"):
579557
reportlet for the skull-stripping
580558
581559
"""
560+
from niworkflows.interfaces.nibabel import ApplyMask
561+
582562
workflow = Workflow(name=name)
583563
inputnode = pe.Node(niu.IdentityInterface(fields=["in_file"]), name="inputnode")
584564
outputnode = pe.Node(
@@ -594,7 +574,7 @@ def init_skullstrip_bold_wf(name="skullstrip_bold_wf"):
594574
afni.Automask(dilate=1, outputtype="NIFTI_GZ"), name="skullstrip_second_pass"
595575
)
596576
combine_masks = pe.Node(fsl.BinaryMaths(operation="mul"), name="combine_masks")
597-
apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask")
577+
apply_mask = pe.Node(ApplyMask(), name="apply_mask")
598578
mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet")
599579

600580
# fmt: off
@@ -606,7 +586,7 @@ def init_skullstrip_bold_wf(name="skullstrip_bold_wf"):
606586
(combine_masks, outputnode, [("out_file", "mask_file")]),
607587
# Masked file
608588
(inputnode, apply_mask, [("in_file", "in_file")]),
609-
(combine_masks, apply_mask, [("out_file", "mask_file")]),
589+
(combine_masks, apply_mask, [("out_file", "in_mask")]),
610590
(apply_mask, outputnode, [("out_file", "skull_stripped_file")]),
611591
# Reportlet
612592
(inputnode, mask_reportlet, [("in_file", "background_file")]),

0 commit comments

Comments
 (0)