From 18eedf70004e42772a39dd57790728cbf79c7324 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 10 Feb 2017 11:48:54 -0500 Subject: [PATCH 01/44] fix: make outvol mandatory --- nipype/interfaces/freesurfer/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 2953963149..d5d40e88af 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1467,7 +1467,7 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): # mandatory in_file = File(exists=True, mandatory=True, argstr="--i %s", desc="input volume. Input can be any format accepted by mri_convert.") - out_file = File(argstr="--o %s", name_source=['in_file'], + out_file = File(argstr="--o %s", mandatory=True, name_source=['in_file'], name_template='%s_output', hash_files=False, keep_extension=True, desc="output volume. Output can be any format accepted by mri_convert. " + "If the output format is COR, then the directory must exist.") From 2cecd53ca6c959c41c9ecd006bd2e1c18106c1b7 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 10 Feb 2017 17:55:18 -0500 Subject: [PATCH 02/44] enh: testing --- .../freesurfer/tests/test_preprocess.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index da6ba65fc3..f4a468bb52 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -85,3 +85,28 @@ def test_synthesizeflash(create_files_in_directory): syn2 = freesurfer.SynthesizeFLASH(t1_image=filelist[0], pd_image=filelist[1], flip_angle=20, te=5, tr=25) assert syn2.cmdline == ('mri_synthesize 25.00 20.00 5.000 %s %s %s' % (filelist[0], filelist[1], os.path.join(outdir, 'synth-flash_20.mgz'))) + +@pytest.mark.skipif(freesurfer.no_freesurfer(), reason="freesurfer is not installed") +def test_mandatory_outvol(create_files_in_directory): + filelist, outdir = create_files_in_directory + mni = freesurfer.MNIBiasCorrection() + + # make sure command gets called + assert mni.cmd == "mri_nu_correct.mni" + + # test raising error with mandatory args absent + with pytest.raises(ValueError): mni.run() + + # test raising error with only partial mandatory args present + mni.inputs.in_file = filelist[0] #mgz + with pytest.raises(ValueError): mni.run() + + # rest of mandatory inputs + mni.inputs.out_file = 'bias_corrected_file' + + assert mni.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_file.mgz' + % filelist[0]) + # constructor based tests + mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_file') + assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_file.mgz' + % filelist[0]) From 43182745b0fdab212b6ec5613d08b1273ea7a590 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 10 Feb 2017 22:32:48 -0500 Subject: [PATCH 03/44] fix: doctest --- nipype/interfaces/freesurfer/preprocess.py | 1 + nipype/interfaces/freesurfer/tests/test_preprocess.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index d5d40e88af..322b0a02c2 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1510,6 +1510,7 @@ class MNIBiasCorrection(FSCommand): >>> from nipype.interfaces.freesurfer import MNIBiasCorrection >>> correct = MNIBiasCorrection() >>> correct.inputs.in_file = "norm.mgz" + >>> correct.inputs.out_file = "norm_output.mgz" >>> correct.inputs.iterations = 6 >>> correct.inputs.protocol_iterations = 1000 >>> correct.inputs.distance = 50 diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index f4a468bb52..d0cc9c850b 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -102,11 +102,11 @@ def test_mandatory_outvol(create_files_in_directory): with pytest.raises(ValueError): mni.run() # rest of mandatory inputs - mni.inputs.out_file = 'bias_corrected_file' + mni.inputs.out_file = 'bias_corrected_output' - assert mni.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_file.mgz' + assert mni.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.mgz' % filelist[0]) # constructor based tests - mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_file') - assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_file.mgz' + mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_output') + assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.mgz' % filelist[0]) From 57826345dc552641c16730856090502657cffd8f Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 13:03:14 -0500 Subject: [PATCH 04/44] enh: genfile --- nipype/interfaces/freesurfer/preprocess.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 322b0a02c2..4b3851d689 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1467,11 +1467,11 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): # mandatory in_file = File(exists=True, mandatory=True, argstr="--i %s", desc="input volume. Input can be any format accepted by mri_convert.") - out_file = File(argstr="--o %s", mandatory=True, name_source=['in_file'], + # optional + out_file = File(argstr="--o %s", name_source=['in_file'], genfile=True, name_template='%s_output', hash_files=False, keep_extension=True, desc="output volume. Output can be any format accepted by mri_convert. " + "If the output format is COR, then the directory must exist.") - # optional iterations = traits.Int(4, argstr="--n %d", desc="Number of iterations to run nu_correct. Default is 4. This is the number of times " + "that nu_correct is repeated (ie, using the output from the previous run as the input for " + @@ -1510,7 +1510,6 @@ class MNIBiasCorrection(FSCommand): >>> from nipype.interfaces.freesurfer import MNIBiasCorrection >>> correct = MNIBiasCorrection() >>> correct.inputs.in_file = "norm.mgz" - >>> correct.inputs.out_file = "norm_output.mgz" >>> correct.inputs.iterations = 6 >>> correct.inputs.protocol_iterations = 1000 >>> correct.inputs.distance = 50 From fd1dda6d14b2d747911b88b85043be92e4256141 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 13:23:25 -0500 Subject: [PATCH 05/44] fix: outputspec --- nipype/interfaces/freesurfer/preprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 4b3851d689..3ce1423c22 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1468,7 +1468,7 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): in_file = File(exists=True, mandatory=True, argstr="--i %s", desc="input volume. Input can be any format accepted by mri_convert.") # optional - out_file = File(argstr="--o %s", name_source=['in_file'], genfile=True, + out_file = File(argstr="--o %s", name_source=['in_file'], name_template='%s_output', hash_files=False, keep_extension=True, desc="output volume. Output can be any format accepted by mri_convert. " + "If the output format is COR, then the directory must exist.") @@ -1528,7 +1528,7 @@ class MNIBiasCorrection(FSCommand): output_spec = MNIBiasCorrectionOutputSpec def _list_outputs(self): - outputs = self._outputs().get() + outputs = self._output_spec().get() outputs["out_file"] = os.path.abspath(self.inputs.out_file) return outputs From cb74279143d48627718e7c08125540bedc979821 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 13:30:47 -0500 Subject: [PATCH 06/44] fix: outputspec attribute --- nipype/interfaces/freesurfer/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 6d517427a2..882aebf88d 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1537,7 +1537,7 @@ class MNIBiasCorrection(FSCommand): output_spec = MNIBiasCorrectionOutputSpec def _list_outputs(self): - outputs = self._output_spec().get() + outputs = self.output_spec().get() outputs["out_file"] = os.path.abspath(self.inputs.out_file) return outputs From a5fc44024fbbdb93c459eddbb36520525ebbf2c8 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 16:07:16 -0500 Subject: [PATCH 07/44] fix: grab out file --- nipype/interfaces/freesurfer/preprocess.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 882aebf88d..0566a67647 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1477,7 +1477,7 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): in_file = File(exists=True, mandatory=True, argstr="--i %s", desc="input volume. Input can be any format accepted by mri_convert.") # optional - out_file = File(argstr="--o %s", name_source=['in_file'], + out_file = File(argstr="--o %s", name_source=['in_file'], genfile=True, name_template='%s_output', hash_files=False, keep_extension=True, desc="output volume. Output can be any format accepted by mri_convert. " + "If the output format is COR, then the directory must exist.") @@ -1501,7 +1501,7 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): desc="Shrink parameter for finer sampling (default is 4)") class MNIBiasCorrectionOutputSpec(TraitedSpec): - out_file = File(desc="output volume") + out_file = File(exists=True, desc="output volume") class MNIBiasCorrection(FSCommand): @@ -1536,9 +1536,17 @@ class MNIBiasCorrection(FSCommand): input_spec = MNIBiasCorrectionInputSpec output_spec = MNIBiasCorrectionOutputSpec + def _gen_filename(self): + # if outfile was not defined + if not isdefined(self.inputs.out_file): + return self._gen_fname(self.inputs.in_file, + suffix='_output') def _list_outputs(self): outputs = self.output_spec().get() - outputs["out_file"] = os.path.abspath(self.inputs.out_file) + if not isdefined(self.inputs.out_file): + outputs["out_file"] = self._gen_filename() + else: + outputs["out_file"] = os.path.abspath(self.inputs.out_file) return outputs From 6a44c6e2aba3804370ee45e12ab7f0111489ea14 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 16:29:26 -0500 Subject: [PATCH 08/44] fix: mnibias test --- .../freesurfer/tests/test_preprocess.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index d0cc9c850b..fbca79a22e 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -95,18 +95,21 @@ def test_mandatory_outvol(create_files_in_directory): assert mni.cmd == "mri_nu_correct.mni" # test raising error with mandatory args absent - with pytest.raises(ValueError): mni.run() + with pytest.raises(ValueError): mni.cmdline - # test raising error with only partial mandatory args present - mni.inputs.in_file = filelist[0] #mgz - with pytest.raises(ValueError): mni.run() + # test with minimal args + mni.inputs.in_file = filelist[0] + assert mni.cmdline == ('mri_nu_correct.mni --i %s --o %s_output.mgz' + % (filelist[0], filelist[0].replace('.mgz', '')) - # rest of mandatory inputs - mni.inputs.out_file = 'bias_corrected_output' + # test with custom outfile + mni.inputs.out_file = 'new_corrected_file.mgz' + assert mni.cmdline == ('mri_nu_correct.mni --i %s --o new_corrected_file.mgz' + % (filelist[0]) - assert mni.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.mgz' - % filelist[0]) # constructor based tests - mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_output') + mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], + out_file='bias_corrected_output', + iterations=4) assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.mgz' % filelist[0]) From b97a329b43bfcb6469707cbdec6c69026b5459fd Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 14 Feb 2017 16:31:57 -0500 Subject: [PATCH 09/44] fix: removed changed file --- nipype/interfaces/mrtrix/convert.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/mrtrix/convert.py b/nipype/interfaces/mrtrix/convert.py index 348fc1c898..e76e847535 100644 --- a/nipype/interfaces/mrtrix/convert.py +++ b/nipype/interfaces/mrtrix/convert.py @@ -10,7 +10,7 @@ """ from __future__ import print_function, division, unicode_literals, absolute_import -from io import open +from builtins import open import os.path as op import nibabel as nb @@ -55,11 +55,10 @@ def read_mrtrix_tracks(in_file, as_generator=True): def read_mrtrix_header(in_file): - fileobj = open(in_file, 'rb') + fileobj = open(in_file, 'r') header = {} iflogger.info('Reading header data...') for line in fileobj: - line = line.decode() if line == 'END\n': iflogger.info('Reached the end of the header!') break @@ -79,7 +78,7 @@ def read_mrtrix_header(in_file): def read_mrtrix_streamlines(in_file, header, as_generator=True): offset = header['offset'] stream_count = header['count'] - fileobj = open(in_file, 'rb') + fileobj = open(in_file, 'r') fileobj.seek(offset) endianness = native_code f4dt = np.dtype(endianness + 'f4') @@ -91,7 +90,7 @@ def points_per_track(offset): n_points = 0 track_points = [] iflogger.info('Identifying the number of points per tract...') - all_str = fileobj.read().decode() + all_str = fileobj.read() num_triplets = int(len(all_str) / bytesize) pts = np.ndarray(shape=(num_triplets, pt_cols), dtype='f4', buffer=all_str) nonfinite_list = np.where(np.isfinite(pts[:, 2]) == False) From db397cc60c18298c9b4b1f2dfecbb45170b4a6fb Mon Sep 17 00:00:00 2001 From: Horea Christian Date: Wed, 15 Feb 2017 16:41:25 +0100 Subject: [PATCH 10/44] removed obligatory xvfb dependency --- nipype/info.py | 1 - requirements.txt | 1 - rtd_requirements.txt | 1 - 3 files changed, 3 deletions(-) diff --git a/nipype/info.py b/nipype/info.py index d98faae782..66dd7f5603 100644 --- a/nipype/info.py +++ b/nipype/info.py @@ -143,7 +143,6 @@ def get_nipype_gitversion(): 'simplejson>=%s' % SIMPLEJSON_MIN_VERSION, 'prov>=%s' % PROV_MIN_VERSION, 'click>=%s' % CLICK_MIN_VERSION, - 'xvfbwrapper', 'funcsigs', 'configparser', 'pytest>=%s' % PYTEST_MIN_VERSION diff --git a/requirements.txt b/requirements.txt index c06bfbfee5..ed758f441d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,6 @@ future>=0.15.2 simplejson>=3.8.0 prov>=1.4.0 click>=6.6.0 -xvfbwrapper psutil funcsigs configparser diff --git a/rtd_requirements.txt b/rtd_requirements.txt index a8b426ea8a..ba76e51a35 100644 --- a/rtd_requirements.txt +++ b/rtd_requirements.txt @@ -9,7 +9,6 @@ pytest-cov future>=0.15.2 simplejson>=3.8.0 prov>=1.4.0 -xvfbwrapper psutil funcsigs configparser From 8231470cd4cb7205e6a8563f28ed3558af154120 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 15 Feb 2017 10:44:17 -0500 Subject: [PATCH 11/44] fix: use _outputs() --- nipype/interfaces/freesurfer/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 0566a67647..d616c622ee 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1542,7 +1542,7 @@ def _gen_filename(self): return self._gen_fname(self.inputs.in_file, suffix='_output') def _list_outputs(self): - outputs = self.output_spec().get() + outputs = self._outputs().get() if not isdefined(self.inputs.out_file): outputs["out_file"] = self._gen_filename() else: From 8d935fb4205c354a383af556a83122c442ace3aa Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 15 Feb 2017 13:10:17 -0500 Subject: [PATCH 12/44] fix: removed list outputs and test changes --- nipype/interfaces/freesurfer/preprocess.py | 13 ------------- .../interfaces/freesurfer/tests/test_preprocess.py | 4 ++-- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index d616c622ee..3ebc26f23a 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1536,19 +1536,6 @@ class MNIBiasCorrection(FSCommand): input_spec = MNIBiasCorrectionInputSpec output_spec = MNIBiasCorrectionOutputSpec - def _gen_filename(self): - # if outfile was not defined - if not isdefined(self.inputs.out_file): - return self._gen_fname(self.inputs.in_file, - suffix='_output') - def _list_outputs(self): - outputs = self._outputs().get() - if not isdefined(self.inputs.out_file): - outputs["out_file"] = self._gen_filename() - else: - outputs["out_file"] = os.path.abspath(self.inputs.out_file) - return outputs - class WatershedSkullStripInputSpec(FSTraitedSpec): # required diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index fbca79a22e..60a51e3a86 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -100,12 +100,12 @@ def test_mandatory_outvol(create_files_in_directory): # test with minimal args mni.inputs.in_file = filelist[0] assert mni.cmdline == ('mri_nu_correct.mni --i %s --o %s_output.mgz' - % (filelist[0], filelist[0].replace('.mgz', '')) + % (filelist[0], filelist[0].replace('.mgz', ''))) # test with custom outfile mni.inputs.out_file = 'new_corrected_file.mgz' assert mni.cmdline == ('mri_nu_correct.mni --i %s --o new_corrected_file.mgz' - % (filelist[0]) + % (filelist[0])) # constructor based tests mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], From ba1a86319d0cb1f8ef6f86dc70f61decbce2a428 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Thu, 16 Feb 2017 14:22:12 -0500 Subject: [PATCH 13/44] removed genfile --- nipype/interfaces/freesurfer/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 4be3185644..c474d7616d 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -1477,7 +1477,7 @@ class MNIBiasCorrectionInputSpec(FSTraitedSpec): in_file = File(exists=True, mandatory=True, argstr="--i %s", desc="input volume. Input can be any format accepted by mri_convert.") # optional - out_file = File(argstr="--o %s", name_source=['in_file'], genfile=True, + out_file = File(argstr="--o %s", name_source=['in_file'], name_template='%s_output', hash_files=False, keep_extension=True, desc="output volume. Output can be any format accepted by mri_convert. " + "If the output format is COR, then the directory must exist.") From 8c831f824df6fdac6dfe5e220d0b2c647607d2d1 Mon Sep 17 00:00:00 2001 From: Chris Gorgolewski Date: Wed, 22 Feb 2017 17:54:39 -0800 Subject: [PATCH 14/44] added non steady state detector --- nipype/algorithms/confounds.py | 73 +++++++++++++++++++++++ nipype/algorithms/tests/test_confounds.py | 10 +++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/nipype/algorithms/confounds.py b/nipype/algorithms/confounds.py index c6503c703a..809f527584 100644 --- a/nipype/algorithms/confounds.py +++ b/nipype/algorithms/confounds.py @@ -561,6 +561,79 @@ def _list_outputs(self): outputs['detrended_file'] = op.abspath(self.inputs.detrended_file) return outputs + +class NonSteadyStateDetectorInputSpec(BaseInterfaceInputSpec): + in_file = File(exists=True, mandatory=True, desc='4D NIFTI EPI file') + + +class NonSteadyStateDetectorOutputSpec(TraitedSpec): + n_volumes_to_discard = traits.Int(desc='Number of non-steady state volumes' + 'detected in the beginning of the scan.') + + +class NonSteadyStateDetector(BaseInterface): + """ + Returns the number of non-steady state volumes detected at the beginning + of the scan. + """ + + input_spec = NonSteadyStateDetectorInputSpec + output_spec = NonSteadyStateDetectorOutputSpec + + def _run_interface(self, runtime): + in_nii = nb.load(self.inputs.in_plots) + global_signal = in_nii.get_data()[:,:,:,:50].mean(axis=0).mean(axis=0).mean(axis=0) + + self._results = { + 'out_file': _is_outlier(global_signal) + } + + return runtime + + def _list_outputs(self): + return self._results + +def _is_outlier(points, thresh=3.5): + """ + Returns a boolean array with True if points are outliers and False + otherwise. + + Parameters: + ----------- + points : An numobservations by numdimensions array of observations + thresh : The modified z-score to use as a threshold. Observations with + a modified z-score (based on the median absolute deviation) greater + than this value will be classified as outliers. + + Returns: + -------- + mask : A numobservations-length boolean array. + + References: + ---------- + Boris Iglewicz and David Hoaglin (1993), "Volume 16: How to Detect and + Handle Outliers", The ASQC Basic References in Quality Control: + Statistical Techniques, Edward F. Mykytka, Ph.D., Editor. + """ + if len(points.shape) == 1: + points = points[:, None] + median = np.median(points, axis=0) + diff = np.sum((points - median) ** 2, axis=-1) + diff = np.sqrt(diff) + med_abs_deviation = np.median(diff) + + modified_z_score = 0.6745 * diff / med_abs_deviation + + timepoints_to_discard = 0 + for i in range(len(modified_z_score)): + if modified_z_score[i] <= thresh: + break + else: + timepoints_to_discard += 1 + + return timepoints_to_discard + + def regress_poly(degree, data, remove_mean=True, axis=-1): ''' returns data with degree polynomial regressed out. Be default it is calculated along the last axis (usu. time). diff --git a/nipype/algorithms/tests/test_confounds.py b/nipype/algorithms/tests/test_confounds.py index a1d6ec9557..db7c20f3ee 100644 --- a/nipype/algorithms/tests/test_confounds.py +++ b/nipype/algorithms/tests/test_confounds.py @@ -6,7 +6,8 @@ import pytest from nipype.testing import example_data -from nipype.algorithms.confounds import FramewiseDisplacement, ComputeDVARS +from nipype.algorithms.confounds import FramewiseDisplacement, ComputeDVARS, \ + _is_outlier import numpy as np @@ -45,3 +46,10 @@ def test_dvars(tmpdir): dv1 = np.loadtxt(res.outputs.out_std) assert (np.abs(dv1 - ground_truth).sum()/ len(dv1)) < 0.05 + + +def test_outliers(tmpdir): + in_data = np.random.randn(100) + in_data[0] += 10 + + assert _is_outlier(in_data) == 1 From d9fa4f67840565901a2f24b3079530dbc271bedb Mon Sep 17 00:00:00 2001 From: Chris Gorgolewski Date: Wed, 22 Feb 2017 17:56:16 -0800 Subject: [PATCH 15/44] [skip ci] changelog --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 52b2c8f00b..fddecb65c9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ Upcoming release 0.13 ===================== +* ENH: Added non-steady state detector for EPI data (https://github.com/nipy/nipype/pull/1839) * ENH: Refactoring of nipype.interfaces.utility (https://github.com/nipy/nipype/pull/1828) * FIX: CircleCI were failing silently. Some fixes to tests (https://github.com/nipy/nipype/pull/1833) * FIX: Issues in Docker image permissions, and docker documentation (https://github.com/nipy/nipype/pull/1825) From e1ca94201123599af997d7090c51a6d1eb06cb8e Mon Sep 17 00:00:00 2001 From: Chris Gorgolewski Date: Thu, 23 Feb 2017 10:10:45 -0800 Subject: [PATCH 16/44] fixed a botched merge --- nipype/algorithms/tests/test_confounds.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nipype/algorithms/tests/test_confounds.py b/nipype/algorithms/tests/test_confounds.py index a0e3a19878..02f5d123b9 100644 --- a/nipype/algorithms/tests/test_confounds.py +++ b/nipype/algorithms/tests/test_confounds.py @@ -44,8 +44,6 @@ def test_dvars(tmpdir): intensity_normalization=0) os.chdir(str(tmpdir)) res = dvars.run() - dv1 = np.loadtxt(res.outputs.out_std) - assert (np.abs(dv1 - ground_truth).sum()/ len(dv1)) < 0.05 dv1 = np.loadtxt(res.outputs.out_all, skiprows=1) assert (np.abs(dv1[:, 0] - ground_truth[:, 0]).sum()/ len(dv1)) < 0.05 From 23882e24e4167f927e6a1c56601fb70e4663c979 Mon Sep 17 00:00:00 2001 From: "Alexandre M. S" Date: Fri, 24 Feb 2017 15:10:59 +0100 Subject: [PATCH 17/44] remove unused node in FSL dmri workflow --- nipype/workflows/dmri/fsl/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nipype/workflows/dmri/fsl/utils.py b/nipype/workflows/dmri/fsl/utils.py index 9c0ba6ab32..d2ea118a9a 100644 --- a/nipype/workflows/dmri/fsl/utils.py +++ b/nipype/workflows/dmri/fsl/utils.py @@ -96,7 +96,6 @@ def dwi_flirt(name='DWICoregistration', excl_nodiff=False, dilate = pe.Node(fsl.maths.MathsCommand( nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') - pick_ref = pe.Node(niu.Select(), name='Pick_b0') n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias') enhb0 = pe.Node(niu.Function( input_names=['in_file', 'in_mask', 'clip_limit'], From 2f8168cd5b4ce28d4f9697791882999ea8e4191e Mon Sep 17 00:00:00 2001 From: Horea Christian Date: Fri, 24 Feb 2017 21:45:17 +0100 Subject: [PATCH 18/44] added package and handle to extra_requires --- nipype/info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/info.py b/nipype/info.py index 66dd7f5603..c3a2fb8d74 100644 --- a/nipype/info.py +++ b/nipype/info.py @@ -164,6 +164,7 @@ def get_nipype_gitversion(): 'fmri': ['nitime', 'nilearn', 'dipy', 'nipy', 'matplotlib'], 'profiler': ['psutil'], 'duecredit': ['duecredit'], + 'xvfbwrapper': ['xvfbwrapper'], # 'mesh': ['mayavi'] # Enable when it works } @@ -171,4 +172,3 @@ def get_nipype_gitversion(): EXTRA_REQUIRES['all'] = [val for _, val in list(EXTRA_REQUIRES.items())] STATUS = 'stable' - From 9e4a94d3d62c64b7a8efd18fdade0285472c99e5 Mon Sep 17 00:00:00 2001 From: MANDY RENFRO Date: Sat, 25 Feb 2017 14:54:37 -0500 Subject: [PATCH 19/44] add documentation & doc tests to fsl preprocess --- .cache/v/cache/lastfailed | 4 + README.rst | 4 +- nipype/algorithms/tests/test_auto_CompCor.py | 37 ---- .../tests/test_auto_ComputeDVARS.py | 2 + nipype/algorithms/tests/test_auto_ErrorMap.py | 35 ---- .../tests/test_auto_FramewiseDisplacement.py | 2 + nipype/algorithms/tests/test_auto_Overlap.py | 47 ----- nipype/algorithms/tests/test_auto_TSNR.py | 43 ----- .../freesurfer/tests/test_auto_BBRegister.py | 1 + nipype/interfaces/fsl/preprocess.py | 49 ++++-- .../fsl/tests/test_auto_ApplyXFM.py | 164 ------------------ nipype/interfaces/fsl/tests/test_maths.py | 2 +- nipype/pipeline/engine/tests/test_engine.py | 16 +- nipype/testing/data/ev_test_condition_0_1.txt | 2 + nipype/utils/tests/test_filemanip.py | 2 +- 15 files changed, 53 insertions(+), 357 deletions(-) create mode 100644 .cache/v/cache/lastfailed delete mode 100644 nipype/algorithms/tests/test_auto_CompCor.py delete mode 100644 nipype/algorithms/tests/test_auto_ErrorMap.py delete mode 100644 nipype/algorithms/tests/test_auto_Overlap.py delete mode 100644 nipype/algorithms/tests/test_auto_TSNR.py delete mode 100644 nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py create mode 100644 nipype/testing/data/ev_test_condition_0_1.txt diff --git a/.cache/v/cache/lastfailed b/.cache/v/cache/lastfailed new file mode 100644 index 0000000000..e5829d176c --- /dev/null +++ b/.cache/v/cache/lastfailed @@ -0,0 +1,4 @@ +{ + "nipype/pipeline/engine/tests/test_engine.py::test_deep_nested_write_graph_runs": true, + "nipype/pipeline/engine/tests/test_engine.py::test_write_graph_runs": true +} \ No newline at end of file diff --git a/README.rst b/README.rst index 8eb7b3e0c0..8f03485a8a 100644 --- a/README.rst +++ b/README.rst @@ -78,8 +78,8 @@ Support and Communication ------------------------- If you have a problem or would like to ask a question about how to do something in Nipype please open an issue to -`NeuroStars.org `_ with a *nipype* tag. `NeuroStars.org `_ is a -platform similar to StackOverflow but dedicated to neuroinformatics. +`NeuroStars.org `_ with a *nipype* tag. `NeuroStars.org `_ is a +platform similar to StackOverflow but dedicated to neuroinformatics. To participate in the Nipype development related discussions please use the following mailing list:: diff --git a/nipype/algorithms/tests/test_auto_CompCor.py b/nipype/algorithms/tests/test_auto_CompCor.py deleted file mode 100644 index 12cec2ebb0..0000000000 --- a/nipype/algorithms/tests/test_auto_CompCor.py +++ /dev/null @@ -1,37 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..confounds import CompCor - - -def test_CompCor_inputs(): - input_map = dict(components_file=dict(usedefault=True, - ), - header=dict(), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - mask_file=dict(), - num_components=dict(usedefault=True, - ), - realigned_file=dict(mandatory=True, - ), - regress_poly_degree=dict(usedefault=True, - ), - use_regress_poly=dict(usedefault=True, - ), - ) - inputs = CompCor.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_CompCor_outputs(): - output_map = dict(components_file=dict(), - ) - outputs = CompCor.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/algorithms/tests/test_auto_ComputeDVARS.py b/nipype/algorithms/tests/test_auto_ComputeDVARS.py index 9a52898fc7..7c59f851d1 100644 --- a/nipype/algorithms/tests/test_auto_ComputeDVARS.py +++ b/nipype/algorithms/tests/test_auto_ComputeDVARS.py @@ -17,6 +17,8 @@ def test_ComputeDVARS_inputs(): ), in_mask=dict(mandatory=True, ), + intensity_normalization=dict(usedefault=True, + ), remove_zerovariance=dict(usedefault=True, ), save_all=dict(usedefault=True, diff --git a/nipype/algorithms/tests/test_auto_ErrorMap.py b/nipype/algorithms/tests/test_auto_ErrorMap.py deleted file mode 100644 index f3d19c5690..0000000000 --- a/nipype/algorithms/tests/test_auto_ErrorMap.py +++ /dev/null @@ -1,35 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..metrics import ErrorMap - - -def test_ErrorMap_inputs(): - input_map = dict(ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_ref=dict(mandatory=True, - ), - in_tst=dict(mandatory=True, - ), - mask=dict(), - metric=dict(mandatory=True, - usedefault=True, - ), - out_map=dict(), - ) - inputs = ErrorMap.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_ErrorMap_outputs(): - output_map = dict(distance=dict(), - out_map=dict(), - ) - outputs = ErrorMap.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/algorithms/tests/test_auto_FramewiseDisplacement.py b/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py index da1dec59d6..e230992eec 100644 --- a/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py +++ b/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py @@ -19,6 +19,8 @@ def test_FramewiseDisplacement_inputs(): ), out_file=dict(usedefault=True, ), + parameter_source=dict(mandatory=True, + ), radius=dict(usedefault=True, ), save_plot=dict(usedefault=True, diff --git a/nipype/algorithms/tests/test_auto_Overlap.py b/nipype/algorithms/tests/test_auto_Overlap.py deleted file mode 100644 index dcabbec296..0000000000 --- a/nipype/algorithms/tests/test_auto_Overlap.py +++ /dev/null @@ -1,47 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..misc import Overlap - - -def test_Overlap_inputs(): - input_map = dict(bg_overlap=dict(mandatory=True, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - mask_volume=dict(), - out_file=dict(usedefault=True, - ), - vol_units=dict(mandatory=True, - usedefault=True, - ), - volume1=dict(mandatory=True, - ), - volume2=dict(mandatory=True, - ), - weighting=dict(usedefault=True, - ), - ) - inputs = Overlap.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_Overlap_outputs(): - output_map = dict(dice=dict(), - diff_file=dict(), - jaccard=dict(), - labels=dict(), - roi_di=dict(), - roi_ji=dict(), - roi_voldiff=dict(), - volume_difference=dict(), - ) - outputs = Overlap.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/algorithms/tests/test_auto_TSNR.py b/nipype/algorithms/tests/test_auto_TSNR.py deleted file mode 100644 index d906d39e3f..0000000000 --- a/nipype/algorithms/tests/test_auto_TSNR.py +++ /dev/null @@ -1,43 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..misc import TSNR - - -def test_TSNR_inputs(): - input_map = dict(detrended_file=dict(hash_files=False, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(mandatory=True, - ), - mean_file=dict(hash_files=False, - usedefault=True, - ), - regress_poly=dict(), - stddev_file=dict(hash_files=False, - usedefault=True, - ), - tsnr_file=dict(hash_files=False, - usedefault=True, - ), - ) - inputs = TSNR.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_TSNR_outputs(): - output_map = dict(detrended_file=dict(), - mean_file=dict(), - stddev_file=dict(), - tsnr_file=dict(), - ) - outputs = TSNR.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/freesurfer/tests/test_auto_BBRegister.py b/nipype/interfaces/freesurfer/tests/test_auto_BBRegister.py index 8712c27bd5..94ef2446df 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_BBRegister.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_BBRegister.py @@ -18,6 +18,7 @@ def test_BBRegister_inputs(): usedefault=True, ), init=dict(argstr='--init-%s', + mandatory=True, xor=['init_reg_file'], ), init_reg_file=dict(argstr='--init-reg %s', diff --git a/nipype/interfaces/fsl/preprocess.py b/nipype/interfaces/fsl/preprocess.py index eaab2a830e..af2ea7c04f 100644 --- a/nipype/interfaces/fsl/preprocess.py +++ b/nipype/interfaces/fsl/preprocess.py @@ -118,15 +118,17 @@ class BET(FSLCommand): """Use FSL BET command for skull stripping. For complete details, see the `BET Documentation. - `_ + `_ Examples -------- >>> from nipype.interfaces import fsl - >>> from nipype.testing import example_data >>> btr = fsl.BET() - >>> btr.inputs.in_file = example_data('structural.nii') + >>> btr.inputs.in_file = 'structural.nii' >>> btr.inputs.frac = 0.7 + >>> btr.inputs.out_file = 'brain_anat.nii' + >>> btr.cmdline # doctest: +ALLOW_UNICODE + 'bet structural.nii brain_anat.nii -f 0.70' >>> res = btr.run() # doctest: +SKIP """ @@ -275,7 +277,7 @@ class FASTOutputSpec(TraitedSpec): mixeltype = File(desc="path/name of mixeltype volume file _mixeltype") - partial_volume_map = File(desc="path/name of partial volume file _pveseg") + partial_volume_map = File(desc='path/name of partial volume file _pveseg') partial_volume_files = OutputMultiPath(File( desc='path/name of partial volumes files one for each class, _pve_x')) @@ -288,18 +290,17 @@ class FAST(FSLCommand): """ Use FSL FAST for segmenting and bias correction. For complete details, see the `FAST Documentation. - `_ + `_ Examples -------- >>> from nipype.interfaces import fsl - >>> from nipype.testing import example_data - - Assign options through the ``inputs`` attribute: - >>> fastr = fsl.FAST() - >>> fastr.inputs.in_files = example_data('structural.nii') - >>> out = fastr.run() #doctest: +SKIP + >>> fastr.inputs.in_files = 'structural.nii' + >>> fastr.inputs.out_basename = 'fast_' + >>> fastr.cmdline # doctest: +ALLOW_UNICODE + 'fast -o fast_ -S 1 structural.nii' + >>> out = fastr.run() # doctest: +SKIP """ _cmd = 'fast' @@ -308,12 +309,12 @@ class FAST(FSLCommand): def _format_arg(self, name, spec, value): # first do what should be done in general - formated = super(FAST, self)._format_arg(name, spec, value) + formatted = super(FAST, self)._format_arg(name, spec, value) if name == 'in_files': # FAST needs the -S parameter value to correspond to the number # of input images, otherwise it will ignore all but the first - formated = "-S %d %s" % (len(value), formated) - return formated + formatted = "-S %d %s" % (len(value), formatted) + return formatted def _list_outputs(self): outputs = self.output_spec().get() @@ -526,7 +527,7 @@ class FLIRT(FSLCommand): """Use FSL FLIRT for coregistration. For complete details, see the `FLIRT Documentation. - `_ + `_ To print out the command line help, use: fsl.FLIRT().inputs_help() @@ -665,14 +666,18 @@ class MCFLIRT(FSLCommand): """Use FSL MCFLIRT to do within-modality motion correction. For complete details, see the `MCFLIRT Documentation. - `_ + `_ Examples -------- >>> from nipype.interfaces import fsl - >>> from nipype.testing import example_data - >>> mcflt = fsl.MCFLIRT(in_file=example_data('functional.nii'), cost='mutualinfo') - >>> res = mcflt.run() # doctest: +SKIP + >>> mcflt = fsl.MCFLIRT() + >>> mcflt.inputs.in_file = 'functional.nii' + >>> mcflt.inputs.cost = 'mutualinfo' + >>> mcflt.inputs.out_file = 'moco.nii' + >>> mcflt.cmdline # doctest: +ALLOW_UNICODE + 'mcflirt -in functional.nii -cost mutualinfo -out moco.nii' + >>> res = mcflt.run() # doctest: +SKIP """ _cmd = 'mcflirt' @@ -918,6 +923,9 @@ class FNIRTOutputSpec(TraitedSpec): class FNIRT(FSLCommand): """Use FSL FNIRT for non-linear registration. + For complete details, see the `MCFLIRT Documentation. + `_ + Examples -------- >>> from nipype.interfaces import fsl @@ -1218,6 +1226,9 @@ class SUSANOutputSpec(TraitedSpec): class SUSAN(FSLCommand): """ use FSL SUSAN to perform smoothing + For complete details, see the `MCFLIRT Documentation. + `_ + Examples -------- diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py deleted file mode 100644 index cf67b12b2b..0000000000 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXFM.py +++ /dev/null @@ -1,164 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..preprocess import ApplyXFM - - -def test_ApplyXFM_inputs(): - input_map = dict(angle_rep=dict(argstr='-anglerep %s', - ), - apply_isoxfm=dict(argstr='-applyisoxfm %f', - xor=['apply_xfm'], - ), - apply_xfm=dict(argstr='-applyxfm', - requires=['in_matrix_file'], - usedefault=True, - ), - args=dict(argstr='%s', - ), - bbrslope=dict(argstr='-bbrslope %f', - min_ver='5.0.0', - ), - bbrtype=dict(argstr='-bbrtype %s', - min_ver='5.0.0', - ), - bgvalue=dict(argstr='-setbackground %f', - ), - bins=dict(argstr='-bins %d', - ), - coarse_search=dict(argstr='-coarsesearch %d', - units='degrees', - ), - cost=dict(argstr='-cost %s', - ), - cost_func=dict(argstr='-searchcost %s', - ), - datatype=dict(argstr='-datatype %s', - ), - display_init=dict(argstr='-displayinit', - ), - dof=dict(argstr='-dof %d', - ), - echospacing=dict(argstr='-echospacing %f', - min_ver='5.0.0', - ), - environ=dict(nohash=True, - usedefault=True, - ), - fieldmap=dict(argstr='-fieldmap %s', - min_ver='5.0.0', - ), - fieldmapmask=dict(argstr='-fieldmapmask %s', - min_ver='5.0.0', - ), - fine_search=dict(argstr='-finesearch %d', - units='degrees', - ), - force_scaling=dict(argstr='-forcescaling', - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(argstr='-in %s', - mandatory=True, - position=0, - ), - in_matrix_file=dict(argstr='-init %s', - ), - in_weight=dict(argstr='-inweight %s', - ), - interp=dict(argstr='-interp %s', - ), - min_sampling=dict(argstr='-minsampling %f', - units='mm', - ), - no_clamp=dict(argstr='-noclamp', - ), - no_resample=dict(argstr='-noresample', - ), - no_resample_blur=dict(argstr='-noresampblur', - ), - no_search=dict(argstr='-nosearch', - ), - out_file=dict(argstr='-out %s', - hash_files=False, - name_source=['in_file'], - name_template='%s_flirt', - position=2, - ), - out_log=dict(keep_extension=True, - name_source=['in_file'], - name_template='%s_flirt.log', - requires=['save_log'], - ), - out_matrix_file=dict(argstr='-omat %s', - hash_files=False, - keep_extension=True, - name_source=['in_file'], - name_template='%s_flirt.mat', - position=3, - ), - output_type=dict(), - padding_size=dict(argstr='-paddingsize %d', - units='voxels', - ), - pedir=dict(argstr='-pedir %d', - min_ver='5.0.0', - ), - ref_weight=dict(argstr='-refweight %s', - ), - reference=dict(argstr='-ref %s', - mandatory=True, - position=1, - ), - rigid2D=dict(argstr='-2D', - ), - save_log=dict(), - schedule=dict(argstr='-schedule %s', - ), - searchr_x=dict(argstr='-searchrx %s', - units='degrees', - ), - searchr_y=dict(argstr='-searchry %s', - units='degrees', - ), - searchr_z=dict(argstr='-searchrz %s', - units='degrees', - ), - sinc_width=dict(argstr='-sincwidth %d', - units='voxels', - ), - sinc_window=dict(argstr='-sincwindow %s', - ), - terminal_output=dict(nohash=True, - ), - uses_qform=dict(argstr='-usesqform', - ), - verbose=dict(argstr='-verbose %d', - ), - wm_seg=dict(argstr='-wmseg %s', - min_ver='5.0.0', - ), - wmcoords=dict(argstr='-wmcoords %s', - min_ver='5.0.0', - ), - wmnorms=dict(argstr='-wmnorms %s', - min_ver='5.0.0', - ), - ) - inputs = ApplyXFM.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_ApplyXFM_outputs(): - output_map = dict(out_file=dict(), - out_log=dict(), - out_matrix_file=dict(), - ) - outputs = ApplyXFM.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/fsl/tests/test_maths.py b/nipype/interfaces/fsl/tests/test_maths.py index e2c6c93bb7..408a74712f 100644 --- a/nipype/interfaces/fsl/tests/test_maths.py +++ b/nipype/interfaces/fsl/tests/test_maths.py @@ -12,7 +12,7 @@ from nipype.interfaces.fsl import no_fsl import pytest -from nipype.testing.fixtures import create_files_in_directory_plus_output_type +from nipype.testing.fixtures import create_files_in_directory_plus_output_type @pytest.mark.skipif(no_fsl(), reason="fsl is not installed") diff --git a/nipype/pipeline/engine/tests/test_engine.py b/nipype/pipeline/engine/tests/test_engine.py index 32271799b8..43345bb8c6 100644 --- a/nipype/pipeline/engine/tests/test_engine.py +++ b/nipype/pipeline/engine/tests/test_engine.py @@ -326,14 +326,14 @@ def test_doubleconnect(): flow1 = pe.Workflow(name='test') flow1.connect(a, 'a', b, 'a') x = lambda: flow1.connect(a, 'b', b, 'a') - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: x() assert "Trying to connect" in str(excinfo.value) c = pe.Node(IdentityInterface(fields=['a', 'b']), name='c') flow1 = pe.Workflow(name='test2') x = lambda: flow1.connect([(a, c, [('b', 'b')]), (b, c, [('a', 'b')])]) - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: x() assert "Trying to connect" in str(excinfo.value) @@ -481,7 +481,7 @@ def func1(in1): name='n1') n2.inputs.in1 = [[1, [2]], 3, [4, 5]] - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: n2.run() assert "can only concatenate list" in str(excinfo.value) @@ -518,7 +518,7 @@ def func2(a): # create dummy distributed plugin class from nipype.pipeline.plugins.base import DistributedPluginBase - # create a custom exception + # create a custom exception class EngineTestException(Exception): pass @@ -529,7 +529,7 @@ def _submit_job(self, node, updatehash=False): # check if a proper exception is raised with pytest.raises(EngineTestException) as excinfo: w1.run(plugin=RaiseError()) - assert 'Submit called' == str(excinfo.value) + assert 'Submit called' == str(excinfo.value) # rerun to ensure we have outputs w1.run(plugin='Linear') @@ -539,7 +539,7 @@ def _submit_job(self, node, updatehash=False): 'crashdump_dir': wd} w1.run(plugin=RaiseError()) - + def test_old_config(tmpdir): wd = str(tmpdir) @@ -607,7 +607,7 @@ def func1(in1): w1.config['execution'].update(**{'stop_on_first_rerun': True}) w1.run() - + def test_parameterize_dirs_false(tmpdir): from ....interfaces.utility import IdentityInterface @@ -665,7 +665,7 @@ def func1(in1): # test running the workflow on serial conditions w1.run(plugin='MultiProc') - + def test_write_graph_runs(tmpdir): os.chdir(str(tmpdir)) diff --git a/nipype/testing/data/ev_test_condition_0_1.txt b/nipype/testing/data/ev_test_condition_0_1.txt new file mode 100644 index 0000000000..a1399761f5 --- /dev/null +++ b/nipype/testing/data/ev_test_condition_0_1.txt @@ -0,0 +1,2 @@ +0.000000 10.000000 1.000000 +10.000000 10.000000 1.000000 diff --git a/nipype/utils/tests/test_filemanip.py b/nipype/utils/tests/test_filemanip.py index 644a055f4b..bf321c5b9c 100644 --- a/nipype/utils/tests/test_filemanip.py +++ b/nipype/utils/tests/test_filemanip.py @@ -306,7 +306,7 @@ def touch(fname): else: assert False, "Should raise OSError on missing dependency" - shutil.rmtree(tmpdir) + shutil.rmtree(tmpdir) def test_json(): From e450340a9c6b1668a617108d3372208e8f3bf68c Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Thu, 2 Mar 2017 07:35:11 -0500 Subject: [PATCH 20/44] Update README.rst --- README.rst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/README.rst b/README.rst index 8eb7b3e0c0..fd001f2581 100644 --- a/README.rst +++ b/README.rst @@ -117,16 +117,3 @@ Currently Nipype consists of the following files and directories: setup.py Script for building and installing NIPYPE. -License information -------------------- - -We use the 3-clause BSD license; the full license is in the file ``LICENSE`` in -the nipype distribution. - -There are interfaces to some GNU code but these are entirely optional. - -All trademarks referenced herein are property of their respective -holders. - -Copyright (c) 2009-2015, NIPY Developers -All rights reserved. From 4f8d29a2c16fd19ae34d448ca72b58caffe2bf3e Mon Sep 17 00:00:00 2001 From: oesteban Date: Thu, 2 Mar 2017 09:59:18 -0800 Subject: [PATCH 21/44] [FIX] CircleCI tests - error codes are not propagated The former structure of the tests.sh file in which all the tests are called did not exit with error if one of the test commands errored, since the last exit code was from codecov, and no exit code tracking or propagation was done. This PR fixes that issue. Additionally, the scripts related to CircleCI have been split up into a new .circle/ folder. --- .circle/codecov.sh | 22 ++++++++++++++++++++++ {docker/files => .circle}/tests.sh | 25 +++++++------------------ .dockerignore | 4 +++- circle.yml | 11 ++++++++--- docker/files/teardown.sh | 15 --------------- 5 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 .circle/codecov.sh rename {docker/files => .circle}/tests.sh (82%) delete mode 100644 docker/files/teardown.sh diff --git a/.circle/codecov.sh b/.circle/codecov.sh new file mode 100644 index 0000000000..6d946c27a3 --- /dev/null +++ b/.circle/codecov.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +# This script pull all coverage files into the $CIRCLE_TEST_REPORTS folder +# and sends data to codecov. +# +# +set -u +set -e + +mkdir -p ${CIRCLE_TEST_REPORTS}/ +for report in $( ls ~/scratch/*.xml ); do + rname=$( basename $report ) + cp ${report} ${CIRCLE_TEST_REPORTS}/${rname:: -4}_${CIRCLE_NODE_INDEX}.xml +done + +# Send coverage data to codecov.io +curl -so codecov.io https://codecov.io/bash +chmod 755 codecov.io +find "${CIRCLE_TEST_REPORTS}/" -name 'coverage*.xml' -print0 | \ + xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F unittests +find "${CIRCLE_TEST_REPORTS}/" -name 'smoketests*.xml' -print0 | \ + xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F smoketests \ No newline at end of file diff --git a/docker/files/tests.sh b/.circle/tests.sh similarity index 82% rename from docker/files/tests.sh rename to .circle/tests.sh index 3b43003294..21655c3e6b 100644 --- a/docker/files/tests.sh +++ b/.circle/tests.sh @@ -14,15 +14,15 @@ fi # They may need to be rebalanced in the future. case ${CIRCLE_NODE_INDEX} in 0) - docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh fmri_spm_dartel Linear /root/examples/ level1 && \ - docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh fmri_spm_dartel Linear /root/examples/ l2pipeline - ;; - 1) - docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh test_spm Linear /root/examples/ workflow3d && \ - docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh test_spm Linear /root/examples/ workflow4d && \ docker run --rm -it -e FSL_COURSE_DATA="/root/examples/nipype-fsl_course_data" -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /root/src/nipype nipype/nipype_test:py27 /usr/bin/run_pytests.sh py27 && \ docker run --rm -it -e FSL_COURSE_DATA="/root/examples/nipype-fsl_course_data" -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /root/src/nipype nipype/nipype_test:py35 /usr/bin/run_pytests.sh py35 && \ - docker run --rm -it -v $SCRATCH:/scratch -w /root/src/nipype/doc nipype/nipype_test:py35 /usr/bin/run_builddocs.sh + docker run --rm -it -v $SCRATCH:/scratch -w /root/src/nipype/doc nipype/nipype_test:py35 /usr/bin/run_builddocs.sh && \ + docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh test_spm Linear /root/examples/ workflow3d && \ + docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh test_spm Linear /root/examples/ workflow4d + ;; + 1) + docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh fmri_spm_dartel Linear /root/examples/ level1 && \ + docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh fmri_spm_dartel Linear /root/examples/ l2pipeline ;; 2) docker run --rm -it -e NIPYPE_NUMBER_OF_CPUS=4 -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py27 /usr/bin/run_examples.sh fmri_spm_nested MultiProc /root/examples/ level1 && \ @@ -34,14 +34,3 @@ case ${CIRCLE_NODE_INDEX} in docker run --rm -it -v $HOME/examples:/root/examples:ro -v $SCRATCH:/scratch -w /scratch nipype/nipype_test:py35 /usr/bin/run_examples.sh fmri_fsl_reuse Linear /root/examples/ level1_workflow ;; esac - -# Put the artifacts in place -bash docker/files/teardown.sh - -# Send coverage data to codecov.io -curl -so codecov.io https://codecov.io/bash -chmod 755 codecov.io -find "${CIRCLE_TEST_REPORTS}/pytest" -name 'coverage*.xml' -print0 | \ - xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F unittests -find "${CIRCLE_TEST_REPORTS}/pytest" -name 'smoketests*.xml' -print0 | \ - xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F smoketests diff --git a/.dockerignore b/.dockerignore index 381de568df..2140bfcb66 100644 --- a/.dockerignore +++ b/.dockerignore @@ -23,11 +23,13 @@ src/ # other docs/**/* docs/ +.circle/**/* +.circle/ +circle.yml .coverage .coveragerc codecov.yml rtd_requirements.txt -circle.yml Vagrantfile .travis.yml .noserc diff --git a/circle.yml b/circle.yml index db67dc81a2..9bbfa82733 100644 --- a/circle.yml +++ b/circle.yml @@ -43,23 +43,28 @@ dependencies: test: override: - - bash docker/files/tests.sh : + - bash .circle/tests.sh : timeout: 7200 parallel: true + post: + # Send coverage data to codecov.io + - bash .circle/codecov.sh general: artifacts: - - "~/docs" - - "~/logs" + - "~/scratch/docs" + - "~/scratch/logs" deployment: production: tag: /.*/ commands: + # Deploy to docker hub - if [[ -n "$DOCKER_PASS" ]]; then docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS && docker push nipype/nipype:latest; fi : timeout: 21600 - if [[ -n "$DOCKER_PASS" ]]; then docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS && docker tag nipype/nipype nipype/nipype:$CIRCLE_TAG && docker push nipype/nipype:$CIRCLE_TAG; fi : timeout: 21600 + # Automatic deployment to Pypi: # - printf "[distutils]\nindex-servers =\n pypi\n\n[pypi]\nusername:$PYPI_USER\npassword:$PYPI_PASS\n" > ~/.pypirc # - python setup.py sdist upload -r pypi diff --git a/docker/files/teardown.sh b/docker/files/teardown.sh deleted file mode 100644 index 3712b7ad23..0000000000 --- a/docker/files/teardown.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# -# This script puts all artifacts in place after the smoke tests -# -# -set -u -set -e - -mkdir -p ${CIRCLE_TEST_REPORTS}/pytest -mv ~/scratch/*.xml ${CIRCLE_TEST_REPORTS}/pytest -mkdir -p ~/docs -mv ~/scratch/docs/* ~/docs/ -mkdir -p ~/logs -mv ~/scratch/builddocs.log ~/logs/builddocs.log -mv ~/scratch/logs/* ~/logs/ From 0ce18310c2951b9414d195c4ee7308c029c9d6f4 Mon Sep 17 00:00:00 2001 From: oesteban Date: Thu, 2 Mar 2017 10:10:00 -0800 Subject: [PATCH 22/44] prevent "Error removing intermediate container" during docker build --- circle.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/circle.yml b/circle.yml index 9bbfa82733..6ca801a90d 100644 --- a/circle.yml +++ b/circle.yml @@ -32,11 +32,11 @@ dependencies: - if [[ ! -d ~/examples/feeds ]]; then wget --retry-connrefused --waitretry=5 --read-timeout=20 --timeout=15 -t 0 -q -O fsl-5.0.9-feeds.tar.gz "${DATA_NIPYPE_FSL_FEEDS}" && tar xzf fsl-5.0.9-feeds.tar.gz -C ~/examples/; fi - docker images - sed -i -E "s/(__version__ = )'[A-Za-z0-9.-]+'/\1'$CIRCLE_TAG'/" nipype/info.py - - e=1 && for i in {1..5}; do docker build -t nipype/nipype:latest --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` --build-arg VERSION=$CIRCLE_TAG . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : + - e=1 && for i in {1..5}; do docker build --rm=false -t nipype/nipype:latest --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` --build-arg VERSION=$CIRCLE_TAG . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : timeout: 21600 - - e=1 && for i in {1..5}; do docker build -f docker/Dockerfile_py27 -t nipype/nipype_test:py27 . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : + - e=1 && for i in {1..5}; do docker build --rm=false -f docker/Dockerfile_py27 -t nipype/nipype_test:py27 . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : timeout: 1600 - - e=1 && for i in {1..5}; do docker build -f docker/Dockerfile_py35 -t nipype/nipype_test:py35 . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : + - e=1 && for i in {1..5}; do docker build --rm=false -f docker/Dockerfile_py35 -t nipype/nipype_test:py35 . && e=0 && break || sleep 15; done && [ "$e" -eq "0" ] : timeout: 1600 - docker save -o $HOME/docker/cache.tar nipype/nipype:latest nipype/nipype_test:py27 nipype/nipype_test:py35 : timeout: 6000 From 2d10e28ddd42d4e0b17b6ea900e02f66f98ddc7c Mon Sep 17 00:00:00 2001 From: oesteban Date: Thu, 2 Mar 2017 14:23:37 -0800 Subject: [PATCH 23/44] fix failing test --- .../freesurfer/tests/test_preprocess.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index 60a51e3a86..0729ae6b41 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -98,9 +98,14 @@ def test_mandatory_outvol(create_files_in_directory): with pytest.raises(ValueError): mni.cmdline # test with minimal args - mni.inputs.in_file = filelist[0] - assert mni.cmdline == ('mri_nu_correct.mni --i %s --o %s_output.mgz' - % (filelist[0], filelist[0].replace('.mgz', ''))) + mni.inputs.in_file = filelist[0] + base, ext = os.path.splitext(os.path.basename(filelist[0])) + if ext == '.gz': + base, ext2 = os.path.splitext(base) + ext = ext2 + ext + + assert mni.cmdline == ( + 'mri_nu_correct.mni --i %s --o %s_output.%s' % (filelist[0], base, ext)) # test with custom outfile mni.inputs.out_file = 'new_corrected_file.mgz' @@ -108,8 +113,8 @@ def test_mandatory_outvol(create_files_in_directory): % (filelist[0])) # constructor based tests - mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], + mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_output', iterations=4) - assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.mgz' - % filelist[0]) + assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.%s' + % (filelist[0], ext)) From 76e43921ea4b604d4da41912bde55eb659455e45 Mon Sep 17 00:00:00 2001 From: Chris Gorgolewski Date: Thu, 2 Mar 2017 15:27:56 -0800 Subject: [PATCH 24/44] make outlier testing deterministic --- nipype/algorithms/tests/test_confounds.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nipype/algorithms/tests/test_confounds.py b/nipype/algorithms/tests/test_confounds.py index a4542d75d0..4eaa9dc073 100644 --- a/nipype/algorithms/tests/test_confounds.py +++ b/nipype/algorithms/tests/test_confounds.py @@ -67,6 +67,7 @@ def test_dvars(tmpdir): assert (np.abs(dv1[:, 2] - ground_truth[:, 2]).sum() / len(dv1)) < 0.05 def test_outliers(tmpdir): + np.random.seed(0) in_data = np.random.randn(100) in_data[0] += 10 From 6c60c588c694804930ea6e2312f80830f7b1fe8d Mon Sep 17 00:00:00 2001 From: oesteban Date: Fri, 3 Mar 2017 07:54:16 -0800 Subject: [PATCH 25/44] fix tests --- nipype/interfaces/freesurfer/tests/test_preprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index 0729ae6b41..283ec5d2d1 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -105,7 +105,7 @@ def test_mandatory_outvol(create_files_in_directory): ext = ext2 + ext assert mni.cmdline == ( - 'mri_nu_correct.mni --i %s --o %s_output.%s' % (filelist[0], base, ext)) + 'mri_nu_correct.mni --i %s --o %s_output%s' % (filelist[0], base, ext)) # test with custom outfile mni.inputs.out_file = 'new_corrected_file.mgz' @@ -116,5 +116,5 @@ def test_mandatory_outvol(create_files_in_directory): mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_output', iterations=4) - assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output.%s' + assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output%s' % (filelist[0], ext)) From 14194060f7c2daad3a60629f7ef5e96196bd3514 Mon Sep 17 00:00:00 2001 From: oesteban Date: Fri, 3 Mar 2017 10:06:27 -0800 Subject: [PATCH 26/44] Place CODECOV_TOKEN in main circle.yml, sort out bash settings in circle scripts --- .circle/codecov.sh | 11 +++++++---- .circle/tests.sh | 11 +++++++---- circle.yml | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.circle/codecov.sh b/.circle/codecov.sh index 6d946c27a3..c71cf1c6f5 100644 --- a/.circle/codecov.sh +++ b/.circle/codecov.sh @@ -3,9 +3,11 @@ # This script pull all coverage files into the $CIRCLE_TEST_REPORTS folder # and sends data to codecov. # -# -set -u -set -e + +# Setting # $ help set +set -e # Exit immediately if a command exits with a non-zero status. +set -u # Treat unset variables as an error when substituting. +set -x # Print command traces before executing command. mkdir -p ${CIRCLE_TEST_REPORTS}/ for report in $( ls ~/scratch/*.xml ); do @@ -16,7 +18,8 @@ done # Send coverage data to codecov.io curl -so codecov.io https://codecov.io/bash chmod 755 codecov.io + find "${CIRCLE_TEST_REPORTS}/" -name 'coverage*.xml' -print0 | \ xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F unittests find "${CIRCLE_TEST_REPORTS}/" -name 'smoketests*.xml' -print0 | \ - xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F smoketests \ No newline at end of file + xargs -0 -I file ./codecov.io -f file -t "${CODECOV_TOKEN}" -F smoketests diff --git a/.circle/tests.sh b/.circle/tests.sh index 21655c3e6b..602dddca8b 100644 --- a/.circle/tests.sh +++ b/.circle/tests.sh @@ -1,9 +1,12 @@ #!/bin/bash +# +# Balance nipype testing workflows across CircleCI build nodes +# -set -o nounset -set -o xtrace - -export CODECOV_TOKEN=ac172a50-8e66-42e5-8822-5373fcf54686 +# Setting # $ help set +set -e # Exit immediately if a command exits with a non-zero status. +set -u # Treat unset variables as an error when substituting. +set -x # Print command traces before executing command. if [ "${CIRCLE_NODE_TOTAL:-}" != "4" ]; then echo "These tests were designed to be run at 4x parallelism." diff --git a/circle.yml b/circle.yml index 6ca801a90d..ac27d71a56 100644 --- a/circle.yml +++ b/circle.yml @@ -8,6 +8,7 @@ machine: DATA_NIPYPE_FSL_COURSE: "${OSF_NIPYPE_URL}/57f472cf9ad5a101f977ecfe" DATA_NIPYPE_FSL_FEEDS: "${OSF_NIPYPE_URL}/57f473066c613b01f113e7af" SCRATCH: "$HOME/scratch" + CODECOV_TOKEN: "ac172a50-8e66-42e5-8822-5373fcf54686" services: - docker From 26dfd794c6af270dcc60f5fcd3a6e7ca05a7b6e2 Mon Sep 17 00:00:00 2001 From: oesteban Date: Fri, 3 Mar 2017 13:48:35 -0800 Subject: [PATCH 27/44] fix freesurfer test --- nipype/interfaces/freesurfer/tests/test_preprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/freesurfer/tests/test_preprocess.py b/nipype/interfaces/freesurfer/tests/test_preprocess.py index 283ec5d2d1..deb475a6b4 100644 --- a/nipype/interfaces/freesurfer/tests/test_preprocess.py +++ b/nipype/interfaces/freesurfer/tests/test_preprocess.py @@ -116,5 +116,5 @@ def test_mandatory_outvol(create_files_in_directory): mni2 = freesurfer.MNIBiasCorrection(in_file=filelist[0], out_file='bias_corrected_output', iterations=4) - assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output%s' - % (filelist[0], ext)) + assert mni2.cmdline == ('mri_nu_correct.mni --i %s --n 4 --o bias_corrected_output' + % filelist[0]) From 71c95382d4f337d83e32d7b58de9f441982b8413 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 1 Mar 2017 09:33:19 -0500 Subject: [PATCH 28/44] Add -hires and -expert flags to ReconAll --- nipype/interfaces/freesurfer/preprocess.py | 4 ++++ nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index abc6e5b51d..735169ca91 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -632,6 +632,10 @@ class ReconAllInputSpec(CommandLineInputSpec): desc="Number of processors to use in parallel") parallel = traits.Bool(argstr="-parallel", desc="Enable parallel execution") + hires = traits.Bool(argstr="-hires", min_ver='6.0.0', + desc="Conform to minimum voxel size (for voxels < 1mm)") + expert = File(exists=True, argstr='-expert %s', + desc="Set parameters using expert file") subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False, desc='path to subjects directory', genfile=True) flags = traits.Str(argstr='%s', desc='additional parameters') diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py b/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py index f86d934d7a..b748df7aa9 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py @@ -18,10 +18,15 @@ def test_ReconAll_inputs(): environ=dict(nohash=True, usedefault=True, ), + expert=dict(argstr='-expert %s', + ), flags=dict(argstr='%s', ), hemi=dict(argstr='-hemi %s', ), + hires=dict(argstr='-hires', + min_ver='6.0.0', + ), ignore_exception=dict(nohash=True, usedefault=True, ), From 260a27577dea454640bfc5117e0ad8e53ece02dd Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 1 Mar 2017 21:33:23 -0500 Subject: [PATCH 29/44] Add ExpertOptions interface to freesurfer.utils --- .../tests/test_auto_ExpertOptions.py | 50 ++++++++++++++ nipype/interfaces/freesurfer/utils.py | 65 ++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py b/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py new file mode 100644 index 0000000000..1c62abb937 --- /dev/null +++ b/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py @@ -0,0 +1,50 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..utils import ExpertOptions + + +def test_ExpertOptions_inputs(): + input_map = dict(mri_aparc2aseg=dict(), + mri_ca_label=dict(), + mri_ca_normalize=dict(), + mri_ca_register=dict(), + mri_edit_wm_with_aseg=dict(), + mri_em_register=dict(), + mri_fill=dict(), + mri_mask=dict(), + mri_normalize=dict(), + mri_pretess=dict(), + mri_remove_neck=dict(), + mri_segment=dict(), + mri_segstats=dict(), + mri_tessellate=dict(), + mri_watershed=dict(), + mris_anatomical_stats=dict(), + mris_ca_label=dict(), + mris_fix_topology=dict(), + mris_inflate=dict(), + mris_make_surfaces=dict(), + mris_register=dict(), + mris_smooth=dict(), + mris_sphere=dict(), + mris_surf2vol=dict(), + mrisp_paint=dict(), + out_file=dict(usedefault=True, + ), + talairach=dict(), + ) + inputs = ExpertOptions.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_ExpertOptions_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = ExpertOptions.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/freesurfer/utils.py b/nipype/interfaces/freesurfer/utils.py index fed63e498e..ad5a50a869 100644 --- a/nipype/interfaces/freesurfer/utils.py +++ b/nipype/interfaces/freesurfer/utils.py @@ -18,8 +18,8 @@ import shutil from ...utils.filemanip import fname_presuffix, split_filename -from ..base import (TraitedSpec, File, traits, OutputMultiPath, isdefined, - CommandLine, CommandLineInputSpec) +from ..base import (TraitedSpec, BaseInterface, File, traits, OutputMultiPath, + isdefined, CommandLine, CommandLineInputSpec) from .base import (FSCommand, FSTraitedSpec, FSScriptCommand, FSScriptOutputSpec, FSTraitedSpecOpenMP, FSCommandOpenMP) @@ -2879,3 +2879,64 @@ def _list_outputs(self): outputs = self._outputs().get() outputs["out_file"] = os.path.abspath(self.inputs.out_file) return outputs + + +class ExpertOptionsInputSpec(TraitedSpec): + talairach = traits.String(desc="Flags to pass to talairach commands") + mri_normalize = traits.String(desc="Flags to pass to mri_normalize commands") + mri_watershed = traits.String(desc="Flags to pass to mri_watershed commands") + mri_em_register = traits.String(desc="Flags to pass to mri_em_register commands") + mri_ca_normalize = traits.String(desc="Flags to pass to mri_ca_normalize commands") + mri_ca_register = traits.String(desc="Flags to pass to mri_ca_register commands") + mri_remove_neck = traits.String(desc="Flags to pass to mri_remove_neck commands") + mri_ca_label = traits.String(desc="Flags to pass to mri_ca_label commands") + mri_segstats = traits.String(desc="Flags to pass to mri_segstats commands") + mri_mask = traits.String(desc="Flags to pass to mri_mask commands") + mri_segment = traits.String(desc="Flags to pass to mri_segment commands") + mri_edit_wm_with_aseg = traits.String(desc="Flags to pass to mri_edit_wm_with_aseg commands") + mri_pretess = traits.String(desc="Flags to pass to mri_pretess commands") + mri_fill = traits.String(desc="Flags to pass to mri_fill commands") + mri_tessellate = traits.String(desc="Flags to pass to mri_tessellate commands") + mris_smooth = traits.String(desc="Flags to pass to mri_smooth commands") + mris_inflate = traits.String(desc="Flags to pass to mri_inflate commands") + mris_sphere = traits.String(desc="Flags to pass to mris_sphere commands") + mris_fix_topology = traits.String(desc="Flags to pass to mris_fix_topology commands") + mris_make_surfaces = traits.String(desc="Flags to pass to mris_make_surfaces commands") + mris_surf2vol = traits.String(desc="Flags to pass to mris_surf2vol commands") + mris_register = traits.String(desc="Flags to pass to mris_register commands") + mrisp_paint = traits.String(desc="Flags to pass to mrisp_paint commands") + mris_ca_label = traits.String(desc="Flags to pass to mris_ca_label commands") + mris_anatomical_stats = traits.String(desc="Flags to pass to mris_anatomical_stats commands") + mri_aparc2aseg = traits.String(desc="Flags to pass to mri_aparc2aseg commands") + out_file = File("expert.opts", usedefault=True, desc="Output expert options file") + + +class ExpertOptionsOutputSpec(TraitedSpec): + out_file = File(exists=False, desc="Output expert options file") + + +class ExpertOptions(BaseInterface): + """ + Creates expert options file + https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all#ExpertOptionsFile + """ + input_spec = ExpertOptionsInputSpec + output_spec = ExpertOptionsOutputSpec + + def _list_outputs(self): + outputs = self._outputs().get() + outputs["out_file"] = os.path.abspath(self.inputs.out_file) + return outputs + + def _run_interface(self, runtime): + out_file = self.inputs.out_file + + lines = [] + for binary, args in self.inputs.get().items(): + if binary == 'out_file' or not isdefined(args): + continue + lines.append('{} {}\n'.format(binary, args)) + + with open(out_file, 'w') as fobj: + fobj.write(''.join(lines)) + return runtime From af036f7276769d498c699e30328e1569056c0aa2 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 3 Mar 2017 13:33:37 -0500 Subject: [PATCH 30/44] Accept expert options as a dictionary --- nipype/interfaces/freesurfer/preprocess.py | 9 ++- .../tests/test_auto_ExpertOptions.py | 50 -------------- nipype/interfaces/freesurfer/utils.py | 65 +------------------ 3 files changed, 10 insertions(+), 114 deletions(-) delete mode 100644 nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 735169ca91..4e43a4f03d 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -28,6 +28,7 @@ Directory, InputMultiPath, OutputMultiPath, CommandLine, CommandLineInputSpec, isdefined) +from ..traits_extension import DictStrStr from .base import (FSCommand, FSTraitedSpec, FSTraitedSpecOpenMP, FSCommandOpenMP, Info) @@ -634,7 +635,7 @@ class ReconAllInputSpec(CommandLineInputSpec): desc="Enable parallel execution") hires = traits.Bool(argstr="-hires", min_ver='6.0.0', desc="Conform to minimum voxel size (for voxels < 1mm)") - expert = File(exists=True, argstr='-expert %s', + expert = traits.Either(File(exists=True), DictStrStr, argstr='-expert %s', desc="Set parameters using expert file") subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False, desc='path to subjects directory', genfile=True) @@ -899,6 +900,12 @@ def _format_arg(self, name, trait_spec, value): if name == 'T1_files': if self._is_resuming(): return '' + if name == 'expert' and isinstance(value, dict): + expert_fname = os.path.abspath('expert.opts') + expert = ['{} {}\n'.format(key, val) for key, val in value.items()] + with open(expert_fname, 'w') as fobj: + fobj.write(''.join(expert)) + value = expert_fname return super(ReconAll, self)._format_arg(name, trait_spec, value) @property diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py b/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py deleted file mode 100644 index 1c62abb937..0000000000 --- a/nipype/interfaces/freesurfer/tests/test_auto_ExpertOptions.py +++ /dev/null @@ -1,50 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..utils import ExpertOptions - - -def test_ExpertOptions_inputs(): - input_map = dict(mri_aparc2aseg=dict(), - mri_ca_label=dict(), - mri_ca_normalize=dict(), - mri_ca_register=dict(), - mri_edit_wm_with_aseg=dict(), - mri_em_register=dict(), - mri_fill=dict(), - mri_mask=dict(), - mri_normalize=dict(), - mri_pretess=dict(), - mri_remove_neck=dict(), - mri_segment=dict(), - mri_segstats=dict(), - mri_tessellate=dict(), - mri_watershed=dict(), - mris_anatomical_stats=dict(), - mris_ca_label=dict(), - mris_fix_topology=dict(), - mris_inflate=dict(), - mris_make_surfaces=dict(), - mris_register=dict(), - mris_smooth=dict(), - mris_sphere=dict(), - mris_surf2vol=dict(), - mrisp_paint=dict(), - out_file=dict(usedefault=True, - ), - talairach=dict(), - ) - inputs = ExpertOptions.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_ExpertOptions_outputs(): - output_map = dict(out_file=dict(), - ) - outputs = ExpertOptions.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/freesurfer/utils.py b/nipype/interfaces/freesurfer/utils.py index ad5a50a869..fed63e498e 100644 --- a/nipype/interfaces/freesurfer/utils.py +++ b/nipype/interfaces/freesurfer/utils.py @@ -18,8 +18,8 @@ import shutil from ...utils.filemanip import fname_presuffix, split_filename -from ..base import (TraitedSpec, BaseInterface, File, traits, OutputMultiPath, - isdefined, CommandLine, CommandLineInputSpec) +from ..base import (TraitedSpec, File, traits, OutputMultiPath, isdefined, + CommandLine, CommandLineInputSpec) from .base import (FSCommand, FSTraitedSpec, FSScriptCommand, FSScriptOutputSpec, FSTraitedSpecOpenMP, FSCommandOpenMP) @@ -2879,64 +2879,3 @@ def _list_outputs(self): outputs = self._outputs().get() outputs["out_file"] = os.path.abspath(self.inputs.out_file) return outputs - - -class ExpertOptionsInputSpec(TraitedSpec): - talairach = traits.String(desc="Flags to pass to talairach commands") - mri_normalize = traits.String(desc="Flags to pass to mri_normalize commands") - mri_watershed = traits.String(desc="Flags to pass to mri_watershed commands") - mri_em_register = traits.String(desc="Flags to pass to mri_em_register commands") - mri_ca_normalize = traits.String(desc="Flags to pass to mri_ca_normalize commands") - mri_ca_register = traits.String(desc="Flags to pass to mri_ca_register commands") - mri_remove_neck = traits.String(desc="Flags to pass to mri_remove_neck commands") - mri_ca_label = traits.String(desc="Flags to pass to mri_ca_label commands") - mri_segstats = traits.String(desc="Flags to pass to mri_segstats commands") - mri_mask = traits.String(desc="Flags to pass to mri_mask commands") - mri_segment = traits.String(desc="Flags to pass to mri_segment commands") - mri_edit_wm_with_aseg = traits.String(desc="Flags to pass to mri_edit_wm_with_aseg commands") - mri_pretess = traits.String(desc="Flags to pass to mri_pretess commands") - mri_fill = traits.String(desc="Flags to pass to mri_fill commands") - mri_tessellate = traits.String(desc="Flags to pass to mri_tessellate commands") - mris_smooth = traits.String(desc="Flags to pass to mri_smooth commands") - mris_inflate = traits.String(desc="Flags to pass to mri_inflate commands") - mris_sphere = traits.String(desc="Flags to pass to mris_sphere commands") - mris_fix_topology = traits.String(desc="Flags to pass to mris_fix_topology commands") - mris_make_surfaces = traits.String(desc="Flags to pass to mris_make_surfaces commands") - mris_surf2vol = traits.String(desc="Flags to pass to mris_surf2vol commands") - mris_register = traits.String(desc="Flags to pass to mris_register commands") - mrisp_paint = traits.String(desc="Flags to pass to mrisp_paint commands") - mris_ca_label = traits.String(desc="Flags to pass to mris_ca_label commands") - mris_anatomical_stats = traits.String(desc="Flags to pass to mris_anatomical_stats commands") - mri_aparc2aseg = traits.String(desc="Flags to pass to mri_aparc2aseg commands") - out_file = File("expert.opts", usedefault=True, desc="Output expert options file") - - -class ExpertOptionsOutputSpec(TraitedSpec): - out_file = File(exists=False, desc="Output expert options file") - - -class ExpertOptions(BaseInterface): - """ - Creates expert options file - https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all#ExpertOptionsFile - """ - input_spec = ExpertOptionsInputSpec - output_spec = ExpertOptionsOutputSpec - - def _list_outputs(self): - outputs = self._outputs().get() - outputs["out_file"] = os.path.abspath(self.inputs.out_file) - return outputs - - def _run_interface(self, runtime): - out_file = self.inputs.out_file - - lines = [] - for binary, args in self.inputs.get().items(): - if binary == 'out_file' or not isdefined(args): - continue - lines.append('{} {}\n'.format(binary, args)) - - with open(out_file, 'w') as fobj: - fobj.write(''.join(lines)) - return runtime From 2aa325ee4f0f3bd7537d7f198f485136034dbd9a Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 3 Mar 2017 14:49:26 -0500 Subject: [PATCH 31/44] Explicitly add extra options to ReconAllInputSpec --- nipype/interfaces/freesurfer/preprocess.py | 70 ++++++++++++++++--- .../freesurfer/tests/test_auto_ReconAll.py | 52 ++++++++++++++ 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 4e43a4f03d..9c25f93e43 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -28,7 +28,6 @@ Directory, InputMultiPath, OutputMultiPath, CommandLine, CommandLineInputSpec, isdefined) -from ..traits_extension import DictStrStr from .base import (FSCommand, FSTraitedSpec, FSTraitedSpecOpenMP, FSCommandOpenMP, Info) @@ -635,12 +634,40 @@ class ReconAllInputSpec(CommandLineInputSpec): desc="Enable parallel execution") hires = traits.Bool(argstr="-hires", min_ver='6.0.0', desc="Conform to minimum voxel size (for voxels < 1mm)") - expert = traits.Either(File(exists=True), DictStrStr, argstr='-expert %s', + expert = File(exists=True, argstr='-expert %s', desc="Set parameters using expert file") subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False, desc='path to subjects directory', genfile=True) flags = traits.Str(argstr='%s', desc='additional parameters') + # Expert options + talairach = traits.Str(desc="Flags to pass to talairach commands", xor=['expert']) + mri_normalize = traits.Str(desc="Flags to pass to mri_normalize commands", xor=['expert']) + mri_watershed = traits.Str(desc="Flags to pass to mri_watershed commands", xor=['expert']) + mri_em_register = traits.Str(desc="Flags to pass to mri_em_register commands", xor=['expert']) + mri_ca_normalize = traits.Str(desc="Flags to pass to mri_ca_normalize commands", xor=['expert']) + mri_ca_register = traits.Str(desc="Flags to pass to mri_ca_register commands", xor=['expert']) + mri_remove_neck = traits.Str(desc="Flags to pass to mri_remove_neck commands", xor=['expert']) + mri_ca_label = traits.Str(desc="Flags to pass to mri_ca_label commands", xor=['expert']) + mri_segstats = traits.Str(desc="Flags to pass to mri_segstats commands", xor=['expert']) + mri_mask = traits.Str(desc="Flags to pass to mri_mask commands", xor=['expert']) + mri_segment = traits.Str(desc="Flags to pass to mri_segment commands", xor=['expert']) + mri_edit_wm_with_aseg = traits.Str(desc="Flags to pass to mri_edit_wm_with_aseg commands", xor=['expert']) + mri_pretess = traits.Str(desc="Flags to pass to mri_pretess commands", xor=['expert']) + mri_fill = traits.Str(desc="Flags to pass to mri_fill commands", xor=['expert']) + mri_tessellate = traits.Str(desc="Flags to pass to mri_tessellate commands", xor=['expert']) + mris_smooth = traits.Str(desc="Flags to pass to mri_smooth commands", xor=['expert']) + mris_inflate = traits.Str(desc="Flags to pass to mri_inflate commands", xor=['expert']) + mris_sphere = traits.Str(desc="Flags to pass to mris_sphere commands", xor=['expert']) + mris_fix_topology = traits.Str(desc="Flags to pass to mris_fix_topology commands", xor=['expert']) + mris_make_surfaces = traits.Str(desc="Flags to pass to mris_make_surfaces commands", xor=['expert']) + mris_surf2vol = traits.Str(desc="Flags to pass to mris_surf2vol commands", xor=['expert']) + mris_register = traits.Str(desc="Flags to pass to mris_register commands", xor=['expert']) + mrisp_paint = traits.Str(desc="Flags to pass to mrisp_paint commands", xor=['expert']) + mris_ca_label = traits.Str(desc="Flags to pass to mris_ca_label commands", xor=['expert']) + mris_anatomical_stats = traits.Str(desc="Flags to pass to mris_anatomical_stats commands", xor=['expert']) + mri_aparc2aseg = traits.Str(desc="Flags to pass to mri_aparc2aseg commands", xor=['expert']) + class ReconAllOutputSpec(FreeSurferSource.output_spec): subjects_dir = Directory(exists=True, desc='Freesurfer subjects directory.') @@ -856,6 +883,16 @@ class ReconAll(CommandLine): _steps = _autorecon1_steps + _autorecon2_steps + _autorecon3_steps + _binaries = ['talairach', 'mri_normalize', 'mri_watershed', + 'mri_em_register', 'mri_ca_normalize', 'mri_ca_register', + 'mri_remove_neck', 'mri_ca_label', 'mri_segstats', + 'mri_mask', 'mri_segment', 'mri_edit_wm_with_aseg', + 'mri_pretess', 'mri_fill', 'mri_tessellate', 'mris_smooth', + 'mris_inflate', 'mris_sphere', 'mris_fix_topology', + 'mris_make_surfaces', 'mris_surf2vol', 'mris_register', + 'mrisp_paint', 'mris_ca_label', 'mris_anatomical_stats', + 'mri_aparc2aseg'] + def _gen_subjects_dir(self): return os.getcwd() @@ -900,17 +937,16 @@ def _format_arg(self, name, trait_spec, value): if name == 'T1_files': if self._is_resuming(): return '' - if name == 'expert' and isinstance(value, dict): - expert_fname = os.path.abspath('expert.opts') - expert = ['{} {}\n'.format(key, val) for key, val in value.items()] - with open(expert_fname, 'w') as fobj: - fobj.write(''.join(expert)) - value = expert_fname return super(ReconAll, self)._format_arg(name, trait_spec, value) @property def cmdline(self): cmd = super(ReconAll, self).cmdline + + # Adds '-expert' flag if expert flags are passed + # Mutually exclusive with 'expert' input parameter + cmd += self._prep_expert_file() + if not self._is_resuming(): return cmd subjects_dir = self.inputs.subjects_dir @@ -944,6 +980,24 @@ def cmdline(self): iflogger.info('resume recon-all : %s' % cmd) return cmd + def _prep_expert_file(self): + if isdefined(self.inputs.expert): + return '' + + lines = [] + for binary in self._binaries: + args = getattr(self.inputs, binary) + if isdefined(args): + lines.append('{} {}\n'.format(binary, args)) + + if lines == []: + return '' + + expert_fname = os.path.abspath('expert.opts') + with open(expert_fname, 'w') as fobj: + fobj.write(''.join(lines)) + return ' -expert {}'.format(expert_fname) + class BBRegisterInputSpec(FSTraitedSpec): subject_id = traits.Str(argstr='--s %s', diff --git a/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py b/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py index b748df7aa9..b0e89e9a3f 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py @@ -30,6 +30,56 @@ def test_ReconAll_inputs(): ignore_exception=dict(nohash=True, usedefault=True, ), + mri_aparc2aseg=dict(xor=['expert'], + ), + mri_ca_label=dict(xor=['expert'], + ), + mri_ca_normalize=dict(xor=['expert'], + ), + mri_ca_register=dict(xor=['expert'], + ), + mri_edit_wm_with_aseg=dict(xor=['expert'], + ), + mri_em_register=dict(xor=['expert'], + ), + mri_fill=dict(xor=['expert'], + ), + mri_mask=dict(xor=['expert'], + ), + mri_normalize=dict(xor=['expert'], + ), + mri_pretess=dict(xor=['expert'], + ), + mri_remove_neck=dict(xor=['expert'], + ), + mri_segment=dict(xor=['expert'], + ), + mri_segstats=dict(xor=['expert'], + ), + mri_tessellate=dict(xor=['expert'], + ), + mri_watershed=dict(xor=['expert'], + ), + mris_anatomical_stats=dict(xor=['expert'], + ), + mris_ca_label=dict(xor=['expert'], + ), + mris_fix_topology=dict(xor=['expert'], + ), + mris_inflate=dict(xor=['expert'], + ), + mris_make_surfaces=dict(xor=['expert'], + ), + mris_register=dict(xor=['expert'], + ), + mris_smooth=dict(xor=['expert'], + ), + mris_sphere=dict(xor=['expert'], + ), + mris_surf2vol=dict(xor=['expert'], + ), + mrisp_paint=dict(xor=['expert'], + ), openmp=dict(argstr='-openmp %d', ), parallel=dict(argstr='-parallel', @@ -41,6 +91,8 @@ def test_ReconAll_inputs(): genfile=True, hash_files=False, ), + talairach=dict(xor=['expert'], + ), terminal_output=dict(nohash=True, ), use_T2=dict(argstr='-T2pial', From 5e7588682fb43a2654b687740875d908994fddee Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Mon, 6 Mar 2017 13:32:12 -0500 Subject: [PATCH 32/44] make specs --- .../tests/test_auto_ComputeDVARS.py | 2 ++ .../tests/test_auto_FramewiseDisplacement.py | 2 ++ .../tests/test_auto_NonSteadyStateDetector.py | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py diff --git a/nipype/algorithms/tests/test_auto_ComputeDVARS.py b/nipype/algorithms/tests/test_auto_ComputeDVARS.py index 9a52898fc7..7c59f851d1 100644 --- a/nipype/algorithms/tests/test_auto_ComputeDVARS.py +++ b/nipype/algorithms/tests/test_auto_ComputeDVARS.py @@ -17,6 +17,8 @@ def test_ComputeDVARS_inputs(): ), in_mask=dict(mandatory=True, ), + intensity_normalization=dict(usedefault=True, + ), remove_zerovariance=dict(usedefault=True, ), save_all=dict(usedefault=True, diff --git a/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py b/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py index da1dec59d6..e230992eec 100644 --- a/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py +++ b/nipype/algorithms/tests/test_auto_FramewiseDisplacement.py @@ -19,6 +19,8 @@ def test_FramewiseDisplacement_inputs(): ), out_file=dict(usedefault=True, ), + parameter_source=dict(mandatory=True, + ), radius=dict(usedefault=True, ), save_plot=dict(usedefault=True, diff --git a/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py b/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py new file mode 100644 index 0000000000..7b12363ee8 --- /dev/null +++ b/nipype/algorithms/tests/test_auto_NonSteadyStateDetector.py @@ -0,0 +1,27 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..confounds import NonSteadyStateDetector + + +def test_NonSteadyStateDetector_inputs(): + input_map = dict(ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(mandatory=True, + ), + ) + inputs = NonSteadyStateDetector.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_NonSteadyStateDetector_outputs(): + output_map = dict(n_volumes_to_discard=dict(), + ) + outputs = NonSteadyStateDetector.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value From 31f6f3d5394f11f985d830c250a41c6d79a7dc0b Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Mon, 6 Mar 2017 20:33:46 -0500 Subject: [PATCH 33/44] crazy file --- nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py index 3186317333..cf67b12b2b 100644 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py +++ b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py @@ -1,9 +1,9 @@ # AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT from __future__ import unicode_literals -from ..preprocess import ApplyXfm +from ..preprocess import ApplyXFM -def test_ApplyXfm_inputs(): +def test_ApplyXFM_inputs(): input_map = dict(angle_rep=dict(argstr='-anglerep %s', ), apply_isoxfm=dict(argstr='-applyisoxfm %f', @@ -145,19 +145,19 @@ def test_ApplyXfm_inputs(): min_ver='5.0.0', ), ) - inputs = ApplyXfm.input_spec() + inputs = ApplyXFM.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_ApplyXfm_outputs(): +def test_ApplyXFM_outputs(): output_map = dict(out_file=dict(), out_log=dict(), out_matrix_file=dict(), ) - outputs = ApplyXfm.output_spec() + outputs = ApplyXFM.output_spec() for key, metadata in list(output_map.items()): for metakey, value in list(metadata.items()): From b2e83fb9e317854dad040a9f8d4607a1b68b1f7c Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Mon, 6 Mar 2017 20:39:01 -0500 Subject: [PATCH 34/44] fixed auto tests and style --- README.rst | 4 +- nipype/algorithms/tests/test_auto_CompCor.py | 37 --------------- nipype/algorithms/tests/test_auto_ErrorMap.py | 35 -------------- nipype/algorithms/tests/test_auto_Overlap.py | 47 ------------------- nipype/algorithms/tests/test_auto_TSNR.py | 43 ----------------- ...est_auto_CreateJacobianDeterminantImage.py | 2 - nipype/interfaces/ants/utils.py | 4 +- nipype/interfaces/fsl/model.py | 1 - nipype/interfaces/fsl/preprocess.py | 2 +- .../fsl/tests/test_auto_ApplyXfm.py | 10 ++-- .../interfaces/fsl/tests/test_auto_FNIRT.py | 2 +- .../fsl/tests/test_auto_Level1Design.py | 3 +- nipype/interfaces/fsl/tests/test_maths.py | 2 +- nipype/pipeline/engine/tests/test_engine.py | 16 +++---- nipype/utils/tests/test_filemanip.py | 2 +- 15 files changed, 22 insertions(+), 188 deletions(-) delete mode 100644 nipype/algorithms/tests/test_auto_CompCor.py delete mode 100644 nipype/algorithms/tests/test_auto_ErrorMap.py delete mode 100644 nipype/algorithms/tests/test_auto_Overlap.py delete mode 100644 nipype/algorithms/tests/test_auto_TSNR.py diff --git a/README.rst b/README.rst index fd001f2581..da6dbd280d 100644 --- a/README.rst +++ b/README.rst @@ -78,8 +78,8 @@ Support and Communication ------------------------- If you have a problem or would like to ask a question about how to do something in Nipype please open an issue to -`NeuroStars.org `_ with a *nipype* tag. `NeuroStars.org `_ is a -platform similar to StackOverflow but dedicated to neuroinformatics. +`NeuroStars.org `_ with a *nipype* tag. `NeuroStars.org `_ is a +platform similar to StackOverflow but dedicated to neuroinformatics. To participate in the Nipype development related discussions please use the following mailing list:: diff --git a/nipype/algorithms/tests/test_auto_CompCor.py b/nipype/algorithms/tests/test_auto_CompCor.py deleted file mode 100644 index 12cec2ebb0..0000000000 --- a/nipype/algorithms/tests/test_auto_CompCor.py +++ /dev/null @@ -1,37 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..confounds import CompCor - - -def test_CompCor_inputs(): - input_map = dict(components_file=dict(usedefault=True, - ), - header=dict(), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - mask_file=dict(), - num_components=dict(usedefault=True, - ), - realigned_file=dict(mandatory=True, - ), - regress_poly_degree=dict(usedefault=True, - ), - use_regress_poly=dict(usedefault=True, - ), - ) - inputs = CompCor.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_CompCor_outputs(): - output_map = dict(components_file=dict(), - ) - outputs = CompCor.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/algorithms/tests/test_auto_ErrorMap.py b/nipype/algorithms/tests/test_auto_ErrorMap.py deleted file mode 100644 index f3d19c5690..0000000000 --- a/nipype/algorithms/tests/test_auto_ErrorMap.py +++ /dev/null @@ -1,35 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..metrics import ErrorMap - - -def test_ErrorMap_inputs(): - input_map = dict(ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_ref=dict(mandatory=True, - ), - in_tst=dict(mandatory=True, - ), - mask=dict(), - metric=dict(mandatory=True, - usedefault=True, - ), - out_map=dict(), - ) - inputs = ErrorMap.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_ErrorMap_outputs(): - output_map = dict(distance=dict(), - out_map=dict(), - ) - outputs = ErrorMap.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/algorithms/tests/test_auto_Overlap.py b/nipype/algorithms/tests/test_auto_Overlap.py deleted file mode 100644 index dcabbec296..0000000000 --- a/nipype/algorithms/tests/test_auto_Overlap.py +++ /dev/null @@ -1,47 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..misc import Overlap - - -def test_Overlap_inputs(): - input_map = dict(bg_overlap=dict(mandatory=True, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - mask_volume=dict(), - out_file=dict(usedefault=True, - ), - vol_units=dict(mandatory=True, - usedefault=True, - ), - volume1=dict(mandatory=True, - ), - volume2=dict(mandatory=True, - ), - weighting=dict(usedefault=True, - ), - ) - inputs = Overlap.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_Overlap_outputs(): - output_map = dict(dice=dict(), - diff_file=dict(), - jaccard=dict(), - labels=dict(), - roi_di=dict(), - roi_ji=dict(), - roi_voldiff=dict(), - volume_difference=dict(), - ) - outputs = Overlap.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/algorithms/tests/test_auto_TSNR.py b/nipype/algorithms/tests/test_auto_TSNR.py deleted file mode 100644 index d906d39e3f..0000000000 --- a/nipype/algorithms/tests/test_auto_TSNR.py +++ /dev/null @@ -1,43 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..misc import TSNR - - -def test_TSNR_inputs(): - input_map = dict(detrended_file=dict(hash_files=False, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(mandatory=True, - ), - mean_file=dict(hash_files=False, - usedefault=True, - ), - regress_poly=dict(), - stddev_file=dict(hash_files=False, - usedefault=True, - ), - tsnr_file=dict(hash_files=False, - usedefault=True, - ), - ) - inputs = TSNR.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_TSNR_outputs(): - output_map = dict(detrended_file=dict(), - mean_file=dict(), - stddev_file=dict(), - tsnr_file=dict(), - ) - outputs = TSNR.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/ants/tests/test_auto_CreateJacobianDeterminantImage.py b/nipype/interfaces/ants/tests/test_auto_CreateJacobianDeterminantImage.py index 4dd522a69b..f7aafb27be 100644 --- a/nipype/interfaces/ants/tests/test_auto_CreateJacobianDeterminantImage.py +++ b/nipype/interfaces/ants/tests/test_auto_CreateJacobianDeterminantImage.py @@ -11,7 +11,6 @@ def test_CreateJacobianDeterminantImage_inputs(): position=1, ), doLogJacobian=dict(argstr='%d', - mandatory=False, position=3, ), environ=dict(nohash=True, @@ -35,7 +34,6 @@ def test_CreateJacobianDeterminantImage_inputs(): terminal_output=dict(nohash=True, ), useGeometric=dict(argstr='%d', - mandatory=False, position=4, ), ) diff --git a/nipype/interfaces/ants/utils.py b/nipype/interfaces/ants/utils.py index ade303898c..b88ca57e14 100644 --- a/nipype/interfaces/ants/utils.py +++ b/nipype/interfaces/ants/utils.py @@ -145,9 +145,9 @@ class CreateJacobianDeterminantImageInputSpec(ANTSCommandInputSpec): outputImage = File(argstr='%s', mandatory=True, position=2, desc='output filename') - doLogJacobian = traits.Enum(0, 1, argstr='%d', mandatory=False, position=3, + doLogJacobian = traits.Enum(0, 1, argstr='%d', position=3, desc='return the log jacobian') - useGeometric = traits.Enum(0, 1, argstr='%d', mandatory=False, position=4, + useGeometric = traits.Enum(0, 1, argstr='%d', position=4, desc='return the geometric jacobian') class CreateJacobianDeterminantImageOutputSpec(TraitedSpec): diff --git a/nipype/interfaces/fsl/model.py b/nipype/interfaces/fsl/model.py index 5ede5fa1f8..8a00b44a76 100644 --- a/nipype/interfaces/fsl/model.py +++ b/nipype/interfaces/fsl/model.py @@ -49,7 +49,6 @@ class Level1DesignInputSpec(BaseInterfaceInputSpec): "{'dgamma': {'derivs': True}}")) orthogonalization = traits.Dict(traits.Int, traits.Dict(traits.Int, traits.Either(traits.Bool,traits.Int)), - mandatory=False, desc=("which regressors to make orthogonal e.g., " "{1: {0:0,1:0,2:0}, 2: {0:1,1:1,2:0}} to make the second " "regressor in a 2-regressor model orthogonal to the first."), diff --git a/nipype/interfaces/fsl/preprocess.py b/nipype/interfaces/fsl/preprocess.py index eaab2a830e..15b1ca6692 100644 --- a/nipype/interfaces/fsl/preprocess.py +++ b/nipype/interfaces/fsl/preprocess.py @@ -751,7 +751,7 @@ class FNIRTInputSpec(FSLCommandInputSpec): inwarp_file = File(exists=True, argstr='--inwarp=%s', desc='name of file containing initial non-linear warps') in_intensitymap_file = traits.List(File(exists=True), argstr='--intin=%s', - copyfiles=False, minlen=1, maxlen=2, + copyfile=False, minlen=1, maxlen=2, desc=('name of file/files containing ' 'initial intensity mapping ' 'usually generated by previous ' diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py index cf67b12b2b..3186317333 100644 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py +++ b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py @@ -1,9 +1,9 @@ # AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT from __future__ import unicode_literals -from ..preprocess import ApplyXFM +from ..preprocess import ApplyXfm -def test_ApplyXFM_inputs(): +def test_ApplyXfm_inputs(): input_map = dict(angle_rep=dict(argstr='-anglerep %s', ), apply_isoxfm=dict(argstr='-applyisoxfm %f', @@ -145,19 +145,19 @@ def test_ApplyXFM_inputs(): min_ver='5.0.0', ), ) - inputs = ApplyXFM.input_spec() + inputs = ApplyXfm.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_ApplyXFM_outputs(): +def test_ApplyXfm_outputs(): output_map = dict(out_file=dict(), out_log=dict(), out_matrix_file=dict(), ) - outputs = ApplyXFM.output_spec() + outputs = ApplyXfm.output_spec() for key, metadata in list(output_map.items()): for metakey, value in list(metadata.items()): diff --git a/nipype/interfaces/fsl/tests/test_auto_FNIRT.py b/nipype/interfaces/fsl/tests/test_auto_FNIRT.py index 7a93e351ed..8e4cf47fc3 100644 --- a/nipype/interfaces/fsl/tests/test_auto_FNIRT.py +++ b/nipype/interfaces/fsl/tests/test_auto_FNIRT.py @@ -48,7 +48,7 @@ def test_FNIRT_inputs(): sep=',', ), in_intensitymap_file=dict(argstr='--intin=%s', - copyfiles=False, + copyfile=False, ), inmask_file=dict(argstr='--inmask=%s', ), diff --git a/nipype/interfaces/fsl/tests/test_auto_Level1Design.py b/nipype/interfaces/fsl/tests/test_auto_Level1Design.py index cc6402fb1a..f5fcfe4093 100644 --- a/nipype/interfaces/fsl/tests/test_auto_Level1Design.py +++ b/nipype/interfaces/fsl/tests/test_auto_Level1Design.py @@ -14,8 +14,7 @@ def test_Level1Design_inputs(): ), model_serial_correlations=dict(mandatory=True, ), - orthogonalization=dict(mandatory=False, - ), + orthogonalization=dict(), session_info=dict(mandatory=True, ), ) diff --git a/nipype/interfaces/fsl/tests/test_maths.py b/nipype/interfaces/fsl/tests/test_maths.py index e2c6c93bb7..408a74712f 100644 --- a/nipype/interfaces/fsl/tests/test_maths.py +++ b/nipype/interfaces/fsl/tests/test_maths.py @@ -12,7 +12,7 @@ from nipype.interfaces.fsl import no_fsl import pytest -from nipype.testing.fixtures import create_files_in_directory_plus_output_type +from nipype.testing.fixtures import create_files_in_directory_plus_output_type @pytest.mark.skipif(no_fsl(), reason="fsl is not installed") diff --git a/nipype/pipeline/engine/tests/test_engine.py b/nipype/pipeline/engine/tests/test_engine.py index 32271799b8..43345bb8c6 100644 --- a/nipype/pipeline/engine/tests/test_engine.py +++ b/nipype/pipeline/engine/tests/test_engine.py @@ -326,14 +326,14 @@ def test_doubleconnect(): flow1 = pe.Workflow(name='test') flow1.connect(a, 'a', b, 'a') x = lambda: flow1.connect(a, 'b', b, 'a') - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: x() assert "Trying to connect" in str(excinfo.value) c = pe.Node(IdentityInterface(fields=['a', 'b']), name='c') flow1 = pe.Workflow(name='test2') x = lambda: flow1.connect([(a, c, [('b', 'b')]), (b, c, [('a', 'b')])]) - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: x() assert "Trying to connect" in str(excinfo.value) @@ -481,7 +481,7 @@ def func1(in1): name='n1') n2.inputs.in1 = [[1, [2]], 3, [4, 5]] - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception) as excinfo: n2.run() assert "can only concatenate list" in str(excinfo.value) @@ -518,7 +518,7 @@ def func2(a): # create dummy distributed plugin class from nipype.pipeline.plugins.base import DistributedPluginBase - # create a custom exception + # create a custom exception class EngineTestException(Exception): pass @@ -529,7 +529,7 @@ def _submit_job(self, node, updatehash=False): # check if a proper exception is raised with pytest.raises(EngineTestException) as excinfo: w1.run(plugin=RaiseError()) - assert 'Submit called' == str(excinfo.value) + assert 'Submit called' == str(excinfo.value) # rerun to ensure we have outputs w1.run(plugin='Linear') @@ -539,7 +539,7 @@ def _submit_job(self, node, updatehash=False): 'crashdump_dir': wd} w1.run(plugin=RaiseError()) - + def test_old_config(tmpdir): wd = str(tmpdir) @@ -607,7 +607,7 @@ def func1(in1): w1.config['execution'].update(**{'stop_on_first_rerun': True}) w1.run() - + def test_parameterize_dirs_false(tmpdir): from ....interfaces.utility import IdentityInterface @@ -665,7 +665,7 @@ def func1(in1): # test running the workflow on serial conditions w1.run(plugin='MultiProc') - + def test_write_graph_runs(tmpdir): os.chdir(str(tmpdir)) diff --git a/nipype/utils/tests/test_filemanip.py b/nipype/utils/tests/test_filemanip.py index 644a055f4b..bf321c5b9c 100644 --- a/nipype/utils/tests/test_filemanip.py +++ b/nipype/utils/tests/test_filemanip.py @@ -306,7 +306,7 @@ def touch(fname): else: assert False, "Should raise OSError on missing dependency" - shutil.rmtree(tmpdir) + shutil.rmtree(tmpdir) def test_json(): From ffe7dd5cfe63889e25c6fa7a1d0587fb317514b5 Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Mon, 6 Mar 2017 20:40:42 -0500 Subject: [PATCH 35/44] fixed missing brukerdir from install --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index 4bf982902f..f09bacaae4 100755 --- a/setup.py +++ b/setup.py @@ -97,6 +97,9 @@ def main(): pjoin('testing', 'data', 'dicomdir', '*'), pjoin('testing', 'data', 'bedpostxout', '*'), pjoin('testing', 'data', 'tbss_dir', '*'), + pjoin('testing', 'data', 'brukerdir', '*'), + pjoin('testing', 'data', 'brukerdir', 'pdata', '*'), + pjoin('testing', 'data', 'brukerdir', 'pdata', '1', '*'), pjoin('workflows', 'data', '*'), pjoin('pipeline', 'engine', 'report_template.html'), pjoin('external', 'd3.js'), From 63c108fb8d00fc66b611225ce02f4880a3f25bd8 Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Tue, 7 Mar 2017 10:33:06 -0500 Subject: [PATCH 36/44] fix: remove deprecated interface. --- nipype/interfaces/fsl/__init__.py | 2 +- nipype/interfaces/fsl/preprocess.py | 10 ---------- nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py | 10 +++++----- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/nipype/interfaces/fsl/__init__.py b/nipype/interfaces/fsl/__init__.py index 58b7321416..ba7d1c0428 100644 --- a/nipype/interfaces/fsl/__init__.py +++ b/nipype/interfaces/fsl/__init__.py @@ -8,7 +8,7 @@ """ from .base import (FSLCommand, Info, check_fsl, no_fsl, no_fsl_course_data) -from .preprocess import (FAST, FLIRT, ApplyXfm, ApplyXFM, BET, MCFLIRT, FNIRT, +from .preprocess import (FAST, FLIRT, pplyXFM, BET, MCFLIRT, FNIRT, ApplyWarp, SliceTimer, SUSAN, PRELUDE, FUGUE, FIRST) from .model import (Level1Design, FEAT, FEATModel, FILMGLS, FEATRegister, FLAMEO, ContrastMgr, MultipleRegressDesign, L2Model, SMM, diff --git a/nipype/interfaces/fsl/preprocess.py b/nipype/interfaces/fsl/preprocess.py index 15b1ca6692..8f23699915 100644 --- a/nipype/interfaces/fsl/preprocess.py +++ b/nipype/interfaces/fsl/preprocess.py @@ -594,16 +594,6 @@ class ApplyXFM(FLIRT): """ input_spec = ApplyXFMInputSpec -class ApplyXfm(ApplyXFM): - """ - .. deprecated:: 0.12.1 - Use :py:class:`nipype.interfaces.fsl.ApplyXFM` instead - """ - def __init__(self, **inputs): - super(ApplyXfm, self).__init__(**inputs) - warn(('This interface has been renamed since 0.12.1, please use ' - 'nipype.interfaces.fsl.ApplyXFM'), - UserWarning) class MCFLIRTInputSpec(FSLCommandInputSpec): in_file = File(exists=True, position=0, argstr="-in %s", mandatory=True, diff --git a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py index 3186317333..cf67b12b2b 100644 --- a/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py +++ b/nipype/interfaces/fsl/tests/test_auto_ApplyXfm.py @@ -1,9 +1,9 @@ # AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT from __future__ import unicode_literals -from ..preprocess import ApplyXfm +from ..preprocess import ApplyXFM -def test_ApplyXfm_inputs(): +def test_ApplyXFM_inputs(): input_map = dict(angle_rep=dict(argstr='-anglerep %s', ), apply_isoxfm=dict(argstr='-applyisoxfm %f', @@ -145,19 +145,19 @@ def test_ApplyXfm_inputs(): min_ver='5.0.0', ), ) - inputs = ApplyXfm.input_spec() + inputs = ApplyXFM.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_ApplyXfm_outputs(): +def test_ApplyXFM_outputs(): output_map = dict(out_file=dict(), out_log=dict(), out_matrix_file=dict(), ) - outputs = ApplyXfm.output_spec() + outputs = ApplyXFM.output_spec() for key, metadata in list(output_map.items()): for metakey, value in list(metadata.items()): From 9a2206b65fa296a948b8a5927f56a81edbe5ae63 Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Tue, 7 Mar 2017 10:33:56 -0500 Subject: [PATCH 37/44] fix: namesource behavior and test error --- nipype/interfaces/base.py | 2 +- nipype/interfaces/tests/test_base.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py index b46712e701..62ea7851ac 100644 --- a/nipype/interfaces/base.py +++ b/nipype/interfaces/base.py @@ -1844,7 +1844,7 @@ def _filename_from_source(self, name, chain=None): # special treatment for files try: _, base, source_ext = split_filename(source) - except AttributeError: + except (AttributeError, TypeError): base = source else: if name in chain: diff --git a/nipype/interfaces/tests/test_base.py b/nipype/interfaces/tests/test_base.py index b4d45c47f4..e27779ce02 100644 --- a/nipype/interfaces/tests/test_base.py +++ b/nipype/interfaces/tests/test_base.py @@ -209,7 +209,8 @@ class spec2(nib.CommandLineInputSpec): position=2) doo = nib.File(exists=True, argstr="%s", position=1) goo = traits.Int(argstr="%d", position=4) - poo = nib.File(name_source=['goo'], hash_files=False, argstr="%s", position=3) + poo = nib.File(name_source=['goo'], hash_files=False, argstr="%s", + position=3) class TestName(nib.CommandLine): _cmd = "mycommand" @@ -218,6 +219,7 @@ class TestName(nib.CommandLine): testobj.inputs.doo = tmp_infile testobj.inputs.goo = 99 assert '%s_generated' % nme in testobj.cmdline + assert '%d_generated' % testobj.inputs.goo in testobj.cmdline testobj.inputs.moo = "my_%s_template" assert 'my_%s_template' % nme in testobj.cmdline From e4ce6368b0065a429435a16372a2e5957a36fadd Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Tue, 7 Mar 2017 10:34:31 -0500 Subject: [PATCH 38/44] fix: allow tests to be installed with nipype --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f09bacaae4..79941f0625 100755 --- a/setup.py +++ b/setup.py @@ -133,7 +133,7 @@ def main(): install_requires=ldict['REQUIRES'], setup_requires=['future', 'configparser'], provides=ldict['PROVIDES'], - packages=find_packages(exclude=['*.tests']), + packages=find_packages(), package_data={'nipype': testdatafiles}, scripts=glob('bin/*'), cmdclass={'build_py': BuildWithCommitInfoCommand}, From 59c8dba584b1b7795e12dc65918204bd42d57bf6 Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Tue, 7 Mar 2017 10:35:56 -0500 Subject: [PATCH 39/44] fix: typo --- nipype/interfaces/fsl/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/fsl/__init__.py b/nipype/interfaces/fsl/__init__.py index ba7d1c0428..b0a8b5a88e 100644 --- a/nipype/interfaces/fsl/__init__.py +++ b/nipype/interfaces/fsl/__init__.py @@ -8,7 +8,7 @@ """ from .base import (FSLCommand, Info, check_fsl, no_fsl, no_fsl_course_data) -from .preprocess import (FAST, FLIRT, pplyXFM, BET, MCFLIRT, FNIRT, +from .preprocess import (FAST, FLIRT, ApplyXFM, BET, MCFLIRT, FNIRT, ApplyWarp, SliceTimer, SUSAN, PRELUDE, FUGUE, FIRST) from .model import (Level1Design, FEAT, FEATModel, FILMGLS, FEATRegister, FLAMEO, ContrastMgr, MultipleRegressDesign, L2Model, SMM, From 6dc7b1c971447e6318eadcff2e3d79b5724f8e65 Mon Sep 17 00:00:00 2001 From: Satrajit Ghosh Date: Tue, 7 Mar 2017 11:08:27 -0500 Subject: [PATCH 40/44] fix: removed unnecessary test --- nipype/interfaces/fsl/tests/test_preprocess.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/nipype/interfaces/fsl/tests/test_preprocess.py b/nipype/interfaces/fsl/tests/test_preprocess.py index f9242c4b26..e2ef8962a7 100644 --- a/nipype/interfaces/fsl/tests/test_preprocess.py +++ b/nipype/interfaces/fsl/tests/test_preprocess.py @@ -569,10 +569,3 @@ def test_first_genfname(): value = first._gen_fname(name='original_segmentations') expected_value = os.path.abspath('segment_all_none_origsegs.nii.gz') assert value == expected_value - - -@pytest.mark.skipif(no_fsl(), reason="fsl is not installed") -def test_deprecation(): - interface = fsl.ApplyXfm() - assert isinstance(interface, fsl.ApplyXFM) - From 6286ed8801c12610069a7bde39fce1577ba42f59 Mon Sep 17 00:00:00 2001 From: Jaime Arias Date: Thu, 9 Mar 2017 21:05:15 +0100 Subject: [PATCH 41/44] fixing related files --- nipype/utils/filemanip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index ca5cd66f07..24f53229db 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -30,7 +30,7 @@ related_filetype_sets = [ - ('.hdr', '.img', '.mat'), + ('.hdr', '.img', '.mat', '.nii'), ('.BRIK', '.HEAD'), ] From f41abd9e7e2162375cc56013c2312eacd97b8963 Mon Sep 17 00:00:00 2001 From: Jaime Arias Date: Fri, 10 Mar 2017 22:54:26 +0100 Subject: [PATCH 42/44] improving solution and updating tests for related_files function --- nipype/utils/filemanip.py | 3 ++- nipype/utils/tests/test_filemanip.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index 24f53229db..6d27e56aa0 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -30,7 +30,8 @@ related_filetype_sets = [ - ('.hdr', '.img', '.mat', '.nii'), + ('.hdr', '.img', '.mat'), + ('.nii', '.mat'), ('.BRIK', '.HEAD'), ] diff --git a/nipype/utils/tests/test_filemanip.py b/nipype/utils/tests/test_filemanip.py index bf321c5b9c..eba0794e52 100644 --- a/nipype/utils/tests/test_filemanip.py +++ b/nipype/utils/tests/test_filemanip.py @@ -324,7 +324,7 @@ def test_json(): ('/path/test.hdr', 3, ['/path/test.hdr', '/path/test.img', '/path/test.mat']), ('/path/test.BRIK', 2, ['/path/test.BRIK', '/path/test.HEAD']), ('/path/test.HEAD', 2, ['/path/test.BRIK', '/path/test.HEAD']), - ('/path/foo.nii', 1, []) + ('/path/foo.nii', 2, ['/path/foo.nii', '/path/foo.mat']) ]) def test_related_files(file, length, expected_files): related_files = get_related_files(file) From d6bcef9ddceac5e1742c63000976eaa43eb49d4b Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sun, 5 Mar 2017 11:39:38 -0600 Subject: [PATCH 43/44] FIX: AntsJointFusion unicode command line formatting When strings are formatted in unicode, then the format of the AntsJointFusion -g, -t flags is not the same as the python string representations of lists. These flags need to be unpacked one-by-one and a new string representation needs to be provided on the command line. --- nipype/interfaces/ants/segmentation.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index d71ec104de..6594719b09 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1129,11 +1129,28 @@ def _format_arg(self, opt, spec, val): retval = '' if not isdefined(self.inputs.out_label_fusion): retval = '-o {0}'.format(self.inputs.out_intensity_fusion_name_format) + elif opt == 'atlas_image': + atlas_image_cmd=" ".join( + [ '-g [{0}]'.format(",".join( + fn for fn in ai) ) for ai in self.inputs.atlas_image] + ) + retval = atlas_image_cmd + elif opt == 'target_image': + target_image_cmd=" ".join( + [ '-t [{0}]'.format(",".join( + fn for fn in ai) ) for ai in self.inputs.target_image] + ) + retval = target_image_cmd + elif opt == 'atlas_segmentation_image': + assert len(val) == len(self.inputs.atlas_image), "Number of specified " \ + "segmentations should be identical to the number of atlas image " \ + "sets {0}!={1}".format(len(val), len(self.inputs.atlas_image)) + atlas_segmentation_image_cmd=" ".join( + [ '-t [{0}]'.format( fn ) for fn in self.inputs.atlas_segmentation_image ] + ) + retval = atlas_segmentation_image_cmd else: - if opt == 'atlas_segmentation_image': - assert len(val) == len(self.inputs.atlas_image), "Number of specified " \ - "segmentations should be identical to the number of atlas image " \ - "sets {0}!={1}".format(len(val), len(self.inputs.atlas_image)) + return super(ANTSCommand, self)._format_arg(opt, spec, val) return retval From 59a146d5e7eb226aff4183ee3a51c5b4d9d7fb4f Mon Sep 17 00:00:00 2001 From: oesteban Date: Mon, 13 Mar 2017 15:12:09 -0700 Subject: [PATCH 44/44] [FIX] Doctest of antsJointFusion failing The doctest of antsJointFusion was failing since #1862, these changes hopefully fix this problem without breaking the correct functionality of the interface. Also corrected what I suspect is an error: -l was replaced by -t for the segmentations. --- nipype/interfaces/ants/segmentation.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index 6594719b09..dfb8997372 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1130,28 +1130,29 @@ def _format_arg(self, opt, spec, val): if not isdefined(self.inputs.out_label_fusion): retval = '-o {0}'.format(self.inputs.out_intensity_fusion_name_format) elif opt == 'atlas_image': - atlas_image_cmd=" ".join( - [ '-g [{0}]'.format(",".join( - fn for fn in ai) ) for ai in self.inputs.atlas_image] + atlas_image_cmd = " ".join( + ['-g [{0}]'.format(", ".join("'%s'" % fn for fn in ai)) + for ai in self.inputs.atlas_image] ) retval = atlas_image_cmd elif opt == 'target_image': - target_image_cmd=" ".join( - [ '-t [{0}]'.format(",".join( - fn for fn in ai) ) for ai in self.inputs.target_image] + target_image_cmd = " ".join( + ['-t [{0}]'.format(", ".join("'%s'" % fn for fn in ai)) + for ai in self.inputs.target_image] ) retval = target_image_cmd elif opt == 'atlas_segmentation_image': assert len(val) == len(self.inputs.atlas_image), "Number of specified " \ "segmentations should be identical to the number of atlas image " \ "sets {0}!={1}".format(len(val), len(self.inputs.atlas_image)) - atlas_segmentation_image_cmd=" ".join( - [ '-t [{0}]'.format( fn ) for fn in self.inputs.atlas_segmentation_image ] + + atlas_segmentation_image_cmd = " ".join( + ['-l {0}'.format(fn) for fn in self.inputs.atlas_segmentation_image] ) retval = atlas_segmentation_image_cmd else: - return super(ANTSCommand, self)._format_arg(opt, spec, val) + return super(AntsJointFusion, self)._format_arg(opt, spec, val) return retval def _list_outputs(self):