Skip to content

Commit bab21d6

Browse files
committed
Merging changes from upstream/master
2 parents 4b8bed7 + e48c9c8 commit bab21d6

36 files changed

+2861
-11
lines changed

nipype/interfaces/ants/segmentation.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
import os
1515
from ...external.due import BibTeX
1616
from ...utils.filemanip import split_filename, copyfile
17-
from ..base import TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined
17+
from ..base import (TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined,
18+
_exists_in_path)
1819
from .base import ANTSCommand, ANTSCommandInputSpec
1920

2021

@@ -692,6 +693,40 @@ class BrainExtraction(ANTSCommand):
692693
output_spec = BrainExtractionOutputSpec
693694
_cmd = 'antsBrainExtraction.sh'
694695

696+
def _run_interface(self, runtime, correct_return_codes=(0,)):
697+
# antsBrainExtraction.sh requires ANTSPATH to be defined
698+
out_environ = self._get_environ()
699+
if out_environ.get('ANTSPATH') is None:
700+
runtime.environ.update(out_environ)
701+
executable_name = self.cmd.split()[0]
702+
exist_val, cmd_path = _exists_in_path(executable_name, runtime.environ)
703+
if not exist_val:
704+
raise IOError("command '%s' could not be found on host %s" %
705+
(self.cmd.split()[0], runtime.hostname))
706+
707+
# Set the environment variable if found
708+
runtime.environ.update({'ANTSPATH': os.path.dirname(cmd_path)})
709+
710+
runtime = super(BrainExtraction, self)._run_interface(runtime)
711+
712+
# Still, double-check if it didn't found N4
713+
if 'we cant find' in runtime.stdout:
714+
for line in runtime.stdout.split('\n'):
715+
if line.strip().startswith('we cant find'):
716+
tool = line.strip().replace('we cant find the', '').split(' ')[0]
717+
break
718+
719+
errmsg = ('antsBrainExtraction.sh requires %s the environment variable '
720+
'ANTSPATH to be defined' % tool)
721+
if runtime.stderr is None:
722+
runtime.stderr = errmsg
723+
else:
724+
runtime.stderr += '\n' + errmsg
725+
runtime.returncode = 1
726+
self.raise_exception(runtime)
727+
728+
return runtime
729+
695730
def _list_outputs(self):
696731
outputs = self._outputs().get()
697732
outputs['BrainExtractionMask'] = os.path.join(os.getcwd(),

nipype/interfaces/freesurfer/preprocess.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ class ReconAllInputSpec(CommandLineInputSpec):
652652
desc="Use, delete or overwrite existing expert options file")
653653
subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False,
654654
desc='path to subjects directory', genfile=True)
655-
flags = traits.Str(argstr='%s', desc='additional parameters')
655+
flags = InputMultiPath(traits.Str, argstr='%s', desc='additional parameters')
656656

