12
12
13
13
import numpy as np
14
14
15
+ from .. import xmlutils as xml
15
16
from ..filebasedimages import FileBasedHeader , FileBasedImage
16
17
from ..nifti1 import data_type_codes , xform_codes , intent_codes
17
18
from .util import (array_index_order_codes , gifti_encoding_codes ,
23
24
import base64
24
25
25
26
26
- class GiftiMetaData (object ):
27
+ class GiftiMetaData (xml . XmlSerializable ):
27
28
""" A list of GiftiNVPairs in stored in
28
29
the list self.data """
29
30
def __init__ (self , nvpair = None ):
@@ -46,18 +47,15 @@ def get_metadata(self):
46
47
self .data_as_dict [ele .name ] = ele .value
47
48
return self .data_as_dict
48
49
49
- def to_xml (self ):
50
- if len (self .data ) == 0 :
51
- return b"<MetaData/>\n "
52
- res = "<MetaData>\n "
50
+ def _to_xml_element (self ):
51
+ metadata = xml .Element ('MetaData' )
53
52
for ele in self .data :
54
- nvpair = """<MD>
55
- \t <Name><![CDATA[%s]]></Name>
56
- \t <Value><![CDATA[%s]]></Value>
57
- </MD>\n """ % (ele .name , ele .value )
58
- res = res + nvpair
59
- res = res + "</MetaData>\n "
60
- return res .encode ('utf-8' )
53
+ md = xml .SubElement (metadata , 'MD' )
54
+ name = xml .SubElement (md , 'Name' )
55
+ value = xml .SubElement (md , 'Value' )
56
+ name .text = ele .name
57
+ value .text = ele .value
58
+ return metadata
61
59
62
60
def print_summary (self ):
63
61
print (self .get_metadata ())
@@ -73,7 +71,7 @@ def __init__(self, name='', value=''):
73
71
self .value = value
74
72
75
73
76
- class GiftiLabelTable (object ):
74
+ class GiftiLabelTable (xml . XmlSerializable ):
77
75
78
76
def __init__ (self ):
79
77
self .labels = []
@@ -84,31 +82,22 @@ def get_labels_as_dict(self):
84
82
self .labels_as_dict [ele .key ] = ele .label
85
83
return self .labels_as_dict
86
84
87
- def to_xml (self ):
88
- if len (self .labels ) == 0 :
89
- return b"<LabelTable/>\n "
90
- res = "<LabelTable>\n "
85
+ def _to_xml_element (self ):
86
+ labeltable = xml .Element ('LabelTable' )
91
87
for ele in self .labels :
92
- col = ''
93
- if not ele .red is None :
94
- col += ' Red="%s"' % str (ele .red )
95
- if not ele .green is None :
96
- col += ' Green="%s"' % str (ele .green )
97
- if not ele .blue is None :
98
- col += ' Blue="%s"' % str (ele .blue )
99
- if not ele .alpha is None :
100
- col += ' Alpha="%s"' % str (ele .alpha )
101
- lab = """\t <Label Key="%s"%s><![CDATA[%s]]></Label>\n """ % \
102
- (str (ele .key ), col , ele .label )
103
- res = res + lab
104
- res = res + "</LabelTable>\n "
105
- return res .encode ('utf-8' )
88
+ label = xml .SubElement (labeltable , 'Label' )
89
+ label .attrib ['Key' ] = str (ele .key )
90
+ label .text = ele .label
91
+ for attr in ['Red' , 'Green' , 'Blue' , 'Alpha' ]:
92
+ if getattr (ele , attr .lower (), None ) is not None :
93
+ label .attrib [attr ] = str (getattr (ele , attr .lower ()))
94
+ return labeltable
106
95
107
96
def print_summary (self ):
108
97
print (self .get_labels_as_dict ())
109
98
110
99
111
- class GiftiLabel (object ):
100
+ class GiftiLabel (xml . XmlSerializable ):
112
101
key = int
113
102
label = str
114
103
# rgba
@@ -143,7 +132,7 @@ def _arr2txt(arr, elem_fmt):
143
132
return '\n ' .join (fmt % tuple (row ) for row in arr )
144
133
145
134
146
- class GiftiCoordSystem (object ):
135
+ class GiftiCoordSystem (xml . XmlSerializable ):
147
136
dataspace = int
148
137
xformspace = int
149
138
xform = np .ndarray # 4x4 numpy array
@@ -157,29 +146,26 @@ def __init__(self, dataspace=0, xformspace=0, xform=None):
157
146
else :
158
147
self .xform = xform
159
148
160
- def to_xml (self ):
161
- if self .xform is None :
162
- return b"<CoordinateSystemTransformMatrix/>\n "
163
- res = ("""<CoordinateSystemTransformMatrix>
164
- \t <DataSpace><![CDATA[%s]]></DataSpace>
165
- \t <TransformedSpace><![CDATA[%s]]></TransformedSpace>\n """
166
- % (xform_codes .niistring [self .dataspace ],
167
- xform_codes .niistring [self .xformspace ]))
168
- res = res + "<MatrixData>\n "
169
- res += _arr2txt (self .xform , '%10.6f' )
170
- res = res + "</MatrixData>\n "
171
- res = res + "</CoordinateSystemTransformMatrix>\n "
172
- return res .encode ('utf-8' )
149
+ def _to_xml_element (self ):
150
+ coord_xform = xml .Element ('CoordinateSystemTransformMatrix' )
151
+ if self .xform is not None :
152
+ dataspace = xml .SubElement (coord_xform , 'DataSpace' )
153
+ dataspace .text = xform_codes .niistring [self .dataspace ]
154
+ xformed_space = xml .SubElement (coord_xform , 'TransformedSpace' )
155
+ xformed_space .text = xform_codes .niistring [self .xformspace ]
156
+ matrix_data = xml .SubElement (coord_xform , 'MatrixData' )
157
+ matrix_data .text = _arr2txt (self .xform , '%10.6f' )
158
+ return coord_xform
173
159
174
160
def print_summary (self ):
175
161
print ('Dataspace: ' , xform_codes .niistring [self .dataspace ])
176
162
print ('XFormSpace: ' , xform_codes .niistring [self .xformspace ])
177
163
print ('Affine Transformation Matrix: \n ' , self .xform )
178
164
179
165
180
- def data_tag (dataarray , encoding , datatype , ordering ):
166
+ def _data_tag_element (dataarray , encoding , datatype , ordering ):
181
167
""" Creates the data tag depending on the required encoding,
182
- returns as bytes """
168
+ returns as XML element """
183
169
import zlib
184
170
ord = array_index_order_codes .npcode [ordering ]
185
171
enclabel = gifti_encoding_codes .label [encoding ]
@@ -194,10 +180,13 @@ def data_tag(dataarray, encoding, datatype, ordering):
194
180
raise NotImplementedError ("In what format are the external files?" )
195
181
else :
196
182
da = ''
197
- return ("<Data>" + da + "</Data>\n " ).encode ('utf-8' )
198
183
184
+ data = xml .Element ('Data' )
185
+ data .text = da
186
+ return data
199
187
200
- class GiftiDataArray (object ):
188
+
189
+ class GiftiDataArray (xml .XmlSerializable ):
201
190
202
191
# These are for documentation only; we don't use these class variables
203
192
intent = int
@@ -278,51 +267,35 @@ def from_array(klass,
278
267
cda .meta = GiftiMetaData .from_dict (meta )
279
268
return cda
280
269
281
- def to_xml (self ):
270
+ def _to_xml_element (self ):
282
271
# fix endianness to machine endianness
283
272
self .endian = gifti_endian_codes .code [sys .byteorder ]
284
- result = ""
285
- result += self .to_xml_open ().decode ('utf-8' )
286
- # write metadata
287
- if not self .meta is None :
288
- result += self .meta .to_xml ().decode ('utf-8' )
289
- # write coord sys
290
- if not self .coordsys is None :
291
- result += self .coordsys .to_xml ().decode ('utf-8' )
273
+
274
+ data_array = xml .Element ('DataArray' , attrib = {
275
+ 'Intent' : intent_codes .niistring [self .intent ],
276
+ 'DataType' : data_type_codes .niistring [self .datatype ],
277
+ 'ArrayIndexingOrder' : array_index_order_codes .label [self .ind_ord ],
278
+ 'Dimensionality' : str (self .num_dim ),
279
+ 'Encoding' : gifti_encoding_codes .specs [self .encoding ],
280
+ 'Endian' : gifti_endian_codes .specs [self .endian ],
281
+ 'ExternalFileName' : self .ext_fname ,
282
+ 'ExternalFileOffset' : self .ext_offset })
283
+ for di , dn in enumerate (self .dims ):
284
+ data_array .attrib ['Dim%d' % di ] = str (dn )
285
+
286
+ if self .meta is not None :
287
+ data_array .append (self .meta ._to_xml_element ())
288
+ if self .coordsys is not None :
289
+ data_array .append (self .coordsys ._to_xml_element ())
292
290
# write data array depending on the encoding
293
291
dt_kind = data_type_codes .dtype [self .datatype ].kind
294
- result += data_tag (self .data ,
295
- gifti_encoding_codes .specs [self .encoding ],
296
- KIND2FMT [dt_kind ],
297
- self .ind_ord ).decode ('utf-8' )
298
- result = result + self .to_xml_close ().decode ('utf-8' )
299
- return result .encode ('utf-8' )
300
-
301
- def to_xml_open (self ):
302
- out = """<DataArray Intent="%s"
303
- \t DataType="%s"
304
- \t ArrayIndexingOrder="%s"
305
- \t Dimensionality="%s"
306
- %s\t Encoding="%s"
307
- \t Endian="%s"
308
- \t ExternalFileName="%s"
309
- \t ExternalFileOffset="%s">\n """
310
- di = ""
311
- for i , n in enumerate (self .dims ):
312
- di = di + '\t Dim%s=\" %s\" \n ' % (str (i ), str (n ))
313
- return (out % (intent_codes .niistring [self .intent ],
314
- data_type_codes .niistring [self .datatype ],
315
- array_index_order_codes .label [self .ind_ord ],
316
- str (self .num_dim ),
317
- str (di ),
318
- gifti_encoding_codes .specs [self .encoding ],
319
- gifti_endian_codes .specs [self .endian ],
320
- self .ext_fname ,
321
- self .ext_offset ,
322
- )).encode ('utf-8' )
323
-
324
- def to_xml_close (self ):
325
- return b"</DataArray>\n "
292
+ data_array .append (
293
+ _data_tag_element (self .data ,
294
+ gifti_encoding_codes .specs [self .encoding ],
295
+ KIND2FMT [dt_kind ],
296
+ self .ind_ord ))
297
+
298
+ return data_array
326
299
327
300
def print_summary (self ):
328
301
print ('Intent: ' , intent_codes .niistring [self .intent ])
@@ -348,15 +321,14 @@ def get_metadata(self):
348
321
class GiftiHeader (FileBasedHeader ):
349
322
pass
350
323
351
-
352
- class GiftiImage (FileBasedImage ):
324
+ class GiftiImage (FileBasedImage , xml .XmlSerializable ):
353
325
valid_exts = ('.gii' ,)
354
326
files_types = (('image' , '.gii' ),)
355
327
356
328
def __init__ (self , header = None , extra = None , file_map = None , meta = None ,
357
329
labeltable = None , darrays = None , version = "1.0" ):
358
- super ( GiftiImage , self ) .__init__ (header = header , extra = extra ,
359
- file_map = file_map )
330
+ FileBasedImage .__init__ (self , header = header , extra = extra ,
331
+ file_map = file_map )
360
332
361
333
if darrays is None :
362
334
darrays = []
@@ -466,20 +438,24 @@ def print_summary(self):
466
438
print (da .print_summary ())
467
439
print ('----end----' )
468
440
469
- def to_xml (self ):
441
+
442
+ def _to_xml_element (self ):
443
+ GIFTI = xml .Element ('GIFTI' , attrib = {
444
+ 'Version' : self .version ,
445
+ 'NumberOfDataArrays' : str (self .numDA )})
446
+ if self .meta is not None :
447
+ GIFTI .append (self .meta ._to_xml_element ())
448
+ if self .labeltable is not None :
449
+ GIFTI .append (self .labeltable ._to_xml_element ())
450
+ for dar in self .darrays :
451
+ GIFTI .append (dar ._to_xml_element ())
452
+ return GIFTI
453
+
454
+ def to_xml (self , enc = 'utf-8' ):
470
455
""" Return XML corresponding to image content """
471
- res = """<?xml version="1.0" encoding="UTF-8"?>
456
+ return b """<?xml version="1.0" encoding="UTF-8"?>
472
457
<!DOCTYPE GIFTI SYSTEM "http://www.nitrc.org/frs/download.php/115/gifti.dtd">
473
- <GIFTI Version="%s" NumberOfDataArrays="%s">\n """ % (self .version ,
474
- str (self .numDA ))
475
- if not self .meta is None :
476
- res += self .meta .to_xml ().decode ('utf-8' )
477
- if not self .labeltable is None :
478
- res += self .labeltable .to_xml ().decode ('utf-8' )
479
- for dar in self .darrays :
480
- res += dar .to_xml ().decode ('utf-8' )
481
- res += "</GIFTI>"
482
- return res .encode ('utf-8' )
458
+ """ + xml .XmlSerializable .to_xml (self , enc )
483
459
484
460
@classmethod
485
461
def from_file_map (klass , file_map ):
0 commit comments