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
4bbd521a
Commit
4bbd521a
authored
5 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
RF,BF: Fixes/adjustments to nonlinear module, and in particular to
convertDisplacementSpace
parent
3a607236
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/transform/nonlinear.py
+57
-41
57 additions, 41 deletions
fsl/transform/nonlinear.py
with
57 additions
and
41 deletions
fsl/transform/nonlinear.py
+
57
−
41
View file @
4bbd521a
...
@@ -26,10 +26,13 @@ class NonLinearTransform(fslimage.Image):
...
@@ -26,10 +26,13 @@ class NonLinearTransform(fslimage.Image):
some mapping between a source image coordinate system and a reference image
some mapping between a source image coordinate system and a reference image
coordinate system.
coordinate system.
In FSL, non-linear transformations are defined in the same space as the
In FSL, non-linear transformations are defined in the same space as the
reference image. At a given location in the reference image space, the
reference image. At a given location in the reference image space, the
non-linear mapping at that location can be used to calculate the
non-linear mapping at that location can be used to calculate the
corresponding location in the source image space.
corresponding location in the source image space. Therefore, these
non-linear transformation effectively encode a transformation *from* the
reference image *to* the source image.
"""
"""
...
@@ -46,7 +49,7 @@ class NonLinearTransform(fslimage.Image):
...
@@ -46,7 +49,7 @@ class NonLinearTransform(fslimage.Image):
or a :mod:`numpy` array, or a :mod:`nibabel` image
or a :mod:`numpy` array, or a :mod:`nibabel` image
object.
object.
:arg src: :class:`.Nifti` representing the sourceimage
:arg src: :class:`.Nifti` representing the source
image
.
:arg ref: :class:`.Nifti` representing the reference image.
:arg ref: :class:`.Nifti` representing the reference image.
If not provided, it is assumed that this
If not provided, it is assumed that this
...
@@ -66,11 +69,6 @@ class NonLinearTransform(fslimage.Image):
...
@@ -66,11 +69,6 @@ class NonLinearTransform(fslimage.Image):
if
srcSpace
is
None
:
srcSpace
=
'
fsl
'
if
srcSpace
is
None
:
srcSpace
=
'
fsl
'
if
refSpace
is
None
:
refSpace
=
'
fsl
'
if
refSpace
is
None
:
refSpace
=
'
fsl
'
if
not
(
isinstance
(
src
,
(
fslimage
.
Nifti
,
type
(
None
)))
and
isinstance
(
ref
,
fslimage
.
Nifti
)):
raise
ValueError
(
'
Invalid source/reference: {} -> {}
'
.
format
(
src
,
ref
))
if
srcSpace
not
in
(
'
fsl
'
,
'
voxel
'
,
'
world
'
)
or
\
if
srcSpace
not
in
(
'
fsl
'
,
'
voxel
'
,
'
world
'
)
or
\
refSpace
not
in
(
'
fsl
'
,
'
voxel
'
,
'
world
'
):
refSpace
not
in
(
'
fsl
'
,
'
voxel
'
,
'
world
'
):
raise
ValueError
(
'
Invalid source/reference space: {} -> {}
'
.
format
(
raise
ValueError
(
'
Invalid source/reference space: {} -> {}
'
.
format
(
...
@@ -78,6 +76,12 @@ class NonLinearTransform(fslimage.Image):
...
@@ -78,6 +76,12 @@ class NonLinearTransform(fslimage.Image):
fslimage
.
Image
.
__init__
(
self
,
image
,
**
kwargs
)
fslimage
.
Image
.
__init__
(
self
,
image
,
**
kwargs
)
# Displacement fields must be
# defined in the same space
# as the reference image
if
not
self
.
sameSpace
(
ref
):
raise
ValueError
(
'
Invalid reference image: {}
'
.
format
(
ref
))
self
.
__src
=
fslimage
.
Nifti
(
src
.
header
.
copy
())
self
.
__src
=
fslimage
.
Nifti
(
src
.
header
.
copy
())
self
.
__ref
=
fslimage
.
Nifti
(
ref
.
header
.
copy
())
self
.
__ref
=
fslimage
.
Nifti
(
ref
.
header
.
copy
())
self
.
__srcSpace
=
srcSpace
self
.
__srcSpace
=
srcSpace
...
@@ -172,7 +176,8 @@ class DisplacementField(NonLinearTransform):
...
@@ -172,7 +176,8 @@ class DisplacementField(NonLinearTransform):
def
transform
(
self
,
coords
,
from_
=
None
,
to
=
None
):
def
transform
(
self
,
coords
,
from_
=
None
,
to
=
None
):
"""
Transform the given XYZ coordinates from the reference to the source.
"""
Transform the given XYZ coordinates from the reference image space
to the source image space.
:arg coords: A sequence of XYZ coordinates, or ``numpy`` array of shape
:arg coords: A sequence of XYZ coordinates, or ``numpy`` array of shape
``(n, 3)`` containing ``n`` sets of coordinates in the
``(n, 3)`` containing ``n`` sets of coordinates in the
...
@@ -192,22 +197,21 @@ class DisplacementField(NonLinearTransform):
...
@@ -192,22 +197,21 @@ class DisplacementField(NonLinearTransform):
# same reference image space as the
# same reference image space as the
# displacements
# displacements
if
from_
!=
self
.
refSpace
:
if
from_
!=
self
.
refSpace
:
coords
=
affine
.
transform
(
xform
=
self
.
ref
.
getAffine
(
from_
,
self
.
refSpace
)
coords
,
self
.
ref
.
getAffine
(
from_
,
self
.
refSpace
)
)
coords
=
affine
.
transform
(
coords
,
xform
)
# We also need to make sure that the
# We also need to make sure that the
# coordinates are in voxels, so we
# coordinates are in voxels, so we
# can look up the displacements
# can look up the displacements
if
self
.
refSpace
!=
'
voxel
'
:
if
self
.
refSpace
!=
'
voxel
'
:
voxels
=
affine
.
transform
(
xform
=
self
.
ref
.
getAffine
(
self
.
refSpace
,
'
voxel
'
)
coords
,
self
.
ref
.
getAffine
(
self
.
refSpace
,
'
voxel
'
)
)
voxels
=
affine
.
transform
(
coords
,
xform
)
else
:
else
:
voxels
=
coords
voxels
=
coords
voxels
=
np
.
round
(
voxels
).
astype
(
np
.
int
)
# Mask out the coordinates
# Mask out the coordinates
# that are out of bounds
# that are out of bounds
voxels
=
np
.
round
(
voxels
).
astype
(
np
.
int
)
voxmask
=
(
voxels
>=
[
0
,
0
,
0
])
&
(
voxels
<
self
.
shape
[:
3
])
voxmask
=
(
voxels
>=
[
0
,
0
,
0
])
&
(
voxels
<
self
.
shape
[:
3
])
voxmask
=
voxmask
.
all
(
axis
=
1
)
voxmask
=
voxmask
.
all
(
axis
=
1
)
voxels
=
voxels
[
voxmask
]
voxels
=
voxels
[
voxmask
]
...
@@ -221,8 +225,8 @@ class DisplacementField(NonLinearTransform):
...
@@ -221,8 +225,8 @@ class DisplacementField(NonLinearTransform):
# are in the requested
# are in the requested
# source image space
# source image space
if
to
!=
self
.
srcSpace
:
if
to
!=
self
.
srcSpace
:
disps
=
affine
.
transform
(
xform
=
self
.
src
.
getAffine
(
self
.
srcSpace
,
to
)
disps
,
self
.
src
.
getAffine
(
self
.
srcSpace
,
to
)
)
disps
=
affine
.
transform
(
disps
,
xform
)
# Nans for input coordinates
# Nans for input coordinates
# which were outside of the
# which were outside of the
...
@@ -276,12 +280,13 @@ def convertDisplacementType(field, dispType=None):
...
@@ -276,12 +280,13 @@ def convertDisplacementType(field, dispType=None):
# we need the coordinates of every voxel
# we need the coordinates of every voxel
# in the reference FSL coordinate system.
# in the reference FSL coordinate system.
dx
,
dy
,
dz
=
field
.
shape
[:
3
]
dx
,
dy
,
dz
=
field
.
shape
[:
3
]
v2fsl
=
field
.
getAffine
(
'
voxel
'
,
field
.
srcSpace
)
xform
=
field
.
getAffine
(
'
voxel
'
,
field
.
refSpace
)
coords
=
np
.
meshgrid
(
np
.
arange
(
dx
),
coords
=
np
.
meshgrid
(
np
.
arange
(
dx
),
np
.
arange
(
dy
),
np
.
arange
(
dy
),
np
.
arange
(
dz
),
indexing
=
'
ij
'
)
np
.
arange
(
dz
),
indexing
=
'
ij
'
)
coords
=
np
.
array
(
coords
).
transpose
((
1
,
2
,
3
,
0
))
coords
=
np
.
array
(
coords
).
transpose
((
1
,
2
,
3
,
0
))
coords
=
affine
.
transform
(
coords
.
reshape
((
-
1
,
3
)),
v2fsl
)
coords
=
affine
.
transform
(
coords
.
reshape
((
-
1
,
3
)),
xform
)
coords
=
coords
.
reshape
((
dx
,
dy
,
dz
,
3
))
coords
=
coords
.
reshape
((
dx
,
dy
,
dz
,
3
))
# If converting from relative to absolute,
# If converting from relative to absolute,
...
@@ -299,47 +304,58 @@ def convertDisplacementSpace(field, from_, to):
...
@@ -299,47 +304,58 @@ def convertDisplacementSpace(field, from_, to):
the ``from_`` and ``to`` arguments.
the ``from_`` and ``to`` arguments.
:arg field: A :class:`DisplacementField` instance
:arg field: A :class:`DisplacementField` instance
:arg from_: New
sour
ce image coordinate system
:arg from_: New
referen
ce image coordinate system
:arg to: New
referen
ce image coordinate system
:arg to: New
sour
ce image coordinate system
:returns: A new :class:`DisplacementField` which transforms between
:returns: A new :class:`DisplacementField` which transforms between
the
sour
ce ``from_`` coordinate system and the
referen
ce ``to``
the
referen
ce ``from_`` coordinate system and the
sour
ce ``to``
coordinate system.
coordinate system.
"""
"""
# Get the field in absolute
# Get the field in absolute coordinates
# coordinates if necessary
# if necessary - these are our source
# coordinates in the original "to" space.
fieldcoords
=
field
.
data
fieldcoords
=
field
.
data
if
field
.
relative
:
srccoords
=
convertDisplacementType
(
field
)
if
field
.
relative
:
srccoords
=
convertDisplacementType
(
field
)
else
:
srccoords
=
fieldcoords
else
:
srccoords
=
fieldcoords
# Now transform those source
# coordinates from the original
# source space to the source
# space specified by "from_"
srcmat
=
field
.
src
.
getAffine
(
field
.
srcSpace
,
from_
)
srccoords
=
srccoords
.
reshape
((
-
1
,
3
))
srccoords
=
srccoords
.
reshape
((
-
1
,
3
))
srccoords
=
affine
.
transform
(
srccoords
,
srcmat
)
# Now transform those source coordinates
# from the original source space to the
# source space specified by "to"
if
to
!=
field
.
srcSpace
:
srcmat
=
field
.
src
.
getAffine
(
field
.
srcSpace
,
to
)
srccoords
=
affine
.
transform
(
srccoords
,
srcmat
)
# If we have been asked to return
# If we have been asked to return
# an absolute displacement, the
# an absolute displacement, the
# reference "
to
" coordinate
system
# reference "
from_
" coordinate
# is irrelevant - we're done.
#
system
is irrelevant - we're done.
if
field
.
absolute
:
if
field
.
absolute
:
fieldcoords
=
srccoords
fieldcoords
=
srccoords
# Otherwise our displacement field
# Otherwise our displacement field
# will contain relative displacements
# will contain relative displacements
# between the reference image "
to
"
# between the reference image "
from_
"
# coordinate system and the source
# coordinate system and the source
# image "from_" coordinate system.
# image "to" coordinate system. We
# We need to re-calculate the relative
# need to re-calculate the relative
# displacements between source "from_"
# displacements between the new
# space and reference "to" space.
# reference "from_" space and source
# "to" space.
else
:
else
:
refmat
=
field
.
ref
.
getAffine
(
field
.
refSpace
,
to
)
refcoords
=
np
.
meshgrid
(
np
.
arange
(
field
.
shape
[
0
]),
refcoords
=
fieldcoords
.
reshape
((
-
1
,
3
))
np
.
arange
(
field
.
shape
[
1
]),
refcoords
=
affine
.
transform
(
refcoords
,
refmat
)
np
.
arange
(
field
.
shape
[
2
]),
indexing
=
'
ij
'
)
refcoords
=
np
.
array
(
refcoords
)
refcoords
=
refcoords
.
transpose
((
1
,
2
,
3
,
0
)).
reshape
((
-
1
,
3
))
if
from_
!=
'
voxel
'
:
refmat
=
field
.
ref
.
getAffine
(
'
voxel
'
,
from_
)
refcoords
=
affine
.
transform
(
refcoords
,
refmat
)
fieldcoords
=
srccoords
-
refcoords
fieldcoords
=
srccoords
-
refcoords
return
DisplacementField
(
return
DisplacementField
(
...
@@ -347,6 +363,6 @@ def convertDisplacementSpace(field, from_, to):
...
@@ -347,6 +363,6 @@ def convertDisplacementSpace(field, from_, to):
header
=
field
.
header
,
header
=
field
.
header
,
src
=
field
.
src
,
src
=
field
.
src
,
ref
=
field
.
ref
,
ref
=
field
.
ref
,
srcSpace
=
from_
,
srcSpace
=
to
,
refSpace
=
to
,
refSpace
=
from_
,
dispType
=
field
.
displacementType
)
dispType
=
field
.
displacementType
)
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