Skip to content

[WIP] Write interfaces for MRTrix3 #1126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Sep 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d6be6fe
first version of interface to tractography
oesteban Jun 26, 2015
55e3f89
add estimate response, fix errors in tracking
oesteban Jun 26, 2015
814349e
add auto tests
oesteban Jun 26, 2015
01bea78
add mesh2pve interface
oesteban Jun 26, 2015
1abc676
add missing edit in mrtrix3
oesteban Jun 26, 2015
85452ce
fix tests
oesteban Jun 28, 2015
5045a8b
fix tests (2)
oesteban Jun 28, 2015
7647d73
add interface to act_anat_prepare_fsl
oesteban Jun 28, 2015
7892cbc
fix tests new interface. Update CHANGES
oesteban Jun 28, 2015
6d4c6ad
fix docstrings
oesteban Jun 29, 2015
a5c6164
add options to tracking interface
oesteban Jun 29, 2015
4ddbd05
Add 5ttgen interface
oesteban Jun 30, 2015
9612ffe
Merge branch 'master' into enh/MRTrix3
oesteban Jun 30, 2015
0f45bc9
Add dwi2tensor and dwi2fod
oesteban Jun 30, 2015
85a51a1
Add dwi2mask, fix auto tests
oesteban Jun 30, 2015
15dd7a8
Add TensorMetrics interface
oesteban Jun 30, 2015
de56b4c
Merge branch 'master' into enh/MRTrix3
oesteban Jul 2, 2015
8a5fd28
fix shells options, merge master
oesteban Jul 2, 2015
204aa89
new base for MRTrix3 interfaces, new nthreads input
oesteban Jul 2, 2015
e28dea5
add tckmap interface
oesteban Jul 3, 2015
b7f0ea5
add labelconfig interface
oesteban Jul 6, 2015
50168f5
fix default file finding
oesteban Jul 6, 2015
3e326f1
add interface for fs_parc_replace_sgm_first
oesteban Jul 6, 2015
f03d224
add tck2connectome interface
oesteban Jul 6, 2015
a27a416
fix errors and missing parts
oesteban Jul 6, 2015
9d298b2
add auto tests, fix doctests
oesteban Jul 6, 2015
efc08b3
Merge branch 'master' into enh/MRTrix3
oesteban Jul 6, 2015
9709872
add nohash=True on nthreads option
oesteban Jul 10, 2015
8ba033c
add tck2vtk
oesteban Jul 10, 2015
9c5eadd
fix doctests
oesteban Jul 10, 2015
432e0f6
add FSL bvec/bval format explicit to all interfaces
oesteban Jul 16, 2015
10f3366
Merge branch 'master' into enh/MRTrix3
oesteban Jul 17, 2015
50f8793
fix parse_inputs for interfaces not defining gradients
oesteban Jul 17, 2015
19effb6
Merge branch 'master' into enh/MRTrix3
oesteban Jul 30, 2015
d2ac3f2
Merge branch 'master' into enh/MRTrix3
oesteban Aug 5, 2015
2751181
Merge branch 'master' into enh/MRTrix3
oesteban Aug 13, 2015
fda2ac5
Merge branch 'master' into enh/MRTrix3
oesteban Sep 7, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -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
Expand Down
10 changes: 10 additions & 0 deletions nipype/interfaces/mrtrix3/__init__.py
Original file line number Diff line number Diff line change
@@ -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
89 changes: 89 additions & 0 deletions nipype/interfaces/mrtrix3/base.py
Original file line number Diff line number Diff line change
@@ -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)
189 changes: 189 additions & 0 deletions nipype/interfaces/mrtrix3/connectivity.py
Original file line number Diff line number Diff line change
@@ -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
Loading