Skip to content

Commit 63519b8

Browse files
authored
Merge branch 'master' into enh/add-masks-overlap
2 parents 36e43d2 + 5c3c413 commit 63519b8

File tree

86 files changed

+2370
-1197
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2370
-1197
lines changed

nipype/algorithms/metrics.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
from scipy.ndimage.measurements import center_of_mass, label
2020

2121
from .. import config, logging
22-
from ..utils.misc import package_check
2322

2423
from ..interfaces.base import (
2524
SimpleInterface, BaseInterface, traits, TraitedSpec, File,
2625
InputMultiPath, BaseInterfaceInputSpec,
2726
isdefined)
27+
from ..interfaces.nipy.base import NipyBaseInterface
2828

2929
iflogger = logging.getLogger('interface')
3030

@@ -645,7 +645,7 @@ class SimilarityOutputSpec(TraitedSpec):
645645
traits.Float(desc="Similarity between volume 1 and 2, frame by frame"))
646646

647647

648-
class Similarity(BaseInterface):
648+
class Similarity(NipyBaseInterface):
649649
"""Calculates similarity between two 3D or 4D volumes. Both volumes have to be in
650650
the same coordinate system, same space within that coordinate system and
651651
with the same voxel dimensions.
@@ -668,19 +668,8 @@ class Similarity(BaseInterface):
668668

669669
input_spec = SimilarityInputSpec
670670
output_spec = SimilarityOutputSpec
671-
_have_nipy = True
672-
673-
def __init__(self, **inputs):
674-
try:
675-
package_check('nipy')
676-
except Exception:
677-
self._have_nipy = False
678-
super(Similarity, self).__init__(**inputs)
679671

680672
def _run_interface(self, runtime):
681-
if not self._have_nipy:
682-
raise RuntimeError('nipy is not installed')
683-
684673
from nipy.algorithms.registration.histogram_registration import HistogramRegistration
685674
from nipy.algorithms.registration.affine import Affine
686675

nipype/algorithms/misc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from ..interfaces.base import (
2727
BaseInterface, traits, TraitedSpec, File, InputMultiPath, OutputMultiPath,
2828
BaseInterfaceInputSpec, isdefined, DynamicTraitedSpec, Undefined)
29-
from ..utils.filemanip import fname_presuffix, split_filename, filename_to_list
29+
from ..utils.filemanip import fname_presuffix, split_filename, ensure_list
3030
from ..utils import NUMPY_MMAP
3131

3232
from . import confounds
@@ -1479,7 +1479,7 @@ def _gen_fname(self, suffix, idx=None, ext=None):
14791479
def _run_interface(self, runtime):
14801480
total = None
14811481
self._median_files = []
1482-
for idx, fname in enumerate(filename_to_list(self.inputs.in_files)):
1482+
for idx, fname in enumerate(ensure_list(self.inputs.in_files)):
14831483
img = nb.load(fname, mmap=NUMPY_MMAP)
14841484
data = np.median(img.get_data(), axis=3)
14851485
if self.inputs.median_per_file:

nipype/algorithms/modelgen.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from ..interfaces.base import (BaseInterface, TraitedSpec, InputMultiPath,
2727
traits, File, Bunch, BaseInterfaceInputSpec,
2828
isdefined)
29-
from ..utils.filemanip import filename_to_list
29+
from ..utils.filemanip import ensure_list
3030
from ..utils.misc import normalize_mc_params
3131
from .. import config, logging
3232
iflogger = logging.getLogger('interface')
@@ -383,7 +383,7 @@ def _generate_standard_design(self,
383383
if outliers is not None:
384384
for i, out in enumerate(outliers):
385385
numscans = 0
386-
for f in filename_to_list(sessinfo[i]['scans']):
386+
for f in ensure_list(sessinfo[i]['scans']):
387387
shape = load(f, mmap=NUMPY_MMAP).shape
388388
if len(shape) == 3 or shape[3] == 1:
389389
iflogger.warning('You are using 3D instead of 4D '
@@ -580,7 +580,7 @@ def _generate_design(self, infolist=None):
580580
else:
581581
infolist = gen_info(self.inputs.event_files)
582582
concatlist, nscans = self._concatenate_info(infolist)
583-
functional_runs = [filename_to_list(self.inputs.functional_runs)]
583+
functional_runs = [ensure_list(self.inputs.functional_runs)]
584584
realignment_parameters = []
585585
if isdefined(self.inputs.realignment_parameters):
586586
realignment_parameters = []

nipype/algorithms/rapidart.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from ..interfaces.base import (BaseInterface, traits, InputMultiPath,
2929
OutputMultiPath, TraitedSpec, File,
3030
BaseInterfaceInputSpec, isdefined)
31-
from ..utils.filemanip import filename_to_list, save_json, split_filename
31+
from ..utils.filemanip import ensure_list, save_json, split_filename
3232
from ..utils.misc import find_indices, normalize_mc_params
3333
from .. import logging, config
3434
iflogger = logging.getLogger('interface')
@@ -376,7 +376,7 @@ def _list_outputs(self):
376376
outputs['displacement_files'] = []
377377
if isdefined(self.inputs.save_plot) and self.inputs.save_plot:
378378
outputs['plot_files'] = []
379-
for i, f in enumerate(filename_to_list(self.inputs.realigned_files)):
379+
for i, f in enumerate(ensure_list(self.inputs.realigned_files)):
380380
(outlierfile, intensityfile, statsfile, normfile, plotfile,
381381
displacementfile, maskfile) = \
382382
self._get_output_filenames(f, os.getcwd())
@@ -616,8 +616,8 @@ def _detect_outliers_core(self, imgfile, motionfile, runidx, cwd=None):
616616
def _run_interface(self, runtime):
617617
"""Execute this module.
618618
"""
619-
funcfilelist = filename_to_list(self.inputs.realigned_files)
620-
motparamlist = filename_to_list(self.inputs.realignment_parameters)
619+
funcfilelist = ensure_list(self.inputs.realigned_files)
620+
motparamlist = ensure_list(self.inputs.realignment_parameters)
621621
for i, imgf in enumerate(funcfilelist):
622622
self._detect_outliers_core(
623623
imgf, motparamlist[i], i, cwd=os.getcwd())

nipype/interfaces/afni/preprocess.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ class AllineateInputSpec(AFNICommandInputSpec):
218218
out_file = File(
219219
desc='output file from 3dAllineate',
220220
argstr='-prefix %s',
221-
genfile=True,
221+
name_template='%s_allineate',
222+
name_source='in_file',
223+
hash_files=False,
222224
xor=['allcostx'])
223225
out_param_file = File(
224226
argstr='-1Dparam_save %s',
@@ -424,11 +426,11 @@ class AllineateInputSpec(AFNICommandInputSpec):
424426
_dirs = ['X', 'Y', 'Z', 'I', 'J', 'K']
425427
nwarp_fixmot = traits.List(
426428
traits.Enum(*_dirs),
427-
argstr='-nwarp_fixmot%s',
429+
argstr='-nwarp_fixmot%s...',
428430
desc='To fix motion along directions.')
429431
nwarp_fixdep = traits.List(
430432
traits.Enum(*_dirs),
431-
argstr='-nwarp_fixdep%s',
433+
argstr='-nwarp_fixdep%s...',
432434
desc='To fix non-linear warp dependency along directions.')
433435
verbose = traits.Bool(
434436
argstr='-verb', desc='Print out verbose progress reports.')
@@ -465,31 +467,29 @@ class Allineate(AFNICommand):
465467
'3dAllineate -source functional.nii -prefix functional_allineate.nii -1Dmatrix_apply cmatrix.mat'
466468
>>> res = allineate.run() # doctest: +SKIP
467469
468-
>>> from nipype.interfaces import afni
469470
>>> allineate = afni.Allineate()
470471
>>> allineate.inputs.in_file = 'functional.nii'
471472
>>> allineate.inputs.reference = 'structural.nii'
472473
>>> allineate.inputs.allcostx = 'out.allcostX.txt'
473474
>>> allineate.cmdline
474475
'3dAllineate -source functional.nii -base structural.nii -allcostx |& tee out.allcostX.txt'
475476
>>> res = allineate.run() # doctest: +SKIP
477+
478+
>>> allineate = afni.Allineate()
479+
>>> allineate.inputs.in_file = 'functional.nii'
480+
>>> allineate.inputs.reference = 'structural.nii'
481+
>>> allineate.inputs.nwarp_fixmot = ['X', 'Y']
482+
>>> allineate.cmdline
483+
'3dAllineate -source functional.nii -nwarp_fixmotX -nwarp_fixmotY -prefix functional_allineate -base structural.nii'
484+
>>> res = allineate.run() # doctest: +SKIP
476485
"""
477486

