Skip to content

Commit 93c475b

Browse files
committed
Merge branch 'master' into remove_users_docs
2 parents 20dd4fe + 39675df commit 93c475b

16 files changed

+138
-40
lines changed

docker/generate_dockerfiles.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ function generate_main_dockerfile() {
109109
--miniconda env_name=neuro \
110110
pip_install="grabbit==0.1.2" \
111111
--run-bash "mkdir -p /src/pybids
112-
&& curl -sSL --retry 5 https://github.com/INCF/pybids/tarball/0.6.5
112+
&& curl -sSL --retry 5 https://github.com/INCF/pybids/tarball/0.5.1
113113
| tar -xz -C /src/pybids --strip-components 1
114114
&& source activate neuro
115115
&& pip install --no-cache-dir -e /src/pybids" \

nipype/info.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def get_nipype_gitversion():
154154
if sys.version_info <= (3, 4):
155155
REQUIRES.append('configparser')
156156

157-
TESTS_REQUIRES = ['pytest-cov', 'codecov', 'pytest-env']
157+
TESTS_REQUIRES = ['pytest-cov', 'codecov', 'pytest-env', 'coverage<5']
158158

159159
EXTRA_REQUIRES = {
160160
'doc': ['Sphinx>=1.4', 'numpydoc', 'matplotlib', 'pydotplus', 'pydot>=1.2.3'],

nipype/interfaces/ants/segmentation.py

+6-17
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ class LaplacianThicknessInputSpec(ANTSCommandInputSpec):
203203
desc='name of output file',
204204
argstr='%s',
205205
position=3,
206-
genfile=True,
206+
name_source=['input_wm'],
207+
name_template='%s_thickness',
208+
keep_extension=True,
207209
hash_files=False)
208210
smooth_param = traits.Float(argstr='smoothparam=%d', desc='', position=4)
209211
prior_thickness = traits.Float(
@@ -228,6 +230,9 @@ class LaplacianThickness(ANTSCommand):
228230
>>> cort_thick = LaplacianThickness()
229231
>>> cort_thick.inputs.input_wm = 'white_matter.nii.gz'
230232
>>> cort_thick.inputs.input_gm = 'gray_matter.nii.gz'
233+
>>> cort_thick.cmdline
234+
'LaplacianThickness white_matter.nii.gz gray_matter.nii.gz white_matter_thickness.nii.gz'
235+
231236
>>> cort_thick.inputs.output_image = 'output_thickness.nii.gz'
232237
>>> cort_thick.cmdline
233238
'LaplacianThickness white_matter.nii.gz gray_matter.nii.gz output_thickness.nii.gz'
@@ -238,22 +243,6 @@ class LaplacianThickness(ANTSCommand):
238243
input_spec = LaplacianThicknessInputSpec
239244
output_spec = LaplacianThicknessOutputSpec
240245

241-
def _gen_filename(self, name):
242-
if name == 'output_image':
243-
output = self.inputs.output_image
244-
if not isdefined(output):
245-
_, name, ext = split_filename(self.inputs.input_wm)
246-
output = name + '_thickness' + ext
247-
return output
248-
return None
249-
250-
def _list_outputs(self):
251-
outputs = self._outputs().get()
252-
_, name, ext = split_filename(os.path.abspath(self.inputs.input_wm))
253-
outputs['output_image'] = os.path.join(os.getcwd(), ''.join(
254-
(name, self.inputs.output_image, ext)))
255-
return outputs
256-
257246

258247
class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec):
259248
dimension = traits.Enum(

nipype/interfaces/ants/tests/test_auto_LaplacianThickness.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ def test_LaplacianThickness_inputs():
3636
),
3737
output_image=dict(
3838
argstr='%s',
39-
genfile=True,
4039
hash_files=False,
40+
keep_extension=True,
41+
name_source=['input_wm'],
42+
name_template='%s_thickness',
4143
position=3,
4244
),
4345
prior_thickness=dict(

nipype/interfaces/base/specs.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ def get_hashval(self, hash_method=None):
234234
The md5 hash value of the traited spec
235235
236236
"""
237-
238237
list_withhash = []
239238
list_nofilename = []
240239
for name, val in sorted(self.trait_get().items()):
@@ -309,6 +308,10 @@ def _get_sorteddict(self,
309308
out = objekt
310309
return out
311310

311+
@property
312+
def __all__(self):
313+
return self.copyable_trait_names()
314+
312315

313316
class TraitedSpec(BaseTraitedSpec):
314317
""" Create a subclass with strict traits.

nipype/interfaces/base/tests/test_resource_monitor.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@
1818
from ... import utility as niu
1919

2020
# Try to enable the resource monitor
21-
config.enable_resource_monitor()
2221
run_profile = config.resource_monitor
2322

2423

24+
@pytest.fixture(scope="module")
25+
def use_resource_monitor():
26+
config.enable_resource_monitor()
27+
yield
28+
config.disable_resource_monitor()
29+
30+
2531
class UseResourcesInputSpec(CommandLineInputSpec):
2632
mem_gb = traits.Float(
2733
desc='Number of GB of RAM to use', argstr='-g %f', mandatory=True)
@@ -51,7 +57,7 @@ class UseResources(CommandLine):
5157
os.getenv('CI_SKIP_TEST', False), reason='disabled in CI tests')
5258
@pytest.mark.parametrize("mem_gb,n_procs", [(0.5, 3), (2.2, 8), (0.8, 4),
5359
(1.5, 1)])
54-
def test_cmdline_profiling(tmpdir, mem_gb, n_procs):
60+
def test_cmdline_profiling(tmpdir, mem_gb, n_procs, use_resource_monitor):
5561
"""
5662
Test runtime profiler correctly records workflow RAM/CPUs consumption
5763
of a CommandLine-derived interface
@@ -73,7 +79,7 @@ def test_cmdline_profiling(tmpdir, mem_gb, n_procs):
7379
True, reason='test disabled temporarily, until funcion profiling works')
7480
@pytest.mark.parametrize("mem_gb,n_procs", [(0.5, 3), (2.2, 8), (0.8, 4),
7581
(1.5, 1)])
76-
def test_function_profiling(tmpdir, mem_gb, n_procs):
82+
def test_function_profiling(tmpdir, mem_gb, n_procs, use_resource_monitor):
7783
"""
7884
Test runtime profiler correctly records workflow RAM/CPUs consumption
7985
of a Function interface

nipype/interfaces/base/tests/test_specs.py

+48
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
from ....utils.filemanip import split_filename
1212
from ... import base as nib
1313
from ...base import traits, Undefined
14+
from ....interfaces import fsl
15+
from ...utility.wrappers import Function
16+
from ....pipeline import Node
17+
1418

1519
standard_library.install_aliases()
1620

@@ -47,6 +51,20 @@ class spec(nib.TraitedSpec):
4751
assert infields.__repr__() == '\nfoo = 1\ngoo = 0.0\n'
4852

4953

54+
def test_TraitedSpec_tab_completion():
55+
bet_nd = Node(fsl.BET(), name='bet')
56+
bet_interface = fsl.BET()
57+
bet_inputs = bet_nd.inputs.class_editable_traits()
58+
bet_outputs = bet_nd.outputs.class_editable_traits()
59+
60+
# Check __all__ for bet node and interface inputs
61+
assert set(bet_nd.inputs.__all__) == set(bet_inputs)
62+
assert set(bet_interface.inputs.__all__) == set(bet_inputs)
63+
64+
# Check __all__ for bet node outputs
65+
assert set(bet_nd.outputs.__all__) == set(bet_outputs)
66+
67+
5068
@pytest.mark.skip
5169
def test_TraitedSpec_dynamic():
5270
from pickle import dumps, loads
@@ -63,6 +81,36 @@ def test_TraitedSpec_dynamic():
6381
assign_a_again
6482

6583

84+
def test_DynamicTraitedSpec_tab_completion():
85+
def extract_func(list_out):
86+
return list_out[0]
87+
88+
# Define interface
89+
func_interface = Function(input_names=["list_out"],
90+
output_names=["out_file", "another_file"],
91+
function=extract_func)
92+
# Define node
93+
list_extract = Node(Function(
94+
input_names=["list_out"], output_names=["out_file"],
95+
function=extract_func), name="list_extract")
96+
97+
# Check __all__ for interface inputs
98+
expected_input = set(list_extract.inputs.editable_traits())
99+
assert(set(func_interface.inputs.__all__) == expected_input)
100+
101+
# Check __all__ for node inputs
102+
assert(set(list_extract.inputs.__all__) == expected_input)
103+
104+
# Check __all__ for node outputs
105+
expected_output = set(list_extract.outputs.editable_traits())
106+
assert(set(list_extract.outputs.__all__) == expected_output)
107+
108+
# Add trait and retest
109+
list_extract._interface._output_names.append('added_out_trait')
110+
expected_output.add('added_out_trait')
111+
assert(set(list_extract.outputs.__all__) == expected_output)
112+
113+
66114
def test_TraitedSpec_logic():
67115
class spec3(nib.TraitedSpec):
68116
_xor_inputs = ('foo', 'bar')

nipype/interfaces/fsl/dti.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class DTIFitOutputSpec(TraitedSpec):
8585
'diffusion weighting'))
8686
tensor = File(
8787
exists=True, desc='path/name of file with the 4D tensor volume')
88+
sse = File(
89+
exists=True, desc='path/name of file with the summed squared error')
8890

