diff --git a/.mailmap b/.mailmap index 259fbe170d..946919557c 100644 --- a/.mailmap +++ b/.mailmap @@ -151,6 +151,7 @@ Michael Waskom mwaskom Michael Waskom mwaskom Michael Waskom mwaskom Miguel Molina-Romero Miguel Molina +Murat Bilgel Murat Bilgel Oliver Contier oliver-contier Oscar Esteban Oscar Esteban Oscar Esteban oesteban @@ -160,6 +161,7 @@ Paul Sharp psharp1289 Ranjit Khanuja RanjitK Rastko Ćirić rciric Rastko Ćirić Rastko Ćirić +Rastko Ćirić rciric Ross Markello Ross Markello Russell Poldrack Russ Poldrack Russell Poldrack poldrack @@ -182,7 +184,11 @@ Siqi Liu sql Steven Giavasis Steven Giavasis Steven Giavasis sgiavasis Steven Giavasis sgiavasis +Steven Tilley Steven Tilley Tristan Glatard Tristan Glatard +Victor Férat Victor +Victor Férat Victor Ferat +Victor Férat Victor Férat Victor Saase vsaase Weijie Huang forwho William Triplett William Triplett diff --git a/.zenodo.json b/.zenodo.json index ee1771da97..06bd8a4ebc 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -78,10 +78,6 @@ "affiliation": "Shattuck Lab, UCLA Brain Mapping Center", "name": "Wong, Jason" }, - { - "affiliation": "Concordia University", - "name": "Benderoff, Erin" - }, { "name": "Modat, Marc" }, @@ -150,6 +146,10 @@ { "name": "Berleant, Shoshana" }, + { + "affiliation": "Concordia University", + "name": "Benderoff, Erin" + }, { "affiliation": "Institute for Biomedical Engineering, ETH and University of Zurich", "name": "Christian, Horea", @@ -293,11 +293,11 @@ "orcid": "0000-0002-7796-8795" }, { - "name": "Heinsfeld, Anibal S\u00f3lon", - "orcid": "0000-0002-2050-0614" + "name": "Kent, James" }, { - "name": "Kent, James" + "name": "Heinsfeld, Anibal S\u00f3lon", + "orcid": "0000-0002-2050-0614" }, { "name": "Watanabe, Aimi" @@ -355,15 +355,15 @@ { "name": "Erickson, Drew" }, - { - "affiliation": "Child Mind Institute", - "name": "Giavasis, Steven" - }, { "affiliation": "NIMH IRP", "name": "Lee, John A.", "orcid": "0000-0001-5884-4247" }, + { + "affiliation": "Child Mind Institute", + "name": "Giavasis, Steven" + }, { "name": "Correa, Carlos" }, @@ -381,9 +381,6 @@ { "name": "Millman, Jarrod" }, - { - "name": "Lai, Jeff" - }, { "name": "Zhou, Dale" }, @@ -393,6 +390,11 @@ { "name": "Haselgrove, Christian" }, + { + "affiliation": "Holland Bloorview Kids Rehabilitation Hospital", + "name": "Tilley II, Steven", + "orcid": "0000-0003-4853-5082" + }, { "name": "Renfro, Mandy" }, @@ -400,16 +402,16 @@ "affiliation": "The University of Sydney", "name": "Liu, Siqi" }, - { - "affiliation": "Leibniz Institute for Neurobiology", - "name": "Stadler, J\u00f6rg", - "orcid": "0000-0003-4313-129X" - }, { "affiliation": "University of Pennsylvania", "name": "Kahn, Ari E.", "orcid": "0000-0002-2127-0507" }, + { + "affiliation": "Leibniz Institute for Neurobiology", + "name": "Stadler, J\u00f6rg", + "orcid": "0000-0003-4313-129X" + }, { "affiliation": "University College London", "name": "P\u00e9rez-Garc\u00eda, Fernando", @@ -502,31 +504,26 @@ "name": "Perkins, L. Nathan" }, { - "affiliation": "University of Amsterdam", - "name": "Lukas Snoek", - "orcid": "0000-0001-8972-204X" + "name": "Marina, Ana" }, { - "affiliation": "Institute of Imaging & Computer Vision, RWTH Aachen University, Germany", - "name": "Weninger, Leon" + "name": "Mattfeld, Aaron" }, { - "affiliation": "Stanford University", - "name": "Lerma-Usabiaga, Garikoitz", - "orcid": "0000-0001-9800-4816" + "name": "Noel, Maxime" }, { - "name": "Marina, Ana" + "affiliation": "University of Amsterdam", + "name": "Lukas Snoek", + "orcid": "0000-0001-8972-204X" }, { - "name": "Mattfeld, Aaron" + "affiliation": "Institute of Imaging & Computer Vision, RWTH Aachen University, Germany", + "name": "Weninger, Leon" }, { "name": "Matsubara, K" }, - { - "name": "Noel, Maxime" - }, { "name": "Cheung, Brian" }, @@ -573,9 +570,6 @@ { "name": "Weinstein, Alejandro" }, - { - "name": "Tambini, Arielle" - }, { "affiliation": "Duke University", "name": "Broderick, William", @@ -598,6 +592,11 @@ { "name": "Khanuja, Ranjeet" }, + { + "affiliation": "National Institute on Aging, Baltimore, MD, USA", + "name": "Bilgel, Murat", + "orcid": "0000-0001-5042-7422" + }, { "name": "Schlamp, Kai" }, @@ -612,6 +611,9 @@ { "name": "Tarbert, Claire" }, + { + "name": "Tambini, Arielle" + }, { "name": "Nickson, Thomas" }, @@ -636,6 +638,11 @@ { "name": "Flandin, Guillaume" }, + { + "affiliation": "Stanford University", + "name": "Lerma-Usabiaga, Garikoitz", + "orcid": "0000-0001-9800-4816" + }, { "affiliation": "Vrije Universiteit Amsterdam", "name": "Ort, Eduard" @@ -691,6 +698,9 @@ "name": "Mihai, Paul Glad", "orcid": "0000-0001-5715-6442" }, + { + "name": "Lai, Jeff" + }, { "affiliation": "MIT, HMS", "name": "Ghosh, Satrajit", diff --git a/doc/changelog/1.X.X-changelog b/doc/changelog/1.X.X-changelog index 9ef4474bf1..71363170df 100644 --- a/doc/changelog/1.X.X-changelog +++ b/doc/changelog/1.X.X-changelog @@ -1,3 +1,19 @@ +1.2.2 (September 07, 2019) +========================== + +##### [Full changelog](https://github.com/nipy/nipype/milestone/33?closed=1) + + * FIX: Ensure ``loadpkl`` returns a not None value (https://github.com/nipy/nipype/pull/3020) + * FIX: ``loadpkl`` failed when pklz file contained versioning info (https://github.com/nipy/nipype/pull/3017) + * FIX: Update mne.WatershedBEM command line (https://github.com/nipy/nipype/pull/3007) + * FIX: Specify correct stop criterion flag in PETPVC (https://github.com/nipy/nipype/pull/3010) + * ENH: Add interface for AFNI ``3dTsmooth`` (https://github.com/nipy/nipype/pull/2948) + * ENH: Additional arguments to ANTs N4BiasFieldCorrection (https://github.com/nipy/nipype/pull/3012) + * ENH: Add ``--rescale-intensities`` and name_source to N4BiasFieldCorrection (https://github.com/nipy/nipype/pull/3011) + * ENH: Add index_mask_file input to ImageStats (https://github.com/nipy/nipype/pull/3005) + * RF: Remove versioning from ``loadpkl`` (https://github.com/nipy/nipype/pull/3019) + * MAINT: Add ``python_requires`` to package metadata (https://github.com/nipy/nipype/pull/3006) + 1.2.1 (August 19, 2019) ======================= diff --git a/doc/conf.py b/doc/conf.py index 2a253eb7aa..bdf938a70c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -82,7 +82,7 @@ # The short X.Y version. version = nipype.__version__ # The full version, including alpha/beta/rc tags. -release = "1.2.1" +release = "1.2.2" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/documentation.rst b/doc/documentation.rst index ab33e90904..b285811531 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -9,7 +9,7 @@ Documentation :Release: |version| :Date: |today| -Previous versions: `1.2.1 `_ `1.2.0 `_ +Previous versions: `1.2.2 `_ `1.2.1 `_ .. container:: doc2 diff --git a/nipype/algorithms/misc.py b/nipype/algorithms/misc.py index a2eaad3610..4fcd7c8d85 100644 --- a/nipype/algorithms/misc.py +++ b/nipype/algorithms/misc.py @@ -799,11 +799,11 @@ def _run_interface(self, runtime): '(http://pandas.pydata.org/) to run.'), e) try: - import lockfile as pl + from filelock import SoftFileLock self._have_lock = True except ImportError: from warnings import warn - warn(('Python module lockfile was not found: AddCSVRow will not be' + warn(('Python module filelock was not found: AddCSVRow will not be' ' thread-safe in multi-processor execution')) input_dict = {} @@ -822,7 +822,7 @@ def _run_interface(self, runtime): df = pd.DataFrame([input_dict]) if self._have_lock: - self._lock = pl.FileLock(self.inputs.in_file) + self._lock = SoftFileLock('%s.lock' % self.inputs.in_file) # Acquire lock self._lock.acquire() @@ -837,13 +837,6 @@ def _run_interface(self, runtime): if self._have_lock: self._lock.release() - # Using nipype.external.portalocker this might be something like: - # with pl.Lock(self.inputs.in_file, timeout=1) as fh: - # if op.exists(fh): - # formerdf = pd.read_csv(fh, index_col=0) - # df = pd.concat([formerdf, df], ignore_index=True) - # df.to_csv(fh) - return runtime def _list_outputs(self): diff --git a/nipype/algorithms/tests/test_auto_AddCSVRow.py b/nipype/algorithms/tests/test_auto_AddCSVRow.py index 3090c8b6a9..a8c4467cbf 100644 --- a/nipype/algorithms/tests/test_auto_AddCSVRow.py +++ b/nipype/algorithms/tests/test_auto_AddCSVRow.py @@ -6,7 +6,10 @@ def test_AddCSVRow_inputs(): input_map = dict( _outputs=dict(usedefault=True, ), - in_file=dict(mandatory=True, ), + in_file=dict( + extensions=None, + mandatory=True, + ), ) inputs = AddCSVRow.input_spec() diff --git a/nipype/algorithms/tests/test_auto_Gunzip.py b/nipype/algorithms/tests/test_auto_Gunzip.py index e583deaa10..d84e84ad61 100644 --- a/nipype/algorithms/tests/test_auto_Gunzip.py +++ b/nipype/algorithms/tests/test_auto_Gunzip.py @@ -4,11 +4,10 @@ def test_Gunzip_inputs(): - input_map = dict( - in_file=dict( - extensions=None, - mandatory=True, - ), ) + input_map = dict(in_file=dict( + extensions=None, + mandatory=True, + ), ) inputs = Gunzip.input_spec() for key, metadata in list(input_map.items()): diff --git a/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py b/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py index 4da9dad47d..10eb41190b 100644 --- a/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py +++ b/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py @@ -4,11 +4,10 @@ def test_NonSteadyStateDetector_inputs(): - input_map = dict( - in_file=dict( - extensions=None, - mandatory=True, - ), ) + input_map = dict(in_file=dict( + extensions=None, + mandatory=True, + ), ) inputs = NonSteadyStateDetector.input_spec() for key, metadata in list(input_map.items()): diff --git a/nipype/external/cloghandler.py b/nipype/external/cloghandler.py index 5fda934c84..05e28968dd 100644 --- a/nipype/external/cloghandler.py +++ b/nipype/external/cloghandler.py @@ -36,10 +36,6 @@ testing, performance was more than adequate, but if you need a high-volume or low-latency solution, I suggest you look elsewhere. -This module currently only support the 'nt' and 'posix' platforms due to the -usage of the portalocker module. I do not have access to any other platforms -for testing, patches are welcome. - See the README file for an example usage of this module. """ @@ -63,13 +59,7 @@ except ImportError: codecs = None -# Question/TODO: Should we have a fallback mode if we can't load portalocker / -# we should still be better off than with the standard RotattingFileHandler -# class, right? We do some rename checking... that should prevent some file -# clobbering that the builtin class allows. - -# sibling module than handles all the ugly platform-specific details of file locking -from .portalocker import lock, unlock, LOCK_EX, LOCK_NB, LockException +from filelock import SoftFileLock # A client can set this to true to automatically convert relative paths to # absolute paths (which will also hide the absolute path warnings) @@ -168,11 +158,8 @@ def __init__(self, self.maxBytes = maxBytes self.backupCount = backupCount # Prevent multiple extensions on the lock file (Only handles the normal "*.log" case.) - if filename.endswith(".log"): - lock_file = filename[:-4] - else: - lock_file = filename - self.stream_lock = open(lock_file + ".lock", "w") + self.lock_file = '%s.lock' % filename + self.stream_lock = SoftFileLock(self.lock_file) # For debug mode, swap out the "_degrade()" method with a more a verbose one. if debug: @@ -189,7 +176,7 @@ def acquire(self): in 'degraded' mode. """ # handle thread lock Handler.acquire(self) - lock(self.stream_lock, LOCK_EX) + self.stream_lock.acquire() if self.stream.closed: self._openFile(self.mode) @@ -206,7 +193,7 @@ def release(self): self.stream.close() finally: try: - unlock(self.stream_lock) + self.stream_lock.release() finally: # release thread lock Handler.release(self) diff --git a/nipype/external/portalocker.py b/nipype/external/portalocker.py deleted file mode 100644 index 1da24d894c..0000000000 --- a/nipype/external/portalocker.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -# portalocker.py - Cross-platform (posix/nt) API for flock-style file locking. -# Requires python 1.5.2 or better. -'''Cross-platform (posix/nt) API for flock-style file locking. - -Synopsis: - - import portalocker - file = open('somefile', 'r+') - portalocker.lock(file, portalocker.LOCK_EX) - file.seek(12) - file.write('foo') - file.close() - -If you know what you're doing, you may choose to - - portalocker.unlock(file) - -before closing the file, but why? - -Methods: - - lock( file, flags ) - unlock( file ) - -Constants: - - LOCK_EX - LOCK_SH - LOCK_NB - -Exceptions: - - LockException - -Notes: - -For the 'nt' platform, this module requires the Python Extensions for Windows. -Be aware that this may not work as expected on Windows 95/98/ME. - -History: - -I learned the win32 technique for locking files from sample code -provided by John Nielsen in the documentation -that accompanies the win32 modules. - -Author: Jonathan Feinberg , - Lowell Alleman -Version: $Id: portalocker.py 5474 2008-05-16 20:53:50Z lowell $ - -''' -from __future__ import (print_function, division, unicode_literals, - absolute_import) -from builtins import open - -__all__ = [ - 'lock', - 'unlock', - 'LOCK_EX', - 'LOCK_SH', - 'LOCK_NB', - 'LockException', -] - -import os - - -class LockException(Exception): - # Error codes: - LOCK_FAILED = 1 - - -if os.name == 'nt': - import win32con - import win32file - import pywintypes - LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK - LOCK_SH = 0 # the default - LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY - # is there any reason not to reuse the following structure? - __overlapped = pywintypes.OVERLAPPED() -elif os.name == 'posix': - import fcntl - LOCK_EX = fcntl.LOCK_EX - LOCK_SH = fcntl.LOCK_SH - LOCK_NB = fcntl.LOCK_NB -else: - raise RuntimeError('PortaLocker only defined for nt and posix platforms') - -if os.name == 'nt': - - def lock(file, flags): - hfile = win32file._get_osfhandle(file.fileno()) - try: - win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped) - except pywintypes.error as exc_value: - # error: (33, 'LockFileEx', 'The process cannot access the file - # because another process has locked a portion of the file.') - if exc_value[0] == 33: - raise LockException(LockException.LOCK_FAILED, exc_value[2]) - else: - # Q: Are there exceptions/codes we should be dealing with here? - raise - - def unlock(file): - hfile = win32file._get_osfhandle(file.fileno()) - try: - win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped) - except pywintypes.error as exc_value: - if exc_value[0] == 158: - # error: (158, 'UnlockFileEx', 'The segment is already - # unlocked.') To match the 'posix' implementation, silently - # ignore this error - pass - else: - # Q: Are there exceptions/codes we should be dealing with here? - raise - -elif os.name == 'posix': - - def lock(file, flags): - try: - fcntl.flock(file.fileno(), flags) - except IOError as exc_value: - # The exception code varies on different systems so we'll catch - # every IO error - raise LockException(*exc_value) - - def unlock(file): - fcntl.flock(file.fileno(), fcntl.LOCK_UN) - - -if __name__ == '__main__': - from time import time, strftime, localtime - import sys - from . import portalocker - - log = open('log.txt', 'a+') - portalocker.lock(log, portalocker.LOCK_EX) - timestamp = strftime('%m/%d/%Y %H:%M:%S\n', localtime(time())) - log.write(timestamp) - - print('Wrote lines. Hit enter to release lock.') - dummy = sys.stdin.readline() - log.close() diff --git a/nipype/info.py b/nipype/info.py index 827bc93a12..83ce1ca43d 100644 --- a/nipype/info.py +++ b/nipype/info.py @@ -9,7 +9,7 @@ # nipype version information # Remove -dev for release -__version__ = '1.2.2-dev' +__version__ = '1.2.3-dev' def get_nipype_gitversion(): @@ -164,6 +164,7 @@ def get_nipype_gitversion(): 'scipy>=%s,<%s ; python_version <= "3.4"' % (SCIPY_MIN_VERSION, SCIPY_MAX_VERSION_34), 'simplejson>=%s' % SIMPLEJSON_MIN_VERSION, 'traits>=%s,!=5.0' % TRAITS_MIN_VERSION, + 'filelock>=3.0.0' ] # neurdflib has to come after prov diff --git a/nipype/interfaces/afni/__init__.py b/nipype/interfaces/afni/__init__.py index 7af80059f2..015f17df73 100644 --- a/nipype/interfaces/afni/__init__.py +++ b/nipype/interfaces/afni/__init__.py @@ -13,7 +13,7 @@ BlurInMask, BlurToFWHM, ClipLevel, DegreeCentrality, Despike, Detrend, ECM, Fim, Fourier, Hist, LFCD, Maskave, Means, OutlierCount, QualityIndex, ROIStats, Retroicor, Seg, SkullStrip, TCorr1D, TCorrMap, TCorrelate, TNorm, - TProject, TShift, Volreg, Warp, QwarpPlusMinus, Qwarp) + TProject, TShift, TSmooth, Volreg, Warp, QwarpPlusMinus, Qwarp) from .svm import (SVMTest, SVMTrain) from .utils import ( ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket, Calc, Cat, diff --git a/nipype/interfaces/afni/preprocess.py b/nipype/interfaces/afni/preprocess.py index a2e9cb7f4d..7b7d252c9f 100644 --- a/nipype/interfaces/afni/preprocess.py +++ b/nipype/interfaces/afni/preprocess.py @@ -2853,6 +2853,79 @@ def _list_outputs(self): return outputs +class TSmoothInputSpec(AFNICommandInputSpec): + in_file = File( + desc='input file to 3dTSmooth', + argstr='%s', + position=-1, + mandatory=True, + exists=True, + copyfile=False) + out_file = File( + name_template='%s_smooth', + desc='output file from 3dTSmooth', + argstr='-prefix %s', + name_source='in_file') + datum = traits.Str( + desc='Sets the data type of the output dataset', + argstr='-datum %s') + lin = traits.Bool( + desc='3 point linear filter: 0.15*a + 0.70*b + 0.15*c' + '[This is the default smoother]', + argstr='-lin') + med = traits.Bool( + desc='3 point median filter: median(a,b,c)', + argstr='-med') + osf = traits.Bool( + desc='3 point order statistics filter:' + '0.15*min(a,b,c) + 0.70*median(a,b,c) + 0.15*max(a,b,c)', + argstr='-osf') + lin3 = traits.Int( + desc='3 point linear filter: 0.5*(1-m)*a + m*b + 0.5*(1-m)*c' + "Here, 'm' is a number strictly between 0 and 1.", + argstr='-3lin %d') + hamming = traits.Int( + argstr='-hamming %d', + desc='Use N point Hamming windows.' + '(N must be odd and bigger than 1.)') + blackman = traits.Int( + argstr='-blackman %d', + desc='Use N point Blackman windows.' + '(N must be odd and bigger than 1.)') + custom = File( + argstr='-custom %s', + desc='odd # of coefficients must be in a single column in ASCII file') + adaptive = traits.Int( + argstr='-adaptive %d', + desc='use adaptive mean filtering of width N ' + '(where N must be odd and bigger than 3).') + + +class TSmooth(AFNICommand): + """Smooths each voxel time series in a 3D+time dataset and produces + as output a new 3D+time dataset (e.g., lowpass filter in time). + + For complete details, see the `3dTsmooth Documentation. + `_ + + Examples + ======== + + >>> from nipype.interfaces import afni + >>> from nipype.testing import example_data + >>> smooth = afni.TSmooth() + >>> smooth.inputs.in_file = 'functional.nii' + >>> smooth.inputs.adaptive = 5 + >>> smooth.cmdline + '3dTsmooth -adaptive 5 -prefix functional_smooth functional.nii' + >>> res = smooth.run() # doctest: +SKIP + + """ + _cmd = '3dTsmooth' + input_spec = TSmoothInputSpec + output_spec = AFNICommandOutputSpec + + class VolregInputSpec(AFNICommandInputSpec): in_file = File( desc='input file to 3dvolreg', diff --git a/nipype/interfaces/afni/tests/test_auto_Allineate.py b/nipype/interfaces/afni/tests/test_auto_Allineate.py index 0b110e669a..e1565376bd 100644 --- a/nipype/interfaces/afni/tests/test_auto_Allineate.py +++ b/nipype/interfaces/afni/tests/test_auto_Allineate.py @@ -86,6 +86,7 @@ def test_Allineate_inputs(): ), out_weight_file=dict( argstr='-wtprefix %s', + extensions=None, xor=['allcostx'], ), outputtype=dict(), diff --git a/nipype/interfaces/afni/tests/test_auto_Cat.py b/nipype/interfaces/afni/tests/test_auto_Cat.py index 345806f746..50806add01 100644 --- a/nipype/interfaces/afni/tests/test_auto_Cat.py +++ b/nipype/interfaces/afni/tests/test_auto_Cat.py @@ -21,10 +21,9 @@ def test_Cat_inputs(): usedefault=True, ), omitconst=dict(argstr='-nonconst', ), - out_cint=dict( - xor=[ - 'out_format', 'out_nice', 'out_double', 'out_fint', 'out_int' - ], ), + out_cint=dict(xor=[ + 'out_format', 'out_nice', 'out_double', 'out_fint', 'out_int' + ], ), out_double=dict( argstr='-d', xor=['out_format', 'out_nice', 'out_int', 'out_fint', 'out_cint'], diff --git a/nipype/interfaces/afni/tests/test_auto_ClipLevel.py b/nipype/interfaces/afni/tests/test_auto_ClipLevel.py index f9b3dbf705..96f928a809 100644 --- a/nipype/interfaces/afni/tests/test_auto_ClipLevel.py +++ b/nipype/interfaces/afni/tests/test_auto_ClipLevel.py @@ -17,6 +17,7 @@ def test_ClipLevel_inputs(): ), grad=dict( argstr='-grad %s', + extensions=None, position=3, xor='doall', ), diff --git a/nipype/interfaces/afni/tests/test_auto_LocalBistat.py b/nipype/interfaces/afni/tests/test_auto_LocalBistat.py index ed3e61d74d..4632e4cf7d 100644 --- a/nipype/interfaces/afni/tests/test_auto_LocalBistat.py +++ b/nipype/interfaces/afni/tests/test_auto_LocalBistat.py @@ -26,7 +26,10 @@ def test_LocalBistat_inputs(): mandatory=True, position=-1, ), - mask_file=dict(argstr='-mask %s', ), + mask_file=dict( + argstr='-mask %s', + extensions=None, + ), neighborhood=dict( argstr="-nbhd '%s(%s)'", mandatory=True, @@ -37,6 +40,7 @@ def test_LocalBistat_inputs(): ), out_file=dict( argstr='-prefix %s', + extensions=None, keep_extension=True, name_source='in_file1', name_template='%s_bistat', @@ -49,6 +53,7 @@ def test_LocalBistat_inputs(): ), weight_file=dict( argstr='-weight %s', + extensions=None, xor=['automask'], ), ) diff --git a/nipype/interfaces/afni/tests/test_auto_Localstat.py b/nipype/interfaces/afni/tests/test_auto_Localstat.py index 011ce44da8..62dc800941 100644 --- a/nipype/interfaces/afni/tests/test_auto_Localstat.py +++ b/nipype/interfaces/afni/tests/test_auto_Localstat.py @@ -21,7 +21,10 @@ def test_Localstat_inputs(): mandatory=True, position=-1, ), - mask_file=dict(argstr='-mask %s', ), + mask_file=dict( + argstr='-mask %s', + extensions=None, + ), neighborhood=dict( argstr="-nbhd '%s(%s)'", mandatory=True, @@ -33,6 +36,7 @@ def test_Localstat_inputs(): ), out_file=dict( argstr='-prefix %s', + extensions=None, keep_extension=True, name_source='in_file', name_template='%s_localstat', diff --git a/nipype/interfaces/afni/tests/test_auto_NwarpApply.py b/nipype/interfaces/afni/tests/test_auto_NwarpApply.py index e00457f4f3..87388c65ec 100644 --- a/nipype/interfaces/afni/tests/test_auto_NwarpApply.py +++ b/nipype/interfaces/afni/tests/test_auto_NwarpApply.py @@ -20,7 +20,10 @@ def test_NwarpApply_inputs(): usedefault=True, ), inv_warp=dict(argstr='-iwarp', ), - master=dict(argstr='-master %s', ), + master=dict( + argstr='-master %s', + extensions=None, + ), out_file=dict( argstr='-prefix %s', extensions=None, diff --git a/nipype/interfaces/afni/tests/test_auto_OneDToolPy.py b/nipype/interfaces/afni/tests/test_auto_OneDToolPy.py index f8e664a727..114fe53fba 100644 --- a/nipype/interfaces/afni/tests/test_auto_OneDToolPy.py +++ b/nipype/interfaces/afni/tests/test_auto_OneDToolPy.py @@ -30,6 +30,7 @@ def test_OneDToolPy_inputs(): show_censor_count=dict(argstr='-show_censor_count', ), show_cormat_warnings=dict( argstr='-show_cormat_warnings |& tee %s', + extensions=None, position=-1, xor=['out_file'], ), diff --git a/nipype/interfaces/afni/tests/test_auto_Qwarp.py b/nipype/interfaces/afni/tests/test_auto_Qwarp.py index 3ef8c2e9b2..0b8a9e38ec 100644 --- a/nipype/interfaces/afni/tests/test_auto_Qwarp.py +++ b/nipype/interfaces/afni/tests/test_auto_Qwarp.py @@ -125,7 +125,10 @@ def test_Qwarp_inputs(): name_source=['in_file'], name_template='ppp_%s', ), - out_weight_file=dict(argstr='-wtprefix %s', ), + out_weight_file=dict( + argstr='-wtprefix %s', + extensions=None, + ), outputtype=dict(), overwrite=dict(argstr='-overwrite', ), pblur=dict(argstr='-pblur %s', ), diff --git a/nipype/interfaces/afni/tests/test_auto_QwarpPlusMinus.py b/nipype/interfaces/afni/tests/test_auto_QwarpPlusMinus.py index ca27a0d682..e282d0d0a5 100644 --- a/nipype/interfaces/afni/tests/test_auto_QwarpPlusMinus.py +++ b/nipype/interfaces/afni/tests/test_auto_QwarpPlusMinus.py @@ -125,7 +125,10 @@ def test_QwarpPlusMinus_inputs(): position=0, usedefault=True, ), - out_weight_file=dict(argstr='-wtprefix %s', ), + out_weight_file=dict( + argstr='-wtprefix %s', + extensions=None, + ), outputtype=dict(), overwrite=dict(argstr='-overwrite', ), pblur=dict(argstr='-pblur %s', ), diff --git a/nipype/interfaces/afni/tests/test_auto_ROIStats.py b/nipype/interfaces/afni/tests/test_auto_ROIStats.py index d3c956f7c5..c7fc517ccc 100644 --- a/nipype/interfaces/afni/tests/test_auto_ROIStats.py +++ b/nipype/interfaces/afni/tests/test_auto_ROIStats.py @@ -49,7 +49,10 @@ def test_ROIStats_inputs(): position=-1, ), quiet=dict(argstr='-quiet', ), - roisel=dict(argstr='-roisel %s', ), + roisel=dict( + argstr='-roisel %s', + extensions=None, + ), stat=dict(argstr='%s...', ), zerofill=dict( argstr='-zerofill %s', diff --git a/nipype/interfaces/afni/tests/test_auto_ReHo.py b/nipype/interfaces/afni/tests/test_auto_ReHo.py index 0edcedcdaf..cf3e468159 100644 --- a/nipype/interfaces/afni/tests/test_auto_ReHo.py +++ b/nipype/interfaces/afni/tests/test_auto_ReHo.py @@ -25,13 +25,17 @@ def test_ReHo_inputs(): argstr='-in_rois %s', extensions=None, ), - mask_file=dict(argstr='-mask %s', ), + mask_file=dict( + argstr='-mask %s', + extensions=None, + ), neighborhood=dict( argstr='-nneigh %s', xor=['sphere', 'ellipsoid'], ), out_file=dict( argstr='-prefix %s', + extensions=None, keep_extension=True, name_source='in_file', name_template='%s_reho', diff --git a/nipype/interfaces/afni/tests/test_auto_Remlfit.py b/nipype/interfaces/afni/tests/test_auto_Remlfit.py index f2e6703bf6..05ee75210e 100644 --- a/nipype/interfaces/afni/tests/test_auto_Remlfit.py +++ b/nipype/interfaces/afni/tests/test_auto_Remlfit.py @@ -58,6 +58,7 @@ def test_Remlfit_inputs(): ), matim=dict( argstr='-matim %s', + extensions=None, xor=['matrix'], ), matrix=dict( diff --git a/nipype/interfaces/afni/tests/test_auto_Resample.py b/nipype/interfaces/afni/tests/test_auto_Resample.py index 560d883d75..f63e1347f5 100644 --- a/nipype/interfaces/afni/tests/test_auto_Resample.py +++ b/nipype/interfaces/afni/tests/test_auto_Resample.py @@ -17,7 +17,10 @@ def test_Resample_inputs(): mandatory=True, position=-1, ), - master=dict(argstr='-master %s', ), + master=dict( + argstr='-master %s', + extensions=None, + ), num_threads=dict( nohash=True, usedefault=True, diff --git a/nipype/interfaces/afni/tests/test_auto_TCorrMap.py b/nipype/interfaces/afni/tests/test_auto_TCorrMap.py index 1ea4c0790e..209473fe6f 100644 --- a/nipype/interfaces/afni/tests/test_auto_TCorrMap.py +++ b/nipype/interfaces/afni/tests/test_auto_TCorrMap.py @@ -93,7 +93,10 @@ def test_TCorrMap_inputs(): name_source='in_file', suffix='_qmean', ), - regress_out_timeseries=dict(argstr='-ort %s', ), + regress_out_timeseries=dict( + argstr='-ort %s', + extensions=None, + ), seeds=dict( argstr='-seed %s', extensions=None, diff --git a/nipype/interfaces/afni/tests/test_auto_TSmooth.py b/nipype/interfaces/afni/tests/test_auto_TSmooth.py new file mode 100644 index 0000000000..cbcc871bc7 --- /dev/null +++ b/nipype/interfaces/afni/tests/test_auto_TSmooth.py @@ -0,0 +1,55 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..preprocess import TSmooth + + +def test_TSmooth_inputs(): + input_map = dict( + adaptive=dict(argstr='-adaptive %d', ), + args=dict(argstr='%s', ), + blackman=dict(argstr='-blackman %d', ), + custom=dict( + argstr='-custom %s', + extensions=None, + ), + datum=dict(argstr='-datum %s', ), + environ=dict( + nohash=True, + usedefault=True, + ), + hamming=dict(argstr='-hamming %d', ), + in_file=dict( + argstr='%s', + copyfile=False, + extensions=None, + mandatory=True, + position=-1, + ), + lin=dict(argstr='-lin', ), + lin3=dict(argstr='-3lin %d', ), + med=dict(argstr='-med', ), + num_threads=dict( + nohash=True, + usedefault=True, + ), + osf=dict(argstr='-osf', ), + out_file=dict( + argstr='-prefix %s', + extensions=None, + name_source='in_file', + name_template='%s_smooth', + ), + outputtype=dict(), + ) + inputs = TSmooth.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value +def test_TSmooth_outputs(): + output_map = dict(out_file=dict(extensions=None, ), ) + outputs = TSmooth.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/afni/tests/test_auto_Zeropad.py b/nipype/interfaces/afni/tests/test_auto_Zeropad.py index abeceda432..1bd80cfad8 100644 --- a/nipype/interfaces/afni/tests/test_auto_Zeropad.py +++ b/nipype/interfaces/afni/tests/test_auto_Zeropad.py @@ -55,6 +55,7 @@ def test_Zeropad_inputs(): ), master=dict( argstr='-master %s', + extensions=None, xor=['I', 'S', 'A', 'P', 'L', 'R', 'z', 'RL', 'AP', 'IS', 'mm'], ), mm=dict( diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index adaf765527..eff769c628 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -7,7 +7,7 @@ import os from ...external.due import BibTeX -from ...utils.filemanip import split_filename, copyfile, which +from ...utils.filemanip import split_filename, copyfile, which, fname_presuffix from ..base import TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined from .base import ANTSCommand, ANTSCommandInputSpec @@ -274,18 +274,20 @@ class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec): argstr='--input-image %s', mandatory=True, desc=('input for bias correction. Negative values or values close to ' - 'zero should be processed prior to correction')) + 'zero should be processed prior to correction')) mask_image = File( argstr='--mask-image %s', desc=('image to specify region to perform final bias correction in')) weight_image = File( argstr='--weight-image %s', desc=('image for relative weighting (e.g. probability map of the white ' - 'matter) of voxels during the B-spline fitting. ')) + 'matter) of voxels during the B-spline fitting. ')) output_image = traits.Str( argstr='--output %s', desc='output file name', - genfile=True, + name_source=['input_image'], + name_template='%s_corrected', + keep_extension=True, hash_files=False) bspline_fitting_distance = traits.Float(argstr="--bspline-fitting %s") bspline_order = traits.Int(requires=['bspline_fitting_distance']) @@ -306,6 +308,25 @@ class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec): usedefault=True, desc='copy headers of the original image into the ' 'output (corrected) file') + rescale_intensities = traits.Bool( + False, usedefault=True, argstr='-r', min_ver='2.1.0', + desc="""\ +[NOTE: Only ANTs>=2.1.0] +At each iteration, a new intensity mapping is calculated and applied but there +is nothing which constrains the new intensity range to be within certain values. +The result is that the range can "drift" from the original at each iteration. +This option rescales to the [min,max] range of the original image intensities +within the user-specified mask.""") + histogram_sharpening = traits.Tuple( + (0.15, 0.01, 200), + traits.Float, traits.Float, traits.Int, + argstr='--histogram-sharpening [%g,%g,%d]', + desc="""\ +Three-values tuple of histogram sharpening parameters \ +(FWHM, wienerNose, numberOfHistogramBins). +These options describe the histogram sharpening parameters, i.e. the \ +deconvolution step parameters described in the original N3 algorithm. +The default values have been shown to work fairly well.""") class N4BiasFieldCorrectionOutputSpec(TraitedSpec): @@ -314,7 +335,10 @@ class N4BiasFieldCorrectionOutputSpec(TraitedSpec): class N4BiasFieldCorrection(ANTSCommand): - """N4 is a variant of the popular N3 (nonparameteric nonuniform normalization) + """ + Bias field correction. + + N4 is a variant of the popular N3 (nonparameteric nonuniform normalization) retrospective bias correction algorithm. Based on the assumption that the corruption of the low frequency bias field can be modeled as a convolution of the intensity histogram by a Gaussian, the basic algorithmic protocol is to @@ -367,34 +391,29 @@ class N4BiasFieldCorrection(ANTSCommand): >>> n4_4.cmdline 'N4BiasFieldCorrection -d 3 --input-image structural.nii \ --output [ structural_corrected.nii, structural_bias.nii ]' + + >>> n4_5 = N4BiasFieldCorrection() + >>> n4_5.inputs.input_image = 'structural.nii' + >>> n4_5.inputs.dimension = 3 + >>> n4_5.inputs.histogram_sharpening = (0.12, 0.02, 200) + >>> n4_5.cmdline + 'N4BiasFieldCorrection -d 3 --histogram-sharpening [0.12,0.02,200] \ +--input-image structural.nii --output structural_corrected.nii' + """ _cmd = 'N4BiasFieldCorrection' input_spec = N4BiasFieldCorrectionInputSpec output_spec = N4BiasFieldCorrectionOutputSpec - def _gen_filename(self, name): - if name == 'output_image': - output = self.inputs.output_image - if not isdefined(output): - _, name, ext = split_filename(self.inputs.input_image) - output = name + '_corrected' + ext - return output - - if name == 'bias_image': - output = self.inputs.bias_image - if not isdefined(output): - _, name, ext = split_filename(self.inputs.input_image) - output = name + '_bias' + ext - return output - return None + def __init__(self, *args, **kwargs): + """Instantiate the N4BiasFieldCorrection interface.""" + self._out_bias_file = None + super(N4BiasFieldCorrection, self).__init__(*args, **kwargs) def _format_arg(self, name, trait_spec, value): - if ((name == 'output_image') and - (self.inputs.save_bias or isdefined(self.inputs.bias_image))): - bias_image = self._gen_filename('bias_image') - output = self._gen_filename('output_image') - newval = '[ %s, %s ]' % (output, bias_image) + if name == 'output_image' and self._out_bias_file: + newval = '[ %s, %s ]' % (value, self._out_bias_file) return trait_spec.argstr % newval if name == 'bspline_fitting_distance': @@ -418,38 +437,35 @@ def _format_arg(self, name, trait_spec, value): name, trait_spec, value) def _parse_inputs(self, skip=None): - if skip is None: - skip = [] - skip += ['save_bias', 'bias_image'] + skip = (skip or []) + ['save_bias', 'bias_image'] + self._out_bias_file = None + if self.inputs.save_bias or isdefined(self.inputs.bias_image): + bias_image = self.inputs.bias_image + if not isdefined(bias_image): + bias_image = fname_presuffix(os.path.basename(self.inputs.input_image), + suffix='_bias') + self._out_bias_file = bias_image return super(N4BiasFieldCorrection, self)._parse_inputs(skip=skip) def _list_outputs(self): - outputs = self._outputs().get() - outputs['output_image'] = os.path.abspath( - self._gen_filename('output_image')) - - if self.inputs.save_bias or isdefined(self.inputs.bias_image): - outputs['bias_image'] = os.path.abspath( - self._gen_filename('bias_image')) - return outputs - - def _run_interface(self, runtime, correct_return_codes=(0, )): - runtime = super(N4BiasFieldCorrection, self)._run_interface( - runtime, correct_return_codes) + outputs = super(N4BiasFieldCorrection, self)._list_outputs() - if self.inputs.copy_header and runtime.returncode in correct_return_codes: - self._copy_header(self._gen_filename('output_image')) - if self.inputs.save_bias or isdefined(self.inputs.bias_image): - self._copy_header(self._gen_filename('bias_image')) + # Fix headers + if self.inputs.copy_header: + self._copy_header(outputs['output_image']) - return runtime + if self._out_bias_file: + outputs['bias_image'] = os.path.abspath(self._out_bias_file) + if self.inputs.copy_header: + self._copy_header(outputs['bias_image']) + return outputs def _copy_header(self, fname): - """Copy header from input image to an output image""" + """Copy header from input image to an output image.""" import nibabel as nb in_img = nb.load(self.inputs.input_image) out_img = nb.load(fname, mmap=False) - new_img = out_img.__class__(out_img.get_data(), in_img.affine, + new_img = out_img.__class__(out_img.get_fdata(), in_img.affine, in_img.header) new_img.set_data_dtype(out_img.get_data_dtype()) new_img.to_filename(fname) diff --git a/nipype/interfaces/ants/tests/test_auto_ANTS.py b/nipype/interfaces/ants/tests/test_auto_ANTS.py index 5c6fa2c501..1ee5cabe21 100644 --- a/nipype/interfaces/ants/tests/test_auto_ANTS.py +++ b/nipype/interfaces/ants/tests/test_auto_ANTS.py @@ -57,8 +57,8 @@ def test_ANTS_inputs(): regularization=dict(argstr='%s', ), regularization_deformation_field_sigma=dict( requires=['regularization'], ), - regularization_gradient_field_sigma=dict( - requires=['regularization'], ), + regularization_gradient_field_sigma=dict(requires=['regularization' + ], ), smoothing_sigmas=dict( argstr='--gaussian-smoothing-sigmas %s', sep='x', diff --git a/nipype/interfaces/ants/tests/test_auto_AntsJointFusion.py b/nipype/interfaces/ants/tests/test_auto_AntsJointFusion.py index 02ebe6431c..a2829be3fa 100644 --- a/nipype/interfaces/ants/tests/test_auto_AntsJointFusion.py +++ b/nipype/interfaces/ants/tests/test_auto_AntsJointFusion.py @@ -44,11 +44,10 @@ def test_AntsJointFusion_inputs(): nohash=True, usedefault=True, ), - out_atlas_voting_weight_name_format=dict( - requires=[ - 'out_label_fusion', 'out_intensity_fusion_name_format', - 'out_label_post_prob_name_format' - ], ), + out_atlas_voting_weight_name_format=dict(requires=[ + 'out_label_fusion', 'out_intensity_fusion_name_format', + 'out_label_post_prob_name_format' + ], ), out_intensity_fusion_name_format=dict(argstr='', ), out_label_fusion=dict( argstr='%s', diff --git a/nipype/interfaces/ants/tests/test_auto_Atropos.py b/nipype/interfaces/ants/tests/test_auto_Atropos.py index be1a271f9a..73d7f6813a 100644 --- a/nipype/interfaces/ants/tests/test_auto_Atropos.py +++ b/nipype/interfaces/ants/tests/test_auto_Atropos.py @@ -53,8 +53,8 @@ def test_Atropos_inputs(): prior_probability_threshold=dict(requires=['prior_weighting'], ), prior_weighting=dict(), save_posteriors=dict(), - use_mixture_model_proportions=dict( - requires=['posterior_formulation'], ), + use_mixture_model_proportions=dict(requires=['posterior_formulation' + ], ), use_random_seed=dict( argstr='--use-random-seed %d', usedefault=True, diff --git a/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py b/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py index c93d847d4b..833e32315b 100644 --- a/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py +++ b/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py @@ -25,6 +25,8 @@ def test_N4BiasFieldCorrection_inputs(): nohash=True, usedefault=True, ), + histogram_sharpening=dict( + argstr='--histogram-sharpening [%g,%g,%d]', ), input_image=dict( argstr='--input-image %s', extensions=None, @@ -41,8 +43,15 @@ def test_N4BiasFieldCorrection_inputs(): ), output_image=dict( argstr='--output %s', - genfile=True, hash_files=False, + keep_extension=True, + name_source=['input_image'], + name_template='%s_corrected', + ), + rescale_intensities=dict( + argstr='-r', + min_ver='2.1.0', + usedefault=True, ), save_bias=dict( mandatory=True, diff --git a/nipype/interfaces/base/tests/test_auto_StdOutCommandLine.py b/nipype/interfaces/base/tests/test_auto_StdOutCommandLine.py index e39dc3acaa..95afcd3216 100644 --- a/nipype/interfaces/base/tests/test_auto_StdOutCommandLine.py +++ b/nipype/interfaces/base/tests/test_auto_StdOutCommandLine.py @@ -12,6 +12,7 @@ def test_StdOutCommandLine_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_AnalyzeHeader.py b/nipype/interfaces/camino/tests/test_auto_AnalyzeHeader.py index 28170946ac..c40082d836 100644 --- a/nipype/interfaces/camino/tests/test_auto_AnalyzeHeader.py +++ b/nipype/interfaces/camino/tests/test_auto_AnalyzeHeader.py @@ -50,6 +50,7 @@ def test_AnalyzeHeader_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_ComputeEigensystem.py b/nipype/interfaces/camino/tests/test_auto_ComputeEigensystem.py index 66ac282175..edf38864fa 100644 --- a/nipype/interfaces/camino/tests/test_auto_ComputeEigensystem.py +++ b/nipype/interfaces/camino/tests/test_auto_ComputeEigensystem.py @@ -24,6 +24,7 @@ def test_ComputeEigensystem_inputs(): maxcomponents=dict(argstr='-maxcomponents %d', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_ComputeFractionalAnisotropy.py b/nipype/interfaces/camino/tests/test_auto_ComputeFractionalAnisotropy.py index 9cfae77b2f..75604df01b 100644 --- a/nipype/interfaces/camino/tests/test_auto_ComputeFractionalAnisotropy.py +++ b/nipype/interfaces/camino/tests/test_auto_ComputeFractionalAnisotropy.py @@ -20,6 +20,7 @@ def test_ComputeFractionalAnisotropy_inputs(): inputmodel=dict(argstr='-inputmodel %s', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_ComputeTensorTrace.py b/nipype/interfaces/camino/tests/test_auto_ComputeTensorTrace.py index 1443a253bd..4d31fa884c 100644 --- a/nipype/interfaces/camino/tests/test_auto_ComputeTensorTrace.py +++ b/nipype/interfaces/camino/tests/test_auto_ComputeTensorTrace.py @@ -20,6 +20,7 @@ def test_ComputeTensorTrace_inputs(): inputmodel=dict(argstr='-inputmodel %s', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_DTIFit.py b/nipype/interfaces/camino/tests/test_auto_DTIFit.py index 26d27d57d2..0870a77752 100644 --- a/nipype/interfaces/camino/tests/test_auto_DTIFit.py +++ b/nipype/interfaces/camino/tests/test_auto_DTIFit.py @@ -26,6 +26,7 @@ def test_DTIFit_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_DTLUTGen.py b/nipype/interfaces/camino/tests/test_auto_DTLUTGen.py index f7caf77ef1..3242163c3a 100644 --- a/nipype/interfaces/camino/tests/test_auto_DTLUTGen.py +++ b/nipype/interfaces/camino/tests/test_auto_DTLUTGen.py @@ -28,6 +28,7 @@ def test_DTLUTGen_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_FSL2Scheme.py b/nipype/interfaces/camino/tests/test_auto_FSL2Scheme.py index 350c604c99..9b8a74be6a 100644 --- a/nipype/interfaces/camino/tests/test_auto_FSL2Scheme.py +++ b/nipype/interfaces/camino/tests/test_auto_FSL2Scheme.py @@ -40,6 +40,7 @@ def test_FSL2Scheme_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_Image2Voxel.py b/nipype/interfaces/camino/tests/test_auto_Image2Voxel.py index 29864bef82..2c013cf216 100644 --- a/nipype/interfaces/camino/tests/test_auto_Image2Voxel.py +++ b/nipype/interfaces/camino/tests/test_auto_Image2Voxel.py @@ -18,6 +18,7 @@ def test_Image2Voxel_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_LinRecon.py b/nipype/interfaces/camino/tests/test_auto_LinRecon.py index 996d8f4b99..147cfaab5e 100644 --- a/nipype/interfaces/camino/tests/test_auto_LinRecon.py +++ b/nipype/interfaces/camino/tests/test_auto_LinRecon.py @@ -24,6 +24,7 @@ def test_LinRecon_inputs(): normalize=dict(argstr='-normalize', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_MESD.py b/nipype/interfaces/camino/tests/test_auto_MESD.py index 57dbbf3b28..f7dfecfdb9 100644 --- a/nipype/interfaces/camino/tests/test_auto_MESD.py +++ b/nipype/interfaces/camino/tests/test_auto_MESD.py @@ -42,6 +42,7 @@ def test_MESD_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_ModelFit.py b/nipype/interfaces/camino/tests/test_auto_ModelFit.py index e5c16ec975..6d49969eb6 100644 --- a/nipype/interfaces/camino/tests/test_auto_ModelFit.py +++ b/nipype/interfaces/camino/tests/test_auto_ModelFit.py @@ -34,6 +34,7 @@ def test_ModelFit_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_NIfTIDT2Camino.py b/nipype/interfaces/camino/tests/test_auto_NIfTIDT2Camino.py index 0a5583b03e..65e0210268 100644 --- a/nipype/interfaces/camino/tests/test_auto_NIfTIDT2Camino.py +++ b/nipype/interfaces/camino/tests/test_auto_NIfTIDT2Camino.py @@ -26,6 +26,7 @@ def test_NIfTIDT2Camino_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_PicoPDFs.py b/nipype/interfaces/camino/tests/test_auto_PicoPDFs.py index c918a372f1..e5cdea5cae 100644 --- a/nipype/interfaces/camino/tests/test_auto_PicoPDFs.py +++ b/nipype/interfaces/camino/tests/test_auto_PicoPDFs.py @@ -36,6 +36,7 @@ def test_PicoPDFs_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_ProcStreamlines.py b/nipype/interfaces/camino/tests/test_auto_ProcStreamlines.py index c30ef08d8c..0386e0d54f 100644 --- a/nipype/interfaces/camino/tests/test_auto_ProcStreamlines.py +++ b/nipype/interfaces/camino/tests/test_auto_ProcStreamlines.py @@ -62,6 +62,7 @@ def test_ProcStreamlines_inputs(): noresample=dict(argstr='-noresample', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_QBallMX.py b/nipype/interfaces/camino/tests/test_auto_QBallMX.py index 7f7d0bc99f..f452f26350 100644 --- a/nipype/interfaces/camino/tests/test_auto_QBallMX.py +++ b/nipype/interfaces/camino/tests/test_auto_QBallMX.py @@ -20,6 +20,7 @@ def test_QBallMX_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_SFLUTGen.py b/nipype/interfaces/camino/tests/test_auto_SFLUTGen.py index 795138ea89..220e116255 100644 --- a/nipype/interfaces/camino/tests/test_auto_SFLUTGen.py +++ b/nipype/interfaces/camino/tests/test_auto_SFLUTGen.py @@ -35,6 +35,7 @@ def test_SFLUTGen_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_SFPICOCalibData.py b/nipype/interfaces/camino/tests/test_auto_SFPICOCalibData.py index 80222fce4c..1b71553676 100644 --- a/nipype/interfaces/camino/tests/test_auto_SFPICOCalibData.py +++ b/nipype/interfaces/camino/tests/test_auto_SFPICOCalibData.py @@ -27,6 +27,7 @@ def test_SFPICOCalibData_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_SFPeaks.py b/nipype/interfaces/camino/tests/test_auto_SFPeaks.py index 8db250c58c..49ac58aa06 100644 --- a/nipype/interfaces/camino/tests/test_auto_SFPeaks.py +++ b/nipype/interfaces/camino/tests/test_auto_SFPeaks.py @@ -38,6 +38,7 @@ def test_SFPeaks_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_Shredder.py b/nipype/interfaces/camino/tests/test_auto_Shredder.py index 594b35fc60..2d8ec43589 100644 --- a/nipype/interfaces/camino/tests/test_auto_Shredder.py +++ b/nipype/interfaces/camino/tests/test_auto_Shredder.py @@ -28,6 +28,7 @@ def test_Shredder_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_TractShredder.py b/nipype/interfaces/camino/tests/test_auto_TractShredder.py index eeed244533..e4df010c60 100644 --- a/nipype/interfaces/camino/tests/test_auto_TractShredder.py +++ b/nipype/interfaces/camino/tests/test_auto_TractShredder.py @@ -28,6 +28,7 @@ def test_TractShredder_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/camino/tests/test_auto_VtkStreamlines.py b/nipype/interfaces/camino/tests/test_auto_VtkStreamlines.py index 72b6f106d8..bd8d295572 100644 --- a/nipype/interfaces/camino/tests/test_auto_VtkStreamlines.py +++ b/nipype/interfaces/camino/tests/test_auto_VtkStreamlines.py @@ -25,6 +25,7 @@ def test_VtkStreamlines_inputs(): interpolatescalars=dict(argstr='-interpolatescalars', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/freesurfer/tests/test_auto_Aparc2Aseg.py b/nipype/interfaces/freesurfer/tests/test_auto_Aparc2Aseg.py index 8a83130a4d..494ce981c5 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_Aparc2Aseg.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_Aparc2Aseg.py @@ -79,11 +79,10 @@ def test_Aparc2Aseg_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_Aparc2Aseg_outputs(): - output_map = dict( - out_file=dict( - argstr='%s', - extensions=None, - ), ) + output_map = dict(out_file=dict( + argstr='%s', + extensions=None, + ), ) outputs = Aparc2Aseg.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_Apas2Aseg.py b/nipype/interfaces/freesurfer/tests/test_auto_Apas2Aseg.py index fea3617596..03385da2ad 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_Apas2Aseg.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_Apas2Aseg.py @@ -28,11 +28,10 @@ def test_Apas2Aseg_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_Apas2Aseg_outputs(): - output_map = dict( - out_file=dict( - argstr='%s', - extensions=None, - ), ) + output_map = dict(out_file=dict( + argstr='%s', + extensions=None, + ), ) outputs = Apas2Aseg.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_CALabel.py b/nipype/interfaces/freesurfer/tests/test_auto_CALabel.py index f3bfd5ad62..4d56d217c7 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_CALabel.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_CALabel.py @@ -7,7 +7,10 @@ def test_CALabel_inputs(): input_map = dict( align=dict(argstr='-align', ), args=dict(argstr='%s', ), - aseg=dict(argstr='-aseg %s', ), + aseg=dict( + argstr='-aseg %s', + extensions=None, + ), environ=dict( nohash=True, usedefault=True, @@ -26,7 +29,10 @@ def test_CALabel_inputs(): argstr='-r %s', extensions=None, ), - label=dict(argstr='-l %s', ), + label=dict( + argstr='-l %s', + extensions=None, + ), no_big_ventricles=dict(argstr='-nobigventricles', ), num_threads=dict(), out_file=dict( diff --git a/nipype/interfaces/freesurfer/tests/test_auto_CANormalize.py b/nipype/interfaces/freesurfer/tests/test_auto_CANormalize.py index 1f6546ae3a..5700103e84 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_CANormalize.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_CANormalize.py @@ -59,7 +59,7 @@ def test_CANormalize_inputs(): def test_CANormalize_outputs(): output_map = dict( control_points=dict(extensions=None, ), - out_file=dict(), + out_file=dict(extensions=None, ), ) outputs = CANormalize.output_spec() diff --git a/nipype/interfaces/freesurfer/tests/test_auto_CARegister.py b/nipype/interfaces/freesurfer/tests/test_auto_CARegister.py index 83f669b218..dcf5aa84a8 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_CARegister.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_CARegister.py @@ -53,7 +53,7 @@ def test_CARegister_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_CARegister_outputs(): - output_map = dict(out_file=dict(), ) + output_map = dict(out_file=dict(extensions=None, ), ) outputs = CARegister.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_CheckTalairachAlignment.py b/nipype/interfaces/freesurfer/tests/test_auto_CheckTalairachAlignment.py index 68a5a98e66..fe9c1a3121 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_CheckTalairachAlignment.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_CheckTalairachAlignment.py @@ -35,7 +35,7 @@ def test_CheckTalairachAlignment_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_CheckTalairachAlignment_outputs(): - output_map = dict(out_file=dict(), ) + output_map = dict(out_file=dict(extensions=None, ), ) outputs = CheckTalairachAlignment.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ConcatenateLTA.py b/nipype/interfaces/freesurfer/tests/test_auto_ConcatenateLTA.py index 8acab945c1..ee1d3ae7f3 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_ConcatenateLTA.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_ConcatenateLTA.py @@ -38,11 +38,13 @@ def test_ConcatenateLTA_inputs(): subjects_dir=dict(), tal_source_file=dict( argstr='-tal %s', + extensions=None, position=-5, requires=['tal_template_file'], ), tal_template_file=dict( argstr='%s', + extensions=None, position=-4, requires=['tal_source_file'], ), diff --git a/nipype/interfaces/freesurfer/tests/test_auto_Contrast.py b/nipype/interfaces/freesurfer/tests/test_auto_Contrast.py index 3c4e5aa484..3cd62e8ee7 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_Contrast.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_Contrast.py @@ -5,10 +5,16 @@ def test_Contrast_inputs(): input_map = dict( - annotation=dict(mandatory=True, ), + annotation=dict( + extensions=None, + mandatory=True, + ), args=dict(argstr='%s', ), copy_inputs=dict(), - cortex=dict(mandatory=True, ), + cortex=dict( + extensions=None, + mandatory=True, + ), environ=dict( nohash=True, usedefault=True, diff --git a/nipype/interfaces/freesurfer/tests/test_auto_FixTopology.py b/nipype/interfaces/freesurfer/tests/test_auto_FixTopology.py index 4ba8442b14..83427dcd20 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_FixTopology.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_FixTopology.py @@ -35,7 +35,10 @@ def test_FixTopology_inputs(): ), mgz=dict(argstr='-mgz', ), seed=dict(argstr='-seed %d', ), - sphere=dict(argstr='-sphere %s', ), + sphere=dict( + argstr='-sphere %s', + extensions=None, + ), subject_id=dict( argstr='%s', mandatory=True, diff --git a/nipype/interfaces/freesurfer/tests/test_auto_MRIsCALabel.py b/nipype/interfaces/freesurfer/tests/test_auto_MRIsCALabel.py index 10c7af6832..eaf91bc1e8 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_MRIsCALabel.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_MRIsCALabel.py @@ -6,7 +6,10 @@ def test_MRIsCALabel_inputs(): input_map = dict( args=dict(argstr='%s', ), - aseg=dict(argstr='-aseg %s', ), + aseg=dict( + argstr='-aseg %s', + extensions=None, + ), canonsurf=dict( argstr='%s', extensions=None, @@ -33,7 +36,10 @@ def test_MRIsCALabel_inputs(): mandatory=True, position=-4, ), - label=dict(argstr='-l %s', ), + label=dict( + argstr='-l %s', + extensions=None, + ), num_threads=dict(), out_file=dict( argstr='%s', diff --git a/nipype/interfaces/freesurfer/tests/test_auto_MS_LDA.py b/nipype/interfaces/freesurfer/tests/test_auto_MS_LDA.py index badb3b4f0c..3d3f5cde11 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_MS_LDA.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_MS_LDA.py @@ -17,22 +17,30 @@ def test_MS_LDA_inputs(): mandatory=True, position=-1, ), - label_file=dict(argstr='-label %s', ), + label_file=dict( + argstr='-label %s', + extensions=None, + ), lda_labels=dict( argstr='-lda %s', mandatory=True, sep=' ', ), - mask_file=dict(argstr='-mask %s', ), + mask_file=dict( + argstr='-mask %s', + extensions=None, + ), shift=dict(argstr='-shift %d', ), subjects_dir=dict(), use_weights=dict(argstr='-W', ), vol_synth_file=dict( argstr='-synth %s', + extensions=None, mandatory=True, ), weight_file=dict( argstr='-weight %s', + extensions=None, mandatory=True, ), ) diff --git a/nipype/interfaces/freesurfer/tests/test_auto_Normalize.py b/nipype/interfaces/freesurfer/tests/test_auto_Normalize.py index 2384adbb2b..baf03f026c 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_Normalize.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_Normalize.py @@ -43,7 +43,7 @@ def test_Normalize_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_Normalize_outputs(): - output_map = dict(out_file=dict(), ) + output_map = dict(out_file=dict(extensions=None, ), ) outputs = Normalize.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ParcellationStats.py b/nipype/interfaces/freesurfer/tests/test_auto_ParcellationStats.py index be19b2bd37..8b4ae45d67 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_ParcellationStats.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_ParcellationStats.py @@ -27,11 +27,16 @@ def test_ParcellationStats_inputs(): ), in_annotation=dict( argstr='-a %s', + extensions=None, xor=['in_label'], ), - in_cortex=dict(argstr='-cortex %s', ), + in_cortex=dict( + argstr='-cortex %s', + extensions=None, + ), in_label=dict( argstr='-l %s', + extensions=None, xor=['in_annotatoin', 'out_color'], ), lh_pial=dict( @@ -45,11 +50,13 @@ def test_ParcellationStats_inputs(): mgz=dict(argstr='-mgz', ), out_color=dict( argstr='-c %s', + extensions=None, genfile=True, xor=['in_label'], ), out_table=dict( argstr='-f %s', + extensions=None, genfile=True, requires=['tabular_output'], ), diff --git a/nipype/interfaces/freesurfer/tests/test_auto_RegisterAVItoTalairach.py b/nipype/interfaces/freesurfer/tests/test_auto_RegisterAVItoTalairach.py index f3406d41fc..5a609f586e 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_RegisterAVItoTalairach.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_RegisterAVItoTalairach.py @@ -47,7 +47,7 @@ def test_RegisterAVItoTalairach_outputs(): extensions=None, usedefault=True, ), - out_file=dict(), + out_file=dict(extensions=None, ), ) outputs = RegisterAVItoTalairach.output_spec() diff --git a/nipype/interfaces/freesurfer/tests/test_auto_RelabelHypointensities.py b/nipype/interfaces/freesurfer/tests/test_auto_RelabelHypointensities.py index 28ff49d99e..f99acec899 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_RelabelHypointensities.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_RelabelHypointensities.py @@ -48,11 +48,10 @@ def test_RelabelHypointensities_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_RelabelHypointensities_outputs(): - output_map = dict( - out_file=dict( - argstr='%s', - extensions=None, - ), ) + output_map = dict(out_file=dict( + argstr='%s', + extensions=None, + ), ) outputs = RelabelHypointensities.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_auto_SegStatsReconAll.py b/nipype/interfaces/freesurfer/tests/test_auto_SegStatsReconAll.py index 3cf47c71ce..09da0d001d 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_SegStatsReconAll.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_SegStatsReconAll.py @@ -100,7 +100,10 @@ def test_SegStatsReconAll_inputs(): extensions=None, mandatory=True, ), - ribbon=dict(mandatory=True, ), + ribbon=dict( + extensions=None, + mandatory=True, + ), segment_id=dict(argstr='--id %s...', ), segmentation_file=dict( argstr='--seg %s', diff --git a/nipype/interfaces/freesurfer/tests/test_auto_SurfaceSnapshots.py b/nipype/interfaces/freesurfer/tests/test_auto_SurfaceSnapshots.py index 26dcbe3458..968041ff67 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_SurfaceSnapshots.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_SurfaceSnapshots.py @@ -59,6 +59,7 @@ def test_SurfaceSnapshots_inputs(): overlay_range_offset=dict(argstr='-foffset %.3f', ), overlay_reg=dict( argstr='-overlay-reg %s', + extensions=None, xor=['overlay_reg', 'identity_reg', 'mni152_reg'], ), patch_file=dict( diff --git a/nipype/interfaces/freesurfer/tests/test_auto_TalairachAVI.py b/nipype/interfaces/freesurfer/tests/test_auto_TalairachAVI.py index 9d248c1a7d..2a28765d67 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_TalairachAVI.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_TalairachAVI.py @@ -30,9 +30,9 @@ def test_TalairachAVI_inputs(): assert getattr(inputs.traits()[key], metakey) == value def test_TalairachAVI_outputs(): output_map = dict( - out_file=dict(), - out_log=dict(), - out_txt=dict(), + out_file=dict(extensions=None, ), + out_log=dict(extensions=None, ), + out_txt=dict(extensions=None, ), ) outputs = TalairachAVI.output_spec() diff --git a/nipype/interfaces/freesurfer/tests/test_auto_TalairachQC.py b/nipype/interfaces/freesurfer/tests/test_auto_TalairachQC.py index 053d429c9b..1961e3ded6 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_TalairachQC.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_TalairachQC.py @@ -24,11 +24,10 @@ def test_TalairachQC_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_TalairachQC_outputs(): - output_map = dict( - log_file=dict( - extensions=None, - usedefault=True, - ), ) + output_map = dict(log_file=dict( + extensions=None, + usedefault=True, + ), ) outputs = TalairachQC.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/fsl/epi.py b/nipype/interfaces/fsl/epi.py index f94bda1147..591cc148e7 100644 --- a/nipype/interfaces/fsl/epi.py +++ b/nipype/interfaces/fsl/epi.py @@ -14,7 +14,7 @@ import nibabel as nb import warnings -from ...utils.filemanip import split_filename +from ...utils.filemanip import split_filename, fname_presuffix from ...utils import NUMPY_MMAP from ..base import (traits, TraitedSpec, InputMultiPath, File, isdefined) @@ -521,8 +521,7 @@ class EddyInputSpec(FSLCommandInputSpec): exists=True, mandatory=True, argstr='--imain=%s', - desc=('File containing all the images to estimate ' - 'distortions for')) + desc='File containing all the images to estimate distortions for') in_mask = File( exists=True, mandatory=True, @@ -543,34 +542,41 @@ class EddyInputSpec(FSLCommandInputSpec): exists=True, mandatory=True, argstr='--bvecs=%s', - desc=('File containing the b-vectors for all volumes in ' - '--imain')) + desc='File containing the b-vectors for all volumes in --imain') in_bval = File( exists=True, mandatory=True, argstr='--bvals=%s', - desc=('File containing the b-values for all volumes in ' - '--imain')) + desc='File containing the b-values for all volumes in --imain') out_base = traits.Str( - 'eddy_corrected', - argstr='--out=%s', + default_value='eddy_corrected', usedefault=True, - desc=('basename for output (warped) image')) + argstr='--out=%s', + desc='basename for output (warped) image') session = File( exists=True, argstr='--session=%s', - desc=('File containing session indices for all volumes in ' - '--imain')) + desc='File containing session indices for all volumes in --imain') in_topup_fieldcoef = File( exists=True, - argstr="--topup=%s", + argstr='--topup=%s', requires=['in_topup_movpar'], - desc=('topup file containing the field ' - 'coefficients')) + desc='topup file containing the field coefficients') in_topup_movpar = File( exists=True, requires=['in_topup_fieldcoef'], desc='topup movpar.txt file') + field = File( + argstr='--field=%s', + desc=('NonTOPUP fieldmap scaled in Hz - filename has ' + 'to be provided without an extension. TOPUP is ' + 'strongly recommended')) + field_mat = File( + exists=True, + argstr='--field_mat=%s', + desc=('Matrix that specifies the relative locations of ' + 'the field specified by --field and first volume ' + 'in file --imain')) flm = traits.Enum( 'linear', @@ -578,87 +584,175 @@ class EddyInputSpec(FSLCommandInputSpec): 'cubic', argstr='--flm=%s', desc='First level EC model') - slm = traits.Enum( 'none', 'linear', 'quadratic', argstr='--slm=%s', desc='Second level EC model') - fep = traits.Bool( False, argstr='--fep', desc='Fill empty planes in x- or y-directions') - + initrand = traits.Bool( + False, + argstr='--initrand', + desc='Resets rand for when selecting voxels', + min_ver='5.0.10') interp = traits.Enum( 'spline', 'trilinear', argstr='--interp=%s', desc='Interpolation model for estimation step') - nvoxhp = traits.Int( - 1000, usedefault=True, + default_value=1000, + usedefault=True, argstr='--nvoxhp=%s', desc=('# of voxels used to estimate the ' 'hyperparameters')) - fudge_factor = traits.Float( - 10.0, usedefault=True, + default_value=10.0, + usedefault=True, argstr='--ff=%s', desc=('Fudge factor for hyperparameter ' 'error variance')) - dont_sep_offs_move = traits.Bool( False, argstr='--dont_sep_offs_move', desc=('Do NOT attempt to separate ' 'field offset from subject ' 'movement')) - dont_peas = traits.Bool( False, argstr='--dont_peas', desc="Do NOT perform a post-eddy alignment of " "shells") - fwhm = traits.Float( desc=('FWHM for conditioning filter when estimating ' 'the parameters'), argstr='--fwhm=%s') - niter = traits.Int(5, usedefault=True, argstr='--niter=%s', desc='Number of iterations') - method = traits.Enum( 'jac', 'lsr', argstr='--resamp=%s', desc=('Final resampling method (jacobian/least ' 'squares)')) + repol = traits.Bool( False, argstr='--repol', desc='Detect and replace outlier slices') + outlier_nstd = traits.Int( + argstr='--ol_nstd', + desc='Number of std off to qualify as outlier', + requires=['repol'], + min_ver='5.0.10') + outlier_nvox = traits.Int( + argstr='--ol_nvox', + desc='Min # of voxels in a slice for inclusion in outlier detection', + requires=['repol'], + min_ver='5.0.10') + outlier_type = traits.Enum( + 'sw', + 'gw', + 'both', + argstr='--ol_type', + desc='Type of outliers, slicewise (sw), groupwise (gw) or both (both)', + requires=['repol'], + min_ver='5.0.10') + outlier_pos = traits.Bool( + False, + argstr='--ol_pos', + desc='Consider both positive and negative outliers if set', + requires=['repol'], + min_ver='5.0.10') + outlier_sqr = traits.Bool( + False, + argstr='--ol_sqr', + desc='Consider outliers among sums-of-squared differences if set', + requires=['repol'], + min_ver='5.0.10') + mb = traits.Int( + argstr='--mb=%s', + desc='Multi-band factor', + min_ver='5.0.10') + mb_offs = traits.Enum( + 0, + 1, + -1, + argstr='--mb_offs=%s', + desc=('Multi-band offset (-1 if bottom slice removed, 1 if ' + 'top slice removed'), + requires=['mb'], + min_ver='5.0.10') + + mporder = traits.Int( + argstr='--mporder=%s', + desc='Order of slice-to-vol movement model', + requires=['slspec'], + min_ver='5.0.11') + s2v_niter = traits.Int( + argstr='--s2v_niter=%s', + desc='Number of iterations for slice-to-vol', + requires=['slspec'], + min_ver='5.0.11') + s2v_lambda = traits.Int( + agstr='--s2v_lambda', + desc='Regularisation weight for slice-to-vol movement (reasonable range 1-10)', + requires=['slspec'], + min_ver='5.0.11') + s2v_interp = traits.Enum( + 'trilinear', + 'spline', + argstr='--s2v_interp=%s', + desc='Slice-to-vol interpolation model for estimation step', + requires=['slspec'], + min_ver='5.0.11') + slspec = traits.File( + exists=True, + argstr='--slspec=%s', + desc='Name of text file completely specifying slice/group acquisition', + xor=['json'], + min_ver='5.0.11') + json = traits.File( + exists=True, + argstr='--json=%s', + desc='Name of .json text file with information about slice timing', + xor=['slspec'], + min_ver='6.0.1') + + estimate_move_by_susceptibility = traits.Bool( + False, + argstr='--estimate_move_by_susceptibility', + desc='Estimate how susceptibility field changes with subject movement', + min_ver='6.0.1') + mbs_niter = traits.Int( + argstr='--mbs_niter=%s', + desc='Number of iterations for MBS estimation', + requires=['estimate_move_by_susceptibility'], + min_ver='6.0.1') + mbs_lambda = traits.Int( + argstr='--mbs_lambda=%s', + desc='Weighting of regularisation for MBS estimation', + requires=['estimate_move_by_susceptibility'], + min_ver='6.0.1') + mbs_ksp = traits.Int( + argstr='--mbs_ksp=%smm', + desc='Knot-spacing for MBS field estimation', + requires=['estimate_move_by_susceptibility'], + min_ver='6.0.1') + num_threads = traits.Int( 1, usedefault=True, nohash=True, - desc="Number of openmp threads to use") + desc='Number of openmp threads to use') is_shelled = traits.Bool( False, argstr='--data_is_shelled', - desc="Override internal check to ensure that " - "date are acquired on a set of b-value " - "shells") - field = traits.Str( - argstr='--field=%s', - desc="NonTOPUP fieldmap scaled in Hz - filename has " - "to be provided without an extension. TOPUP is " - "strongly recommended") - field_mat = File( - exists=True, - argstr='--field_mat=%s', - desc="Matrix that specifies the relative locations of " - "the field specified by --field and first volume " - "in file --imain") - use_cuda = traits.Bool(False, desc="Run eddy using cuda gpu") + desc=('Override internal check to ensure that ' + 'date are acquired on a set of b-value ' + 'shells')) + + use_cuda = traits.Bool(False, desc='Run eddy using cuda gpu') cnr_maps = traits.Bool( False, desc='Output CNR-Maps', argstr='--cnr_maps', min_ver='5.0.10') residuals = traits.Bool( @@ -670,7 +764,7 @@ class EddyOutputSpec(TraitedSpec): exists=True, desc='4D image file containing all the corrected volumes') out_parameter = File( exists=True, - desc=('text file with parameters definining the field and' + desc=('Text file with parameters defining the field and' 'movement for each scan')) out_rotated_bvecs = File( exists=True, desc='File containing rotated b-values for all volumes') @@ -682,13 +776,48 @@ class EddyOutputSpec(TraitedSpec): 'disregarding translation in the PE direction')) out_shell_alignment_parameters = File( exists=True, - desc=('File containing rigid body movement parameters ' + desc=('Text file containing rigid body movement parameters ' + 'between the different shells as estimated by a ' + 'post-hoc mutual information based registration')) + out_shell_pe_translation_parameters = File( + exists=True, + desc=('Text file containing translation along the PE-direction ' + 'between the different shells as estimated by a ' + 'post-hoc mutual information based registration')) + out_shell_pe_translation_parameters = File( + exists=True, + desc=('Text file containing translation along the PE-direction ' 'between the different shells as estimated by a ' 'post-hoc mutual information based registration')) + out_outlier_map = File( + exists=True, + desc=('Matrix where rows represent volumes and columns represent ' + 'slices. "0" indicates that scan-slice is not an outlier ' + 'and "1" indicates that it is')) + out_outlier_n_stdev_map = File( + exists=True, + desc=('Matrix where rows represent volumes and columns represent ' + 'slices. Values indicate number of standard deviations off the ' + 'mean difference between observation and prediction is')) + out_outlier_n_sqr_stdev_map = File( + exists=True, + desc=('Matrix where rows represent volumes and columns represent ' + 'slices. Values indicate number of standard deivations off the ' + 'square root of the mean squared difference between observation ' + 'and prediction is')) out_outlier_report = File( exists=True, - desc=('Text-file with a plain language report on what ' + desc=('Text file with a plain language report on what ' 'outlier slices eddy has found')) + out_outlier_free = File( + exists=True, + desc=('4D image file not corrected for susceptibility or eddy-' + 'current distortions or subject movement but with outlier ' + 'slices replaced')) + out_movement_over_time = File( + exists=True, + desc=('Text file containing translations (mm) and rotations ' + '(radians) for each excitation')) out_cnr_maps = File( exists=True, desc='path/name of file with the cnr_maps') out_residuals = File( @@ -699,9 +828,9 @@ class Eddy(FSLCommand): """ Interface for FSL eddy, a tool for estimating and correcting eddy currents induced distortions. `User guide - `_ and + `_ and `more info regarding acqp file - `_. + `_. Examples -------- @@ -716,12 +845,12 @@ class Eddy(FSLCommand): >>> eddy.inputs.in_bval = 'bvals.scheme' >>> eddy.inputs.use_cuda = True >>> eddy.cmdline # doctest: +ELLIPSIS - 'eddy_cuda --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ + 'eddy_cuda --ff=10.0 --fwhm=0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ --bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \ --mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected' >>> eddy.inputs.use_cuda = False >>> eddy.cmdline # doctest: +ELLIPSIS - 'eddy_openmp --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ + 'eddy_openmp --ff=10.0 --fwhm=0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ --bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \ --mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected' >>> res = eddy.run() # doctest: +SKIP @@ -772,6 +901,8 @@ def _run_interface(self, runtime): def _format_arg(self, name, spec, value): if name == 'in_topup_fieldcoef': return spec.argstr % value.split('_fieldcoef')[0] + if name == 'field': + return spec.argstr % fname_presuffix(value, use_ext=False) if name == 'out_base': return spec.argstr % os.path.abspath(value) return super(Eddy, self)._format_arg(name, spec, value) @@ -793,8 +924,27 @@ def _list_outputs(self): out_shell_alignment_parameters = os.path.abspath( '%s.eddy_post_eddy_shell_alignment_parameters' % self.inputs.out_base) + out_shell_pe_translation_parameters = os.path.abspath( + '%s.eddy_post_eddy_shell_PE_translation_parameters' % + self.inputs.out_base) + out_outlier_map = os.path.abspath( + '%s.eddy_outlier_map' % self.inputs.out_base) + out_outlier_n_stdev_map = os.path.abspath( + '%s.eddy_outlier_n_stdev_map' % self.inputs.out_base) + out_outlier_n_sqr_stdev_map = os.path.abspath( + '%s.eddy_outlier_n_sqr_stdev_map' % self.inputs.out_base) out_outlier_report = os.path.abspath( '%s.eddy_outlier_report' % self.inputs.out_base) + if isdefined(self.inputs.repol) and self.inputs.repol: + out_outlier_free = os.path.abspath( + '%s.eddy_outlier_free_data' % self.inputs.out_base) + if os.path.exists(out_outlier_free): + outputs['out_outlier_free'] = out_outlier_free + if isdefined(self.inputs.mporder) and self.inputs.mporder > 0: + out_movement_over_time = os.path.abspath( + '%s.eddy_movement_over_time' % self.inputs.out_base) + if os.path.exists(out_movement_over_time): + outputs['out_movement_over_time'] = out_movement_over_time if isdefined(self.inputs.cnr_maps) and self.inputs.cnr_maps: out_cnr_maps = os.path.abspath( '%s.eddy_cnr_maps.nii.gz' % self.inputs.out_base) @@ -816,6 +966,15 @@ def _list_outputs(self): if os.path.exists(out_shell_alignment_parameters): outputs['out_shell_alignment_parameters'] = \ out_shell_alignment_parameters + if os.path.exists(out_shell_pe_translation_parameters): + outputs['out_shell_pe_translation_parameters'] = \ + out_shell_pe_translation_parameters + if os.path.exists(out_outlier_map): + outputs['out_outlier_map'] = out_outlier_map + if os.path.exists(out_outlier_n_stdev_map): + outputs['out_outlier_n_stdev_map'] = out_outlier_n_stdev_map + if os.path.exists(out_outlier_n_sqr_stdev_map): + outputs['out_outlier_n_sqr_stdev_map'] = out_outlier_n_sqr_stdev_map if os.path.exists(out_outlier_report): outputs['out_outlier_report'] = out_outlier_report diff --git a/nipype/interfaces/fsl/tests/test_auto_AccuracyTester.py b/nipype/interfaces/fsl/tests/test_auto_AccuracyTester.py index de32f63f5f..ffd5b42bd1 100644 --- a/nipype/interfaces/fsl/tests/test_auto_AccuracyTester.py +++ b/nipype/interfaces/fsl/tests/test_auto_AccuracyTester.py @@ -34,11 +34,10 @@ def test_AccuracyTester_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_AccuracyTester_outputs(): - output_map = dict( - output_directory=dict( - argstr='%s', - position=1, - ), ) + output_map = dict(output_directory=dict( + argstr='%s', + position=1, + ), ) outputs = AccuracyTester.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/fsl/tests/test_auto_Cleaner.py b/nipype/interfaces/fsl/tests/test_auto_Cleaner.py index a75df99db5..597dc88d5e 100644 --- a/nipype/interfaces/fsl/tests/test_auto_Cleaner.py +++ b/nipype/interfaces/fsl/tests/test_auto_Cleaner.py @@ -22,14 +22,17 @@ def test_Cleaner_inputs(): ), confound_file=dict( argstr='-x %s', + extensions=None, position=4, ), confound_file_1=dict( argstr='-x %s', + extensions=None, position=5, ), confound_file_2=dict( argstr='-x %s', + extensions=None, position=6, ), environ=dict( diff --git a/nipype/interfaces/fsl/tests/test_auto_Cluster.py b/nipype/interfaces/fsl/tests/test_auto_Cluster.py index 6ed34ab816..19340b9383 100644 --- a/nipype/interfaces/fsl/tests/test_auto_Cluster.py +++ b/nipype/interfaces/fsl/tests/test_auto_Cluster.py @@ -7,7 +7,10 @@ def test_Cluster_inputs(): input_map = dict( args=dict(argstr='%s', ), connectivity=dict(argstr='--connectivity=%d', ), - cope_file=dict(argstr='--cope=%s', ), + cope_file=dict( + argstr='--cope=%s', + extensions=None, + ), dlh=dict(argstr='--dlh=%.10f', ), environ=dict( nohash=True, diff --git a/nipype/interfaces/fsl/tests/test_auto_Eddy.py b/nipype/interfaces/fsl/tests/test_auto_Eddy.py index 4bd6a3e840..3e68a01d6e 100644 --- a/nipype/interfaces/fsl/tests/test_auto_Eddy.py +++ b/nipype/interfaces/fsl/tests/test_auto_Eddy.py @@ -16,18 +16,29 @@ def test_Eddy_inputs(): nohash=True, usedefault=True, ), + estimate_move_by_susceptibility=dict( + argstr='--estimate_move_by_susceptibility', + min_ver='6.0.1', + ), fep=dict(argstr='--fep', ), - field=dict(argstr='--field=%s', ), + field=dict( + argstr='--field=%s', + extensions=None, + ), field_mat=dict( argstr='--field_mat=%s', extensions=None, + requires=['field'], ), flm=dict(argstr='--flm=%s', ), fudge_factor=dict( argstr='--ff=%s', usedefault=True, ), - fwhm=dict(argstr='--fwhm=%s', ), + fwhm=dict( + argstr='--fwhm=%s', + usedefault=True, + ), in_acqp=dict( argstr='--acqp=%s', extensions=None, @@ -67,9 +78,47 @@ def test_Eddy_inputs(): extensions=None, requires=['in_topup_fieldcoef'], ), + initrand=dict( + argstr='--initrand', + min_ver='5.0.10', + ), interp=dict(argstr='--interp=%s', ), is_shelled=dict(argstr='--data_is_shelled', ), + json=dict( + argstr='--json=%s', + min_ver='6.0.1', + xor=['slspec'], + ), + mb=dict( + argstr='--mb=%s', + min_ver='5.0.10', + ), + mb_offs=dict( + argstr='--mb_offs=%s', + min_ver='5.0.10', + requires=['mb'], + ), + mbs_ksp=dict( + argstr='--mbs_ksp=%smm', + min_ver='6.0.1', + requires=['estimate_move_by_susceptibility'], + ), + mbs_lambda=dict( + argstr='--mbs_lambda=%s', + min_ver='6.0.1', + requires=['estimate_move_by_susceptibility'], + ), + mbs_niter=dict( + argstr='--mbs_niter=%s', + min_ver='6.0.1', + requires=['estimate_move_by_susceptibility'], + ), method=dict(argstr='--resamp=%s', ), + mporder=dict( + argstr='--mporder=%s', + min_ver='5.0.11', + requires=['slspec'], + ), niter=dict( argstr='--niter=%s', usedefault=True, @@ -86,17 +135,62 @@ def test_Eddy_inputs(): argstr='--out=%s', usedefault=True, ), + outlier_nstd=dict( + argstr='--ol_nstd', + min_ver='5.0.10', + requires=['repol'], + ), + outlier_nvox=dict( + argstr='--ol_nvox', + min_ver='5.0.10', + requires=['repol'], + ), + outlier_pos=dict( + argstr='--ol_pos', + min_ver='5.0.10', + requires=['repol'], + ), + outlier_sqr=dict( + argstr='--ol_sqr', + min_ver='5.0.10', + requires=['repol'], + ), + outlier_type=dict( + argstr='--ol_type', + min_ver='5.0.10', + requires=['repol'], + ), output_type=dict(), repol=dict(argstr='--repol', ), residuals=dict( argstr='--residuals', min_ver='5.0.10', ), + s2v_interp=dict( + argstr='--s2v_interp=%s', + min_ver='5.0.11', + requires=['slspec'], + ), + s2v_lambda=dict( + agstr='--s2v_lambda', + min_ver='5.0.11', + requires=['slspec'], + ), + s2v_niter=dict( + argstr='--s2v_niter=%s', + min_ver='5.0.11', + requires=['slspec'], + ), session=dict( argstr='--session=%s', extensions=None, ), slm=dict(argstr='--slm=%s', ), + slspec=dict( + argstr='--slspec=%s', + min_ver='5.0.11', + xor=['json'], + ), use_cuda=dict(), ) inputs = Eddy.input_spec() @@ -108,13 +202,19 @@ def test_Eddy_outputs(): output_map = dict( out_cnr_maps=dict(extensions=None, ), out_corrected=dict(extensions=None, ), + out_movement_over_time=dict(extensions=None, ), out_movement_rms=dict(extensions=None, ), + out_outlier_free=dict(extensions=None, ), + out_outlier_map=dict(extensions=None, ), + out_outlier_n_sqr_stdev_map=dict(extensions=None, ), + out_outlier_n_stdev_map=dict(extensions=None, ), out_outlier_report=dict(extensions=None, ), out_parameter=dict(extensions=None, ), out_residuals=dict(extensions=None, ), out_restricted_movement_rms=dict(extensions=None, ), out_rotated_bvecs=dict(extensions=None, ), out_shell_alignment_parameters=dict(extensions=None, ), + out_shell_pe_translation_parameters=dict(extensions=None, ), ) outputs = Eddy.output_spec() diff --git a/nipype/interfaces/fsl/tests/test_auto_FeatureExtractor.py b/nipype/interfaces/fsl/tests/test_auto_FeatureExtractor.py index 3945c40a87..eaeeb34ce8 100644 --- a/nipype/interfaces/fsl/tests/test_auto_FeatureExtractor.py +++ b/nipype/interfaces/fsl/tests/test_auto_FeatureExtractor.py @@ -22,12 +22,11 @@ def test_FeatureExtractor_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_FeatureExtractor_outputs(): - output_map = dict( - mel_ica=dict( - argstr='%s', - copyfile=False, - position=-1, - ), ) + output_map = dict(mel_ica=dict( + argstr='%s', + copyfile=False, + position=-1, + ), ) outputs = FeatureExtractor.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/fsl/tests/test_auto_FindTheBiggest.py b/nipype/interfaces/fsl/tests/test_auto_FindTheBiggest.py index 5c7b717d93..a8262c9be1 100644 --- a/nipype/interfaces/fsl/tests/test_auto_FindTheBiggest.py +++ b/nipype/interfaces/fsl/tests/test_auto_FindTheBiggest.py @@ -30,11 +30,10 @@ def test_FindTheBiggest_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_FindTheBiggest_outputs(): - output_map = dict( - out_file=dict( - argstr='%s', - extensions=None, - ), ) + output_map = dict(out_file=dict( + argstr='%s', + extensions=None, + ), ) outputs = FindTheBiggest.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/fsl/tests/test_auto_ImageStats.py b/nipype/interfaces/fsl/tests/test_auto_ImageStats.py index 0230245f2e..f2dc0af947 100644 --- a/nipype/interfaces/fsl/tests/test_auto_ImageStats.py +++ b/nipype/interfaces/fsl/tests/test_auto_ImageStats.py @@ -14,6 +14,11 @@ def test_ImageStats_inputs(): argstr='%s', extensions=None, mandatory=True, + position=3, + ), + index_mask_file=dict( + argstr='-K %s', + extensions=None, position=2, ), mask_file=dict( @@ -23,7 +28,7 @@ def test_ImageStats_inputs(): op_string=dict( argstr='%s', mandatory=True, - position=3, + position=4, ), output_type=dict(), split_4d=dict( diff --git a/nipype/interfaces/fsl/tests/test_auto_TrainingSetCreator.py b/nipype/interfaces/fsl/tests/test_auto_TrainingSetCreator.py index 18ef078a79..638bcdd156 100644 --- a/nipype/interfaces/fsl/tests/test_auto_TrainingSetCreator.py +++ b/nipype/interfaces/fsl/tests/test_auto_TrainingSetCreator.py @@ -4,24 +4,22 @@ def test_TrainingSetCreator_inputs(): - input_map = dict( - mel_icas_in=dict( - argstr='%s', - copyfile=False, - position=-1, - ), ) + input_map = dict(mel_icas_in=dict( + argstr='%s', + copyfile=False, + position=-1, + ), ) inputs = TrainingSetCreator.input_spec() for key, metadata in list(input_map.items()): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_TrainingSetCreator_outputs(): - output_map = dict( - mel_icas_out=dict( - argstr='%s', - copyfile=False, - position=-1, - ), ) + output_map = dict(mel_icas_out=dict( + argstr='%s', + copyfile=False, + position=-1, + ), ) outputs = TrainingSetCreator.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/fsl/utils.py b/nipype/interfaces/fsl/utils.py index f4ef73c0e9..a572259e2e 100644 --- a/nipype/interfaces/fsl/utils.py +++ b/nipype/interfaces/fsl/utils.py @@ -725,18 +725,25 @@ class ImageStatsInputSpec(FSLCommandInputSpec): exists=True, argstr="%s", mandatory=True, - position=2, + position=3, desc='input file to generate stats of') op_string = traits.Str( argstr="%s", mandatory=True, - position=3, + position=4, desc=("string defining the operation, options are " "applied in order, e.g. -M -l 10 -M will " "report the non-zero mean, apply a threshold " "and then report the new nonzero mean")) mask_file = File( exists=True, argstr="", desc='mask file used for option -k %s') + index_mask_file = File( + exists=True, + argstr="-K %s", + position=2, + desc="generate seperate n submasks from indexMask, " + "for indexvalues 1..n where n is the maximum index " + "value in indexMask, and generate statistics for each submask") class ImageStatsOutputSpec(TraitedSpec): diff --git a/nipype/interfaces/minc/tests/test_auto_Average.py b/nipype/interfaces/minc/tests/test_auto_Average.py index 678ab93a52..6f0e84d144 100644 --- a/nipype/interfaces/minc/tests/test_auto_Average.py +++ b/nipype/interfaces/minc/tests/test_auto_Average.py @@ -29,6 +29,7 @@ def test_Average_inputs(): ), filelist=dict( argstr='-filelist %s', + extensions=None, mandatory=True, xor=('input_files', 'filelist'), ), @@ -126,7 +127,10 @@ def test_Average_inputs(): argstr='-quiet', xor=('verbose', 'quiet'), ), - sdfile=dict(argstr='-sdfile %s', ), + sdfile=dict( + argstr='-sdfile %s', + extensions=None, + ), two=dict(argstr='-2', ), verbose=dict( argstr='-verbose', diff --git a/nipype/interfaces/minc/tests/test_auto_BBox.py b/nipype/interfaces/minc/tests/test_auto_BBox.py index c1b3515cea..7bdf35f03d 100644 --- a/nipype/interfaces/minc/tests/test_auto_BBox.py +++ b/nipype/interfaces/minc/tests/test_auto_BBox.py @@ -25,6 +25,7 @@ def test_BBox_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/minc/tests/test_auto_Beast.py b/nipype/interfaces/minc/tests/test_auto_Beast.py index bc4705db2e..3a44b436b0 100644 --- a/nipype/interfaces/minc/tests/test_auto_Beast.py +++ b/nipype/interfaces/minc/tests/test_auto_Beast.py @@ -18,7 +18,10 @@ def test_Beast_inputs(): argstr='-alpha %s', usedefault=True, ), - configuration_file=dict(argstr='-configuration %s', ), + configuration_file=dict( + argstr='-configuration %s', + extensions=None, + ), environ=dict( nohash=True, usedefault=True, @@ -27,6 +30,7 @@ def test_Beast_inputs(): flip_images=dict(argstr='-flip', ), input_file=dict( argstr='%s', + extensions=None, mandatory=True, position=-2, ), @@ -44,6 +48,7 @@ def test_Beast_inputs(): ), output_file=dict( argstr='%s', + extensions=None, hash_files=False, name_source=['input_file'], name_template='%s_beast_mask.mnc', diff --git a/nipype/interfaces/minc/tests/test_auto_Calc.py b/nipype/interfaces/minc/tests/test_auto_Calc.py index e9df677150..d5fb316e39 100644 --- a/nipype/interfaces/minc/tests/test_auto_Calc.py +++ b/nipype/interfaces/minc/tests/test_auto_Calc.py @@ -26,6 +26,7 @@ def test_Calc_inputs(): eval_width=dict(argstr='-eval_width %s', ), expfile=dict( argstr='-expfile %s', + extensions=None, mandatory=True, xor=('expression', 'expfile'), ), @@ -36,6 +37,7 @@ def test_Calc_inputs(): ), filelist=dict( argstr='-filelist %s', + extensions=None, mandatory=True, xor=('input_files', 'filelist'), ), diff --git a/nipype/interfaces/minc/tests/test_auto_Dump.py b/nipype/interfaces/minc/tests/test_auto_Dump.py index 19c299dac8..fbd33f5a46 100644 --- a/nipype/interfaces/minc/tests/test_auto_Dump.py +++ b/nipype/interfaces/minc/tests/test_auto_Dump.py @@ -36,6 +36,7 @@ def test_Dump_inputs(): netcdf_name=dict(argstr='-n %s', ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/minc/tests/test_auto_Extract.py b/nipype/interfaces/minc/tests/test_auto_Extract.py index 35f6162c7f..fbd0a84729 100644 --- a/nipype/interfaces/minc/tests/test_auto_Extract.py +++ b/nipype/interfaces/minc/tests/test_auto_Extract.py @@ -84,6 +84,7 @@ def test_Extract_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/minc/tests/test_auto_Math.py b/nipype/interfaces/minc/tests/test_auto_Math.py index 6bc142b15d..41d75379d4 100644 --- a/nipype/interfaces/minc/tests/test_auto_Math.py +++ b/nipype/interfaces/minc/tests/test_auto_Math.py @@ -36,6 +36,7 @@ def test_Math_inputs(): exp=dict(argstr='-exp -const2 %s %s', ), filelist=dict( argstr='-filelist %s', + extensions=None, mandatory=True, xor=('input_files', 'filelist'), ), diff --git a/nipype/interfaces/minc/tests/test_auto_Norm.py b/nipype/interfaces/minc/tests/test_auto_Norm.py index 9fb0d3c5ba..cdd4a3db7c 100644 --- a/nipype/interfaces/minc/tests/test_auto_Norm.py +++ b/nipype/interfaces/minc/tests/test_auto_Norm.py @@ -26,7 +26,10 @@ def test_Norm_inputs(): position=-2, ), lower=dict(argstr='-lower %s', ), - mask=dict(argstr='-mask %s', ), + mask=dict( + argstr='-mask %s', + extensions=None, + ), out_ceil=dict(argstr='-out_ceil %s', ), out_floor=dict(argstr='-out_floor %s', ), output_file=dict( @@ -40,6 +43,7 @@ def test_Norm_inputs(): ), output_threshold_mask=dict( argstr='-threshold_mask %s', + extensions=None, hash_files=False, name_source=['input_file'], name_template='%s_norm_threshold_mask.mnc', diff --git a/nipype/interfaces/minc/tests/test_auto_Resample.py b/nipype/interfaces/minc/tests/test_auto_Resample.py index 8d4b24ff41..da512d9f62 100644 --- a/nipype/interfaces/minc/tests/test_auto_Resample.py +++ b/nipype/interfaces/minc/tests/test_auto_Resample.py @@ -94,7 +94,10 @@ def test_Resample_inputs(): argstr='-keep_real_range', xor=('keep_real_range', 'nokeep_real_range'), ), - like=dict(argstr='-like %s', ), + like=dict( + argstr='-like %s', + extensions=None, + ), nearest_neighbour_interpolation=dict( argstr='-nearest_neighbour', xor=('trilinear_interpolation', 'tricubic_interpolation', @@ -157,7 +160,10 @@ def test_Resample_inputs(): xor=('nelements', 'nelements_x_y_or_z'), ), talairach=dict(argstr='-talairach', ), - transformation=dict(argstr='-transformation %s', ), + transformation=dict( + argstr='-transformation %s', + extensions=None, + ), transverse_slices=dict( argstr='-transverse', xor=('transverse', 'sagittal', 'coronal'), diff --git a/nipype/interfaces/minc/tests/test_auto_Reshape.py b/nipype/interfaces/minc/tests/test_auto_Reshape.py index 669425da95..d80f9a377b 100644 --- a/nipype/interfaces/minc/tests/test_auto_Reshape.py +++ b/nipype/interfaces/minc/tests/test_auto_Reshape.py @@ -16,6 +16,7 @@ def test_Reshape_inputs(): ), input_file=dict( argstr='%s', + extensions=None, mandatory=True, position=-2, ), diff --git a/nipype/interfaces/minc/tests/test_auto_ToRaw.py b/nipype/interfaces/minc/tests/test_auto_ToRaw.py index aeda687c97..42ba72f145 100644 --- a/nipype/interfaces/minc/tests/test_auto_ToRaw.py +++ b/nipype/interfaces/minc/tests/test_auto_ToRaw.py @@ -26,6 +26,7 @@ def test_ToRaw_inputs(): ), out_file=dict( argstr='> %s', + extensions=None, genfile=True, position=-1, ), diff --git a/nipype/interfaces/minc/tests/test_auto_VolSymm.py b/nipype/interfaces/minc/tests/test_auto_VolSymm.py index b710d59543..ae3332b7f2 100644 --- a/nipype/interfaces/minc/tests/test_auto_VolSymm.py +++ b/nipype/interfaces/minc/tests/test_auto_VolSymm.py @@ -22,6 +22,7 @@ def test_VolSymm_inputs(): fit_nonlinear=dict(argstr='-nonlinear', ), input_file=dict( argstr='%s', + extensions=None, mandatory=True, position=-3, ), @@ -38,6 +39,7 @@ def test_VolSymm_inputs(): ), trans_file=dict( argstr='%s', + extensions=None, genfile=True, hash_files=False, keep_extension=False, diff --git a/nipype/interfaces/minc/tests/test_auto_XfmInvert.py b/nipype/interfaces/minc/tests/test_auto_XfmInvert.py index 9e242300da..69c455f875 100644 --- a/nipype/interfaces/minc/tests/test_auto_XfmInvert.py +++ b/nipype/interfaces/minc/tests/test_auto_XfmInvert.py @@ -16,6 +16,7 @@ def test_XfmInvert_inputs(): ), input_file=dict( argstr='%s', + extensions=None, mandatory=True, position=-2, ), diff --git a/nipype/interfaces/mne/base.py b/nipype/interfaces/mne/base.py index 7f53071372..b6c8320e7a 100644 --- a/nipype/interfaces/mne/base.py +++ b/nipype/interfaces/mne/base.py @@ -89,12 +89,12 @@ class WatershedBEM(FSCommand): >>> bem.inputs.subject_id = 'subj1' >>> bem.inputs.subjects_dir = '.' >>> bem.cmdline - 'mne_watershed_bem --overwrite --subject subj1 --volume T1' + 'mne watershed_bem --overwrite --subject subj1 --volume T1' >>> bem.run() # doctest: +SKIP """ - _cmd = 'mne_watershed_bem' + _cmd = 'mne watershed_bem' input_spec = WatershedBEMInputSpec output_spec = WatershedBEMOutputSpec _additional_metadata = ['loc', 'altkey'] diff --git a/nipype/interfaces/mrtrix3/__init__.py b/nipype/interfaces/mrtrix3/__init__.py index c9c131dde3..d28d8b4012 100644 --- a/nipype/interfaces/mrtrix3/__init__.py +++ b/nipype/interfaces/mrtrix3/__init__.py @@ -4,7 +4,7 @@ # -*- coding: utf-8 -*- from .utils import (Mesh2PVE, Generate5tt, BrainMask, TensorMetrics, - ComputeTDI, TCK2VTK, MRMath, MRConvert, DWIExtract) + ComputeTDI, TCK2VTK, MRMath, MRConvert, MRResize, DWIExtract) from .preprocess import (ResponseSD, ACTPrepareFSL, ReplaceFSwithFIRST, DWIDenoise, MRDeGibbs, DWIBiasCorrect) from .tracking import Tractography diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py b/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py index 90c5272ed0..5ee1e8cb00 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_BrainMask.py @@ -14,8 +14,12 @@ def test_BrainMask_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_DWIExtract.py b/nipype/interfaces/mrtrix3/tests/test_auto_DWIExtract.py index 7658201223..59617b30ab 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_DWIExtract.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_DWIExtract.py @@ -15,8 +15,12 @@ def test_DWIExtract_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py b/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py index 84404fdde6..8f8142746a 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_FitTensor.py @@ -14,8 +14,12 @@ def test_FitTensor_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py b/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py index 92594da593..f7032cb624 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_Generate5tt.py @@ -19,8 +19,12 @@ def test_Generate5tt_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_MRConvert.py b/nipype/interfaces/mrtrix3/tests/test_auto_MRConvert.py index 9271d07517..f11b615cc8 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_MRConvert.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_MRConvert.py @@ -22,8 +22,12 @@ def test_MRConvert_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_MRMath.py b/nipype/interfaces/mrtrix3/tests/test_auto_MRMath.py index ae494bb932..fe934c45b1 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_MRMath.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_MRMath.py @@ -15,8 +15,12 @@ def test_MRMath_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_MRResize.py b/nipype/interfaces/mrtrix3/tests/test_auto_MRResize.py new file mode 100644 index 0000000000..83c77ccc66 --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_MRResize.py @@ -0,0 +1,77 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..utils import MRResize + + +def test_MRResize_inputs(): + input_map = dict( + args=dict(argstr='%s', ), + bval_scale=dict(argstr='-bvalue_scaling %s', ), + environ=dict( + nohash=True, + usedefault=True, + ), + grad_file=dict( + argstr='-grad %s', + extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], + ), + image_size=dict( + argstr='-size %d,%d,%d', + mandatory=True, + xor=['voxel_size', 'scale_factor'], + ), + in_bval=dict(extensions=None, ), + in_bvec=dict( + argstr='-fslgrad %s %s', + extensions=None, + ), + in_file=dict( + argstr='%s', + extensions=None, + mandatory=True, + position=-2, + ), + interp=dict( + argstr='-interp %s', + usedefault=True, + ), + nthreads=dict( + argstr='-nthreads %d', + nohash=True, + ), + out_file=dict( + argstr='%s', + extensions=None, + keep_extension=True, + name_source=['in_file'], + name_template='%s_resized', + position=-1, + ), + scale_factor=dict( + argstr='-scale %d,%d,%d', + mandatory=True, + xor=['image_size', 'voxel_size'], + ), + voxel_size=dict( + argstr='-voxel %d,%d,%d', + mandatory=True, + xor=['image_size', 'scale_factor'], + ), + ) + inputs = MRResize.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value +def test_MRResize_outputs(): + output_map = dict(out_file=dict(extensions=None, ), ) + outputs = MRResize.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py b/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py index dd326bad5b..9415cae211 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_ResponseSD.py @@ -29,8 +29,12 @@ def test_ResponseSD_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py b/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py index 39f239b81d..cf685a50d8 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_Tractography.py @@ -28,8 +28,12 @@ def test_Tractography_inputs(): grad_file=dict( argstr='-grad %s', extensions=None, + xor=['grad_fsl'], + ), + grad_fsl=dict( + argstr='-fslgrad %s %s', + xor=['grad_file'], ), - grad_fsl=dict(argstr='-fslgrad %s %s', ), in_bval=dict(extensions=None, ), in_bvec=dict( argstr='-fslgrad %s %s', diff --git a/nipype/interfaces/mrtrix3/utils.py b/nipype/interfaces/mrtrix3/utils.py index a667c716f4..b66eff77aa 100644 --- a/nipype/interfaces/mrtrix3/utils.py +++ b/nipype/interfaces/mrtrix3/utils.py @@ -677,3 +677,87 @@ def _list_outputs(self): outputs = self.output_spec().get() outputs['out_file'] = op.abspath(self.inputs.out_file) return outputs + + +class MRResizeInputSpec(MRTrix3BaseInputSpec): + in_file = File( + exists=True, + argstr='%s', + position=-2, + mandatory=True, + desc='input DWI image' + ) + image_size = traits.Tuple( + (traits.Int, traits.Int, traits.Int), + argstr='-size %d,%d,%d', + mandatory=True, + desc='define the new image size for the output image. This should be ' + 'specified as a comma-separated list.', + xor=['voxel_size', 'scale_factor'], + ) + voxel_size = traits.Tuple( + (traits.Float, traits.Float, traits.Float), + argstr='-voxel %d,%d,%d', + mandatory=True, + desc='define the new voxel size for the output image. This can be ' + 'specified either as a single value to be used for all ' + 'dimensions, or as a comma-separated list of the size for each ' + 'voxel dimension.', + xor=['image_size', 'scale_factor'], + ) + scale_factor = traits.Tuple( + (traits.Float, traits.Float, traits.Float), + argstr='-scale %d,%d,%d', + mandatory=True, + desc='scale the image resolution by the supplied factor. This can be ' + 'specified either as a single value to be used for all ' + 'dimensions, or as a comma-separated list of scale factors for ' + 'each dimension.', + xor=['image_size', 'voxel_size'], + ) + interp = traits.Enum( + 'cubic', + 'nearest', + 'linear', + 'sinc', + usedefault=True, + argstr='-interp %s', + desc='set the interpolation method to use when resizing (choices: ' + 'nearest, linear, cubic, sinc. Default: cubic).', + ) + out_file = File( + argstr='%s', + name_template='%s_resized', + name_source=['in_file'], + keep_extension=True, + position=-1, + desc='the output resized DWI image', + ) + + +class MRResizeOutputSpec(TraitedSpec): + out_file = File(desc='the output resized DWI image', exists=True) + + +class MRResize(MRTrix3Base): + """ + Resize an image by defining the new image resolution, voxel size or a + scale factor. If the image is 4D, then only the first 3 dimensions can be + resized. Also, if the image is down-sampled, the appropriate smoothing is + automatically applied using Gaussian smoothing. + For more information, see + + Example + ------- + >>> import nipype.interfaces.mrtrix3 as mrt + >>> resize = mrt.MRResize() + >>> resize.inputs.in_file = 'dwi.mif' + >>> resize.inputs.voxel_size = (1, 1, 1) + >>> resize.cmdline # doctest: +ELLIPSIS + 'mrresize -interp cubic -voxel 1,1,1 dwi.mif dwi_resized.mif' + >>> resize.run() # doctest: +SKIP + """ + + _cmd = 'mrresize' + input_spec = MRResizeInputSpec + output_spec = MRResizeOutputSpec diff --git a/nipype/interfaces/niftyfit/tests/test_auto_DwiTool.py b/nipype/interfaces/niftyfit/tests/test_auto_DwiTool.py index 20995e806e..2a58b39d57 100644 --- a/nipype/interfaces/niftyfit/tests/test_auto_DwiTool.py +++ b/nipype/interfaces/niftyfit/tests/test_auto_DwiTool.py @@ -8,6 +8,7 @@ def test_DwiTool_inputs(): args=dict(argstr='%s', ), b0_file=dict( argstr='-b0 %s', + extensions=None, position=4, ), ball_flag=dict( @@ -28,11 +29,13 @@ def test_DwiTool_inputs(): ), bval_file=dict( argstr='-bval %s', + extensions=None, mandatory=True, position=2, ), bvec_file=dict( argstr='-bvec %s', + extensions=None, position=3, ), diso_val=dict(argstr='-diso %f', ), @@ -59,6 +62,7 @@ def test_DwiTool_inputs(): ), famap_file=dict( argstr='-famap %s', + extensions=None, name_source=['source_file'], name_template='%s_famap.nii.gz', ), @@ -72,20 +76,24 @@ def test_DwiTool_inputs(): ), logdti_file=dict( argstr='-logdti2 %s', + extensions=None, name_source=['source_file'], name_template='%s_logdti2.nii.gz', ), mask_file=dict( argstr='-mask %s', + extensions=None, position=5, ), mcmap_file=dict( argstr='-mcmap %s', + extensions=None, name_source=['source_file'], name_template='%s_mcmap.nii.gz', ), mdmap_file=dict( argstr='-mdmap %s', + extensions=None, name_source=['source_file'], name_template='%s_mdmap.nii.gz', ), @@ -115,22 +123,26 @@ def test_DwiTool_inputs(): ), rgbmap_file=dict( argstr='-rgbmap %s', + extensions=None, name_source=['source_file'], name_template='%s_rgbmap.nii.gz', ), source_file=dict( argstr='-source %s', + extensions=None, mandatory=True, position=1, ), syn_file=dict( argstr='-syn %s', + extensions=None, name_source=['source_file'], name_template='%s_syn.nii.gz', requires=['bvec_file', 'b0_file'], ), v1map_file=dict( argstr='-v1map %s', + extensions=None, name_source=['source_file'], name_template='%s_v1map.nii.gz', ), @@ -142,13 +154,13 @@ def test_DwiTool_inputs(): assert getattr(inputs.traits()[key], metakey) == value def test_DwiTool_outputs(): output_map = dict( - famap_file=dict(), - logdti_file=dict(), - mcmap_file=dict(), - mdmap_file=dict(), - rgbmap_file=dict(), - syn_file=dict(), - v1map_file=dict(), + famap_file=dict(extensions=None, ), + logdti_file=dict(extensions=None, ), + mcmap_file=dict(extensions=None, ), + mdmap_file=dict(extensions=None, ), + rgbmap_file=dict(extensions=None, ), + syn_file=dict(extensions=None, ), + v1map_file=dict(extensions=None, ), ) outputs = DwiTool.output_spec() diff --git a/nipype/interfaces/niftyfit/tests/test_auto_FitAsl.py b/nipype/interfaces/niftyfit/tests/test_auto_FitAsl.py index b2e1bef961..94a489a4ad 100644 --- a/nipype/interfaces/niftyfit/tests/test_auto_FitAsl.py +++ b/nipype/interfaces/niftyfit/tests/test_auto_FitAsl.py @@ -8,6 +8,7 @@ def test_FitAsl_inputs(): args=dict(argstr='%s', ), cbf_file=dict( argstr='-cbf %s', + extensions=None, name_source=['source_file'], name_template='%s_cbf.nii.gz', ), @@ -20,19 +21,33 @@ def test_FitAsl_inputs(): ), error_file=dict( argstr='-error %s', + extensions=None, name_source=['source_file'], name_template='%s_error.nii.gz', ), gm_plasma=dict(argstr='-gmL %f', ), gm_t1=dict(argstr='-gmT1 %f', ), gm_ttt=dict(argstr='-gmTTT %f', ), - ir_output=dict(argstr='-IRoutput %s', ), - ir_volume=dict(argstr='-IRvolume %s', ), + ir_output=dict( + argstr='-IRoutput %s', + extensions=None, + ), + ir_volume=dict( + argstr='-IRvolume %s', + extensions=None, + ), ldd=dict(argstr='-LDD %f', ), - m0map=dict(argstr='-m0map %s', ), - m0mape=dict(argstr='-m0mape %s', ), + m0map=dict( + argstr='-m0map %s', + extensions=None, + ), + m0mape=dict( + argstr='-m0mape %s', + extensions=None, + ), mask=dict( argstr='-mask %s', + extensions=None, position=2, ), mul=dict(argstr='-mul %f', ), @@ -46,21 +61,29 @@ def test_FitAsl_inputs(): pv2=dict(argstr='-pv2 %d', ), pv3=dict(argstr='-pv3 %d %d %d', ), pv_threshold=dict(argstr='-pvthreshold', ), - seg=dict(argstr='-seg %s', ), + seg=dict( + argstr='-seg %s', + extensions=None, + ), segstyle=dict(argstr='-segstyle', ), sig=dict(argstr='-sig', ), source_file=dict( argstr='-source %s', + extensions=None, mandatory=True, position=1, ), syn_file=dict( argstr='-syn %s', + extensions=None, name_source=['source_file'], name_template='%s_syn.nii.gz', ), t1_art_cmp=dict(argstr='-T1a %f', ), - t1map=dict(argstr='-t1map %s', ), + t1map=dict( + argstr='-t1map %s', + extensions=None, + ), t_inv1=dict(argstr='-Tinv1 %f', ), t_inv2=dict(argstr='-Tinv2 %f', ), wm_plasma=dict(argstr='-wmL %f', ), @@ -74,9 +97,9 @@ def test_FitAsl_inputs(): assert getattr(inputs.traits()[key], metakey) == value def test_FitAsl_outputs(): output_map = dict( - cbf_file=dict(), - error_file=dict(), - syn_file=dict(), + cbf_file=dict(extensions=None, ), + error_file=dict(extensions=None, ), + syn_file=dict(extensions=None, ), ) outputs = FitAsl.output_spec() diff --git a/nipype/interfaces/niftyfit/tests/test_auto_FitDwi.py b/nipype/interfaces/niftyfit/tests/test_auto_FitDwi.py index 700d9a31c4..2086d12a2b 100644 --- a/nipype/interfaces/niftyfit/tests/test_auto_FitDwi.py +++ b/nipype/interfaces/niftyfit/tests/test_auto_FitDwi.py @@ -25,15 +25,20 @@ def test_FitDwi_inputs(): ), bval_file=dict( argstr='-bval %s', + extensions=None, mandatory=True, position=2, ), bvec_file=dict( argstr='-bvec %s', + extensions=None, mandatory=True, position=3, ), - cov_file=dict(argstr='-cov %s', ), + cov_file=dict( + argstr='-cov %s', + extensions=None, + ), csf_t2_val=dict(argstr='-csfT2 %f', ), diso_val=dict(argstr='-diso %f', ), dpr_val=dict(argstr='-dpr %f', ), @@ -51,11 +56,13 @@ def test_FitDwi_inputs(): ), error_file=dict( argstr='-error %s', + extensions=None, name_source=['source_file'], name_template='%s_error.nii.gz', ), famap_file=dict( argstr='-famap %s', + extensions=None, name_source=['source_file'], name_template='%s_famap.nii.gz', ), @@ -75,13 +82,17 @@ def test_FitDwi_inputs(): argstr='-lm %f %f', requires=['gn_flag'], ), - mask_file=dict(argstr='-mask %s', ), + mask_file=dict( + argstr='-mask %s', + extensions=None, + ), maxit_val=dict( argstr='-maxit %d', requires=['gn_flag'], ), mcmap_file=dict( argstr='-mcmap %s', + extensions=None, name_source=['source_file'], name_template='%s_mcmap.nii.gz', requires=['nodv_flag'], @@ -89,12 +100,14 @@ def test_FitDwi_inputs(): mcmaxit=dict(argstr='-mcmaxit %d', ), mcout=dict( argstr='-mcout %s', + extensions=None, name_source=['source_file'], name_template='%s_mcout.txt', ), mcsamples=dict(argstr='-mcsamples %d', ), mdmap_file=dict( argstr='-mdmap %s', + extensions=None, name_source=['source_file'], name_template='%s_mdmap.nii.gz', ), @@ -116,6 +129,7 @@ def test_FitDwi_inputs(): ), nodiff_file=dict( argstr='-nodiff %s', + extensions=None, name_source=['source_file'], name_template='%s_no_diff.nii.gz', ), @@ -128,14 +142,19 @@ def test_FitDwi_inputs(): ], ), perf_thr=dict(argstr='-perfthreshold %f', ), - prior_file=dict(argstr='-prior %s', ), + prior_file=dict( + argstr='-prior %s', + extensions=None, + ), res_file=dict( argstr='-res %s', + extensions=None, name_source=['source_file'], name_template='%s_resmap.nii.gz', ), rgbmap_file=dict( argstr='-rgbmap %s', + extensions=None, name_source=['source_file'], name_template='%s_rgbmap.nii.gz', requires=['dti_flag'], @@ -144,38 +163,45 @@ def test_FitDwi_inputs(): slice_no=dict(argstr='-slice %d', ), source_file=dict( argstr='-source %s', + extensions=None, mandatory=True, position=1, ), swls_val=dict(argstr='-swls %f', ), syn_file=dict( argstr='-syn %s', + extensions=None, name_source=['source_file'], name_template='%s_syn.nii.gz', ), te_file=dict( argstr='-TE %s', + extensions=None, xor=['te_file'], ), te_value=dict( argstr='-TE %s', + extensions=None, xor=['te_file'], ), ten_type=dict(usedefault=True, ), tenmap2_file=dict( argstr='-tenmap2 %s', + extensions=None, name_source=['source_file'], name_template='%s_tenmap2.nii.gz', requires=['dti_flag'], ), tenmap_file=dict( argstr='-tenmap %s', + extensions=None, name_source=['source_file'], name_template='%s_tenmap.nii.gz', requires=['dti_flag'], ), v1map_file=dict( argstr='-v1map %s', + extensions=None, name_source=['source_file'], name_template='%s_v1map.nii.gz', ), @@ -194,18 +220,18 @@ def test_FitDwi_inputs(): assert getattr(inputs.traits()[key], metakey) == value def test_FitDwi_outputs(): output_map = dict( - error_file=dict(), - famap_file=dict(), - mcmap_file=dict(), - mcout=dict(), - mdmap_file=dict(), - nodiff_file=dict(), - res_file=dict(), - rgbmap_file=dict(), - syn_file=dict(), - tenmap2_file=dict(), - tenmap_file=dict(), - v1map_file=dict(), + error_file=dict(extensions=None, ), + famap_file=dict(extensions=None, ), + mcmap_file=dict(extensions=None, ), + mcout=dict(extensions=None, ), + mdmap_file=dict(extensions=None, ), + nodiff_file=dict(extensions=None, ), + res_file=dict(extensions=None, ), + rgbmap_file=dict(extensions=None, ), + syn_file=dict(extensions=None, ), + tenmap2_file=dict(extensions=None, ), + tenmap_file=dict(extensions=None, ), + v1map_file=dict(extensions=None, ), ) outputs = FitDwi.output_spec() diff --git a/nipype/interfaces/niftyfit/tests/test_auto_FitQt1.py b/nipype/interfaces/niftyfit/tests/test_auto_FitQt1.py index 392654fd5c..b184e448cd 100644 --- a/nipype/interfaces/niftyfit/tests/test_auto_FitQt1.py +++ b/nipype/interfaces/niftyfit/tests/test_auto_FitQt1.py @@ -7,7 +7,10 @@ def test_FitQt1_inputs(): input_map = dict( acceptance=dict(argstr='-acceptance %f', ), args=dict(argstr='%s', ), - b1map=dict(argstr='-b1map %s', ), + b1map=dict( + argstr='-b1map %s', + extensions=None, + ), comp_file=dict( argstr='-comp %s', extensions=None, @@ -28,7 +31,10 @@ def test_FitQt1_inputs(): argstr='-flips %s', sep=' ', ), - flips_list=dict(argstr='-fliplist %s', ), + flips_list=dict( + argstr='-fliplist %s', + extensions=None, + ), gn_flag=dict( argstr='-gn', position=8, @@ -63,7 +69,10 @@ def test_FitQt1_inputs(): name_template='%s_mcmap.nii.gz', ), mcmaxit=dict(argstr='-mcmaxit %d', ), - mcout=dict(argstr='-mcout %s', ), + mcout=dict( + argstr='-mcout %s', + extensions=None, + ), mcsamples=dict(argstr='-mcsamples %d', ), nb_comp=dict( argstr='-nc %d', @@ -101,7 +110,10 @@ def test_FitQt1_inputs(): name_source=['source_file'], name_template='%s_syn.nii.gz', ), - t1_list=dict(argstr='-T1list %s', ), + t1_list=dict( + argstr='-T1list %s', + extensions=None, + ), t1map_file=dict( argstr='-t1map %s', extensions=None, @@ -119,7 +131,10 @@ def test_FitQt1_inputs(): position=14, sep=' ', ), - tis_list=dict(argstr='-TIlist %s', ), + tis_list=dict( + argstr='-TIlist %s', + extensions=None, + ), tr_value=dict( argstr='-TR %f', position=5, diff --git a/nipype/interfaces/nipy/tests/test_auto_EstimateContrast.py b/nipype/interfaces/nipy/tests/test_auto_EstimateContrast.py index 3fe17160db..9a9b5c421c 100644 --- a/nipype/interfaces/nipy/tests/test_auto_EstimateContrast.py +++ b/nipype/interfaces/nipy/tests/test_auto_EstimateContrast.py @@ -13,7 +13,7 @@ def test_EstimateContrast_inputs(): constants=dict(mandatory=True, ), contrasts=dict(mandatory=True, ), dof=dict(mandatory=True, ), - mask=dict(), + mask=dict(extensions=None, ), nvbeta=dict(mandatory=True, ), reg_names=dict(mandatory=True, ), s2=dict( diff --git a/nipype/interfaces/nipy/tests/test_auto_FitGLM.py b/nipype/interfaces/nipy/tests/test_auto_FitGLM.py index a700c18d43..71ca221efc 100644 --- a/nipype/interfaces/nipy/tests/test_auto_FitGLM.py +++ b/nipype/interfaces/nipy/tests/test_auto_FitGLM.py @@ -8,7 +8,7 @@ def test_FitGLM_inputs(): TR=dict(mandatory=True, ), drift_model=dict(usedefault=True, ), hrf_model=dict(usedefault=True, ), - mask=dict(), + mask=dict(extensions=None, ), method=dict(usedefault=True, ), model=dict(usedefault=True, ), normalize_design_matrix=dict(usedefault=True, ), @@ -30,7 +30,7 @@ def test_FitGLM_outputs(): dof=dict(), nvbeta=dict(), reg_names=dict(), - residuals=dict(), + residuals=dict(extensions=None, ), s2=dict(extensions=None, ), ) outputs = FitGLM.output_spec() diff --git a/nipype/interfaces/petpvc.py b/nipype/interfaces/petpvc.py index c73b408bf3..63a0a8ed83 100644 --- a/nipype/interfaces/petpvc.py +++ b/nipype/interfaces/petpvc.py @@ -56,7 +56,7 @@ class PETPVCInputSpec(CommandLineInputSpec): argstr="-a %.4f") stop_crit = traits.Float( desc="Stopping criterion", default_value=0.01, usedefault=True, - argstr="-a %.4f") + argstr="-s %.4f") class PETPVCOutputSpec(TraitedSpec): diff --git a/nipype/interfaces/semtools/filtering/tests/test_auto_UnbiasedNonLocalMeans.py b/nipype/interfaces/semtools/filtering/tests/test_auto_UnbiasedNonLocalMeans.py index 866af46740..2eaeb1acef 100644 --- a/nipype/interfaces/semtools/filtering/tests/test_auto_UnbiasedNonLocalMeans.py +++ b/nipype/interfaces/semtools/filtering/tests/test_auto_UnbiasedNonLocalMeans.py @@ -38,11 +38,10 @@ def test_UnbiasedNonLocalMeans_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_UnbiasedNonLocalMeans_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = UnbiasedNonLocalMeans.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIexport.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIexport.py index 1ca79a6e96..33e52ed707 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIexport.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIexport.py @@ -27,11 +27,10 @@ def test_DTIexport_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DTIexport_outputs(): - output_map = dict( - outputFile=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputFile=dict( + extensions=None, + position=-1, + ), ) outputs = DTIexport.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIimport.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIimport.py index 58ae495f3f..ddb07c9428 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIimport.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_DTIimport.py @@ -28,11 +28,10 @@ def test_DTIimport_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DTIimport_outputs(): - output_map = dict( - outputTensor=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputTensor=dict( + extensions=None, + position=-1, + ), ) outputs = DTIimport.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIJointRicianLMMSEFilter.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIJointRicianLMMSEFilter.py index f8000c49b1..aa0b6f97b5 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIJointRicianLMMSEFilter.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIJointRicianLMMSEFilter.py @@ -37,11 +37,10 @@ def test_DWIJointRicianLMMSEFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DWIJointRicianLMMSEFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = DWIJointRicianLMMSEFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIRicianLMMSEFilter.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIRicianLMMSEFilter.py index 29b5e0b7e1..69509fcf28 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIRicianLMMSEFilter.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_DWIRicianLMMSEFilter.py @@ -43,11 +43,10 @@ def test_DWIRicianLMMSEFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DWIRicianLMMSEFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = DWIRicianLMMSEFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_DiffusionTensorScalarMeasurements.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_DiffusionTensorScalarMeasurements.py index 5dcdbd7e2e..060c47ecc2 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_DiffusionTensorScalarMeasurements.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_DiffusionTensorScalarMeasurements.py @@ -28,11 +28,10 @@ def test_DiffusionTensorScalarMeasurements_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DiffusionTensorScalarMeasurements_outputs(): - output_map = dict( - outputScalar=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputScalar=dict( + extensions=None, + position=-1, + ), ) outputs = DiffusionTensorScalarMeasurements.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/diffusion/tests/test_auto_ResampleDTIVolume.py b/nipype/interfaces/slicer/diffusion/tests/test_auto_ResampleDTIVolume.py index bd35268bdb..9cfcdb14fb 100644 --- a/nipype/interfaces/slicer/diffusion/tests/test_auto_ResampleDTIVolume.py +++ b/nipype/interfaces/slicer/diffusion/tests/test_auto_ResampleDTIVolume.py @@ -73,11 +73,10 @@ def test_ResampleDTIVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ResampleDTIVolume_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = ResampleDTIVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_AddScalarVolumes.py b/nipype/interfaces/slicer/filtering/tests/test_auto_AddScalarVolumes.py index d2b17c562a..42a7b17a19 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_AddScalarVolumes.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_AddScalarVolumes.py @@ -33,11 +33,10 @@ def test_AddScalarVolumes_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_AddScalarVolumes_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = AddScalarVolumes.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_CastScalarVolume.py b/nipype/interfaces/slicer/filtering/tests/test_auto_CastScalarVolume.py index bbcb2f077c..0c05002ff8 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_CastScalarVolume.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_CastScalarVolume.py @@ -28,11 +28,10 @@ def test_CastScalarVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_CastScalarVolume_outputs(): - output_map = dict( - OutputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = CastScalarVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_CheckerBoardFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_CheckerBoardFilter.py index 24f5b74307..b602012d0c 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_CheckerBoardFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_CheckerBoardFilter.py @@ -36,11 +36,10 @@ def test_CheckerBoardFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_CheckerBoardFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = CheckerBoardFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_CurvatureAnisotropicDiffusion.py b/nipype/interfaces/slicer/filtering/tests/test_auto_CurvatureAnisotropicDiffusion.py index 0240ad676a..7389aa0cee 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_CurvatureAnisotropicDiffusion.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_CurvatureAnisotropicDiffusion.py @@ -30,11 +30,10 @@ def test_CurvatureAnisotropicDiffusion_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_CurvatureAnisotropicDiffusion_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = CurvatureAnisotropicDiffusion.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_ExtractSkeleton.py b/nipype/interfaces/slicer/filtering/tests/test_auto_ExtractSkeleton.py index c47382aef5..d6f93cb41d 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_ExtractSkeleton.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_ExtractSkeleton.py @@ -31,11 +31,10 @@ def test_ExtractSkeleton_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ExtractSkeleton_outputs(): - output_map = dict( - OutputImageFileName=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputImageFileName=dict( + extensions=None, + position=-1, + ), ) outputs = ExtractSkeleton.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_GaussianBlurImageFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_GaussianBlurImageFilter.py index 2bdb73c4d5..9511f9ce1d 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_GaussianBlurImageFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_GaussianBlurImageFilter.py @@ -28,11 +28,10 @@ def test_GaussianBlurImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_GaussianBlurImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = GaussianBlurImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_GradientAnisotropicDiffusion.py b/nipype/interfaces/slicer/filtering/tests/test_auto_GradientAnisotropicDiffusion.py index 6d3e40c8de..02c9d7fb20 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_GradientAnisotropicDiffusion.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_GradientAnisotropicDiffusion.py @@ -30,11 +30,10 @@ def test_GradientAnisotropicDiffusion_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_GradientAnisotropicDiffusion_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = GradientAnisotropicDiffusion.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleFillHoleImageFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleFillHoleImageFilter.py index f1ff2c3809..45b2b4b8dc 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleFillHoleImageFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleFillHoleImageFilter.py @@ -27,11 +27,10 @@ def test_GrayscaleFillHoleImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_GrayscaleFillHoleImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = GrayscaleFillHoleImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleGrindPeakImageFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleGrindPeakImageFilter.py index 6aee86282a..77536e147d 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleGrindPeakImageFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_GrayscaleGrindPeakImageFilter.py @@ -27,11 +27,10 @@ def test_GrayscaleGrindPeakImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_GrayscaleGrindPeakImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = GrayscaleGrindPeakImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_HistogramMatching.py b/nipype/interfaces/slicer/filtering/tests/test_auto_HistogramMatching.py index c839c50abf..9541702731 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_HistogramMatching.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_HistogramMatching.py @@ -35,11 +35,10 @@ def test_HistogramMatching_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_HistogramMatching_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = HistogramMatching.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_ImageLabelCombine.py b/nipype/interfaces/slicer/filtering/tests/test_auto_ImageLabelCombine.py index 7fd2c31db3..c3373f80ec 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_ImageLabelCombine.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_ImageLabelCombine.py @@ -33,11 +33,10 @@ def test_ImageLabelCombine_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ImageLabelCombine_outputs(): - output_map = dict( - OutputLabelMap=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputLabelMap=dict( + extensions=None, + position=-1, + ), ) outputs = ImageLabelCombine.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_MaskScalarVolume.py b/nipype/interfaces/slicer/filtering/tests/test_auto_MaskScalarVolume.py index 56d68199af..11999f2001 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_MaskScalarVolume.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_MaskScalarVolume.py @@ -34,11 +34,10 @@ def test_MaskScalarVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_MaskScalarVolume_outputs(): - output_map = dict( - OutputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = MaskScalarVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_MedianImageFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_MedianImageFilter.py index c0bf97e152..4c890aa30f 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_MedianImageFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_MedianImageFilter.py @@ -31,11 +31,10 @@ def test_MedianImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_MedianImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = MedianImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_MultiplyScalarVolumes.py b/nipype/interfaces/slicer/filtering/tests/test_auto_MultiplyScalarVolumes.py index cc39d5b7b1..99772b41db 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_MultiplyScalarVolumes.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_MultiplyScalarVolumes.py @@ -33,11 +33,10 @@ def test_MultiplyScalarVolumes_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_MultiplyScalarVolumes_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = MultiplyScalarVolumes.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_ResampleScalarVectorDWIVolume.py b/nipype/interfaces/slicer/filtering/tests/test_auto_ResampleScalarVectorDWIVolume.py index 12d7af77c4..28a9876943 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_ResampleScalarVectorDWIVolume.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_ResampleScalarVectorDWIVolume.py @@ -71,11 +71,10 @@ def test_ResampleScalarVectorDWIVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ResampleScalarVectorDWIVolume_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = ResampleScalarVectorDWIVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_SubtractScalarVolumes.py b/nipype/interfaces/slicer/filtering/tests/test_auto_SubtractScalarVolumes.py index 106cd843a4..62bf214bf4 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_SubtractScalarVolumes.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_SubtractScalarVolumes.py @@ -33,11 +33,10 @@ def test_SubtractScalarVolumes_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_SubtractScalarVolumes_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = SubtractScalarVolumes.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_ThresholdScalarVolume.py b/nipype/interfaces/slicer/filtering/tests/test_auto_ThresholdScalarVolume.py index e63ed5923f..ce7f97ec58 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_ThresholdScalarVolume.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_ThresholdScalarVolume.py @@ -32,11 +32,10 @@ def test_ThresholdScalarVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ThresholdScalarVolume_outputs(): - output_map = dict( - OutputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = ThresholdScalarVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/filtering/tests/test_auto_VotingBinaryHoleFillingImageFilter.py b/nipype/interfaces/slicer/filtering/tests/test_auto_VotingBinaryHoleFillingImageFilter.py index 89832bf9ba..c8100fd74b 100644 --- a/nipype/interfaces/slicer/filtering/tests/test_auto_VotingBinaryHoleFillingImageFilter.py +++ b/nipype/interfaces/slicer/filtering/tests/test_auto_VotingBinaryHoleFillingImageFilter.py @@ -34,11 +34,10 @@ def test_VotingBinaryHoleFillingImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_VotingBinaryHoleFillingImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = VotingBinaryHoleFillingImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/legacy/diffusion/tests/test_auto_DWIUnbiasedNonLocalMeansFilter.py b/nipype/interfaces/slicer/legacy/diffusion/tests/test_auto_DWIUnbiasedNonLocalMeansFilter.py index f3c1ec6ff0..a121f85614 100644 --- a/nipype/interfaces/slicer/legacy/diffusion/tests/test_auto_DWIUnbiasedNonLocalMeansFilter.py +++ b/nipype/interfaces/slicer/legacy/diffusion/tests/test_auto_DWIUnbiasedNonLocalMeansFilter.py @@ -41,11 +41,10 @@ def test_DWIUnbiasedNonLocalMeansFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_DWIUnbiasedNonLocalMeansFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = DWIUnbiasedNonLocalMeansFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdImageFilter.py b/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdImageFilter.py index 19b41f7127..6af3c1d54c 100644 --- a/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdImageFilter.py +++ b/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdImageFilter.py @@ -30,11 +30,10 @@ def test_OtsuThresholdImageFilter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_OtsuThresholdImageFilter_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = OtsuThresholdImageFilter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdSegmentation.py b/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdSegmentation.py index b9fa12f2aa..c73313751e 100644 --- a/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdSegmentation.py +++ b/nipype/interfaces/slicer/legacy/tests/test_auto_OtsuThresholdSegmentation.py @@ -31,11 +31,10 @@ def test_OtsuThresholdSegmentation_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_OtsuThresholdSegmentation_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = OtsuThresholdSegmentation.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/legacy/tests/test_auto_ResampleScalarVolume.py b/nipype/interfaces/slicer/legacy/tests/test_auto_ResampleScalarVolume.py index 7f1c259cd6..66207fb604 100644 --- a/nipype/interfaces/slicer/legacy/tests/test_auto_ResampleScalarVolume.py +++ b/nipype/interfaces/slicer/legacy/tests/test_auto_ResampleScalarVolume.py @@ -32,11 +32,10 @@ def test_ResampleScalarVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ResampleScalarVolume_outputs(): - output_map = dict( - OutputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = ResampleScalarVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/segmentation/tests/test_auto_RobustStatisticsSegmenter.py b/nipype/interfaces/slicer/segmentation/tests/test_auto_RobustStatisticsSegmenter.py index 6befb36860..c956ae34ec 100644 --- a/nipype/interfaces/slicer/segmentation/tests/test_auto_RobustStatisticsSegmenter.py +++ b/nipype/interfaces/slicer/segmentation/tests/test_auto_RobustStatisticsSegmenter.py @@ -37,11 +37,10 @@ def test_RobustStatisticsSegmenter_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_RobustStatisticsSegmenter_outputs(): - output_map = dict( - segmentedImageFileName=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(segmentedImageFileName=dict( + extensions=None, + position=-1, + ), ) outputs = RobustStatisticsSegmenter.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/segmentation/tests/test_auto_SimpleRegionGrowingSegmentation.py b/nipype/interfaces/slicer/segmentation/tests/test_auto_SimpleRegionGrowingSegmentation.py index 5f880c08cb..8ffdd04355 100644 --- a/nipype/interfaces/slicer/segmentation/tests/test_auto_SimpleRegionGrowingSegmentation.py +++ b/nipype/interfaces/slicer/segmentation/tests/test_auto_SimpleRegionGrowingSegmentation.py @@ -34,11 +34,10 @@ def test_SimpleRegionGrowingSegmentation_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_SimpleRegionGrowingSegmentation_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = SimpleRegionGrowingSegmentation.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_GrayscaleModelMaker.py b/nipype/interfaces/slicer/tests/test_auto_GrayscaleModelMaker.py index 3669a21fc3..e18c0f0d5d 100644 --- a/nipype/interfaces/slicer/tests/test_auto_GrayscaleModelMaker.py +++ b/nipype/interfaces/slicer/tests/test_auto_GrayscaleModelMaker.py @@ -33,11 +33,10 @@ def test_GrayscaleModelMaker_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_GrayscaleModelMaker_outputs(): - output_map = dict( - OutputGeometry=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputGeometry=dict( + extensions=None, + position=-1, + ), ) outputs = GrayscaleModelMaker.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_LabelMapSmoothing.py b/nipype/interfaces/slicer/tests/test_auto_LabelMapSmoothing.py index faf982a342..d196dbf5d8 100644 --- a/nipype/interfaces/slicer/tests/test_auto_LabelMapSmoothing.py +++ b/nipype/interfaces/slicer/tests/test_auto_LabelMapSmoothing.py @@ -31,11 +31,10 @@ def test_LabelMapSmoothing_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_LabelMapSmoothing_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = LabelMapSmoothing.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_MergeModels.py b/nipype/interfaces/slicer/tests/test_auto_MergeModels.py index c25d4ebcf3..2e09b69bd1 100644 --- a/nipype/interfaces/slicer/tests/test_auto_MergeModels.py +++ b/nipype/interfaces/slicer/tests/test_auto_MergeModels.py @@ -32,11 +32,10 @@ def test_MergeModels_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_MergeModels_outputs(): - output_map = dict( - ModelOutput=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(ModelOutput=dict( + extensions=None, + position=-1, + ), ) outputs = MergeModels.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_ModelToLabelMap.py b/nipype/interfaces/slicer/tests/test_auto_ModelToLabelMap.py index d39ae392bd..2e684e3e65 100644 --- a/nipype/interfaces/slicer/tests/test_auto_ModelToLabelMap.py +++ b/nipype/interfaces/slicer/tests/test_auto_ModelToLabelMap.py @@ -33,11 +33,10 @@ def test_ModelToLabelMap_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ModelToLabelMap_outputs(): - output_map = dict( - OutputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = ModelToLabelMap.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_OrientScalarVolume.py b/nipype/interfaces/slicer/tests/test_auto_OrientScalarVolume.py index d0d437915b..479bb842bb 100644 --- a/nipype/interfaces/slicer/tests/test_auto_OrientScalarVolume.py +++ b/nipype/interfaces/slicer/tests/test_auto_OrientScalarVolume.py @@ -28,11 +28,10 @@ def test_OrientScalarVolume_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_OrientScalarVolume_outputs(): - output_map = dict( - outputVolume=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(outputVolume=dict( + extensions=None, + position=-1, + ), ) outputs = OrientScalarVolume.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/slicer/tests/test_auto_ProbeVolumeWithModel.py b/nipype/interfaces/slicer/tests/test_auto_ProbeVolumeWithModel.py index 528ba47e1b..b4bbdbe283 100644 --- a/nipype/interfaces/slicer/tests/test_auto_ProbeVolumeWithModel.py +++ b/nipype/interfaces/slicer/tests/test_auto_ProbeVolumeWithModel.py @@ -32,11 +32,10 @@ def test_ProbeVolumeWithModel_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_ProbeVolumeWithModel_outputs(): - output_map = dict( - OutputModel=dict( - extensions=None, - position=-1, - ), ) + output_map = dict(OutputModel=dict( + extensions=None, + position=-1, + ), ) outputs = ProbeVolumeWithModel.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/tests/test_auto_PETPVC.py b/nipype/interfaces/tests/test_auto_PETPVC.py index 60f5b29826..de7c1fa272 100644 --- a/nipype/interfaces/tests/test_auto_PETPVC.py +++ b/nipype/interfaces/tests/test_auto_PETPVC.py @@ -59,7 +59,7 @@ def test_PETPVC_inputs(): mandatory=True, ), stop_crit=dict( - argstr='-a %.4f', + argstr='-s %.4f', usedefault=True, ), ) diff --git a/nipype/interfaces/utility/tests/test_auto_Rename.py b/nipype/interfaces/utility/tests/test_auto_Rename.py index 6b56badd6f..70ced0ecdd 100644 --- a/nipype/interfaces/utility/tests/test_auto_Rename.py +++ b/nipype/interfaces/utility/tests/test_auto_Rename.py @@ -20,7 +20,7 @@ def test_Rename_inputs(): for metakey, value in list(metadata.items()): assert getattr(inputs.traits()[key], metakey) == value def test_Rename_outputs(): - output_map = dict(out_file=dict(), ) + output_map = dict(out_file=dict(extensions=None, ), ) outputs = Rename.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/pipeline/engine/nodes.py b/nipype/pipeline/engine/nodes.py index 2c441a5c57..bf58934f5b 100644 --- a/nipype/pipeline/engine/nodes.py +++ b/nipype/pipeline/engine/nodes.py @@ -37,7 +37,7 @@ from .utils import ( _parameterization_dir, save_hashfile as _save_hashfile, load_resultfile as _load_resultfile, save_resultfile as _save_resultfile, nodelist_runner as - _node_runner, strip_temp as _strip_temp, write_report, + _node_runner, strip_temp as _strip_temp, write_node_report, clean_working_directory, merge_dict, evaluate_connect_function) from .base import EngineBase @@ -195,7 +195,7 @@ def interface(self): def result(self): """Get result from result file (do not hold it in memory)""" return _load_resultfile( - op.join(self.output_dir(), 'result_%s.pklz' % self.name))[0] + op.join(self.output_dir(), 'result_%s.pklz' % self.name)) @property def inputs(self): @@ -293,27 +293,29 @@ def is_cached(self, rm_outdated=False): """ outdir = self.output_dir() - # Update hash - hashed_inputs, hashvalue = self._get_hashval() - # The output folder does not exist: not cached - if not op.exists(outdir): - logger.debug('[Node] Directory not found "%s".', outdir) + if not op.exists(outdir) or \ + not op.exists(op.join(outdir, 'result_%s.pklz' % self.name)): + logger.debug('[Node] Not cached "%s".', outdir) return False, False - hashfile = op.join(outdir, '_0x%s.json' % hashvalue) - cached = op.exists(hashfile) - - # Check if updated + # Check if there are hashfiles globhashes = glob(op.join(outdir, '_0x*.json')) unfinished = [ path for path in globhashes if path.endswith('_unfinished.json') ] hashfiles = list(set(globhashes) - set(unfinished)) + + # Update hash + hashed_inputs, hashvalue = self._get_hashval() + + hashfile = op.join(outdir, '_0x%s.json' % hashvalue) logger.debug('[Node] Hashes: %s, %s, %s, %s', hashed_inputs, hashvalue, hashfile, hashfiles) + cached = hashfile in hashfiles + # No previous hashfiles found, we're all set. if cached and len(hashfiles) == 1: assert(hashfile == hashfiles[0]) @@ -387,17 +389,17 @@ def hash_exists(self, updatehash=False): return cached, self._hashvalue, hashfile, self._hashed_inputs def run(self, updatehash=False): - """Execute the node in its directory. + """ + Execute the node in its directory. Parameters ---------- - updatehash: boolean When the hash stored in the output directory as a result of a previous run does not match that calculated for this execution, updatehash=True only updates the hash without re-running. - """ + """ if self.config is None: self.config = {} self.config = merge_dict(deepcopy(config._sections), self.config) @@ -441,6 +443,11 @@ def run(self, updatehash=False): for outdatedhash in glob(op.join(self.output_dir(), '_0x*.json')): os.remove(outdatedhash) + # _get_hashval needs to be called before running. When there is a valid (or seemingly + # valid cache), the is_cached() member updates the hashval via _get_hashval. + # However, if this node's folder doesn't exist or the result file is not found, then + # the hashval needs to be generated here. See #3026 for a larger context. + self._get_hashval() # Hashfile while running hashfile_unfinished = op.join( outdir, '_0x%s_unfinished.json' % self._hashvalue) @@ -464,8 +471,7 @@ def run(self, updatehash=False): # Store runtime-hashfile, pre-execution report, the node and the inputs set. _save_hashfile(hashfile_unfinished, self._hashed_inputs) - write_report( - self, report_type='preexec', is_mapnode=isinstance(self, MapNode)) + write_node_report(self, is_mapnode=isinstance(self, MapNode)) savepkl(op.join(outdir, '_node.pklz'), self) savepkl(op.join(outdir, '_inputs.pklz'), self.inputs.get_traitsfree()) @@ -484,8 +490,7 @@ def run(self, updatehash=False): # Tear-up after success shutil.move(hashfile_unfinished, hashfile_unfinished.replace('_unfinished', '')) - write_report( - self, report_type='postexec', is_mapnode=isinstance(self, MapNode)) + write_node_report(self, result=result, is_mapnode=isinstance(self, MapNode)) logger.info('[Node] Finished "%s".', self.fullname) return result @@ -518,7 +523,7 @@ def _get_inputs(self): logger.debug('input: %s', key) results_file = info[0] logger.debug('results file: %s', results_file) - outputs = _load_resultfile(results_file)[0].outputs + outputs = _load_resultfile(results_file).outputs if outputs is None: raise RuntimeError("""\ Error populating the input "%s" of node "%s": the results file of the source node \ @@ -565,34 +570,42 @@ def _run_interface(self, execute=True, updatehash=False): def _load_results(self): cwd = self.output_dir() - result, aggregate, attribute_error = _load_resultfile( - op.join(cwd, 'result_%s.pklz' % self.name)) + + try: + result = _load_resultfile( + op.join(cwd, 'result_%s.pklz' % self.name)) + except (traits.TraitError, EOFError): + logger.debug( + 'Error populating inputs/outputs, (re)aggregating results...') + except (AttributeError, ImportError) as err: + logger.debug('attribute error: %s probably using ' + 'different trait pickled file', str(err)) + old_inputs = loadpkl(op.join(cwd, '_inputs.pklz')) + self.inputs.trait_set(**old_inputs) + else: + return result + # try aggregating first - if aggregate: - logger.debug('aggregating results') - if attribute_error: - old_inputs = loadpkl(op.join(cwd, '_inputs.pklz')) - self.inputs.trait_set(**old_inputs) - if not isinstance(self, MapNode): - self._copyfiles_to_wd(linksonly=True) - aggouts = self._interface.aggregate_outputs( - needed_outputs=self.needed_outputs) - runtime = Bunch( - cwd=cwd, - returncode=0, - environ=dict(os.environ), - hostname=socket.gethostname()) - result = InterfaceResult( - interface=self._interface.__class__, - runtime=runtime, - inputs=self._interface.inputs.get_traitsfree(), - outputs=aggouts) - _save_resultfile( - result, cwd, self.name, - rebase=str2bool(self.config['execution']['use_relative_paths'])) - else: - logger.debug('aggregating mapnode results') - result = self._run_interface() + if not isinstance(self, MapNode): + self._copyfiles_to_wd(linksonly=True) + aggouts = self._interface.aggregate_outputs( + needed_outputs=self.needed_outputs) + runtime = Bunch( + cwd=cwd, + returncode=0, + environ=dict(os.environ), + hostname=socket.gethostname()) + result = InterfaceResult( + interface=self._interface.__class__, + runtime=runtime, + inputs=self._interface.inputs.get_traitsfree(), + outputs=aggouts) + _save_resultfile( + result, cwd, self.name, + rebase=str2bool(self.config['execution']['use_relative_paths'])) + else: + logger.debug('aggregating mapnode results') + result = self._run_interface() return result def _run_command(self, execute, copyfiles=True): @@ -1196,7 +1209,7 @@ def get_subnodes(self): """Generate subnodes of a mapnode and write pre-execution report""" self._get_inputs() self._check_iterfield() - write_report(self, report_type='preexec', is_mapnode=True) + write_node_report(self, result=None, is_mapnode=True) return [node for _, node in self._make_nodes()] def num_subnodes(self): diff --git a/nipype/pipeline/engine/tests/test_utils.py b/nipype/pipeline/engine/tests/test_utils.py index c462ea1533..dd44f430e1 100644 --- a/nipype/pipeline/engine/tests/test_utils.py +++ b/nipype/pipeline/engine/tests/test_utils.py @@ -16,7 +16,8 @@ from ....interfaces import base as nib from ....interfaces import utility as niu from .... import config -from ..utils import clean_working_directory, write_workflow_prov +from ..utils import (clean_working_directory, write_workflow_prov, + load_resultfile) class InputSpec(nib.TraitedSpec): @@ -283,3 +284,49 @@ def test_modify_paths_bug(tmpdir): assert outputs.out_dict_path == {out_str: out_path} assert outputs.out_dict_str == {out_str: out_str} assert outputs.out_list == [out_str] * 2 + + +@pytest.mark.xfail(sys.version_info < (3, 4), + reason="rebase does not fully work with Python 2.7") +@pytest.mark.parametrize("use_relative", [True, False]) +def test_save_load_resultfile(tmpdir, use_relative): + """Test minimally the save/load functions for result files.""" + from shutil import copytree, rmtree + tmpdir.chdir() + + old_use_relative = config.getboolean('execution', 'use_relative_paths') + config.set('execution', 'use_relative_paths', use_relative) + + spc = pe.Node(StrPathConfuser(in_str='2'), name='spc') + spc.base_dir = tmpdir.mkdir('node').strpath + + result = spc.run() + + loaded_result = load_resultfile( + tmpdir.join('node').join('spc').join('result_spc.pklz').strpath) + + assert result.runtime.dictcopy() == loaded_result.runtime.dictcopy() + assert result.inputs == loaded_result.inputs + assert result.outputs.get() == loaded_result.outputs.get() + + # Test the mobility of the result file. + copytree(tmpdir.join('node').strpath, tmpdir.join('node2').strpath) + rmtree(tmpdir.join('node').strpath) + + if use_relative: + loaded_result2 = load_resultfile( + tmpdir.join('node2').join('spc').join('result_spc.pklz').strpath) + + assert result.runtime.dictcopy() == loaded_result2.runtime.dictcopy() + assert result.inputs == loaded_result2.inputs + assert loaded_result2.outputs.get() != result.outputs.get() + newpath = result.outputs.out_path.replace('/node/', '/node2/') + assert loaded_result2.outputs.out_path == newpath + assert loaded_result2.outputs.out_tuple[0] == newpath + assert loaded_result2.outputs.out_dict_path['2'] == newpath + else: + with pytest.raises(nib.TraitError): + load_resultfile( + tmpdir.join('node2').join('spc').join('result_spc.pklz').strpath) + + config.set('execution', 'use_relative_paths', old_use_relative) diff --git a/nipype/pipeline/engine/utils.py b/nipype/pipeline/engine/utils.py index 65170f14c9..0df39e2a5a 100644 --- a/nipype/pipeline/engine/utils.py +++ b/nipype/pipeline/engine/utils.py @@ -38,11 +38,12 @@ write_rst_header, write_rst_dict, write_rst_list, + FileNotFoundError, ) from ...utils.misc import str2bool from ...utils.functions import create_function_from_source from ...interfaces.base.traits_extension import ( - rebase_path_traits, resolve_path_traits, OutputMultiPath, isdefined, Undefined, traits) + rebase_path_traits, resolve_path_traits, OutputMultiPath, isdefined, Undefined) from ...interfaces.base.support import Bunch, InterfaceResult from ...interfaces.base import CommandLine from ...interfaces.utility import IdentityInterface @@ -115,68 +116,60 @@ def nodelist_runner(nodes, updatehash=False, stop_first=False): yield i, result, err -def write_report(node, report_type=None, is_mapnode=False): - """Write a report file for a node""" +def write_node_report(node, result=None, is_mapnode=False): + """Write a report file for a node.""" if not str2bool(node.config['execution']['create_report']): return - if report_type not in ['preexec', 'postexec']: - logger.warning('[Node] Unknown report type "%s".', report_type) - return - cwd = node.output_dir() - report_dir = os.path.join(cwd, '_report') - report_file = os.path.join(report_dir, 'report.rst') - makedirs(report_dir, exist_ok=True) - - logger.debug('[Node] Writing %s-exec report to "%s"', report_type[:-4], - report_file) - if report_type.startswith('pre'): - lines = [ - write_rst_header('Node: %s' % get_print_name(node), level=0), - write_rst_list( - ['Hierarchy : %s' % node.fullname, - 'Exec ID : %s' % node._id]), - write_rst_header('Original Inputs', level=1), - write_rst_dict(node.inputs.trait_get()), - ] - with open(report_file, 'wt') as fp: - fp.write('\n'.join(lines)) - return + report_file = Path(cwd) / '_report' / 'report.rst' + report_file.parent.mkdir(exist_ok=True, parents=True) lines = [ + write_rst_header('Node: %s' % get_print_name(node), level=0), + write_rst_list( + ['Hierarchy : %s' % node.fullname, + 'Exec ID : %s' % node._id]), + write_rst_header('Original Inputs', level=1), + write_rst_dict(node.inputs.trait_get()), + ] + + if result is None: + logger.debug('[Node] Writing pre-exec report to "%s"', report_file) + report_file.write_text('\n'.join(lines)) + return + + logger.debug('[Node] Writing post-exec report to "%s"', report_file) + lines += [ write_rst_header('Execution Inputs', level=1), write_rst_dict(node.inputs.trait_get()), + write_rst_header('Execution Outputs', level=1) ] - result = node.result # Locally cache result outputs = result.outputs - if outputs is None: - with open(report_file, 'at') as fp: - fp.write('\n'.join(lines)) + lines += ['None'] + report_file.write_text('\n'.join(lines)) return - lines.append(write_rst_header('Execution Outputs', level=1)) - if isinstance(outputs, Bunch): lines.append(write_rst_dict(outputs.dictcopy())) elif outputs: lines.append(write_rst_dict(outputs.trait_get())) + else: + lines += ['Outputs object was empty.'] if is_mapnode: lines.append(write_rst_header('Subnode reports', level=1)) nitems = len(ensure_list(getattr(node.inputs, node.iterfield[0]))) subnode_report_files = [] for i in range(nitems): - nodecwd = os.path.join(cwd, 'mapflow', '_%s%d' % (node.name, i), - '_report', 'report.rst') - subnode_report_files.append('subnode %d : %s' % (i, nodecwd)) + subnode_file = Path(cwd) / 'mapflow' / ( + '_%s%d' % (node.name, i)) / '_report' / 'report.rst' + subnode_report_files.append('subnode %d : %s' % (i, subnode_file)) lines.append(write_rst_list(subnode_report_files)) - - with open(report_file, 'at') as fp: - fp.write('\n'.join(lines)) + report_file.write_text('\n'.join(lines)) return lines.append(write_rst_header('Runtime info', level=1)) @@ -188,15 +181,9 @@ def write_report(node, report_type=None, is_mapnode=False): 'prev_wd': getattr(result.runtime, 'prevcwd', ''), } - if hasattr(result.runtime, 'cmdline'): - rst_dict['command'] = result.runtime.cmdline - - # Try and insert memory/threads usage if available - if hasattr(result.runtime, 'mem_peak_gb'): - rst_dict['mem_peak_gb'] = result.runtime.mem_peak_gb - - if hasattr(result.runtime, 'cpu_percent'): - rst_dict['cpu_percent'] = result.runtime.cpu_percent + for prop in ('cmdline', 'mem_peak_gb', 'cpu_percent'): + if hasattr(result.runtime, prop): + rst_dict[prop] = getattr(result.runtime, prop) lines.append(write_rst_dict(rst_dict)) @@ -224,9 +211,17 @@ def write_report(node, report_type=None, is_mapnode=False): write_rst_dict(result.runtime.environ), ] - with open(report_file, 'at') as fp: - fp.write('\n'.join(lines)) - return + report_file.write_text('\n'.join(lines)) + + +def write_report(node, report_type=None, is_mapnode=False): + """Write a report file for a node - DEPRECATED""" + if report_type not in ('preexec', 'postexec'): + logger.warning('[Node] Unknown report type "%s".', report_type) + return + + write_node_report(node, is_mapnode=is_mapnode, + result=node.result if report_type == 'postexec' else None) def save_resultfile(result, cwd, name, rebase=None): @@ -249,6 +244,10 @@ def save_resultfile(result, cwd, name, rebase=None): savepkl(resultsfile, result) return + if not rebase: + savepkl(resultsfile, result) + return + backup_traits = {} try: with indirectory(cwd): @@ -273,58 +272,44 @@ def load_resultfile(results_file, resolve=True): """ Load InterfaceResult file from path. - Parameter - --------- - path : base_dir of node - name : name of node + Parameters + ---------- + results_file : pathlike + Path to an existing pickle (``result_.pklz``) created with + ``save_resultfile``. + Raises ``FileNotFoundError`` if ``results_file`` does not exist. + resolve : bool + Determines whether relative paths will be resolved to absolute (default is ``True``). Returns ------- - result : InterfaceResult structure - aggregate : boolean indicating whether node should aggregate_outputs - attribute error : boolean indicating whether there was some mismatch in - versions of traits used to store result and hence node needs to - rerun + result : InterfaceResult + A Nipype object containing the runtime, inputs, outputs and other interface information + such as a traceback in the case of errors. """ results_file = Path(results_file) - aggregate = True - result = None - attribute_error = False - if not results_file.exists(): - return result, aggregate, attribute_error + raise FileNotFoundError(results_file) - with indirectory(str(results_file.parent)): + result = loadpkl(results_file) + if resolve and result.outputs: try: - result = loadpkl(results_file) - except (traits.TraitError, EOFError): - logger.debug( - 'some file does not exist. hence trait cannot be set') - except (AttributeError, ImportError) as err: - attribute_error = True - logger.debug('attribute error: %s probably using ' - 'different trait pickled file', str(err)) - else: - aggregate = False - - if resolve and result.outputs: - try: - outputs = result.outputs.get() - except TypeError: # This is a Bunch - return result, aggregate, attribute_error - - logger.debug('Resolving paths in outputs loaded from results file.') - for trait_name, old in list(outputs.items()): - if isdefined(old): - if result.outputs.trait(trait_name).is_trait_type(OutputMultiPath): - old = result.outputs.trait(trait_name).handler.get_value( - result.outputs, trait_name) - value = resolve_path_traits(result.outputs.trait(trait_name), old, - results_file.parent) - setattr(result.outputs, trait_name, value) - - return result, aggregate, attribute_error + outputs = result.outputs.get() + except TypeError: # This is a Bunch + logger.debug('Outputs object of loaded result %s is a Bunch.', results_file) + return result + + logger.debug('Resolving paths in outputs loaded from results file.') + for trait_name, old in list(outputs.items()): + if isdefined(old): + if result.outputs.trait(trait_name).is_trait_type(OutputMultiPath): + old = result.outputs.trait(trait_name).handler.get_value( + result.outputs, trait_name) + value = resolve_path_traits(result.outputs.trait(trait_name), old, + results_file.parent) + setattr(result.outputs, trait_name, value) + return result def strip_temp(files, wd): diff --git a/nipype/pipeline/plugins/tools.py b/nipype/pipeline/plugins/tools.py index 54fffd2398..ebf023b787 100644 --- a/nipype/pipeline/plugins/tools.py +++ b/nipype/pipeline/plugins/tools.py @@ -16,7 +16,7 @@ from traceback import format_exception from ... import logging -from ...utils.filemanip import savepkl, crash2txt, makedirs +from ...utils.filemanip import savepkl, crash2txt, makedirs, FileNotFoundError logger = logging.getLogger('nipype.workflow') @@ -26,17 +26,30 @@ def report_crash(node, traceback=None, hostname=None): """ name = node._id host = None - if node.result and getattr(node.result, 'runtime'): - if isinstance(node.result.runtime, list): - host = node.result.runtime[0].hostname - else: - host = node.result.runtime.hostname + traceback = traceback or format_exception(*sys.exc_info()) + + try: + result = node.result + except FileNotFoundError: + traceback += """ + +When creating this crashfile, the results file corresponding +to the node could not be found.""".splitlines(keepends=True) + except Exception as exc: + traceback += """ + +During the creation of this crashfile triggered by the above exception, +another exception occurred:\n\n{}.""".format(exc).splitlines(keepends=True) + else: + if getattr(result, 'runtime', None): + if isinstance(result.runtime, list): + host = result.runtime[0].hostname + else: + host = result.runtime.hostname # Try everything to fill in the host host = host or hostname or gethostname() logger.error('Node %s failed to run on host %s.', name, host) - if not traceback: - traceback = format_exception(*sys.exc_info()) timeofcrash = strftime('%Y%m%d-%H%M%S') try: login_name = getpass.getuser() @@ -49,7 +62,7 @@ def report_crash(node, traceback=None, hostname=None): makedirs(crashdir, exist_ok=True) crashfile = os.path.join(crashdir, crashfile) - if node.config['execution']['crashfile_format'].lower() in ['text', 'txt']: + if node.config['execution']['crashfile_format'].lower() in ('text', 'txt', '.txt'): crashfile += '.txt' else: crashfile += '.pklz' diff --git a/nipype/utils/config.py b/nipype/utils/config.py index 79c0bf6b51..d6d6d0879d 100644 --- a/nipype/utils/config.py +++ b/nipype/utils/config.py @@ -25,7 +25,7 @@ from future import standard_library from .misc import str2bool -from ..external import portalocker +from filelock import SoftFileLock standard_library.install_aliases() @@ -209,9 +209,9 @@ def get_data(self, key): """Read options file""" if not os.path.exists(self.data_file): return None - with open(self.data_file, 'rt') as file: - portalocker.lock(file, portalocker.LOCK_EX) - datadict = load(file) + with SoftFileLock('%s.lock' % self.data_file): + with open(self.data_file, 'rt') as file: + datadict = load(file) if key in datadict: return datadict[key] return None @@ -220,17 +220,17 @@ def save_data(self, key, value): """Store config flie""" datadict = {} if os.path.exists(self.data_file): - with open(self.data_file, 'rt') as file: - portalocker.lock(file, portalocker.LOCK_EX) - datadict = load(file) + with SoftFileLock('%s.lock' % self.data_file): + with open(self.data_file, 'rt') as file: + datadict = load(file) else: dirname = os.path.dirname(self.data_file) if not os.path.exists(dirname): mkdir_p(dirname) - with open(self.data_file, 'wt') as file: - portalocker.lock(file, portalocker.LOCK_EX) - datadict[key] = value - dump(datadict, file) + with SoftFileLock('%s.lock' % self.data_file): + with open(self.data_file, 'wt') as file: + datadict[key] = value + dump(datadict, file) def update_config(self, config_dict): """Extend internal dictionary with config_dict""" diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index 44654c0197..c919000d34 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -21,6 +21,7 @@ import contextlib import posixpath import simplejson as json +from filelock import SoftFileLock from builtins import str, bytes, open @@ -56,7 +57,7 @@ def __init__(self, path): from pathlib2 import Path USING_PATHLIB2 = True -try: +try: # PY35 - strict mode was added in 3.6 Path('/invented/file/path').resolve(strict=True) except TypeError: def _patch_resolve(self, strict=False): @@ -72,6 +73,7 @@ def _patch_resolve(self, strict=False): except FileNotFoundError: pass except OSError: + # PY2 def _patch_resolve(self, strict=False): """Raise FileNotFoundError instead of OSError with pathlib2.""" try: @@ -84,6 +86,27 @@ def _patch_resolve(self, strict=False): Path.old_resolve = Path.resolve Path.resolve = _patch_resolve +if not hasattr(Path, 'write_text'): + # PY34 - Path does not have write_text + def _write_text(self, text): + with open(str(self), 'w') as f: + f.write(text) + Path.write_text = _write_text + +if PY3: + try: # PY34 - mkdir does not have exist_ok + from tempfile import TemporaryDirectory + with TemporaryDirectory() as tmpdir: + (Path(tmpdir) / 'exist_ok_test').mkdir(exist_ok=True) + except TypeError: + def _mkdir(self, mode=0o777, parents=False, exist_ok=False): + if parents: + os.makedirs(str(self), mode=mode, exist_ok=exist_ok) + elif not exist_ok or not self.exists(): + os.mkdir(str(self), mode=mode) + + Path.mkdir = _mkdir + def split_filename(fname): """Split a filename into parts: path, base filename and extension. @@ -670,56 +693,52 @@ def load_json(filename): def loadcrash(infile, *args): if infile.endswith('pkl') or infile.endswith('pklz'): - return loadpkl(infile, versioning=True) + return loadpkl(infile) else: raise ValueError('Only pickled crashfiles are supported') -def loadpkl(infile, versioning=False): +def loadpkl(infile): """Load a zipped or plain cPickled file.""" infile = Path(infile) fmlogger.debug('Loading pkl: %s', infile) pklopen = gzip.open if infile.suffix == '.pklz' else open pkl_metadata = None + unpkl = None with indirectory(infile.parent): - pkl_file = pklopen(infile.name, 'rb') - - try: # Look if pkl file contains version file - pkl_metadata_line = pkl_file.readline() - pkl_metadata = json.loads(pkl_metadata_line) - except (UnicodeDecodeError, json.JSONDecodeError): - pass - finally: - # Could not get version info - pkl_file.seek(0) - - try: - unpkl = pickle.load(pkl_file) - except UnicodeDecodeError: - # Was this pickle created with Python 2.x? - unpkl = pickle.load(pkl_file, fix_imports=True, encoding='utf-8') - fmlogger.info('Successfully loaded pkl in compatibility mode.') - # Unpickling problems - except Exception as e: - if not versioning: - raise e - - if pkl_metadata and 'version' in pkl_metadata: - from nipype import __version__ as version - if pkl_metadata['version'] != version: - fmlogger.error("""\ + with SoftFileLock('%s.lock' % infile.name): + with pklopen(infile.name, 'rb') as pkl_file: + try: # Look if pkl file contains version file + pkl_metadata_line = pkl_file.readline() + pkl_metadata = json.loads(pkl_metadata_line) + except (UnicodeDecodeError, json.JSONDecodeError): + # Could not get version info + pkl_file.seek(0) + try: + unpkl = pickle.load(pkl_file) + except UnicodeDecodeError: + # Was this pickle created with Python 2.x? + unpkl = pickle.load(pkl_file, fix_imports=True, encoding='utf-8') + fmlogger.info('Successfully loaded pkl in compatibility mode.') + # Unpickling problems + except Exception as e: + if pkl_metadata and 'version' in pkl_metadata: + from nipype import __version__ as version + if pkl_metadata['version'] != version: + fmlogger.error("""\ Attempted to open a results file generated by Nipype version %s, \ with an incompatible Nipype version (%s)""", pkl_metadata['version'], version) - raise e - fmlogger.error("""\ + raise e + fmlogger.warning("""\ No metadata was found in the pkl file. Make sure you are currently using \ the same Nipype version from the generated pkl.""") - raise e - else: - return unpkl - finally: - pkl_file.close() + raise e + + if unpkl is None: + raise ValueError('Loading %s resulted in None.' % infile) + + return unpkl def crash2txt(filename, record): @@ -755,20 +774,17 @@ def read_stream(stream, logger=None, encoding=None): def savepkl(filename, record, versioning=False): - if filename.endswith('pklz'): - pkl_file = gzip.open(filename, 'wb') - else: - pkl_file = open(filename, 'wb') - - if versioning: - from nipype import __version__ as version - metadata = json.dumps({'version': version}) + pklopen = gzip.open if filename.endswith('.pklz') else open + with SoftFileLock('%s.lock' % filename): + with pklopen(filename, 'wb') as pkl_file: + if versioning: + from nipype import __version__ as version + metadata = json.dumps({'version': version}) - pkl_file.write(metadata.encode('utf-8')) - pkl_file.write('\n'.encode('utf-8')) + pkl_file.write(metadata.encode('utf-8')) + pkl_file.write('\n'.encode('utf-8')) - pickle.dump(record, pkl_file) - pkl_file.close() + pickle.dump(record, pkl_file) rst_levels = ['=', '-', '~', '+'] diff --git a/nipype/utils/tests/test_filemanip.py b/nipype/utils/tests/test_filemanip.py index 7eaa8b9c86..9ee2e4c0ba 100644 --- a/nipype/utils/tests/test_filemanip.py +++ b/nipype/utils/tests/test_filemanip.py @@ -558,7 +558,7 @@ def test_versioned_pklization(tmpdir): with mock.patch('nipype.utils.tests.test_filemanip.Pickled', PickledBreaker), \ mock.patch('nipype.__version__', '0.0.0'): - loadpkl('./pickled.pkz', versioning=True) + loadpkl('./pickled.pkz') def test_unversioned_pklization(tmpdir): @@ -569,7 +569,7 @@ def test_unversioned_pklization(tmpdir): with pytest.raises(Exception): with mock.patch('nipype.utils.tests.test_filemanip.Pickled', PickledBreaker): - loadpkl('./pickled.pkz', versioning=True) + loadpkl('./pickled.pkz') def test_Path_strict_resolve(tmpdir): @@ -587,3 +587,28 @@ def test_Path_strict_resolve(tmpdir): # If the file is created, it should not raise open('somefile.txt', 'w').close() assert '%s/somefile.txt' % tmpdir == '%s' % testfile.resolve(strict=True) + + +@pytest.mark.parametrize("save_versioning", [True, False]) +def test_pickle(tmp_path, save_versioning): + testobj = 'iamateststr' + pickle_fname = str(tmp_path / 'testpickle.pklz') + savepkl(pickle_fname, testobj, versioning=save_versioning) + outobj = loadpkl(pickle_fname) + assert outobj == testobj + + +def test_Path(tmpdir): + tmp_path = Path(tmpdir.strpath) + + (tmp_path / 'textfile').write_text('some text') + + with pytest.raises(OSError): + (tmp_path / 'no' / 'parents').mkdir(parents=False) + + (tmp_path / 'no' / 'parents').mkdir(parents=True) + + with pytest.raises(OSError): + (tmp_path / 'no' / 'parents').mkdir(parents=False) + + (tmp_path / 'no' / 'parents').mkdir(parents=True, exist_ok=True) diff --git a/requirements.txt b/requirements.txt index 99b97a19a6..44226da48b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ python-dateutil>=2.2 scipy>=0.14 simplejson>=3.8.0 traits>=4.6 +filelock>= 3.0.0 diff --git a/tools/update_zenodo.py b/tools/update_zenodo.py index 637defad49..163f88084d 100755 --- a/tools/update_zenodo.py +++ b/tools/update_zenodo.py @@ -58,6 +58,7 @@ "Leipzig, Germany.", "name": "Mihai, Paul Glad", "orcid": "0000-0001-5715-6442"}, + {"name": "Lai, Jeff"} ] for entry in missing_entries: