Skip to content

Commit ced8260

Browse files
committed
Merge branch 'master' into fix/ants_resampling
2 parents 7304913 + 4bbd583 commit ced8260

File tree

11 files changed

+171
-25
lines changed

11 files changed

+171
-25
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Next Release
22
============
33

4+
* ENH: New Freesurfer interface: Tkregister2 (for conversion of fsl style matrices to freesurfer format)
45
* ENH: New FSL interfaces: WarpPoints, WarpPointsToStd.
56
* ENH: New Freesurfer interface: MRIPretess
67
* ENH: New miscelaneous interface: AddCSVRow

nipype/interfaces/ants/segmentation.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,12 @@ class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec):
226226
usedefault=True,
227227
desc='image dimension (2 or 3)')
228228
input_image = File(argstr='--input-image %s', mandatory=True,
229-
desc=('image to apply transformation to (generally a '
230-
'coregistered functional)'))
229+
desc=('image to apply transformation to (generally a '
230+
'coregistered functional)'))
231231
mask_image = File(argstr='--mask-image %s')
232232
output_image = traits.Str(argstr='--output %s',
233-
desc=('output file name'), genfile=True,
234-
hash_files=False)
233+
desc=('output file name'), genfile=True,
234+
hash_files=False)
235235
bspline_fitting_distance = traits.Float(argstr="--bsline-fitting [%g]")
236236
shrink_factor = traits.Int(argstr="--shrink-factor %d")
237237
n_iterations = traits.List(traits.Int(), argstr="--convergence [ %s",
@@ -240,10 +240,16 @@ class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec):
240240
convergence_threshold = traits.Float(argstr=",%g]",
241241
requires=['n_iterations'],
242242
position=2)
243+
save_bias = traits.Bool(False, mandatory=True, usedefault=True,
244+
desc=('True if the estimated bias should be saved'
245+
' to file.'), xor=['bias_image'])
246+
bias_image = File(desc=('Filename for the estimated bias.'),
247+
hash_files=False)
243248

244249

245250
class N4BiasFieldCorrectionOutputSpec(TraitedSpec):
246251
output_image = File(exists=True, desc='Warped image')
252+
bias_image = File(exists=True, desc='Estimated bias')
247253

248254

