Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor 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
Michiel Cottaar
fslpy
Commits
2263243c
Commit
2263243c
authored
7 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
Label atlas image values no longer need to match the index of the label
into the AtlasDescription.labels list.
parent
cf99f6ab
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
fsl/data/atlases.py
+82
-40
82 additions, 40 deletions
fsl/data/atlases.py
with
82 additions
and
40 deletions
fsl/data/atlases.py
+
82
−
40
View file @
2263243c
...
...
@@ -314,17 +314,18 @@ class AtlasLabel(object):
An ``AtlasLabel`` instance contains the following attributes:
========= ==============================================================
========= ==============================================================
==
``name`` Region name
``index`` For probabilistic atlases, the volume index into the 4D atlas
image that corresponds to this region. For label atlases, the
value of voxels that are in this region. For summary images of
probabilistic atlases, add 1 to this value to get the
corresponding voxel values.
``index`` The index of this label into the list of all labels in the
``AtlasDescription`` that owns it. For probabilistic atlases,
this is also the index into the 4D atlas image of the volume
that corresponds to this region.
``value`` For label atlases and summary images, the value of voxels that
are in this region.
``x`` X coordinate of the region in world space
``y`` Y coordinate of the region in world space
``z`` Z coordinate of the region in world space
========= ==============================================================
========= ==============================================================
==
.. note:: The ``x``, ``y`` and ``z`` label coordinates are pre-calculated
centre-of-gravity coordinates, as listed in the atlas xml file.
...
...
@@ -333,9 +334,10 @@ class AtlasLabel(object):
XML file (typically MNI152 space).
"""
def
__init__
(
self
,
name
,
index
,
x
,
y
,
z
):
def
__init__
(
self
,
name
,
index
,
value
,
x
,
y
,
z
):
self
.
name
=
name
self
.
index
=
index
self
.
value
=
value
self
.
x
=
x
self
.
y
=
y
self
.
z
=
z
...
...
@@ -383,8 +385,11 @@ class AtlasDescription(object):
# as relative to the location of this
# XML file.
<summaryimagefile> # Path to 3D summary file, with each
</summaryimagefile> # region having value (index + 1)
<summaryimagefile> # Path to 3D label summary file,
</summaryimagefile> # Every <image> must be accompanied
# by a <summaryimage> - for label
# atlases, they will typically refer
# to the same image file.
</images>
...
# More images - generally both
...
...
@@ -395,7 +400,10 @@ class AtlasDescription(object):
# index - For probabilistic atlases, index of corresponding volume in
# 4D image file. For label images, the value of voxels which
# are in the corresponding region.
# are in the corresponding region. For probabilistic atlases,
# it is assumed that the value for each region in the summary
# image(s) are equal to ``index + 1``.
#
#
# x |
# y |- XYZ *voxel* coordinates into the first image of the <images>
...
...
@@ -487,6 +495,8 @@ class AtlasDescription(object):
atlasDir
=
op
.
dirname
(
self
.
specPath
)
for
image
in
images
:
# Every image must also have a summary image
imagefile
=
image
.
find
(
'
imagefile
'
)
.
text
summaryimagefile
=
image
.
find
(
'
summaryimagefile
'
).
text
...
...
@@ -505,6 +515,11 @@ class AtlasDescription(object):
labels
=
data
.
findall
(
'
label
'
)
self
.
labels
=
[]
# Refs to AtlasLabel objects
# indexed by their value.
# Used by the find method.
self
.
__labelsByValue
=
{}
# The xyz coordinates for each label are in terms
# of the voxel space of the first images element
# in the header. For convenience, we're going to
...
...
@@ -519,11 +534,26 @@ class AtlasDescription(object):
x
=
float
(
label
.
attrib
[
'
x
'
])
y
=
float
(
label
.
attrib
[
'
y
'
])
z
=
float
(
label
.
attrib
[
'
z
'
])
al
=
AtlasLabel
(
name
,
index
,
x
,
y
,
z
)
# For label images, the index field
# contains the region value
if
self
.
atlasType
==
'
label
'
:
value
=
index
index
=
i
# For probablistic images, the index
# field specifies the volume in the
# 4D atlas corresponding to the region.
# It is assumed that the summary value
# for each region is index + 1
else
:
value
=
index
+
1
al
=
AtlasLabel
(
name
,
index
,
value
,
x
,
y
,
z
)
coords
[
i
]
=
(
x
,
y
,
z
)
self
.
labels
.
append
(
al
)
self
.
__labelsByValue
[
value
]
=
al
# Load the appropriate transformation matrix
# and transform all those voxel coordinates
...
...
@@ -536,6 +566,20 @@ class AtlasDescription(object):
label
.
x
,
label
.
y
,
label
.
z
=
coords
[
i
]
def
find
(
self
,
index
=
None
,
value
=
None
):
"""
Find an :class:`.AtlasLabel` either by ``index``, or by ``value``.
Exactly one of ``index`` or ``value`` may be specified - a
``ValueError`` is raised otherwise.
"""
if
(
index
is
None
and
value
is
None
)
or
\
(
index
is
not
None
and
value
is
not
None
):
raise
ValueError
(
'
Only one of index or value may be specified
'
)
if
index
is
not
None
:
return
self
.
labels
[
index
]
else
:
return
self
.
__labelsByValue
[
value
]
def
__eq__
(
self
,
other
):
"""
Compares the ``atlasID`` of this ``AtlasDescription`` with another.
"""
...
...
@@ -605,6 +649,13 @@ class Atlas(fslimage.Image):
self
.
desc
=
atlasDesc
def
find
(
self
,
*
args
,
**
kwargs
):
"""
Find an ``AtlasLabel`` - see the :meth:`AtlasDescription.find`
method.
"""
return
self
.
desc
.
find
(
*
args
,
**
kwargs
)
class
MaskError
(
Exception
):
"""
Exception raised by the :meth:`LabelAtlas.maskLabel` and
:meth:`ProbabilisticAtlas.maskProportions` when a mask is provided which
...
...
@@ -671,9 +722,8 @@ class LabelAtlas(Atlas):
:returns: The label at the given coordinates, or ``None`` if the
coordinates are out of bounds.
.. note:: If this is a summary image of a probabilistic atlas, you need
to subtract one from the result to get the region volume
index into the probabilistic atlas.
.. note:: Use the :meth:`find` method to retrieve the ``AtlasLabel``
associated with each returned value.
"""
if
not
voxel
:
...
...
@@ -703,15 +753,13 @@ class LabelAtlas(Atlas):
:returns: A tuple containing:
- A sequence of all
labels
which are present in the mask
- A sequence of all
values
which are present in the mask
- A sequence containing the proportion, within the mask,
of each present
label
. The proportions are returned as
of each present
value
. The proportions are returned as
values between 0 and 100.
.. note:: If this is a summary image of a probabilistic atlas, you need
to subtract one from the returned label values to get the
corresponding region volume indices into the probabilistic
atlas.
.. note:: Use the :meth:`find` method to retrieve the ``AtlasLabel``
associated with each returned value.
"""
# Make sure that the mask has the same
...
...
@@ -726,44 +774,36 @@ class LabelAtlas(Atlas):
# Extract the
label
s that are in
# Extract the
value
s that are in
# the mask, and their corresponding
# mask weights
boolmask
=
mask
>
0
vals
=
self
[
boolmask
]
weights
=
mask
[
boolmask
]
weightsum
=
weights
.
sum
()
got
Label
s
=
np
.
unique
(
vals
)
label
s
=
[]
got
Value
s
=
np
.
unique
(
vals
)
value
s
=
[]
props
=
[]
# Only consider labels that
# this atlas is aware of
for
label
in
self
.
desc
.
labels
:
# For probabilistic images, the label index
# is the index of the volume corresponding
# to the region. We need to add 1 to this
# to get its value in the summary image.
if
self
.
desc
.
atlasType
==
'
label
'
:
label
=
label
.
index
else
:
label
=
label
.
index
+
1
if
label
in
gotLabels
:
if
label
.
value
in
gotValues
:
# Figure out the number of all voxels
# in the mask with this
label
, weighted
# in the mask with this
value
, weighted
# by the mask.
prop
=
weights
[
vals
==
label
].
sum
()
prop
=
weights
[
vals
==
label
.
value
].
sum
()
# Normalise it to be a proportion
# of all voxels in the mask. We
# multiply by 100 because the FSL
# probabilistic atlases store their
# probabilities as percentages.
label
s
.
append
(
label
)
value
s
.
append
(
label
.
value
)
props
.
append
(
100
*
prop
/
weightsum
)
return
label
s
,
props
return
value
s
,
props
class
ProbabilisticAtlas
(
Atlas
):
...
...
@@ -839,11 +879,13 @@ class ProbabilisticAtlas(Atlas):
loc
[
2
]
>=
self
.
shape
[
2
]:
return
[]
# We only return labels for this atlas
props
=
self
[
loc
[
0
],
loc
[
1
],
loc
[
2
],
:]
props
=
[
props
[
l
.
index
]
for
l
in
self
.
desc
.
labels
]
return
props
# We only return labels for this atlas -
# the underlying image may have more
# volumes than this atlas has labels.
return
[
props
[
l
.
index
]
for
l
in
self
.
desc
.
labels
]
def
maskProportions
(
self
,
mask
):
...
...
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