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
c2ca0fc3
Commit
c2ca0fc3
authored
9 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
A custom transformation matrix may now be applied to ImageOpts instances.
parent
48be21b2
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
fsl/data/atlases.py
+1
-0
1 addition, 0 deletions
fsl/data/atlases.py
fsl/data/strings.py
+3
-1
3 additions, 1 deletion
fsl/data/strings.py
fsl/fsleyes/displaycontext/volumeopts.py
+85
-40
85 additions, 40 deletions
fsl/fsleyes/displaycontext/volumeopts.py
with
89 additions
and
41 deletions
fsl/data/atlases.py
+
1
−
0
View file @
c2ca0fc3
...
@@ -284,6 +284,7 @@ class AtlasDescription(object):
...
@@ -284,6 +284,7 @@ class AtlasDescription(object):
# Load the appropriate transformation matrix
# Load the appropriate transformation matrix
# and transform all those voxel coordinates
# and transform all those voxel coordinates
# into world coordinates
xform
=
fslimage
.
Image
(
self
.
images
[
0
],
loadData
=
False
).
voxToWorldMat
xform
=
fslimage
.
Image
(
self
.
images
[
0
],
loadData
=
False
).
voxToWorldMat
coords
=
transform
.
transform
(
coords
,
xform
.
T
)
coords
=
transform
.
transform
(
coords
,
xform
.
T
)
...
...
This diff is collapsed.
Click to expand it.
fsl/data/strings.py
+
3
−
1
View file @
c2ca0fc3
...
@@ -510,7 +510,9 @@ choices = TypeDict({
...
@@ -510,7 +510,9 @@ choices = TypeDict({
'
ImageOpts.transform
'
:
{
'
affine
'
:
'
Use qform/sform transformation
'
'
ImageOpts.transform
'
:
{
'
affine
'
:
'
Use qform/sform transformation
'
'
matrix
'
,
'
matrix
'
,
'
pixdim
'
:
'
Use pixdims only
'
,
'
pixdim
'
:
'
Use pixdims only
'
,
'
id
'
:
'
Do not use qform/sform or pixdims
'
},
'
id
'
:
'
Do not use qform/sform or pixdims
'
,
'
custom
'
:
'
Apply a custom transformation
'
'
matrix
'
},
'
VolumeOpts.interpolation
'
:
{
'
none
'
:
'
No interpolation
'
,
'
VolumeOpts.interpolation
'
:
{
'
none
'
:
'
No interpolation
'
,
'
linear
'
:
'
Linear interpolation
'
,
'
linear
'
:
'
Linear interpolation
'
,
...
...
This diff is collapsed.
Click to expand it.
fsl/fsleyes/displaycontext/volumeopts.py
+
85
−
40
View file @
c2ca0fc3
...
@@ -33,19 +33,17 @@ overlays can potentially be displayed in one of three coordinate systems:
...
@@ -33,19 +33,17 @@ overlays can potentially be displayed in one of three coordinate systems:
====================== ====================================================
====================== ====================================================
The :attr:`Image.transform` property controls how the image data is
The :attr:`ImageOpts.transform` property controls how the image data is
transformed into the display coordinate system.
transformed into the display coordinate system. It allows any of the above
spaces to be specified (as ``id``, ``pixdim`` or ``affine``` respectively),
and also allows a ``custom`` transformation to be specified (see the
:attr:`customXform` property).
.. note:: Currently, the ``transform`` property for every image overlay must
Regardless of the space in which the ``Image`` is displayed , the
be independently set for each image. However, in the next version of
voxel-to-display space transformation assumes that integer voxel coordinates
*FSLeyes* this will change, with the introduction of **GedMode**.
correspond to the centre of the voxel in the display coordinate system. In
other words, a voxel at location::
As of ``fslpy`` version |version|, when the ``transform`` property for an
image is ``id`` or ``pixdim``, the data to display space transformation assumes
that integer voxel coordinates correspond to the bottom-left of the voxel
in the display coordinate system. In other words, a voxel at location::
[x, y, z]
[x, y, z]
...
@@ -56,7 +54,8 @@ the space::
...
@@ -56,7 +54,8 @@ the space::
[x-0.5 - x+0.5, y-0.5 - y+0.5, z-0.5 - z+0.5]
[x-0.5 - x+0.5, y-0.5 - y+0.5, z-0.5 - z+0.5]
For example, the voxel::
For example, if the :attr:`ImageOpts.transform` property is set to ``id``, the
voxel::
[2, 3, 4]
[2, 3, 4]
...
@@ -65,18 +64,9 @@ is drawn such that it occupies the space::
...
@@ -65,18 +64,9 @@ is drawn such that it occupies the space::
[1.5 - 2.5, 2.5 - 3.5, 3.5 - 4.5]
[1.5 - 2.5, 2.5 - 3.5, 3.5 - 4.5]
This convention is the same as the convention taken when images are displayed
This convention is in line with the convention defined by the ``NIFTI1``
in world, or ``affine`` space. The ``qform`` and ``sform`` transformation
specification: it assumes that the voxel coordinates ``[x, y, z]`` correspond
matrices in the ``NIFTI1`` specification assume that the voxel coordinates
to the centre of a voxel.
``[x, y, z]`` correspond to the centre of a voxel. As an example, assuming
that our affine transformation is an identity matrix, the voxel::
[2, 3, 4]
for an image displayed in ``affine`` space would occupy the space::
[1.5 - 2.5, 2.5 - 3.5, 3.5 - 4.5]
"""
"""
...
@@ -115,13 +105,25 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -115,13 +105,25 @@ class ImageOpts(fsldisplay.DisplayOpts):
"""
"""
transform
=
props
.
Choice
((
'
affine
'
,
'
pixdim
'
,
'
id
'
),
default
=
'
pixdim
'
)
transform
=
props
.
Choice
(
(
'
affine
'
,
'
pixdim
'
,
'
id
'
,
'
custom
'
),
default
=
'
pixdim
'
)
"""
This property defines how the overlay should be transformd into
"""
This property defines how the overlay should be transformd into
the display coordinate system. See the
the display coordinate system. See the
:ref:`note on coordinate systems <volumeopts-coordinate-systems>`
:ref:`note on coordinate systems <volumeopts-coordinate-systems>`
for important information regarding this property.
for important information regarding this property.
"""
"""
customXform
=
props
.
Array
(
dtype
=
np
.
float64
,
shape
=
(
4
,
4
),
resizable
=
False
,
default
=
[[
1
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
],
[
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
1
]])
"""
A custom transformation matrix which is used when the :attr:`transform`
property is set to ``custom``.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
Create an ``ImageOpts`` instance.
"""
Create an ``ImageOpts`` instance.
...
@@ -132,10 +134,11 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -132,10 +134,11 @@ class ImageOpts(fsldisplay.DisplayOpts):
# The transform property cannot be unsynced
# The transform property cannot be unsynced
# across different displays, as it affects
# across different displays, as it affects
# the display context bounds, wich also
# the display context bounds, w
h
ich also
# cannot be unsynced
# cannot be unsynced
nounbind
=
kwargs
.
get
(
'
nounbind
'
,
[])
nounbind
=
kwargs
.
get
(
'
nounbind
'
,
[])
nounbind
.
append
(
'
transform
'
)
nounbind
.
append
(
'
transform
'
)
nounbind
.
append
(
'
customXform
'
)
kwargs
[
'
nounbind
'
]
=
nounbind
kwargs
[
'
nounbind
'
]
=
nounbind
...
@@ -143,7 +146,8 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -143,7 +146,8 @@ class ImageOpts(fsldisplay.DisplayOpts):
overlay
=
self
.
overlay
overlay
=
self
.
overlay
self
.
addListener
(
'
transform
'
,
self
.
name
,
self
.
__transformChanged
)
self
.
addListener
(
'
transform
'
,
self
.
name
,
self
.
__transformChanged
)
self
.
addListener
(
'
customXform
'
,
self
.
name
,
self
.
__customXformChanged
)
# The display<->* transformation matrices
# The display<->* transformation matrices
# are created in the _setupTransforms method
# are created in the _setupTransforms method
...
@@ -179,6 +183,17 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -179,6 +183,17 @@ class ImageOpts(fsldisplay.DisplayOpts):
self
.
bounds
[:]
=
[
lo
[
0
],
hi
[
0
],
lo
[
1
],
hi
[
1
],
lo
[
2
],
hi
[
2
]]
self
.
bounds
[:]
=
[
lo
[
0
],
hi
[
0
],
lo
[
1
],
hi
[
1
],
lo
[
2
],
hi
[
2
]]
def
__customXformChanged
(
self
,
*
a
):
"""
Called when the :attr:`customXform` property changes. Re-generates
transformation matrices, and re-calculates the display :attr:`bounds`
(via calls to :meth:`__setupTransforms` and
:meth:`__transformChanged`).
"""
self
.
__setupTransforms
()
self
.
__transformChanged
()
def
__setupTransforms
(
self
):
def
__setupTransforms
(
self
):
"""
Calculates transformation matrices between all of the possible
"""
Calculates transformation matrices between all of the possible
...
@@ -187,35 +202,52 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -187,35 +202,52 @@ class ImageOpts(fsldisplay.DisplayOpts):
These matrices are accessible via the :meth:`getTransform` method.
These matrices are accessible via the :meth:`getTransform` method.
"""
"""
image
=
self
.
overlay
image
=
self
.
overlay
voxToIdMat
=
np
.
eye
(
4
)
voxToIdMat
=
np
.
eye
(
4
)
voxToPixdimMat
=
np
.
diag
(
list
(
image
.
pixdim
[:
3
])
+
[
1.0
])
voxToPixdimMat
=
np
.
diag
(
list
(
image
.
pixdim
[:
3
])
+
[
1.0
])
voxToAffineMat
=
image
.
voxToWorldMat
.
T
voxToAffineMat
=
image
.
voxToWorldMat
.
T
voxToCustomMat
=
self
.
customXform
idToVoxMat
=
transform
.
invert
(
voxToIdMat
)
idToVoxMat
=
transform
.
invert
(
voxToIdMat
)
idToPixdimMat
=
transform
.
concat
(
idToVoxMat
,
voxToPixdimMat
)
idToPixdimMat
=
transform
.
concat
(
idToVoxMat
,
voxToPixdimMat
)
idToAffineMat
=
transform
.
concat
(
idToVoxMat
,
voxToAffineMat
)
idToAffineMat
=
transform
.
concat
(
idToVoxMat
,
voxToAffineMat
)
idToCustomMat
=
transform
.
concat
(
idToVoxMat
,
voxToCustomMat
)
pixdimToVoxMat
=
transform
.
invert
(
voxToPixdimMat
)
pixdimToVoxMat
=
transform
.
invert
(
voxToPixdimMat
)
pixdimToIdMat
=
transform
.
concat
(
pixdimToVoxMat
,
voxToIdMat
)
pixdimToIdMat
=
transform
.
concat
(
pixdimToVoxMat
,
voxToIdMat
)
pixdimToAffineMat
=
transform
.
concat
(
pixdimToVoxMat
,
voxToAffineMat
)
pixdimToAffineMat
=
transform
.
concat
(
pixdimToVoxMat
,
voxToAffineMat
)
pixdimToCustomMat
=
transform
.
concat
(
pixdimToVoxMat
,
voxToCustomMat
)
affineToVoxMat
=
image
.
worldToVoxMat
.
T
affineToVoxMat
=
image
.
worldToVoxMat
.
T
affineToIdMat
=
transform
.
concat
(
affineToVoxMat
,
voxToIdMat
)
affineToIdMat
=
transform
.
concat
(
affineToVoxMat
,
voxToIdMat
)
affineToPixdimMat
=
transform
.
concat
(
affineToVoxMat
,
voxToPixdimMat
)
affineToPixdimMat
=
transform
.
concat
(
affineToVoxMat
,
voxToPixdimMat
)
affineToCustomMat
=
transform
.
concat
(
affineToVoxMat
,
voxToCustomMat
)
customToVoxMat
=
transform
.
invert
(
voxToCustomMat
)
customToIdMat
=
transform
.
concat
(
customToVoxMat
,
voxToIdMat
)
customToPixdimMat
=
transform
.
concat
(
customToVoxMat
,
voxToPixdimMat
)
customToAffineMat
=
transform
.
concat
(
customToVoxMat
,
voxToAffineMat
)
self
.
__xforms
[
'
id
'
,
'
id
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
id
'
,
'
id
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
id
'
,
'
pixdim
'
]
=
idToPixdimMat
self
.
__xforms
[
'
id
'
,
'
pixdim
'
]
=
idToPixdimMat
self
.
__xforms
[
'
id
'
,
'
affine
'
]
=
idToAffineMat
self
.
__xforms
[
'
id
'
,
'
affine
'
]
=
idToAffineMat
self
.
__xforms
[
'
id
'
,
'
custom
'
]
=
idToCustomMat
self
.
__xforms
[
'
pixdim
'
,
'
pixdim
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
pixdim
'
,
'
pixdim
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
pixdim
'
,
'
id
'
]
=
pixdimToIdMat
self
.
__xforms
[
'
pixdim
'
,
'
id
'
]
=
pixdimToIdMat
self
.
__xforms
[
'
pixdim
'
,
'
affine
'
]
=
pixdimToAffineMat
self
.
__xforms
[
'
pixdim
'
,
'
affine
'
]
=
pixdimToAffineMat
self
.
__xforms
[
'
pixdim
'
,
'
custom
'
]
=
pixdimToCustomMat
self
.
__xforms
[
'
affine
'
,
'
affine
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
affine
'
,
'
affine
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
affine
'
,
'
id
'
]
=
affineToIdMat
self
.
__xforms
[
'
affine
'
,
'
id
'
]
=
affineToIdMat
self
.
__xforms
[
'
affine
'
,
'
pixdim
'
]
=
affineToPixdimMat
self
.
__xforms
[
'
affine
'
,
'
pixdim
'
]
=
affineToPixdimMat
self
.
__xforms
[
'
affine
'
,
'
custom
'
]
=
affineToCustomMat
self
.
__xforms
[
'
custom
'
,
'
custom
'
]
=
np
.
eye
(
4
)
self
.
__xforms
[
'
custom
'
,
'
id
'
]
=
customToIdMat
self
.
__xforms
[
'
custom
'
,
'
pixdim
'
]
=
customToPixdimMat
self
.
__xforms
[
'
custom
'
,
'
affine
'
]
=
customToAffineMat
def
getTransform
(
self
,
from_
,
to
,
xform
=
None
):
def
getTransform
(
self
,
from_
,
to
,
xform
=
None
):
...
@@ -227,16 +259,20 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -227,16 +259,20 @@ class ImageOpts(fsldisplay.DisplayOpts):
=========== ======================================================
=========== ======================================================
``id`` Voxel coordinates
``id`` Voxel coordinates
``voxel`` Equivalent to ``id``.
``pixdim`` Voxel coordinates, scaled by voxel dimensions
``pixdim`` Voxel coordinates, scaled by voxel dimensions
``affine`` World coordinates, as defined by the NIFTI1
``affine`` World coordinates, as defined by the NIFTI1
``qform``/``sform``. See :attr:`.Image.voxToWorldMat`.
``qform``/``sform``. See :attr:`.Image.voxToWorldMat`.
``voxel`` Equivalent to ``id``.
``world`` Equivalent to ``affine``.
``custom`` Coordinates in the space defined by the custom
transformation matrix, as specified via the
:attr:`customXform` property.
``display`` Equivalent to the current value of :attr:`transform`.
``display`` Equivalent to the current value of :attr:`transform`.
``world`` Equivalent to ``affine``.
=========== ======================================================
=========== ======================================================
...
@@ -292,9 +328,9 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -292,9 +328,9 @@ class ImageOpts(fsldisplay.DisplayOpts):
on each other were aligned at the voxel corner, whereas in
on each other were aligned at the voxel corner, whereas in
``affine`` space, they were aligned at the voxel
``affine`` space, they were aligned at the voxel
centre. This is no longer the case, so this method is not
centre. This is no longer the case, so this method is not
actually necessary
. But it is sti
ll
h
er
e, and still being
actually necessary
, and just returns a
ll
z
er
os. But it is
used, just in case we need to
change these conventions again
still here, and still being
used, just in case we need to
in the future.
change these conventions again
in the future.
"""
"""
return
(
0
,
0
,
0
),
(
0
,
0
,
0
)
return
(
0
,
0
,
0
),
(
0
,
0
,
0
)
...
@@ -307,6 +343,10 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -307,6 +343,10 @@ class ImageOpts(fsldisplay.DisplayOpts):
- ``display``: The display coordinate system
- ``display``: The display coordinate system
- ``voxel``: The image voxel coordinate system
- ``voxel``: The image voxel coordinate system
- ``world``: The image world coordinate system
- ``world``: The image world coordinate system
- ``custom``: The coordinate system defined by the custom
transformation matrix (see :attr:`customXform`)
See also the :meth:`transformToVoxels` method.
"""
"""
xform
=
self
.
getTransform
(
from_
,
to_
)
xform
=
self
.
getTransform
(
from_
,
to_
)
...
@@ -324,6 +364,11 @@ class ImageOpts(fsldisplay.DisplayOpts):
...
@@ -324,6 +364,11 @@ class ImageOpts(fsldisplay.DisplayOpts):
If the :attr:`transform` property has changed, returns the given
If the :attr:`transform` property has changed, returns the given
location, assumed to be in the old display coordinate system,
location, assumed to be in the old display coordinate system,
transformed into the new display coordinate system.
transformed into the new display coordinate system.
.. note:: This method will probably break if the ``custom``
transformation matrix changes between the time that
the ``transform`` property changes, and the time that
this method is called.
"""
"""
lastVal
=
self
.
getLastValue
(
'
transform
'
)
lastVal
=
self
.
getLastValue
(
'
transform
'
)
...
...
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