657657
# Expert options
658658
talairach = traits.Str(desc="Flags to pass to talairach commands", xor=['expert'])
@@ -703,7 +703,12 @@ class ReconAll(CommandLine):
703703
>>> reconall.inputs.T1_files = 'structural.nii'
704704
>>> reconall.cmdline # doctest: +ALLOW_UNICODE
705705
'recon-all -all -i structural.nii -subjid foo -sd .'
706-
706+
>>> reconall.inputs.flags = "-qcache"
707+
>>> reconall.cmdline # doctest: +ALLOW_UNICODE
708+
'recon-all -all -i structural.nii -qcache -subjid foo -sd .'
709+
>>> reconall.inputs.flags = ["-cw256", "-qcache"]
710+
>>> reconall.cmdline # doctest: +ALLOW_UNICODE
711+
'recon-all -all -i structural.nii -cw256 -qcache -subjid foo -sd .'
707712
"""
708713

709714
_cmd = 'recon-all'
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
4+
"""
5+
The niftyseg module provides classes for interfacing with the `NIFTYSEG
6+
<https://sourceforge.net/projects/niftyseg/>`_ command line tools.
7+
8+
Top-level namespace for niftyseg.
9+
"""
10+
11+
from .em import EM
12+
from .label_fusion import LabelFusion, CalcTopNCC
13+
from .lesions import FillLesions
14+
from .maths import (UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths,
15+
Merge)
16+
from .patchmatch import PatchMatch
17+
from .stats import UnaryStats, BinaryStats

nipype/interfaces/niftyseg/base.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
4+
"""
5+
The niftyseg module provides classes for interfacing with `niftyseg
6+
<https://sourceforge.net/projects/niftyseg/>`_ command line tools.
7+
These are the base tools for working with niftyseg.
8+
EM Statistical Segmentation tool is found in niftyseg/em.py
9+
Fill lesions tool is found in niftyseg/lesions.py
10+
Mathematical operation tool is found in niftyseg/maths.py
11+
Patch Match tool is found in niftyseg/patchmatch.py
12+
Statistical operation tool is found in niftyseg/stats.py
13+
Label Fusion and CalcTopNcc tools are in niftyseg/steps.py
14+
Examples
15+
--------
16+
See the docstrings of the individual classes for examples.
17+
"""
18+
19+
from nipype.interfaces.niftyreg.base import NiftyRegCommand, no_nifty_package
20+
import subprocess
21+
import warnings
22+
23+
24+
warn = warnings.warn
25+
warnings.filterwarnings('always', category=UserWarning)
26+
27+
28+
class NiftySegCommand(NiftyRegCommand):
29+
"""
30+
Base support interface for NiftySeg commands.
31+
"""
32+
_suffix = '_ns'
33+
_min_version = None
34+
35+
def __init__(self, **inputs):
36+
super(NiftySegCommand, self).__init__(**inputs)
37+
38+
def get_version(self):
39+
if no_nifty_package(cmd=self.cmd):
40+
return None
41+
# exec_cmd = ''.join((self.cmd, ' --version'))
42+
exec_cmd = 'seg_EM --version'
43+
# Using seg_EM for version (E.G: seg_stats --version doesn't work)
44+
return subprocess.check_output(exec_cmd, shell=True).strip('\n')

nipype/interfaces/niftyseg/em.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
4+
"""
5+
Nipype interface for seg_EM.
6+
7+
The em module provides higher-level interfaces to some of the operations
8+
that can be performed with the seg_em command-line program.
9+
10+
Examples
11+
--------
12+
See the docstrings of the individual classes for examples.
13+
14+
Change directory to provide relative paths for doctests
15+
>>> import os
16+
>>> filepath = os.path.dirname( os.path.realpath( __file__ ) )
17+
>>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data'))
18+
>>> os.chdir(datadir)
19+
"""
20+
21+
from ..base import (TraitedSpec, File, traits, CommandLineInputSpec,
22+
InputMultiPath)
23+
from .base import NiftySegCommand
24+
from ..niftyreg.base import get_custom_path
25+
26+
27+
class EMInputSpec(CommandLineInputSpec):
28+
"""Input Spec for EM."""
29+
in_file = File(argstr='-in %s',
30+
exists=True,
31+
mandatory=True,
32+
desc='Input image to segment',
33+
position=4)
34+
35+
mask_file = File(argstr='-mask %s',
36+
exists=True,
37+
desc='Filename of the ROI for label fusion')
38+
39+
# Priors
40+
no_prior = traits.Int(argstr='-nopriors %s',
41+
mandatory=True,
42+
desc='Number of classes to use without prior',
43+
xor=['prior_4D', 'priors'])
44+
45+
prior_4D = File(argstr='-prior4D %s',
46+
exists=True,
47+
mandatory=True,
48+
desc='4D file containing the priors',
49+
xor=['no_prior', 'priors'])
50+
51+
priors = InputMultiPath(argstr='%s',
52+
mandatory=True,
53+
desc='List of priors filepaths.',
54+
xor=['no_prior', 'prior_4D'])
55+
56+
# iterations
57+
max_iter = traits.Int(argstr='-max_iter %s', default=100,
58+
desc='Maximum number of iterations')
59+
60+
min_iter = traits.Int(argstr='-min_iter %s', default=0,
61+
desc='Minimun number of iterations')
62+
63+
# other options
64+
bc_order_val = traits.Int(argstr='-bc_order %s', default=3,
65+
desc='Polynomial order for the bias field')
66+
67+
mrf_beta_val = traits.Float(argstr='-mrf_beta %s',
68+
desc='Weight of the Markov Random Field')
69+
70+
desc = 'Bias field correction will run only if the ratio of improvement \
71+
is below bc_thresh. (default=0 [OFF])'
72+
bc_thresh_val = traits.Float(argstr='-bc_thresh %s', default=0, desc=desc)
73+
74+
desc = 'Amount of regularization over the diagonal of the covariance \
75+
matrix [above 1]'
76+
reg_val = traits.Float(argstr='-reg %s', desc=desc)
77+
78+
desc = 'Outlier detection as in (Van Leemput TMI 2003). <fl1> is the \
79+
Mahalanobis threshold [recommended between 3 and 7] <fl2> is a convergence \
80+
ratio below which the outlier detection is going to be done [recommended 0.01]'
81+
outlier_val = traits.Tuple(traits.Float(), traits.Float(),
82+
argstr='-outlier %s %s',
83+
desc=desc)
84+
85+
desc = 'Relax Priors [relaxation factor: 0<rf<1 (recommended=0.5), \
86+
gaussian regularization: gstd>0 (recommended=2.0)] /only 3D/'
87+
relax_priors = traits.Tuple(traits.Float(), traits.Float(),
88+
argstr='-rf %s %s',
89+
desc=desc)
90+
91+
# outputs
92+
out_file = File(name_source=['in_file'],
93+
name_template='%s_em.nii.gz',
94+
argstr='-out %s',
95+
desc='Output segmentation')
96+
out_bc_file = File(name_source=['in_file'],
97+
name_template='%s_bc_em.nii.gz',
98+
argstr='-bc_out %s',
99+
desc='Output bias corrected image')
100+
out_outlier_file = File(name_source=['in_file'],
101+
name_template='%s_outlier_em.nii.gz',
102+
argstr='-out_outlier %s',
103+
desc='Output outlierness image')
104+
105+
106+
class EMOutputSpec(TraitedSpec):
107+
"""Output Spec for EM."""
108+
out_file = File(desc="Output segmentation")
109+
out_bc_file = File(desc="Output bias corrected image")
110+
out_outlier_file = File(desc='Output outlierness image')
111+
112+
113+
class EM(NiftySegCommand):
114+
"""Interface for executable seg_EM from NiftySeg platform.
115+
116+
seg_EM is a general purpose intensity based image segmentation tool. In
117+
it's simplest form, it takes in one 2D or 3D image and segments it in n
118+
classes.
119+
120+
For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg
121+
For Documentation, see:
122+
http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation
123+
124+
Examples
125+
--------
126+
>>> from nipype.interfaces import niftyseg
127+
>>> node = niftyseg.EM()
128+
>>> node.inputs.in_file = 'im1.nii'
129+
>>> node.inputs.no_prior = 4
130+
>>> node.cmdline # doctest: +ALLOW_UNICODE
131+
'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii.gz \
132+
-out im1_em.nii.gz -out_outlier im1_outlier_em.nii.gz'
133+
134+
"""
135+
_cmd = get_custom_path('seg_EM', env_dir='NIFTYSEGDIR')
136+
_suffix = '_em'
137+
input_spec = EMInputSpec
138+
output_spec = EMOutputSpec
139+
140+
def _format_arg(self, opt, spec, val):
141+
"""Convert input to appropriate format for seg_EM."""
142+
if opt == 'priors':
143+
_nb_priors = len(self.inputs.priors)
144+
return '-priors %d %s' % (_nb_priors, ' '.join(self.inputs.priors))
145+
else:
146+
return super(EM, self)._format_arg(opt, spec, val)

0 commit comments

Comments
 (0)