Skip to content

Commit 2a2ad9c

Browse files
committed
Added convenience functions
1 parent 060e65a commit 2a2ad9c

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

nibabel/cifti2/cifti2.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,9 +1114,67 @@ def metadata(self, meta):
11141114
"""
11151115
self._meta = _value_if_klass(meta, Cifti2MetaData)
11161116

1117+
def _get_indices_from_mim(self, mim):
1118+
applies_to_matrix_dimension = mim.applies_to_matrix_dimension
1119+
if not isinstance(
1120+
applies_to_matrix_dimension,
1121+
collections.Iterable
1122+
):
1123+
applies_to_matrix_dimension = (int(applies_to_matrix_dimension),)
1124+
return applies_to_matrix_dimension
1125+
1126+
@property
1127+
def mapped_indices(self):
1128+
'''
1129+
List of matrix indices that are mapped
1130+
'''
1131+
mapped_indices = []
1132+
for v in self:
1133+
a2md = self._get_indices_from_mim(v)
1134+
mapped_indices += a2md
1135+
return mapped_indices
1136+
1137+
def get_index_map(self, index):
1138+
'''
1139+
Cifti2 Mapping class for a given index
1140+
1141+
Parameters
1142+
----------
1143+
index : int
1144+
Index for which we want to obtain the mapping.
1145+
Must be in the mapped_indices sequence.
1146+
1147+
Returns
1148+
-------
1149+
cifti2_map : Cifti2MatrixIndicesMap
1150+
Returns the Cifti2MatrixIndicesMap corresponding to
1151+
the given index.
1152+
'''
1153+
1154+
for v in self:
1155+
a2md = self._get_indices_from_mim(v)
1156+
if index in a2md:
1157+
return v
1158+
else:
1159+
raise Cifti2HeaderError("Index not mapped")
1160+
1161+
def _validate_new_mim(self, value):
1162+
if value.applies_to_matrix_dimension is None:
1163+
raise Cifti2HeaderError(
1164+
"Cifti2MatrixIndicesMap needs to have "
1165+
"the applies_to_matrix_dimension attribute set"
1166+
)
1167+
a2md = self._get_indices_from_mim(value)
1168+
if not set(self.mapped_indices).isdisjoint(a2md):
1169+
raise Cifti2HeaderError(
1170+
"Indices in this Cifti2MatrixIndicesMap "
1171+
"already mapped in this matrix"
1172+
)
1173+
11171174
def __setitem__(self, key, value):
11181175
if not isinstance(value, Cifti2MatrixIndicesMap):
11191176
raise TypeError("Not a valid Cifti2MatrixIndicesMap instance")
1177+
self._validate_new_mim(value)
11201178
self._mims[key] = value
11211179

11221180
def __getitem__(self, key):
@@ -1131,6 +1189,7 @@ def __len__(self):
11311189
def insert(self, index, value):
11321190
if not isinstance(value, Cifti2MatrixIndicesMap):
11331191
raise TypeError("Not a valid Cifti2MatrixIndicesMap instance")
1192+
self._validate_new_mim(value)
11341193
self._mims.insert(index, value)
11351194

11361195
def _to_xml_element(self):
@@ -1151,7 +1210,9 @@ class Cifti2Header(FileBasedHeader, xml.XmlSerializable):
11511210
def __init__(self, matrix=None, version="2.0"):
11521211
FileBasedHeader.__init__(self)
11531212
xml.XmlSerializable.__init__(self)
1154-
self.matrix = Cifti2Matrix() if matrix is None else Cifti2Matrix()
1213+
if matrix is None:
1214+
matrix = Cifti2Matrix()
1215+
self.matrix = matrix
11551216
self.version = version
11561217

11571218
def _to_xml_element(self):
@@ -1167,6 +1228,38 @@ def may_contain_header(klass, binaryblock):
11671228
from .parse_cifti2 import _Cifti2AsNiftiHeader
11681229
return _Cifti2AsNiftiHeader.may_contain_header(binaryblock)
11691230

1231+
@property
1232+
def number_of_mapped_indices(self):
1233+
'''
1234+
Number of mapped indices
1235+
'''
1236+
return len(self.matrix)
1237+
1238+
@property
1239+
def mapped_indices(self):
1240+
'''
1241+
List of matrix indices that are mapped
1242+
'''
1243+
return self.matrix.mapped_indices
1244+
1245+
def get_index_map(self, index):
1246+
'''
1247+
Cifti2 Mapping class for a given index
1248+
1249+
Parameters
1250+
----------
1251+
index : int
1252+
Index for which we want to obtain the mapping.
1253+
Must be in the mapped_indices sequence.
1254+
1255+
Returns
1256+
-------
1257+
cifti2_map : Cifti2MatrixIndicesMap
1258+
Returns the Cifti2MatrixIndicesMap corresponding to
1259+
the given index.
1260+
'''
1261+
return self.matrix.get_index_map(index)
1262+
11701263

11711264
class Cifti2Image(DataobjImage):
11721265
""" Class for single file CIFTI2 format image

nibabel/cifti2/tests/test_cifti2.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,30 @@ def test_matrix():
277277
assert_raises(TypeError, m.__setitem__, 0, ci.Cifti2Parcel())
278278
assert_raises(TypeError, m.insert, 0, ci.Cifti2Parcel())
279279

280+
mim_none = ci.Cifti2MatrixIndicesMap(None, 'CIFTI_INDEX_TYPE_LABELS')
281+
mim_0 = ci.Cifti2MatrixIndicesMap(0, 'CIFTI_INDEX_TYPE_LABELS')
282+
mim_1 = ci.Cifti2MatrixIndicesMap(1, 'CIFTI_INDEX_TYPE_LABELS')
283+
mim_01 = ci.Cifti2MatrixIndicesMap([0, 1], 'CIFTI_INDEX_TYPE_LABELS')
284+
285+
assert_raises(ci.Cifti2HeaderError, m.insert, 0, mim_none)
286+
assert_equal(m.mapped_indices, [])
287+
288+
h = ci.Cifti2Header(matrix=m)
289+
assert_equal(m.mapped_indices, [])
290+
m.insert(0, mim_0)
291+
assert_equal(h.mapped_indices, [0])
292+
assert_equal(h.number_of_mapped_indices, 1)
293+
assert_raises(ci.Cifti2HeaderError, m.insert, 0, mim_0)
294+
assert_raises(ci.Cifti2HeaderError, m.insert, 0, mim_01)
295+
m[0] = mim_1
296+
assert_equal(list(m.mapped_indices), [1])
297+
m.insert(0, mim_0)
298+
assert_equal(list(sorted(m.mapped_indices)), [0, 1])
299+
assert_equal(h.number_of_mapped_indices, 2)
300+
assert_equal(h.get_index_map(0), mim_0)
301+
assert_equal(h.get_index_map(1), mim_1)
302+
assert_raises(ci.Cifti2HeaderError, h.get_index_map, 2)
303+
280304

281305
def test_underscoring():
282306
# Pairs taken from inflection tests

0 commit comments

Comments
 (0)