Skip to content

Commit 588c7ef

Browse files
committed
[FSL] Updated BEDPOSTX and XFibres
Old interfaces are still available as OldBEDPOSTX and OldXFibres
1 parent f626d94 commit 588c7ef

File tree

11 files changed

+857
-259
lines changed

11 files changed

+857
-259
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Next Release
22
============
33

4+
* ENH: Updated FSL interfaces: BEDPOSTX and XFibres, former interfaces are still available with the prefix `Old`.
45
* ENH: New FSL interface: EpiReg
56
* ENH: New Freesurfer interface: Tkregister2 (for conversion of fsl style matrices to freesurfer format)
67
* ENH: New FSL interfaces: WarpPoints, WarpPointsToStd.

nipype/interfaces/fsl/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
from .epi import (PrepareFieldmap, TOPUP, ApplyTOPUP, Eddy, EPIDeWarp,
2222
SigLoss, EddyCorrect, EpiReg)
2323

24-
from .dti import (BEDPOSTX, DTIFit, ProbTrackX, ProbTrackX2,
24+
from .dti import (BEDPOSTX, XFibres, DTIFit, ProbTrackX, ProbTrackX2,
2525
VecReg, ProjThresh, FindTheBiggest, DistanceMap,
26-
TractSkeleton, XFibres, MakeDyadicVectors)
26+
TractSkeleton, MakeDyadicVectors, OldBEDPOSTX, OldXFibres)
2727
from .maths import (ChangeDataType, Threshold, MeanImage, ApplyMask,
2828
IsotropicSmooth, TemporalFilter, DilateImage, ErodeImage,
2929
SpatialFilter, UnaryMaths, BinaryMaths, MultiImageMaths)

nipype/interfaces/fsl/base.py

Lines changed: 183 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
import os
3030
import warnings
3131

32-
from ...utils.filemanip import fname_presuffix
33-
from ..base import (CommandLine, traits, CommandLineInputSpec, isdefined)
32+
from ...utils.filemanip import fname_presuffix, split_filename, copyfile
33+
from ..base import (traits, isdefined,
34+
CommandLine, CommandLineInputSpec, TraitedSpec,
35+
File, Directory, InputMultiPath, OutputMultiPath)
3436

3537
warn = warnings.warn
3638
warnings.filterwarnings('always', category=UserWarning)
@@ -243,6 +245,185 @@ def _overload_extension(self, value, name=None):
243245
return value + Info.output_type_to_ext(self.inputs.output_type)
244246

245247

