Skip to content

Commit 5c34854

Browse files
committed
rebased dipy and adapted old interfaces
1 parent a70bcb3 commit 5c34854

16 files changed

+220
-250
lines changed

nipype/interfaces/dipy/base.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,44 @@
11
# -*- coding: utf-8 -*-
2-
import numpy as np
2+
""" Base interfaces for dipy """
33
import os.path as op
4+
import numpy as np
45
from nipype.interfaces.base import (traits, File, isdefined,
56
BaseInterface, BaseInterfaceInputSpec)
7+
from ... import logging
8+
9+
IFLOGGER = logging.getLogger('interface')
10+
11+
HAVE_DIPY = True
12+
try:
13+
import dipy
14+
except ImportError:
15+
HAVE_DIPY = False
16+
17+
18+
def no_dipy():
19+
""" Check if dipy is available """
20+
global HAVE_DIPY
21+
return not HAVE_DIPY
22+
23+
24+
def dipy_version():
25+
""" Check dipy version """
26+
if no_dipy():
27+
return None
28+
29+
return dipy.__version__
30+
31+
32+
class DipyBaseInterface(BaseInterface):
33+
34+
"""
35+
A base interface for py:mod:`dipy` computations
36+
"""
37+
def __init__(self, **inputs):
38+
if no_dipy():
39+
IFLOGGER.error('dipy was not found')
40+
# raise ImportError('dipy was not found')
41+
super(DipyBaseInterface, self).__init__(**inputs)
642

743

844
class DipyBaseInterfaceInputSpec(BaseInterfaceInputSpec):
@@ -13,7 +49,7 @@ class DipyBaseInterfaceInputSpec(BaseInterfaceInputSpec):
1349
out_prefix = traits.Str(desc=('output prefix for file names'))
1450

1551

16-
class DipyBaseInterface(BaseInterface):
52+
class DipyDiffusionInterface(DipyBaseInterface):
1753

1854
"""
1955
A base interface for py:mod:`dipy` computations

nipype/interfaces/dipy/preprocess.py

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,13 @@
88
>>> os.chdir(datadir)
99
"""
1010
import os.path as op
11-
import warnings
12-
1311
import nibabel as nb
1412
import numpy as np
1513

16-
from ..base import (traits, TraitedSpec, BaseInterface, File, isdefined)
17-
from ...utils.filemanip import split_filename
18-
from ...utils.misc import package_check
14+
from ..base import (traits, TraitedSpec, File, isdefined)
15+
from .base import DipyBaseInterface
1916
from ... import logging
20-
iflogger = logging.getLogger('interface')
21-
22-
have_dipy = True
23-
try:
24-
package_check('dipy', version='0.6.0')
25-
except Exception as e:
26-
have_dipy = False
27-
else:
28-
from dipy.align.aniso2iso import resample
29-
from dipy.core.gradients import GradientTable
17+
IFLOGGER = logging.getLogger('interface')
3018

3119

3220
class ResampleInputSpec(TraitedSpec):
@@ -46,7 +34,7 @@ class ResampleOutputSpec(TraitedSpec):
4634
out_file = File(exists=True)
4735

4836

49-
class Resample(BaseInterface):
37+
class Resample(DipyBaseInterface):
5038

