Skip to content

Commit a3ac6c2

Browse files
author
Martin Luessi
committed
Merge pull request #1 from satra/tst/martin
Tst/martin
2 parents 7230ef0 + 75f1520 commit a3ac6c2

15 files changed

+346
-28
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
.project
1313
.settings
1414
.pydevproject
15+
.idea/

CHANGES

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ Next release
88
* ENH: Added support for Simple Linux Utility Resource Management (SLURM)
99
* ENH: AFNI interfaces refactor, prefix, suffix are replaced by "flexible_%s_templates"
1010
* ENH: DataGrabber and SelectFiles use human (or natural) sort now
11-
1211
* ENH: Several new interfaces related to Camino were added:
1312
- camino.SFPICOCalibData
1413
- camino.Conmat
@@ -17,6 +16,10 @@ Next release
1716
- camino.SFPeaks
1817
One outdated interface no longer part of Camino was removed:
1918
- camino.Conmap
19+
* ENH: Three new mrtrix interfaces were added:
20+
- mrtrix.GenerateDirections
21+
- mrtrix.FindShPeaks
22+
- mrtrix.Directions2Amplitude
2023

2124
* FIX: Several fixes related to Camino interfaces:
2225
- ProcStreamlines would ignore many arguments silently (target, waypoint, exclusion ROIS, etc.)

