From 1f49bbbceb5e8e13ab3c1a44d8b92d8acd4d11ca Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sat, 26 May 2018 21:01:36 -0400 Subject: [PATCH 1/6] CI: Stop using Miniconda on Travis --- .travis.yml | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 74d5ebed4b..e7de4b9f55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,10 +10,24 @@ python: - 3.6 env: -- INSTALL_DEB_DEPENDECIES=true NIPYPE_EXTRAS="doc,tests,fmri,profiler" CI_SKIP_TEST=1 -- INSTALL_DEB_DEPENDECIES=false NIPYPE_EXTRAS="doc,tests,fmri,profiler" CI_SKIP_TEST=1 -- INSTALL_DEB_DEPENDECIES=true NIPYPE_EXTRAS="doc,tests,fmri,profiler,duecredit,ssh" CI_SKIP_TEST=1 -- INSTALL_DEB_DEPENDECIES=true NIPYPE_EXTRAS="doc,tests,fmri,profiler" PIP_FLAGS="--pre" CI_SKIP_TEST=1 + global: + - EXTRA_WHEELS="https://5cf40426d9f06eb7461d-6fe47d9331aba7cd62fc36c7196769e4.ssl.cf2.rackcdn.com" + - PRE_WHEELS="https://7933911d6844c6c53a7d-47bd50c35cd79bd838daf386af554a83.ssl.cf2.rackcdn.com" + - EXTRA_PIP_FLAGS="--find-links=$EXTRA_WHEELS" + matrix: + - INSTALL_DEB_DEPENDECIES=true + NIPYPE_EXTRAS="doc,tests,fmri,profiler" + CI_SKIP_TEST=1 + - INSTALL_DEB_DEPENDECIES=false + NIPYPE_EXTRAS="doc,tests,fmri,profiler" + CI_SKIP_TEST=1 + - INSTALL_DEB_DEPENDECIES=true + NIPYPE_EXTRAS="doc,tests,fmri,profiler,duecredit,ssh" + CI_SKIP_TEST=1 + - INSTALL_DEB_DEPENDECIES=true + NIPYPE_EXTRAS="doc,tests,fmri,profiler" + EXTRA_PIP_FLAGS="--pre $EXTRA_PIP_FLAGS --find-links $PRE_WHEELS" + CI_SKIP_TEST=1 addons: apt: @@ -39,23 +53,12 @@ before_install: export FSLOUTPUTTYPE=NIFTI_GZ; fi; -# handle python operations separately to reduce timeouts -- wget https://repo.continuum.io/miniconda/Miniconda${TRAVIS_PYTHON_VERSION:0:1}-latest-Linux-x86_64.sh - -O /home/travis/.cache/conda.sh -- bash ${HOME}/.cache/conda.sh -b -p ${HOME}/conda -- export PATH=${HOME}/conda/bin:$PATH -- hash -r -- conda config --set always_yes yes --set changeps1 no -- travis_retry conda update -q conda -- conda config --add channels conda-forge -- travis_retry conda install -y python=${TRAVIS_PYTHON_VERSION} icu - travis_retry pip install -r requirements.txt - travis_retry git clone https://github.com/INCF/pybids.git ${HOME}/pybids && pip install -e ${HOME}/pybids -- travis_retry pip install codecov install: -- travis_retry pip install $PIP_FLAGS -e .[$NIPYPE_EXTRAS] +- travis_retry pip install $EXTRA_PIP_FLAGS -e .[$NIPYPE_EXTRAS] script: - py.test -v --cov nipype --cov-config .coveragerc --cov-report xml:cov.xml -c nipype/pytest.ini --doctest-modules nipype From 55ee3f1c9ef3523bebb08bc53b410bfa4c847de4 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 29 May 2018 17:54:43 -0400 Subject: [PATCH 2/6] TEST: Use legacy printing for numpy arrays --- nipype/conftest.py | 3 +++ nipype/interfaces/image.py | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/nipype/conftest.py b/nipype/conftest.py index 9e646a2a4f..90d73cf699 100644 --- a/nipype/conftest.py +++ b/nipype/conftest.py @@ -1,6 +1,7 @@ import pytest import numpy import os +from distutils.version import LooseVersion DATADIR = os.path.realpath( os.path.join(os.path.dirname(__file__), 'testing/data')) @@ -19,3 +20,5 @@ def in_testing(request): # This seems to be a reliable way to distinguish tests from doctests if request.function is None: os.chdir(DATADIR) + if LooseVersion(numpy.__version__) >= LooseVersion('1.14'): + numpy.set_printoptions(legacy="1.13") diff --git a/nipype/interfaces/image.py b/nipype/interfaces/image.py index 64105de739..e7d31b41a1 100644 --- a/nipype/interfaces/image.py +++ b/nipype/interfaces/image.py @@ -61,10 +61,10 @@ class Reorient(SimpleInterface): 'segmentation0.nii.gz' >>> print(np.loadtxt(res.outputs.transform)) - [[1. 0. 0. 0.] - [0. 1. 0. 0.] - [0. 0. 1. 0.] - [0. 0. 0. 1.]] + [[ 1. 0. 0. 0.] + [ 0. 1. 0. 0.] + [ 0. 0. 1. 0.] + [ 0. 0. 0. 1.]] >>> reorient.inputs.orientation = 'RAS' >>> res = reorient.run() @@ -72,10 +72,10 @@ class Reorient(SimpleInterface): '.../segmentation0_ras.nii.gz' >>> print(np.loadtxt(res.outputs.transform)) - [[-1. 0. 0. 60.] - [ 0. -1. 0. 72.] - [ 0. 0. 1. 0.] - [ 0. 0. 0. 1.]] + [[ -1. 0. 0. 60.] + [ 0. -1. 0. 72.] + [ 0. 0. 1. 0.] + [ 0. 0. 0. 1.]] .. testcleanup:: From 1ea55de5262a7132771b4136ff32dfcae50fe635 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 30 May 2018 09:48:21 -0400 Subject: [PATCH 3/6] TEST: Normalize array printing ourselves --- nipype/conftest.py | 3 --- nipype/interfaces/image.py | 27 +++++++++++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/nipype/conftest.py b/nipype/conftest.py index 90d73cf699..9e646a2a4f 100644 --- a/nipype/conftest.py +++ b/nipype/conftest.py @@ -1,7 +1,6 @@ import pytest import numpy import os -from distutils.version import LooseVersion DATADIR = os.path.realpath( os.path.join(os.path.dirname(__file__), 'testing/data')) @@ -20,5 +19,3 @@ def in_testing(request): # This seems to be a reliable way to distinguish tests from doctests if request.function is None: os.chdir(DATADIR) - if LooseVersion(numpy.__version__) >= LooseVersion('1.14'): - numpy.set_printoptions(legacy="1.13") diff --git a/nipype/interfaces/image.py b/nipype/interfaces/image.py index e7d31b41a1..eab2c684df 100644 --- a/nipype/interfaces/image.py +++ b/nipype/interfaces/image.py @@ -50,6 +50,13 @@ class Reorient(SimpleInterface): Examples -------- + .. testsetup:: + + >>> def print_affine(matrix): + ... print(str(matrix).translate(dict(zip(b'[]', ' ')))) + + .. doctest:: + If an image is not reoriented, the original file is not modified >>> import numpy as np @@ -60,22 +67,22 @@ class Reorient(SimpleInterface): >>> res.outputs.out_file 'segmentation0.nii.gz' - >>> print(np.loadtxt(res.outputs.transform)) - [[ 1. 0. 0. 0.] - [ 0. 1. 0. 0.] - [ 0. 0. 1. 0.] - [ 0. 0. 0. 1.]] + >>> print_affine(np.loadtxt(res.outputs.transform)) + 1. 0. 0. 0. + 0. 1. 0. 0. + 0. 0. 1. 0. + 0. 0. 0. 1. >>> reorient.inputs.orientation = 'RAS' >>> res = reorient.run() >>> res.outputs.out_file # doctest: +ELLIPSIS '.../segmentation0_ras.nii.gz' - >>> print(np.loadtxt(res.outputs.transform)) - [[ -1. 0. 0. 60.] - [ 0. -1. 0. 72.] - [ 0. 0. 1. 0.] - [ 0. 0. 0. 1.]] + >>> print_affine(np.loadtxt(res.outputs.transform)) + -1. 0. 0. 60. + 0. -1. 0. 72. + 0. 0. 1. 0. + 0. 0. 0. 1. .. testcleanup:: From 6bca39873ea91e4bc73262a5c3d851eb62f33256 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 30 May 2018 10:19:02 -0400 Subject: [PATCH 4/6] PY2 compatibility --- nipype/interfaces/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/image.py b/nipype/interfaces/image.py index eab2c684df..0a16aaef62 100644 --- a/nipype/interfaces/image.py +++ b/nipype/interfaces/image.py @@ -53,7 +53,7 @@ class Reorient(SimpleInterface): .. testsetup:: >>> def print_affine(matrix): - ... print(str(matrix).translate(dict(zip(b'[]', ' ')))) + ... print(str(matrix).replace(']', ' ').replace('[', ' ')) .. doctest:: From eca32f64e5aedcec52fff78142d0170043a0bc62 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 5 Jun 2018 08:51:51 -0400 Subject: [PATCH 5/6] DOCTEST: De-indent or remove testsetup blocks --- nipype/interfaces/base/core.py | 13 ---- nipype/interfaces/dcm2nii.py | 20 ++---- nipype/interfaces/image.py | 98 +++++++++++++------------- nipype/interfaces/io.py | 12 ---- nipype/interfaces/niftyreg/regutils.py | 12 ---- 5 files changed, 52 insertions(+), 103 deletions(-) diff --git a/nipype/interfaces/base/core.py b/nipype/interfaces/base/core.py index e5c7fb2ca6..9b8650100f 100644 --- a/nipype/interfaces/base/core.py +++ b/nipype/interfaces/base/core.py @@ -692,14 +692,6 @@ class SimpleInterface(BaseInterface): Examples -------- - .. testsetup:: - - >>> from .specs import TraitedSpec - >>> tmp = getfixture('tmpdir') - >>> old = tmp.chdir() # changing to a temporary directory - - .. doctest:: - >>> def double(x): ... return 2 * x ... @@ -721,11 +713,6 @@ class SimpleInterface(BaseInterface): >>> dbl.inputs.x = 2 >>> dbl.run().outputs.doubled 4.0 - - .. testsetup:: - - >>> os.chdir(old.strpath) - """ def __init__(self, from_file=None, resource_monitor=None, **inputs): diff --git a/nipype/interfaces/dcm2nii.py b/nipype/interfaces/dcm2nii.py index 3fa657fab3..db0c0ec4cf 100644 --- a/nipype/interfaces/dcm2nii.py +++ b/nipype/interfaces/dcm2nii.py @@ -106,26 +106,14 @@ class Dcm2nii(CommandLine): Examples ======== - .. testsetup:: - - >>> tmp = getfixture('tmpdir') - >>> old = tmp.chdir() # changing to a temporary directory - - .. doctest:: - >>> from nipype.interfaces.dcm2nii import Dcm2nii >>> converter = Dcm2nii() - >>> converter.inputs.source_names = [os.path.join(datadir, 'functional_1.dcm'), os.path.join(datadir, 'functional_2.dcm')] + >>> converter.inputs.source_names = ['functional_1.dcm', 'functional_2.dcm'] >>> converter.inputs.gzip_output = True >>> converter.inputs.output_dir = '.' - >>> converter.cmdline #doctest: +ELLIPSIS - 'dcm2nii -a y -c y -b config.ini -v y -d y -e y -g y -i n -n y -o . -p y -x n -f n ...functional_1.dcm' - - .. testsetup:: - - >>> os.chdir(old.strpath) - - """ + >>> converter.cmdline # doctest: +ELLIPSIS + 'dcm2nii -a y -c y -b config.ini -v y -d y -e y -g y -i n -n y -o . -p y -x n -f n functional_1.dcm' +""" input_spec = Dcm2niiInputSpec output_spec = Dcm2niiOutputSpec diff --git a/nipype/interfaces/image.py b/nipype/interfaces/image.py index 0a16aaef62..ded7589f15 100644 --- a/nipype/interfaces/image.py +++ b/nipype/interfaces/image.py @@ -32,65 +32,63 @@ class ReorientOutputSpec(TraitedSpec): class Reorient(SimpleInterface): """Conform an image to a given orientation - Flips and reorder the image data array so that the axes match the - directions indicated in ``orientation``. - The default ``RAS`` orientation corresponds to the first axis being ordered - from left to right, the second axis from posterior to anterior, and the - third axis from inferior to superior. +Flips and reorder the image data array so that the axes match the +directions indicated in ``orientation``. +The default ``RAS`` orientation corresponds to the first axis being ordered +from left to right, the second axis from posterior to anterior, and the +third axis from inferior to superior. - For oblique images, the original orientation is considered to be the - closest plumb orientation. +For oblique images, the original orientation is considered to be the +closest plumb orientation. - No resampling is performed, and thus the output image is not de-obliqued - or registered to any other image or template. +No resampling is performed, and thus the output image is not de-obliqued +or registered to any other image or template. - The effective transform is calculated from the original affine matrix to - the reoriented affine matrix. +The effective transform is calculated from the original affine matrix to +the reoriented affine matrix. - Examples - -------- +Examples +-------- - .. testsetup:: +If an image is not reoriented, the original file is not modified + +.. testsetup:: >>> def print_affine(matrix): ... print(str(matrix).replace(']', ' ').replace('[', ' ')) - .. doctest:: - - If an image is not reoriented, the original file is not modified - - >>> import numpy as np - >>> from nipype.interfaces.image import Reorient - >>> reorient = Reorient(orientation='LPS') - >>> reorient.inputs.in_file = 'segmentation0.nii.gz' - >>> res = reorient.run() - >>> res.outputs.out_file - 'segmentation0.nii.gz' - - >>> print_affine(np.loadtxt(res.outputs.transform)) - 1. 0. 0. 0. - 0. 1. 0. 0. - 0. 0. 1. 0. - 0. 0. 0. 1. - - >>> reorient.inputs.orientation = 'RAS' - >>> res = reorient.run() - >>> res.outputs.out_file # doctest: +ELLIPSIS - '.../segmentation0_ras.nii.gz' - - >>> print_affine(np.loadtxt(res.outputs.transform)) - -1. 0. 0. 60. - 0. -1. 0. 72. - 0. 0. 1. 0. - 0. 0. 0. 1. - - .. testcleanup:: - - >>> import os - >>> os.unlink(res.outputs.out_file) - >>> os.unlink(res.outputs.transform) - - """ +>>> import numpy as np +>>> from nipype.interfaces.image import Reorient +>>> reorient = Reorient(orientation='LPS') +>>> reorient.inputs.in_file = 'segmentation0.nii.gz' +>>> res = reorient.run() +>>> res.outputs.out_file +'segmentation0.nii.gz' + +>>> print_affine(np.loadtxt(res.outputs.transform)) +1. 0. 0. 0. +0. 1. 0. 0. +0. 0. 1. 0. +0. 0. 0. 1. + +>>> reorient.inputs.orientation = 'RAS' +>>> res = reorient.run() +>>> res.outputs.out_file # doctest: +ELLIPSIS +'.../segmentation0_ras.nii.gz' + +>>> print_affine(np.loadtxt(res.outputs.transform)) +-1. 0. 0. 60. + 0. -1. 0. 72. + 0. 0. 1. 0. + 0. 0. 0. 1. + +.. testcleanup:: + + >>> import os + >>> os.unlink(res.outputs.out_file) + >>> os.unlink(res.outputs.transform) + +""" input_spec = ReorientInputSpec output_spec = ReorientOutputSpec diff --git a/nipype/interfaces/io.py b/nipype/interfaces/io.py index 5135656d37..c9487ca5cd 100644 --- a/nipype/interfaces/io.py +++ b/nipype/interfaces/io.py @@ -2585,13 +2585,6 @@ class JSONFileGrabber(IOBase): Example ------- - .. testsetup:: - - >>> tmp = getfixture('tmpdir') - >>> old = tmp.chdir() # changing to a temporary directory - - .. doctest:: - >>> import pprint >>> from nipype.interfaces.io import JSONFileGrabber >>> jsonSource = JSONFileGrabber() @@ -2603,11 +2596,6 @@ class JSONFileGrabber(IOBase): >>> res = jsonSource.run() >>> pprint.pprint(res.outputs.get()) # doctest:, +ELLIPSIS {'param1': 'exampleStr', 'param2': 4, 'param3': 1.0} - - .. testsetup:: - - >>> os.chdir(old.strpath) - """ input_spec = JSONFileGrabberInputSpec output_spec = DynamicTraitedSpec diff --git a/nipype/interfaces/niftyreg/regutils.py b/nipype/interfaces/niftyreg/regutils.py index 669ed92d1c..c90aa53bed 100644 --- a/nipype/interfaces/niftyreg/regutils.py +++ b/nipype/interfaces/niftyreg/regutils.py @@ -450,13 +450,6 @@ class RegAverage(NiftyRegCommand): Examples -------- - .. testsetup:: - - >>> tmp = getfixture('tmpdir') - >>> old = tmp.chdir() # changing to temporary file - - .. doctest:: - >>> from nipype.interfaces import niftyreg >>> node = niftyreg.RegAverage() >>> one_file = 'im1.nii' @@ -465,11 +458,6 @@ class RegAverage(NiftyRegCommand): >>> node.inputs.avg_files = [one_file, two_file, three_file] >>> node.cmdline # doctest: +ELLIPSIS 'reg_average --cmd_file .../reg_average_cmd' - - .. testsetup:: - - >>> os.chdir(old.strpath) - """ _cmd = get_custom_path('reg_average') input_spec = RegAverageInputSpec From 2025a06e39da70c3c4d6a4a1cf4ae444f30d264a Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 5 Jun 2018 11:21:04 -0400 Subject: [PATCH 6/6] TEST: Import interface plumbing --- nipype/interfaces/base/core.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nipype/interfaces/base/core.py b/nipype/interfaces/base/core.py index 9b8650100f..ae87328e29 100644 --- a/nipype/interfaces/base/core.py +++ b/nipype/interfaces/base/core.py @@ -692,6 +692,9 @@ class SimpleInterface(BaseInterface): Examples -------- + >>> from nipype.interfaces.base import ( + ... SimpleInterface, BaseInterfaceInputSpec, TraitedSpec) + >>> def double(x): ... return 2 * x ...