From abd05f906309ff49a2777a0ad836e91588eb1b8e Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Thu, 1 Sep 2016 15:25:42 +0100 Subject: [PATCH] Started adding wsome test cases for fsl.data.image. --- tests/conftest.py | 33 +++++++ tests/test_image.py | 37 ++++++++ tests/test_imagewrapper.py | 180 +++++++++++++++++++------------------ 3 files changed, 164 insertions(+), 86 deletions(-) create mode 100644 tests/conftest.py create mode 100644 tests/test_image.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..0047f5247 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# conftest.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import pytest + + +def pytest_addoption(parser): + parser.addoption('--niters', + type=int, + action='store', + default=150, + help='Number of test iterations for imagewrapper') + + parser.addoption('--testdir', + action='store', + help='FSLeyes test data directory') + + + +@pytest.fixture +def testdir(request): + """FSLeyes test data directory.""" + return request.config.getoption('--testdir') + + +@pytest.fixture +def niters(request): + """Number of test iterations.""" + return request.config.getoption('--niters') diff --git a/tests/test_image.py b/tests/test_image.py new file mode 100644 index 000000000..ff722fc2b --- /dev/null +++ b/tests/test_image.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# +# test_image.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import os.path as op +import logging + + +import numpy as np +import nibabel as nib + +import fsl.data.image as fslimage + + +# Need to test: +# - Create image from file name (create a temp .nii.gz) +# - Create image from existing nibabel image +# - Create image from numpy array +# - calcRange +# - loadData + +def test_load(testdir): + + assert testdir is not None + + fslimage.Image(op.join(testdir, 'nifti_formats', 'compressed')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'compressed.nii.gz')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'uncompressed')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'uncompressed.nii')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'img_hdr_pair')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'img_hdr_pair.img')) + fslimage.Image(op.join(testdir, 'nifti_formats', 'img_hdr_pair.hdr')) + + diff --git a/tests/test_imagewrapper.py b/tests/test_imagewrapper.py index b2f5279e0..0692f1da2 100644 --- a/tests/test_imagewrapper.py +++ b/tests/test_imagewrapper.py @@ -5,6 +5,7 @@ # Author: Paul McCarthy <pauldmccarthy@gmail.com> +from __future__ import print_function import collections import random @@ -17,6 +18,12 @@ import fsl.data.image as image import fsl.data.imagewrapper as imagewrap +real_print = print + +def print(*args, **kwargs): + pass + + def setup_module(): pass @@ -24,13 +31,14 @@ def teardown_module(): pass + def random_coverage(shape, vol_limit=None): ndims = len(shape) - 1 nvols = shape[-1] - print '{}D (shape: {}, {} vectors/slices/volumes)'.format( - ndims, shape, nvols) + print('{}D (shape: {}, {} vectors/slices/volumes)'.format( + ndims, shape, nvols)) # Generate a random coverage. # We use the same coverage for @@ -304,10 +312,10 @@ def test_adjustCoverage(): assert np.all(imagewrap.adjustCoverage(coverage, expansion) == result) -def test_sliceOverlap(niters=150): +def test_sliceOverlap(niters): # A bunch of random coverages - for i in range(niters): + for _ in range(niters): # 2D, 3D or 4D? # ndims is the number of dimensions @@ -324,27 +332,27 @@ def test_sliceOverlap(niters=150): # Generate some slices that should # be contained within the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'in') assert imagewrap.sliceOverlap(slices, coverage) == imagewrap.OVERLAP_ALL # Generate some slices that should # overlap with the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'overlap') assert imagewrap.sliceOverlap(slices, coverage) == imagewrap.OVERLAP_SOME # Generate some slices that should # be outside of the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'out') assert imagewrap.sliceOverlap(slices, coverage) == imagewrap.OVERLAP_NONE -def test_sliceCovered(niters=150): +def test_sliceCovered(niters): # A bunch of random coverages - for i in range(niters): + for _ in range(niters): # 2D, 3D or 4D? # ndims is the number of dimensions @@ -361,19 +369,19 @@ def test_sliceCovered(niters=150): # Generate some slices that should # be contained within the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'in') assert imagewrap.sliceCovered(slices, coverage) # Generate some slices that should # overlap with the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'overlap') assert not imagewrap.sliceCovered(slices, coverage) # Generate some slices that should # be outside of the coverage - for j in range(niters): + for _ in range(niters): slices = random_slices(coverage, shape, 'out') assert not imagewrap.sliceCovered(slices, coverage) @@ -389,8 +397,8 @@ def test_sliceCovered(niters=150): def _test_expansion(coverage, slices, volumes, expansions): ndims = coverage.shape[1] - print - print 'Slice: "{}"'.format(" ".join(["{:2d} {:2d}".format(l, h) for l, h in slices])) + print() + print('Slice: "{}"'.format(" ".join(["{:2d} {:2d}".format(l, h) for l, h in slices]))) # Figure out what the adjusted # coverage should look like (assumes @@ -415,9 +423,9 @@ def _test_expansion(coverage, slices, volumes, expansions): # Bin the expansions by volume expsByVol = collections.defaultdict(list) for vol, exp in zip(volumes, expansions): - print ' {:3d}: "{}"'.format( + print(' {:3d}: "{}"'.format( int(vol), - " ".join(["{:2d} {:2d}".format(int(l), int(h)) for l, h in exp])) + " ".join(["{:2d} {:2d}".format(int(l), int(h)) for l, h in exp]))) expsByVol[vol].append(exp) for point in points: @@ -456,26 +464,26 @@ def _test_expansion(coverage, slices, volumes, expansions): raise AssertionError(point) -def test_calcExpansionNoCoverage(niters=150): +def test_calcExpansionNoCoverage(niters): - for i in range(niters): + for _ in range(niters): ndims = random.choice((2, 3, 4)) - 1 shape = np.random.randint(5, 100, size=ndims + 1) shape[-1] = np.random.randint(1, 8) coverage = np.zeros((2, ndims, shape[-1])) coverage[:] = np.nan - print - print '-- Out --' - for j in range(niters): + print() + print('-- Out --' ) + for _ in range(niters): slices = random_slices(coverage, shape, 'out') vols, exps = imagewrap.calcExpansion(slices, coverage) _test_expansion(coverage, slices, vols, exps) -def test_calcExpansion(niters=150): +def test_calcExpansion(niters): - for i in range(niters): + for _ in range(niters): ndims = random.choice((2, 3, 4)) - 1 shape = np.random.randint(5, 60, size=ndims + 1) @@ -484,12 +492,12 @@ def test_calcExpansion(niters=150): cov = [(lo, hi) for lo, hi in coverage[:, :, 0].T] - print 'Shape: {}'.format(shape) - print 'Coverage: {}'.format(cov) + print('Shape: {}'.format(shape)) + print('Coverage: {}'.format(cov)) - print - print '-- In --' - for j in range(niters): + print() + print('-- In --') + for _ in range(niters): slices = random_slices(coverage, shape, 'in') vols, exps = imagewrap.calcExpansion(slices, coverage) @@ -497,24 +505,24 @@ def test_calcExpansion(niters=150): # slice that's inside the coverage assert len(vols) == 0 and len(exps) == 0 - print - print '-- Overlap --' - for j in range(niters): + print() + print('-- Overlap --' ) + for _ in range(niters): slices = random_slices(coverage, shape, 'overlap') vols, exps = imagewrap.calcExpansion(slices, coverage) _test_expansion(coverage, slices, vols, exps) - print - print '-- Out --' - for j in range(niters): + print() + print('-- Out --' ) + for _ in range(niters): slices = random_slices(coverage, shape, 'out') vols, exps = imagewrap.calcExpansion(slices, coverage) _test_expansion(coverage, slices, vols, exps) -def test_ImageWrapper_read(niters=150): +def test_ImageWrapper_read(niters): - for i in range(niters): + for _ in range(niters): # Generate an image with a number of volumes ndims = random.choice((2, 3, 4)) - 1 @@ -530,10 +538,10 @@ def test_ImageWrapper_read(niters=150): volRanges = [(np.min(data[..., 0]), np.max(data[..., 0]))] - for i in range(1, nvols): - data[..., i] = data[..., 0] * (i + 1) - volRanges.append((np.min(data[..., i]), - np.max(data[..., i]))) + for vol in range(1, nvols): + data[..., vol] = data[..., 0] * (vol + 1) + volRanges.append((np.min(data[..., vol]), + np.max(data[..., vol]))) img = nib.Nifti1Image(data, np.eye(4)) wrapper = imagewrap.ImageWrapper(img, loadData=False) @@ -542,7 +550,7 @@ def test_ImageWrapper_read(niters=150): # through the image wrapper with a # bunch of random volume orderings. - for i in range(niters): + for _ in range(niters): ordering = list(range(nvols)) random.shuffle(ordering) @@ -570,11 +578,11 @@ def test_ImageWrapper_read(niters=150): else: assert wrapper.covered -def test_ImageWrapper_write_out(niters=150): +def test_ImageWrapper_write_out(niters): # This is HORRIBLE # Generate a bunch of random coverages - for i in range(niters): + for _ in range(niters): # Generate an image with just two volumes. We're only # testing within-volume modifications here. @@ -588,13 +596,13 @@ def test_ImageWrapper_write_out(niters=150): # The data range of each volume # increases sequentially data[..., 0] = np.random.randint(-5, 6, shape[:-1]) - for i in range(1, nvols): - data[..., i] = data[..., 0] * (i + 1) + for vol in range(1, nvols): + data[..., vol] = data[..., 0] * (vol + 1) # Generate a random coverage cov = random_coverage(shape, vol_limit=1) - print 'This is the coverage: {}'.format(cov) + print('This is the coverage: {}'.format(cov)) img = nib.Nifti1Image(data, np.eye(4)) wrapper = imagewrap.ImageWrapper(img) @@ -603,7 +611,7 @@ def test_ImageWrapper_write_out(niters=150): # Now, we'll simulate some writes # outside of the coverage area. - for i in range(niters): + for _ in range(niters): # Generate some slices outside # of the coverage area, making @@ -622,8 +630,8 @@ def test_ImageWrapper_write_out(niters=150): sliceshape = sliceshape[:-1] break - print '---------------' - print 'Slice {}'.format(slices) + print('---------------') + print('Slice {}'.format(slices)) # Expected wrapper coverage after the write expCov = imagewrap.adjustCoverage(cov[..., 0], slices) @@ -661,9 +669,9 @@ def test_ImageWrapper_write_out(niters=150): wrapper = imagewrap.ImageWrapper(img) applyCoverage(wrapper, cov) - print 'ndims', ndims - print 'sliceshape', sliceshape - print 'sliceobjs', sliceobjs + print('ndims', ndims) + print('sliceshape', sliceshape) + print('sliceobjs', sliceobjs) newData = np.linspace(rlo, rhi, np.prod(sliceshape)) newData = newData.reshape(sliceshape) @@ -671,7 +679,7 @@ def test_ImageWrapper_write_out(niters=150): # Make sure that the expected low/high values # are present in the data being written - print 'Writing data (shape: {})'.format(newData.shape) + print('Writing data (shape: {})'.format(newData.shape)) oldCov = wrapper.coverage(0) @@ -680,32 +688,32 @@ def test_ImageWrapper_write_out(niters=150): expLo, expHi = coverageDataRange(img.get_data(), cov, slices) newLo, newHi = wrapper.dataRange - print 'Old range: {} - {}'.format(clo, chi) - print 'Sim range: {} - {}'.format(rlo, rhi) - print 'Exp range: {} - {}'.format(expLo, expHi) - print 'NewDat range: {} - {}'.format(newData.min(), newData.max()) - print 'Data range: {} - {}'.format(data.min(), data.max()) - print 'Expand range: {} - {}'.format(elo, ehi) - print 'New range: {} - {}'.format(newLo, newHi) + print('Old range: {} - {}'.format(clo, chi)) + print('Sim range: {} - {}'.format(rlo, rhi)) + print('Exp range: {} - {}'.format(expLo, expHi)) + print('NewDat range: {} - {}'.format(newData.min(), newData.max())) + print('Data range: {} - {}'.format(data.min(), data.max())) + print('Expand range: {} - {}'.format(elo, ehi)) + print('New range: {} - {}'.format(newLo, newHi)) newCov = wrapper.coverage(0) - print 'Old coverage: {}'.format(oldCov) - print 'New coverage: {}'.format(newCov) - print 'Expected coverage: {}'.format(expCov) - print - print + print('Old coverage: {}'.format(oldCov)) + print('New coverage: {}'.format(newCov)) + print('Expected coverage: {}'.format(expCov)) + print() + print() assert np.all(newCov == expCov) assert np.isclose(newLo, expLo) assert np.isclose(newHi, expHi) - print '--------------' + print('--------------') -def test_ImageWrapper_write_in_overlap(niters=150): +def test_ImageWrapper_write_in_overlap(niters): # Generate a bunch of random coverages - for i in range(niters): + for _ in range(niters): # Generate an image with just two volumes. We're only # testing within-volume modifications here. @@ -719,8 +727,8 @@ def test_ImageWrapper_write_in_overlap(niters=150): # The data range of each volume # increases sequentially data[..., 0] = np.random.randint(-5, 6, shape[:-1]) - for i in range(1, nvols): - data[..., i] = data[..., 0] * (i + 1) + for vol in range(1, nvols): + data[..., vol] = data[..., 0] * (vol + 1) # Generate a random coverage cov = random_coverage(shape, vol_limit=1) @@ -728,7 +736,7 @@ def test_ImageWrapper_write_in_overlap(niters=150): # Now, we'll simulate some writes # which are contained within, or # overlap with, the initial coverage - for i in range(niters): + for _ in range(niters): # Generate some slices outside # of the coverage area, making @@ -757,7 +765,7 @@ def test_ImageWrapper_write_in_overlap(niters=150): nullCov[:] = np.nan expCov = imagewrap.adjustCoverage(nullCov[..., 0], slices) - for i in range(10): + for _ in range(10): rlo = rfloat(data.min() - 100, data.max() + 100) rhi = rfloat(rlo, data.max() + 100) @@ -770,15 +778,15 @@ def test_ImageWrapper_write_in_overlap(niters=150): newData = newData.reshape(sliceshape) - print 'Old range: {} - {}'.format(*wrapper.dataRange) + print('Old range: {} - {}'.format(*wrapper.dataRange)) wrapper[tuple(sliceobjs)] = newData newCov = wrapper.coverage(0) newLo, newHi = wrapper.dataRange - print 'Expected range: {} - {}'.format(rlo, rhi) - print 'New range: {} - {}'.format(newLo, newHi) + print('Expected range: {} - {}'.format(rlo, rhi)) + print('New range: {} - {}'.format(newLo, newHi)) assert np.all(newCov == expCov) @@ -786,9 +794,9 @@ def test_ImageWrapper_write_in_overlap(niters=150): assert np.isclose(newHi, rhi) -def test_ImageWrapper_write_different_volume(niters=150): +def test_ImageWrapper_write_different_volume(niters): - for i in range(niters): + for _ in range(niters): # Generate an image with several volumes. ndims = random.choice((2, 3, 4)) - 1 @@ -801,8 +809,8 @@ def test_ImageWrapper_write_different_volume(niters=150): # The data range of each volume # increases sequentially data[..., 0] = np.random.randint(-5, 6, shape[:-1]) - for i in range(1, nvols): - data[..., i] = data[..., 0] * (i + 1) + for vol in range(1, nvols): + data[..., vol] = data[..., 0] * (vol + 1) # Generate a random coverage @@ -826,14 +834,14 @@ def test_ImageWrapper_write_different_volume(niters=150): covlo, covhi = coverageDataRange(data, cov) - print 'Coverage: {} [{} - {}]'.format( + print('Coverage: {} [{} - {}]'.format( [(lo, hi) for lo, hi in cov[:, :, covvlo].T], - covvlo, covvhi) + covvlo, covvhi)) # Now, we'll simulate some writes # on volumes that are not in the # coverage - for i in range(niters): + for _ in range(niters): # Generate a slice, making # sure that the slice covers @@ -843,7 +851,7 @@ def test_ImageWrapper_write_different_volume(niters=150): shape, random.choice(('out', 'in', 'overlap'))) - # print slices + # print(slices) # Clobber the slice volume range # so it does not overlap with the @@ -923,7 +931,7 @@ def test_ImageWrapper_write_different_volume(niters=150): assert np.isclose(newHi, ehi) -def test_collapseExpansions(niters=500): +def test_collapseExpansions(niters): def expEq(exp1, exp2): @@ -943,7 +951,7 @@ def test_collapseExpansions(niters=500): return not ((r1lo > r2hi) or (r1hi < r2lo) or \ (r2lo > r1hi) or (r2hi < r1lo)) - for i in range(niters): + for _ in range(niters): # Generate a random coverage shape ndims = random.choice((2, 3, 4)) - 1 @@ -957,7 +965,7 @@ def test_collapseExpansions(niters=500): exps = [] expected = [] - for i in range(10): + for _ in range(10): # Generate a random slice with a volume # range that doesn't overlap with, and -- GitLab