Skip to content

Commit dc654bb

Browse files
committed
MAINT: Finalize upstreaming of ants interfaces to nipype
After nipy/nipype#3210 the ``niworkflows/interfaces/ants.py`` can go in whole.
1 parent bb44cd7 commit dc654bb

File tree

3 files changed

+38
-723
lines changed

3 files changed

+38
-723
lines changed

niworkflows/anat/ants.py

Lines changed: 30 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,25 @@
1212
# nipype
1313
from nipype.pipeline import engine as pe
1414
from nipype.interfaces import utility as niu
15-
from nipype.interfaces.fsl.maths import ApplyMask
16-
from nipype.interfaces.ants import N4BiasFieldCorrection, Atropos, MultiplyImages
15+
from nipype.interfaces.ants import (
16+
AI,
17+
Atropos,
18+
MultiplyImages,
19+
N4BiasFieldCorrection,
20+
ResampleImageBySpacing,
21+
ThresholdImage,
22+
)
1723

1824
from ..utils.misc import get_template_specs
1925
from ..utils.connections import pop_file as _pop
2026

2127
# niworkflows
22-
from ..interfaces.ants import (
23-
ImageMath,
24-
ResampleImageBySpacing,
25-
AI,
26-
ThresholdImage,
27-
)
28+
from ..interfaces.nibabel import ApplyMask
29+
from ..interfaces.ants import ImageMath
2830
from ..interfaces.fixes import (
2931
FixHeaderRegistration as Registration,
3032
FixHeaderApplyTransforms as ApplyTransforms,
3133
)
32-
from ..interfaces.utils import CopyXForm
3334
from ..interfaces.nibabel import Binarize
3435

3536

