Skip to content

Commit cdf5276

Browse files
Merge pull request #25 from poldracklab/enh/use-niworkflows-interface
FIX: Correctly pin niworkflows branch and use new interface
2 parents 15b9fa5 + 3d09d34 commit cdf5276

File tree

2 files changed

+27
-57
lines changed

2 files changed

+27
-57
lines changed

nirodents/workflows/brainextraction.py

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,30 @@
33
"""Nipype translation of ANTs' workflows."""
44

55
# general purpose
6-
import os
76
from multiprocessing import cpu_count
87
from pkg_resources import resource_filename as pkgr_fn
9-
from packaging.version import parse as parseversion, Version
10-
from warnings import warn
118

129
# nipype
1310
from nipype.pipeline import engine as pe
1411
from nipype.interfaces import utility as niu
1512
from nipype.interfaces.ants import N4BiasFieldCorrection, Atropos
16-
from nipype.interfaces.ants.utils import AI # , ImageMath, ResampleImageBySpacing,
13+
from nipype.interfaces.ants.utils import AI
1714
from nipype.interfaces.afni import MaskTool
1815
from nipype.interfaces.io import DataSink
1916

2017
# niworkflows
2118
from niworkflows.interfaces.ants import ImageMath
22-
from niworkflows.utils.images import resample_by_spacing
19+
from niworkflows.interfaces.images import RegridToZooms
2320
from niworkflows.interfaces.nibabel import ApplyMask
2421
from niworkflows.interfaces.fixes import (
2522
FixHeaderRegistration as Registration,
2623
FixHeaderApplyTransforms as ApplyTransforms)
2724

2825
from templateflow.api import get as get_template
2926

