Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
.pydevproject
.idea/
/documentation.zip
.DS_Store
2 changes: 1 addition & 1 deletion nipype/interfaces/dipy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .tracks import TrackDensityMap
from .tensors import TensorMode
from .tensors import TensorMode, DTI
from .preprocess import Resample, Denoise
129 changes: 104 additions & 25 deletions nipype/interfaces/dipy/tensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,116 @@
have_dipy = False
else:
import dipy.reconst.dti as dti
from dipy.core.gradients import GradientTable
from dipy.core.gradients import gradient_table
from dipy.io.utils import nifti1_symmat


def tensor_fitting(data, bvals, bvecs, mask_file=None):
"""
Use dipy to fit DTI

Parameters
----------
in_file : str
Full path to a DWI data file.
bvals : str
Full path to a file containing gradient magnitude information (b-values).
bvecs : str
Full path to a file containing gradient direction information (b-vectors).
mask_file : str, optional
Full path to a file containing a binary mask. Defaults to use the entire volume.

Returns
-------
TensorFit object, affine
"""
img = nb.load(in_file).get_data()
data = img.get_data()
affine = img.get_affine()
if mask_file is not None:
mask = nb.load(self.inputs.mask_file).get_data()
else:
mask=None

# Load information about the gradients:
gtab = grad.gradient_table(self.inputs.bvals, self.inputs.bvecs)

# Fit it
tenmodel = dti.TensorModel(gtab)
return tenmodel.fit(data, mask), affine


class DTIInputSpec(TraitedSpec):
in_file = File(exists=True, mandatory=True,
desc='The input 4D diffusion-weighted image file')
bvecs = File(exists=True, mandatory=True,
desc='The input b-vector text file')
bvals = File(exists=True, mandatory=True,
desc='The input b-value text file')
mask_file = File(exists=True, mandatory=False,
desc='An optional white matter mask')
out_filename = File(
genfile=True, desc='The output filename for the DTI parameters image')


class DTIOutputSpec(TraitedSpec):
out_file = File(exists=True)


class DTI(BaseInterface):
"""
Calculates the diffusion tensor model parameters

Example
-------

>>> import nipype.interfaces.dipy as dipy
>>> dti = dipy.DTI()
>>> dti.inputs.in_file = 'diffusion.nii'
>>> dti.inputs.bvecs = 'bvecs'
>>> dti.inputs.bvals = 'bvals'
>>> dti.run() # doctest: +SKIP
"""
input_spec = DTIInputSpec
output_spec = DTIOutputSpec

def _run_interface(self, runtime):
ten_fit, affine = tensor_fitting(self.inputs.in_file,
self.inputs.bvals,
self.inputs.bvecs,
self.inputs.mask_file)
lower_triangular = tenfit.lower_triangular()
img = nifti1_symmat(lower_triangular, affine)
out_file = op.abspath(self._gen_outfilename())
nb.save(img, out_file)
iflogger.info('DTI parameters image saved as {i}'.format(i=out_file))
return runtime

def _list_outputs(self):
outputs = self._outputs().get()
outputs['out_file'] = op.abspath(self._gen_outfilename())
return outputs

def _gen_filename(self, name):
if name is 'out_filename':
return self._gen_outfilename()
else:
return None

def _gen_outfilename(self):
_, name, _ = split_filename(self.inputs.in_file)
return name + '_dti.nii'


class TensorModeInputSpec(TraitedSpec):
in_file = File(exists=True, mandatory=True,
desc='The input 4D diffusion-weighted image file')
bvecs = File(exists=True, mandatory=True,
desc='The input b-vector text file')
bvals = File(exists=True, mandatory=True,
desc='The input b-value text file')
mask_file = File(exists=True, mandatory=False,
desc='An optional white matter mask')
out_filename = File(
genfile=True, desc='The output filename for the Tensor mode image')

Expand Down Expand Up @@ -69,32 +169,11 @@ class TensorMode(BaseInterface):
output_spec = TensorModeOutputSpec

def _run_interface(self, runtime):
## Load the 4D image files
img = nb.load(self.inputs.in_file)
data = img.get_data()
affine = img.get_affine()

## Load the gradient strengths and directions
bvals = np.loadtxt(self.inputs.bvals)
gradients = np.loadtxt(self.inputs.bvecs).T

## Place in Dipy's preferred format
gtab = GradientTable(gradients)
gtab.bvals = bvals

## Mask the data so that tensors are not fit for
## unnecessary voxels
mask = data[..., 0] > 50

## Fit the tensors to the data
tenmodel = dti.TensorModel(gtab)
tenfit = tenmodel.fit(data, mask)

## Calculate the mode of each voxel's tensor
mode_data = tenfit.mode
ten_fit = tensor_fitting(self.inputs.in_file, self.inputs.bvals, self.inputs.bvecs,
self.inputs.mask_file)

## Write as a 3D Nifti image with the original affine
img = nb.Nifti1Image(mode_data, affine)
img = nb.Nifti1Image(tenfit.mode, affine)
out_file = op.abspath(self._gen_outfilename())
nb.save(img, out_file)
iflogger.info('Tensor mode image saved as {i}'.format(i=out_file))
Expand Down
31 changes: 31 additions & 0 deletions nipype/interfaces/dipy/tests/test_auto_DTI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
from nipype.testing import assert_equal
from nipype.interfaces.dipy.tensors import DTI

def test_DTI_inputs():
input_map = dict(bvals=dict(mandatory=True,
),
bvecs=dict(mandatory=True,
),
in_file=dict(mandatory=True,
),
mask_file=dict(mandatory=False,
),
out_filename=dict(genfile=True,
),
)
inputs = DTI.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_DTI_outputs():
output_map = dict(out_file=dict(),
)
outputs = DTI.output_spec()

for key, metadata in output_map.items():
for metakey, value in metadata.items():
yield assert_equal, getattr(outputs.traits()[key], metakey), value

2 changes: 2 additions & 0 deletions nipype/interfaces/dipy/tests/test_auto_TensorMode.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ def test_TensorMode_inputs():
),
in_file=dict(mandatory=True,
),
mask_file=dict(mandatory=False,
),
out_filename=dict(genfile=True,
),
)
Expand Down