8
8
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
9
9
10
10
import base64
11
+ import sys
11
12
import zlib
12
13
from StringIO import StringIO
13
14
from xml .parsers .expat import ParserCreate , ExpatError
14
15
15
16
import numpy as np
16
17
18
+ from ..nifti1 import data_type_codes , xform_codes , intent_codes
17
19
from . import gifti as gi
18
- from .util import (data_type_codes , xform_codes , intent_codes ,
19
- array_index_order_codes , gifti_encoding_codes ,
20
+ from .util import (array_index_order_codes , gifti_encoding_codes ,
20
21
gifti_endian_codes )
21
22
22
23
25
26
26
27
def read_data_block (encoding , endian , ordering , datatype , shape , data ):
27
28
""" Tries to unzip, decode, parse the funny string data """
28
- if ordering == 1 :
29
- ord = 'C'
30
- elif ordering == 2 :
31
- ord = 'F'
32
- else :
33
- ord = 'C'
34
-
35
- if encoding == 1 :
29
+ ord = array_index_order_codes .npcode [ordering ]
30
+ enclabel = gifti_encoding_codes .label [encoding ]
31
+ if enclabel == 'ASCII' :
36
32
# GIFTI_ENCODING_ASCII
37
33
c = StringIO (data )
38
34
da = np .loadtxt (c )
39
35
da = da .astype (data_type_codes .type [datatype ])
36
+ # independent of the endianness
40
37
return da
41
-
42
- elif encoding == 2 :
38
+ elif enclabel == 'B64BIN' :
43
39
# GIFTI_ENCODING_B64BIN
44
40
dec = base64 .decodestring (data .encode ('ascii' ))
45
41
dt = data_type_codes .type [datatype ]
46
42
sh = tuple (shape )
47
43
newarr = np .fromstring (dec , dtype = dt )
48
- if len (newarr .shape ) == len (sh ):
49
- return newarr
50
- else :
51
- return newarr .reshape (sh , order = ord )
52
-
53
- elif encoding == 3 :
44
+ if len (newarr .shape ) != len (sh ):
45
+ newarr = newarr .reshape (sh , order = ord )
46
+ elif enclabel == 'B64GZ' :
54
47
# GIFTI_ENCODING_B64GZ
55
48
# convert to bytes array for python 3.2
56
49
# http://diveintopython3.org/strings.html#byte-arrays
@@ -59,16 +52,20 @@ def read_data_block(encoding, endian, ordering, datatype, shape, data):
59
52
dt = data_type_codes .type [datatype ]
60
53
sh = tuple (shape )
61
54
newarr = np .fromstring (zdec , dtype = dt )
62
- if len (newarr .shape ) == len (sh ):
63
- return newarr
64
- else :
65
- return newarr .reshape (sh , order = ord )
66
-
67
- elif encoding == 4 :
55
+ if len (newarr .shape ) != len (sh ):
56
+ newarr = newarr .reshape (sh , order = ord )
57
+ elif enclabel == 'External' :
68
58
# GIFTI_ENCODING_EXTBIN
69
59
raise NotImplementedError ("In what format are the external files?" )
70
60
else :
71
61
return 0
62
+ # check if we need to byteswap
63
+ required_byteorder = gifti_endian_codes .byteorder [endian ]
64
+ if (required_byteorder in ('big' , 'little' ) and
65
+ required_byteorder != sys .byteorder ):
66
+ newarr = newarr .byteswap ()
67
+ return newarr
68
+
72
69
73
70
class Outputter (object ):
74
71
@@ -95,11 +92,10 @@ def initialize(self):
95
92
# where to write CDATA:
96
93
self .write_to = None
97
94
self .img = None
98
-
95
+
99
96
def StartElementHandler (self , name , attrs ):
100
97
if DEBUG_PRINT :
101
98
print 'Start element:\n \t ' , repr (name ), attrs
102
-
103
99
if name == 'GIFTI' :
104
100
# create gifti image
105
101
self .img = gi .GiftiImage ()
@@ -110,7 +106,6 @@ def StartElementHandler(self, name, attrs):
110
106
self .count_da = False
111
107
112
108
self .fsm_state .append ('GIFTI' )
113
-
114
109
elif name == 'MetaData' :
115
110
self .fsm_state .append ('MetaData' )
116
111
@@ -120,28 +115,22 @@ def StartElementHandler(self, name, attrs):
120
115
else :
121
116
# otherwise, create darray.meta
122
117
self .meta_da = gi .GiftiMetaData ()
123
-
124
-
125
118
elif name == 'MD' :
126
119
self .nvpair = gi .GiftiNVPairs ()
127
120
self .fsm_state .append ('MD' )
128
-
129
121
elif name == 'Name' :
130
122
if self .nvpair == None :
131
123
raise ExpatError
132
124
else :
133
125
self .write_to = 'Name'
134
-
135
126
elif name == 'Value' :
136
127
if self .nvpair == None :
137
128
raise ExpatError
138
129
else :
139
130
self .write_to = 'Value'
140
-
141
131
elif name == 'LabelTable' :
142
132
self .lata = gi .GiftiLabelTable ()
143
133
self .fsm_state .append ('LabelTable' )
144
-
145
134
elif name == 'Label' :
146
135
self .label = gi .GiftiLabel ()
147
136
if "Index" in attrs :
@@ -154,9 +143,7 @@ def StartElementHandler(self, name, attrs):
154
143
self .label .blue = float (attrs ["Blue" ])
155
144
if "Alpha" in attrs :
156
145
self .label .alpha = float (attrs ["Alpha" ])
157
-
158
146
self .write_to = 'Label'
159
-
160
147
elif name == 'DataArray' :
161
148
self .da = gi .GiftiDataArray ()
162
149
if "Intent" in attrs :
@@ -171,7 +158,6 @@ def StartElementHandler(self, name, attrs):
171
158
di = "Dim%s" % str (i )
172
159
if di in attrs :
173
160
self .da .dims .append (int (attrs [di ]))
174
-
175
161
# dimensionality has to correspond to the number of DimX given
176
162
assert len (self .da .dims ) == self .da .num_dim
177
163
if "Encoding" in attrs :
@@ -182,49 +168,39 @@ def StartElementHandler(self, name, attrs):
182
168
self .da .ext_fname = attrs ["ExternalFileName" ]
183
169
if "ExternalFileOffset" in attrs :
184
170
self .da .ext_offset = attrs ["ExternalFileOffset" ]
185
-
186
171
self .img .darrays .append (self .da )
187
172
self .fsm_state .append ('DataArray' )
188
-
189
173
elif name == 'CoordinateSystemTransformMatrix' :
190
174
self .coordsys = gi .GiftiCoordSystem ()
191
175
self .img .darrays [- 1 ].coordsys = self .coordsys
192
176
self .fsm_state .append ('CoordinateSystemTransformMatrix' )
193
-
194
177
elif name == 'DataSpace' :
195
178
if self .coordsys == None :
196
179
raise ExpatError
197
180
else :
198
181
self .write_to = 'DataSpace'
199
-
200
182
elif name == 'TransformedSpace' :
201
183
if self .coordsys == None :
202
184
raise ExpatError
203
185
else :
204
186
self .write_to = 'TransformedSpace'
205
-
206
187
elif name == 'MatrixData' :
207
188
if self .coordsys == None :
208
189
raise ExpatError
209
190
else :
210
191
self .write_to = 'MatrixData'
211
-
212
192
elif name == 'Data' :
213
193
self .write_to = 'Data'
214
194
215
-
216
195
def EndElementHandler (self , name ):
217
196
if DEBUG_PRINT :
218
197
print 'End element:\n \t ' , repr (name )
219
-
220
198
if name == 'GIFTI' :
221
199
# remove last element of the list
222
200
self .fsm_state .pop ()
223
201
# assert len(self.fsm_state) == 0
224
-
225
202
elif name == 'MetaData' :
226
203
self .fsm_state .pop ()
227
-
228
204
if len (self .fsm_state ) == 1 :
229
205
# only Gifti there, so this was a closing global
230
206
# metadata tag
@@ -233,26 +209,19 @@ def EndElementHandler(self, name):
233
209
else :
234
210
self .img .darrays [- 1 ].meta = self .meta_da
235
211
self .meta_da = None
236
-
237
212
elif name == 'MD' :
238
213
self .fsm_state .pop ()
239
-
240
214
if not self .meta_global is None and self .meta_da == None :
241
215
self .meta_global .data .append (self .nvpair )
242
-
243
216
elif not self .meta_da is None and self .meta_global == None :
244
217
self .meta_da .data .append (self .nvpair )
245
-
246
218
# remove reference
247
219
self .nvpair = None
248
-
249
220
elif name == 'LabelTable' :
250
221
self .fsm_state .pop ()
251
-
252
222
# add labeltable
253
223
self .img .labeltable = self .lata
254
224
self .lata = None
255
-
256
225
elif name == 'DataArray' :
257
226
if self .count_da :
258
227
self .img .numDA += 1
@@ -277,9 +246,7 @@ def EndElementHandler(self, name):
277
246
self .label = None
278
247
self .write_to = None
279
248
280
-
281
249
def CharacterDataHandler (self , data ):
282
-
283
250
if self .write_to == 'Name' :
284
251
data = data .strip ()
285
252
self .nvpair .name = data
@@ -302,30 +269,41 @@ def CharacterDataHandler(self, data):
302
269
da_tmp .data = read_data_block (da_tmp .encoding , da_tmp .endian , \
303
270
da_tmp .ind_ord , da_tmp .datatype , \
304
271
da_tmp .dims , data )
272
+ # update the endianness according to the
273
+ # current machine setting
274
+ self .endian = gifti_endian_codes .code [sys .byteorder ]
305
275
elif self .write_to == 'Label' :
306
276
self .label .label = data .strip ()
307
277
308
278
309
279
def parse_gifti_file (fname , buffer_size = 35000000 ):
310
-
280
+ """ Parse gifti file named `fname`, return image
281
+
282
+ Parameters
283
+ ----------
284
+ fname : str
285
+ filename of gifti file
286
+ buffer_size: int, optional
287
+ size of read buffer.
288
+
289
+ Returns
290
+ -------
291
+ img : gifti image
292
+ """
311
293
datasource = open (fname ,'rb' )
312
-
313
294
parser = ParserCreate ()
314
295
parser .buffer_text = True
315
296
parser .buffer_size = buffer_size
316
- HANDLER_NAMES = [
317
- 'StartElementHandler' , 'EndElementHandler' ,
318
- 'CharacterDataHandler' ,
319
- ]
297
+ HANDLER_NAMES = ['StartElementHandler' ,
298
+ 'EndElementHandler' ,
299
+ 'CharacterDataHandler' ]
320
300
out = Outputter ()
321
301
for name in HANDLER_NAMES :
322
302
setattr (parser , name , getattr (out , name ))
323
-
324
303
try :
325
304
parser .ParseFile (datasource )
326
305
except ExpatError :
327
306
print 'An expat error occured while parsing the Gifti file.'
328
-
329
307
# update filename
330
308
out .img .filename = fname
331
309
return out .img
0 commit comments