Skip to content

Commit 814997a

Browse files
committed
Merge pull request #1159 from BRAINSia/20150804_ANTsFloatTest
20150804 an ts float test
2 parents 4346f29 + 9acb53e commit 814997a

File tree

3 files changed

+101
-80
lines changed

3 files changed

+101
-80
lines changed

nipype/interfaces/ants/registration.py

Lines changed: 98 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@ class RegistrationInputSpec(ANTSCommandInputSpec):
291291
'each stage directly updates the estimated linear transform from the previous '
292292
'stage. (e.g. Translation -> Rigid -> Affine). '
293293
))
294+
# NOTE: Even though only 0=False and 1=True are allowed, ants uses integer
295+
# values instead of booleans
296+
float = traits.Bool(
297+
argstr='--float %d', default=False,
298+
desc=('Use float instead of double for computations.'))
294299

295300
transforms = traits.List(traits.Enum('Rigid', 'Affine', 'CompositeAffine',
296301
'Similarity', 'Translation', 'BSpline',
@@ -405,6 +410,16 @@ class Registration(ANTSCommand):
405410
>>> reg3.cmdline
406411
'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'
407412
413+
>>> reg3a = copy.deepcopy(reg)
414+
>>> reg3a.inputs.float = True
415+
>>> reg3a.cmdline
416+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --float 1 --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, 1.0 ] --write-composite-transform 1'
417+
418+
>>> reg3b = copy.deepcopy(reg)
419+
>>> reg3b.inputs.float = False
420+
>>> reg3b.cmdline
421+
'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --float 0 --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, 1.0 ] --write-composite-transform 1'
422+
408423
>>> # Test collapse transforms flag
409424
>>> reg4 = copy.deepcopy(reg)
410425
>>> reg.inputs.save_state = 'trans.mat'
@@ -647,8 +662,9 @@ def _format_arg(self, opt, spec, val):
647662
if not self._quantilesDone:
648663
return self._formatWinsorizeImageIntensities()
649664
return '' # Must return something for argstr!
650-
elif opt == 'collapse_linear_transforms_to_fixed_image_header':
651-
return '' # Command no longer exist, so return empty string for backwards compatibility
665+
# This feature was removed from recent versions of antsRegistration due to corrupt outputs.
666+
#elif opt == 'collapse_linear_transforms_to_fixed_image_header':
667+
# return self._formatCollapseLinearTransformsToFixedImageHeader()
652668
return super(Registration, self)._format_arg(opt, spec, val)
653669

654670
def _outputFileNames(self, prefix, count, transform, inverse=False):
@@ -684,91 +700,93 @@ def _list_outputs(self):
684700
if isdefined(self.inputs.invert_initial_moving_transform):
685701
invert_initial_moving_transform = self.inputs.invert_initial_moving_transform
686702

687-
if not self.inputs.collapse_output_transforms:
688-
transformCount = 0
689-
if isdefined(self.inputs.initial_moving_transform):
690-
outputs['forward_transforms'].append(
691-
self.inputs.initial_moving_transform)
692-
outputs['forward_invert_flags'].append(
693-
invert_initial_moving_transform)
694-
outputs['reverse_transforms'].insert(
695-
0, self.inputs.initial_moving_transform)
696-
outputs['reverse_invert_flags'].insert(
697-
0, not invert_initial_moving_transform) # Prepend
698-
transformCount += 1
699-
elif isdefined(self.inputs.initial_moving_transform_com):
700-
forwardFileName, forwardInverseMode = self._outputFileNames(
701-
self.inputs.output_transform_prefix,
702-
transformCount,
703-
'Initial')
704-
reverseFileName, reverseInverseMode = self._outputFileNames(
705-
self.inputs.output_transform_prefix,
706-
transformCount,
707-
'Initial',
708-
True)
709-
outputs['forward_transforms'].append(os.path.abspath(forwardFileName))
710-
outputs['forward_invert_flags'].append(False)
711-
outputs['reverse_transforms'].insert(0,
712-
os.path.abspath(reverseFileName))
713-
outputs['reverse_invert_flags'].insert(0, True)
714-
transformCount += 1
715-
716-
for count in range(len(self.inputs.transforms)):
717-
forwardFileName, forwardInverseMode = self._outputFileNames(
718-
self.inputs.output_transform_prefix, transformCount,
719-
self.inputs.transforms[count])
720-
reverseFileName, reverseInverseMode = self._outputFileNames(
721-
self.inputs.output_transform_prefix, transformCount,
722-
self.inputs.transforms[count], True)
723-
outputs['forward_transforms'].append(
724-
os.path.abspath(forwardFileName))
725-
outputs['forward_invert_flags'].append(forwardInverseMode)
726-
outputs['reverse_transforms'].insert(
727-
0, os.path.abspath(reverseFileName))
728-
outputs[
729-
'reverse_invert_flags'].insert(0, reverseInverseMode)
730-
transformCount += 1
731-
elif not self.inputs.write_composite_transform:
732-
transformCount = 0
733-
isLinear = [any(self._linear_transform_names == t)
734-
for t in self.inputs.transforms]
735-
collapse_list = []
736-
737-
if isdefined(self.inputs.initial_moving_transform) or \
738-
isdefined(self.inputs.initial_moving_transform_com):
739-
isLinear.insert(0, True)
740-
741-
# Only files returned by collapse_output_transforms
742-
if any(isLinear):
743-
collapse_list.append('GenericAffine')
744-
if not all(isLinear):
745-
collapse_list.append('SyN')
746-
747-
for transform in collapse_list:
748-
forwardFileName, forwardInverseMode = self._outputFileNames(
749-
self.inputs.output_transform_prefix,
750-
transformCount,
751-
transform,
752-
inverse=False)
753-
reverseFileName, reverseInverseMode = self._outputFileNames(
754-
self.inputs.output_transform_prefix,
755-
transformCount,
756-
transform,
757-
inverse=True)
758-
outputs['forward_transforms'].append(os.path.abspath(
759-
forwardFileName))
760-
outputs['forward_invert_flags'].append(forwardInverseMode)
761-
outputs['reverse_transforms'].append(
762-
os.path.abspath(reverseFileName))
763-
outputs['reverse_invert_flags'].append(reverseInverseMode)
764-
transformCount += 1
765703
if self.inputs.write_composite_transform:
766704
fileName = self.inputs.output_transform_prefix + 'Composite.h5'
767705
outputs['composite_transform'] = [os.path.abspath(fileName)]
768706
fileName = self.inputs.output_transform_prefix + \
769707
'InverseComposite.h5'
770708
outputs['inverse_composite_transform'] = [
771709
os.path.abspath(fileName)]
710+
else: # If composite transforms are written, then individuals are not written (as of 2014-10-26
711+
if not self.inputs.collapse_output_transforms:
712+
transformCount = 0
713+
if isdefined(self.inputs.initial_moving_transform):
714+
outputs['forward_transforms'].append(
715+
self.inputs.initial_moving_transform)
716+
outputs['forward_invert_flags'].append(
717+
invert_initial_moving_transform)
718+
outputs['reverse_transforms'].insert(
719+
0, self.inputs.initial_moving_transform)
720+
outputs['reverse_invert_flags'].insert(
721+
0, not invert_initial_moving_transform) # Prepend
722+
transformCount += 1
723+
elif isdefined(self.inputs.initial_moving_transform_com):
724+
forwardFileName, forwardInverseMode = self._outputFileNames(
725+
self.inputs.output_transform_prefix,
726+
transformCount,
727+
'Initial')
728+
reverseFileName, reverseInverseMode = self._outputFileNames(
729+
self.inputs.output_transform_prefix,
730+
transformCount,
731+
'Initial',
732+
True)
733+
outputs['forward_transforms'].append(os.path.abspath(forwardFileName))
734+
outputs['forward_invert_flags'].append(False)
735+
outputs['reverse_transforms'].insert(0,
736+
os.path.abspath(reverseFileName))
737+
outputs['reverse_invert_flags'].insert(0, True)
738+
transformCount += 1
739+
740+
for count in range(len(self.inputs.transforms)):
741+
forwardFileName, forwardInverseMode = self._outputFileNames(
742+
self.inputs.output_transform_prefix, transformCount,
743+
self.inputs.transforms[count])
744+
reverseFileName, reverseInverseMode = self._outputFileNames(
745+
self.inputs.output_transform_prefix, transformCount,
746+
self.inputs.transforms[count], True)
747+
outputs['forward_transforms'].append(
748+
os.path.abspath(forwardFileName))
749+
outputs['forward_invert_flags'].append(forwardInverseMode)
750+
outputs['reverse_transforms'].insert(
751+
0, os.path.abspath(reverseFileName))
752+
outputs[
753+
'reverse_invert_flags'].insert(0, reverseInverseMode)
754+
transformCount += 1
755+
else:
756+
transformCount = 0
757+
isLinear = [any(self._linear_transform_names == t)
758+
for t in self.inputs.transforms]
759+
collapse_list = []
760+
761+
if isdefined(self.inputs.initial_moving_transform) or \
762+
isdefined(self.inputs.initial_moving_transform_com):
763+
isLinear.insert(0, True)
764+
765+
# Only files returned by collapse_output_transforms
766+
if any(isLinear):
767+
collapse_list.append('GenericAffine')
768+
if not all(isLinear):
769+
collapse_list.append('SyN')
770+
771+
for transform in collapse_list:
772+
forwardFileName, forwardInverseMode = self._outputFileNames(
773+
self.inputs.output_transform_prefix,
774+
transformCount,
775+
transform,
776+
inverse=False)
777+
reverseFileName, reverseInverseMode = self._outputFileNames(
778+
self.inputs.output_transform_prefix,
779+
transformCount,
780+
transform,
781+
inverse=True)
782+
outputs['forward_transforms'].append(os.path.abspath(
783+
forwardFileName))
784+
outputs['forward_invert_flags'].append(forwardInverseMode)
785+
outputs['reverse_transforms'].append(
786+
os.path.abspath(reverseFileName))
787+
outputs['reverse_invert_flags'].append(reverseInverseMode)
788+
transformCount += 1
789+
772790
out_filename = self._get_outputfilenames(inverse=False)
773791
inv_out_filename = self._get_outputfilenames(inverse=True)
774792
if out_filename:

nipype/interfaces/slicer/registration/brainsfit.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class BRAINSFitInputSpec(CommandLineInputSpec):
6767
NEVER_USE_THIS_FLAG_IT_IS_OUTDATED_02 = traits.Bool(desc="DO NOT USE THIS FLAG", argstr="--NEVER_USE_THIS_FLAG_IT_IS_OUTDATED_02 ")
6868
permitParameterVariation = InputMultiPath(traits.Int, desc="A bit vector to permit linear transform parameters to vary under optimization. The vector order corresponds with transform parameters, and beyond the end ones fill in as a default. For instance, you can choose to rotate only in x (pitch) with 1,0,0; this is mostly for expert use in turning on and off individual degrees of freedom in rotation, translation or scaling without multiplying the number of transform representations; this trick is probably meaningless when tried with the general affine transform.", sep=",", argstr="--permitParameterVariation %s")
6969
costMetric = traits.Enum("MMI", "MSE", "NC", "MC", desc="The cost metric to be used during fitting. Defaults to MMI. Options are MMI (Mattes Mutual Information), MSE (Mean Square Error), NC (Normalized Correlation), MC (Match Cardinality for binary images)", argstr="--costMetric %s")
70+
writeOutputTransformInFloat = traits.Bool(desc="By default, the output registration transforms (either the output composite transform or each transform component) are written to the disk in double precision. If this flag is ON, the output transforms will be written in single (float) precision. It is especially important if the output transform is a displacement field transform, or it is a composite transform that includes several displacement fields.", argstr="--writeOutputTransformInFloat ")
7071

7172

7273
class BRAINSFitOutputSpec(TraitedSpec):

nipype/interfaces/slicer/registration/tests/test_auto_BRAINSFit.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ def test_BRAINSFit_inputs():
146146
),
147147
writeTransformOnFailure=dict(argstr='--writeTransformOnFailure ',
148148
),
149+
writeOutputTransformInFloat=dict(argstr='--writeOutputTransformInFloat ',
150+
),
149151
)
150152
inputs = BRAINSFit.input_spec()
151153

0 commit comments

Comments
 (0)