Skip to content

Commit e514c9c

Browse files
committed
Merge pull request nipy#403 from bcipolli/gifti-fix4
MRG: More GIFTI fixes More commits to make GIFTI more pythonic and test the functionality a bit more thoroughly.
2 parents 664c064 + 48d7bdc commit e514c9c

File tree

4 files changed

+63
-23
lines changed

4 files changed

+63
-23
lines changed

nibabel/gifti/gifti.py

+30-9
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ def print_summary(self):
6868

6969

7070
class GiftiNVPairs(object):
71-
71+
"""
7272
name = str
7373
value = str
74-
74+
"""
7575
def __init__(self, name='', value=''):
7676
self.name = name
7777
self.value = value
@@ -104,6 +104,7 @@ def print_summary(self):
104104

105105

106106
class GiftiLabel(xml.XmlSerializable):
107+
"""
107108
key = int
108109
label = str
109110
# rgba
@@ -114,6 +115,7 @@ class GiftiLabel(xml.XmlSerializable):
114115
green = float
115116
blue = float
116117
alpha = float
118+
"""
117119

118120
def __init__(self, key=0, label='', red=None, green=None, blue=None,
119121
alpha=None):
@@ -157,9 +159,11 @@ def _arr2txt(arr, elem_fmt):
157159

158160

159161
class GiftiCoordSystem(xml.XmlSerializable):
162+
"""
160163
dataspace = int
161164
xformspace = int
162165
xform = np.ndarray # 4x4 numpy array
166+
"""
163167

164168
def __init__(self, dataspace=0, xformspace=0, xform=None):
165169
self.dataspace = dataspace
@@ -224,12 +228,11 @@ def _data_tag_element(dataarray, encoding, datatype, ordering):
224228

225229

226230
class GiftiDataArray(xml.XmlSerializable):
227-
231+
"""
228232
# These are for documentation only; we don't use these class variables
229233
intent = int
230234
datatype = int
231235
ind_ord = int
232-
num_dim = int
233236
dims = list
234237
encoding = int
235238
endian = int
@@ -238,19 +241,38 @@ class GiftiDataArray(xml.XmlSerializable):
238241
data = np.ndarray
239242
coordsys = GiftiCoordSystem
240243
meta = GiftiMetaData
244+
"""
241245

242-
def __init__(self, data=None):
246+
def __init__(self, data=None,
247+
encoding="GIFTI_ENCODING_B64GZ",
248+
endian=sys.byteorder,
249+
coordsys=None,
250+
ordering="C",
251+
meta=None):
252+
"""
253+
Returns a shell object that cannot be saved.
254+
"""
243255
self.data = data
244256
self.dims = []
245-
self.meta = GiftiMetaData()
246-
self.coordsys = GiftiCoordSystem()
257+
self.meta = meta or GiftiMetaData()
258+
self.coordsys = coordsys or GiftiCoordSystem()
247259
self.ext_fname = ''
248260
self.ext_offset = ''
261+
self.intent = 0 # required attribute, NIFTI_INTENT_NONE
262+
self.datatype = 0 # required attribute, void/none
263+
# python/numpy default: column major order
264+
self.ind_ord = array_index_order_codes.code[ordering]
265+
self.encoding = encoding
266+
self.endian = endian
267+
268+
@property
269+
def num_dim(self):
270+
return len(self.dims)
249271

