From e89e4ac40f4a32d8b46b3830af58090f44806fc9 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Fri, 14 Aug 2020 15:39:27 -0400 Subject: [PATCH 1/3] FIX: Permit identity transforms in list of transforms to antsApplyTransforms Convert to InputMultiObject while we're at it. --- nipype/interfaces/ants/resampling.py | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/nipype/interfaces/ants/resampling.py b/nipype/interfaces/ants/resampling.py index a5d6a52c04..1a03470a53 100644 --- a/nipype/interfaces/ants/resampling.py +++ b/nipype/interfaces/ants/resampling.py @@ -4,7 +4,7 @@ import os from .base import ANTSCommand, ANTSCommandInputSpec -from ..base import TraitedSpec, File, traits, isdefined, InputMultiPath +from ..base import TraitedSpec, File, traits, isdefined, InputMultiObject from ...utils.filemanip import split_filename @@ -52,7 +52,7 @@ class WarpTimeSeriesImageMultiTransformInputSpec(ANTSCommandInputSpec): use_bspline = traits.Bool( argstr="--use-Bspline", desc="Use 3rd order B-Spline interpolation" ) - transformation_series = InputMultiPath( + transformation_series = InputMultiObject( File(exists=True), argstr="%s", desc="transformation file(s) to be applied", @@ -204,7 +204,7 @@ class WarpImageMultiTransformInputSpec(ANTSCommandInputSpec): use_bspline = traits.Bool( argstr="--use-BSpline", desc="Use 3rd order B-Spline interpolation" ) - transformation_series = InputMultiPath( + transformation_series = InputMultiObject( File(exists=True), argstr="%s", desc="transformation file(s) to be applied", @@ -369,15 +369,14 @@ class ApplyTransformsInputSpec(ANTSCommandInputSpec): traits.Float(), traits.Float() # Gaussian/MultiLabel (sigma, alpha) ), ) - transforms = traits.Either( - InputMultiPath(File(exists=True)), - "identity", + transforms = InputMultiObject( + traits.Either(File(exists=True), "identity"), argstr="%s", mandatory=True, desc="transform files: will be applied in reverse order. For " "example, the last specified transform will be applied first.", ) - invert_transform_flags = InputMultiPath(traits.Bool()) + invert_transform_flags = InputMultiObject(traits.Bool()) default_value = traits.Float(0.0, argstr="--default-value %g", usedefault=True) print_out_composite_warp_file = traits.Bool( False, @@ -411,7 +410,7 @@ class ApplyTransforms(ANTSCommand): >>> at.cmdline 'antsApplyTransforms --default-value 0 --float 0 --input moving1.nii \ --interpolation Linear --output moving1_trans.nii \ ---reference-image fixed1.nii -t identity' +--reference-image fixed1.nii --transform identity' >>> at = ApplyTransforms() >>> at.inputs.dimension = 3 @@ -441,6 +440,22 @@ class ApplyTransforms(ANTSCommand): 'antsApplyTransforms --default-value 0 --dimensionality 3 --float 0 --input moving1.nii \ --interpolation BSpline[ 5 ] --output deformed_moving1.nii --reference-image fixed1.nii \ --transform [ ants_Warp.nii.gz, 0 ] --transform [ trans.mat, 0 ]' + + Identity transforms may be used as part of a chain: + + >>> at2 = ApplyTransforms() + >>> at2.inputs.dimension = 3 + >>> at2.inputs.input_image = 'moving1.nii' + >>> at2.inputs.reference_image = 'fixed1.nii' + >>> at2.inputs.output_image = 'deformed_moving1.nii' + >>> at2.inputs.interpolation = 'BSpline' + >>> at2.inputs.interpolation_parameters = (5,) + >>> at2.inputs.default_value = 0 + >>> at2.inputs.transforms = ['identity', 'ants_Warp.nii.gz', 'trans.mat'] + >>> at2.cmdline + 'antsApplyTransforms --default-value 0 --dimensionality 3 --float 0 --input moving1.nii \ +--interpolation BSpline[ 5 ] --output deformed_moving1.nii --reference-image fixed1.nii \ +--transform identity --transform ants_Warp.nii.gz --transform trans.mat' """ _cmd = "antsApplyTransforms" From 68bbf02fe862fcb8416385c12c004257cfb191ff Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Fri, 14 Aug 2020 15:40:38 -0400 Subject: [PATCH 2/3] RF: Simplify inversion logic, use ValueError --- nipype/interfaces/ants/resampling.py | 37 ++++++++++++---------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/nipype/interfaces/ants/resampling.py b/nipype/interfaces/ants/resampling.py index 1a03470a53..48e944e091 100644 --- a/nipype/interfaces/ants/resampling.py +++ b/nipype/interfaces/ants/resampling.py @@ -420,11 +420,11 @@ class ApplyTransforms(ANTSCommand): >>> at.inputs.interpolation = 'Linear' >>> at.inputs.default_value = 0 >>> at.inputs.transforms = ['ants_Warp.nii.gz', 'trans.mat'] - >>> at.inputs.invert_transform_flags = [False, False] + >>> at.inputs.invert_transform_flags = [False, True] >>> at.cmdline 'antsApplyTransforms --default-value 0 --dimensionality 3 --float 0 --input moving1.nii \ --interpolation Linear --output deformed_moving1.nii --reference-image fixed1.nii \ ---transform [ ants_Warp.nii.gz, 0 ] --transform [ trans.mat, 0 ]' +--transform ants_Warp.nii.gz --transform [ trans.mat, 1 ]' >>> at1 = ApplyTransforms() >>> at1.inputs.dimension = 3 @@ -439,7 +439,7 @@ class ApplyTransforms(ANTSCommand): >>> at1.cmdline 'antsApplyTransforms --default-value 0 --dimensionality 3 --float 0 --input moving1.nii \ --interpolation BSpline[ 5 ] --output deformed_moving1.nii --reference-image fixed1.nii \ ---transform [ ants_Warp.nii.gz, 0 ] --transform [ trans.mat, 0 ]' +--transform ants_Warp.nii.gz --transform trans.mat' Identity transforms may be used as part of a chain: @@ -473,25 +473,20 @@ def _gen_filename(self, name): def _get_transform_filenames(self): retval = [] - for ii in range(len(self.inputs.transforms)): - if isdefined(self.inputs.invert_transform_flags): - if len(self.inputs.transforms) == len( - self.inputs.invert_transform_flags - ): - invert_code = 1 if self.inputs.invert_transform_flags[ii] else 0 - retval.append( - "--transform [ %s, %d ]" - % (self.inputs.transforms[ii], invert_code) - ) - else: - raise Exception( - ( - "ERROR: The useInverse list must have the same number " - "of entries as the transformsFileName list." - ) - ) + invert_flags = self.inputs.invert_transform_flags + if not isdefined(invert_flags): + invert_flags = [False] * len(self.inputs.transforms) + elif len(self.inputs.transforms) != len(invert_flags): + raise ValueError( + "ERROR: The invert_transform_flags list must have the same number " + "of entries as the transforms list." + ) + + for transform, invert in zip(self.inputs.transforms, invert_flags): + if invert: + retval.append(f"--transform [ {transform}, 1 ]") else: - retval.append("--transform %s" % self.inputs.transforms[ii]) + retval.append(f"--transform {transform}") return " ".join(retval) def _get_output_warped_filename(self): From c729c1ce761793715371b0295c9b39eeb878aeda Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Fri, 14 Aug 2020 15:42:01 -0400 Subject: [PATCH 3/3] STY: Drop unused identity branch --- nipype/interfaces/ants/resampling.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nipype/interfaces/ants/resampling.py b/nipype/interfaces/ants/resampling.py index 48e944e091..607202c109 100644 --- a/nipype/interfaces/ants/resampling.py +++ b/nipype/interfaces/ants/resampling.py @@ -502,8 +502,6 @@ def _format_arg(self, opt, spec, val): if opt == "output_image": return self._get_output_warped_filename() elif opt == "transforms": - if val == "identity": - return "-t identity" return self._get_transform_filenames() elif opt == "interpolation": if self.inputs.interpolation in [