8991

9092
class DTIFit(FSLCommand):
@@ -111,13 +113,21 @@ class DTIFit(FSLCommand):
111113
output_spec = DTIFitOutputSpec
112114

113115
def _list_outputs(self):
116+
keys_to_ignore = {'outputtype', 'environ', 'args'}
117+
# Optional output: Map output name to input flag
118+
opt_output = {'tensor': self.inputs.save_tensor,
119+
'sse': self.inputs.sse}
120+
# Ignore optional output, whose corresponding input-flag is not defined
121+
# or set to False
122+
for output, input_flag in opt_output.items():
123+
if isdefined(input_flag) and input_flag:
124+
# this is wanted output, do not ignore
125+
continue
126+
keys_to_ignore.add(output)
127+
114128
outputs = self.output_spec().get()
115-
for k in list(outputs.keys()):
116-
if k not in ('outputtype', 'environ', 'args'):
117-
if k != 'tensor' or (isdefined(self.inputs.save_tensor)
118-
and self.inputs.save_tensor):
119-
outputs[k] = self._gen_fname(
120-
self.inputs.base_name, suffix='_' + k)
129+
for k in set(outputs.keys()) - keys_to_ignore:
130+
outputs[k] = self._gen_fname(self.inputs.base_name, suffix='_' + k)
121131
return outputs
122132

