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
Model registry
Operate
Environments
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
FSL
fslpy
Commits
4cd6c30b
Commit
4cd6c30b
authored
4 years ago
by
Michiel Cottaar
Browse files
Options
Downloads
Patches
Plain Diff
BUG: add tests for extracting images/surface data
parent
bca18bf7
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
fsl/data/cifti.py
+15
-15
15 additions, 15 deletions
fsl/data/cifti.py
tests/test_cifti.py
+113
-4
113 additions, 4 deletions
tests/test_cifti.py
with
128 additions
and
19 deletions
fsl/data/cifti.py
+
15
−
15
View file @
4cd6c30b
...
...
@@ -224,10 +224,10 @@ class DenseCifti(Cifti):
"""
if
self
.
brain_model_axis
.
volume_mask
.
sum
()
==
0
:
raise
ValueError
(
f
"
Can not create volume without voxels in
{
self
}
"
)
data
=
np
.
full
(
self
.
brain_model_axis
.
volume_shape
+
self
.
data
.
shape
[:
-
1
],
fill
,
dtype
=
self
.
data
.
dtype
)
data
=
np
.
full
(
self
.
brain_model_axis
.
volume_shape
+
self
.
arr
.
shape
[:
-
1
],
fill
,
dtype
=
self
.
arr
.
dtype
)
voxels
=
self
.
brain_model_axis
.
voxel
[
self
.
brain_model_axis
.
volume_mask
]
data
[
tuple
(
voxels
.
T
)]
=
np
.
transpose
(
self
.
data
,
(
-
1
,)
+
tuple
(
range
(
self
.
data
.
ndim
-
1
)))[
data
[
tuple
(
voxels
.
T
)]
=
np
.
transpose
(
self
.
arr
,
(
-
1
,)
+
tuple
(
range
(
self
.
arr
.
ndim
-
1
)))[
self
.
brain_model_axis
.
volume_mask
]
return
image
.
Image
(
data
,
xform
=
self
.
brain_model_axis
.
affine
)
...
...
@@ -249,8 +249,8 @@ class DenseCifti(Cifti):
if
anatomy
.
cifti
not
in
self
.
brain_model_axis
.
name
:
raise
ValueError
(
f
"
No surface data for
{
anatomy
.
cifti
}
found
"
)
slc
,
bm
=
None
,
None
arr
=
np
.
full
(
self
.
data
.
shape
[:
-
1
]
+
(
self
.
brain_model_axis
.
nvertices
[
anatomy
.
cifti
],),
fill
,
dtype
=
self
.
data
.
dtype
)
arr
=
np
.
full
(
self
.
arr
.
shape
[:
-
1
]
+
(
self
.
brain_model_axis
.
nvertices
[
anatomy
.
cifti
],),
fill
,
dtype
=
self
.
arr
.
dtype
)
for
name
,
slc_try
,
bm_try
in
self
.
brain_model_axis
.
iter_structures
():
if
name
==
anatomy
.
cifti
:
if
partial
:
...
...
@@ -258,11 +258,11 @@ class DenseCifti(Cifti):
raise
ValueError
(
f
"
Surface
{
anatomy
}
does not form a contiguous block
"
)
slc
,
bm
=
slc_try
,
bm_try
else
:
arr
[...,
bm_try
.
vertex
]
=
self
.
data
[...,
slc_try
]
arr
[...,
bm_try
.
vertex
]
=
self
.
arr
[...,
slc_try
]
if
not
partial
:
return
arr
else
:
return
bm
.
vertex
,
self
.
data
[...,
slc
]
return
bm
.
vertex
,
self
.
arr
[...,
slc
]
class
ParcelCifti
(
Cifti
):
...
...
@@ -290,14 +290,14 @@ class ParcelCifti(Cifti):
"""
data
=
np
.
full
(
self
.
parcel_axis
.
volume_shape
+
self
.
arr
.
shape
[:
-
1
],
fill
,
dtype
=
self
.
arr
.
dtype
)
written
=
np
.
zeros
(
self
.
parcel_axis
.
volume_shape
,
dtype
=
'
bool
'
)
for
idx
,
write_to
in
enumerate
(
self
.
parcel_axis
)
.
voxels
:
if
written
[
write_to
].
any
():
for
idx
,
write_to
in
enumerate
(
self
.
parcel_axis
.
voxels
)
:
if
written
[
tuple
(
write_to
.
T
)
].
any
():
raise
ValueError
(
"
Duplicate voxels in different parcels
"
)
data
[
write_to
]
=
self
.
arr
[
np
.
newaxis
,
...,
idx
]
written
[
write_to
]
=
True
data
[
tuple
(
write_to
.
T
)
]
=
self
.
arr
[
np
.
newaxis
,
...,
idx
]
written
[
tuple
(
write_to
.
T
)
]
=
True
if
not
written
.
any
():
raise
ValueError
(
"
Parcellation does not contain any volumetric data
"
)
return
image
.
Image
(
data
,
xform
=
self
.
brain_mod
el_axis
.
affine
)
return
image
.
Image
(
data
,
xform
=
self
.
parc
el_axis
.
affine
)
def
surface
(
self
,
anatomy
,
fill
=
np
.
nan
,
partial
=
False
):
"""
...
...
@@ -315,9 +315,9 @@ class ParcelCifti(Cifti):
if
anatomy
.
cifti
not
in
self
.
parcel_axis
.
nvertices
:
raise
ValueError
(
f
"
No surface data for
{
anatomy
.
cifti
}
found
"
)
arr
=
np
.
full
(
self
.
data
.
shape
[:
-
1
]
+
(
self
.
parcel_axis
.
nvertices
[
anatomy
.
cifti
],),
fill
,
dtype
=
self
.
data
.
dtype
)
written
=
np
.
zeros
(
self
.
parcel_axis
.
nvertices
[
anatomy
.
cifti
])
arr
=
np
.
full
(
self
.
arr
.
shape
[:
-
1
]
+
(
self
.
parcel_axis
.
nvertices
[
anatomy
.
cifti
],),
fill
,
dtype
=
self
.
arr
.
dtype
)
written
=
np
.
zeros
(
self
.
parcel_axis
.
nvertices
[
anatomy
.
cifti
]
,
dtype
=
'
bool
'
)
for
idx
,
vertices
in
enumerate
(
self
.
parcel_axis
.
vertices
):
if
anatomy
.
cifti
not
in
vertices
:
continue
...
...
This diff is collapsed.
Click to expand it.
tests/test_cifti.py
+
113
−
4
View file @
4cd6c30b
...
...
@@ -17,23 +17,33 @@ def surface_brain_model():
return
cifti2_axes
.
BrainModelAxis
.
from_mask
(
mask
,
name
=
'
cortex
'
)
def
volumetric_parcels
():
def
volumetric_parcels
(
return_mask
=
False
):
mask
=
np
.
random
.
randint
(
5
,
size
=
(
10
,
10
,
10
))
return
cifti2_axes
.
ParcelsAxis
(
axis
=
cifti2_axes
.
ParcelsAxis
(
[
f
'
vol_
{
idx
}
'
for
idx
in
range
(
1
,
5
)],
voxels
=
[
np
.
stack
(
np
.
where
(
mask
==
idx
),
axis
=-
1
)
for
idx
in
range
(
1
,
5
)],
vertices
=
[{}
for
_
in
range
(
1
,
5
)],
volume_shape
=
mask
.
shape
,
affine
=
np
.
eye
(
4
),
)
if
return_mask
:
return
axis
,
mask
else
:
return
axis
def
surface_parcels
():
def
surface_parcels
(
return_mask
=
False
):
mask
=
np
.
random
.
randint
(
5
,
size
=
100
)
return
cifti2_axes
.
ParcelsAxis
(
axis
=
cifti2_axes
.
ParcelsAxis
(
[
f
'
surf_
{
idx
}
'
for
idx
in
range
(
1
,
5
)],
voxels
=
[
np
.
zeros
((
0
,
3
),
dtype
=
int
)
for
_
in
range
(
1
,
5
)],
vertices
=
[{
'
CIFTI_STRUCTURE_CORTEX
'
:
np
.
where
(
mask
==
idx
)[
0
]}
for
idx
in
range
(
1
,
5
)],
nvertices
=
{
'
CIFTI_STRUCTURE_CORTEX
'
:
100
},
)
if
return_mask
:
return
axis
,
mask
else
:
return
axis
def
gen_data
(
axes
):
...
...
@@ -128,3 +138,102 @@ def test_io_cifti():
dense_axis
=
surface_brain_model
()
pdconn
=
cifti_class
(
gen_data
([
dense_axis
,
main_axis
]),
(
dense_axis
,
main_axis
))
check_io
(
pdconn
,
'
pdconn
'
)
def
test_extract_dense
():
vol_bm
=
volumetric_brain_model
()
surf_bm
=
surface_brain_model
()
for
bm
in
(
vol_bm
+
surf_bm
,
surf_bm
+
vol_bm
):
for
ndim
,
no_other_axis
in
((
1
,
True
),
(
2
,
False
),
(
2
,
True
)):
if
ndim
==
1
:
data
=
cifti
.
DenseCifti
(
gen_data
([
bm
]),
[
bm
])
else
:
scl
=
cifti2_axes
.
ScalarAxis
([
'
A
'
,
'
B
'
,
'
C
'
])
data
=
cifti
.
DenseCifti
(
gen_data
([
scl
,
bm
]),
[
None
if
no_other_axis
else
scl
,
bm
])
# extract volume
ref_arr
=
data
.
arr
[...,
data
.
brain_model_axis
.
volume_mask
]
vol_image
=
data
.
to_image
(
fill
=
np
.
nan
)
if
ndim
==
1
:
assert
vol_image
.
shape
==
data
.
brain_model_axis
.
volume_shape
else
:
assert
vol_image
.
shape
==
data
.
brain_model_axis
.
volume_shape
+
(
3
,
)
assert
np
.
isfinite
(
vol_image
.
data
).
sum
()
==
len
(
vol_bm
)
*
(
3
if
ndim
==
2
else
1
)
testing
.
assert_equal
(
vol_image
.
data
[
tuple
(
vol_bm
.
voxel
.
T
)],
ref_arr
.
T
)
from_image
=
cifti
.
DenseCifti
.
from_image
(
vol_image
)
assert
from_image
.
brain_model_axis
==
vol_bm
testing
.
assert_equal
(
from_image
.
arr
,
ref_arr
)
# extract surface
ref_arr
=
data
.
arr
[...,
data
.
brain_model_axis
.
surface_mask
]
mask
,
surf_data
=
data
.
surface
(
'
cortex
'
,
partial
=
True
)
assert
surf_data
.
shape
[
-
1
]
<
100
testing
.
assert_equal
(
ref_arr
,
surf_data
)
testing
.
assert_equal
(
surf_bm
.
vertex
,
mask
)
surf_data_full
=
data
.
surface
(
'
cortex
'
,
fill
=
np
.
nan
)
assert
surf_data_full
.
shape
[
-
1
]
==
100
mask_full
=
np
.
isfinite
(
surf_data_full
)
if
ndim
==
2
:
assert
(
mask_full
.
any
(
0
)
==
mask_full
.
all
(
0
)).
all
()
mask_full
=
mask_full
[
0
]
assert
mask_full
.
sum
()
==
len
(
surf_bm
)
assert
mask_full
[...,
mask
].
sum
()
==
len
(
surf_bm
)
testing
.
assert_equal
(
surf_data_full
[...,
mask_full
],
ref_arr
)
def
test_extract_parcel
():
vol_parcel
,
vol_mask
=
volumetric_parcels
(
return_mask
=
True
)
surf_parcel
,
surf_mask
=
surface_parcels
(
return_mask
=
True
)
parcel
=
vol_parcel
+
surf_parcel
for
ndim
,
no_other_axis
in
((
1
,
True
),
(
2
,
False
),
(
2
,
True
)):
if
ndim
==
1
:
data
=
cifti
.
ParcelCifti
(
gen_data
([
parcel
]),
[
parcel
])
else
:
scl
=
cifti2_axes
.
ScalarAxis
([
'
A
'
,
'
B
'
,
'
C
'
])
data
=
cifti
.
ParcelCifti
(
gen_data
([
scl
,
parcel
]),
[
None
if
no_other_axis
else
scl
,
parcel
])
# extract volume
vol_image
=
data
.
to_image
(
fill
=
np
.
nan
)
if
ndim
==
1
:
assert
vol_image
.
shape
==
data
.
parcel_axis
.
volume_shape
else
:
assert
vol_image
.
shape
==
data
.
parcel_axis
.
volume_shape
+
(
3
,
)
assert
np
.
isfinite
(
vol_image
.
data
).
sum
()
==
np
.
sum
(
vol_mask
!=
0
)
*
(
3
if
ndim
==
2
else
1
)
if
ndim
==
1
:
testing
.
assert_equal
(
vol_mask
!=
0
,
np
.
isfinite
(
vol_image
.
data
))
for
idx
in
range
(
1
,
5
):
testing
.
assert_allclose
(
vol_image
.
data
[
vol_mask
==
idx
],
data
.
arr
[...,
idx
-
1
])
else
:
for
idx
in
range
(
3
):
testing
.
assert_equal
(
vol_mask
!=
0
,
np
.
isfinite
(
vol_image
.
data
[...,
idx
]))
for
idx2
in
range
(
1
,
5
):
testing
.
assert_allclose
(
vol_image
.
data
[
vol_mask
==
idx2
,
idx
],
data
.
arr
[
idx
,
idx2
-
1
])
# extract surface
mask
,
surf_data
=
data
.
surface
(
'
cortex
'
,
partial
=
True
)
assert
surf_data
.
shape
[
-
1
]
==
(
surf_mask
!=
0
).
sum
()
assert
(
surf_mask
[
mask
]
!=
0
).
all
()
print
(
data
.
arr
)
for
idx
in
range
(
1
,
5
):
if
ndim
==
1
:
testing
.
assert_equal
(
surf_data
.
T
[
surf_mask
[
mask
]
==
idx
],
data
.
arr
[
idx
+
3
])
else
:
for
idx2
in
range
(
3
):
testing
.
assert_equal
(
surf_data
.
T
[
surf_mask
[
mask
]
==
idx
,
idx2
],
data
.
arr
[
idx2
,
idx
+
3
])
surf_data_full
=
data
.
surface
(
'
cortex
'
,
partial
=
False
)
assert
surf_data_full
.
shape
[
-
1
]
==
100
if
ndim
==
1
:
testing
.
assert_equal
(
np
.
isfinite
(
surf_data_full
),
surf_mask
!=
0
)
for
idx
in
range
(
1
,
5
):
testing
.
assert_equal
(
surf_data_full
.
T
[
surf_mask
==
idx
],
data
.
arr
[
idx
+
3
])
else
:
for
idx2
in
range
(
3
):
testing
.
assert_equal
(
np
.
isfinite
(
surf_data_full
)[
idx2
],
(
surf_mask
!=
0
))
for
idx
in
range
(
1
,
5
):
testing
.
assert_equal
(
surf_data_full
.
T
[
surf_mask
==
idx
,
idx2
],
data
.
arr
[
idx2
,
idx
+
3
])
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