Skip to content

Commit 893d600

Browse files
committed
Merge pull request #1004 from BRAINSia/20141101NewAntsInterface
ENH: Adding new ants command line feature.
2 parents afae53c + 0513cef commit 893d600

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

nipype/interfaces/ants/registration.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,17 @@ class RegistrationInputSpec(ANTSCommandInputSpec):
200200
fixed_image = InputMultiPath(File(exists=True), mandatory=True,
201201
desc='image to apply transformation to (generally a coregistered functional)')
202202
fixed_image_mask = File(argstr='%s', exists=True,
203-
desc='mask used to limit registration region')
203+
desc='mask used to limit metric sampling region of the fixed image')
204204
moving_image = InputMultiPath(File(exists=True), mandatory=True,
205205
desc='image to apply transformation to (generally a coregistered functional)')
206206
moving_image_mask = File(requires=['fixed_image_mask'],
207-
exists=True, desc='')
207+
exists=True, desc='mask used to limit metric sampling region of the moving image')
208+
209+
save_state = File(argstr='--save-state %s', exists=False,
210+
desc='Filename for saving the internal restorable state of the registration')
211+
restore_state = File(argstr='--restore-state %s', exists=True,
212+
desc='Filename for restoring the internal restorable state of the registration')
213+
208214
initial_moving_transform = File(argstr='%s', exists=True, desc='',
209215
xor=['initial_moving_transform_com'])
210216
invert_initial_moving_transform = traits.Bool(
@@ -276,6 +282,15 @@ class RegistrationInputSpec(ANTSCommandInputSpec):
276282
'combines all adjacent linear transforms and composes all '
277283
'adjacent displacement field transforms before writing the '
278284
'results to disk.'))
285+
initialize_transforms_per_stage = traits.Bool(
286+
argstr='--initialize-transforms-per-stage %d', default=False,
287+
usedefault=True, # This should be true for explicit completeness
288+
desc=('Initialize linear transforms from the previous stage. By enabling this option, '
289+
'the current linear stage transform is directly intialized from the previous '
290+
'stages linear transform; this allows multiple linear stages to be run where '
291+
'each stage directly updates the estimated linear transform from the previous '
292+
'stage. (e.g. Translation -> Rigid -> Affine). '
293+
))
279294

