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
d93c4e65
Commit
d93c4e65
authored
7 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
GiftiSurface renamed to GiftiMesh because it fits better with new
nomenclature.
parent
daea0469
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/gifti.py
+146
-59
146 additions, 59 deletions
fsl/data/gifti.py
with
146 additions
and
59 deletions
fsl/data/gifti.py
+
146
−
59
View file @
d93c4e65
...
@@ -16,62 +16,96 @@ are available:
...
@@ -16,62 +16,96 @@ are available:
.. autosummary::
.. autosummary::
:nosignatures:
:nosignatures:
GiftiSurface
GiftiMesh
loadGiftiSurface
loadGiftiMesh
loadGiftiVertexData
relatedFiles
relatedFiles
"""
"""
import
glob
import
glob
import
os.path
as
op
import
os.path
as
op
import
deprecation
import
numpy
as
np
import
numpy
as
np
import
nibabel
as
nib
import
nibabel
as
nib
import
fsl.utils.path
as
fslpath
import
fsl.utils.path
as
fslpath
from
.
import
constants
import
fsl.data.constants
as
constants
from
.
import
mesh
import
fsl.data.mesh
as
fsl
mesh
class
GiftiSurface
(
mesh
.
TriangleMesh
):
ALLOWED_EXTENSIONS
=
[
'
.surf.gii
'
]
"""
List of file extensions that a file containing Gifti surface data
is expected to have.
"""
EXTENSION_DESCRIPTIONS
=
[
'
GIFTI surface file
'
]
"""
A description for each of the :data:`ALLOWED_EXTENSIONS`.
"""
class
GiftiMesh
(
fslmesh
.
Mesh
):
"""
Class which represents a GIFTI surface image. This is essentially
"""
Class which represents a GIFTI surface image. This is essentially
just a 3D model made of triangles.
just a 3D model made of triangles.
In addition to the ``vertices`` and ``indices`` provided by the
For each GIFTI surface file that is loaded, the
:class:`.TriangleMesh` class (from which the ``GiftiSurface`` class
``nibabel.gifti.GiftiImage`` instance is stored in the :class:`.Meta`
derives), a ``GiftiSurface`` instance has the following attributes:
store, with the absolute path to the surface file as the key.
============== ====================================================
``name`` A name, typically the file name sans-suffix.
``dataSource`` Full path to the GIFTI file.
``surfImg`` Reference to the loaded ``nibabel.gifti.GiftiImage``
============== ====================================================
"""
"""
def
__init__
(
self
,
infile
,
fixWinding
=
False
):
def
__init__
(
self
,
infile
,
fixWinding
=
False
,
loadAll
=
False
):
"""
Load the given GIFTI file using ``nibabel``, and extracts surface
"""
Load the given GIFTI file using ``nibabel``, and extracts surface
data using the :func:`loadGiftiSurface` function.
data using the :func:`loadGiftiSurface` function.
:arg infile: A GIFTI surface file (``*.surf.gii``).
:arg infile: A GIFTI surface file (``*.surf.gii``).
:arg fixWinding: Passed through to the :meth:`addVertices` method
for the first vertex set.
:arg loadAll: If ``True``, the ``infile`` directory is scanned
for other surface files which are then loaded
as additional vertex sets.
.. todo:: Allow loading from a ``.topo.gii`` and ``.coord.gii`` file?
.. todo:: Allow loading from a ``.topo.gii`` and ``.coord.gii`` file?
Maybe.
Maybe.
"""
"""
name
=
fslpath
.
removeExt
(
op
.
basename
(
infile
),
ALLOWED_EXTENSIONS
)
infile
=
op
.
abspath
(
infile
)
surfimg
,
vertices
,
indices
=
loadGiftiSurface
(
infile
)
surfimg
,
vertices
,
indices
=
loadGiftiSurface
(
infile
)
mesh
.
TriangleMesh
.
__init__
(
self
,
vertices
,
indices
,
fixWinding
)
fslmesh
.
Mesh
.
__init__
(
self
,
indices
,
name
=
name
,
dataSource
=
infile
)
name
=
fslpath
.
removeExt
(
op
.
basename
(
infile
)
,
ALLOWED_EXTENSIONS
)
self
.
addVertices
(
vertices
,
infile
,
fixWinding
=
fixWinding
)
infile
=
op
.
abspath
(
infile
)
self
.
setMeta
(
infile
,
surfimg
)
self
.
name
=
name
# Find and load all other
self
.
dataSource
=
infile
# surfaces in the same directory
self
.
surfImg
=
surfimg
# as the specfiied one.
if
loadAll
:
nvertices
=
vertices
.
shape
[
0
]
surfFiles
=
relatedFiles
(
infile
,
'
surf
'
)
def
loadVertexData
(
self
,
dataSource
,
vertexData
=
None
):
for
sfile
in
surfFiles
:
surfimg
,
vertices
,
_
=
loadGiftiSurface
(
sfile
)
if
vertices
.
shape
[
0
]
!=
nvertices
:
continue
self
.
addVertices
(
vertices
,
sfile
,
select
=
False
)
self
.
setMeta
(
sfile
,
surfimg
)
def
loadVertexData
(
self
,
infile
,
key
=
None
):
"""
Overrides the :meth:`.TriangleMesh.loadVertexData` method.
"""
Overrides the :meth:`.TriangleMesh.loadVertexData` method.
Attempts to load data associated with each vertex of this
Attempts to load data associated with each vertex of this
...
@@ -79,27 +113,21 @@ class GiftiSurface(mesh.TriangleMesh):
...
@@ -79,27 +113,21 @@ class GiftiSurface(mesh.TriangleMesh):
a GIFTI file or a plain text file which contains vertex data.
a GIFTI file or a plain text file which contains vertex data.
"""
"""
if
vertexData
is
None
:
infile
=
op
.
abspath
(
infile
)
if
dataSource
.
endswith
(
'
.gii
'
):
vertexData
=
loadGiftiVertexData
(
dataSource
)[
1
]
else
:
vertexData
=
None
return
mesh
.
TriangleMesh
.
loadVertexData
(
self
,
dataSource
,
vertexData
)
if
key
is
None
:
key
=
infile
if
infile
.
endswith
(
'
.gii
'
):
vdata
=
loadGiftiVertexData
(
infile
)[
1
]
self
.
addVertexData
(
key
,
vdata
)
return
vdata
ALLOWED_EXTENSIONS
=
[
'
.surf.gii
'
,
'
.gii
'
]
else
:
"""
List of file extensions that a file containing Gifti surface data
return
fslmesh
.
Mesh
.
loadVertexData
(
self
,
infile
,
key
)
is expected to have.
"""
EXTENSION_DESCRIPTIONS
=
[
'
GIFTI surface file
'
,
'
GIFTI surface file
'
]
def
loadGiftiMesh
(
filename
):
"""
A description for each of the :data:`ALLOWED_EXTENSIONS`.
"""
def
loadGiftiSurface
(
filename
):
"""
Extracts surface data from the given ``nibabel.gifti.GiftiImage``.
"""
Extracts surface data from the given ``nibabel.gifti.GiftiImage``.
The image is expected to contain the following``<DataArray>`` elements:
The image is expected to contain the following``<DataArray>`` elements:
...
@@ -116,11 +144,10 @@ def loadGiftiSurface(filename):
...
@@ -116,11 +144,10 @@ def loadGiftiSurface(filename):
- The loaded ``nibabel.gifti.GiftiImage`` instance
- The loaded ``nibabel.gifti.GiftiImage`` instance
- A :math:`N
\\
times 3` ``numpy`` array containing :math:`N`
- A ``(N, 3)`` array containing ``N`` vertices.
vertices.
- A
:math:`M
\\
times 3` ``numpy
`` array containing the
- A
``(M, 3))
`` array containing the
vertex indices for
vertex indices for :math:
`M` triangles.
`
`M`
`
triangles.
"""
"""
gimg
=
nib
.
load
(
filename
)
gimg
=
nib
.
load
(
filename
)
...
@@ -132,16 +159,17 @@ def loadGiftiSurface(filename):
...
@@ -132,16 +159,17 @@ def loadGiftiSurface(filename):
triangles
=
[
d
for
d
in
gimg
.
darrays
if
d
.
intent
==
triangleCode
]
triangles
=
[
d
for
d
in
gimg
.
darrays
if
d
.
intent
==
triangleCode
]
if
len
(
gimg
.
darrays
)
!=
2
:
if
len
(
gimg
.
darrays
)
!=
2
:
raise
ValueError
(
'
GIFTI surface files must contain exactly
'
raise
ValueError
(
'
{}: GIFTI surface files must contain
'
'
one pointset array and one triangle array
'
)
'
exactly one pointset array and one
'
'
triangle array
'
.
format
(
filename
))
if
len
(
pointsets
)
!=
1
:
if
len
(
pointsets
)
!=
1
:
raise
ValueError
(
'
GIFTI surface files must contain
'
raise
ValueError
(
'
{}:
GIFTI surface files must contain
'
'
exactly one pointset array
'
)
'
exactly one pointset array
'
.
format
(
filename
)
)
if
len
(
triangles
)
!=
1
:
if
len
(
triangles
)
!=
1
:
raise
ValueError
(
'
GIFTI surface files must contain
'
raise
ValueError
(
'
{}:
GIFTI surface files must contain
'
'
exactly one triangle array
'
)
'
exactly one triangle array
'
.
format
(
filename
)
)
vertices
=
pointsets
[
0
].
data
vertices
=
pointsets
[
0
].
data
indices
=
triangles
[
0
].
data
indices
=
triangles
[
0
].
data
...
@@ -190,7 +218,8 @@ def loadGiftiVertexData(filename):
...
@@ -190,7 +218,8 @@ def loadGiftiVertexData(filename):
# DataArray goes against the GIFTI spec,
# DataArray goes against the GIFTI spec,
# but hey, it happens.
# but hey, it happens.
if
len
(
gimg
.
darrays
)
==
1
:
if
len
(
gimg
.
darrays
)
==
1
:
return
gimg
,
gimg
.
darrays
[
0
].
data
vdata
=
gimg
.
darrays
[
0
].
data
return
gimg
,
vdata
.
reshape
(
vdata
.
shape
[
0
],
-
1
)
# Otherwise extract and concatenate
# Otherwise extract and concatenate
# multiple 1-dimensional arrays
# multiple 1-dimensional arrays
...
@@ -200,13 +229,21 @@ def loadGiftiVertexData(filename):
...
@@ -200,13 +229,21 @@ def loadGiftiVertexData(filename):
raise
ValueError
(
'
{} contains one or more non-vector
'
raise
ValueError
(
'
{} contains one or more non-vector
'
'
darrays
'
.
format
(
filename
))
'
darrays
'
.
format
(
filename
))
return
gimg
,
np
.
vstack
(
vdata
).
T
vdata
=
np
.
vstack
(
vdata
).
T
vdata
=
vdata
.
reshape
(
vdata
.
shape
[
0
],
-
1
)
return
gimg
,
vdata
def
relatedFiles
(
fname
):
def
relatedFiles
(
fname
,
ftype
=
None
):
"""
Given a GIFTI file, returns a list of other GIFTI files in the same
"""
Given a GIFTI file, returns a list of other GIFTI files in the same
directory which appear to be related with the given one. Files which
directory which appear to be related with the given one. Files which
share the same prefix are assumed to be related to the given file.
share the same prefix are assumed to be related to the given file.
:arg fname: Name of the file to search for related files for
:arg ftype: If provided, only files with a name ``
'
*.[ftype].gii
'
`` are
searched for.
"""
"""
# We want to return all files in the same
# We want to return all files in the same
...
@@ -221,7 +258,7 @@ def relatedFiles(fname):
...
@@ -221,7 +258,7 @@ def relatedFiles(fname):
#
#
# - we don't care about the middle
# - we don't care about the middle
#
#
# - type is func, shape, label,
or
time
# - type is func, shape, label, time
, or `ftype`
# We determine the unique prefix of the
# We determine the unique prefix of the
# given file, and back-up to the most
# given file, and back-up to the most
...
@@ -235,9 +272,59 @@ def relatedFiles(fname):
...
@@ -235,9 +272,59 @@ def relatedFiles(fname):
if
lastdot
==
-
1
:
if
lastdot
==
-
1
:
return
[]
return
[]
funcs
=
list
(
glob
.
glob
(
'
{}*.func.gii
'
.
format
(
prefix
)))
if
ftype
is
None
:
shapes
=
list
(
glob
.
glob
(
'
{}*.shape.gii
'
.
format
(
prefix
)))
ftypes
=
[
'
func
'
,
'
shape
'
,
'
label
'
,
'
time
'
]
labels
=
list
(
glob
.
glob
(
'
{}*.label.gii
'
.
format
(
prefix
)))
else
:
times
=
list
(
glob
.
glob
(
'
{}*.time.gii
'
.
format
(
prefix
)))
ftypes
=
[
ftype
]
related
=
[]
for
ftype
in
ftypes
:
related
+=
list
(
glob
.
glob
(
'
{}*.{}.gii
'
.
format
(
prefix
,
ftype
)))
return
[
r
for
r
in
related
if
r
!=
fname
]
class
GiftiSurface
(
fslmesh
.
TriangleMesh
):
"""
Deprecated - use GiftiMesh instead.
"""
@deprecation.deprecated
(
deprecated_in
=
'
1.6.0
'
,
removed_in
=
'
2.0.0
'
,
details
=
'
Use GiftiMesh instead
'
)
def
__init__
(
self
,
infile
,
fixWinding
=
False
):
"""
Deprecated - use GiftiMesh instead.
"""
surfimg
,
vertices
,
indices
=
loadGiftiSurface
(
infile
)
fslmesh
.
TriangleMesh
.
__init__
(
self
,
vertices
,
indices
,
fixWinding
)
return
funcs
+
shapes
+
labels
+
times
name
=
fslpath
.
removeExt
(
op
.
basename
(
infile
),
ALLOWED_EXTENSIONS
)
infile
=
op
.
abspath
(
infile
)
self
.
_Mesh__name
=
name
self
.
_Mesh__dataSource
=
infile
self
.
surfImg
=
surfimg
@deprecation.deprecated
(
deprecated_in
=
'
1.6.0
'
,
removed_in
=
'
2.0.0
'
,
details
=
'
Use GiftiMesh instead
'
)
def
loadVertexData
(
self
,
dataSource
,
vertexData
=
None
):
"""
Deprecated - use GiftiMesh instead.
"""
if
vertexData
is
None
:
if
dataSource
.
endswith
(
'
.gii
'
):
vertexData
=
loadGiftiVertexData
(
dataSource
)[
1
]
else
:
vertexData
=
None
return
fslmesh
.
TriangleMesh
.
loadVertexData
(
self
,
dataSource
,
vertexData
)
@deprecation.deprecated
(
deprecated_in
=
'
1.6.0
'
,
removed_in
=
'
2.0.0
'
,
details
=
'
Use loadGiftiMesh instead
'
)
def
loadGiftiSurface
(
filename
):
"""
Deprecated - use loadGiftiMesh instead.
"""
return
loadGiftiMesh
(
filename
)
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