27+
LOWRES_ZOOMS = (0.4, 0.4, 0.4)
28+
29+
3030
def init_rodent_brain_extraction_wf(
3131
atropos_model=None,
3232
atropos_refine=True,
@@ -71,25 +71,20 @@ def init_rodent_brain_extraction_wf(
7171
tpl_brain_mask = get_template(in_template, resolution=debug + 1, desc='cerebrum', suffix='mask')
7272

7373
# resample template and target
74-
res_tmpl = pe.Node(niu.Function(function=res_by_spc,
75-
input_names=['in_file'], output_names=['out_file']), name='res_tmpl')
76-
if tpl_target_path:
77-
res_tmpl.inputs.in_file = tpl_target_path
74+
res_tmpl = pe.Node(RegridToZooms(
75+
in_file=tpl_target_path, zooms=LOWRES_ZOOMS), name="res_tmpl")
7876

79-
res_target = pe.Node(niu.Function(function=res_by_spc,
80-
input_names=['in_file'], output_names=['out_file']), name='res_target')
81-
res_target2 = pe.Node(niu.Function(function=res_by_spc,
82-
input_names=['in_file'], output_names=['out_file']), name='res_target2')
77+
res_target = pe.Node(RegridToZooms(zooms=LOWRES_ZOOMS), name="res_target")
78+
res_target2 = pe.Node(RegridToZooms(zooms=LOWRES_ZOOMS), name="res_target2")
8379

84-
dil_mask = pe.Node(MaskTool(), name = 'dil_mask')
85-
dil_mask.inputs.outputtype = 'NIFTI_GZ'
86-
dil_mask.inputs.dilate_inputs = '2'
87-
dil_mask.inputs.fill_holes = True
80+
dil_mask = pe.Node(MaskTool(
81+
outputtype='NIFTI_GZ', dilate_inputs='2', fill_holes=True),
82+
name='dil_mask')
8883

8984
# truncate target intensity for N4 correction
9085
trunc_opts = {"T1w": "0.005 0.999 256", "T2w": "0.01 0.999 256"}
9186
trunc = pe.MapNode(ImageMath(operation='TruncateImageIntensity', op2=trunc_opts[bids_suffix]),
92-
name='truncate_images', iterfield=['op1'])
87+
name='truncate_images', iterfield=['op1'])
9388

9489
# Initial N4 correction
9590
inu_n4 = pe.MapNode(
@@ -104,7 +99,7 @@ def init_rodent_brain_extraction_wf(
10499
if tpl_target_path:
105100
lap_tmpl.inputs.op1 = tpl_target_path
106101
lap_target = pe.Node(ImageMath(operation='Laplacian', op2='0.4'), name='lap_target')
107-
102+
108103
norm_lap_tmpl = pe.Node(ImageMath(operation='Normalize'), name='norm_lap_tmpl')
109104
norm_lap_target = pe.Node(ImageMath(operation='Normalize'), name='norm_lap_target')
110105

@@ -129,9 +124,6 @@ def init_rodent_brain_extraction_wf(
129124
warp_mask = pe.Node(ApplyTransforms(
130125
interpolation='Linear', invert_transform_flags=True), name='warp_mask')
131126

132-
fixed_mask_trait = 'fixed_image_masks'
133-
moving_mask_trait = 'moving_image_masks'
134-
135127
# Set up initial spatial normalization
136128
init_settings_file = f'data/brainextraction_{init_normalization_quality}_{modality}.json'
137129
init_norm = pe.Node(Registration(from_file=pkgr_fn(
@@ -145,12 +137,12 @@ def init_rodent_brain_extraction_wf(
145137
inu_n4_final = pe.MapNode(
146138
N4BiasFieldCorrection(
147139
dimension=3, save_bias=True, copy_header=True,
148-
n_iterations=[50] * 5, convergence_threshold=1e-7,
140+
n_iterations=[50] * 5, convergence_threshold=1e-7,
149141
bspline_fitting_distance=bspline_fitting_distance,
150-
rescale_intensities = True, shrink_factor=4),
142+
rescale_intensities=True, shrink_factor=4),
151143
n_procs=omp_nthreads, name='inu_n4_final', iterfield=['input_image'])
152144

153-
split_init_transforms = pe.Node(niu.Split(splits=[1,1]), name='split_init_transforms')
145+
split_init_transforms = pe.Node(niu.Split(splits=[1, 1]), name='split_init_transforms')
154146
mrg_init_transforms = pe.Node(niu.Merge(2), name='mrg_init_transforms')
155147

156148
# Use more precise transforms to warp mask to subject space
@@ -159,10 +151,8 @@ def init_rodent_brain_extraction_wf(
159151
name='warp_mask_final')
160152

161153
# morphological closing of warped mask
162-
close_mask = pe.Node(MaskTool(), name = 'close_mask')
163-
close_mask.inputs.outputtype = 'NIFTI_GZ'
164-
close_mask.inputs.dilate_inputs = '5 -5'
165-
close_mask.inputs.fill_holes = True
154+
close_mask = pe.Node(MaskTool(outputtype='NIFTI_GZ', dilate_inputs='5 -5', fill_holes=True),
155+
name='close_mask')
166156

167157
# Use subject-space mask to skull-strip subject
168158
skullstrip_tar = pe.Node(ApplyMask(), name='skullstrip_tar')
@@ -179,7 +169,7 @@ def init_rodent_brain_extraction_wf(
179169
mem_gb=mem_gb)
180170
final_norm.inputs.float = use_float
181171

182-
split_final_transforms = pe.Node(niu.Split(splits=[1,1]), name='split_final_transforms')
172+
split_final_transforms = pe.Node(niu.Split(splits=[1, 1]), name='split_final_transforms')
183173
mrg_final_transforms = pe.Node(niu.Merge(2), name='mrg_final_transforms')
184174

185175
warp_seg_mask = pe.Node(ApplyTransforms(
@@ -188,8 +178,8 @@ def init_rodent_brain_extraction_wf(
188178
if tpl_brain_mask:
189179
warp_seg_mask.inputs.input_image = tpl_brain_mask
190180

191-
warp_seg_labels =pe.Node(ApplyTransforms(
192-
interpolation='Linear', invert_transform_flags=[False, True]),
181+
warp_seg_labels = pe.Node(ApplyTransforms(
182+
interpolation='Linear', invert_transform_flags=[False, True]),
193183
name='warp_seg_labels')
194184
if tpl_tissue_labels:
195185
warp_seg_labels.inputs.input_image = tpl_tissue_labels
@@ -287,7 +277,7 @@ def init_rodent_brain_extraction_wf(
287277
(inputnode, res_target, [('in_files', 'in_file')]),
288278
(inputnode, lap_target, [('in_files', 'op1')]),
289279
(lap_target, norm_lap_target, [('output_image', 'op1')]),
290-
(norm_lap_target, mrg_target, [('output_image', 'in2')]),
280+
(norm_lap_target, mrg_target, [('output_image', 'in2')]),
291281
(res_target, mrg_target, [('out_file', 'in1')]),
292282

293283
(res_tmpl, mrg_tmpl, [('out_file', 'in1')]),
@@ -309,7 +299,7 @@ def init_rodent_brain_extraction_wf(
309299

310300
# normalisation inputs
311301
(mrg_tmpl, init_norm, [('out', 'fixed_image')]),
312-
(mrg_target, init_norm, [('out', 'moving_image')]),
302+
(mrg_target, init_norm, [('out', 'moving_image')]),
313303
(dil_mask, init_norm, [('out_file', 'fixed_image_masks')]),
314304
(warp_mask, init_norm, [('output_image', 'moving_image_masks')]),
315305
(init_aff, init_norm, [('output_transform', 'initial_moving_transform')]),
@@ -347,26 +337,10 @@ def init_rodent_brain_extraction_wf(
347337
(skullstrip_tar, segment, [('out_file', 'intensity_images')]),
348338
(warp_seg_labels, segment, [('output_image', 'prior_image')]),
349339
(warp_seg_mask, segment, [('output_image', 'mask_image')]),
350-
])
340+
])
351341
return wf
352342

353343
def _pop(in_files):
354344
if isinstance(in_files, (list, tuple)):
355345
return in_files[0]
356346
return in_files
357-
358-
def res_by_spc(in_file, out_file = None):
359-
import os.path as op
360-
from niworkflows.utils.images import resample_by_spacing
361-
import nibabel as nib
362-
resampled = resample_by_spacing(in_file, (0.4, 0.4, 0.4), clip = False)
363-
364-
if out_file is None:
365-
fname, ext = op.splitext(op.basename(in_file))
366-
if ext == '.gz':
367-
fname, ext2 = op.splitext(fname)
368-
ext = ext2 + ext
369-
out_file = op.abspath('{}_resampled{}'.format(fname, ext))
370-
371-
nib.save(resampled, out_file)
372-
return out_file

setup.cfg

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@ install_requires =
2323
attrs
2424
nibabel >= 3.0.1
2525
nipype @ git+https://github.com/nipy/nipype.git@master
26-
niworkflows @ git+https://github.com/nipreps/niworkflows.git@master
27-
templateflow >= 0.5.2
26+
niworkflows @ git+https://github.com/oesteban/niworkflows.git@6d2286268d09215045161e534d0bf84dc34f38fc
27+
templateflow ~= 0.6
2828
test_requires =
2929
coverage < 5
3030
pytest >= 4.4
3131
pytest-cov
3232
pytest-xdist >= 1.28
3333
packages = find:
34-
include_package_data = True
3534

3635
[options.entry_points]
3736
console_scripts =
@@ -59,8 +58,6 @@ docs =
5958
%(doc)s
6059
duecredit =
6160
duecredit
62-
pointclouds =
63-
pyntcloud
6461
style =
6562
flake8 >= 3.7.0
6663
test =
@@ -73,7 +70,6 @@ tests =
7370
all =
7471
%(doc)s
7572
%(duecredit)s
76-
%(pointclouds)s
7773
%(style)s
7874
%(test)s
7975

0 commit comments

Comments
 (0)