Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
William Clarke
fsl_mrs
Commits
e07fc8a1
Commit
e07fc8a1
authored
May 20, 2021
by
William Clarke
Browse files
Add new module and tests for nifti-mrs operations. Implemented split.
parent
68b29d1a
Changes
2
Hide whitespace changes
Inline
Side-by-side
fsl_mrs/tests/test_utils_proc_nifti_mrs_tools.py
0 → 100644
View file @
e07fc8a1
"""Test the split, merge and reorder tools for NIFTI-MRS
Author: Will Clarke <william.clarke@ndcn.ox.ac.uk>
Copyright (C) 2021 University of Oxford
"""
from
pathlib
import
Path
import
pytest
import
numpy
as
np
from
fsl_mrs.utils
import
mrs_io
from
fsl_mrs.utils.preproc
import
nifti_mrs_tools
as
nmrs_tools
testsPath
=
Path
(
__file__
).
parent
test_data_split
=
testsPath
/
'testdata'
/
'fsl_mrs_preproc'
/
'metab_raw.nii.gz'
test_data_merge
=
testsPath
/
'testdata'
/
'fsl_mrs_preproc'
/
'wref_raw.nii.gz'
def
test_split
():
"""Test the split functionality
"""
nmrs
=
mrs_io
.
read_FID
(
test_data_split
)
# Error testing
# Wrong dim tag
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_EDIT'
,
1
)
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"DIM_EDIT not found as dimension tag."
\
" This data contains ['DIM_COIL', 'DIM_DYN', None]."
# Wrong dim index (no dim in this data)
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
6
,
1
)
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"Dimension must be one of 4, 5, or 6 (or DIM_TAG string)."
\
" This data has 6 dimensions,"
\
" i.e. a maximum dimension value of 5."
# Wrong dim index (too low)
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
3
,
1
)
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"Dimension must be one of 4, 5, or 6 (or DIM_TAG string)."
\
" This data has 6 dimensions,"
\
" i.e. a maximum dimension value of 5."
# Wrong dim index type
with
pytest
.
raises
(
TypeError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
[
3
,
],
1
)
assert
exc_info
.
type
is
TypeError
assert
exc_info
.
value
.
args
[
0
]
==
"Dimension must be an int (4, 5, or 6) or string (DIM_TAG string)."
# Single index - out of range low
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
-
1
)
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"index_or_indicies must be between 0 and N-1,"
\
" where N is the size of the specified dimension (64)."
# Single index - out of range high
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
64
)
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"index_or_indicies must be between 0 and N-1,"
\
" where N is the size of the specified dimension (64)."
# List of indicies - out of range low
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
[
-
1
,
0
,
1
])
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"index_or_indicies must have elements between 0 and N,"
\
" where N is the size of the specified dimension (64)."
# List of indicies - out of range high
with
pytest
.
raises
(
ValueError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
[
0
,
65
])
assert
exc_info
.
type
is
ValueError
assert
exc_info
.
value
.
args
[
0
]
==
"index_or_indicies must have elements between 0 and N,"
\
" where N is the size of the specified dimension (64)."
# List of indicies - wrong type
with
pytest
.
raises
(
TypeError
)
as
exc_info
:
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
'1'
)
assert
exc_info
.
type
is
TypeError
assert
exc_info
.
value
.
args
[
0
]
==
"index_or_indicies must be single index or list of indicies"
# Functionality testing
out_1
,
out_2
=
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
32
)
assert
out_1
.
data
.
shape
==
(
1
,
1
,
1
,
4096
,
32
,
32
)
assert
out_2
.
data
.
shape
==
(
1
,
1
,
1
,
4096
,
32
,
32
)
assert
np
.
allclose
(
out_1
.
data
,
nmrs
.
data
[:,
:,
:,
:,
:,
0
:
32
])
assert
np
.
allclose
(
out_2
.
data
,
nmrs
.
data
[:,
:,
:,
:,
:,
32
:])
assert
out_1
.
hdr_ext
==
nmrs
.
hdr_ext
assert
out_1
.
hdr_ext
==
nmrs
.
hdr_ext
assert
np
.
allclose
(
out_1
.
getAffine
(
'voxel'
,
'world'
),
nmrs
.
getAffine
(
'voxel'
,
'world'
))
assert
np
.
allclose
(
out_2
.
getAffine
(
'voxel'
,
'world'
),
nmrs
.
getAffine
(
'voxel'
,
'world'
))
out_1
,
out_2
=
nmrs_tools
.
split
(
nmrs
,
'DIM_DYN'
,
[
0
,
32
,
63
])
assert
out_1
.
data
.
shape
==
(
1
,
1
,
1
,
4096
,
32
,
61
)
assert
out_2
.
data
.
shape
==
(
1
,
1
,
1
,
4096
,
32
,
3
)
test_list
=
np
.
arange
(
0
,
64
)
test_list
=
np
.
delete
(
test_list
,
[
0
,
32
,
63
])
assert
np
.
allclose
(
out_1
.
data
,
nmrs
.
data
[:,
:,
:,
:,
:,
test_list
])
assert
np
.
allclose
(
out_2
.
data
,
nmrs
.
data
[:,
:,
:,
:,
:,
[
0
,
32
,
63
]])
fsl_mrs/utils/preproc/nifti_mrs_tools.py
0 → 100644
View file @
e07fc8a1
"""Tools for merging, splitting and reordering the dimensions of NIfTI-MRS
Author: Will Clarke <william.clarke@ndcn.ox.ac.uk>
Copyright (C) 2021 University of Oxford
"""
import
numpy
as
np
from
fsl_mrs.core.nifti_mrs
import
NIFTI_MRS
,
NIFTIMRS_DimDoesntExist
def
split
(
nmrs
,
dimension
,
index_or_indicies
):
"""Splits, or extracts indices from, a specified dimension of a
NIFTI_MRS object. Output is two NIFTI_MRS objects. Header information preserved.
:param nmrs: Input nifti_mrs object to split
:type nmrs: fsl_mrs.core.nifti_mrs.NIFTI_MRS
:param dimension: Dimension tag or one of 4, 5, 6 (for 0-indexed 5th, 6th, and 7th)
:type dimension: str or int
:param index_or_indicies: Single integer index to split after,
or list of interger indices to insert into second array.
E.g. '0' will place the first index into the first output
and 1 -> N in the second.
'[1, 5, 10]' will place 1, 5 and 10 into the second output
and all other will remain in the first.
:type index_or_indicies: int or [int]
:return: Two NIFTI_MRS object containing the split files
:rtype: fsl_mrs.core.nifti_mrs.NIFTI_MRS
"""
if
isinstance
(
dimension
,
str
):
try
:
dim_index
=
nmrs
.
dim_position
(
dimension
)
except
NIFTIMRS_DimDoesntExist
:
raise
ValueError
(
f
'
{
dimension
}
not found as dimension tag. This data contains
{
nmrs
.
dim_tags
}
.'
)
elif
isinstance
(
dimension
,
int
):
if
dimension
>
(
nmrs
.
ndim
-
1
)
or
dimension
<
4
:
raise
ValueError
(
'Dimension must be one of 4, 5, or 6 (or DIM_TAG string).'
f
' This data has
{
nmrs
.
ndim
}
dimensions,'
f
' i.e. a maximum dimension value of
{
nmrs
.
ndim
-
1
}
.'
)
dim_index
=
dimension
else
:
raise
TypeError
(
'Dimension must be an int (4, 5, or 6) or string (DIM_TAG string).'
)
# Construct indexing
if
isinstance
(
index_or_indicies
,
int
):
if
index_or_indicies
<
0
\
or
index_or_indicies
>=
nmrs
.
shape
[
dim_index
]:
raise
ValueError
(
'index_or_indicies must be between 0 and N-1,'
f
' where N is the size of the specified dimension (
{
nmrs
.
shape
[
dim_index
]
}
).'
)
index
=
np
.
arange
(
index_or_indicies
,
nmrs
.
shape
[
dim_index
])
elif
isinstance
(
index_or_indicies
,
list
):
if
not
np
.
logical_and
(
np
.
asarray
(
index_or_indicies
)
>=
0
,
np
.
asarray
(
index_or_indicies
)
<=
nmrs
.
shape
[
dim_index
]).
all
():
raise
ValueError
(
'index_or_indicies must have elements between 0 and N,'
f
' where N is the size of the specified dimension (
{
nmrs
.
shape
[
dim_index
]
}
).'
)
index
=
index_or_indicies
else
:
raise
TypeError
(
'index_or_indicies must be single index or list of indicies'
)
nmrs_1
=
NIFTI_MRS
(
np
.
delete
(
nmrs
.
data
,
index
,
axis
=
dim_index
),
header
=
nmrs
.
header
)
nmrs_2
=
NIFTI_MRS
(
np
.
take
(
nmrs
.
data
,
index
,
axis
=
dim_index
),
header
=
nmrs
.
header
)
return
nmrs_1
,
nmrs_2
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment