From 60a107dd215a320e04c190be1c7654ea86da9c52 Mon Sep 17 00:00:00 2001 From: Ross Markello Date: Sat, 24 Jun 2017 14:43:17 -0400 Subject: [PATCH 1/3] [FIX]: AFNI Allineate Errors in OutputSpec mapping for Allineate, where out_file name was not successfully generated or mapped. Added xor options for some input options that are mutually exclusive. Included new "overwrite" feature to overwrite output if it already exists. --- nipype/interfaces/afni/preprocess.py | 37 ++++++++++++------- .../afni/tests/test_auto_Allineate.py | 13 +++++-- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/nipype/interfaces/afni/preprocess.py b/nipype/interfaces/afni/preprocess.py index 5fd1ab0f21..4b08a4c794 100644 --- a/nipype/interfaces/afni/preprocess.py +++ b/nipype/interfaces/afni/preprocess.py @@ -64,24 +64,29 @@ class AllineateInputSpec(AFNICommandInputSpec): desc='output file from 3dAllineate', argstr='-prefix %s', position=-2, - name_source='%s_allineate', genfile=True) out_param_file = File( argstr='-1Dparam_save %s', - desc='Save the warp parameters in ASCII (.1D) format.') + desc='Save the warp parameters in ASCII (.1D) format.', + xor=['in_param_file']) in_param_file = File( exists=True, argstr='-1Dparam_apply %s', desc='Read warp parameters from file and apply them to ' - 'the source dataset, and produce a new dataset') + 'the source dataset, and produce a new dataset', + xor=['out_param_file']) out_matrix = File( argstr='-1Dmatrix_save %s', - desc='Save the transformation matrix for each volume.') + desc='Save the transformation matrix for each volume.', + xor=['in_matrix']) in_matrix = File( desc='matrix to align input file', argstr='-1Dmatrix_apply %s', - position=-3) - + position=-3, + xor=['out_matrix']) + overwrite = traits.Bool( + desc='overwrite output file if it already exists', + argstr='-overwrite') _cost_funcs = [ 'leastsq', 'ls', 'mutualinfo', 'mi', @@ -250,8 +255,10 @@ class AllineateInputSpec(AFNICommandInputSpec): class AllineateOutputSpec(TraitedSpec): - out_file = File(desc='output image file name') - matrix = File(desc='matrix to align input file') + out_file = File(exists=True, desc='output image file name') + out_matrix = File(exists=True, desc='matrix to align input file') + out_param_file = File(exists=True, desc='warp parameters') + out_weight_file = File(exists=True, desc='weight volume') class Allineate(AFNICommand): @@ -271,7 +278,6 @@ class Allineate(AFNICommand): >>> allineate.cmdline # doctest: +ALLOW_UNICODE '3dAllineate -1Dmatrix_apply cmatrix.mat -prefix functional_allineate.nii -source functional.nii' >>> res = allineate.run() # doctest: +SKIP - """ _cmd = '3dAllineate' @@ -285,21 +291,23 @@ def _format_arg(self, name, trait_spec, value): return super(Allineate, self)._format_arg(name, trait_spec, value) def _list_outputs(self): - outputs = self.output_spec().get() + outputs = self._outputs().get() if not isdefined(self.inputs.out_file): - outputs['out_file'] = self._gen_filename(self.inputs.in_file, - suffix=self.inputs.suffix) + outputs['out_file'] = self._gen_fname(self.inputs.in_file, + suffix='_allineate.nii') else: outputs['out_file'] = os.path.abspath(self.inputs.out_file) if isdefined(self.inputs.out_matrix): - outputs['matrix'] = os.path.abspath(os.path.join(os.getcwd(),\ - self.inputs.out_matrix +'.aff12.1D')) + outputs['out_matrix'] = os.path.abspath(os.path.join(os.getcwd(), + self.inputs.out_matrix + + '.aff12.1D')) return outputs def _gen_filename(self, name): if name == 'out_file': return self._list_outputs()[name] + return None class AutoTcorrelateInputSpec(AFNICommandInputSpec): @@ -358,6 +366,7 @@ class AutoTcorrelate(AFNICommand): '3dAutoTcorrelate -eta2 -mask mask.nii -mask_only_targets -prefix functional_similarity_matrix.1D -polort -1 functional.nii' >>> res = corr.run() # doctest: +SKIP """ + input_spec = AutoTcorrelateInputSpec output_spec = AFNICommandOutputSpec _cmd = '3dAutoTcorrelate' diff --git a/nipype/interfaces/afni/tests/test_auto_Allineate.py b/nipype/interfaces/afni/tests/test_auto_Allineate.py index 0bf37ea8cd..a7a79ee749 100644 --- a/nipype/interfaces/afni/tests/test_auto_Allineate.py +++ b/nipype/interfaces/afni/tests/test_auto_Allineate.py @@ -39,8 +39,10 @@ def test_Allineate_inputs(): ), in_matrix=dict(argstr='-1Dmatrix_apply %s', position=-3, + xor=['out_matrix'], ), in_param_file=dict(argstr='-1Dparam_apply %s', + xor=['out_param_file'], ), interpolation=dict(argstr='-interp %s', ), @@ -64,16 +66,19 @@ def test_Allineate_inputs(): ), out_file=dict(argstr='-prefix %s', genfile=True, - name_source='%s_allineate', position=-2, ), out_matrix=dict(argstr='-1Dmatrix_save %s', + xor=['in_matrix'], ), out_param_file=dict(argstr='-1Dparam_save %s', + xor=['in_param_file'], ), out_weight_file=dict(argstr='-wtprefix %s', ), outputtype=dict(), + overwrite=dict(argstr='-overwrite', + ), reference=dict(argstr='-base %s', ), replacebase=dict(argstr='-replacebase', @@ -113,8 +118,10 @@ def test_Allineate_inputs(): def test_Allineate_outputs(): - output_map = dict(matrix=dict(), - out_file=dict(), + output_map = dict(out_file=dict(), + out_matrix=dict(), + out_param_file=dict(), + out_weight_file=dict(), ) outputs = Allineate.output_spec() From 0d21a92d8853aa074f0c1442aec8692be3ae5be1 Mon Sep 17 00:00:00 2001 From: Ross Markello Date: Fri, 28 Jul 2017 17:00:33 -0400 Subject: [PATCH 2/3] [FIX]: AFNI Allineate _list_output Fixed output mapping in Allineate. Ensures suffixes are in line with AFNI standards. --- nipype/interfaces/afni/preprocess.py | 33 +++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/nipype/interfaces/afni/preprocess.py b/nipype/interfaces/afni/preprocess.py index 7180953c28..6742ec4f05 100644 --- a/nipype/interfaces/afni/preprocess.py +++ b/nipype/interfaces/afni/preprocess.py @@ -291,17 +291,30 @@ def _format_arg(self, name, trait_spec, value): return super(Allineate, self)._format_arg(name, trait_spec, value) def _list_outputs(self): - outputs = self._outputs().get() - if not isdefined(self.inputs.out_file): - outputs['out_file'] = self._gen_fname(self.inputs.in_file, - suffix='_allineate.nii') - else: - outputs['out_file'] = os.path.abspath(self.inputs.out_file) + outputs = self.output_spec().get() + + if self.inputs.out_file: + outputs['out_file'] = op.abspath(self.inputs.out_file) + + if self.inputs.out_weight_file: + outputs['out_weight_file'] = op.abspath(self.inputs.out_weight_file) + + if self.inputs.out_matrix: + path, base, ext = split_filename(self.inputs.out_matrix) + if ext.lower() not in ['.1d', '.1D']: + outputs['out_matrix'] = self._gen_fname(self.inputs.out_matrix, + suffix='.aff12.1D') + else: + outputs['out_matrix'] = op.abspath(self.inputs.out_matrix) + + if self.inputs.out_param_file: + path, base, ext = split_filename(self.inputs.out_param_file) + if ext.lower() not in ['.1d', '.1D']: + outputs['out_param_file'] = self._gen_fname(self.inputs.out_param_file, + suffix='.param.1D') + else: + outputs['out_param_file'] = op.abspath(self.inputs.out_param_file) - if isdefined(self.inputs.out_matrix): - outputs['out_matrix'] = os.path.abspath(os.path.join(os.getcwd(), - self.inputs.out_matrix + - '.aff12.1D')) return outputs def _gen_filename(self, name): From 9b71e7163486a90817d4d48ae81ac5aea19795cd Mon Sep 17 00:00:00 2001 From: Ross Markello Date: Wed, 23 Aug 2017 13:09:57 -0400 Subject: [PATCH 3/3] [FIX]: AFNI Allineate conflicts with master Edited AFNI Allineate interface to accommodate updated master branch. Updated xor options for allcostx. --- nipype/interfaces/afni/preprocess.py | 21 ++++++++----------- .../afni/tests/test_auto_Allineate.py | 9 ++++---- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/nipype/interfaces/afni/preprocess.py b/nipype/interfaces/afni/preprocess.py index f75922aefe..d17e0313f2 100644 --- a/nipype/interfaces/afni/preprocess.py +++ b/nipype/interfaces/afni/preprocess.py @@ -220,14 +220,12 @@ class AllineateInputSpec(AFNICommandInputSpec): out_file = File( desc='output file from 3dAllineate', argstr='-prefix %s', - name_source='in_file', - name_template='%s_allineate', genfile=True, xor=['allcostx']) out_param_file = File( argstr='-1Dparam_save %s', desc='Save the warp parameters in ASCII (.1D) format.', - xor=['in_param_file']) + xor=['in_param_file','allcostx']) in_param_file = File( exists=True, argstr='-1Dparam_apply %s', @@ -237,7 +235,7 @@ class AllineateInputSpec(AFNICommandInputSpec): out_matrix = File( argstr='-1Dmatrix_save %s', desc='Save the transformation matrix for each volume.', - xor=['in_matrix']) + xor=['in_matrix','allcostx']) in_matrix = File( desc='matrix to align input file', argstr='-1Dmatrix_apply %s', @@ -247,14 +245,12 @@ class AllineateInputSpec(AFNICommandInputSpec): desc='overwrite output file if it already exists', argstr='-overwrite') - # TODO: implement sensible xors for allcostx and suppres prefix in command when allcosx is used allcostx= File( desc='Compute and print ALL available cost functionals for the un-warped inputs' 'AND THEN QUIT. If you use this option none of the other expected outputs will be produced', argstr='-allcostx |& tee %s', position=-1, - xor=['out_file']) - + xor=['out_file', 'out_matrix', 'out_param_file', 'out_weight_file']) _cost_funcs = [ 'leastsq', 'ls', 'mutualinfo', 'mi', @@ -365,7 +361,8 @@ class AllineateInputSpec(AFNICommandInputSpec): 'Must be defined on the same grid as the base dataset') out_weight_file = traits.File( argstr='-wtprefix %s', - desc='Write the weight volume to disk as a dataset') + desc='Write the weight volume to disk as a dataset', + xor=['allcostx']) source_mask = File( exists=True, argstr='-source_mask %s', @@ -445,7 +442,7 @@ class Allineate(AFNICommand): >>> allineate.inputs.out_file = 'functional_allineate.nii' >>> allineate.inputs.in_matrix = 'cmatrix.mat' >>> allineate.cmdline # doctest: +ALLOW_UNICODE - '3dAllineate -source functional.nii -1Dmatrix_apply cmatrix.mat -prefix functional_allineate.nii' + '3dAllineate -source functional.nii -prefix functional_allineate.nii -1Dmatrix_apply cmatrix.mat' >>> res = allineate.run() # doctest: +SKIP >>> from nipype.interfaces import afni @@ -454,7 +451,7 @@ class Allineate(AFNICommand): >>> allineate.inputs.reference = 'structural.nii' >>> allineate.inputs.allcostx = 'out.allcostX.txt' >>> allineate.cmdline # doctest: +ALLOW_UNICODE - '3dAllineate -source functional.nii -prefix functional_allineate -base structural.nii -allcostx |& tee out.allcostX.txt' + '3dAllineate -source functional.nii -base structural.nii -allcostx |& tee out.allcostX.txt' >>> res = allineate.run() # doctest: +SKIP """ @@ -493,8 +490,8 @@ def _list_outputs(self): else: outputs['out_param_file'] = op.abspath(self.inputs.out_param_file) - if isdefined(self.inputs.allcostX): - outputs['allcostX'] = os.path.abspath(os.path.join(os.getcwd(),\ + if isdefined(self.inputs.allcostx): + outputs['allcostX'] = os.path.abspath(os.path.join(os.getcwd(), self.inputs.allcostx)) return outputs diff --git a/nipype/interfaces/afni/tests/test_auto_Allineate.py b/nipype/interfaces/afni/tests/test_auto_Allineate.py index ee2a41011b..cc75f973cc 100644 --- a/nipype/interfaces/afni/tests/test_auto_Allineate.py +++ b/nipype/interfaces/afni/tests/test_auto_Allineate.py @@ -6,7 +6,7 @@ def test_Allineate_inputs(): input_map = dict(allcostx=dict(argstr='-allcostx |& tee %s', position=-1, - xor=['out_file'], + xor=['out_file', 'out_matrix', 'out_param_file', 'out_weight_file'], ), args=dict(argstr='%s', ), @@ -69,17 +69,16 @@ def test_Allineate_inputs(): ), out_file=dict(argstr='-prefix %s', genfile=True, - name_source='in_file', - name_template='%s_allineate', xor=['allcostx'], ), out_matrix=dict(argstr='-1Dmatrix_save %s', - xor=['in_matrix'], + xor=['in_matrix', 'allcostx'], ), out_param_file=dict(argstr='-1Dparam_save %s', - xor=['in_param_file'], + xor=['in_param_file', 'allcostx'], ), out_weight_file=dict(argstr='-wtprefix %s', + xor=['allcostx'], ), outputtype=dict(), overwrite=dict(argstr='-overwrite',