5139
"""
5240
An interface to reslicing diffusion datasets.
@@ -75,7 +63,7 @@ def _run_interface(self, runtime):
7563
resample_proxy(self.inputs.in_file, order=order,
7664
new_zooms=vox_size, out_file=out_file)
7765

78-
iflogger.info('Resliced image saved as {i}'.format(i=out_file))
66+
IFLOGGER.info('Resliced image saved as {i}'.format(i=out_file))
7967
return runtime
8068

8169
def _list_outputs(self):
@@ -111,7 +99,7 @@ class DenoiseOutputSpec(TraitedSpec):
11199
out_file = File(exists=True)
112100

113101

114-
class Denoise(BaseInterface):
102+
class Denoise(DipyBaseInterface):
115103

116104
"""
117105
An interface to denoising diffusion datasets [Coupe2008]_.
@@ -166,7 +154,7 @@ def _run_interface(self, runtime):
166154
smask=signal_mask,
167155
nmask=noise_mask,
168156
out_file=out_file)
169-
iflogger.info(('Denoised image saved as {i}, estimated '
157+
IFLOGGER.info(('Denoised image saved as {i}, estimated '
170158
'SNR={s}').format(i=out_file, s=str(s)))
171159
return runtime
172160

@@ -187,6 +175,7 @@ def resample_proxy(in_file, order=3, new_zooms=None, out_file=None):
187175
"""
188176
Performs regridding of an image to set isotropic voxel sizes using dipy.
189177
"""
178+
from dipy.align.aniso2iso import resample
190179

191180
if out_file is None:
192181
fname, fext = op.splitext(op.basename(in_file))
@@ -227,7 +216,6 @@ def nlmeans_proxy(in_file, settings,
227216
"""
228217
Uses non-local means to denoise 4D datasets
229218
"""
230-
package_check('dipy', version='0.8.0.dev')
231219
from dipy.denoise.nlmeans import nlmeans
232220
from scipy.ndimage.morphology import binary_erosion
233221
from scipy import ndimage

nipype/interfaces/dipy/reconstruction.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
# -*- coding: utf-8 -*-
2-
import os
2+
"""
3+
Interfaces to the reconstruction algorithms in dipy
4+
5+
"""
36
import os.path as op
47

58
import numpy as np
6-
from dipy.core.gradients import GradientTable
79
import nibabel as nb
810

9-
from nipype.interfaces.base import (TraitedSpec, File, InputMultiPath,
10-
OutputMultiPath, Undefined, traits,
11-
isdefined, OutputMultiPath,
12-
CommandLineInputSpec, CommandLine,
13-
BaseInterface, BaseInterfaceInputSpec,
14-
traits)
15-
from nipype.utils.filemanip import split_filename, fname_presuffix
16-
17-
from .base import DipyBaseInterface, DipyBaseInterfaceInputSpec
11+
from nipype.interfaces.base import TraitedSpec, File, traits, isdefined
12+
from .base import DipyDiffusionInterface, DipyBaseInterfaceInputSpec
1813

1914
from nipype import logging
20-
iflogger = logging.getLogger('interface')
15+
IFLOGGER = logging.getLogger('interface')
2116

2217

2318
class RESTOREInputSpec(DipyBaseInterfaceInputSpec):
@@ -27,20 +22,20 @@ class RESTOREInputSpec(DipyBaseInterfaceInputSpec):
2722

2823

2924
class RESTOREOutputSpec(TraitedSpec):
30-
fa = File(desc=('output fractional anisotropy (FA) map computed from '
31-
'the fitted DTI'))
32-
md = File(desc=('output mean diffusivity (MD) map computed from the '
33-
'fitted DTI'))
34-
rd = File(desc=('output radial diffusivity (RD) map computed from '
35-
'the fitted DTI'))
25+
fa = File(desc='output fractional anisotropy (FA) map computed from '
26+
'the fitted DTI')
27+
md = File(desc='output mean diffusivity (MD) map computed from the '
28+
'fitted DTI')
29+
rd = File(desc='output radial diffusivity (RD) map computed from '
30+
'the fitted DTI')
3631
mode = File(desc=('output mode (MO) map computed from the fitted DTI'))
3732
trace = File(desc=('output the tensor trace map computed from the '
3833
'fitted DTI'))
3934
evals = File(desc=('output the eigenvalues of the fitted DTI'))
4035
evecs = File(desc=('output the eigenvectors of the fitted DTI'))
4136

4237

43-
class RESTORE(DipyBaseInterface):
38+
class RESTORE(DipyDiffusionInterface):
4439

4540
"""
4641
Uses RESTORE [Chang2005]_ to perform DTI fitting with outlier detection.
@@ -92,7 +87,7 @@ def _run_interface(self, runtime):
9287
noise_msk = noise_msk.astype(np.uint8)
9388
try_b0 = False
9489
elif np.all(data[msk == 0, 0] == 0):
95-
iflogger.info('Input data are masked.')
90+
IFLOGGER.info('Input data are masked.')
9691
noise_msk = msk.reshape(-1).astype(np.uint8)
9792
else:
9893
noise_msk = (1 - msk).reshape(-1).astype(np.uint8)
@@ -123,18 +118,18 @@ def _run_interface(self, runtime):
123118
sigma = mean_std * (1 + bias)
124119

125120
if sigma == 0:
126-
iflogger.warn(
121+
IFLOGGER.warn(
127122
('Noise std is 0.0, looks like data was masked and noise'
128123
' cannot be estimated correctly. Using default tensor '
129124
'model instead of RESTORE.'))
130125
dti = TensorModel(gtab)
131126
else:
132-
iflogger.info(('Performing RESTORE with noise std=%.4f.') % sigma)
127+
IFLOGGER.info(('Performing RESTORE with noise std=%.4f.') % sigma)
133128
dti = TensorModel(gtab, fit_method='RESTORE', sigma=sigma)
134129

135130
try:
136131
fit_restore = dti.fit(data, msk)
137-
except TypeError as e:
132+
except TypeError:
138133
dti = TensorModel(gtab)
139134
fit_restore = dti.fit(data, msk)
140135

@@ -181,7 +176,7 @@ class EstimateResponseSHOutputSpec(TraitedSpec):
181176
out_mask = File(exists=True, desc=('output wm mask'))
182177

183178

184-
class EstimateResponseSH(DipyBaseInterface):
179+
class EstimateResponseSH(DipyDiffusionInterface):
185180

186181
"""
187182
Uses dipy to compute the single fiber response to be used in spherical
@@ -253,14 +248,14 @@ def _run_interface(self, runtime):
253248
ratio = abs(response[1] / response[0])
254249

255250
if ratio > 0.25:
256-
iflogger.warn(('Estimated response is not prolate enough. '
251+
IFLOGGER.warn(('Estimated response is not prolate enough. '
257252
'Ratio=%0.3f.') % ratio)
258253
elif ratio < 1.e-5 or np.any(np.isnan(response)):
259254
response = np.array([1.8e-3, 3.6e-4, 3.6e-4, S0])
260-
iflogger.warn(
255+
IFLOGGER.warn(
261256
('Estimated response is not valid, using a default one'))
262257
else:
263-
iflogger.info(('Estimated response: %s') % str(response[:3]))
258+
IFLOGGER.info(('Estimated response: %s') % str(response[:3]))
264259

265260
np.savetxt(op.abspath(self.inputs.response), response)
266261

@@ -293,7 +288,7 @@ class CSDOutputSpec(TraitedSpec):
293288
out_fods = File(desc=('fODFs output file name'))
294289

295290

296-
class CSD(DipyBaseInterface):
291+
class CSD(DipyDiffusionInterface):
297292

298293
"""
299294
Uses CSD [Tournier2007]_ to generate the fODF of DWIs. The interface uses
@@ -344,13 +339,13 @@ def _run_interface(self, runtime):
344339
ratio = response[0][1] / response[0][0]
345340

346341
if abs(ratio - 0.2) > 0.1:
347-
iflogger.warn(('Estimated response is not prolate enough. '
342+
IFLOGGER.warn(('Estimated response is not prolate enough. '
348343
'Ratio=%0.3f.') % ratio)
349344

350345
csd_model = ConstrainedSphericalDeconvModel(
351346
gtab, response, sh_order=self.inputs.sh_order)
352347

353-
iflogger.info('Fitting CSD model')
348+
IFLOGGER.info('Fitting CSD model')
354349
csd_fit = csd_model.fit(data, msk)
355350

356351
f = gzip.open(self._gen_filename('csdmodel', ext='.pklz'), 'wb')

nipype/interfaces/dipy/simulate.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,18 @@
77
"""
88

99
from __future__ import division
10+
from multiprocessing import (Pool, cpu_count)
11+
import os.path as op
1012
from builtins import range
1113

12-
import os.path as op
13-
from multiprocessing import (Pool, cpu_count)
1414

1515
import nibabel as nb
1616

17-
from ..base import (traits, TraitedSpec, BaseInterface, BaseInterfaceInputSpec,
17+
from ..base import (traits, TraitedSpec, BaseInterfaceInputSpec,
1818
File, InputMultiPath, isdefined)
19-
from ...utils.misc import package_check
19+
from .base import DipyBaseInterface
2020
from ... import logging
21-
iflogger = logging.getLogger('interface')
22-
23-
have_dipy = True
24-
try:
25-
package_check('dipy', version='0.8.0')
26-
except Exception as e:
27-
have_dipy = False
28-
else:
29-
import numpy as np
30-
from dipy.sims.voxel import (multi_tensor, add_noise,
31-
all_tensor_evecs)
32-
from dipy.core.gradients import gradient_table
21+
IFLOGGER = logging.getLogger('interface')
3322

3423

3524
class SimulateMultiTensorInputSpec(BaseInterfaceInputSpec):
@@ -77,7 +66,7 @@ class SimulateMultiTensorOutputSpec(TraitedSpec):
7766
out_bval = File(exists=True, desc='simulated b values')
7867

7968

80-
class SimulateMultiTensor(BaseInterface):
69+
class SimulateMultiTensor(DipyBaseInterface):
8170

8271
"""
8372
Interface to MultiTensor model simulator in dipy
@@ -101,6 +90,8 @@ class SimulateMultiTensor(BaseInterface):
10190
output_spec = SimulateMultiTensorOutputSpec
10291

10392
def _run_interface(self, runtime):
93+
from dipy.core.gradients import gradient_table
94+
10495
# Gradient table
10596
if isdefined(self.inputs.in_bval) and isdefined(self.inputs.in_bvec):
10697
# Load the gradient strengths and directions
@@ -237,7 +228,7 @@ def _run_interface(self, runtime):
237228
pool = Pool(processes=n_proc)
238229

239230
# Simulate sticks using dipy
240-
iflogger.info(('Starting simulation of %d voxels, %d diffusion'
231+
IFLOGGER.info(('Starting simulation of %d voxels, %d diffusion'
241232
' directions.') % (len(args), ndirs))
242233
result = np.array(pool.map(_compute_voxel, args))
243234
if np.shape(result)[1] != ndirs:
@@ -280,6 +271,7 @@ def _compute_voxel(args):
280271
.. [Pierpaoli1996] Pierpaoli et al., Diffusion tensor MR imaging
281272
of the human brain, Radiology 201:637-648. 1996.
282273
"""
274+
from dipy.sims.voxel import multi_tensor
283275

284276
ffs = args['fractions']
285277
gtab = args['gradients']
@@ -297,7 +289,7 @@ def _compute_voxel(args):
297289
angles=args['sticks'], fractions=ffs, snr=snr)
298290
except Exception as e:
299291
pass
300-
# iflogger.warn('Exception simulating dwi signal: %s' % e)
292+
# IFLOGGER.warn('Exception simulating dwi signal: %s' % e)
301293

302294
return signal.tolist()
303295

0 commit comments

Comments
 (0)