diff --git a/CHANGES b/CHANGES index 2cd766c107..0c3a39b589 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ Next release ============ +* ENH: New interfaces for MRTrix3 (https://github.com/nipy/nipype/pull/1126) * ENH: New option in afni.3dRefit - zdel, ydel, zdel etc. (https://github.com/nipy/nipype/pull/1079) * FIX: ants.Registration composite transform outputs are no longer returned as lists (https://github.com/nipy/nipype/pull/1183) * BUG: ANTs Registration interface failed with multi-modal inputs diff --git a/nipype/interfaces/mrtrix3/__init__.py b/nipype/interfaces/mrtrix3/__init__.py new file mode 100644 index 0000000000..ec7d02aecb --- /dev/null +++ b/nipype/interfaces/mrtrix3/__init__.py @@ -0,0 +1,10 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +from utils import (Mesh2PVE, Generate5tt, BrainMask, TensorMetrics, + ComputeTDI, TCK2VTK) +from preprocess import ResponseSD, ACTPrepareFSL, ReplaceFSwithFIRST +from tracking import Tractography +from reconst import FitTensor, EstimateFOD +from connectivity import LabelConfig, BuildConnectome diff --git a/nipype/interfaces/mrtrix3/base.py b/nipype/interfaces/mrtrix3/base.py new file mode 100644 index 0000000000..18432d760a --- /dev/null +++ b/nipype/interfaces/mrtrix3/base.py @@ -0,0 +1,89 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File, + InputMultiPath) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + +from ... import logging +logger = logging.getLogger('interface') + + +class MRTrix3BaseInputSpec(CommandLineInputSpec): + nthreads = traits.Int( + argstr='-nthreads %d', desc='number of threads. if zero, the number' + ' of available cpus will be used', nohash=True) + # DW gradient table import options + grad_file = File(exists=True, argstr='-grad %s', + desc='dw gradient scheme (MRTrix format') + grad_fsl = traits.Tuple( + File(exists=True), File(exists=True), argstr='-fslgrad %s %s', + desc='(bvecs, bvals) dw gradient scheme (FSL format') + bval_scale = traits.Enum( + 'yes', 'no', argstr='-bvalue_scaling %s', + desc='specifies whether the b - values should be scaled by the square' + ' of the corresponding DW gradient norm, as often required for ' + 'multishell or DSI DW acquisition schemes. The default action ' + 'can also be set in the MRtrix config file, under the ' + 'BValueScaling entry. Valid choices are yes / no, true / ' + 'false, 0 / 1 (default: true).') + + in_bvec = File(exists=True, argstr='-fslgrad %s %s', + desc='bvecs file in FSL format') + in_bval = File(exists=True, desc='bvals file in FSL format') + + +class MRTrix3Base(CommandLine): + + def _format_arg(self, name, trait_spec, value): + if name == 'nthreads' and value == 0: + value = 1 + try: + from multiprocessing import cpu_count + value = cpu_count() + except: + logger.warn('Number of threads could not be computed') + pass + return trait_spec.argstr % value + + if name == 'in_bvec': + return trait_spec.argstr % (value, self.inputs.in_bval) + + return super(MRTrix3Base, self)._format_arg(name, trait_spec, value) + + def _parse_inputs(self, skip=None): + if skip is None: + skip = [] + + try: + if (isdefined(self.inputs.grad_file) or + isdefined(self.inputs.grad_fsl)): + skip += ['in_bvec', 'in_bval'] + + is_bvec = isdefined(self.inputs.in_bvec) + is_bval = isdefined(self.inputs.in_bval) + if is_bvec or is_bval: + if not is_bvec or not is_bval: + raise RuntimeError('If using bvecs and bvals inputs, both' + 'should be defined') + skip += ['in_bval'] + except AttributeError: + pass + + return super(MRTrix3Base, self)._parse_inputs(skip=skip) diff --git a/nipype/interfaces/mrtrix3/connectivity.py b/nipype/interfaces/mrtrix3/connectivity.py new file mode 100644 index 0000000000..af09ae36bc --- /dev/null +++ b/nipype/interfaces/mrtrix3/connectivity.py @@ -0,0 +1,189 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from base import MRTrix3BaseInputSpec, MRTrix3Base +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + + +class BuildConnectomeInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-3, + desc='input tractography') + in_parc = File(exists=True, argstr='%s', position=-2, + desc='parcellation file') + out_file = File( + 'connectome.csv', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file after processing') + + nthreads = traits.Int( + argstr='-nthreads %d', desc='number of threads. if zero, the number' + ' of available cpus will be used', nohash=True) + + vox_lookup = traits.Bool( + argstr='-assignment_voxel_lookup', + desc='use a simple voxel lookup value at each streamline endpoint') + search_radius = traits.Float( + argstr='-assignment_radial_search %f', + desc='perform a radial search from each streamline endpoint to locate ' + 'the nearest node. Argument is the maximum radius in mm; if no node is' + ' found within this radius, the streamline endpoint is not assigned to' + ' any node.') + search_reverse = traits.Float( + argstr='-assignment_reverse_search %f', + desc='traverse from each streamline endpoint inwards along the ' + 'streamline, in search of the last node traversed by the streamline. ' + 'Argument is the maximum traversal length in mm (set to 0 to allow ' + 'search to continue to the streamline midpoint).') + search_forward = traits.Float( + argstr='-assignment_forward_search %f', + desc='project the streamline forwards from the endpoint in search of a' + 'parcellation node voxel. Argument is the maximum traversal length in ' + 'mm.') + + metric = traits.Enum( + 'count', 'meanlength', 'invlength', 'invnodevolume', 'mean_scalar', + 'invlength_invnodevolume', argstr='-metric %s', desc='specify the edge' + ' weight metric') + + in_scalar = File( + exists=True, argstr='-image %s', desc='provide the associated image ' + 'for the mean_scalar metric') + + in_weights = File( + exists=True, argstr='-tck_weights_in %s', desc='specify a text scalar ' + 'file containing the streamline weights') + + keep_unassigned = traits.Bool( + argstr='-keep_unassigned', desc='By default, the program discards the' + ' information regarding those streamlines that are not successfully ' + 'assigned to a node pair. Set this option to keep these values (will ' + 'be the first row/column in the output matrix)') + zero_diagonal = traits.Bool( + argstr='-zero_diagonal', desc='set all diagonal entries in the matrix ' + 'to zero (these represent streamlines that connect to the same node at' + ' both ends)') + + +class BuildConnectomeOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class BuildConnectome(MRTrix3Base): + + """ + Generate a connectome matrix from a streamlines file and a node + parcellation image + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> mat = mrt.BuildConnectome() + >>> mat.inputs.in_file = 'tracks.tck' + >>> mat.inputs.in_parc = 'aparc+aseg.nii' + >>> mat.cmdline # doctest: +ELLIPSIS + 'tck2connectome tracks.tck aparc+aseg.nii connectome.csv' + >>> mat.run() # doctest: +SKIP + """ + + _cmd = 'tck2connectome' + input_spec = BuildConnectomeInputSpec + output_spec = BuildConnectomeOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class LabelConfigInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-3, + desc='input anatomical image') + in_config = File(exists=True, argstr='%s', position=-2, + desc='connectome configuration file') + out_file = File( + 'parcellation.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file after processing') + + lut_basic = File(argstr='-lut_basic %s', desc='get information from ' + 'a basic lookup table consisting of index / name pairs') + lut_fs = File(argstr='-lut_freesurfer %s', desc='get information from ' + 'a FreeSurfer lookup table(typically "FreeSurferColorLUT' + '.txt")') + lut_aal = File(argstr='-lut_aal %s', desc='get information from the AAL ' + 'lookup table (typically "ROI_MNI_V4.txt")') + lut_itksnap = File(argstr='-lut_itksnap %s', desc='get information from an' + ' ITK - SNAP lookup table(this includes the IIT atlas ' + 'file "LUT_GM.txt")') + spine = File(argstr='-spine %s', desc='provide a manually-defined ' + 'segmentation of the base of the spine where the streamlines' + ' terminate, so that this can become a node in the connection' + ' matrix.') + nthreads = traits.Int( + argstr='-nthreads %d', desc='number of threads. if zero, the number' + ' of available cpus will be used', nohash=True) + + +class LabelConfigOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class LabelConfig(MRTrix3Base): + + """ + Re-configure parcellation to be incrementally defined. + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> labels = mrt.LabelConfig() + >>> labels.inputs.in_file = 'aparc+aseg.nii' + >>> labels.inputs.in_config = 'mrtrix3_labelconfig.txt' + >>> labels.cmdline # doctest: +ELLIPSIS + 'labelconfig aparc+aseg.nii mrtrix3_labelconfig.txt parcellation.mif' + >>> labels.run() # doctest: +SKIP + """ + + _cmd = 'labelconfig' + input_spec = LabelConfigInputSpec + output_spec = LabelConfigOutputSpec + + def _parse_inputs(self, skip=None): + if skip is None: + skip = [] + + if not isdefined(self.inputs.in_config): + from distutils.spawn import find_executable + path = find_executable(self._cmd) + if path is None: + path = os.getenv(MRTRIX3_HOME, '/opt/mrtrix3') + else: + path = op.dirname(op.dirname(path)) + + self.inputs.in_config = op.join( + path, 'src/dwi/tractography/connectomics/' + 'example_configs/fs_default.txt') + + return super(LabelConfig, self)._parse_inputs(skip=skip) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py new file mode 100644 index 0000000000..aea3ef97f9 --- /dev/null +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -0,0 +1,202 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from base import MRTrix3BaseInputSpec, MRTrix3Base +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + + +class ResponseSDInputSpec(MRTrix3BaseInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input diffusion weighted images') + + out_file = File( + 'response.txt', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file containing SH coefficients') + + # DW Shell selection options + shell = traits.List(traits.Float, sep=',', argstr='-shell %s', + desc='specify one or more dw gradient shells') + in_mask = File(exists=True, argstr='-mask %s', + desc='provide initial mask image') + max_sh = traits.Int(8, argstr='-lmax %d', + desc='maximum harmonic degree of response function') + out_sf = File('sf_mask.nii.gz', argstr='-sf %s', + desc='write a mask containing single-fibre voxels') + test_all = traits.Bool(False, argstr='-test_all', + desc='re-test all voxels at every iteration') + + # Optimization + iterations = traits.Int(0, argstr='-max_iters %d', + desc='maximum number of iterations per pass') + max_change = traits.Float( + argstr='-max_change %f', + desc=('maximum percentile change in any response function coefficient;' + ' if no individual coefficient changes by more than this ' + 'fraction, the algorithm is terminated.')) + + # Thresholds + vol_ratio = traits.Float( + .15, argstr='-volume_ratio %f', + desc=('maximal volume ratio between the sum of all other positive' + ' lobes in the voxel and the largest FOD lobe')) + disp_mult = traits.Float( + 1., argstr='-dispersion_multiplier %f', + desc=('dispersion of FOD lobe must not exceed some threshold as ' + 'determined by this multiplier and the FOD dispersion in other ' + 'single-fibre voxels. The threshold is: (mean + (multiplier * ' + '(mean - min))); default = 1.0. Criterion is only applied in ' + 'second pass of RF estimation.')) + int_mult = traits.Float( + 2., argstr='-integral_multiplier %f', + desc=('integral of FOD lobe must not be outside some range as ' + 'determined by this multiplier and FOD lobe integral in other' + ' single-fibre voxels. The range is: (mean +- (multiplier * ' + 'stdev)); default = 2.0. Criterion is only applied in second ' + 'pass of RF estimation.')) + + +class ResponseSDOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + out_sf = File(desc=('mask containing single-fibre voxels')) + + +class ResponseSD(MRTrix3Base): + + """ + Generate an appropriate response function from the image data for + spherical deconvolution. + + .. [1] Tax, C. M.; Jeurissen, B.; Vos, S. B.; Viergever, M. A. and + Leemans, A., Recursive calibration of the fiber response function + for spherical deconvolution of diffusion MRI data. NeuroImage, + 2014, 86, 67-80 + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> resp = mrt.ResponseSD() + >>> resp.inputs.in_file = 'dwi.mif' + >>> resp.inputs.in_mask = 'mask.nii.gz' + >>> resp.inputs.grad_fsl = ('bvecs', 'bvals') + >>> resp.cmdline # doctest: +ELLIPSIS + 'dwi2response -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif response.txt' + >>> resp.run() # doctest: +SKIP + """ + + _cmd = 'dwi2response' + input_spec = ResponseSDInputSpec + output_spec = ResponseSDOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + + if isdefined(self.inputs.out_sf): + outputs['out_sf'] = op.abspath(self.inputs.out_sf) + return outputs + + +class ACTPrepareFSLInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input anatomical image') + + out_file = File( + 'act_5tt.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file after processing') + + +class ACTPrepareFSLOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class ACTPrepareFSL(CommandLine): + + """ + Generate anatomical information necessary for Anatomically + Constrained Tractography (ACT). + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> prep = mrt.ACTPrepareFSL() + >>> prep.inputs.in_file = 'T1.nii.gz' + >>> prep.cmdline # doctest: +ELLIPSIS + 'act_anat_prepare_fsl T1.nii.gz act_5tt.mif' + >>> prep.run() # doctest: +SKIP + """ + + _cmd = 'act_anat_prepare_fsl' + input_spec = ACTPrepareFSLInputSpec + output_spec = ACTPrepareFSLOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class ReplaceFSwithFIRSTInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-4, + desc='input anatomical image') + in_t1w = File(exists=True, argstr='%s', mandatory=True, position=-3, + desc='input T1 image') + in_config = File(exists=True, argstr='%s', position=-2, + desc='connectome configuration file') + + out_file = File( + 'aparc+first.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file after processing') + + +class ReplaceFSwithFIRSTOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class ReplaceFSwithFIRST(CommandLine): + + """ + Replace deep gray matter structures segmented with FSL FIRST in a + FreeSurfer parcellation. + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> prep = mrt.ReplaceFSwithFIRST() + >>> prep.inputs.in_file = 'aparc+aseg.nii' + >>> prep.inputs.in_t1w = 'T1.nii.gz' + >>> prep.inputs.in_config = 'mrtrix3_labelconfig.txt' + >>> prep.cmdline # doctest: +ELLIPSIS + 'fs_parc_replace_sgm_first aparc+aseg.nii T1.nii.gz \ +mrtrix3_labelconfig.txt aparc+first.mif' + >>> prep.run() # doctest: +SKIP + """ + + _cmd = 'fs_parc_replace_sgm_first' + input_spec = ReplaceFSwithFIRSTInputSpec + output_spec = ReplaceFSwithFIRSTOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/mrtrix3/reconst.py b/nipype/interfaces/mrtrix3/reconst.py new file mode 100644 index 0000000000..2916b4bdac --- /dev/null +++ b/nipype/interfaces/mrtrix3/reconst.py @@ -0,0 +1,193 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from base import MRTrix3BaseInputSpec, MRTrix3Base +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File, + InputMultiPath) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + + +class FitTensorInputSpec(MRTrix3BaseInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input diffusion weighted images') + out_file = File( + 'dti.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='the output diffusion tensor image') + + # General options + in_mask = File(exists=True, argstr='-mask %s', + desc=('only perform computation within the specified ' + 'binary brain mask image')) + method = traits.Enum( + 'nonlinear', 'loglinear', 'sech', 'rician', argstr='-method %s', + desc=('select method used to perform the fitting')) + reg_term = traits.Float( + 5.e3, argstr='-regularisation %f', + desc=('specify the strength of the regularisation term on the ' + 'magnitude of the tensor elements (default = 5000). This ' + 'only applies to the non-linear methods')) + + +class FitTensorOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output DTI file') + + +class FitTensor(MRTrix3Base): + + """ + Convert diffusion-weighted images to tensor images + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> tsr = mrt.FitTensor() + >>> tsr.inputs.in_file = 'dwi.mif' + >>> tsr.inputs.in_mask = 'mask.nii.gz' + >>> tsr.inputs.grad_fsl = ('bvecs', 'bvals') + >>> tsr.cmdline # doctest: +ELLIPSIS + 'dwi2tensor -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif dti.mif' + >>> tsr.run() # doctest: +SKIP + """ + + _cmd = 'dwi2tensor' + input_spec = FitTensorInputSpec + output_spec = FitTensorOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class EstimateFODInputSpec(MRTrix3BaseInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-3, + desc='input diffusion weighted images') + response = File( + exists=True, argstr='%s', mandatory=True, position=-2, + desc=('a text file containing the diffusion-weighted signal response ' + 'function coefficients for a single fibre population')) + out_file = File( + 'fods.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc=('the output spherical harmonics coefficients' + ' image')) + + # DW Shell selection options + shell = traits.List(traits.Float, sep=',', argstr='-shell %s', + desc='specify one or more dw gradient shells') + + # Spherical deconvolution options + max_sh = traits.Int(8, argstr='-lmax %d', + desc='maximum harmonic degree of response function') + in_mask = File(exists=True, argstr='-mask %s', + desc='provide initial mask image') + in_dirs = File( + exists=True, argstr='-directions %s', + desc=('specify the directions over which to apply the non-negativity ' + 'constraint (by default, the built-in 300 direction set is ' + 'used). These should be supplied as a text file containing the ' + '[ az el ] pairs for the directions.')) + sh_filter = File( + exists=True, argstr='-filter %s', + desc=('the linear frequency filtering parameters used for the initial ' + 'linear spherical deconvolution step (default = [ 1 1 1 0 0 ]). ' + 'These should be supplied as a text file containing the ' + 'filtering coefficients for each even harmonic order.')) + + neg_lambda = traits.Float( + 1.0, argstr='-neg_lambda %f', + desc=('the regularisation parameter lambda that controls the strength' + ' of the non-negativity constraint')) + thres = traits.Float( + 0.0, argstr='-threshold %f', + desc=('the threshold below which the amplitude of the FOD is assumed ' + 'to be zero, expressed as an absolute amplitude')) + + n_iter = traits.Int( + 50, argstr='-niter %d', desc=('the maximum number of iterations ' + 'to perform for each voxel')) + + +class EstimateFODOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class EstimateFOD(MRTrix3Base): + + """ + Convert diffusion-weighted images to tensor images + + Note that this program makes use of implied symmetries in the diffusion + profile. First, the fact the signal attenuation profile is real implies + that it has conjugate symmetry, i.e. Y(l,-m) = Y(l,m)* (where * denotes + the complex conjugate). Second, the diffusion profile should be + antipodally symmetric (i.e. S(x) = S(-x)), implying that all odd l + components should be zero. Therefore, this program only computes the even + elements. + + Note that the spherical harmonics equations used here differ slightly from + those conventionally used, in that the (-1)^m factor has been omitted. + This should be taken into account in all subsequent calculations. + The spherical harmonic coefficients are stored as follows. First, since + the signal attenuation profile is real, it has conjugate symmetry, i.e. + Y(l,-m) = Y(l,m)* (where * denotes the complex conjugate). Second, the + diffusion profile should be antipodally symmetric (i.e. S(x) = S(-x)), + implying that all odd l components should be zero. Therefore, only the + even elements are computed. + + Note that the spherical harmonics equations used here differ slightly from + those conventionally used, in that the (-1)^m factor has been omitted. + This should be taken into account in all subsequent calculations. + Each volume in the output image corresponds to a different spherical + harmonic component. Each volume will correspond to the following: + + volume 0: l = 0, m = 0 + volume 1: l = 2, m = -2 (imaginary part of m=2 SH) + volume 2: l = 2, m = -1 (imaginary part of m=1 SH) + volume 3: l = 2, m = 0 + volume 4: l = 2, m = 1 (real part of m=1 SH) + volume 5: l = 2, m = 2 (real part of m=2 SH) + etc... + + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> fod = mrt.EstimateFOD() + >>> fod.inputs.in_file = 'dwi.mif' + >>> fod.inputs.response = 'response.txt' + >>> fod.inputs.in_mask = 'mask.nii.gz' + >>> fod.inputs.grad_fsl = ('bvecs', 'bvals') + >>> fod.cmdline # doctest: +ELLIPSIS + 'dwi2fod -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif response.txt\ + fods.mif' + >>> fod.run() # doctest: +SKIP + """ + + _cmd = 'dwi2fod' + input_spec = EstimateFODInputSpec + output_spec = EstimateFODOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_ACTPrepareFSL.py b/nipype/interfaces/mrtrix3/tests/test_auto_ACTPrepareFSL.py new file mode 100644 index 0000000000..7a8c4a54a0 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_ACTPrepareFSL.py @@ -0,0 +1,40 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.preprocess import ACTPrepareFSL + +def test_ACTPrepareFSL_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = ACTPrepareFSL.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_ACTPrepareFSL_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = ACTPrepareFSL.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py b/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py new file mode 100644 index 0000000000..58b6184044 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py @@ -0,0 +1,52 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import BrainMask + +def test_BrainMask_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bval_scale=dict(argstr='-bvalue_scaling %s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + grad_file=dict(argstr='-grad %s', + ), + grad_fsl=dict(argstr='-fslgrad %s %s', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_bval=dict(), + in_bvec=dict(argstr='-fslgrad %s %s', + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = BrainMask.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_BrainMask_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = BrainMask.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_BuildConnectome.py b/nipype/interfaces/mrtrix3/tests/test_auto_BuildConnectome.py new file mode 100644 index 0000000000..68ea51ede8 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_BuildConnectome.py @@ -0,0 +1,64 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.connectivity import BuildConnectome + +def test_BuildConnectome_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-3, + ), + in_parc=dict(argstr='%s', + position=-2, + ), + in_scalar=dict(argstr='-image %s', + ), + in_weights=dict(argstr='-tck_weights_in %s', + ), + keep_unassigned=dict(argstr='-keep_unassigned', + ), + metric=dict(argstr='-metric %s', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + search_forward=dict(argstr='-assignment_forward_search %f', + ), + search_radius=dict(argstr='-assignment_radial_search %f', + ), + search_reverse=dict(argstr='-assignment_reverse_search %f', + ), + terminal_output=dict(nohash=True, + ), + vox_lookup=dict(argstr='-assignment_voxel_lookup', + ), + zero_diagonal=dict(argstr='-zero_diagonal', + ), + ) + inputs = BuildConnectome.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_BuildConnectome_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = BuildConnectome.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_ComputeTDI.py b/nipype/interfaces/mrtrix3/tests/test_auto_ComputeTDI.py new file mode 100644 index 0000000000..25c36d0265 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_ComputeTDI.py @@ -0,0 +1,75 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import ComputeTDI + +def test_ComputeTDI_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + contrast=dict(argstr='-constrast %s', + ), + data_type=dict(argstr='-datatype %s', + ), + dixel=dict(argstr='-dixel %s', + ), + ends_only=dict(argstr='-ends_only', + ), + environ=dict(nohash=True, + usedefault=True, + ), + fwhm_tck=dict(argstr='-fwhm_tck %f', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + in_map=dict(argstr='-image %s', + ), + map_zero=dict(argstr='-map_zero', + ), + max_tod=dict(argstr='-tod %d', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + position=-1, + usedefault=True, + ), + precise=dict(argstr='-precise', + ), + reference=dict(argstr='-template %s', + ), + stat_tck=dict(argstr='-stat_tck %s', + ), + stat_vox=dict(argstr='-stat_vox %s', + ), + tck_weights=dict(argstr='-tck_weights_in %s', + ), + terminal_output=dict(nohash=True, + ), + upsample=dict(argstr='-upsample %d', + ), + use_dec=dict(argstr='-dec', + ), + vox_size=dict(argstr='-vox %s', + sep=',', + ), + ) + inputs = ComputeTDI.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_ComputeTDI_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = ComputeTDI.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_EstimateFOD.py b/nipype/interfaces/mrtrix3/tests/test_auto_EstimateFOD.py new file mode 100644 index 0000000000..10ef4b33d0 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_EstimateFOD.py @@ -0,0 +1,73 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.reconst import EstimateFOD + +def test_EstimateFOD_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bval_scale=dict(argstr='-bvalue_scaling %s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + grad_file=dict(argstr='-grad %s', + ), + grad_fsl=dict(argstr='-fslgrad %s %s', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_bval=dict(), + in_bvec=dict(argstr='-fslgrad %s %s', + ), + in_dirs=dict(argstr='-directions %s', + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-3, + ), + in_mask=dict(argstr='-mask %s', + ), + max_sh=dict(argstr='-lmax %d', + ), + n_iter=dict(argstr='-niter %d', + ), + neg_lambda=dict(argstr='-neg_lambda %f', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + response=dict(argstr='%s', + mandatory=True, + position=-2, + ), + sh_filter=dict(argstr='-filter %s', + ), + shell=dict(argstr='-shell %s', + sep=',', + ), + terminal_output=dict(nohash=True, + ), + thres=dict(argstr='-threshold %f', + ), + ) + inputs = EstimateFOD.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_EstimateFOD_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = EstimateFOD.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py b/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py new file mode 100644 index 0000000000..2dc23a5a3a --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py @@ -0,0 +1,58 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.reconst import FitTensor + +def test_FitTensor_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bval_scale=dict(argstr='-bvalue_scaling %s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + grad_file=dict(argstr='-grad %s', + ), + grad_fsl=dict(argstr='-fslgrad %s %s', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_bval=dict(), + in_bvec=dict(argstr='-fslgrad %s %s', + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + in_mask=dict(argstr='-mask %s', + ), + method=dict(argstr='-method %s', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + reg_term=dict(argstr='-regularisation %f', + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = FitTensor.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_FitTensor_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = FitTensor.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py b/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py new file mode 100644 index 0000000000..a6e4e76989 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py @@ -0,0 +1,43 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import Generate5tt + +def test_Generate5tt_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_fast=dict(argstr='%s', + mandatory=True, + position=-3, + ), + in_first=dict(argstr='%s', + position=-2, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = Generate5tt.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_Generate5tt_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = Generate5tt.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_LabelConfig.py b/nipype/interfaces/mrtrix3/tests/test_auto_LabelConfig.py new file mode 100644 index 0000000000..f559920ab1 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_LabelConfig.py @@ -0,0 +1,56 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.connectivity import LabelConfig + +def test_LabelConfig_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_config=dict(argstr='%s', + position=-2, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-3, + ), + lut_aal=dict(argstr='-lut_aal %s', + ), + lut_basic=dict(argstr='-lut_basic %s', + ), + lut_fs=dict(argstr='-lut_freesurfer %s', + ), + lut_itksnap=dict(argstr='-lut_itksnap %s', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + spine=dict(argstr='-spine %s', + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = LabelConfig.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_LabelConfig_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = LabelConfig.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_MRTrix3Base.py b/nipype/interfaces/mrtrix3/tests/test_auto_MRTrix3Base.py new file mode 100644 index 0000000000..3595f3acd9 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_MRTrix3Base.py @@ -0,0 +1,22 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.base import MRTrix3Base + +def test_MRTrix3Base_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = MRTrix3Base.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_Mesh2PVE.py b/nipype/interfaces/mrtrix3/tests/test_auto_Mesh2PVE.py new file mode 100644 index 0000000000..a019f52eb7 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_Mesh2PVE.py @@ -0,0 +1,46 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import Mesh2PVE + +def test_Mesh2PVE_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-3, + ), + in_first=dict(argstr='-first %s', + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + reference=dict(argstr='%s', + mandatory=True, + position=-2, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = Mesh2PVE.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_Mesh2PVE_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = Mesh2PVE.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_ReplaceFSwithFIRST.py b/nipype/interfaces/mrtrix3/tests/test_auto_ReplaceFSwithFIRST.py new file mode 100644 index 0000000000..fd5b38bc42 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_ReplaceFSwithFIRST.py @@ -0,0 +1,47 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.preprocess import ReplaceFSwithFIRST + +def test_ReplaceFSwithFIRST_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_config=dict(argstr='%s', + position=-2, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-4, + ), + in_t1w=dict(argstr='%s', + mandatory=True, + position=-3, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = ReplaceFSwithFIRST.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_ReplaceFSwithFIRST_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = ReplaceFSwithFIRST.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py b/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py new file mode 100644 index 0000000000..6bbc14c195 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py @@ -0,0 +1,74 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.preprocess import ResponseSD + +def test_ResponseSD_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bval_scale=dict(argstr='-bvalue_scaling %s', + ), + disp_mult=dict(argstr='-dispersion_multiplier %f', + ), + environ=dict(nohash=True, + usedefault=True, + ), + grad_file=dict(argstr='-grad %s', + ), + grad_fsl=dict(argstr='-fslgrad %s %s', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_bval=dict(), + in_bvec=dict(argstr='-fslgrad %s %s', + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + in_mask=dict(argstr='-mask %s', + ), + int_mult=dict(argstr='-integral_multiplier %f', + ), + iterations=dict(argstr='-max_iters %d', + ), + max_change=dict(argstr='-max_change %f', + ), + max_sh=dict(argstr='-lmax %d', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + out_sf=dict(argstr='-sf %s', + ), + shell=dict(argstr='-shell %s', + sep=',', + ), + terminal_output=dict(nohash=True, + ), + test_all=dict(argstr='-test_all', + ), + vol_ratio=dict(argstr='-volume_ratio %f', + ), + ) + inputs = ResponseSD.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_ResponseSD_outputs(): + output_map = dict(out_file=dict(), + out_sf=dict(), + ) + outputs = ResponseSD.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_TCK2VTK.py b/nipype/interfaces/mrtrix3/tests/test_auto_TCK2VTK.py new file mode 100644 index 0000000000..6e7c5c193f --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_TCK2VTK.py @@ -0,0 +1,46 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import TCK2VTK + +def test_TCK2VTK_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + position=-1, + usedefault=True, + ), + reference=dict(argstr='-image %s', + ), + terminal_output=dict(nohash=True, + ), + voxel=dict(argstr='-image %s', + ), + ) + inputs = TCK2VTK.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_TCK2VTK_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = TCK2VTK.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_TensorMetrics.py b/nipype/interfaces/mrtrix3/tests/test_auto_TensorMetrics.py new file mode 100644 index 0000000000..4c0f6f97eb --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_TensorMetrics.py @@ -0,0 +1,53 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.utils import TensorMetrics + +def test_TensorMetrics_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + component=dict(argstr='-num %s', + sep=',', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-1, + ), + in_mask=dict(argstr='-mask %s', + ), + modulate=dict(argstr='-modulate %s', + ), + out_adc=dict(argstr='-adc %s', + ), + out_eval=dict(argstr='-value %s', + ), + out_evec=dict(argstr='-vector %s', + ), + out_fa=dict(argstr='-fa %s', + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = TensorMetrics.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_TensorMetrics_outputs(): + output_map = dict(out_adc=dict(), + out_eval=dict(), + out_evec=dict(), + out_fa=dict(), + ) + outputs = TensorMetrics.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py b/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py new file mode 100644 index 0000000000..03154c5d8a --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py @@ -0,0 +1,125 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from nipype.testing import assert_equal +from nipype.interfaces.mrtrix3.tracking import Tractography + +def test_Tractography_inputs(): + input_map = dict(act_file=dict(argstr='-act %s', + ), + algorithm=dict(argstr='-algorithm %s', + usedefault=True, + ), + angle=dict(argstr='-angle %f', + ), + args=dict(argstr='%s', + ), + backtrack=dict(argstr='-backtrack', + ), + bval_scale=dict(argstr='-bvalue_scaling %s', + ), + crop_at_gmwmi=dict(argstr='-crop_at_gmwmi', + ), + cutoff=dict(argstr='-cutoff %f', + ), + cutoff_init=dict(argstr='-initcutoff %f', + ), + downsample=dict(argstr='-downsample %f', + ), + environ=dict(nohash=True, + usedefault=True, + ), + grad_file=dict(argstr='-grad %s', + ), + grad_fsl=dict(argstr='-fslgrad %s %s', + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_bval=dict(), + in_bvec=dict(argstr='-fslgrad %s %s', + ), + in_file=dict(argstr='%s', + mandatory=True, + position=-2, + ), + init_dir=dict(argstr='-initdirection %f,%f,%f', + ), + max_length=dict(argstr='-maxlength %f', + ), + max_seed_attempts=dict(argstr='-max_seed_attempts %d', + ), + max_tracks=dict(argstr='-maxnum %d', + ), + min_length=dict(argstr='-minlength %f', + ), + n_samples=dict(argstr='-samples %d', + ), + n_tracks=dict(argstr='-number %d', + ), + n_trials=dict(argstr='-trials %d', + ), + noprecompt=dict(argstr='-noprecomputed', + ), + nthreads=dict(argstr='-nthreads %d', + nohash=True, + ), + out_file=dict(argstr='%s', + mandatory=True, + position=-1, + usedefault=True, + ), + out_seeds=dict(argstr='-output_seeds %s', + ), + power=dict(argstr='-power %d', + ), + roi_excl=dict(argstr='-exclude %s', + ), + roi_incl=dict(argstr='-include %s', + ), + roi_mask=dict(argstr='-mask %s', + ), + seed_dynamic=dict(argstr='-seed_dynamic %s', + ), + seed_gmwmi=dict(argstr='-seed_gmwmi %s', + requires=['act_file'], + ), + seed_grid_voxel=dict(argstr='-seed_grid_per_voxel %s %d', + xor=['seed_image', 'seed_rnd_voxel'], + ), + seed_image=dict(argstr='-seed_image %s', + ), + seed_rejection=dict(argstr='-seed_rejection %s', + ), + seed_rnd_voxel=dict(argstr='-seed_random_per_voxel %s %d', + xor=['seed_image', 'seed_grid_voxel'], + ), + seed_sphere=dict(argstr='-seed_sphere %f,%f,%f,%f', + ), + sph_trait=dict(argstr='%f,%f,%f,%f', + ), + step_size=dict(argstr='-step %f', + ), + stop=dict(argstr='-stop', + ), + terminal_output=dict(nohash=True, + ), + unidirectional=dict(argstr='-unidirectional', + ), + use_rk4=dict(argstr='-rk4', + ), + ) + inputs = Tractography.input_spec() + + for key, metadata in input_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(inputs.traits()[key], metakey), value + +def test_Tractography_outputs(): + output_map = dict(out_file=dict(), + out_seeds=dict(), + ) + outputs = Tractography.output_spec() + + for key, metadata in output_map.items(): + for metakey, value in metadata.items(): + yield assert_equal, getattr(outputs.traits()[key], metakey), value + diff --git a/nipype/interfaces/mrtrix3/tracking.py b/nipype/interfaces/mrtrix3/tracking.py new file mode 100644 index 0000000000..b90ad6aab7 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tracking.py @@ -0,0 +1,253 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from base import MRTrix3BaseInputSpec, MRTrix3Base +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + + +class TractographyInputSpec(MRTrix3BaseInputSpec): + sph_trait = traits.Tuple(traits.Float, traits.Float, traits.Float, + traits.Float, argstr='%f,%f,%f,%f') + + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input file to be processed') + + out_file = File('tracked.tck', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file containing tracks') + + algorithm = traits.Enum( + 'iFOD2', 'FACT', 'iFOD1', 'Nulldist', 'SD_Stream', 'Tensor_Det', + 'Tensor_Prob', usedefault=True, argstr='-algorithm %s', + desc='tractography algorithm to be used') + + # ROIs processing options + roi_incl = traits.Either( + File(exists=True), sph_trait, argstr='-include %s', + desc=('specify an inclusion region of interest, streamlines must' + ' traverse ALL inclusion regions to be accepted')) + roi_excl = traits.Either( + File(exists=True), sph_trait, argstr='-exclude %s', + desc=('specify an exclusion region of interest, streamlines that' + ' enter ANY exclude region will be discarded')) + roi_mask = traits.Either( + File(exists=True), sph_trait, argstr='-mask %s', + desc=('specify a masking region of interest. If defined,' + 'streamlines exiting the mask will be truncated')) + + # Streamlines tractography options + step_size = traits.Float( + argstr='-step %f', + desc=('set the step size of the algorithm in mm (default is 0.1' + ' x voxelsize; for iFOD2: 0.5 x voxelsize)')) + angle = traits.Float( + argstr='-angle %f', + desc=('set the maximum angle between successive steps (default ' + 'is 90deg x stepsize / voxelsize)')) + n_tracks = traits.Int( + argstr='-number %d', + desc=('set the desired number of tracks. The program will continue' + ' to generate tracks until this number of tracks have been ' + 'selected and written to the output file')) + max_tracks = traits.Int( + argstr='-maxnum %d', + desc=('set the maximum number of tracks to generate. The program ' + 'will not generate more tracks than this number, even if ' + 'the desired number of tracks hasn\'t yet been reached ' + '(default is 100 x number)')) + max_length = traits.Float( + argstr='-maxlength %f', + desc=('set the maximum length of any track in mm (default is ' + '100 x voxelsize)')) + min_length = traits.Float( + argstr='-minlength %f', + desc=('set the minimum length of any track in mm (default is ' + '5 x voxelsize)')) + cutoff = traits.Float( + argstr='-cutoff %f', + desc=('set the FA or FOD amplitude cutoff for terminating ' + 'tracks (default is 0.1)')) + cutoff_init = traits.Float( + argstr='-initcutoff %f', + desc=('set the minimum FA or FOD amplitude for initiating ' + 'tracks (default is the same as the normal cutoff)')) + n_trials = traits.Int( + argstr='-trials %d', + desc=('set the maximum number of sampling trials at each point' + ' (only used for probabilistic tracking)')) + unidirectional = traits.Bool( + argstr='-unidirectional', + desc=('track from the seed point in one direction only ' + '(default is to track in both directions)')) + init_dir = traits.Tuple( + traits.Float, traits.Float, traits.Float, + argstr='-initdirection %f,%f,%f', + desc=('specify an initial direction for the tracking (this ' + 'should be supplied as a vector of 3 comma-separated values')) + noprecompt = traits.Bool( + argstr='-noprecomputed', + desc=('do NOT pre-compute legendre polynomial values. Warning: this ' + 'will slow down the algorithm by a factor of approximately 4')) + power = traits.Int( + argstr='-power %d', + desc=('raise the FOD to the power specified (default is 1/nsamples)')) + n_samples = traits.Int( + 4, argstr='-samples %d', + desc=('set the number of FOD samples to take per step for the 2nd ' + 'order (iFOD2) method')) + use_rk4 = traits.Bool( + argstr='-rk4', + desc=('use 4th-order Runge-Kutta integration (slower, but eliminates' + ' curvature overshoot in 1st-order deterministic methods)')) + stop = traits.Bool( + argstr='-stop', + desc=('stop propagating a streamline once it has traversed all ' + 'include regions')) + downsample = traits.Float( + argstr='-downsample %f', + desc='downsample the generated streamlines to reduce output file size') + + # Anatomically-Constrained Tractography options + act_file = File( + exists=True, argstr='-act %s', + desc=('use the Anatomically-Constrained Tractography framework during' + ' tracking; provided image must be in the 5TT ' + '(five - tissue - type) format')) + backtrack = traits.Bool(argstr='-backtrack', + desc='allow tracks to be truncated') + + crop_at_gmwmi = traits.Bool( + argstr='-crop_at_gmwmi', + desc=('crop streamline endpoints more ' + 'precisely as they cross the GM-WM interface')) + + # Tractography seeding options + seed_sphere = traits.Tuple( + traits.Float, traits.Float, traits.Float, traits.Float, + argstr='-seed_sphere %f,%f,%f,%f', desc='spherical seed') + seed_image = File(exists=True, argstr='-seed_image %s', + desc='seed streamlines entirely at random within mask') + seed_rnd_voxel = traits.Tuple( + File(exists=True), traits.Int(), + argstr='-seed_random_per_voxel %s %d', + xor=['seed_image', 'seed_grid_voxel'], + desc=('seed a fixed number of streamlines per voxel in a mask ' + 'image; random placement of seeds in each voxel')) + seed_grid_voxel = traits.Tuple( + File(exists=True), traits.Int(), + argstr='-seed_grid_per_voxel %s %d', + xor=['seed_image', 'seed_rnd_voxel'], + desc=('seed a fixed number of streamlines per voxel in a mask ' + 'image; place seeds on a 3D mesh grid (grid_size argument ' + 'is per axis; so a grid_size of 3 results in 27 seeds per' + ' voxel)')) + seed_rejection = File( + exists=True, argstr='-seed_rejection %s', + desc=('seed from an image using rejection sampling (higher ' + 'values = more probable to seed from')) + seed_gmwmi = File( + exists=True, argstr='-seed_gmwmi %s', requires=['act_file'], + desc=('seed from the grey matter - white matter interface (only ' + 'valid if using ACT framework)')) + seed_dynamic = File( + exists=True, argstr='-seed_dynamic %s', + desc=('determine seed points dynamically using the SIFT model ' + '(must not provide any other seeding mechanism). Note that' + ' while this seeding mechanism improves the distribution of' + ' reconstructed streamlines density, it should NOT be used ' + 'as a substitute for the SIFT method itself.')) + max_seed_attempts = traits.Int( + argstr='-max_seed_attempts %d', + desc=('set the maximum number of times that the tracking ' + 'algorithm should attempt to find an appropriate tracking' + ' direction from a given seed point')) + out_seeds = File( + 'out_seeds.nii.gz', argstr='-output_seeds %s', + desc=('output the seed location of all successful streamlines to' + ' a file')) + + +class TractographyOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output filtered tracks') + out_seeds = File(desc=('output the seed location of all successful' + ' streamlines to a file')) + + +class Tractography(MRTrix3Base): + + """ + Performs streamlines tractography after selecting the appropriate + algorithm. + + .. [FACT] Mori, S.; Crain, B. J.; Chacko, V. P. & van Zijl, + P. C. M. Three-dimensional tracking of axonal projections in the + brain by magnetic resonance imaging. Annals of Neurology, 1999, + 45, 265-269 + + .. [iFOD1] Tournier, J.-D.; Calamante, F. & Connelly, A. MRtrix: + Diffusion tractography in crossing fiber regions. Int. J. Imaging + Syst. Technol., 2012, 22, 53-66 + + .. [iFOD2] Tournier, J.-D.; Calamante, F. & Connelly, A. Improved + probabilistic streamlines tractography by 2nd order integration + over fibre orientation distributions. Proceedings of the + International Society for Magnetic Resonance in Medicine, 2010, 1670 + + .. [Nulldist] Morris, D. M.; Embleton, K. V. & Parker, G. J. + Probabilistic fibre tracking: Differentiation of connections from + chance events. NeuroImage, 2008, 42, 1329-1339 + + .. [Tensor_Det] Basser, P. J.; Pajevic, S.; Pierpaoli, C.; Duda, J. + and Aldroubi, A. In vivo fiber tractography using DT-MRI data. + Magnetic Resonance in Medicine, 2000, 44, 625-632 + + .. [Tensor_Prob] Jones, D. Tractography Gone Wild: Probabilistic Fibre + Tracking Using the Wild Bootstrap With Diffusion Tensor MRI. IEEE + Transactions on Medical Imaging, 2008, 27, 1268-1274 + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> tk = mrt.Tractography() + >>> tk.inputs.in_file = 'fods.mif' + >>> tk.inputs.roi_mask = 'mask.nii.gz' + >>> tk.inputs.seed_sphere = (80, 100, 70, 10) + >>> tk.cmdline # doctest: +ELLIPSIS + 'tckgen -algorithm iFOD2 -mask mask.nii.gz -seed_sphere \ +80.000000,100.000000,70.000000,10.000000 fods.mif tracked.tck' + >>> tk.run() # doctest: +SKIP + """ + + _cmd = 'tckgen' + input_spec = TractographyInputSpec + output_spec = TractographyOutputSpec + + def _format_arg(self, name, trait_spec, value): + if 'roi_' in name and isinstance(value, tuple): + value = ['%f' % v for v in value] + return trait_spec.argstr % ','.join(value) + + return super(Tractography, self)._format_arg(name, trait_spec, value) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/mrtrix3/utils.py b/nipype/interfaces/mrtrix3/utils.py new file mode 100644 index 0000000000..fe542f8000 --- /dev/null +++ b/nipype/interfaces/mrtrix3/utils.py @@ -0,0 +1,404 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +# -*- coding: utf-8 -*- + +""" + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__ )) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +import os.path as op + +from base import MRTrix3BaseInputSpec, MRTrix3Base +from nipype.interfaces.base import ( + CommandLineInputSpec, CommandLine, traits, TraitedSpec, File, + InputMultiPath) + +from nipype.utils.filemanip import split_filename +from nipype.interfaces.traits_extension import isdefined + + +class BrainMaskInputSpec(MRTrix3BaseInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input diffusion weighted images') + out_file = File( + 'brainmask.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output brain mask') + + +class BrainMaskOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class BrainMask(CommandLine): + + """ + Convert a mesh surface to a partial volume estimation image + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> bmsk = mrt.BrainMask() + >>> bmsk.inputs.in_file = 'dwi.mif' + >>> bmsk.cmdline # doctest: +ELLIPSIS + 'dwi2mask dwi.mif brainmask.mif' + >>> bmsk.run() # doctest: +SKIP + """ + + _cmd = 'dwi2mask' + input_spec = BrainMaskInputSpec + output_spec = BrainMaskOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class Mesh2PVEInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-3, + desc='input mesh') + reference = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input reference image') + in_first = File( + exists=True, argstr='-first %s', + desc='indicates that the mesh file is provided by FSL FIRST') + + out_file = File( + 'mesh2volume.nii.gz', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='output file containing SH coefficients') + + +class Mesh2PVEOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='the output response file') + + +class Mesh2PVE(CommandLine): + + """ + Convert a mesh surface to a partial volume estimation image + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> m2p = mrt.Mesh2PVE() + >>> m2p.inputs.in_file = 'surf1.vtk' + >>> m2p.inputs.reference = 'dwi.mif' + >>> m2p.inputs.in_first = 'T1.nii.gz' + >>> m2p.cmdline # doctest: +ELLIPSIS + 'mesh2pve -first T1.nii.gz surf1.vtk dwi.mif mesh2volume.nii.gz' + >>> m2p.run() # doctest: +SKIP + """ + + _cmd = 'mesh2pve' + input_spec = Mesh2PVEInputSpec + output_spec = Mesh2PVEOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class Generate5ttInputSpec(CommandLineInputSpec): + in_fast = InputMultiPath( + File(exists=True), argstr='%s', mandatory=True, position=-3, + desc='list of PVE images from FAST') + in_first = File( + exists=True, argstr='%s', position=-2, + desc='combined segmentation file from FIRST') + out_file = File( + 'act-5tt.mif', argstr='%s', mandatory=True, position=-1, + usedefault=True, desc='name of output file') + + +class Generate5ttOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='segmentation for ACT in 5tt format') + + +class Generate5tt(CommandLine): + + """ + Concatenate segmentation results from FSL FAST and FIRST into the 5TT + format required for ACT + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> seg = mrt.Generate5tt() + >>> seg.inputs.in_fast = ['tpm_00.nii.gz', + ... 'tpm_01.nii.gz', 'tpm_02.nii.gz'] + >>> seg.inputs.in_first = 'first_merged.nii.gz' + >>> seg.cmdline # doctest: +ELLIPSIS + '5ttgen tpm_00.nii.gz tpm_01.nii.gz tpm_02.nii.gz first_merged.nii.gz\ + act-5tt.mif' + >>> seg.run() # doctest: +SKIP + """ + + _cmd = '5ttgen' + input_spec = Generate5ttInputSpec + output_spec = Generate5ttOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class TensorMetricsInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-1, + desc='input DTI image') + + out_fa = File(argstr='-fa %s', desc='output FA file') + out_adc = File(argstr='-adc %s', desc='output ADC file') + out_evec = File(argstr='-vector %s', + desc='output selected eigenvector(s) file') + out_eval = File(argstr='-value %s', + desc='output selected eigenvalue(s) file') + component = traits.List( + [1, 2, 3], argstr='-num %s', sep=',', + desc=('specify the desired eigenvalue/eigenvector(s). Note that ' + 'several eigenvalues can be specified as a number sequence')) + in_mask = File(exists=True, argstr='-mask %s', + desc=('only perform computation within the specified binary' + ' brain mask image')) + modulate = traits.Enum('FA', 'none', 'eval', argstr='-modulate %s', + desc=('how to modulate the magnitude of the' + ' eigenvectors')) + + +class TensorMetricsOutputSpec(TraitedSpec): + out_fa = File(desc='output FA file') + out_adc = File(desc='output ADC file') + out_evec = File(desc='output selected eigenvector(s) file') + out_eval = File(desc='output selected eigenvalue(s) file') + + +class TensorMetrics(CommandLine): + + """ + Compute metrics from tensors + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> comp = mrt.TensorMetrics() + >>> comp.inputs.in_file = 'dti.mif' + >>> comp.inputs.out_fa = 'fa.mif' + >>> comp.cmdline # doctest: +ELLIPSIS + 'tensor2metric -fa fa.mif dti.mif' + >>> comp.run() # doctest: +SKIP + """ + + _cmd = 'tensor2metric' + input_spec = TensorMetricsInputSpec + output_spec = TensorMetricsOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + + for k in outputs.keys(): + if isdefined(getattr(self.inputs, k)): + outputs[k] = op.abspath(getattr(self.inputs, k)) + + return outputs + + +class ComputeTDIInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input tractography') + out_file = File('tdi.mif', argstr='%s', usedefault=True, position=-1, + desc='output TDI file') + reference = File( + exists=True, argstr='-template %s', desc='a reference' + 'image to be used as template') + vox_size = traits.List(traits.Int, argstr='-vox %s', sep=',', + desc='voxel dimensions') + data_type = traits.Enum('float', 'unsigned int', argstr='-datatype %s', + desc='specify output image data type') + use_dec = traits.Bool(argstr='-dec', desc='perform mapping in DEC space') + dixel = File('dixels.txt', argstr='-dixel %s', desc='map streamlines to' + 'dixels within each voxel. Directions are stored as' + 'azimuth elevation pairs.') + max_tod = traits.Int(argstr='-tod %d', desc='generate a Track Orientation ' + 'Distribution (TOD) in each voxel.') + + contrast = traits.Enum('tdi', 'length', 'invlength', 'scalar_map', + 'scalar_map_conut', 'fod_amp', 'curvature', + argstr='-constrast %s', desc='define the desired ' + 'form of contrast for the output image') + in_map = File(exists=True, argstr='-image %s', desc='provide the' + 'scalar image map for generating images with ' + '\'scalar_map\' contrasts, or the SHs image for fod_amp') + + stat_vox = traits.Enum('sum', 'min', 'mean', 'max', argstr='-stat_vox %s', + desc='define the statistic for choosing the final' + 'voxel intesities for a given contrast') + stat_tck = traits.Enum( + 'mean', 'sum', 'min', 'max', 'median', 'mean_nonzero', 'gaussian', + 'ends_min', 'ends_mean', 'ends_max', 'ends_prod', + argstr='-stat_tck %s', desc='define the statistic for choosing ' + 'the contribution to be made by each streamline as a function of' + ' the samples taken along their lengths.') + + fwhm_tck = traits.Float( + argstr='-fwhm_tck %f', desc='define the statistic for choosing the' + ' contribution to be made by each streamline as a function of the ' + 'samples taken along their lengths') + + map_zero = traits.Bool( + argstr='-map_zero', desc='if a streamline has zero contribution based ' + 'on the contrast & statistic, typically it is not mapped; use this ' + 'option to still contribute to the map even if this is the case ' + '(these non-contributing voxels can then influence the mean value in ' + 'each voxel of the map)') + + upsample = traits.Int(argstr='-upsample %d', desc='upsample the tracks by' + ' some ratio using Hermite interpolation before ' + 'mappping') + + precise = traits.Bool( + argstr='-precise', desc='use a more precise streamline mapping ' + 'strategy, that accurately quantifies the length through each voxel ' + '(these lengths are then taken into account during TWI calculation)') + ends_only = traits.Bool(argstr='-ends_only', desc='only map the streamline' + ' endpoints to the image') + + tck_weights = File(exists=True, argstr='-tck_weights_in %s', desc='specify' + ' a text scalar file containing the streamline weights') + nthreads = traits.Int( + argstr='-nthreads %d', desc='number of threads. if zero, the number' + ' of available cpus will be used', nohash=True) + + +class ComputeTDIOutputSpec(TraitedSpec): + out_file = File(desc='output TDI file') + + +class ComputeTDI(MRTrix3Base): + + """ + Use track data as a form of contrast for producing a high-resolution + image. + + .. admonition:: References + + * For TDI or DEC TDI: Calamante, F.; Tournier, J.-D.; Jackson, G. D. & + Connelly, A. Track-density imaging (TDI): Super-resolution white + matter imaging using whole-brain track-density mapping. NeuroImage, + 2010, 53, 1233-1243 + + * If using -contrast length and -stat_vox mean: Pannek, K.; Mathias, + J. L.; Bigler, E. D.; Brown, G.; Taylor, J. D. & Rose, S. E. The + average pathlength map: A diffusion MRI tractography-derived index + for studying brain pathology. NeuroImage, 2011, 55, 133-141 + + * If using -dixel option with TDI contrast only: Smith, R.E., Tournier, + J-D., Calamante, F., Connelly, A. A novel paradigm for automated + segmentation of very large whole-brain probabilistic tractography + data sets. In proc. ISMRM, 2011, 19, 673 + + * If using -dixel option with any other contrast: Pannek, K., Raffelt, + D., Salvado, O., Rose, S. Incorporating directional information in + diffusion tractography derived maps: angular track imaging (ATI). + In Proc. ISMRM, 2012, 20, 1912 + + * If using -tod option: Dhollander, T., Emsell, L., Van Hecke, W., Maes, + F., Sunaert, S., Suetens, P. Track Orientation Density Imaging (TODI) + and Track Orientation Distribution (TOD) based tractography. + NeuroImage, 2014, 94, 312-336 + + * If using other contrasts / statistics: Calamante, F.; Tournier, J.-D.; + Smith, R. E. & Connelly, A. A generalised framework for + super-resolution track-weighted imaging. NeuroImage, 2012, 59, + 2494-2503 + + * If using -precise mapping option: Smith, R. E.; Tournier, J.-D.; + Calamante, F. & Connelly, A. SIFT: Spherical-deconvolution informed + filtering of tractograms. NeuroImage, 2013, 67, 298-312 (Appendix 3) + + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> tdi = mrt.ComputeTDI() + >>> tdi.inputs.in_file = 'dti.mif' + >>> tdi.cmdline # doctest: +ELLIPSIS + 'tckmap dti.mif tdi.mif' + >>> tdi.run() # doctest: +SKIP + """ + + _cmd = 'tckmap' + input_spec = ComputeTDIInputSpec + output_spec = ComputeTDIOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs + + +class TCK2VTKInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, + desc='input tractography') + out_file = File('tracks.vtk', argstr='%s', usedefault=True, position=-1, + desc='output VTK file') + reference = File( + exists=True, argstr='-image %s', desc='if specified, the properties of' + ' this image will be used to convert track point positions from real ' + '(scanner) coordinates into image coordinates (in mm).') + voxel = File( + exists=True, argstr='-image %s', desc='if specified, the properties of' + ' this image will be used to convert track point positions from real ' + '(scanner) coordinates into image coordinates.') + + nthreads = traits.Int( + argstr='-nthreads %d', desc='number of threads. if zero, the number' + ' of available cpus will be used', nohash=True) + + +class TCK2VTKOutputSpec(TraitedSpec): + out_file = File(desc='output VTK file') + + +class TCK2VTK(MRTrix3Base): + + """ + Convert a track file to a vtk format, cave: coordinates are in XYZ + coordinates not reference + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> vtk = mrt.TCK2VTK() + >>> vtk.inputs.in_file = 'tracks.tck' + >>> vtk.inputs.reference = 'b0.nii' + >>> vtk.cmdline # doctest: +ELLIPSIS + 'tck2vtk -image b0.nii tracks.tck tracks.vtk' + >>> vtk.run() # doctest: +SKIP + """ + + _cmd = 'tck2vtk' + input_spec = TCK2VTKInputSpec + output_spec = TCK2VTKOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = op.abspath(self.inputs.out_file) + return outputs diff --git a/nipype/interfaces/setup.py b/nipype/interfaces/setup.py new file mode 100644 index 0000000000..ade51ff8a1 --- /dev/null +++ b/nipype/interfaces/setup.py @@ -0,0 +1,35 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + + +def configuration(parent_package='', top_path=None): + from numpy.distutils.misc_util import Configuration + + config = Configuration('interfaces', parent_package, top_path) + + config.add_subpackage('afni') + config.add_subpackage('ants') + config.add_subpackage('camino') + config.add_subpackage('camino2trackvis') + config.add_subpackage('cmtk') + config.add_subpackage('diffusion_toolkit') + config.add_subpackage('dipy') + config.add_subpackage('elastix') + config.add_subpackage('freesurfer') + config.add_subpackage('fsl') + config.add_subpackage('mne') + config.add_subpackage('mrtrix') + config.add_subpackage('mrtrix3') + config.add_subpackage('nipy') + config.add_subpackage('spm') + config.add_subpackage('slicer') + config.add_subpackage('mipav') + + config.add_data_dir('script_templates') + config.add_data_dir('tests') + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(**configuration(top_path='').todict()) diff --git a/nipype/testing/data/dti.mif b/nipype/testing/data/dti.mif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/first_merged.nii.gz b/nipype/testing/data/first_merged.nii.gz new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/fods.mif b/nipype/testing/data/fods.mif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/mrtrix3_labelconfig.txt b/nipype/testing/data/mrtrix3_labelconfig.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/response.txt b/nipype/testing/data/response.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/testing/data/tdi.mif b/nipype/testing/data/tdi.mif new file mode 100644 index 0000000000..e69de29bb2