diff --git a/nipype/interfaces/afni/__init__.py b/nipype/interfaces/afni/__init__.py index bebcdab4b6..6a1e7df767 100644 --- a/nipype/interfaces/afni/__init__.py +++ b/nipype/interfaces/afni/__init__.py @@ -22,7 +22,7 @@ from .utils import (ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket, Calc, Cat, CatMatvec, CenterMass, Copy, Dot, Edge3, Eval, FWHMx, MaskTool, Merge, Notes, NwarpApply, - OneDToolPy, + NwarpCat, OneDToolPy, Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize, Undump, ZCutUp, GCOR, Zcat, Zeropad) diff --git a/nipype/interfaces/afni/tests/test_auto_NwarpCat.py b/nipype/interfaces/afni/tests/test_auto_NwarpCat.py new file mode 100644 index 0000000000..6e5077e645 --- /dev/null +++ b/nipype/interfaces/afni/tests/test_auto_NwarpCat.py @@ -0,0 +1,56 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..utils import NwarpCat + + +def test_NwarpCat_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + expad=dict(argstr='-expad %d', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_files=dict(argstr='%s', + descr='list of tuples of 3D warps and associated functions', + mandatory=True, + position=-1, + ), + interp=dict(argstr='-interp %s', + ), + inv_warp=dict(argstr='-iwarp', + ), + num_threads=dict(nohash=True, + usedefault=True, + ), + out_file=dict(argstr='-prefix %s', + name_source='in_files', + name_template='%s_NwarpCat', + ), + outputtype=dict(), + space=dict(argstr='-space %s', + ), + terminal_output=dict(deprecated='1.0.0', + nohash=True, + ), + verb=dict(argstr='-verb', + ), + ) + inputs = NwarpCat.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_NwarpCat_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = NwarpCat.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/afni/utils.py b/nipype/interfaces/afni/utils.py index f7281542a6..8245578780 100644 --- a/nipype/interfaces/afni/utils.py +++ b/nipype/interfaces/afni/utils.py @@ -1588,6 +1588,123 @@ class NwarpApply(AFNICommandBase): input_spec = NwarpApplyInputSpec output_spec = AFNICommandOutputSpec + +class NwarpCatInputSpec(AFNICommandInputSpec): + in_files = traits.List( + traits.Either( + traits.File(), + traits.Tuple(traits.Enum('IDENT', 'INV', 'SQRT', 'SQRTINV'), + traits.File())), + descr="list of tuples of 3D warps and associated functions", + mandatory=True, + argstr="%s", + position=-1) + space = traits.String( + desc='string to attach to the output dataset as its atlas space ' + 'marker.', + argstr='-space %s') + inv_warp = traits.Bool( + desc='invert the final warp before output', + argstr='-iwarp') + interp = traits.Enum( + 'linear', 'quintic', 'wsinc5', + desc='specify a different interpolation method than might ' + 'be used for the warp', + argstr='-interp %s', + default='wsinc5') + expad = traits.Int( + desc='Pad the nonlinear warps by the given number of voxels voxels in ' + 'all directions. The warp displacements are extended by linear ' + 'extrapolation from the faces of the input grid..', + argstr='-expad %d') + out_file = File( + name_template='%s_NwarpCat', + desc='output image file name', + argstr='-prefix %s', + name_source='in_files') + verb = traits.Bool( + desc='be verbose', + argstr='-verb') + + +class NwarpCat(AFNICommand): + """Catenates (composes) 3D warps defined on a grid, OR via a matrix. + + .. note:: + + * All transformations are from DICOM xyz (in mm) to DICOM xyz. + + * Matrix warps are in files that end in '.1D' or in '.txt'. A matrix + warp file should have 12 numbers in it, as output (for example), by + '3dAllineate -1Dmatrix_save'. + + * Nonlinear warps are in dataset files (AFNI .HEAD/.BRIK or NIfTI .nii) + with 3 sub-bricks giving the DICOM order xyz grid displacements in mm. + + * If all the input warps are matrices, then the output is a matrix + and will be written to the file 'prefix.aff12.1D'. + Unless the prefix already contains the string '.1D', in which case + the filename is just the prefix. + + * If 'prefix' is just 'stdout', then the output matrix is written + to standard output. + In any of these cases, the output format is 12 numbers in one row. + + * If any of the input warps are datasets, they must all be defined on + the same 3D grid! + And of course, then the output will be a dataset on the same grid. + However, you can expand the grid using the '-expad' option. + + * The order of operations in the final (output) warp is, for the + case of 3 input warps: + + OUTPUT(x) = warp3( warp2( warp1(x) ) ) + + That is, warp1 is applied first, then warp2, et cetera. + The 3D x coordinates are taken from each grid location in the + first dataset defined on a grid. + + For complete details, see the `3dNwarpCat Documentation. + `_ + + Examples + ======== + + >>> from nipype.interfaces import afni + >>> nwarpcat = afni.NwarpCat() + >>> nwarpcat.inputs.in_files = ['Q25_warp+tlrc.HEAD', ('IDENT', 'structural.nii')] + >>> nwarpcat.inputs.out_file = 'Fred_total_WARP' + >>> nwarpcat.cmdline # doctest: +ALLOW_UNICODE + "3dNwarpCat -prefix Fred_total_WARP Q25_warp+tlrc.HEAD 'IDENT(structural.nii)'" + >>> res = nwarpcat.run() # doctest: +SKIP + + """ + _cmd = '3dNwarpCat' + input_spec = NwarpCatInputSpec + output_spec = AFNICommandOutputSpec + + def _format_arg(self, name, spec, value): + if name == 'in_files': + return spec.argstr % (' '.join(["'" + v[0] + "(" + v[1] + ")'" + if isinstance(v, tuple) else v + for v in value])) + return super(NwarpCat, self)._format_arg(name, spec, value) + + def _gen_filename(self, name): + if name == 'out_file': + return self._gen_fname(self.inputs.in_files[0][0], + suffix='_NwarpCat') + + def _list_outputs(self): + outputs = self.output_spec().get() + if isdefined(self.inputs.out_file): + outputs['out_file'] = os.path.abspath(self.inputs.out_file) + else: + outputs['out_file'] = os.path.abspath(self._gen_fname( + self.inputs.in_files[0], suffix='_NwarpCat+tlrc', ext='.HEAD')) + return outputs + + class OneDToolPyInputSpec(AFNIPythonCommandInputSpec): in_file = File( desc='input file to OneDTool',