280295
transforms = traits.List(traits.Enum('Rigid', 'Affine', 'CompositeAffine',
281296
'Similarity', 'Translation', 'BSpline',
@@ -337,7 +352,7 @@ class RegistrationOutputSpec(TraitedSpec):
337352
File(exists=True), desc='Inverse composite transform file')
338353
warped_image = File(desc="Outputs warped image")
339354
inverse_warped_image = File(desc="Outputs the inverse of the warped image")
340-
355+
save_state = File(desc="The saved registration state to be restored")
341356

342357
class Registration(ANTSCommand):
343358

@@ -358,6 +373,7 @@ class Registration(ANTSCommand):
358373
>>> reg.inputs.dimension = 3
359374
>>> reg.inputs.write_composite_transform = True
360375
>>> reg.inputs.collapse_output_transforms = False
376+
>>> reg.inputs.initialize_transforms_per_stage = False
361377
>>> reg.inputs.metric = ['Mattes']*2
362378
>>> reg.inputs.metric_weight = [1]*2 # Default (value ignored currently by ANTs)
363379
>>> reg.inputs.radius_or_number_of_bins = [32]*2
@@ -375,33 +391,36 @@ class Registration(ANTSCommand):
375391
>>> reg1 = copy.deepcopy(reg)
376392
>>> reg1.inputs.winsorize_lower_quantile = 0.025
377393
>>> reg1.cmdline
378-
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 1.0 ] --write-composite-transform 1'
394+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 1.0 ] --write-composite-transform 1'
379395
>>> reg1.run() #doctest: +SKIP
380396
381397
>>> reg2 = copy.deepcopy(reg)
382398
>>> reg2.inputs.winsorize_upper_quantile = 0.975
383399
>>> reg2.cmdline
384-
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 0.975 ] --write-composite-transform 1'
400+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 0.975 ] --write-composite-transform 1'
385401
386402
>>> reg3 = copy.deepcopy(reg)
387403
>>> reg3.inputs.winsorize_lower_quantile = 0.025
388404
>>> reg3.inputs.winsorize_upper_quantile = 0.975
389405
>>> reg3.cmdline
390-
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 0.975 ] --write-composite-transform 1'
406+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes[ fixed1.nii, moving1.nii, 1, 32 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 0.975 ] --write-composite-transform 1'
391407
392408
>>> # Test collapse transforms flag
393409
>>> reg4 = copy.deepcopy(reg)
410+
>>> reg.inputs.save_state = 'trans.mat'
411+
>>> reg.inputs.restore_state = 'trans.mat'
412+
>>> reg4.inputs.initialize_transforms_per_stage = True
394413
>>> reg4.inputs.collapse_output_transforms = True
395414
>>> outputs = reg4._list_outputs()
396415
>>> print outputs #doctest: +ELLIPSIS
397-
{'reverse_invert_flags': [], 'inverse_composite_transform': ['.../nipype/testing/data/output_InverseComposite.h5'], 'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz', 'inverse_warped_image': <undefined>, 'forward_invert_flags': [], 'reverse_transforms': [], 'composite_transform': ['.../nipype/testing/data/output_Composite.h5'], 'forward_transforms': []}
416+
{'reverse_invert_flags': [], 'inverse_composite_transform': ['.../nipype/testing/data/output_InverseComposite.h5'], 'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz', 'inverse_warped_image': <undefined>, 'forward_invert_flags': [], 'reverse_transforms': [], 'save_state': <undefined>, 'composite_transform': ['.../nipype/testing/data/output_Composite.h5'], 'forward_transforms': []}
398417
399418
>>> # Test collapse transforms flag
400419
>>> reg4b = copy.deepcopy(reg4)
401420
>>> reg4b.inputs.write_composite_transform = False
402421
>>> outputs = reg4b._list_outputs()
403422
>>> print outputs #doctest: +ELLIPSIS
404-
{'reverse_invert_flags': [True, False], 'inverse_composite_transform': <undefined>, 'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz', 'inverse_warped_image': <undefined>, 'forward_invert_flags': [False, False], 'reverse_transforms': ['.../nipype/testing/data/output_0GenericAffine.mat', '.../nipype/testing/data/output_1InverseWarp.nii.gz'], 'composite_transform': <undefined>, 'forward_transforms': ['.../nipype/testing/data/output_0GenericAffine.mat', '.../nipype/testing/data/output_1Warp.nii.gz']}
423+
{'reverse_invert_flags': [True, False], 'inverse_composite_transform': <undefined>, 'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz', 'inverse_warped_image': <undefined>, 'forward_invert_flags': [False, False], 'reverse_transforms': ['.../nipype/testing/data/output_0GenericAffine.mat', '.../nipype/testing/data/output_1InverseWarp.nii.gz'], 'save_state': <undefined>, 'composite_transform': <undefined>, 'forward_transforms': ['.../nipype/testing/data/output_0GenericAffine.mat', '.../nipype/testing/data/output_1Warp.nii.gz']}
405424
>>> reg4b.aggregate_outputs() #doctest: +SKIP
406425
407426
>>> # Test multiple metrics per stage
@@ -412,7 +431,7 @@ class Registration(ANTSCommand):
412431
>>> reg5.inputs.sampling_strategy = ['Random', None] # use default strategy in second stage
413432
>>> reg5.inputs.sampling_percentage = [0.05, [0.05, 0.10]]
414433
>>> reg5.cmdline
415-
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --transform Affine[ 2.0 ] --metric CC[ fixed1.nii, moving1.nii, 1, 4, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric CC[ fixed1.nii, moving1.nii, 0.5, 32, None, 0.05 ] --metric Mattes[ fixed1.nii, moving1.nii, 0.5, 32, None, 0.1 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
434+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --restore-state trans.mat --save-state trans.mat --transform Affine[ 2.0 ] --metric CC[ fixed1.nii, moving1.nii, 1, 4, Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric CC[ fixed1.nii, moving1.nii, 0.5, 32, None, 0.05 ] --metric Mattes[ fixed1.nii, moving1.nii, 0.5, 32, None, 0.1 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
416435
"""
417436
DEF_SAMPLING_STRATEGY = 'None'
418437
"""The default sampling strategy argument."""
@@ -581,13 +600,6 @@ def _formatWinsorizeImageIntensities(self):
581600
self._quantilesDone = True
582601
return '--winsorize-image-intensities [ %s, %s ]' % (self.inputs.winsorize_lower_quantile, self.inputs.winsorize_upper_quantile)
583602

584-
def _formatCollapseLinearTransformsToFixedImageHeader(self):
585-
if self.inputs.collapse_linear_transforms_to_fixed_image_header:
586-
# return '--collapse-linear-transforms-to-fixed-image-header 1'
587-
return ''
588-
else:
589-
# return '--collapse-linear-transforms-to-fixed-image-header 0'
590-
return ''
591603

592604
def _format_arg(self, opt, spec, val):
593605
if opt == 'fixed_image_mask':
@@ -636,7 +648,7 @@ def _format_arg(self, opt, spec, val):
636648
return self._formatWinsorizeImageIntensities()
637649
return '' # Must return something for argstr!
638650
elif opt == 'collapse_linear_transforms_to_fixed_image_header':
639-
return self._formatCollapseLinearTransformsToFixedImageHeader()
651+
return '' # Command no longer exist, so return empty string for backwards compatibility
640652
return super(Registration, self)._format_arg(opt, spec, val)
641653

642654
def _outputFileNames(self, prefix, count, transform, inverse=False):
@@ -763,4 +775,6 @@ def _list_outputs(self):
763775
outputs['warped_image'] = os.path.abspath(out_filename)
764776
if inv_out_filename:
765777
outputs['inverse_warped_image'] = os.path.abspath(inv_out_filename)
778+
if len(self.inputs.save_state):
779+
outputs['save_state'] = os.path.abspath(self.inputs.save_state)
766780
return outputs

nipype/interfaces/ants/tests/test_auto_Registration.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def test_Registration_inputs():
3333
initial_moving_transform_com=dict(argstr='%s',
3434
xor=['initial_moving_transform'],
3535
),
36+
initialize_transforms_per_stage=dict(argstr='--initialize-transforms-per-stage %d',
37+
usedefault=True,
38+
),
3639
interpolation=dict(argstr='%s',
3740
usedefault=True,
3841
),
@@ -70,6 +73,8 @@ def test_Registration_inputs():
7073
radius_or_number_of_bins=dict(requires=['metric_weight'],
7174
usedefault=True,
7275
),
76+
restore_state=dict(argstr='--restore-state %s',
77+
),
7378
sampling_percentage=dict(requires=['sampling_strategy'],
7479
),
7580
sampling_percentage_item_trait=dict(),
@@ -78,6 +83,8 @@ def test_Registration_inputs():
7883
),
7984
sampling_strategy_item_trait=dict(),
8085
sampling_strategy_stage_trait=dict(),
86+
save_state=dict(argstr='--save-state %s',
87+
),
8188
shrink_factors=dict(mandatory=True,
8289
),
8390
sigma_units=dict(requires=['smoothing_sigmas'],
@@ -117,6 +124,7 @@ def test_Registration_outputs():
117124
inverse_warped_image=dict(),
118125
reverse_invert_flags=dict(),
119126
reverse_transforms=dict(),
127+
save_state=dict(),
120128
warped_image=dict(),
121129
)
122130
outputs = Registration.output_spec()

0 commit comments

Comments
 (0)