Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Evan Edmond
fslpy
Commits
c60cda17
Commit
c60cda17
authored
8 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
My first set of unit tests for fslpy - tests functions in the
imagewrapper module.
parent
6c1405a4
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
test/test_imagewrapper.py
+320
-0
320 additions, 0 deletions
test/test_imagewrapper.py
with
320 additions
and
0 deletions
test/test_imagewrapper.py
0 → 100644
+
320
−
0
View file @
c60cda17
#!/usr/bin/env python
#
# test_imagewrapper.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
import
collections
import
random
import
itertools
as
it
import
numpy
as
np
import
fsl.data.image
as
image
import
fsl.data.imagewrapper
as
imagewrap
def
setup_module
():
pass
def
teardown_module
():
pass
def
random_coverage
(
shape
):
ndims
=
len
(
shape
)
-
1
nvols
=
shape
[
-
1
]
print
'
{}D (shape: {}, {} vectors/slices/volumes)
'
.
format
(
ndims
,
shape
,
nvols
)
# Generate a random coverage.
# We use the same coverage for
# each vector/slice/volume, so
# are not fully testing the function.
coverage
=
np
.
zeros
((
2
,
ndims
,
nvols
),
dtype
=
np
.
uint32
)
for
dim
in
range
(
ndims
):
dsize
=
shape
[
dim
]
# Random low/high indices for each dimension.
low
=
np
.
random
.
randint
(
0
,
dsize
)
# We have to make sure that the coverage is not
# complete, as some of the tests will fail if
# the coverage is complete.
if
low
==
0
:
high
=
np
.
random
.
randint
(
low
+
1
,
dsize
)
else
:
high
=
np
.
random
.
randint
(
low
+
1
,
dsize
+
1
)
coverage
[
0
,
dim
,
:]
=
low
coverage
[
1
,
dim
,
:]
=
high
return
coverage
def
random_slices
(
coverage
,
shape
,
mode
):
ndims
=
len
(
shape
)
-
1
nvols
=
shape
[
-
1
]
slices
=
np
.
zeros
((
2
,
len
(
shape
)))
for
dim
,
size
in
enumerate
(
shape
):
# Volumes
if
dim
==
ndims
:
lowCover
=
np
.
random
.
randint
(
0
,
nvols
)
highCover
=
np
.
random
.
randint
(
lowCover
+
1
,
nvols
+
1
)
slices
[:,
dim
]
=
lowCover
,
highCover
continue
# Assuming that coverage is same for each volume
lowCover
=
coverage
[
0
,
dim
,
0
]
highCover
=
coverage
[
1
,
dim
,
0
]
# Generate some slices that will
# be contained within the coverage
if
mode
==
'
in
'
:
lowSlice
=
np
.
random
.
randint
(
lowCover
,
highCover
)
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
highCover
+
1
)
# Generate some indices which will
# randomly overlap with the coverage
# (if it is possible to do so)
elif
mode
==
'
overlap
'
:
if
highCover
==
size
:
lowSlice
=
np
.
random
.
randint
(
0
,
lowCover
)
else
:
lowSlice
=
np
.
random
.
randint
(
0
,
highCover
)
if
lowSlice
<
lowCover
:
highSlice
=
np
.
random
.
randint
(
lowCover
+
1
,
size
+
1
)
else
:
highSlice
=
np
.
random
.
randint
(
highCover
+
1
,
size
+
1
)
elif
mode
==
'
out
'
:
# The coverage is full, so we can't
# generate an outside range
if
lowCover
==
0
and
highCover
==
size
:
lowSlice
=
np
.
random
.
randint
(
lowCover
,
highCover
)
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
highCover
+
1
)
# If low coverage is 0, the slice
# must be above the coverage
elif
lowCover
==
0
:
lowSlice
=
np
.
random
.
randint
(
highCover
,
size
)
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
size
+
1
)
# If high coverage is size, the
# slice must be below the coverage
elif
highCover
==
size
:
lowSlice
=
np
.
random
.
randint
(
0
,
lowCover
)
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
lowCover
+
1
)
# Otherwise the slice could be
# below or above the coverage
else
:
lowSlice
=
random
.
choice
((
np
.
random
.
randint
(
0
,
lowCover
),
np
.
random
.
randint
(
highCover
,
size
)))
if
lowSlice
<
lowCover
:
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
lowCover
+
1
)
else
:
highSlice
=
np
.
random
.
randint
(
lowSlice
+
1
,
size
+
1
)
slices
[
0
,
dim
]
=
lowSlice
slices
[
1
,
dim
]
=
highSlice
slices
=
[
tuple
(
map
(
int
,
pair
))
for
pair
in
slices
.
T
]
return
slices
def
test_sliceObjToSliceTuple
():
func
=
imagewrap
.
sliceObjToSliceTuple
shape
=
(
10
,
10
,
10
)
assert
func
(
2
,
shape
)
==
((
2
,
3
),
(
0
,
10
),
(
0
,
10
))
assert
func
(
slice
(
None
),
shape
)
==
((
0
,
10
),
(
0
,
10
),
(
0
,
10
))
assert
func
((
slice
(
None
),
slice
(
None
),
slice
(
None
)),
shape
)
==
((
0
,
10
),
(
0
,
10
),
(
0
,
10
))
assert
func
((
9
,
slice
(
None
),
slice
(
None
)),
shape
)
==
((
9
,
10
),
(
0
,
10
),
(
0
,
10
))
assert
func
((
slice
(
None
),
5
,
slice
(
None
)),
shape
)
==
((
0
,
10
),
(
5
,
6
),
(
0
,
10
))
assert
func
((
slice
(
None
),
slice
(
None
),
3
),
shape
)
==
((
0
,
10
),
(
0
,
10
),
(
3
,
4
))
assert
func
((
slice
(
4
,
6
),
slice
(
None
),
slice
(
None
)),
shape
)
==
((
4
,
6
),
(
0
,
10
),
(
0
,
10
))
assert
func
((
8
,
slice
(
1
,
10
),
slice
(
None
)),
shape
)
==
((
8
,
9
),
(
1
,
10
),
(
0
,
10
))
def
test_sliceTupleToSliceObj
():
func
=
imagewrap
.
sliceTupleToSliceObj
shape
=
(
10
,
10
,
10
)
for
x1
,
y1
,
z1
in
it
.
product
(
*
[
range
(
d
-
1
)
for
d
in
shape
]):
for
x2
,
y2
,
z2
in
it
.
product
(
*
[
range
(
s
+
1
,
d
)
for
s
,
d
in
zip
((
x1
,
y1
,
z1
),
shape
)]):
slices
=
[[
x1
,
x2
],
[
y1
,
y2
],
[
z1
,
z2
]]
sliceobj
=
(
slice
(
x1
,
x2
,
1
),
slice
(
y1
,
y2
,
1
),
slice
(
z1
,
z2
,
1
))
assert
func
(
slices
)
==
sliceobj
def
test_adjustCoverage
():
# TODO Randomise
# Each test is a tuple of (coverage, expansion, expectedResult)
tests
=
[([[
3
,
5
],
[
2
,
6
]],
[[
6
,
7
],
[
8
,
10
]],
[[
3
,
7
],
[
2
,
10
]]),
([[
0
,
0
],
[
0
,
0
]],
[[
1
,
2
],
[
3
,
5
]],
[[
0
,
2
],
[
0
,
5
]]),
([[
2
,
3
],
[
0
,
6
]],
[[
1
,
5
],
[
4
,
10
]],
[[
1
,
5
],
[
0
,
10
]]),
([[
0
,
1
],
[
0
,
1
]],
[[
0
,
7
],
[
19
,
25
],
[
0
,
1
]],
[[
0
,
7
],
[
0
,
25
]]),
]
for
coverage
,
expansion
,
result
in
tests
:
result
=
np
.
array
(
result
)
.
T
coverage
=
np
.
array
(
coverage
).
T
assert
np
.
all
(
imagewrap
.
adjustCoverage
(
coverage
,
expansion
)
==
result
)
def
test_sliceCovered
():
# A bunch of random coverages
for
i
in
range
(
500
):
# 2D, 3D or 4D?
# ndims is the number of dimensions
# in one vector/slice/volume
ndims
=
random
.
choice
((
2
,
3
,
4
))
-
1
# Shape of one vector[2D]/slice[3D]/volume[4D]
shape
=
np
.
random
.
randint
(
5
,
100
,
size
=
ndims
+
1
)
# Number of vectors/slices/volumes
nvols
=
shape
[
-
1
]
coverage
=
random_coverage
(
shape
)
# Generate some slices that should
# be contained within the coverage
for
j
in
range
(
500
):
slices
=
random_slices
(
coverage
,
shape
,
'
in
'
)
assert
imagewrap
.
sliceCovered
(
slices
,
coverage
,
shape
)
# Generate some slices that should
# overlap with the coverage
for
j
in
range
(
500
):
slices
=
random_slices
(
coverage
,
shape
,
'
overlap
'
)
assert
not
imagewrap
.
sliceCovered
(
slices
,
coverage
,
shape
)
# Generate some slices that should
# be outside of the coverage
for
j
in
range
(
500
):
slices
=
random_slices
(
coverage
,
shape
,
'
out
'
)
assert
not
imagewrap
.
sliceCovered
(
slices
,
coverage
,
shape
)
# The sum of the coverage ranges + the
# expansion ranges should be equal to
# the coverage, expanded to include the
# original slices (or the expansions
# - should be equivalent). Note that
# if imagewrapper.adjustCoverage is
# broken, this validation will also be
# broken.
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
]))
# Bin the expansions by volume
expsByVol
=
collections
.
defaultdict
(
list
)
for
vol
,
exp
in
zip
(
volumes
,
expansions
):
print
'
{:3d}:
"
{}
"'
.
format
(
vol
,
"
"
.
join
([
"
{:2d} {:2d}
"
.
format
(
l
,
h
)
for
l
,
h
in
exp
]))
expsByVol
[
vol
].
append
(
exp
)
for
vol
,
exps
in
expsByVol
.
items
():
# Figure out what the adjusted
# coverage should look like (assumes
# that adjustCoverage is working).
oldCoverage
=
coverage
[...,
vol
]
newCoverage
=
imagewrap
.
adjustCoverage
(
oldCoverage
,
slices
)
nc
=
newCoverage
dimranges
=
[]
for
d
in
range
(
ndims
):
dimranges
.
append
(
np
.
arange
(
nc
[
0
,
d
],
nc
[
1
,
d
]))
points
=
it
.
product
(
*
dimranges
)
for
point
in
points
:
# Is this point in the old coverage?
covered
=
True
for
dim
in
range
(
ndims
):
covLow
,
covHigh
=
oldCoverage
[:,
dim
]
if
point
[
dim
]
<
covLow
or
point
[
dim
]
>
covHigh
:
covered
=
False
break
if
covered
:
break
# Is this point in any of the expansions
covered
=
[
False
]
*
len
(
exps
)
for
i
,
exp
in
enumerate
(
exps
):
covered
[
i
]
=
True
for
dim
in
range
(
ndims
):
expLow
,
expHigh
=
exp
[
dim
]
if
point
[
dim
]
<
expLow
or
point
[
dim
]
>
expHigh
:
covered
[
i
]
=
False
break
if
not
any
(
covered
):
raise
AssertionError
(
point
)
def
test_calcSliceExpansion
():
for
i
in
range
(
500
):
ndims
=
3
# random.choice((2, 3, 4)) - 1
shape
=
np
.
random
.
randint
(
5
,
100
,
size
=
ndims
+
1
)
coverage
=
random_coverage
(
shape
)
cov
=
[(
lo
,
hi
)
for
lo
,
hi
in
coverage
[:,
:,
0
].
T
]
print
'
Shape: {}
'
.
format
(
shape
)
print
'
Coverage: {}
'
.
format
(
cov
)
print
print
'
-- In --
'
for
j
in
range
(
250
):
slices
=
random_slices
(
coverage
,
shape
,
'
in
'
)
vols
,
exps
=
imagewrap
.
calcExpansion
(
slices
,
coverage
)
_test_expansion
(
coverage
,
slices
,
vols
,
exps
)
print
print
'
-- Overlap --
'
for
j
in
range
(
250
):
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
(
250
):
slices
=
random_slices
(
coverage
,
shape
,
'
out
'
)
vols
,
exps
=
imagewrap
.
calcExpansion
(
slices
,
coverage
)
_test_expansion
(
coverage
,
slices
,
vols
,
exps
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment