Skip to content

Commit e6760fc

Browse files
committed
removed redundant code in registrations
1 parent 3874713 commit e6760fc

File tree

2 files changed

+171
-81
lines changed

2 files changed

+171
-81
lines changed

nipype/workflows/dmri/preprocess/epi.py

Lines changed: 46 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ def all_fmb_pipeline(name='hmc_sdc_ecc',
5353
wf = pe.Workflow('dMRI_Artifacts')
5454
wf.connect([
5555
(inputnode, hmc, [('in_file', 'inputnode.in_file'),
56-
('in_bvec', 'inputnode.in_bvec')])
56+
('in_bvec', 'inputnode.in_bvec'),
57+
('in_bval', 'inputnode.in_bval')])
5758
,(inputnode, avg_b0_0, [('in_file', 'in_dwi'),
5859
('in_bval', 'in_bval')])
5960
,(avg_b0_0, bet_dwi0, [('out_file', 'in_file')])
@@ -120,7 +121,8 @@ def all_peb_pipeline(name='hmc_sdc_ecc',
120121
wf = pe.Workflow('dMRI_Artifacts')
121122
wf.connect([
122123
(inputnode, hmc, [('in_file', 'inputnode.in_file'),
123-
('in_bvec', 'inputnode.in_bvec')])
124+
('in_bvec', 'inputnode.in_bvec'),
125+
('in_bval', 'inputnode.in_bval')])
124126
,(inputnode, avg_b0_0, [('in_file', 'in_dwi'),
125127
('in_bval', 'in_bval')])
126128
,(avg_b0_0, bet_dwi0, [('out_file','in_file')])
@@ -257,6 +259,7 @@ def hmc_pipeline(name='motion_correct'):
257259
>>> hmc = hmc_pipeline()
258260
>>> hmc.inputs.inputnode.in_file = 'diffusion.nii'
259261
>>> hmc.inputs.inputnode.in_bvec = 'diffusion.bvec'
262+
>>> hmc.inputs.inputnode.in_bval = 'diffusion.bval'
260263
>>> hmc.inputs.inputnode.in_mask = 'mask.nii'
261264
>>> hmc.run() # doctest: +SKIP
262265
@@ -276,48 +279,35 @@ def hmc_pipeline(name='motion_correct'):
276279
outputnode.out_xfms - list of transformation matrices
277280
278281
"""
282+
params = dict(interp='spline', cost='normmi',
283+
cost_func='normmi', dof=6, bins=64, save_log=True,
284+
searchr_x=[-4, 4], searchr_y=[-4, 4], searchr_z=[-4, 4],
285+
fine_search=1, coarse_search=10, padding_size=1)
286+
279287
inputnode = pe.Node(niu.IdentityInterface(fields=['in_file', 'ref_num',
280-
'in_bvec', 'in_mask']), name='inputnode')
281-
split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
282-
pick_ref = pe.Node(niu.Select(), name='Pick_b0')
283-
enhb0 = pe.Node(niu.Function(input_names=['in_file'],
284-
output_names=['out_file'], function=enhance),
285-
name='B0Equalize')
286-
enhdw = pe.MapNode(niu.Function(input_names=['in_file'],
287-
output_names=['out_file'], function=enhance),
288-
name='DWEqualize', iterfield=['in_file'])
289-
flirt = pe.MapNode(fsl.FLIRT(interp='spline', cost='normmi',
290-
cost_func='normmi', dof=6, bins=64, save_log=True,
291-
searchr_x=[-4, 4], searchr_y=[-4, 4], searchr_z=[-4, 4],
292-
fine_search=1, coarse_search=10, padding_size=1),
293-
name='CoRegistration', iterfield=['in_file'])
288+
'in_bvec', 'in_bval', 'in_mask']), name='inputnode')
289+
pick_ref = pe.Node(fsl.ExtractROI(t_size=1), name='GetB0')
290+
flirt = dwi_flirt(flirt_param=params)
294291
rot_bvec = pe.Node(niu.Function(input_names=['in_bvec', 'in_matrix'],
295292
output_names=['out_file'], function=rotate_bvecs),
296293
name='Rotate_Bvec')
297-
thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
298-
name='RemoveNegative')
299-
merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')
300294
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file',
301295
'out_bvec', 'out_xfms']),
302296
name='outputnode')
303297

304298
wf = pe.Workflow(name=name)
305299
wf.connect([
306-
(inputnode, split, [('in_file', 'in_file')])
307-
,(split, pick_ref, [('out_files', 'inlist')])
308-
,(inputnode, pick_ref, [(('ref_num', _checkrnum), 'index')])
309-
,(inputnode, flirt, [('in_mask', 'ref_weight')])
310-
,(pick_ref, enhb0, [('out', 'in_file')])
311-
,(split, enhdw, [('out_files', 'in_file')])
312-
,(enhb0, flirt, [('out_file', 'reference')])
313-
,(enhdw, flirt, [('out_file', 'in_file')])
300+
(inputnode, pick_ref, [('in_file', 'in_file'),
301+
(('ref_num', _checkrnum), 't_min')])
302+
,(inputnode, flirt, [('in_file', 'inputnode.in_file'),
303+
('in_mask', 'inputnode.ref_mask'),
304+
('in_bval', 'inputnode.in_bval')])
305+
,(pick_ref, flirt, [('roi_file', 'inputnode.reference')])
314306
,(inputnode, rot_bvec, [('in_bvec', 'in_bvec')])
315-
,(flirt, rot_bvec, [('out_matrix_file', 'in_matrix')])
316-
,(flirt, thres, [('out_file', 'in_file')])
317-
,(thres, merge, [('out_file', 'in_files')])
318-
,(merge, outputnode, [('merged_file', 'out_file')])
307+
,(flirt, rot_bvec, [('outputnode.out_xfms', 'in_matrix')])
319308
,(rot_bvec, outputnode, [('out_file', 'out_bvec')])
320-
,(flirt, outputnode, [('out_matrix_file', 'out_xfms')])
309+
,(flirt, outputnode, [('outputnode.out_xfms', 'out_xfms'),
310+
('outputnode.out_file', 'out_file')])
321311
])
322312
return wf
323313

@@ -376,19 +366,21 @@ def ecc_pipeline(name='eddy_correct'):
376366
outputnode.out_file - corrected dwi file
377367
outputnode.out_xfms - list of transformation matrices
378368
"""
369+
params = dict(no_search=True, interp='spline', cost='normmi',
370+
cost_func='normmi', dof=12, bins=64,
371+
padding_size=1)
372+
379373
inputnode = pe.Node(niu.IdentityInterface(fields=['in_file', 'in_bval',
380374
'in_mask', 'in_xfms']), name='inputnode')
381-
split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
382375
avg_b0 = pe.Node(niu.Function(input_names=['in_dwi', 'in_bval'],
383-
output_names=['out_file'], function=b0_average), name='b0_avg')
384-
pick_dwi = pe.Node(niu.Select(), name='Pick_DWIs')
385-
flirt = pe.MapNode(fsl.FLIRT(no_search=True, interp='spline', cost='normmi',
386-
cost_func = 'normmi', dof=12, bins=64, save_log=True,
387-
padding_size=1), name='CoRegistration',
388-
iterfield=['in_file', 'in_matrix_file'])
389-
initmat = pe.Node(niu.Function(input_names=['in_bval', 'in_xfms'],
390-
output_names=['init_xfms'], function=_checkinitxfm),
391-
name='InitXforms')
376+
output_names=['out_file'], function=b0_average),
377+
name='b0_avg')
378+
pick_dws = pe.Node(niu.Function(input_names=['in_dwi', 'in_bval', 'b'],
379+
output_names=['out_file'], function=extract_bval),
380+
name='ExtractDWI')
381+
pick_dws.inputs.b = 'diff'
382+
383+
flirt = dwi_flirt(flirt_param=params, excl_nodiff=True)
392384