478487
_cmd = '3dAllineate'
479488
input_spec = AllineateInputSpec
480489
output_spec = AllineateOutputSpec
481490

482-
def _format_arg(self, name, trait_spec, value):
483-
if name == 'nwarp_fixmot' or name == 'nwarp_fixdep':
484-
arg = ' '.join([trait_spec.argstr % v for v in value])
485-
return arg
486-
return super(Allineate, self)._format_arg(name, trait_spec, value)
487-
488491
def _list_outputs(self):
489-
outputs = self.output_spec().get()
490-
491-
if self.inputs.out_file:
492-
outputs['out_file'] = op.abspath(self.inputs.out_file)
492+
outputs = super(Allineate, self)._list_outputs()
493493

494494
if self.inputs.out_weight_file:
495495
outputs['out_weight_file'] = op.abspath(
@@ -512,16 +512,10 @@ def _list_outputs(self):
512512
outputs['out_param_file'] = op.abspath(
513513
self.inputs.out_param_file)
514514

515-
if isdefined(self.inputs.allcostx):
516-
outputs['allcostX'] = os.path.abspath(
517-
os.path.join(os.getcwd(), self.inputs.allcostx))
515+
if self.inputs.allcostx:
516+
outputs['allcostX'] = os.path.abspath(self.inputs.allcostx)
518517
return outputs
519518

520-
def _gen_filename(self, name):
521-
if name == 'out_file':
522-
return self._list_outputs()[name]
523-
return None
524-
525519

526520
class AutoTcorrelateInputSpec(AFNICommandInputSpec):
527521
in_file = File(
@@ -2510,7 +2504,7 @@ class TProjectInputSpec(AFNICommandInputSpec):
25102504
rather than the value stored in the dataset header.""",
25112505
argstr='-TR %g')
25122506
mask = File(
2513-
exist=True,
2507+
exists=True,
25142508
desc="""Only operate on voxels nonzero in the mset dataset.
25152509
++ Voxels outside the mask will be filled with zeros.
25162510
++ If no masking option is given, then all voxels

nipype/interfaces/afni/tests/test_auto_Allineate.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@ def test_Allineate_inputs():
6161
usedefault=True,
6262
),
6363
nwarp=dict(argstr='-nwarp %s', ),
64-
nwarp_fixdep=dict(argstr='-nwarp_fixdep%s', ),
65-
nwarp_fixmot=dict(argstr='-nwarp_fixmot%s', ),
64+
nwarp_fixdep=dict(argstr='-nwarp_fixdep%s...', ),
65+
nwarp_fixmot=dict(argstr='-nwarp_fixmot%s...', ),
6666
one_pass=dict(argstr='-onepass', ),
6767
out_file=dict(
6868
argstr='-prefix %s',
69-
genfile=True,
69+
hash_files=False,
70+
name_source='in_file',
71+
name_template='%s_allineate',
7072
xor=['allcostx'],
7173
),
7274
out_matrix=dict(

nipype/interfaces/afni/tests/test_auto_TProject.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@ def test_TProject_inputs():
3232
mandatory=True,
3333
position=1,
3434
),
35-
mask=dict(
36-
argstr='-mask %s',
37-
exist=True,
38-
),
35+
mask=dict(argstr='-mask %s', ),
3936
noblock=dict(argstr='-noblock', ),
4037
norm=dict(argstr='-norm', ),
4138
num_threads=dict(

nipype/interfaces/ants/registration.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from builtins import range, str
88
import os
99

10-
from ...utils.filemanip import filename_to_list
10+
from ...utils.filemanip import ensure_list
1111
from ..base import TraitedSpec, File, Str, traits, InputMultiPath, isdefined
1212
from .base import ANTSCommand, ANTSCommandInputSpec, LOCAL_DEFAULT_NUMBER_OF_THREADS
1313

@@ -1088,14 +1088,14 @@ def _format_registration(self):
10881088
if any((isdefined(self.inputs.fixed_image_masks),
10891089
isdefined(self.inputs.moving_image_masks))):
10901090
if isdefined(self.inputs.fixed_image_masks):
1091-
fixed_masks = filename_to_list(
1091+
fixed_masks = ensure_list(
10921092
self.inputs.fixed_image_masks)
10931093
fixed_mask = fixed_masks[ii if len(fixed_masks) > 1 else 0]
10941094
else:
10951095
fixed_mask = 'NULL'
10961096

10971097
if isdefined(self.inputs.moving_image_masks):
1098-
moving_masks = filename_to_list(
1098+
moving_masks = ensure_list(
10991099
self.inputs.moving_image_masks)
11001100
moving_mask = moving_masks[ii
11011101
if len(moving_masks) > 1 else 0]
@@ -1556,7 +1556,7 @@ class RegistrationSynQuick(ANTSCommand):
15561556
>>> reg.inputs.moving_image = 'moving1.nii'
15571557
>>> reg.inputs.num_threads = 2
15581558
>>> reg.cmdline
1559-
'antsRegistrationSynQuick.sh -d 3 -f fixed1.nii -m moving1.nii -n 2 -o transform -p d -t s'
1559+
'antsRegistrationSyNQuick.sh -d 3 -f fixed1.nii -m moving1.nii -n 2 -o transform -p d -t s'
15601560
>>> reg.run() # doctest: +SKIP
15611561
15621562
example for multiple images
@@ -1567,19 +1567,18 @@ class RegistrationSynQuick(ANTSCommand):
15671567
>>> reg.inputs.moving_image = ['moving1.nii', 'moving2.nii']
15681568
>>> reg.inputs.num_threads = 2
15691569
>>> reg.cmdline
1570-
'antsRegistrationSynQuick.sh -d 3 -f fixed1.nii -f fixed2.nii -m moving1.nii -m moving2.nii -n 2 -o transform -p d -t s'
1570+
'antsRegistrationSyNQuick.sh -d 3 -f fixed1.nii -f fixed2.nii -m moving1.nii -m moving2.nii -n 2 -o transform -p d -t s'
15711571
>>> reg.run() # doctest: +SKIP
15721572
"""
15731573

1574-
1575-
_cmd = 'antsRegistrationSynQuick.sh'
1574+
_cmd = 'antsRegistrationSyNQuick.sh'
15761575
input_spec = RegistrationSynQuickInputSpec
15771576
output_spec = RegistrationSynQuickOutputSpec
15781577

15791578
def _num_threads_update(self):
15801579
"""
1581-
antsRegistrationSynQuick.sh ignores environment variables,
1582-
so override environment update frm ANTSCommand class
1580+
antsRegistrationSyNQuick.sh ignores environment variables,
1581+
so override environment update from ANTSCommand class
15831582
"""
15841583
pass
15851584

nipype/interfaces/base/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
"""
1111
from .core import (Interface, BaseInterface, SimpleInterface, CommandLine,
1212
StdOutCommandLine, MpiCommandLine, SEMLikeCommandLine,
13-
PackageInfo)
13+
LibraryBaseInterface, PackageInfo)
1414

1515
from .specs import (BaseTraitedSpec, TraitedSpec, DynamicTraitedSpec,
1616
BaseInterfaceInputSpec, CommandLineInputSpec,
1717
StdOutCommandLineInputSpec)
1818

1919
from .traits_extension import (
2020
traits, Undefined, TraitDictObject, TraitListObject, TraitError, isdefined,
21-
File, Directory, Str, DictStrStr, has_metadata, ImageFile, MultiPath,
21+
File, Directory, Str, DictStrStr, has_metadata, ImageFile,
22+
OutputMultiObject, InputMultiObject,
2223
OutputMultiPath, InputMultiPath)
2324

2425
from .support import (Bunch, InterfaceResult, load_template,

nipype/interfaces/base/core.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,12 @@ def _filename_from_source(self, name, chain=None):
10721072
if not isdefined(retval) or "%s" in retval:
10731073
if not trait_spec.name_source:
10741074
return retval
1075+
1076+
# Do not generate filename when excluded by other inputs
1077+
if trait_spec.xor and any(isdefined(getattr(self.inputs, field))
1078+
for field in trait_spec.xor):
1079+
return retval
1080+
10751081
if isdefined(retval) and "%s" in retval:
10761082
name_template = retval
10771083
else:
@@ -1133,7 +1139,7 @@ def _list_outputs(self):
11331139
metadata = dict(name_source=lambda t: t is not None)
11341140
traits = self.inputs.traits(**metadata)
11351141
if traits:
1136-
outputs = self.output_spec().get()
1142+
outputs = self.output_spec().trait_get()
11371143
for name, trait_spec in list(traits.items()):
11381144
out_name = name
11391145
if trait_spec.output_name is not None:
@@ -1237,7 +1243,7 @@ class SEMLikeCommandLine(CommandLine):
12371243
"""
12381244

12391245
def _list_outputs(self):
1240-
outputs = self.output_spec().get()
1246+
outputs = self.output_spec().trait_get()
12411247
return self._outputs_from_inputs(outputs)
12421248

12431249
def _outputs_from_inputs(self, outputs):
@@ -1267,6 +1273,35 @@ def _format_arg(self, name, spec, value):
12671273
return super(SEMLikeCommandLine, self)._format_arg(name, spec, value)
12681274

12691275

1276+
class LibraryBaseInterface(BaseInterface):
1277+
_pkg = None
1278+
imports = ()
1279+
1280+
def __init__(self, check_import=True, *args, **kwargs):
1281+
super(LibraryBaseInterface, self).__init__(*args, **kwargs)
1282+
if check_import:
1283+
import importlib
1284+
failed_imports = []
1285+
for pkg in (self._pkg,) + tuple(self.imports):
1286+
try:
1287+
importlib.import_module(pkg)
1288+
except ImportError:
1289+
failed_imports.append(pkg)
1290+
if failed_imports:
1291+
iflogger.warn('Unable to import %s; %s interface may fail to '
1292+
'run', failed_imports, self.__class__.__name__)
1293+
1294+
@property
1295+
def version(self):
1296+
if self._version is None:
1297+
import importlib
1298+
try:
1299+
self._version = importlib.import_module(self._pkg).__version__
1300+
except (ImportError, AttributeError):
1301+
pass
1302+
return super(LibraryBaseInterface, self).version
1303+
1304+
12701305
class PackageInfo(object):
12711306
_version = None
12721307
version_cmd = None

0 commit comments

Comments
 (0)