248+
class FSLXCommandInputSpec(FSLCommandInputSpec):
249+
out_dir = Directory('.', mandatory=True, desc='output directory',
250+
usedefault=True, position=1, argstr='%s')
251+
dwi = File(exists=True, argstr='--data=%s', mandatory=True,
252+
desc='diffusion weighted image data file')
253+
mask = File(exists=True, argstr='--mask=%s', mandatory=True,
254+
desc='brain binary mask file (i.e. from BET)')
255+
bvecs = File(exists=True, argstr='--bvecs=%s', mandatory=True,
256+
desc='b vectors file')
257+
bvals = File(exists=True, argstr='--bvals=%s', mandatory=True,
258+
desc='b values file')
259+
260+
logdir = Directory('logdir', argstr='--logdir=%s', usedefault=True)
261+
n_fibres = traits.Range(low=1, argstr='--nfibres=%d', desc=('Maximum '
262+
'number of fibres to fit in each voxel'))
263+
model = traits.Enum(1, 2, argstr='--model=%d',
264+
desc=('use monoexponential (1, default, required for '
265+
'single-shell) or multiexponential (2, multi-'
266+
'shell) model'))
267+
fudge = traits.Int(argstr='--fudge=%d',
268+
desc='ARD fudge factor')
269+
n_jumps = traits.Int(5000, argstr='--njumps=%d',
270+
desc='Num of jumps to be made by MCMC')
271+
burn_in = traits.Range(low=0, default=0, argstr='--burnin=%d',
272+
desc=('Total num of jumps at start of MCMC to be '
273+
'discarded'))
274+
burn_in_no_ard = traits.Range(low=0, default=0, argstr='--burninnoard=%d',
275+
desc=('num of burnin jumps before the ard is'
276+
' imposed'))
277+
sample_every = traits.Range(low=0, default=1, argstr='--sampleevery=%d',
278+
desc='Num of jumps for each sample (MCMC)')
279+
update_proposal_every = traits.Range(low=1, default=40,
280+
argstr='--updateproposalevery=%d',
281+
desc=('Num of jumps for each update '
282+
'to the proposal density std '
283+
'(MCMC)'))
284+
seed = traits.Int(argstr='--seed=%d',
285+
desc='seed for pseudo random number generator')
286+
287+
_xor_inputs1 = ('no_ard', 'all_ard')
288+
no_ard = traits.Bool(argstr='--noard', xor=_xor_inputs1,
289+
desc='Turn ARD off on all fibres')
290+
all_ard = traits.Bool(argstr='--allard', xor=_xor_inputs1,
291+
desc='Turn ARD on on all fibres')
292+
293+
_xor_inputs2 = ('no_spat', 'non_linear', 'cnlinear')
294+
no_spat = traits.Bool(argstr='--nospat', xor=_xor_inputs2,
295+
desc='Initialise with tensor, not spatially')
296+
non_linear = traits.Bool(argstr='--nonlinear', xor=_xor_inputs2,
297+
desc='Initialise with nonlinear fitting')
298+
cnlinear = traits.Bool(argstr='--cnonlinear', xor=_xor_inputs2,
299+
desc=('Initialise with constrained nonlinear '
300+
'fitting'))
301+
rician = traits.Bool(argstr='--rician', desc=('use Rician noise modeling'))
302+
303+
_xor_inputs3 = ['f0_noard', 'f0_ard']
304+
f0_noard = traits.Bool(argstr='--f0', xor=_xor_inputs3,
305+
desc=('Noise floor model: add to the model an '
306+
'unattenuated signal compartment f0'))
307+
f0_ard = traits.Bool(argstr='--f0 --ardf0', xor=_xor_inputs3 + ['all_ard'],
308+
desc=('Noise floor model: add to the model an '
309+
'unattenuated signal compartment f0'))
310+
force_dir = traits.Bool(False, argstr='--forcedir', usedefault=True,
311+
desc=('use the actual directory name given '
312+
'(do not add + to make a new directory)'))
313+
314+
315+
class FSLXCommandOutputSpec(TraitedSpec):
316+
merged_thsamples = OutputMultiPath(File(exists=True), desc=('Samples from '
317+
'the distribution on theta'))
318+
merged_phsamples = OutputMultiPath(File(exists=True), desc=('Samples from '
319+
'the distribution on phi'))
320+
merged_fsamples = OutputMultiPath(File(exists=True),
321+
desc=('Samples from the distribution on '
322+
'anisotropic volume fraction.'))
323+
324+
mean_thsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
325+
'distribution on theta'))
326+
mean_phsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
327+
'distribution on phi'))
328+
mean_fsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
329+
'distribution on f anisotropy'))
330+
331+
mean_dsamples = File(exists=True, desc='Mean of distribution on '
332+
'diffusivity d')
333+
mean_S0samples = File(exists=True, desc='Mean of distribution on T2w'
334+
'baseline signal intensity S0')
335+
mean_tausamples = File(exists=True, desc='Mean of distribution on '
336+
'tau samples (only with rician noise)')
337+
338+
dyads = OutputMultiPath(File(exists=True), desc=('Mean of PDD distribution'
339+
' in vector form.'))
340+
dyads_disp = OutputMultiPath(File(exists=True), desc=('Uncertainty on the '
341+
' estimated fiber orientation'))
342+
fsamples = OutputMultiPath(File(exists=True), desc=('Samples from the '
343+
'distribution on anisotropic volume fraction'))
344+
345+
346+
class FSLXCommand(FSLCommand):
347+
"""
348+
Base support for ``xfibres`` and ``bedpostx``
349+
"""
350+
input_spec = FSLXCommandInputSpec
351+
output_spec = FSLXCommandOutputSpec
352+
353+
def _run_interface(self, runtime):
354+
subjectdir = os.path.abspath(self.inputs.out_dir)
355+
out_dir = subjectdir + '.bedpostX'
356+
357+
if isdefined(self.inputs.force_dir) and self.inputs.force_dir:
358+
out_dir = os.path.abspath(self.inputs.out_dir)
359+
self._out_dir = out_dir
360+
361+
if not os.path.exists(out_dir):
362+
os.makedirs(out_dir)
363+
364+
_, _, ext = split_filename(self.inputs.mask)
365+
copyfile(self.inputs.mask,
366+
os.path.join(subjectdir,
367+
'nodif_brain_mask' + ext))
368+
_, _, ext = split_filename(self.inputs.dwi)
369+
copyfile(self.inputs.dwi,
370+
os.path.join(subjectdir, 'data' + ext))
371+
copyfile(self.inputs.bvals,
372+
os.path.join(subjectdir, 'bvals'))
373+
copyfile(self.inputs.bvecs,
374+
os.path.join(subjectdir, 'bvecs'))
375+
376+
runtime = super(FSLXCommand, self)._run_interface(runtime)
377+
if runtime.stderr:
378+
self.raise_exception(runtime)
379+
return runtime
380+
381+
def _list_outputs(self):
382+
outputs = self.output_spec().get()
383+
out_dir = self._out_dir
384+
385+
for k in outputs.keys():
386+
if k not in ('outputtype', 'environ', 'args', 'bpx_out_directory',
387+
'xfms_directory', 'mean_dsamples', 'mean_S0samples',
388+
'mean_tausamples'):
389+
outputs[k] = []
390+
391+
outputs['mean_dsamples'] = self._gen_fname('mean_dsamples',
392+
cwd=out_dir)
393+
outputs['mean_S0samples'] = self._gen_fname('mean_S0samples',
394+
cwd=out_dir)
395+
396+
if isdefined(self.inputs.rician) and self.inputs.rician:
397+
outputs['mean_tausamples'] = self._gen_fname('mean_tausamples',
398+
cwd=out_dir)
399+
400+
for i in xrange(1, self.inputs.fibres + 1):
401+
outputs['merged_thsamples'].append(self._gen_fname(('merged_th%d'
402+
'samples') % i),
403+
cwd=out_dir)
404+
outputs['merged_phsamples'].append(self._gen_fname(('merged_ph%d'
405+
'samples') % i),
406+
cwd=out_dir)
407+
outputs['merged_fsamples'].append(self._gen_fname(('merged_f%d'
408+
'samples') % i),
409+
cwd=out_dir)
410+
411+
outputs['mean_thsamples'].append(self._gen_fname(('mean_th%d'
412+
'samples') % i),
413+
cwd=out_dir)
414+
outputs['mean_phsamples'].append(self._gen_fname(('mean_ph%d'
415+
'samples') % i),
416+
cwd=out_dir)
417+
outputs['mean_fsamples'].append(self._gen_fname(('mean_f%d'
418+
'samples') % i),
419+
cwd=out_dir)
420+
outputs['dyads'].append(self._gen_fname('dyads%d' % i),
421+
cwd=out_dir)
422+
outputs['dyads_dispersion'].append(self._gen_fname(('dyads%d'
423+
'_dispersion') % i),
424+
cwd=out_dir)
425+
return outputs
426+
246427

247428
def check_fsl():
248429
ver = Info.version()

0 commit comments

Comments
 (0)