Skip to content
Snippets Groups Projects
Commit 5d431a9f authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Nearly 100% coverage for transform module

parent 5f2bd94c
No related branches found
No related tags found
No related merge requests found
Showing
with 86540 additions and 7 deletions
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
# Author: Paul McCarthy <pauldmccarthy@gmail.com> # Author: Paul McCarthy <pauldmccarthy@gmail.com>
# #
import os.path as op import glob
import os.path as op
import itertools as it
import numpy as np
import numpy as np import pytest
import fsl.utils.transform as transform import fsl.utils.transform as transform
...@@ -108,7 +111,7 @@ def test_compose_and_decompose(): ...@@ -108,7 +111,7 @@ def test_compose_and_decompose():
scales, offsets, rotations = transform.decompose(xform) scales, offsets, rotations = transform.decompose(xform)
result = transform.compose(scales, offsets, rotations) result = transform.compose(scales, offsets, rotations)
assert np.all(np.isclose(xform, result)) assert np.all(np.isclose(xform, result, atol=1e-5))
# The decompose function does not support a # The decompose function does not support a
# different rotation origin, but we test # different rotation origin, but we test
...@@ -117,4 +120,136 @@ def test_compose_and_decompose(): ...@@ -117,4 +120,136 @@ def test_compose_and_decompose():
scales, offsets, rotations = transform.decompose(xform) scales, offsets, rotations = transform.decompose(xform)
result = transform.compose(scales, offsets, rotations, [0, 0, 0]) result = transform.compose(scales, offsets, rotations, [0, 0, 0])
assert np.all(np.isclose(xform, result)) assert np.all(np.isclose(xform, result, atol=1e-5))
def test_axisBounds():
testfile = op.join(datadir, 'test_transform_test_axisBounds.txt')
lines = readlines(testfile)
ntests = len(lines) / 6
def readTest(testnum):
tlines = lines[testnum * 6: testnum * 6 + 6]
params = [p.strip() for p in tlines[0].split(',')]
shape = [int(s) for s in params[0].split()]
origin = params[1]
boundary = None if params[2] == 'None' else params[2]
xform = np.genfromtxt(tlines[1:5])
expected = np.genfromtxt([tlines[5]])
expected = (expected[:3], expected[3:])
return shape, origin, boundary, xform, expected
allAxes = list(it.chain(
range(0, 1, 2),
it.permutations((0, 1, 2), 1),
it.permutations((0, 1, 2), 2),
it.permutations((0, 1, 2), 3)))
for i in range(ntests):
shape, origin, boundary, xform, expected = readTest(i)
print('Test {}'.format(i))
print(' shape {}'.format(shape))
print(' origin {}'.format(origin))
print(' boundary {}'.format(boundary))
for axes in allAxes:
result = transform.axisBounds(shape,
xform,
axes=axes,
origin=origin,
boundary=boundary)
exp = expected[0][(axes,)], expected[1][(axes,)]
assert np.all(np.isclose(exp, result))
# Do some parameter checks on
# the first test in the file
# which has origin == centre
for i in range(ntests):
shape, origin, boundary, xform, expected = readTest(i)
if origin == 'centre':
break
# US-spelling
assert np.all(np.isclose(
expected,
transform.axisBounds(
shape, xform, origin='center', boundary=boundary)))
# Bad origin/boundary values
with pytest.raises(ValueError):
transform.axisBounds(shape, xform, origin='Blag', boundary=boundary)
with pytest.raises(ValueError):
transform.axisBounds(shape, xform, origin=origin, boundary='Blufu')
def test_transform():
def is_orthogonal(xform):
"""Returns ``True`` if the given xform consists
solely of translations and scales.
"""
mask = np.array([[1, 0, 0, 1],
[0, 1, 0, 1],
[0, 0, 1, 1],
[0, 0, 0, 1]], dtype=np.bool)
return np.all((xform != 0) == mask)
coordfile = op.join(datadir, 'test_transform_test_transform_coords.txt')
testcoords = np.loadtxt(coordfile)
testpattern = op.join(datadir, 'test_transform_test_transform_??.txt')
testfiles = glob.glob(testpattern)
allAxes = list(it.chain(
range(0, 1, 2),
it.permutations((0, 1, 2), 1),
it.permutations((0, 1, 2), 2),
it.permutations((0, 1, 2), 3)))
for i, testfile in enumerate(testfiles):
lines = readlines(testfile)
xform = np.genfromtxt(lines[:4])
expected = np.genfromtxt(lines[ 4:])
result = transform.transform(testcoords, xform)
assert np.all(np.isclose(expected, result))
if not is_orthogonal(xform):
continue
for axes in allAxes:
atestcoords = testcoords[:, axes]
aexpected = expected[ :, axes]
aresult = transform.transform(atestcoords, xform, axes=axes)
assert np.all(np.isclose(aexpected, aresult))
# Pass in some bad data, expect an error
xform = np.eye(4)
badxform = np.eye(3)
badcoords = np.random.randint(1, 10, (10, 4))
coords = badcoords[:, :3]
with pytest.raises(IndexError):
transform.transform(coords, badxform)
with pytest.raises(ValueError):
transform.transform(badcoords, xform)
with pytest.raises(ValueError):
transform.transform(badcoords.reshape(5, 2, 4), xform)
with pytest.raises(ValueError):
transform.transform(badcoords.reshape(5, 2, 4), xform, axes=1)
with pytest.raises(ValueError):
transform.transform(badcoords[:, (1, 2, 3)], xform, axes=[1, 2])
This diff is collapsed.
# Test data for test_transform:test_compose. # Test data for test_transform:test_compose_and_decompose.
# #
# Each test is just an affine transformation matrix. # Each test is just an affine transformation matrix.
# The matrix is decomposed into its components, # The matrix is decomposed into its components,
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0
-1.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
...@@ -55,12 +54,58 @@ ...@@ -55,12 +54,58 @@
-0.0159784155 1.6056689296 1.1880787388 -16.2943532298 -0.0159784155 1.6056689296 1.1880787388 -16.2943532298
-0.2093817023 -1.640493784 0.9565424959 66.1123321137 -0.2093817023 -1.640493784 0.9565424959 66.1123321137
0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0
-1.1974397443 -0.8580717933 -0.3645386503 -50.0240993667 -1.1974397443 -0.8580717933 -0.3645386503 -50.0240993667
-0.7458801726 1.1196201539 -0.5710576979 -106.3700007704 -0.7458801726 1.1196201539 -0.5710576979 -106.3700007704
0.7128023509 -0.2699020211 -1.2099478647 -7.4191935569 0.7128023509 -0.2699020211 -1.2099478647 -7.4191935569
0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0
-1.000000 0.000000 -0.000000 0.000000
0.000000 1.000000 -0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000
1.000000 0.000000 -0.000000 0.000000
0.000000 1.000000 -0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000
-2.000000 0.000000 -0.000000 90.000000
0.000000 2.000000 -0.000000 -126.000000
0.000000 0.000000 2.000000 -72.000000
0.000000 0.000000 0.000000 1.000000
-1.000000 0.000000 -0.000000 90.000000
0.000000 1.000000 -0.000000 -126.000000
0.000000 0.000000 1.000000 -72.000000
0.000000 0.000000 0.000000 1.000000
-0.500000 0.000000 -0.000000 90.000000
0.000000 0.500000 -0.000000 -126.000000
0.000000 0.000000 0.500000 -72.000000
0.000000 0.000000 0.000000 1.000000
-0.998351 0.172175 -0.001508 88.453751
0.055809 2.891963 -0.260024 -92.767014
0.013469 0.779036 0.965601 -92.031097
0.000000 0.000000 0.000000 1.000000
0.859157 -0.011162 -0.018416 -99.552223
0.011895 0.858345 0.046943 -83.334167
0.015283 -0.040551 0.998728 -77.306473
0.000000 0.000000 0.000000 1.000000
0.499529 -0.028847 -0.020837 -52.412189
0.018158 0.818889 0.038023 -79.724884
0.011864 -0.038744 0.819166 -71.899895
0.000000 0.000000 0.000000 1.000000
-0.374721 0.013086 0.098275 97.767311
0.010162 0.351788 -2.071789 -111.735596
0.010280 0.129224 5.630100 -91.104904
0.000000 0.000000 0.000000 1.000000
-0.388466 -0.008614 -0.667304 102.035919
0.041017 -0.081580 -6.319922 72.090378
-0.000000 0.381914 -1.365036 -41.159451
0.000000 0.000000 0.000000 1.000000
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment