diff --git a/nipype/interfaces/fsl/preprocess.py b/nipype/interfaces/fsl/preprocess.py index 8f23699915..4b485e169c 100644 --- a/nipype/interfaces/fsl/preprocess.py +++ b/nipype/interfaces/fsl/preprocess.py @@ -400,8 +400,9 @@ class FLIRTInputSpec(FSLCommandInputSpec): name_template='%s_flirt.log', desc='output log') in_matrix_file = File(argstr='-init %s', desc='input 4x4 affine matrix') apply_xfm = traits.Bool( - argstr='-applyxfm', requires=['in_matrix_file'], - desc='apply transformation supplied by in_matrix_file') + argstr='-applyxfm', + desc=('apply transformation supplied by in_matrix_file or uses_qform to' + ' use the affine matrix stored in the reference header')) apply_isoxfm = traits.Float( argstr='-applyisoxfm %f', xor=['apply_xfm'], desc='as applyxfm but forces isotropic resampling') @@ -561,13 +562,18 @@ def _parse_inputs(self, skip=None): if isdefined(self.inputs.save_log) and self.inputs.save_log: if not isdefined(self.inputs.verbose) or self.inputs.verbose == 0: self.inputs.verbose = 1 + if isdefined(self.inputs.apply_xfm) and self.inputs.apply_xfm: + if not self.inputs.in_matrix_file and not self.inputs.uses_qform: + raise RuntimeError('Argument apply_xfm requires in_matrix_file ' + 'or uses_qform arguments to run') skip.append('save_log') return super(FLIRT, self)._parse_inputs(skip=skip) class ApplyXFMInputSpec(FLIRTInputSpec): apply_xfm = traits.Bool( - True, argstr='-applyxfm', requires=['in_matrix_file'], - desc='apply transformation supplied by in_matrix_file', + True, argstr='-applyxfm', + desc=('apply transformation supplied by in_matrix_file or uses_qform to' + ' use the affine matrix stored in the reference header'), usedefault=True) diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py index cf67b12b2b..438f4ce486 100644 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py +++ b/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py @@ -10,7 +10,6 @@ def test_ApplyXFM_inputs(): xor=['apply_xfm'], ), apply_xfm=dict(argstr='-applyxfm', - requires=['in_matrix_file'], usedefault=True, ), args=dict(argstr='%s', diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py deleted file mode 100644 index cf67b12b2b..0000000000 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py +++ /dev/null @@ -1,164 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..preprocess import ApplyXFM - - -def test_ApplyXFM_inputs(): - input_map = dict(angle_rep=dict(argstr='-anglerep %s', - ), - apply_isoxfm=dict(argstr='-applyisoxfm %f', - xor=['apply_xfm'], - ), - apply_xfm=dict(argstr='-applyxfm', - requires=['in_matrix_file'], - usedefault=True, - ), - args=dict(argstr='%s', - ), - bbrslope=dict(argstr='-bbrslope %f', - min_ver='5.0.0', - ), - bbrtype=dict(argstr='-bbrtype %s', - min_ver='5.0.0', - ), - bgvalue=dict(argstr='-setbackground %f', - ), - bins=dict(argstr='-bins %d', - ), - coarse_search=dict(argstr='-coarsesearch %d', - units='degrees', - ), - cost=dict(argstr='-cost %s', - ), - cost_func=dict(argstr='-searchcost %s', - ), - datatype=dict(argstr='-datatype %s', - ), - display_init=dict(argstr='-displayinit', - ), - dof=dict(argstr='-dof %d', - ), - echospacing=dict(argstr='-echospacing %f', - min_ver='5.0.0', - ), - environ=dict(nohash=True, - usedefault=True, - ), - fieldmap=dict(argstr='-fieldmap %s', - min_ver='5.0.0', - ), - fieldmapmask=dict(argstr='-fieldmapmask %s', - min_ver='5.0.0', - ), - fine_search=dict(argstr='-finesearch %d', - units='degrees', - ), - force_scaling=dict(argstr='-forcescaling', - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(argstr='-in %s', - mandatory=True, - position=0, - ), - in_matrix_file=dict(argstr='-init %s', - ), - in_weight=dict(argstr='-inweight %s', - ), - interp=dict(argstr='-interp %s', - ), - min_sampling=dict(argstr='-minsampling %f', - units='mm', - ), - no_clamp=dict(argstr='-noclamp', - ), - no_resample=dict(argstr='-noresample', - ), - no_resample_blur=dict(argstr='-noresampblur', - ), - no_search=dict(argstr='-nosearch', - ), - out_file=dict(argstr='-out %s', - hash_files=False, - name_source=['in_file'], - name_template='%s_flirt', - position=2, - ), - out_log=dict(keep_extension=True, - name_source=['in_file'], - name_template='%s_flirt.log', - requires=['save_log'], - ), - out_matrix_file=dict(argstr='-omat %s', - hash_files=False, - keep_extension=True, - name_source=['in_file'], - name_template='%s_flirt.mat', - position=3, - ), - output_type=dict(), - padding_size=dict(argstr='-paddingsize %d', - units='voxels', - ), - pedir=dict(argstr='-pedir %d', - min_ver='5.0.0', - ), - ref_weight=dict(argstr='-refweight %s', - ), - reference=dict(argstr='-ref %s', - mandatory=True, - position=1, - ), - rigid2D=dict(argstr='-2D', - ), - save_log=dict(), - schedule=dict(argstr='-schedule %s', - ), - searchr_x=dict(argstr='-searchrx %s', - units='degrees', - ), - searchr_y=dict(argstr='-searchry %s', - units='degrees', - ), - searchr_z=dict(argstr='-searchrz %s', - units='degrees', - ), - sinc_width=dict(argstr='-sincwidth %d', - units='voxels', - ), - sinc_window=dict(argstr='-sincwindow %s', - ), - terminal_output=dict(nohash=True, - ), - uses_qform=dict(argstr='-usesqform', - ), - verbose=dict(argstr='-verbose %d', - ), - wm_seg=dict(argstr='-wmseg %s', - min_ver='5.0.0', - ), - wmcoords=dict(argstr='-wmcoords %s', - min_ver='5.0.0', - ), - wmnorms=dict(argstr='-wmnorms %s', - min_ver='5.0.0', - ), - ) - inputs = ApplyXFM.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_ApplyXFM_outputs(): - output_map = dict(out_file=dict(), - out_log=dict(), - out_matrix_file=dict(), - ) - outputs = ApplyXFM.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/interfaces/fsl/tests/test_auto_FLIRT.py b/nipype/interfaces/fsl/tests/test_auto_FLIRT.py index 3a69778b3d..fabfa4054c 100644 --- a/nipype/interfaces/fsl/tests/test_auto_FLIRT.py +++ b/nipype/interfaces/fsl/tests/test_auto_FLIRT.py @@ -10,7 +10,6 @@ def test_FLIRT_inputs(): xor=['apply_xfm'], ), apply_xfm=dict(argstr='-applyxfm', - requires=['in_matrix_file'], ), args=dict(argstr='%s', ), diff --git a/nipype/interfaces/fsl/tests/test_preprocess.py b/nipype/interfaces/fsl/tests/test_preprocess.py index e2ef8962a7..96c5a2dd53 100644 --- a/nipype/interfaces/fsl/tests/test_preprocess.py +++ b/nipype/interfaces/fsl/tests/test_preprocess.py @@ -7,6 +7,7 @@ import os import tempfile +from copy import deepcopy import pytest from nipype.utils.filemanip import split_filename, filename_to_list @@ -220,12 +221,13 @@ def test_flirt(setup_flirt): flirter = fsl.FLIRT() # infile not specified with pytest.raises(ValueError): - flirter.run() + flirter.cmdline flirter.inputs.in_file = infile # reference not specified with pytest.raises(ValueError): - flirter.run() + flirter.cmdline flirter.inputs.reference = reffile + # Generate outfile and outmatrix pth, fname, ext = split_filename(infile) outfile = fsl_name(flirter, '%s_flirt' % fname) @@ -234,6 +236,20 @@ def test_flirt(setup_flirt): outfile, outmat) assert flirter.cmdline == realcmd + # test apply_xfm option + axfm = deepcopy(flirter) + axfm.inputs.apply_xfm = True + # in_matrix_file or uses_qform must be defined + with pytest.raises(RuntimeError): axfm.cmdline + axfm2 = deepcopy(axfm) + # test uses_qform + axfm.inputs.uses_qform = True + assert axfm.cmdline == (realcmd + ' -applyxfm -usesqform') + # test in_matrix_file + axfm2.inputs.in_matrix_file = reffile + assert axfm2.cmdline == (realcmd + ' -applyxfm -init %s' % reffile) + + _, tmpfile = tempfile.mkstemp(suffix='.nii', dir=tmpdir) # Loop over all inputs, set a reasonable value and make sure the # cmdline is updated correctly.