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
db21c20b
Commit
db21c20b
authored
4 years ago
by
Michiel Cottaar
Browse files
Options
Downloads
Patches
Plain Diff
BUG: set undefined axes to None
parent
c95dacf1
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
fsl/data/cifti.py
+54
-34
54 additions, 34 deletions
fsl/data/cifti.py
with
54 additions
and
34 deletions
fsl/data/cifti.py
+
54
−
34
View file @
db21c20b
...
@@ -7,7 +7,7 @@ The data can be read from NIFTI, GIFTI, or CIFTI files.
...
@@ -7,7 +7,7 @@ The data can be read from NIFTI, GIFTI, or CIFTI files.
Non-sparse volumetric or surface representations can be extracte.
Non-sparse volumetric or surface representations can be extracte.
"""
"""
from
nibabel.cifti2
import
cifti2_axes
from
nibabel.cifti2
import
cifti2_axes
from
typing
import
Sequence
from
typing
import
Sequence
,
Optional
import
numpy
as
np
import
numpy
as
np
from
fsl.data.image
import
Image
from
fsl.data.image
import
Image
import
nibabel
as
nib
import
nibabel
as
nib
...
@@ -40,45 +40,59 @@ class Cifti:
...
@@ -40,45 +40,59 @@ class Cifti:
- :py:class:`BrainModelAxis <cifti2_axes.BrainModelAxis>`
- :py:class:`BrainModelAxis <cifti2_axes.BrainModelAxis>`
- :py:class:`ParcelsAxis <cifti2_axes.ParcelsAxis>`
- :py:class:`ParcelsAxis <cifti2_axes.ParcelsAxis>`
"""
"""
def
__init__
(
self
,
arr
:
np
.
ndarray
,
axes
:
Sequence
[
cifti2_axes
.
Axis
]):
def
__init__
(
self
,
arr
:
np
.
ndarray
,
axes
:
Sequence
[
Optional
[
cifti2_axes
.
Axis
]
,
...]
):
"""
"""
Defines a new dataset in greyordinate space
Defines a new dataset in greyordinate space
:param data: (..., N) array for N greyordinates or parcels
:param data: (..., N) array for N greyordinates or parcels
; can contain Nones for undefined axes
:param axes: sequence of CIFTI axes describing the data along each dimension
:param axes: sequence of CIFTI axes describing the data along each dimension
"""
"""
self
.
arr
=
arr
self
.
arr
=
arr
axes
=
tuple
(
axes
)
while
self
.
arr
.
ndim
>
len
(
axes
):
axes
=
(
None
,
)
+
axes
self
.
axes
=
axes
self
.
axes
=
axes
if
arr
.
shape
[
-
len
(
axes
):]
!=
tuple
(
len
(
ax
)
for
ax
in
axes
):
if
not
all
(
ax
is
None
or
len
(
ax
)
==
sz
for
ax
,
sz
in
zip
(
axes
,
self
.
arr
.
shape
)):
raise
ValueError
(
f
"
Shape of axes
{
tuple
(
len
(
ax
)
for
ax
in
axes
)
}
does not match shape of array
{
self
.
arr
.
shape
}
"
)
raise
ValueError
(
f
"
Shape of axes
{
tuple
(
-
1
if
ax
is
None
else
len
(
ax
)
for
ax
in
axes
)
}
does not
"
f
"
match shape of array
{
self
.
arr
.
shape
}
"
)
def
to_cifti
(
self
,
other
_ax
e
s
=
None
):
def
to_cifti
(
self
,
default
_ax
i
s
=
None
):
"""
"""
Create a CIFTI image from the data
Create a CIFTI image from the data
:param other_axes: overwrites the :mod:`cifti2_axes` to be used to write to create the CIFTI image
:param default_axis: What to use as an axis along any undefined dimensions
- By default an error is raised
- if set to
"
scalar
"
a ScalarAxis is used with names of
"
default {index}
"
- if set to
"
series
"
a SeriesAxis is used
:return: nibabel CIFTI image
:return: nibabel CIFTI image
"""
"""
if
other_axes
is
None
:
if
any
(
ax
is
None
for
ax
in
self
.
axes
):
if
len
(
self
.
axes
)
!=
self
.
data
.
ndim
:
if
default_axis
is
None
:
raise
ValueError
(
"
Can not store to CIFTI without defining what is stored along the other dimensions
"
)
raise
ValueError
(
"
Can not store to CIFTI without defining what is stored along each dimension
"
)
other_axes
=
self
.
axes
[:
-
1
]
elif
default_axis
==
'
scalar
'
:
def
get_axis
(
n
:
int
):
return
cifti2_axes
.
ScalarAxis
([
f
'
default
{
idx
+
1
}
'
for
idx
in
range
(
n
)])
elif
default_axis
==
'
series
'
:
def
get_axis
(
n
:
int
):
return
cifti2_axes
.
SeriesAxis
(
0
,
1
,
n
)
else
:
raise
ValueError
(
f
"
default_axis should be set to None,
'
scalar
'
, or
'
series
'
, not
{
default_axis
}
"
)
new_axes
=
[
get_axis
(
sz
)
if
ax
is
None
else
ax
for
ax
,
sz
in
zip
(
self
.
axes
,
self
.
arr
.
shape
)
]
else
:
else
:
if
len
(
other_axes
)
!=
self
.
data
.
ndim
-
1
:
new_axes
=
list
(
self
.
axes
)
raise
ValueError
(
"
Number of axis does not match dimensionality of the data
"
)
if
tuple
(
len
(
ax
)
for
ax
in
other_axes
)
!=
self
.
data
.
shape
[:
-
1
]:
raise
ValueError
(
"
Size of other axes does not match data size
"
)
data
=
self
.
data
data
=
self
.
data
if
data
.
ndim
==
1
:
if
data
.
ndim
==
1
:
# CIFTI axes are always at least 2D
# CIFTI axes are always at least 2D
data
=
data
[
None
,
:]
data
=
data
[
None
,
:]
other_axes
=
[
cifti2_axes
.
ScalarAxis
([
'
default
'
])
]
new_axes
.
insert
(
0
,
cifti2_axes
.
ScalarAxis
([
'
default
'
])
)
return
cifti2_axes
.
Cifti2Image
(
return
cifti2_axes
.
Cifti2Image
(
data
,
header
=
new_axes
)
data
,
header
=
list
(
other_axes
)
+
[
self
.
axes
[
-
1
]]
)
@classmethod
@classmethod
def
from_cifti
(
cls
,
filename
,
writable
=
False
):
def
from_cifti
(
cls
,
filename
,
writable
=
False
):
...
@@ -110,25 +124,30 @@ class Cifti:
...
@@ -110,25 +124,30 @@ class Cifti:
return
ParcelCifti
(
data
,
axes
)
return
ParcelCifti
(
data
,
axes
)
raise
ValueError
(
"
Last axis of CIFTI object should be a BrainModelAxis or ParcelsAxis
"
)
raise
ValueError
(
"
Last axis of CIFTI object should be a BrainModelAxis or ParcelsAxis
"
)
def
writ
e
(
self
,
cifti_filename
,
other
_ax
e
s
=
None
):
def
sav
e
(
self
,
cifti_filename
,
default
_ax
i
s
=
None
):
"""
"""
Writes this sparse representation to/from a filename
Writes this sparse representation to/from a filename
:param cifti_filename: output filename
:param cifti_filename: output filename
:param other_axes: overwrites the :mod:`cifti2_axes` to be used to write to the file
:param default_axis: What to use as an axis along any undefined dimensions
- By default an error is raised
- if set to
"
scalar
"
a ScalarAxis is used with names of
"
default {index}
"
- if set to
"
series
"
a SeriesAxis is used
:return:
:return:
"""
"""
self
.
to_cifti
(
other
_ax
e
s
).
to_filename
(
addExt
(
cifti_filename
,
defaultExt
=
self
.
extension
))
self
.
to_cifti
(
default
_ax
i
s
).
to_filename
(
addExt
(
cifti_filename
,
defaultExt
=
self
.
extension
))
def
read
(
cls
,
filename
,
mask_values
=
(
0
,
np
.
nan
),
writable
=
False
):
@classmethod
def
load
(
cls
,
filename
,
mask_values
=
(
0
,
np
.
nan
),
writable
=
False
):
"""
"""
Reads greyordinate data from the given file
Reads greyordinate data from the given file
File can be:
File can be:
- NIFTI mask
- NIFTI mask
- GIFTI mask
- GIFTI mask
- CIFTI file
- CIFTI file
:param filename: input filename
:param filename: input filename
:param mask_values: which values are outside of the mask for NIFTI or GIFTI input
:param mask_values: which values are outside of the mask for NIFTI or GIFTI input
...
@@ -140,17 +159,19 @@ class Cifti:
...
@@ -140,17 +159,19 @@ class Cifti:
else
:
else
:
img
=
filename
img
=
filename
if
isinstance
(
img
,
nib
.
Nifti1Image
):
if
writable
:
raise
ValueError
(
"
Can not open NIFTI file in writable mode
"
)
return
cls
.
from_image
(
Image
(
img
),
mask_values
)
if
isinstance
(
img
,
nib
.
Cifti2Image
):
if
isinstance
(
img
,
nib
.
Cifti2Image
):
return
cls
.
from_cifti
(
img
,
writable
=
writable
)
return
cls
.
from_cifti
(
img
,
writable
=
writable
)
if
isinstance
(
img
,
nib
.
GiftiImage
):
if
isinstance
(
img
,
nib
.
GiftiImage
):
if
writable
:
if
writable
:
raise
ValueError
(
"
Can not open GIFTI file in writable mode
"
)
raise
ValueError
(
"
Can not open GIFTI file in writable mode
"
)
return
cls
.
from_gifti
(
img
,
mask_values
)
return
cls
.
from_gifti
(
img
,
mask_values
)
raise
ValueError
(
f
"
I do not know how to convert
{
type
(
img
)
}
into greyordinates (from
{
filename
}
)
"
)
try
:
vol_img
=
Image
(
img
)
except
ValueError
:
raise
ValueError
(
f
"
I do not know how to convert
{
type
(
img
)
}
into greyordinates (from
{
filename
}
)
"
)
if
writable
:
raise
ValueError
(
"
Can not open NIFTI file in writable mode
"
)
return
cls
.
from_image
(
vol_img
,
mask_values
)
@classmethod
@classmethod
def
from_gifti
(
cls
,
filename
,
mask_values
=
(
0
,
np
.
nan
)):
def
from_gifti
(
cls
,
filename
,
mask_values
=
(
0
,
np
.
nan
)):
...
@@ -191,7 +212,7 @@ class Cifti:
...
@@ -191,7 +212,7 @@ class Cifti:
"""
"""
Creates a new greyordinate object from a NIFTI file
Creates a new greyordinate object from a NIFTI file
:param
filename: NIFTI filename or
Image object
:param
image: FSL :class:`image.
Image
`
object
:param mask_values: which values to mask out
:param mask_values: which values to mask out
:return: greyordinate object representing the unmasked voxels
:return: greyordinate object representing the unmasked voxels
"""
"""
...
@@ -211,7 +232,6 @@ class Cifti:
...
@@ -211,7 +232,6 @@ class Cifti:
return
cifti2_axes
.
GreyOrdinates
(
inverted_data
,
[
bm_axes
])
return
cifti2_axes
.
GreyOrdinates
(
inverted_data
,
[
bm_axes
])
class
DenseCifti
(
Cifti
):
class
DenseCifti
(
Cifti
):
"""
"""
Represents sparse data defined for a subset of voxels and vertices (i.e., greyordinates)
Represents sparse data defined for a subset of voxels and vertices (i.e., greyordinates)
...
...
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