nipype/interfaces/fsl/preprocess.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ class FUGUEInputSpec(FSLCommandInputSpec):
11971197
desc='apply Fourier (sinusoidal) fitting of order N')
11981198
pava = traits.Bool(argstr='--pava',
11991199
desc='apply monotonic enforcement via PAVA')
1200-
despike_theshold = traits.Float(argstr='--despikethreshold=%s',
1200+
despike_threshold = traits.Float(argstr='--despikethreshold=%s',
12011201
desc='specify the threshold for de-spiking (default=3.0)')
12021202
unwarp_direction = traits.Enum('x', 'y', 'z', 'x-', 'y-', 'z-',
12031203
argstr='--unwarpdir=%s',
@@ -1287,13 +1287,13 @@ def _parse_inputs(self, skip=None):
12871287
self.inputs.shift_out_file = self._gen_fname(
12881288
self.inputs.in_file, suffix='_vsm')
12891289

1290-
if self.inputs.forward_warping or not isdefined(self.inputs.in_file):
1291-
skip += ['unwarped_file']
1290+
if not isdefined(self.inputs.in_file):
1291+
skip += ['unwarped_file', 'warped_file']
1292+
elif self.inputs.forward_warping:
12921293
if not isdefined(self.inputs.warped_file):
12931294
self.inputs.warped_file = self._gen_fname(
12941295
self.inputs.in_file, suffix='_warped')
1295-
if not self.inputs.forward_warping or not isdefined(self.inputs.in_file):
1296-
skip += ['warped_file']
1296+
elif not self.inputs.forward_warping:
12971297
if not isdefined(self.inputs.unwarped_file):
12981298
self.inputs.unwarped_file = self._gen_fname(
12991299
self.inputs.in_file, suffix='_unwarped')

nipype/interfaces/fsl/tests/test_auto_ApplyTOPUP.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def test_ApplyTOPUP_inputs():
1212
),
1313
args=dict(argstr='%s',
1414
),
15-
interp=dict(argstr='-n=%s',
15+
interp=dict(argstr='--interp=%s',
1616
),
1717
in_files=dict(mandatory=True,
1818
argstr='%s',
@@ -32,7 +32,7 @@ def test_ApplyTOPUP_inputs():
3232
out_base=dict(argstr='--out=%s',
3333
),
3434
output_type=dict(),
35-
method=dict(argstr='-m=%s',
35+
method=dict(argstr='--method=%s',
3636
),
3737
)
3838
inputs = ApplyTOPUP.input_spec()

nipype/interfaces/fsl/tests/test_auto_FUGUE.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ def test_FUGUE_inputs():
6161
nohash=True,
6262
),
6363
output_type=dict(),
64-
despike_theshold=dict(argstr='--despikethreshold=%s',
65-
),
6664
icorr=dict(requires=['shift_in_file'],
6765
argstr='--icorr',
6866
),
6967
fmap_in_file=dict(argstr='--loadfmap=%s',
7068
),
69+
despike_threshold=dict(argstr='--despikethreshold=%s',
70+
),
7171
unwarp_direction=dict(argstr='--unwarpdir=%s',
7272
),
7373
fmap_out_file=dict(hash_files=False,

nipype/interfaces/mrtrix/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
SphericallyDeconvolutedStreamlineTrack,
66
ProbabilisticSphericallyDeconvolutedStreamlineTrack)
77
from .tensors import (FSL2MRTrix, ConstrainedSphericalDeconvolution,
8-
DWI2SphericalHarmonicsImage, EstimateResponseForSH)
8+
DWI2SphericalHarmonicsImage, EstimateResponseForSH,
9+
GenerateDirections, FindShPeaks, Directions2Amplitude)
910
from .preprocess import (MRConvert, MRMultiply, MRTrixViewer, MRTrixInfo,
1011
GenerateWhiteMatterMask, DWI2Tensor,
1112
Tensor2ApparentDiffusion, Tensor2FractionalAnisotropy,
1213
Tensor2Vector, MedianFilter3D, Erode, Threshold)
13-
from .convert import MRTrix2TrackVis
14-
14+
from .convert import MRTrix2TrackVis

nipype/interfaces/mrtrix/preprocess.py

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from nipype.interfaces.base import CommandLineInputSpec, CommandLine, traits, TraitedSpec, File, InputMultiPath, isdefined
1313
from nipype.utils.filemanip import split_filename
14-
import os, os.path as op
14+
import os.path as op
1515

1616
class MRConvertInputSpec(CommandLineInputSpec):
1717
in_file = File(exists=True, argstr='%s', mandatory=True, position=-2,
@@ -65,7 +65,11 @@ class MRConvert(CommandLine):
6565

6666
def _list_outputs(self):
6767
outputs = self.output_spec().get()
68-
outputs['converted'] = op.abspath(self._gen_outfilename())
68+
outputs['converted'] = self.inputs.out_filename
69+
if not isdefined(outputs['converted']):
70+
outputs['converted'] = op.abspath(self._gen_outfilename())
71+
else:
72+
outputs['converted'] = op.abspath(outputs['converted'])
6973
return outputs
7074

7175
def _gen_filename(self, name):
@@ -169,7 +173,11 @@ class Tensor2Vector(CommandLine):
169173

170174
def _list_outputs(self):
171175
outputs = self.output_spec().get()
172-
outputs['vector'] = op.abspath(self._gen_outfilename())
176+
outputs['vector'] = self.inputs.out_filename
177+
if not isdefined(outputs['vector']):
178+
outputs['vector'] = op.abspath(self._gen_outfilename())
179+
else:
180+
outputs['vector'] = op.abspath(outputs['vector'])
173181
return outputs
174182

175183
def _gen_filename(self, name):
@@ -210,7 +218,11 @@ class Tensor2FractionalAnisotropy(CommandLine):
210218

211219
def _list_outputs(self):
212220
outputs = self.output_spec().get()
213-
outputs['FA'] = op.abspath(self._gen_outfilename())
221+
outputs['FA'] = self.inputs.out_filename
222+
if not isdefined(outputs['FA']):
223+
outputs['FA'] = op.abspath(self._gen_outfilename())
224+
else:
225+
outputs['FA'] = op.abspath(outputs['FA'])
214226
return outputs
215227

216228
def _gen_filename(self, name):
@@ -251,7 +263,11 @@ class Tensor2ApparentDiffusion(CommandLine):
251263

252264
def _list_outputs(self):
253265
outputs = self.output_spec().get()
254-
outputs['ADC'] = op.abspath(self._gen_outfilename())
266+
outputs['ADC'] = self.inputs.out_filename
267+
if not isdefined(outputs['ADC']):
268+
outputs['ADC'] = op.abspath(self._gen_outfilename())
269+
else:
270+
outputs['ADC'] = op.abspath(outputs['ADC'])
255271
return outputs
256272

257273
def _gen_filename(self, name):
@@ -293,7 +309,11 @@ class MRMultiply(CommandLine):
293309

294310
def _list_outputs(self):
295311
outputs = self.output_spec().get()
296-
outputs['out_file'] = op.abspath(self._gen_outfilename())
312+
outputs['out_file'] = self.inputs.out_filename
313+
if not isdefined(outputs['out_file']):
314+
outputs['out_file'] = op.abspath(self._gen_outfilename())
315+
else:
316+
outputs['out_file'] = op.abspath(outputs['out_file'])
297317
return outputs
298318

299319
def _gen_filename(self, name):
@@ -435,7 +455,11 @@ class Erode(CommandLine):
435455

436456
def _list_outputs(self):
437457
outputs = self.output_spec().get()
438-
outputs['out_file'] = op.abspath(self._gen_outfilename())
458+
outputs['out_file'] = self.inputs.out_filename
459+
if not isdefined(outputs['out_file']):
460+
outputs['out_file'] = op.abspath(self._gen_outfilename())
461+
else:
462+
outputs['out_file'] = op.abspath(outputs['out_file'])
439463
return outputs
440464

441465
def _gen_filename(self, name):
@@ -485,7 +509,11 @@ class Threshold(CommandLine):
485509

486510
def _list_outputs(self):
487511
outputs = self.output_spec().get()
488-
outputs['out_file'] = op.abspath(self._gen_outfilename())
512+
outputs['out_file'] = self.inputs.out_filename
513+
if not isdefined(outputs['out_file']):
514+
outputs['out_file'] = op.abspath(self._gen_outfilename())
515+
else:
516+
outputs['out_file'] = op.abspath(outputs['out_file'])
489517
return outputs
490518

491519
def _gen_filename(self, name):
@@ -526,7 +554,11 @@ class MedianFilter3D(CommandLine):
526554

527555
def _list_outputs(self):
528556
outputs = self.output_spec().get()
529-
outputs['out_file'] = op.abspath(self._gen_outfilename())
557+
outputs['out_file'] = self.inputs.out_filename
558+
if not isdefined(outputs['out_file']):
559+
outputs['out_file'] = op.abspath(self._gen_outfilename())
560+
else:
561+
outputs['out_file'] = op.abspath(outputs['out_file'])
530562
return outputs
531563

532564
def _gen_filename(self, name):
@@ -576,7 +608,11 @@ class MRTransform(CommandLine):
576608

577609
def _list_outputs(self):
578610
outputs = self.output_spec().get()
579-
outputs['out_file'] = op.abspath(self._gen_outfilename())
611+
outputs['out_file'] = self.inputs.out_filename
612+
if not isdefined(outputs['out_file']):
613+
outputs['out_file'] = op.abspath(self._gen_outfilename())
614+
else:
615+
outputs['out_file'] = op.abspath(outputs['out_file'])
580616
return outputs
581617

582618
def _gen_filename(self, name):

nipype/interfaces/mrtrix/tensors.py

Lines changed: 121 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ class DWI2SphericalHarmonicsImage(CommandLine):
7373

7474
def _list_outputs(self):
7575
outputs = self.output_spec().get()
76-
outputs['spherical_harmonics_image'] = op.abspath(self._gen_outfilename())
76+
outputs['spherical_harmonics_image'] = self.inputs.out_filename
77+
if not isdefined(outputs['spherical_harmonics_image']):
78+
outputs['spherical_harmonics_image'] = op.abspath(self._gen_outfilename())
79+
else:
80+
outputs['spherical_harmonics_image'] = op.abspath(outputs['spherical_harmonics_image'])
7781
return outputs
7882

7983
def _gen_filename(self, name):
@@ -148,7 +152,11 @@ class ConstrainedSphericalDeconvolution(CommandLine):
148152

149153
def _list_outputs(self):
150154
outputs = self.output_spec().get()
151-
outputs['spherical_harmonics_image'] = op.abspath(self._gen_outfilename())
155+
outputs['spherical_harmonics_image'] = self.inputs.out_filename
156+
if not isdefined(outputs['spherical_harmonics_image']):
157+
outputs['spherical_harmonics_image'] = op.abspath(self._gen_outfilename())
158+
else:
159+
outputs['spherical_harmonics_image'] = op.abspath(outputs['spherical_harmonics_image'])
152160
return outputs
153161

154162
def _gen_filename(self, name):
@@ -194,7 +202,11 @@ class EstimateResponseForSH(CommandLine):
194202

195203
def _list_outputs(self):
196204
outputs = self.output_spec().get()
197-
outputs['response'] = op.abspath(self._gen_outfilename())
205+
outputs['response'] = self.inputs.out_filename
206+
if not isdefined(outputs['response']):
207+
outputs['response'] = op.abspath(self._gen_outfilename())
208+
else:
209+
outputs['response'] = op.abspath(outputs['response'])
198210
return outputs
199211

200212
def _gen_filename(self, name):
@@ -282,3 +294,109 @@ def _gen_outfilename(self):
282294
_, bvec , _ = split_filename(self.inputs.bvec_file)
283295
_, bval , _ = split_filename(self.inputs.bval_file)
284296
return bvec + '_' + bval + '.txt'
297+
298+
299+
class GenerateDirectionsInputSpec(CommandLineInputSpec):
300+
num_dirs = traits.Int(mandatory=True, argstr='%s', position=-2 , desc='the number of directions to generate.')
301+
302+
power = traits.Float(argstr='-power %s', desc='specify exponent to use for repulsion power law.')
303+
niter = traits.Int(argstr='-niter %s', desc='specify the maximum number of iterations to perform.')
304+
display_info = traits.Bool(argstr='-info', desc='Display information messages.')
305+
quiet_display = traits.Bool(argstr='-quiet', desc='do not display information messages or progress status.')
306+
display_debug = traits.Bool(argstr='-debug', desc='Display debugging messages.')
307+
out_file = File("directions.txt", argstr='%s', hash_files=False,
308+
position= -1, desc='the text file to write the directions to, as [ az el ] pairs.', usedefault=True)
309+
310+
class GenerateDirectionsOutputSpec(TraitedSpec):
311+
out_file = File(exists=True, desc='directions file')
312+
313+
class GenerateDirections(CommandLine):
314+
"""
315+
generate a set of directions evenly distributed over a hemisphere.
316+
317+
Example
318+
-------
319+
320+
>>> import nipype.interfaces.mrtrix as mrt
321+
>>> gendir = mrt.GenerateDirections()
322+
>>> gendir.inputs.num_dirs = 300
323+
>>> gendir.run() # doctest: +SKIP
324+
"""
325+
326+
_cmd = 'gendir'
327+
input_spec=GenerateDirectionsInputSpec
328+
output_spec=GenerateDirectionsOutputSpec
329+
330+
331+
class FindShPeaksInputSpec(CommandLineInputSpec):
332+
in_file = File(exists=True, argstr='%s', mandatory=True, position=-3, desc='the input image of SH coefficients.')
333+
directions_file = File(exists=True, argstr='%s', mandatory=True, position=-2, desc='the set of directions to use as seeds for the peak finding')
334+
peaks_image = File(exists=True, argstr='-peaks %s', desc='the program will try to find the peaks that most closely match those in the image provided')
335+
num_peaks = traits.Int(argstr='-num %s', desc='the number of peaks to extract (default is 3)')
336+
peak_directions = traits.List(traits.Float, argstr='-direction %s', sep=' ', minlen=2, maxlen=2,
337+
desc='phi theta. the direction of a peak to estimate. The algorithm will attempt to find the same number of peaks as have been specified using this option ' \
338+
' phi: the azimuthal angle of the direction (in degrees). theta: the elevation angle of the direction (in degrees, from the vertical z-axis)')
339+
peak_threshold = traits.Float(argstr='-threshold %s', desc='only peak amplitudes greater than the threshold will be considered')
340+
display_info = traits.Bool(argstr='-info', desc='Display information messages.')
341+
quiet_display = traits.Bool(argstr='-quiet', desc='do not display information messages or progress status.')
342+
display_debug = traits.Bool(argstr='-debug', desc='Display debugging messages.')
343+
out_file = File(name_template="%s_peak_dirs.mif", keep_extension=False, argstr='%s', hash_files=False, position= -1,
344+
desc='the output image. Each volume corresponds to the x, y & z component of each peak direction vector in turn', name_source=["in_file"])
345+
346+
class FindShPeaksOutputSpec(TraitedSpec):
347+
out_file = File(exists=True, desc='Peak directions image')
348+
349+
class FindShPeaks(CommandLine):
350+
"""
351+
identify the orientations of the N largest peaks of a SH profile
352+
353+
Example
354+
-------
355+
356+
>>> import nipype.interfaces.mrtrix as mrt
357+
>>> shpeaks = mrt.FindShPeaks()
358+
>>> shpeaks.inputs.in_file = 'csd.mif'
359+
>>> shpeaks.inputs.directions_file = 'dirs.txt'
360+
>>> shpeaks.inputs.num_peaks = 2
361+
>>> shpeaks.run() # doctest: +SKIP
362+
"""
363+
364+
_cmd = 'find_SH_peaks'
365+
input_spec=FindShPeaksInputSpec
366+
output_spec=FindShPeaksOutputSpec
367+
368+
369+
370+
class Directions2AmplitudeInputSpec(CommandLineInputSpec):
371+
in_file = File(exists=True, argstr='%s', mandatory=True, position=-2, desc='the input directions image. Each volume corresponds to the x, y & z component of each direction vector in turn.')
372+
peaks_image = File(exists=True, argstr='-peaks %s', desc='the program will try to find the peaks that most closely match those in the image provided')
373+
num_peaks = traits.Int(argstr='-num %s', desc='the number of peaks to extract (default is 3)')
374+
peak_directions = traits.List(traits.Float, argstr='-direction %s', sep=' ', minlen=2, maxlen=2,
375+
desc='phi theta. the direction of a peak to estimate. The algorithm will attempt to find the same number of peaks as have been specified using this option ' \
376+
' phi: the azimuthal angle of the direction (in degrees). theta: the elevation angle of the direction (in degrees, from the vertical z-axis)')
377+
display_info = traits.Bool(argstr='-info', desc='Display information messages.')
378+
quiet_display = traits.Bool(argstr='-quiet', desc='do not display information messages or progress status.')
379+
display_debug = traits.Bool(argstr='-debug', desc='Display debugging messages.')
380+
out_file = File(name_template="%s_amplitudes.mif", keep_extension=False, argstr='%s', hash_files=False, position= -1,
381+
desc='the output amplitudes image', name_source=["in_file"])
382+
383+
class Directions2AmplitudeOutputSpec(TraitedSpec):
384+
out_file = File(exists=True, desc='amplitudes image')
385+
386+
class Directions2Amplitude(CommandLine):
387+
"""
388+
convert directions image to amplitudes
389+
390+
Example
391+
-------
392+
393+
>>> import nipype.interfaces.mrtrix as mrt
394+
>>> amplitudes = mrt.Directions2Amplitude()
395+
>>> amplitudes.inputs.in_file = 'peak_directions.mif'
396+
>>> amplitudes.run() # doctest: +SKIP
397+
"""
398+
399+
_cmd = 'dir2amp'
400+
input_spec=Directions2AmplitudeInputSpec
401+
output_spec=Directions2AmplitudeOutputSpec
402+

0 commit comments

Comments
 (0)