249255
class N4BiasFieldCorrection(ANTSCommand):
@@ -254,9 +260,11 @@ class N4BiasFieldCorrection(ANTSCommand):
254260
iterate between deconvolving the intensity histogram by a Gaussian, remapping
255261
the intensities, and then spatially smoothing this result by a B-spline modeling
256262
of the bias field itself. The modifications from and improvements obtained over
257-
the original N3 algorithm are described in the following paper: N. Tustison et
258-
al., N4ITK: Improved N3 Bias Correction, IEEE Transactions on Medical Imaging,
259-
29(6):1310-1320, June 2010.
263+
the original N3 algorithm are described in [Tustison2010]_.
264+
265+
.. [Tustison2010] N. Tustison et al.,
266+
N4ITK: Improved N3 Bias Correction, IEEE Transactions on Medical Imaging,
267+
29(6):1310-1320, June 2010.
260268
261269
Examples
262270
--------
@@ -270,7 +278,16 @@ class N4BiasFieldCorrection(ANTSCommand):
270278
>>> n4.inputs.n_iterations = [50,50,30,20]
271279
>>> n4.inputs.convergence_threshold = 1e-6
272280
>>> n4.cmdline
273-
'N4BiasFieldCorrection --convergence [ 50x50x30x20 ,1e-06] --bsline-fitting [300] --image-dimension 3 --input-image structural.nii --output structural_corrected.nii --shrink-factor 3'
281+
'N4BiasFieldCorrection --convergence [ 50x50x30x20 ,1e-06] \
282+
--bsline-fitting [300] --image-dimension 3 --input-image structural.nii \
283+
--output structural_corrected.nii --shrink-factor 3'
284+
285+
>>> n4_2 = N4BiasFieldCorrection()
286+
>>> n4_2.inputs.input_image = 'structural.nii'
287+
>>> n4_2.inputs.save_bias = True
288+
>>> n4_2.cmdline
289+
'N4BiasFieldCorrection --image-dimension 3 --input-image structural.nii \
290+
--output [structural_corrected.nii,structural_bias.nii]'
274291
"""
275292

276293
_cmd = 'N4BiasFieldCorrection'
@@ -284,9 +301,36 @@ def _gen_filename(self, name):
284301
_, name, ext = split_filename(self.inputs.input_image)
285302
output = name + '_corrected' + ext
286303
return output
304+
305+
if name == 'bias_image':
306+
output = self.inputs.bias_image
307+
if not isdefined(output):
308+
_, name, ext = split_filename(self.inputs.input_image)
309+
output = name + '_bias' + ext
310+
return output
287311
return None
288312

313+
def _format_arg(self, name, trait_spec, value):
314+
if ((name == 'output_image') and
315+
(self.inputs.save_bias or isdefined(self.inputs.bias_image))):
316+
bias_image = self._gen_filename('bias_image')
317+
output = self._gen_filename('output_image')
318+
newval = '[%s,%s]' % (output, bias_image)
319+
return trait_spec.argstr % newval
320+
321+
return super(N4BiasFieldCorrection,
322+
self)._format_arg(name, trait_spec, value)
323+
324+
def _parse_inputs(self, skip=None):
325+
if skip is None:
326+
skip = []
327+
skip += ['save_bias', 'bias_image']
328+
return super(N4BiasFieldCorrection, self)._parse_inputs(skip=skip)
329+
289330
def _list_outputs(self):
290331
outputs = self._outputs().get()
291332
outputs['output_image'] = os.path.abspath(self._gen_filename('output_image'))
333+
334+
if self.inputs.save_bias or isdefined(self.inputs.bias_image):
335+
outputs['bias_image'] = os.path.abspath(self._gen_filename('bias_image'))
292336
return outputs

nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
def test_N4BiasFieldCorrection_inputs():
66
input_map = dict(args=dict(argstr='%s',
77
),
8+
bias_image=dict(hash_files=False,
9+
),
810
bspline_fitting_distance=dict(argstr='--bsline-fitting [%g]',
911
),
1012
convergence_threshold=dict(argstr=',%g]',
@@ -37,6 +39,10 @@ def test_N4BiasFieldCorrection_inputs():
3739
genfile=True,
3840
hash_files=False,
3941
),
42+
save_bias=dict(mandatory=True,
43+
usedefault=True,
44+
xor=['bias_image'],
45+
),
4046
shrink_factor=dict(argstr='--shrink-factor %d',
4147
),
4248
terminal_output=dict(mandatory=True,
@@ -50,7 +56,8 @@ def test_N4BiasFieldCorrection_inputs():
5056
yield assert_equal, getattr(inputs.traits()[key], metakey), value
5157

5258
def test_N4BiasFieldCorrection_outputs():
53-
output_map = dict(output_image=dict(),
59+
output_map = dict(bias_image=dict(),
60+
output_image=dict(),
5461
)
5562
outputs = N4BiasFieldCorrection.output_spec()
5663

nipype/interfaces/freesurfer/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
from .utils import (SampleToSurface, SurfaceSmooth, SurfaceTransform, Surface2VolTransform,
1313
SurfaceSnapshots,ApplyMask, MRIsConvert, MRITessellate, MRIPretess,
1414
MRIMarchingCubes, SmoothTessellation, MakeAverageSubject,
15-
ExtractMainComponent)
15+
ExtractMainComponent, Tkregister2)

nipype/interfaces/freesurfer/preprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ class BBRegisterInputSpec(FSTraitedSpec):
807807
init = traits.Enum('spm', 'fsl', 'header', argstr='--init-%s',
808808
mandatory=True, xor=['init_reg_file'],
809809
desc='initialize registration spm, fsl, header')
810-
init_reg_file = File(exists=True,
810+
init_reg_file = File(exists=True, argstr='--init-reg %s',
811811
desc='existing registration file',
812812
xor=['init'], mandatory=True)
813813
contrast_type = traits.Enum('t1', 't2', argstr='--%s',

nipype/interfaces/freesurfer/tests/test_auto_BBRegister.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def test_BBRegister_inputs():
2020
mandatory=True,
2121
xor=['init_reg_file'],
2222
),
23-
init_reg_file=dict(mandatory=True,
23+
init_reg_file=dict(argstr='--init-reg %s',
24+
mandatory=True,
2425
xor=['init'],
2526
),
2627
intermediate_file=dict(argstr='--int %s',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from nipype.testing import assert_equal
3+
from nipype.interfaces.freesurfer.utils import Tkregister2
4+
5+
def test_Tkregister2_inputs():
6+
input_map = dict(args=dict(argstr='%s',
7+
),
8+
environ=dict(nohash=True,
9+
usedefault=True,
10+
),
11+
fsl_in_matrix=dict(argstr='--fsl %s',
12+
),
13+
ignore_exception=dict(nohash=True,
14+
usedefault=True,
15+
),
16+
moving_image=dict(argstr='--mov %s',
17+
mandatory=True,
18+
),
19+
noedit=dict(argstr='--noedit',
20+
usedefault=True,
21+
),
22+
reg_file=dict(argstr='--reg %s',
23+
mandatory=True,
24+
name_source='fsl',
25+
name_template='%s.dat',
26+
),
27+
subject_id=dict(argstr='--s %s',
28+
mandatory=True,
29+
),
30+
subjects_dir=dict(),
31+
terminal_output=dict(mandatory=True,
32+
nohash=True,
33+
),
34+
)
35+
inputs = Tkregister2.input_spec()
36+
37+
for key, metadata in input_map.items():
38+
for metakey, value in metadata.items():
39+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
40+
41+
def test_Tkregister2_outputs():
42+
output_map = dict(reg_file=dict(),
43+
)
44+
outputs = Tkregister2.output_spec()
45+
46+
for key, metadata in output_map.items():
47+
for metakey, value in metadata.items():
48+
yield assert_equal, getattr(outputs.traits()[key], metakey), value
49+

nipype/interfaces/freesurfer/utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,3 +1188,42 @@ class ExtractMainComponent(CommandLine):
11881188
_cmd='mris_extract_main_component'
11891189
input_spec=ExtractMainComponentInputSpec
11901190
output_spec=ExtractMainComponentOutputSpec
1191+
1192+
1193+
class Tkregister2InputSpec(FSTraitedSpec):
1194+
moving_image = File(exists=True, mandatory=True, argstr="--mov %s",
1195+
desc='moving volume')
1196+
fsl_in_matrix = File(exists=True, argstr="--fsl %s",
1197+
desc='fsl-style registration input matrix')
1198+
subject_id = traits.String(argstr="--s %s", mandatory=True,
1199+
desc='freesurfer subject ID')
1200+
noedit = traits.Bool(True, argstr="--noedit", desc='do not open edit window (exit)', usedefault=True)
1201+
reg_file = File(name_template='%s.dat', name_source='fsl',
1202+
mandatory=True, argstr="--reg %s",
1203+
desc='freesurfer-style registration file')
1204+
1205+
1206+
class Tkregister2OutputSpec(TraitedSpec):
1207+
reg_file = File(exists=True, desc='freesurfer-style registration file')
1208+
1209+
1210+
class Tkregister2(FSCommand):
1211+
"""Use tkregister2 without the manual editing stage to convert
1212+
FSL-style registration matrix (.mat) to FreeSurfer-style registration matrix (.dat)
1213+
1214+
Examples
1215+
--------
1216+
1217+
>>> from nipype.interfaces.freesurfer import Tkregister2
1218+
>>> tk2 = Tkregister2(reg_file='register.dat')
1219+
>>> tk2.inputs.moving_image = 'epi.nii'
1220+
>>> tk2.inputs.fsl_in_matrix = 'flirt.mat'
1221+
>>> tk2.inputs.subject_id = 'test_subject'
1222+
>>> tk2.run() # doctest: +SKIP
1223+
"""
1224+
_cmd = "tkregister2"
1225+
input_spec = Tkregister2InputSpec
1226+
output_spec = Tkregister2OutputSpec
1227+
1228+
1229+

nipype/interfaces/fsl/preprocess.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -941,18 +941,18 @@ def write_config(self, configfile):
941941

942942
class ApplyWarpInputSpec(FSLCommandInputSpec):
943943
in_file = File(exists=True, argstr='--in=%s',
944-
mandatory=True,
944+
mandatory=True, position=0,
945945
desc='image to be warped')
946-
out_file = File(argstr='--out=%s', genfile=True,
946+
out_file = File(argstr='--out=%s', genfile=True, position=2,
947947
desc='output filename', hash_files=False)
948948
ref_file = File(exists=True, argstr='--ref=%s',
949-
mandatory=True,
949+
mandatory=True, position=1,
950950
desc='reference image')
951951
field_file = File(exists=True, argstr='--warp=%s',
952952
desc='file containing warp field')
953953
abswarp = traits.Bool(argstr='--abs', xor=['relwarp'],
954954
desc="treat warp field as absolute: x' = w(x)")
955-
relwarp = traits.Bool(argstr='--rel', xor=['abswarp'],
955+
relwarp = traits.Bool(argstr='--rel', xor=['abswarp'], position=-1,
956956
desc="treat warp field as relative: x' = x + w(x)")
957957
datatype = traits.Enum('char', 'short', 'int', 'float', 'double',
958958
argstr='--datatype=%s',
@@ -969,7 +969,7 @@ class ApplyWarpInputSpec(FSLCommandInputSpec):
969969
mask_file = File(exists=True, argstr='--mask=%s',
970970
desc='filename for mask image (in reference space)')
971971
interp = traits.Enum(
972-
'nn', 'trilinear', 'sinc', 'spline', argstr='--interp=%s',
972+
'nn', 'trilinear', 'sinc', 'spline', argstr='--interp=%s', position=-2,
973973
desc='interpolation method')
974974

975975

nipype/interfaces/fsl/tests/test_auto_ApplyWarp.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@ def test_ApplyWarp_inputs():
2020
),
2121
in_file=dict(argstr='--in=%s',
2222
mandatory=True,
23+
position=0,
2324
),
2425
interp=dict(argstr='--interp=%s',
26+
position=-2,
2527
),
2628
mask_file=dict(argstr='--mask=%s',
2729
),
2830
out_file=dict(argstr='--out=%s',
2931
genfile=True,
3032
hash_files=False,
33+
position=2,
3134
),
3235
output_type=dict(),
3336
postmat=dict(argstr='--postmat=%s',
@@ -36,8 +39,10 @@ def test_ApplyWarp_inputs():
3639
),
3740
ref_file=dict(argstr='--ref=%s',
3841
mandatory=True,
42+
position=1,
3943
),
4044
relwarp=dict(argstr='--rel',
45+
position=-1,
4146
xor=['abswarp'],
4247
),
4348
superlevel=dict(argstr='--superlevel=%s',

0 commit comments

Comments
 (0)