From 8249094f7953178af6f34bb417761a07d0e5b5e2 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Fri, 13 Oct 2017 16:26:01 -0400 Subject: [PATCH 1/3] changing _format_arg in WarpImageMultiTransform and adding simple tests (mostly copy of doctests) --- nipype/interfaces/ants/resampling.py | 4 +- .../interfaces/ants/tests/test_resampling.py | 93 +++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 nipype/interfaces/ants/tests/test_resampling.py diff --git a/nipype/interfaces/ants/resampling.py b/nipype/interfaces/ants/resampling.py index 39393dc0f0..63bb5c4a16 100644 --- a/nipype/interfaces/ants/resampling.py +++ b/nipype/interfaces/ants/resampling.py @@ -86,7 +86,7 @@ def _format_arg(self, opt, spec, val): isdefined(self.inputs.invert_affine): affine_counter += 1 if affine_counter in self.inputs.invert_affine: - series += ['-i'], + series += ['-i'] series += [transformation] return ' '.join(series) return super(WarpTimeSeriesImageMultiTransform, self)._format_arg(opt, spec, val) @@ -195,7 +195,7 @@ def _format_arg(self, opt, spec, val): isdefined(self.inputs.invert_affine): affine_counter += 1 if affine_counter in self.inputs.invert_affine: - series += '-i', + series += ['-i'] series += [transformation] return ' '.join(series) return super(WarpImageMultiTransform, self)._format_arg(opt, spec, val) diff --git a/nipype/interfaces/ants/tests/test_resampling.py b/nipype/interfaces/ants/tests/test_resampling.py new file mode 100644 index 0000000000..3c13afd853 --- /dev/null +++ b/nipype/interfaces/ants/tests/test_resampling.py @@ -0,0 +1,93 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.ants import WarpImageMultiTransform, WarpTimeSeriesImageMultiTransform +import os +import pytest, pdb + + +@pytest.fixture() +def change_dir(request): + orig_dir = os.getcwd() + filepath = os.path.dirname( os.path.realpath( __file__ ) ) + datadir = os.path.realpath(os.path.join(filepath, '../../../testing/data')) + os.chdir(datadir) + + def move2orig(): + os.chdir(orig_dir) + + request.addfinalizer(move2orig) + + + +def test_WarpImageMultiTransform(change_dir): + wimt = WarpImageMultiTransform() + wimt.inputs.input_image = 'diffusion_weighted.nii' + wimt.inputs.reference_image = 'functional.nii' + wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ + 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] + assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii \ +func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz dwi2anat_coreg_Affine.txt' + + +def test_WarpImageMultiTransform_invaffine_1(change_dir): + wimt = WarpImageMultiTransform() + wimt.inputs.input_image = 'diffusion_weighted.nii' + wimt.inputs.reference_image = 'functional.nii' + wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ + 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] + wimt.inputs.invert_affine = [1] + assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii \ +-i func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz dwi2anat_coreg_Affine.txt' + + +def test_WarpImageMultiTransform_invaffine_2(change_dir): + wimt = WarpImageMultiTransform() + wimt.inputs.input_image = 'diffusion_weighted.nii' + wimt.inputs.reference_image = 'functional.nii' + wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ + 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] + wimt.inputs.invert_affine = [2] + assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz -i dwi2anat_coreg_Affine.txt' + + +@pytest.mark.xfail(reason="dj: should it fail?") +def test_WarpImageMultiTransform_invaffine_wrong(change_dir): + wimt = WarpImageMultiTransform() + wimt.inputs.input_image = 'diffusion_weighted.nii' + wimt.inputs.reference_image = 'functional.nii' + wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ + 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] + wimt.inputs.invert_affine = [3] + with pytest.raises(Exception): + assert wimt.cmdline + + +def test_WarpTimeSeriesImageMultiTransform(change_dir): + wtsimt = WarpTimeSeriesImageMultiTransform() + wtsimt.inputs.input_image = 'resting.nii' + wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' + wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + assert wtsimt.cmdline == 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii \ +-R ants_deformed.nii.gz ants_Warp.nii.gz ants_Affine.txt' + + +def test_WarpTimeSeriesImageMultiTransform_invaffine(change_dir): + wtsimt = WarpTimeSeriesImageMultiTransform() + wtsimt.inputs.input_image = 'resting.nii' + wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' + wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + wtsimt.inputs.invert_affine = [1] + assert wtsimt.cmdline == 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii \ +-R ants_deformed.nii.gz ants_Warp.nii.gz -i ants_Affine.txt' + + +@pytest.mark.xfail(reason="dj: should it fail?") +def test_WarpTimeSeriesImageMultiTransform_invaffine_wrong(change_dir): + wtsimt = WarpTimeSeriesImageMultiTransform() + wtsimt.inputs.input_image = 'resting.nii' + wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' + wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + wtsimt.inputs.invert_affine = [0] + with pytest.raises(Exception): + wtsimt.cmdline From 0b7742d224f06ae0f6d580d4f759cee780955fc3 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Fri, 27 Oct 2017 14:30:58 -0400 Subject: [PATCH 2/3] adding fixtures to test_resamplig --- .../interfaces/ants/tests/test_resampling.py | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/nipype/interfaces/ants/tests/test_resampling.py b/nipype/interfaces/ants/tests/test_resampling.py index 3c13afd853..6bbb31b24d 100644 --- a/nipype/interfaces/ants/tests/test_resampling.py +++ b/nipype/interfaces/ants/tests/test_resampling.py @@ -19,75 +19,67 @@ def move2orig(): request.addfinalizer(move2orig) - -def test_WarpImageMultiTransform(change_dir): +@pytest.fixture() +def create_wimt(): wimt = WarpImageMultiTransform() wimt.inputs.input_image = 'diffusion_weighted.nii' wimt.inputs.reference_image = 'functional.nii' wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] + return wimt + +def test_WarpImageMultiTransform(change_dir, create_wimt): + wimt = create_wimt assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii \ func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz dwi2anat_coreg_Affine.txt' -def test_WarpImageMultiTransform_invaffine_1(change_dir): - wimt = WarpImageMultiTransform() - wimt.inputs.input_image = 'diffusion_weighted.nii' - wimt.inputs.reference_image = 'functional.nii' - wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ - 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] +def test_WarpImageMultiTransform_invaffine_1(change_dir, create_wimt): + wimt = create_wimt wimt.inputs.invert_affine = [1] assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii \ -i func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz dwi2anat_coreg_Affine.txt' -def test_WarpImageMultiTransform_invaffine_2(change_dir): - wimt = WarpImageMultiTransform() - wimt.inputs.input_image = 'diffusion_weighted.nii' - wimt.inputs.reference_image = 'functional.nii' - wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ - 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] +def test_WarpImageMultiTransform_invaffine_2(change_dir, create_wimt): + wimt = create_wimt wimt.inputs.invert_affine = [2] assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz -i dwi2anat_coreg_Affine.txt' @pytest.mark.xfail(reason="dj: should it fail?") -def test_WarpImageMultiTransform_invaffine_wrong(change_dir): - wimt = WarpImageMultiTransform() - wimt.inputs.input_image = 'diffusion_weighted.nii' - wimt.inputs.reference_image = 'functional.nii' - wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ - 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] +def test_WarpImageMultiTransform_invaffine_wrong(change_dir, create_wimt): + wimt = create_wimt wimt.inputs.invert_affine = [3] with pytest.raises(Exception): assert wimt.cmdline -def test_WarpTimeSeriesImageMultiTransform(change_dir): - wtsimt = WarpTimeSeriesImageMultiTransform() - wtsimt.inputs.input_image = 'resting.nii' - wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' +@pytest.fixture() +def create_wtsimt(): + wtsimt = WarpTimeSeriesImageMultiTransform() + wtsimt.inputs.input_image = 'resting.nii' + wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + return wtsimt + + +def test_WarpTimeSeriesImageMultiTransform(change_dir, create_wtsimt): + wtsimt = create_wtsimt assert wtsimt.cmdline == 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii \ -R ants_deformed.nii.gz ants_Warp.nii.gz ants_Affine.txt' -def test_WarpTimeSeriesImageMultiTransform_invaffine(change_dir): - wtsimt = WarpTimeSeriesImageMultiTransform() - wtsimt.inputs.input_image = 'resting.nii' - wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' - wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] +def test_WarpTimeSeriesImageMultiTransform_invaffine(change_dir, create_wtsimt): + wtsimt = create_wtsimt wtsimt.inputs.invert_affine = [1] assert wtsimt.cmdline == 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii \ -R ants_deformed.nii.gz ants_Warp.nii.gz -i ants_Affine.txt' @pytest.mark.xfail(reason="dj: should it fail?") -def test_WarpTimeSeriesImageMultiTransform_invaffine_wrong(change_dir): - wtsimt = WarpTimeSeriesImageMultiTransform() - wtsimt.inputs.input_image = 'resting.nii' - wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' - wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] +def test_WarpTimeSeriesImageMultiTransform_invaffine_wrong(change_dir, create_wtsimt): + wtsimt = create_wtsimt wtsimt.inputs.invert_affine = [0] with pytest.raises(Exception): wtsimt.cmdline From a8f32b64ddd1f34cae9d9f699609c4e24272efaa Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Fri, 27 Oct 2017 21:14:55 -0400 Subject: [PATCH 3/3] raising exception if the list provided as invert_affine doesnt make sense --- nipype/interfaces/ants/resampling.py | 36 +++++++++++++++++-- .../interfaces/ants/tests/test_resampling.py | 4 +-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/nipype/interfaces/ants/resampling.py b/nipype/interfaces/ants/resampling.py index 63bb5c4a16..29f7c6d27b 100644 --- a/nipype/interfaces/ants/resampling.py +++ b/nipype/interfaces/ants/resampling.py @@ -43,9 +43,12 @@ class WarpTimeSeriesImageMultiTransformInputSpec(ANTSCommandInputSpec): desc='transformation file(s) to be applied', mandatory=True, copyfile=False) invert_affine = traits.List(traits.Int, - desc=('List of Affine transformations to invert. ' + desc=('List of Affine transformations to invert.' 'E.g.: [1,4,5] inverts the 1st, 4th, and 5th Affines ' - 'found in transformation_series')) + 'found in transformation_series. Note that indexing ' + 'starts with 1 and does not include warp fields. Affine ' + 'transformations are distinguished ' + 'from warp fields by the word "affine" included in their filenames.')) class WarpTimeSeriesImageMultiTransformOutputSpec(TraitedSpec): @@ -67,6 +70,14 @@ class WarpTimeSeriesImageMultiTransform(ANTSCommand): 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii -R ants_deformed.nii.gz ants_Warp.nii.gz \ ants_Affine.txt' + >>> wtsimt = WarpTimeSeriesImageMultiTransform() + >>> wtsimt.inputs.input_image = 'resting.nii' + >>> wtsimt.inputs.reference_image = 'ants_deformed.nii.gz' + >>> wtsimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + >>> wtsimt.inputs.invert_affine = [1] # # this will invert the 1st Affine file: ants_Affine.txt + >>> wtsimt.cmdline # doctest: +ALLOW_UNICODE + 'WarpTimeSeriesImageMultiTransform 4 resting.nii resting_wtsimt.nii -R ants_deformed.nii.gz ants_Warp.nii.gz \ +-i ants_Affine.txt' """ _cmd = 'WarpTimeSeriesImageMultiTransform' @@ -81,13 +92,22 @@ def _format_arg(self, opt, spec, val): if opt == 'transformation_series': series = [] affine_counter = 0 + affine_invert = [] for transformation in val: if 'Affine' in transformation and \ isdefined(self.inputs.invert_affine): affine_counter += 1 if affine_counter in self.inputs.invert_affine: series += ['-i'] + affine_invert.append(affine_counter) series += [transformation] + + if isdefined(self.inputs.invert_affine): + diff_inv = set(self.inputs.invert_affine) - set(affine_invert) + if diff_inv: + raise Exceptions("Review invert_affine, not all indexes from invert_affine were used, " + "check the description for the full definition") + return ' '.join(series) return super(WarpTimeSeriesImageMultiTransform, self)._format_arg(opt, spec, val) @@ -168,7 +188,7 @@ class WarpImageMultiTransform(ANTSCommand): >>> wimt.inputs.reference_image = 'functional.nii' >>> wimt.inputs.transformation_series = ['func2anat_coreg_Affine.txt','func2anat_InverseWarp.nii.gz', \ 'dwi2anat_Warp.nii.gz','dwi2anat_coreg_Affine.txt'] - >>> wimt.inputs.invert_affine = [1] + >>> wimt.inputs.invert_affine = [1] # this will invert the 1st Affine file: 'func2anat_coreg_Affine.txt' >>> wimt.cmdline # doctest: +ALLOW_UNICODE 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii \ -i func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz dwi2anat_coreg_Affine.txt' @@ -190,14 +210,24 @@ def _format_arg(self, opt, spec, val): if opt == 'transformation_series': series = [] affine_counter = 0 + affine_invert = [] for transformation in val: if "affine" in transformation.lower() and \ isdefined(self.inputs.invert_affine): affine_counter += 1 if affine_counter in self.inputs.invert_affine: series += ['-i'] + affine_invert.append(affine_counter) series += [transformation] + + if isdefined(self.inputs.invert_affine): + diff_inv = set(self.inputs.invert_affine) - set(affine_invert) + if diff_inv: + raise Exceptions("Review invert_affine, not all indexes from invert_affine were used, " + "check the description for the full definition") + return ' '.join(series) + return super(WarpImageMultiTransform, self)._format_arg(opt, spec, val) def _list_outputs(self): diff --git a/nipype/interfaces/ants/tests/test_resampling.py b/nipype/interfaces/ants/tests/test_resampling.py index 6bbb31b24d..22dc4446e9 100644 --- a/nipype/interfaces/ants/tests/test_resampling.py +++ b/nipype/interfaces/ants/tests/test_resampling.py @@ -3,7 +3,7 @@ from nipype.interfaces.ants import WarpImageMultiTransform, WarpTimeSeriesImageMultiTransform import os -import pytest, pdb +import pytest @pytest.fixture() @@ -47,7 +47,6 @@ def test_WarpImageMultiTransform_invaffine_2(change_dir, create_wimt): assert wimt.cmdline == 'WarpImageMultiTransform 3 diffusion_weighted.nii diffusion_weighted_wimt.nii -R functional.nii func2anat_coreg_Affine.txt func2anat_InverseWarp.nii.gz dwi2anat_Warp.nii.gz -i dwi2anat_coreg_Affine.txt' -@pytest.mark.xfail(reason="dj: should it fail?") def test_WarpImageMultiTransform_invaffine_wrong(change_dir, create_wimt): wimt = create_wimt wimt.inputs.invert_affine = [3] @@ -77,7 +76,6 @@ def test_WarpTimeSeriesImageMultiTransform_invaffine(change_dir, create_wtsimt): -R ants_deformed.nii.gz ants_Warp.nii.gz -i ants_Affine.txt' -@pytest.mark.xfail(reason="dj: should it fail?") def test_WarpTimeSeriesImageMultiTransform_invaffine_wrong(change_dir, create_wtsimt): wtsimt = create_wtsimt wtsimt.inputs.invert_affine = [0]