393385
mult = pe.MapNode(fsl.BinaryMaths(operation='mul'), name='ModulateDWIs',
394386
iterfield=['in_file', 'operand_value'])
@@ -406,23 +398,22 @@ def ecc_pipeline(name='eddy_correct'):
406398

407399
wf = pe.Workflow(name=name)
408400
wf.connect([
409-
(inputnode, split, [('in_file', 'in_file')])
410-
,(inputnode, avg_b0, [('in_file', 'in_dwi'),
401+
(inputnode, avg_b0, [('in_file', 'in_dwi'),
411402
('in_bval', 'in_bval')])
412-
,(inputnode, merge, [('in_file', 'in_dwi'),
403+
,(inputnode, pick_dws, [('in_file', 'in_dwi'),
413404
('in_bval', 'in_bval')])
414-
,(inputnode, initmat, [('in_xfms', 'in_xfms'),
405+
,(inputnode, merge, [('in_file', 'in_dwi'),
415406
('in_bval', 'in_bval')])
407+
,(inputnode, flirt, [('in_mask', 'inputnode.ref_mask'),
408+
('in_xfms', 'inputnode.in_xfms'),
409+
('in_bval', 'inputnode.in_bval')])
416410
,(inputnode, get_mat, [('in_bval', 'in_bval')])
417-
,(split, pick_dwi, [('out_files', 'inlist')])
418-
,(inputnode, pick_dwi, [(('in_bval', _nonb0), 'index')])
419-
,(inputnode, flirt, [('in_mask', 'ref_weight')])
420-
,(avg_b0, flirt, [('out_file', 'reference')])
421-
,(pick_dwi, flirt, [('out', 'in_file')])
422-
,(initmat, flirt, [('init_xfms', 'in_matrix_file')])
423-
,(flirt, get_mat, [('out_matrix_file', 'in_xfms')])
424-
,(flirt, mult, [(('out_matrix_file',_xfm_jacobian), 'operand_value')])
425-
,(flirt, mult, [('out_file', 'in_file')])
411+
,(avg_b0, flirt, [('out_file', 'inputnode.reference')])
412+
,(pick_dws, flirt, [('out_file', 'inputnode.in_file')])
413+
,(flirt, get_mat, [('outputnode.out_xfms', 'in_xfms')])
414+
,(flirt, mult, [(('outputnode.out_xfms',_xfm_jacobian),
415+
'operand_value')])
416+
,(flirt, mult, [('outputnode.out_file', 'in_file')])
426417
,(mult, thres, [('out_file', 'in_file')])
427418
,(thres, merge, [('out_file', 'in_corrected')])
428419
,(get_mat, outputnode, [('out_files', 'out_xfms')])
@@ -710,24 +701,6 @@ def _checkrnum(ref_num):
710701
return ref_num
711702

712703

713-
def _checkinitxfm(in_bval, in_xfms=None):
714-
from nipype.interfaces.base import isdefined
715-
import numpy as np
716-
import os.path as op
717-
bvals = np.loadtxt(in_bval)
718-
non_b0 = np.where(bvals != 0)[0].tolist()
719-
720-
init_xfms = []
721-
if (in_xfms is None) or (not isdefined(in_xfms)) or (len(in_xfms)!=len(bvals)):
722-
for i in non_b0:
723-
xfm_file = op.abspath('init_%04d.mat' % i)
724-
np.savetxt(xfm_file, np.eye(4))
725-
init_xfms.append(xfm_file)
726-
else:
727-
for i in non_b0:
728-
init_xfms.append(in_xfms[i])
729-
return init_xfms
730-
731704
def _nonb0(in_bval):
732705
import numpy as np
733706
bvals = np.loadtxt(in_bval)

nipype/workflows/dmri/preprocess/utils.py

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
# @Author: oesteban
66
# @Date: 2014-08-30 10:53:13
77
# @Last Modified by: oesteban
8-
# @Last Modified time: 2014-09-03 18:03:47
8+
# @Last Modified time: 2014-09-03 20:04:13
99
import nipype.pipeline.engine as pe
1010
import nipype.interfaces.utility as niu
1111
from nipype.interfaces import fsl
12+
from nipype.interfaces import ants
1213

1314

1415
def cleanup_edge_pipeline(name='Cleanup'):
@@ -80,6 +81,59 @@ def vsm2warp(name='Shiftmap2Warping'):
8081
return wf
8182

8283

84+
def dwi_flirt(name='DWICoregistration', excl_nodiff=False,
85+
flirt_param={}):
86+
"""
87+
Generates a workflow for linear registration of dwi volumes
88+
"""
89+
inputnode = pe.Node(niu.IdentityInterface(fields=['reference',
90+
'in_file', 'ref_mask', 'in_xfms', 'in_bval']),
91+
name='inputnode')
92+
93+
initmat = pe.Node(niu.Function(input_names=['in_bval', 'in_xfms',
94+
'excl_nodiff'], output_names=['init_xfms'],
95+
function=_checkinitxfm), name='InitXforms')
96+
initmat.inputs.excl_nodiff = excl_nodiff
97+
98+
split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
99+
pick_ref = pe.Node(niu.Select(), name='Pick_b0')
100+
n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias')
101+
enhb0 = pe.Node(niu.Function(input_names=['in_file', 'in_mask',
102+
'clip_limit'], output_names=['out_file'],
103+
function=enhance), name='B0Equalize')
104+
enhb0.inputs.clip_limit = 0.02
105+
enhdw = pe.MapNode(niu.Function(input_names=['in_file'],
106+
output_names=['out_file'], function=enhance),
107+
name='DWEqualize', iterfield=['in_file'])
108+
flirt = pe.MapNode(fsl.FLIRT(**flirt_param), name='CoRegistration',
109+
iterfield=['in_file', 'in_matrix_file'])
110+
thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
111+
name='RemoveNegative')
112+
merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')
113+
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file',
114+
'out_xfms']), name='outputnode')
115+
wf = pe.Workflow(name=name)
116+
wf.connect([
117+
(inputnode, split, [('in_file', 'in_file')])
118+
,(inputnode, enhb0, [('ref_mask', 'in_mask')])
119+
,(inputnode, initmat, [('in_xfms', 'in_xfms'),
120+
('in_bval', 'in_bval')])
121+
,(inputnode, n4, [('reference', 'input_image'),
122+
('ref_mask', 'mask_image')])
123+
,(inputnode, flirt, [('ref_mask', 'ref_weight')])
124+
,(n4, enhb0, [('output_image', 'in_file')])
125+
,(split, enhdw, [('out_files', 'in_file')])
126+
,(enhb0, flirt, [('out_file', 'reference')])
127+
,(enhdw, flirt, [('out_file', 'in_file')])
128+
,(initmat, flirt, [('init_xfms', 'in_matrix_file')])
129+
,(flirt, thres, [('out_file', 'in_file')])
130+
,(thres, merge, [('out_file', 'in_files')])
131+
,(merge, outputnode, [('merged_file', 'out_file')])
132+
,(flirt, outputnode, [('out_matrix_file', 'out_xfms')])
133+
])
134+
return wf
135+
136+
83137
def apply_all_corrections(name='UnwarpArtifacts'):
84138
"""
85139
Combines two lists of linear transforms with the deformation field
@@ -142,6 +196,41 @@ def apply_all_corrections(name='UnwarpArtifacts'):
142196
return wf
143197

144198

199+
def extract_bval(in_dwi, in_bval, b=0, out_file=None):
200+
"""
201+
Writes an image containing only the volumes with b-value specified at
202+
input
203+
"""
204+
import numpy as np
205+
import nibabel as nb
206+
import os.path as op
207+
208+
if out_file is None:
209+
fname, ext = op.splitext(op.basename(in_dwi))
210+
if ext == ".gz":
211+
fname, ext2 = op.splitext(fname)
212+
ext = ext2 + ext
213+
out_file = op.abspath("%s_tsoi%s" % (fname, ext))
214+
215+
im = nb.load(in_dwi)
216+
dwidata = im.get_data()
217+
bvals = np.loadtxt(in_bval)
218+
219+
if b == 'diff':
220+
selection = np.where(bvals != 0)
221+
elif b == 'nodiff':
222+
selection = np.where(bvals == 0)
223+
else:
224+
selection = np.where(bvals == b)
225+
226+
extdata = np.squeeze(dwidata.take(selection, axis=3))
227+
hdr = im.get_header().copy()
228+
hdr.set_data_shape(extdata.shape)
229+
nb.Nifti1Image(extdata, im.get_affine(),
230+
hdr).to_filename(out_file)
231+
return out_file
232+
233+
145234
def recompose_dwi(in_dwi, in_bval, in_corrected, out_file=None):
146235
"""
147236
Recompose back the dMRI data accordingly the b-values table after EC correction
@@ -151,24 +240,25 @@ def recompose_dwi(in_dwi, in_bval, in_corrected, out_file=None):
151240
import os.path as op
152241

153242
if out_file is None:
154-
fname,ext = op.splitext(op.basename(in_dwi))
243+
fname, ext = op.splitext(op.basename(in_dwi))
155244
if ext == ".gz":
156-
fname,ext2 = op.splitext(fname)
245+
fname, ext2 = op.splitext(fname)
157246
ext = ext2 + ext
158247
out_file = op.abspath("%s_eccorrect%s" % (fname, ext))
159248

160249
im = nb.load(in_dwi)
161250
dwidata = im.get_data()
162251
bvals = np.loadtxt(in_bval)
163-
non_b0 = np.where(bvals!=0)[0].tolist()
252+
dwis = np.where(bvals != 0)[0].tolist()
164253

165-
if len(non_b0)!=len(in_corrected):
254+
if len(dwis) != len(in_corrected):
166255
raise RuntimeError('Length of DWIs in b-values table and after correction should match')
167256

168-
for bindex, dwi in zip(non_b0, in_corrected):
169-
dwidata[...,bindex] = nb.load(dwi).get_data()
257+
for bindex, dwi in zip(dwis, in_corrected):
258+
dwidata[..., bindex] = nb.load(dwi).get_data()
170259

171-
nb.Nifti1Image(dwidata, im.get_affine(), im.get_header()).to_filename(out_file)
260+
nb.Nifti1Image(dwidata, im.get_affine(),
261+
im.get_header()).to_filename(out_file)
172262
return out_file
173263

174264

@@ -519,3 +609,30 @@ def enhance(in_file, clip_limit=0.015, in_mask=None, out_file=None):
519609
im.get_header()).to_filename(out_file)
520610

521611
return out_file
612+
613+
614+
def _checkinitxfm(in_bval, excl_nodiff, in_xfms=None):
615+
from nipype.interfaces.base import isdefined
616+
import numpy as np
617+
import os.path as op
618+
bvals = np.loadtxt(in_bval)
619+
620+
gen_id = ((in_xfms is None) or
621+
(not isdefined(in_xfms)) or
622+
(len(in_xfms) != len(bvals)))
623+
624+
init_xfms = []
625+
if excl_nodiff:
626+
dws = np.where(bvals != 0)[0].tolist()
627+
else:
628+
dws = range(len(bvals))
629+
630+
if gen_id:
631+
for i in dws:
632+
xfm_file = op.abspath('init_%04d.mat' % i)
633+
np.savetxt(xfm_file, np.eye(4))
634+
init_xfms.append(xfm_file)
635+
else:
636+
init_xfms = [in_xfms[i] for i in dws]
637+
638+
return init_xfms

0 commit comments

Comments
 (0)