250272
@classmethod
251273
def from_array(klass,
252274
darray,
253-
intent,
275+
intent="NIFTI_INTENT_NONE",
254276
datatype=None,
255277
encoding="GIFTI_ENCODING_B64GZ",
256278
endian=sys.byteorder,
@@ -289,7 +311,6 @@ def from_array(klass,
289311
if meta is None:
290312
meta = {}
291313
cda = klass(darray)
292-
cda.num_dim = len(darray.shape)
293314
cda.dims = list(darray.shape)
294315
if datatype is None:
295316
cda.datatype = data_type_codes.code[darray.dtype]

nibabel/gifti/parse_gifti_fast.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@ def StartElementHandler(self, name, attrs):
167167
if "ArrayIndexingOrder" in attrs:
168168
self.da.ind_ord = array_index_order_codes.code[
169169
attrs["ArrayIndexingOrder"]]
170-
if "Dimensionality" in attrs:
171-
self.da.num_dim = int(attrs["Dimensionality"])
172-
for i in range(self.da.num_dim):
170+
num_dim = int(attrs.get("Dimensionality", 0))
171+
for i in range(num_dim):
173172
di = "Dim%s" % str(i)
174173
if di in attrs:
175174
self.da.dims.append(int(attrs[di]))
176175
# dimensionality has to correspond to the number of DimX given
177-
assert len(self.da.dims) == self.da.num_dim
176+
# TODO (bcipolli): don't assert; raise parse warning, and recover.
177+
assert len(self.da.dims) == num_dim
178178
if "Encoding" in attrs:
179179
self.da.encoding = gifti_encoding_codes.code[attrs["Encoding"]]
180180
if "Endian" in attrs:

nibabel/gifti/tests/test_gifti.py

+28-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import nibabel as nib
88
from nibabel.externals.six import string_types
99
from nibabel.gifti import (GiftiImage, GiftiDataArray, GiftiLabel,
10-
GiftiLabelTable, GiftiMetaData)
10+
GiftiLabelTable, GiftiMetaData, GiftiNVPairs)
1111
from nibabel.gifti.gifti import data_tag
1212
from nibabel.nifti1 import data_type_codes
1313

@@ -34,29 +34,38 @@ def test_gifti_image():
3434
gi = GiftiImage()
3535
assert_equal(gi.numDA, 0)
3636

37-
da = GiftiDataArray(data='data')
37+
# Test from numpy numeric array
38+
data = np.random.random((5,))
39+
da = GiftiDataArray.from_array(data)
3840
gi.add_gifti_data_array(da)
3941
assert_equal(gi.numDA, 1)
40-
assert_equal(gi.darrays[0].data, 'data')
42+
assert_array_equal(gi.darrays[0].data, data)
4143

44+
# Test removing
4245
gi.remove_gifti_data_array(0)
4346
assert_equal(gi.numDA, 0)
4447

48+
# Test from string
49+
da = GiftiDataArray.from_array('zzzzz')
50+
gi.add_gifti_data_array(da)
51+
assert_equal(gi.numDA, 1)
52+
assert_array_equal(gi.darrays[0].data, data)
53+
54+
4555
# Remove from empty
4656
gi = GiftiImage()
4757
gi.remove_gifti_data_array_by_intent(0)
4858
assert_equal(gi.numDA, 0)
4959

5060
# Remove one
5161
gi = GiftiImage()
52-
da = GiftiDataArray(data='data')
62+
da = GiftiDataArray.from_array(np.zeros((5,)), intent=0)
5363
gi.add_gifti_data_array(da)
5464

55-
gi.remove_gifti_data_array_by_intent(0)
56-
assert_equal(gi.numDA, 1)
65+
gi.remove_gifti_data_array_by_intent(3)
66+
assert_equal(gi.numDA, 1, "data array should exist on 'missed' remove")
5767

58-
gi.darrays[0].intent = 0
59-
gi.remove_gifti_data_array_by_intent(0)
68+
gi.remove_gifti_data_array_by_intent(da.intent)
6069
assert_equal(gi.numDA, 0)
6170

6271

@@ -97,13 +106,22 @@ def test_labeltable():
97106
def test_metadata():
98107
# Test deprecation
99108
with clear_and_catch_warnings() as w:
100-
warnings.filterwarnings('once', category=DeprecationWarning)
109+
warnings.filterwarnings('always', category=DeprecationWarning)
101110
assert_equal(len(GiftiDataArray().get_metadata()), 0)
111+
assert_equal(len(w), 1)
102112

103113
# Test deprecation
104114
with clear_and_catch_warnings() as w:
105115
warnings.filterwarnings('once', category=DeprecationWarning)
106116
assert_equal(len(GiftiMetaData().get_metadata()), 0)
117+
assert_equal(len(w), 1)
118+
119+
120+
def test_metadata():
121+
nvpair = GiftiNVPairs('key', 'value')
122+
da = GiftiMetaData(nvpair=nvpair)
123+
assert_equal(da.data[0].name, 'key')
124+
assert_equal(da.data[0].value, 'value')
107125

108126

109127
def test_gifti_label_rgba():
@@ -133,6 +151,7 @@ def assign_rgba(gl, val):
133151
with clear_and_catch_warnings() as w:
134152
warnings.filterwarnings('once', category=DeprecationWarning)
135153
assert_equal(kwargs['red'], gl3.get_rgba()[0])
154+
assert_equal(len(w), 1)
136155

137156
# Test default value
138157
gl4 = GiftiLabel()

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ deps =
2020
deps =
2121
[flake8]
2222
max-line-length=100
23-
ignore=D100,D101,D102,D103,D104,D105,D200,D201,D204,D205,D208,D210,D300,D301,D400,D401,D403,E266,E402,E731,F821,I100,I101,I201,N802,N803,N804,N806
23+
ignore=D100,D101,D102,D103,D104,D105,D200,D201,D202,D204,D205,D208,D209,D210,D300,D301,D400,D401,D403,E266,E402,E731,F821,I100,I101,I201,N802,N803,N804,N806
2424
exclude=*test*,*sphinx*,nibabel/externals/*,*/__init__.py
2525

0 commit comments

Comments
 (0)