Skip to content

Commit 969d7b0

Browse files
authored
Merge branch 'master' into enh/resolve-rebase-paths
2 parents 8766840 + 6f2f94f commit 969d7b0

File tree

6 files changed

+80
-90
lines changed

6 files changed

+80
-90
lines changed

nipype/interfaces/base/core.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,10 @@ def _check_requires(self, spec, name, value):
204204
]
205205
if any(values) and isdefined(value):
206206
if len(values) > 1:
207-
fmt = ("%s requires values for inputs %s because '%s' is set. "
207+
fmt = ("%s requires values for inputs %s because '%s' is set. "
208208
"For a list of required inputs, see %s.help()")
209209
else:
210-
fmt = ("%s requires a value for input %s because '%s' is set. "
210+
fmt = ("%s requires a value for input %s because '%s' is set. "
211211
"For a list of required inputs, see %s.help()")
212212
msg = fmt % (self.__class__.__name__,
213213
', '.join("'%s'" % req for req in spec.requires),
@@ -450,34 +450,36 @@ def _list_outputs(self):
450450
return None
451451

452452
def aggregate_outputs(self, runtime=None, needed_outputs=None):
453-
""" Collate expected outputs and check for existence
454-
"""
455-
456-
predicted_outputs = self._list_outputs()
457-
outputs = self._outputs()
458-
if predicted_outputs:
459-
_unavailable_outputs = []
460-
if outputs:
461-
_unavailable_outputs = \
462-
self._check_version_requirements(self._outputs())
463-
for key, val in list(predicted_outputs.items()):
464-
if needed_outputs and key not in needed_outputs:
465-
continue
466-
if key in _unavailable_outputs:
467-
raise KeyError(('Output trait %s not available in version '
468-
'%s of interface %s. Please inform '
469-
'developers.') % (key, self.version,
470-
self.__class__.__name__))
471-
try:
472-
setattr(outputs, key, val)
473-
except TraitError as error:
474-
if getattr(error, 'info',
475-
'default').startswith('an existing'):
476-
msg = ("File/Directory '%s' not found for %s output "
477-
"'%s'." % (val, self.__class__.__name__, key))
478-
raise FileNotFoundError(msg)
479-
raise error
453+
"""Collate expected outputs and apply output traits validation."""
454+
outputs = self._outputs() # Generate an empty output spec object
455+
predicted_outputs = self._list_outputs() # Predictions from _list_outputs
456+
if not predicted_outputs:
457+
return outputs
480458

459+
# Precalculate the list of output trait names that should be aggregated
460+
aggregate_names = set(predicted_outputs)
461+
if needed_outputs is not None:
462+
aggregate_names = set(needed_outputs).intersection(aggregate_names)
463+
464+
if aggregate_names: # Make sure outputs are compatible
465+
_na_outputs = self._check_version_requirements(outputs)
466+
na_names = aggregate_names.intersection(_na_outputs)
467+
if na_names:
468+
# XXX Change to TypeError in Nipype 2.0
469+
raise KeyError("""\
470+
Output trait(s) %s not available in version %s of interface %s.\
471+
""" % (', '.join(na_names), self.version, self.__class__.__name__))
472+
473+
for key in aggregate_names: # Final aggregation
474+
val = predicted_outputs[key]
475+
try:
476+
setattr(outputs, key, val)
477+
except TraitError as error:
478+
if 'an existing' in getattr(error, 'info', 'default'):
479+
msg = "No such file or directory for output '%s' of a %s interface" % \
480+
(key, self.__class__.__name__)
481+
raise FileNotFoundError(val, message=msg)
482+
raise error
481483
return outputs
482484

483485
@property

nipype/interfaces/mrtrix3/base.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ class MRTrix3BaseInputSpec(CommandLineInputSpec):
4848
grad_file = File(
4949
exists=True,
5050
argstr='-grad %s',
51-
desc='dw gradient scheme (MRTrix format')
51+
desc='dw gradient scheme (MRTrix format)',
52+
xor=['grad_fsl'])
5253
grad_fsl = Tuple(
5354
File(exists=True),
5455
File(exists=True),
5556
argstr='-fslgrad %s %s',
56-
desc='(bvecs, bvals) dw gradient scheme (FSL format')
57+
desc='(bvecs, bvals) dw gradient scheme (FSL format)',
58+
xor=['grad_file'])
5759
bval_scale = traits.Enum(
5860
'yes',
5961
'no',

nipype/interfaces/mrtrix3/preprocess.py

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,24 @@ class DWIDenoiseInputSpec(MRTrix3BaseInputSpec):
2323
argstr='-mask %s',
2424
position=1,
2525
desc='mask image')
26-
extent = Tuple((traits.Int, traits.Int, traits.Int),
26+
extent = Tuple(
27+
(traits.Int, traits.Int, traits.Int),
2728
argstr='-extent %d,%d,%d',
2829
desc='set the window size of the denoising filter. (default = 5,5,5)')
2930
noise = File(
3031
argstr='-noise %s',
31-
desc='the output noise map')
32-
out_file = File(name_template='%s_denoised',
32+
name_template='%s_noise',
3333
name_source='in_file',
3434
keep_extension=True,
35+
desc='the output noise map')
36+
out_file = File(
3537
argstr='%s',
3638
position=-1,
37-
desc='the output denoised DWI image',
38-
genfile=True)
39+
name_template='%s_denoised',
40+
name_source='in_file',
41+
keep_extension=True,
42+
desc='the output denoised DWI image')
43+
3944

4045
class DWIDenoiseOutputSpec(TraitedSpec):
4146
noise = File(desc='the output noise map', exists=True)
@@ -67,22 +72,16 @@ class DWIDenoise(MRTrix3Base):
6772
>>> denoise = mrt.DWIDenoise()
6873
>>> denoise.inputs.in_file = 'dwi.mif'
6974
>>> denoise.inputs.mask = 'mask.mif'
75+
>>> denoise.inputs.noise = 'noise.mif'
7076
>>> denoise.cmdline # doctest: +ELLIPSIS
71-
'dwidenoise -mask mask.mif dwi.mif dwi_denoised.mif'
77+
'dwidenoise -mask mask.mif -noise noise.mif dwi.mif dwi_denoised.mif'
7278
>>> denoise.run() # doctest: +SKIP
7379
"""
7480

7581
_cmd = 'dwidenoise'
7682
input_spec = DWIDenoiseInputSpec
7783
output_spec = DWIDenoiseOutputSpec
7884

79-
def _list_outputs(self):
80-
outputs = self.output_spec().get()
81-
outputs['out_file'] = op.abspath(self.inputs.out_file)
82-
if self.inputs.noise != Undefined:
83-
outputs['noise'] = op.abspath(self.inputs.noise)
84-
return outputs
85-
8685

8786
class MRDeGibbsInputSpec(MRTrix3BaseInputSpec):
8887
in_file = File(
@@ -92,7 +91,7 @@ class MRDeGibbsInputSpec(MRTrix3BaseInputSpec):
9291
mandatory=True,
9392
desc='input DWI image')
9493
axes = traits.ListInt(
95-
default_value=[0,1],
94+
default_value=[0, 1],
9695
usedefault=True,
9796
sep=',',
9897
minlen=2,
@@ -117,13 +116,13 @@ class MRDeGibbsInputSpec(MRTrix3BaseInputSpec):
117116
argstr='-maxW %d',
118117
desc='right border of window used for total variation (TV) computation '
119118
'(default = 3)')
120-
out_file = File(name_template='%s_unr',
119+
out_file = File(
120+
name_template='%s_unr',
121121
name_source='in_file',
122122
keep_extension=True,
123123
argstr='%s',
124124
position=-1,
125-
desc='the output unringed DWI image',
126-
genfile=True)
125+
desc='the output unringed DWI image')
127126

128127
class MRDeGibbsOutputSpec(TraitedSpec):
129128
out_file = File(desc='the output unringed DWI image', exists=True)
@@ -179,31 +178,21 @@ class DWIBiasCorrectInputSpec(MRTrix3BaseInputSpec):
179178
in_mask = File(
180179
argstr='-mask %s',
181180
desc='input mask image for bias field estimation')
182-
_xor_methods = ('use_ants', 'use_fsl')
183181
use_ants = traits.Bool(
184-
default_value=True,
185-
usedefault=True,
186182
argstr='-ants',
183+
mandatory=True,
187184
desc='use ANTS N4 to estimate the inhomogeneity field',
188-
xor=_xor_methods)
185+
xor=['use_fsl'])
189186
use_fsl = traits.Bool(
190187
argstr='-fsl',
188+
mandatory=True,
191189
desc='use FSL FAST to estimate the inhomogeneity field',
192-
xor=_xor_methods,
193-
min_ver='5.0.10')
194-
_xor_grads = ('mrtrix_grad', 'fsl_grad')
195-
mrtrix_grad = File(
196-
argstr='-grad %s',
197-
desc='diffusion gradient table in MRtrix format',
198-
xor=_xor_grads)
199-
fsl_grad = File(
200-
argstr='-fslgrad %s %s',
201-
desc='diffusion gradient table in FSL bvecs/bvals format',
202-
xor=_xor_grads)
190+
xor=['use_ants'])
203191
bias = File(
204192
argstr='-bias %s',
205193
desc='bias field')
206-
out_file = File(name_template='%s_biascorr',
194+
out_file = File(
195+
name_template='%s_biascorr',
207196
name_source='in_file',
208197
keep_extension=True,
209198
argstr='%s',
@@ -228,6 +217,7 @@ class DWIBiasCorrect(MRTrix3Base):
228217
>>> import nipype.interfaces.mrtrix3 as mrt
229218
>>> bias_correct = mrt.DWIBiasCorrect()
230219
>>> bias_correct.inputs.in_file = 'dwi.mif'
220+
>>> bias_correct.inputs.use_ants = True
231221
>>> bias_correct.cmdline
232222
'dwibiascorrect -ants dwi.mif dwi_biascorr.mif'
233223
>>> bias_correct.run() # doctest: +SKIP
@@ -237,13 +227,6 @@ class DWIBiasCorrect(MRTrix3Base):
237227
input_spec = DWIBiasCorrectInputSpec
238228
output_spec = DWIBiasCorrectOutputSpec
239229

240-
def _list_outputs(self):
241-
outputs = self.output_spec().get()
242-
outputs['out_file'] = op.abspath(self.inputs.out_file)
243-
if self.inputs.bias != Undefined:
244-
outputs['bias'] = op.abspath(self.inputs.bias)
245-
return outputs
246-
247230

248231
class ResponseSDInputSpec(MRTrix3BaseInputSpec):
249232
algorithm = traits.Enum(

nipype/interfaces/mrtrix3/tests/test_auto_DWIBiasCorrect.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@ def test_DWIBiasCorrect_inputs():
1515
nohash=True,
1616
usedefault=True,
1717
),
18-
fsl_grad=dict(
19-
argstr='-fslgrad %s %s',
20-
extensions=None,
21-
xor=('mrtrix_grad', 'fsl_grad'),
22-
),
2318
grad_file=dict(
2419
argstr='-grad %s',
2520
extensions=None,
21+
xor=['grad_fsl'],
22+
),
23+
grad_fsl=dict(
24+
argstr='-fslgrad %s %s',
25+
xor=['grad_file'],
2626
),
27-
grad_fsl=dict(argstr='-fslgrad %s %s', ),
2827
in_bval=dict(extensions=None, ),
2928
in_bvec=dict(
3029
argstr='-fslgrad %s %s',
@@ -40,11 +39,6 @@ def test_DWIBiasCorrect_inputs():
4039
argstr='-mask %s',
4140
extensions=None,
4241
),
43-
mrtrix_grad=dict(
44-
argstr='-grad %s',
45-
extensions=None,
46-
xor=('mrtrix_grad', 'fsl_grad'),
47-
),
4842
nthreads=dict(
4943
argstr='-nthreads %d',
5044
nohash=True,
@@ -60,13 +54,13 @@ def test_DWIBiasCorrect_inputs():
6054
),
6155
use_ants=dict(
6256
argstr='-ants',
63-
usedefault=True,
64-
xor=('use_ants', 'use_fsl'),
57+
mandatory=True,
58+
xor=['use_fsl'],
6559
),
6660
use_fsl=dict(
6761
argstr='-fsl',
68-
min_ver='5.0.10',
69-
xor=('use_ants', 'use_fsl'),
62+
mandatory=True,
63+
xor=['use_ants'],
7064
),
7165
)
7266
inputs = DWIBiasCorrect.input_spec()

nipype/interfaces/mrtrix3/tests/test_auto_DWIDenoise.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ def test_DWIDenoise_inputs():
1515
grad_file=dict(
1616
argstr='-grad %s',
1717
extensions=None,
18+
xor=['grad_fsl'],
19+
),
20+
grad_fsl=dict(
21+
argstr='-fslgrad %s %s',
22+
xor=['grad_file'],
1823
),
19-
grad_fsl=dict(argstr='-fslgrad %s %s', ),
2024
in_bval=dict(extensions=None, ),
2125
in_bvec=dict(
2226
argstr='-fslgrad %s %s',
@@ -36,6 +40,9 @@ def test_DWIDenoise_inputs():
3640
noise=dict(
3741
argstr='-noise %s',
3842
extensions=None,
43+
keep_extension=True,
44+
name_source='in_file',
45+
name_template='%s_noise',
3946
),
4047
nthreads=dict(
4148
argstr='-nthreads %d',
@@ -44,7 +51,6 @@ def test_DWIDenoise_inputs():
4451
out_file=dict(
4552
argstr='%s',
4653
extensions=None,
47-
genfile=True,
4854
keep_extension=True,
4955
name_source='in_file',
5056
name_template='%s_denoised',

nipype/interfaces/mrtrix3/tests/test_auto_MRDeGibbs.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ def test_MRDeGibbs_inputs():
2121
grad_file=dict(
2222
argstr='-grad %s',
2323
extensions=None,
24+
xor=['grad_fsl'],
25+
),
26+
grad_fsl=dict(
27+
argstr='-fslgrad %s %s',
28+
xor=['grad_file'],
2429
),
25-
grad_fsl=dict(argstr='-fslgrad %s %s', ),
2630
in_bval=dict(extensions=None, ),
2731
in_bvec=dict(
2832
argstr='-fslgrad %s %s',
@@ -53,7 +57,6 @@ def test_MRDeGibbs_inputs():
5357
out_file=dict(
5458
argstr='%s',
5559
extensions=None,
56-
genfile=True,
5760
keep_extension=True,
5861
name_source='in_file',
5962
name_template='%s_unr',

0 commit comments

Comments
 (0)