diff --git a/nipype/interfaces/ants/__init__.py b/nipype/interfaces/ants/__init__.py index e1970912cf..fa441944a2 100644 --- a/nipype/interfaces/ants/__init__.py +++ b/nipype/interfaces/ants/__init__.py @@ -5,7 +5,7 @@ # Registraiton programs from .registration import (ANTS, Registration, RegistrationSynQuick, - MeasureImageSimilarity) + CompositeTransformUtil, MeasureImageSimilarity) # Resampling Programs from .resampling import (ApplyTransforms, ApplyTransformsToPoints, diff --git a/nipype/interfaces/ants/registration.py b/nipype/interfaces/ants/registration.py index 556c19bf17..7c4a696c5a 100644 --- a/nipype/interfaces/ants/registration.py +++ b/nipype/interfaces/ants/registration.py @@ -1596,3 +1596,77 @@ def _list_outputs(self): outputs['forward_warp_field'] = out_base + '1Warp.nii.gz' outputs['inverse_warp_field'] = out_base + '1InverseWarp.nii.gz' return outputs + +class CompositeTransformUtilInputSpec(ANTSCommandInputSpec): + process = traits.Enum('assemble', 'disassemble', argstr='--%s', + position=1, usedefault=True, + desc='What to do with the transform inputs (assemble or disassemble)', + ) + out_file = File(exists=False, argstr='%s', position=2, + desc='Output file path (only used for disassembly).') + in_file = InputMultiPath(File(exists=True), mandatory=True, argstr='%s...', + position=3, desc='Input transform file(s)') + output_prefix = Str("transform", usedefault=True, argstr='%s', position=4, + desc="A prefix that is prepended to all output files (only used for assembly).") + +class CompositeTransformUtilOutputSpec(TraitedSpec): + affine_transform = File(desc="Affine transform component") + displacement_field = File(desc="Displacement field component") + out_file = File(desc="Compound transformation file") + +class CompositeTransformUtil(ANTSCommand): + """ + ANTs utility which can combine or break apart transform files into their individual + constituent components. + + Examples + -------- + + >>> from nipype.interfaces.ants import CompositeTransformUtil + >>> tran = CompositeTransformUtil() + >>> tran.inputs.process = 'disassemble' + >>> tran.inputs.in_file = 'output_Composite.h5' + >>> tran.cmdline + 'CompositeTransformUtil --disassemble output_Composite.h5 transform' + >>> tran.run() # doctest: +SKIP + + example for assembling transformation files + + >>> from nipype.interfaces.ants import CompositeTransformUtil + >>> tran = CompositeTransformUtil() + >>> tran.inputs.process = 'assemble' + >>> tran.inputs.out_file = 'my.h5' + >>> tran.inputs.in_file = ['AffineTransform.mat', 'DisplacementFieldTransform.nii.gz'] + >>> tran.cmdline + 'CompositeTransformUtil --assemble my.h5 AffineTransform.mat DisplacementFieldTransform.nii.gz ' + >>> tran.run() # doctest: +SKIP + """ + + _cmd = 'CompositeTransformUtil' + input_spec = CompositeTransformUtilInputSpec + output_spec = CompositeTransformUtilOutputSpec + + def _num_threads_update(self): + """ + CompositeTransformUtil ignores environment variables, + so override environment update from ANTSCommand class + """ + pass + + def _format_arg(self, name, spec, value): + if name == 'output_prefix' and self.inputs.process == 'assemble': + return '' + if name == 'out_file' and self.inputs.process == 'disassemble': + return '' + return super(CompositeTransformUtil, self)._format_arg(name, spec, value) + + def _list_outputs(self): + outputs = self.output_spec().get() + if self.inputs.process == 'disassemble': + outputs['affine_transform'] = os.path.abspath( + '00_{}_AffineTransform.mat'.format(self.inputs.output_prefix)) + outputs['displacement_field'] = os.path.abspath( + '01_{}_DisplacementFieldTransform.nii.gz'.format(self.inputs.output_prefix)) + if self.inputs.process == 'assemble': + outputs['out_file'] = os.path.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/ants/tests/test_auto_CompositeTransformUtil.py b/nipype/interfaces/ants/tests/test_auto_CompositeTransformUtil.py new file mode 100644 index 0000000000..d2e6f943e2 --- /dev/null +++ b/nipype/interfaces/ants/tests/test_auto_CompositeTransformUtil.py @@ -0,0 +1,52 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..registration import CompositeTransformUtil + + +def test_CompositeTransformUtil_inputs(): + input_map = dict( + args=dict(argstr='%s', ), + environ=dict( + nohash=True, + usedefault=True, + ), + in_file=dict( + argstr='%s...', + mandatory=True, + position=3, + ), + num_threads=dict( + nohash=True, + usedefault=True, + ), + out_file=dict( + argstr='%s', + position=2, + ), + output_prefix=dict( + argstr='%s', + position=4, + usedefault=True, + ), + process=dict( + argstr='--%s', + position=1, + usedefault=True, + ), + ) + inputs = CompositeTransformUtil.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value +def test_CompositeTransformUtil_outputs(): + output_map = dict( + affine_transform=dict(), + displacement_field=dict(), + out_file=dict(), + ) + outputs = CompositeTransformUtil.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/testing/data/AffineTransform.mat b/nipype/testing/data/AffineTransform.mat new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/DisplacementFieldTransform.nii.gz b/nipype/testing/data/DisplacementFieldTransform.nii.gz new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/output_Composite.h5 b/nipype/testing/data/output_Composite.h5 new file mode 100644 index 0000000000..e69de29bb2