123133

nipype/interfaces/fsl/tests/test_auto_DTIFit.py

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def test_DTIFit_outputs():
6666
V2=dict(),
6767
V3=dict(),
6868
tensor=dict(),
69+
sse=dict(),
6970
)
7071
outputs = DTIFit.output_spec()
7172

nipype/interfaces/fsl/utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,9 @@ def _list_outputs(self):
551551
"""
552552
outputs = self._outputs().get()
553553
ext = Info.output_type_to_ext(self.inputs.output_type)
554-
outbase = 'vol*'
554+
outbase = 'vol[0-9]*'
555555
if isdefined(self.inputs.out_base_name):
556-
outbase = '%s*' % self.inputs.out_base_name
556+
outbase = '%s[0-9]*' % self.inputs.out_base_name
557557
outputs['out_files'] = sorted(
558558
glob(os.path.join(os.getcwd(), outbase + ext)))
559559
return outputs

nipype/interfaces/mrtrix3/base.py

+34-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,39 @@
44
from __future__ import (print_function, division, unicode_literals,
55
absolute_import)
66

7-
from ... import logging
8-
from ..base import (CommandLineInputSpec, CommandLine, traits, File, isdefined)
7+
from ... import logging, LooseVersion
8+
from ...utils.filemanip import which
9+
from ..base import (CommandLineInputSpec, CommandLine, traits, File, isdefined, PackageInfo)
910
iflogger = logging.getLogger('nipype.interface')
1011

1112

13+
class Info(PackageInfo):
14+
version_cmd = 'mrconvert --version'
15+
16+
@staticmethod
17+
def parse_version(raw_info):
18+
# info is like: "== mrconvert 0.3.15-githash"
19+
for line in raw_info.splitlines():
20+
if line.startswith('== mrconvert '):
21+
v_string = line.split()[2]
22+
break
23+
else:
24+
return None
25+
26+
# -githash may or may not be appended
27+
v_string = v_string.split('-')[0]
28+
29+
return '.'.join(v_string.split('.')[:3])
30+
31+
@classmethod
32+
def looseversion(cls):
33+
""" Return a comparable version object
34+
35+
If no version found, use LooseVersion('0.0.0')
36+
"""
37+
return LooseVersion(cls.version() or '0.0.0')
38+
39+
1240
class MRTrix3BaseInputSpec(CommandLineInputSpec):
1341
nthreads = traits.Int(
1442
argstr='-nthreads %d',
@@ -78,3 +106,7 @@ def _parse_inputs(self, skip=None):
78106
pass
79107

80108
return super(MRTrix3Base, self)._parse_inputs(skip=skip)
109+
110+
@property
111+
def version(self):
112+
return Info.version()

nipype/interfaces/mrtrix3/reconst.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class FitTensorInputSpec(MRTrix3BaseInputSpec):
3939
argstr='-method %s',
4040
desc=('select method used to perform the fitting'))
4141
reg_term = traits.Float(
42-
5.e3, usedefault=True,
4342
argstr='-regularisation %f',
43+
max_ver='0.3.13',
4444
desc=('specify the strength of the regularisation term on the '
4545
'magnitude of the tensor elements (default = 5000). This '
4646
'only applies to the non-linear methods'))
@@ -64,8 +64,7 @@ class FitTensor(MRTrix3Base):
6464
>>> tsr.inputs.in_mask = 'mask.nii.gz'
6565
>>> tsr.inputs.grad_fsl = ('bvecs', 'bvals')
6666
>>> tsr.cmdline # doctest: +ELLIPSIS
67-
'dwi2tensor -fslgrad bvecs bvals -mask mask.nii.gz \
68-
-regularisation 5000.000000 dwi.mif dti.mif'
67+
'dwi2tensor -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif dti.mif'
6968
>>> tsr.run() # doctest: +SKIP
7069
"""
7170

nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_FitTensor_inputs():
3434
),
3535
reg_term=dict(
3636
argstr='-regularisation %f',
37-
usedefault=True,
37+
max_ver='0.3.13',
3838
),
3939
)
4040
inputs = FitTensor.input_spec()

nipype/pipeline/engine/tests/test_engine.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,12 @@ def test_deep_nested_write_graph_runs(tmpdir):
484484
except OSError:
485485
pass
486486

487+
import networkx
488+
# Format of the graph has slightly changed
489+
graph_str = '""' if int(networkx.__version__.split('.')[0]) == 1 else ''
487490

488491
# examples of dot files used in the following test
489-
dotfile_orig = ['strict digraph {\n',
492+
dotfile_orig = ['strict digraph ' + graph_str + ' {\n',
490493
'"mod1 (engine)";\n',
491494
'"mod2 (engine)";\n',
492495
'"mod1 (engine)" -> "mod2 (engine)";\n',

nipype/pipeline/engine/utils.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,8 @@ def clean_working_directory(outputs,
14731473
needed_files += [path for path, type in input_files if type == 'f']
14741474
for extra in [
14751475
'_0x*.json', 'provenance.*', 'pyscript*.m', 'pyjobs*.mat',
1476-
'command.txt', 'result*.pklz', '_inputs.pklz', '_node.pklz'
1476+
'command.txt', 'result*.pklz', '_inputs.pklz', '_node.pklz',
1477+
'.proc-*',
14771478
]:
14781479
needed_files.extend(glob(os.path.join(cwd, extra)))
14791480
if files2keep:

nipype/utils/config.py

+4
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ def enable_resource_monitor(self):
291291
"""Sets the resource monitor on"""
292292
self.resource_monitor = True
293293

294+
def disable_resource_monitor(self):
295+
"""Sets the resource monitor off"""
296+
self.resource_monitor = False
297+
294298
def get_display(self):
295299
"""Returns the first display available"""
296300

0 commit comments

Comments
 (0)