@@ -84,7 +85,7 @@ def init_brain_extraction_wf(
8485
Parameters
8586
----------
8687
in_template : str
87-
Name of the skull-stripping template ('OASIS30ANTs', 'NKI', or
88+
Name of the skull-stripping template ("OASIS30ANTs", "NKI", or
8889
path).
8990
The brain template from which regions will be projected
9091
Anatomical template created using e.g. LPBA40 data set with
@@ -201,12 +202,6 @@ def init_brain_extraction_wf(
201202
name="outputnode",
202203
)
203204

204-
copy_xform = pe.Node(
205-
CopyXForm(fields=["out_file", "out_mask", "bias_corrected", "bias_image"]),
206-
name="copy_xform",
207-
run_without_submitting=True,
208-
)
209-
210205
trunc = pe.MapNode(
211206
ImageMath(operation="TruncateImageIntensity", op2="0.01 0.999 256"),
212207
name="truncate_images",
@@ -338,7 +333,6 @@ def init_brain_extraction_wf(
338333
# fmt: off
339334
wf.connect([
340335
(inputnode, trunc, [("in_files", "op1")]),
341-
(inputnode, copy_xform, [(("in_files", _pop), "hdr_file")]),
342336
(inputnode, inu_n4_final, [("in_files", "input_image")]),
343337
(inputnode, init_aff, [("in_mask", "fixed_image_mask")]),
344338
(inputnode, norm, [("in_mask", fixed_mask_trait)]),
@@ -356,19 +350,11 @@ def init_brain_extraction_wf(
356350
(thr_brainmask, dil_brainmask, [("output_image", "op1")]),
357351
(dil_brainmask, get_brainmask, [("output_image", "op1")]),
358352
(inu_n4_final, apply_mask, [("output_image", "in_file")]),
359-
(get_brainmask, apply_mask, [("output_image", "mask_file")]),
360-
(get_brainmask, copy_xform, [("output_image", "out_mask")]),
361-
(apply_mask, copy_xform, [("out_file", "out_file")]),
362-
(inu_n4_final, copy_xform, [
363-
("output_image", "bias_corrected"),
364-
("bias_image", "bias_image"),
365-
]),
366-
(copy_xform, outputnode, [
367-
("out_file", "out_file"),
368-
("out_mask", "out_mask"),
369-
("bias_corrected", "bias_corrected"),
370-
("bias_image", "bias_image"),
371-
]),
353+
(get_brainmask, apply_mask, [("output_image", "in_mask")]),
354+
(get_brainmask, outputnode, [("output_image", "out_mask")]),
355+
(inu_n4_final, outputnode, [("output_image", "bias_corrected"),
356+
("bias_image", "bias_image")]),
357+
(apply_mask, outputnode, [("out_file", "out_file")]),
372358
])
373359
# fmt: on
374360

@@ -418,8 +404,8 @@ def init_brain_extraction_wf(
418404

419405
# fmt: off
420406
wf.disconnect([
421-
(get_brainmask, apply_mask, [("output_image", "mask_file")]),
422-
(copy_xform, outputnode, [("out_mask", "out_mask")]),
407+
(get_brainmask, apply_mask, [("output_image", "in_mask")]),
408+
(get_brainmask, outputnode, [("output_image", "out_mask")]),
423409
])
424410
wf.connect([
425411
(inu_n4, atropos_wf, [("output_image", "inputnode.in_files")]),
@@ -429,7 +415,7 @@ def init_brain_extraction_wf(
429415
]),
430416
(atropos_wf, sel_wm, [("outputnode.out_tpms", "inlist")]),
431417
(sel_wm, inu_n4_final, [("out", "weight_image")]),
432-
(atropos_wf, apply_mask, [("outputnode.out_mask", "mask_file")]),
418+
(atropos_wf, apply_mask, [("outputnode.out_mask", "in_mask")]),
433419
(atropos_wf, outputnode, [
434420
("outputnode.out_mask", "out_mask"),
435421
("outputnode.out_segm", "out_segm"),
@@ -508,7 +494,6 @@ def init_atropos_wf(
508494
out_tpms : str
509495
Output :abbr:`TPMs (tissue probability maps)`
510496
511-
512497
"""
513498
wf = pe.Workflow(name)
514499

@@ -521,12 +506,6 @@ def init_atropos_wf(
521506
name="outputnode",
522507
)
523508

524-
copy_xform = pe.Node(
525-
CopyXForm(fields=["out_mask", "out_segm", "out_tpms"]),
526-
name="copy_xform",
527-
run_without_submitting=True,
528-
)
529-
530509
# Run atropos (core node)
531510
atropos = pe.Node(
532511
Atropos(
@@ -645,17 +624,16 @@ def init_atropos_wf(
645624
ImageMath(operation="PadImage", op2="-%d" % padding), name="27_depad_csf"
646625
)
647626

648-
msk_conform = pe.Node(niu.Function(function=_conform_mask), name="msk_conform")
627+
msk_dtype = pe.Node(niu.Function(function=_ensure_dtype), name="msk_dtype")
628+
msk_dtype.inputs.dtype = "uint8"
649629
merge_tpms = pe.Node(niu.Merge(in_segmentation_model[0]), name="merge_tpms")
650630
# fmt: off
651631
wf.connect([
652-
(inputnode, copy_xform, [(("in_files", _pop), "hdr_file")]),
653632
(inputnode, pad_mask, [("in_mask", "op1")]),
654633
(inputnode, atropos, [
655634
("in_files", "intensity_images"),
656635
("in_mask_dilated", "mask_image"),
657636
]),
658-
(inputnode, msk_conform, [(("in_files", _pop), "in_reference")]),
659637
(atropos, pad_segm, [("classified_image", "op1")]),
660638
(pad_segm, sel_labels, [("output_image", "in_segm")]),
661639
(sel_labels, get_wm, [("out_wm", "op1")]),
@@ -688,15 +666,10 @@ def init_atropos_wf(
688666
(depad_csf, merge_tpms, [("output_image", "in1")]),
689667
(depad_gm, merge_tpms, [("output_image", "in2")]),
690668
(depad_wm, merge_tpms, [("output_image", "in3")]),
691-
(depad_mask, msk_conform, [("output_image", "in_mask")]),
692-
(msk_conform, copy_xform, [("out", "out_mask")]),
693-
(depad_segm, copy_xform, [("output_image", "out_segm")]),
694-
(merge_tpms, copy_xform, [("out", "out_tpms")]),
695-
(copy_xform, outputnode, [
696-
("out_mask", "out_mask"),
697-
("out_segm", "out_segm"),
698-
("out_tpms", "out_tpms"),
699-
]),
669+
(depad_mask, msk_dtype, [("output_image", "in_mask")]),
670+
(msk_dtype, outputnode, [("out", "out_mask")]),
671+
(depad_segm, outputnode, [("output_image", "out_segm")]),
672+
(merge_tpms, outputnode, [("out", "out_tpms")]),
700673
])
701674
# fmt: on
702675
return wf
@@ -748,7 +721,7 @@ def init_n4_only_wf(
748721
Allows to specify a particular segmentation model, overwriting
749722
the defaults based on ``bids_suffix``
750723
name : str, optional
751-
Workflow name (default: ``'n4_only_wf'``).
724+
Workflow name (default: ``"n4_only_wf"``).
752725
753726
Inputs
754727
------
@@ -918,34 +891,25 @@ def _select_labels(in_segm, labels):
918891
return out_files
919892

920893

921-
def _conform_mask(in_mask, in_reference):
922-
"""Ensures the mask headers make sense and match those of the T1w"""
894+
def _ensure_dtype(in_mask, dtype="uint8"):
895+
"""Ensure the mask headers make sense and match those of the T1w."""
923896
from pathlib import Path
924897
import numpy as np
925898
import nibabel as nb
926899
from nipype.utils.filemanip import fname_presuffix
927900

928-
ref = nb.load(in_reference)
929901
nii = nb.load(in_mask)
930902
hdr = nii.header.copy()
931-
hdr.set_data_dtype("int16")
903+
hdr.set_data_dtype(dtype)
932904
hdr.set_slope_inter(1, 0)
933905

934-
qform, qcode = ref.header.get_qform(coded=True)
935-
if qcode is not None:
936-
hdr.set_qform(qform, int(qcode))
937-
938-
sform, scode = ref.header.get_sform(coded=True)
939-
if scode is not None:
940-
hdr.set_sform(sform, int(scode))
941-
942906
if "_maths" in in_mask: # Cut the name at first _maths occurrence
943907
ext = "".join(Path(in_mask).suffixes)
944908
basename = Path(in_mask).name
945909
in_mask = basename.split("_maths")[0] + ext
946910

947911
out_file = fname_presuffix(in_mask, suffix="_mask", newpath=str(Path()))
948912
nii.__class__(
949-
np.asanyarray(nii.dataobj).astype("int16"), ref.affine, hdr
913+
np.asanyarray(nii.dataobj).astype(dtype), nii.affine, hdr
950914
).to_filename(out_file)
951915
return out_file

niworkflows/func/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
from nipype.pipeline import engine as pe
88
from nipype.interfaces import utility as niu, fsl, afni
9+
from nipype.interfaces.ants.utils import AI
910

1011
from templateflow.api import get as get_template
1112

1213
from ..engine.workflows import LiterateWorkflow as Workflow
13-
from ..interfaces.ants import AI
1414
from ..interfaces.fixes import (
1515
FixHeaderRegistration as Registration,
1616
FixHeaderApplyTransforms as ApplyTransforms,

0 commit comments

Comments
 (0)