12
12
13
13
import numpy as np
14
14
15
+ from .. import xmlutils as xml
15
16
from ..nifti1 import data_type_codes , xform_codes , intent_codes
16
17
from .util import (array_index_order_codes , gifti_encoding_codes ,
17
18
gifti_endian_codes , KIND2FMT )
22
23
import base64
23
24
24
25
25
- class GiftiMetaData (object ):
26
+ class GiftiMetaData (xml . XmlSerializable ):
26
27
""" A list of GiftiNVPairs in stored in
27
28
the list self.data """
28
29
def __init__ (self , nvpair = None ):
@@ -50,18 +51,15 @@ def metadata(self):
50
51
self .data_as_dict [ele .name ] = ele .value
51
52
return self .data_as_dict
52
53
53
- def to_xml (self ):
54
- if len (self .data ) == 0 :
55
- return "<MetaData/>\n "
56
- res = "<MetaData>\n "
54
+ def _to_xml_element (self ):
55
+ metadata = xml .Element ('MetaData' )
57
56
for ele in self .data :
58
- nvpair = """<MD>
59
- \t <Name><![CDATA[%s]]></Name>
60
- \t <Value><![CDATA[%s]]></Value>
61
- </MD>\n """ % (ele .name , ele .value )
62
- res = res + nvpair
63
- res = res + "</MetaData>\n "
64
- return res
57
+ md = xml .SubElement (metadata , 'MD' )
58
+ name = xml .SubElement (md , 'Name' )
59
+ value = xml .SubElement (md , 'Value' )
60
+ name .text = ele .name
61
+ value .text = ele .value
62
+ return metadata
65
63
66
64
def print_summary (self ):
67
65
print (self .metadata )
@@ -77,7 +75,7 @@ def __init__(self, name='', value=''):
77
75
self .value = value
78
76
79
77
80
- class GiftiLabelTable (object ):
78
+ class GiftiLabelTable (xml . XmlSerializable ):
81
79
82
80
def __init__ (self ):
83
81
self .labels = []
@@ -88,31 +86,22 @@ def get_labels_as_dict(self):
88
86
self .labels_as_dict [ele .key ] = ele .label
89
87
return self .labels_as_dict
90
88
91
- def to_xml (self ):
92
- if len (self .labels ) == 0 :
93
- return "<LabelTable/>\n "
94
- res = "<LabelTable>\n "
89
+ def _to_xml_element (self ):
90
+ labeltable = xml .Element ('LabelTable' )
95
91
for ele in self .labels :
96
- col = ''
97
- if not ele .red is None :
98
- col += ' Red="%s"' % str (ele .red )
99
- if not ele .green is None :
100
- col += ' Green="%s"' % str (ele .green )
101
- if not ele .blue is None :
102
- col += ' Blue="%s"' % str (ele .blue )
103
- if not ele .alpha is None :
104
- col += ' Alpha="%s"' % str (ele .alpha )
105
- lab = """\t <Label Key="%s"%s><![CDATA[%s]]></Label>\n """ % \
106
- (str (ele .key ), col , ele .label )
107
- res = res + lab
108
- res = res + "</LabelTable>\n "
109
- return res
92
+ label = xml .SubElement (labeltable , 'Label' )
93
+ label .attrib ['Key' ] = str (ele .key )
94
+ label .text = ele .label
95
+ for attr in ['Red' , 'Green' , 'Blue' , 'Alpha' ]:
96
+ if getattr (ele , attr .lower (), None ) is not None :
97
+ label .attrib [attr ] = str (getattr (ele , attr .lower ()))
98
+ return labeltable
110
99
111
100
def print_summary (self ):
112
101
print (self .get_labels_as_dict ())
113
102
114
103
115
- class GiftiLabel (object ):
104
+ class GiftiLabel (xml . XmlSerializable ):
116
105
key = int
117
106
label = str
118
107
# rgba
@@ -165,7 +154,7 @@ def _arr2txt(arr, elem_fmt):
165
154
return '\n ' .join (fmt % tuple (row ) for row in arr )
166
155
167
156
168
- class GiftiCoordSystem (object ):
157
+ class GiftiCoordSystem (xml . XmlSerializable ):
169
158
dataspace = int
170
159
xformspace = int
171
160
xform = np .ndarray # 4x4 numpy array
@@ -179,28 +168,37 @@ def __init__(self, dataspace=0, xformspace=0, xform=None):
179
168
else :
180
169
self .xform = xform
181
170
182
- def to_xml (self ):
183
- if self .xform is None :
184
- return "<CoordinateSystemTransformMatrix/>\n "
185
- res = ("""<CoordinateSystemTransformMatrix>
186
- \t <DataSpace><![CDATA[%s]]></DataSpace>
187
- \t <TransformedSpace><![CDATA[%s]]></TransformedSpace>\n """
188
- % (xform_codes .niistring [self .dataspace ],
189
- xform_codes .niistring [self .xformspace ]))
190
- res = res + "<MatrixData>\n "
191
- res += _arr2txt (self .xform , '%10.6f' )
192
- res = res + "</MatrixData>\n "
193
- res = res + "</CoordinateSystemTransformMatrix>\n "
194
- return res
171
+ def _to_xml_element (self ):
172
+ coord_xform = xml .Element ('CoordinateSystemTransformMatrix' )
173
+ if self .xform is not None :
174
+ dataspace = xml .SubElement (coord_xform , 'DataSpace' )
175
+ dataspace .text = xform_codes .niistring [self .dataspace ]
176
+ xformed_space = xml .SubElement (coord_xform , 'TransformedSpace' )
177
+ xformed_space .text = xform_codes .niistring [self .xformspace ]
178
+ matrix_data = xml .SubElement (coord_xform , 'MatrixData' )
179
+ matrix_data .text = _arr2txt (self .xform , '%10.6f' )
180
+ return coord_xform
195
181
196
182
def print_summary (self ):
197
183
print ('Dataspace: ' , xform_codes .niistring [self .dataspace ])
198
184
print ('XFormSpace: ' , xform_codes .niistring [self .xformspace ])
199
185
print ('Affine Transformation Matrix: \n ' , self .xform )
200
186
201
187
188
+ @np .deprecate_with_doc ("This is an internal API that will be discontinued." )
202
189
def data_tag (dataarray , encoding , datatype , ordering ):
203
- """ Creates the data tag depending on the required encoding """
190
+ class DataTag (xml .XmlSerializable ):
191
+ def __init__ (self , * args ):
192
+ self .args = args
193
+ def _to_xml_element (self ):
194
+ return _data_tag_element (* self .args )
195
+
196
+ return DataTag (dataarray , encoding , datatype , ordering ).to_xml ()
197
+
198
+
199
+ def _data_tag_element (dataarray , encoding , datatype , ordering ):
200
+ """ Creates the data tag depending on the required encoding,
201
+ returns as XML element"""
204
202
import zlib
205
203
ord = array_index_order_codes .npcode [ordering ]
206
204
enclabel = gifti_encoding_codes .label [encoding ]
@@ -215,10 +213,13 @@ def data_tag(dataarray, encoding, datatype, ordering):
215
213
raise NotImplementedError ("In what format are the external files?" )
216
214
else :
217
215
da = ''
218
- return "<Data>" + da + "</Data>\n "
216
+
217
+ data = xml .Element ('Data' )
218
+ data .text = da
219
+ return data
219
220
220
221
221
- class GiftiDataArray (object ):
222
+ class GiftiDataArray (xml . XmlSerializable ):
222
223
223
224
# These are for documentation only; we don't use these class variables
224
225
intent = int
@@ -299,26 +300,37 @@ def from_array(klass,
299
300
cda .meta = GiftiMetaData .from_dict (meta )
300
301
return cda
301
302
302
- def to_xml (self ):
303
+ def _to_xml_element (self ):
303
304
# fix endianness to machine endianness
304
305
self .endian = gifti_endian_codes .code [sys .byteorder ]
305
- result = ""
306
- result += self .to_xml_open ()
307
- # write metadata
308
- if not self .meta is None :
309
- result += self .meta .to_xml ()
310
- # write coord sys
311
- if not self .coordsys is None :
312
- result += self .coordsys .to_xml ()
306
+
307
+ data_array = xml .Element ('DataArray' , attrib = {
308
+ 'Intent' : intent_codes .niistring [self .intent ],
309
+ 'DataType' : data_type_codes .niistring [self .datatype ],
310
+ 'ArrayIndexingOrder' : array_index_order_codes .label [self .ind_ord ],
311
+ 'Dimensionality' : str (self .num_dim ),
312
+ 'Encoding' : gifti_encoding_codes .specs [self .encoding ],
313
+ 'Endian' : gifti_endian_codes .specs [self .endian ],
314
+ 'ExternalFileName' : self .ext_fname ,
315
+ 'ExternalFileOffset' : self .ext_offset })
316
+ for di , dn in enumerate (self .dims ):
317
+ data_array .attrib ['Dim%d' % di ] = str (dn )
318
+
319
+ if self .meta is not None :
320
+ data_array .append (self .meta ._to_xml_element ())
321
+ if self .coordsys is not None :
322
+ data_array .append (self .coordsys ._to_xml_element ())
313
323
# write data array depending on the encoding
314
324
dt_kind = data_type_codes .dtype [self .datatype ].kind
315
- result += data_tag (self .data ,
316
- gifti_encoding_codes .specs [self .encoding ],
317
- KIND2FMT [dt_kind ],
318
- self .ind_ord )
319
- result = result + self .to_xml_close ()
320
- return result
325
+ data_array .append (
326
+ _data_tag_element (self .data ,
327
+ gifti_encoding_codes .specs [self .encoding ],
328
+ KIND2FMT [dt_kind ],
329
+ self .ind_ord ))
321
330
331
+ return data_array
332
+
333
+ @np .deprecate_with_doc ("Use the to_xml() function instead." )
322
334
def to_xml_open (self ):
323
335
out = """<DataArray Intent="%s"
324
336
\t DataType="%s"
@@ -342,6 +354,7 @@ def to_xml_open(self):
342
354
self .ext_offset ,
343
355
)
344
356
357
+ @np .deprecate_with_doc ("Use the to_xml() function instead." )
345
358
def to_xml_close (self ):
346
359
return "</DataArray>\n "
347
360
@@ -371,7 +384,8 @@ def metadata(self):
371
384
return self .meta .metadata
372
385
373
386
374
- class GiftiImage (object ):
387
+ class GiftiImage (xml .XmlSerializable ):
388
+
375
389
def __init__ (self , meta = None , labeltable = None , darrays = None ,
376
390
version = "1.0" ):
377
391
if darrays is None :
@@ -497,17 +511,21 @@ def print_summary(self):
497
511
print (da .print_summary ())
498
512
print ('----end----' )
499
513
500
- def to_xml (self ):
514
+
515
+ def _to_xml_element (self ):
516
+ GIFTI = xml .Element ('GIFTI' , attrib = {
517
+ 'Version' : self .version ,
518
+ 'NumberOfDataArrays' : str (self .numDA )})
519
+ if self .meta is not None :
520
+ GIFTI .append (self .meta ._to_xml_element ())
521
+ if self .labeltable is not None :
522
+ GIFTI .append (self .labeltable ._to_xml_element ())
523
+ for dar in self .darrays :
524
+ GIFTI .append (dar ._to_xml_element ())
525
+ return GIFTI
526
+
527
+ def to_xml (self , enc = 'utf-8' ):
501
528
""" Return XML corresponding to image content """
502
- res = """<?xml version="1.0" encoding="UTF-8"?>
529
+ return b """<?xml version="1.0" encoding="UTF-8"?>
503
530
<!DOCTYPE GIFTI SYSTEM "http://www.nitrc.org/frs/download.php/115/gifti.dtd">
504
- <GIFTI Version="%s" NumberOfDataArrays="%s">\n """ % (self .version ,
505
- str (self .numDA ))
506
- if not self .meta is None :
507
- res += self .meta .to_xml ()
508
- if not self .labeltable is None :
509
- res += self .labeltable .to_xml ()
510
- for dar in self .darrays :
511
- res += dar .to_xml ()
512
- res += "</GIFTI>"
513
- return res
531
+ """ + xml .XmlSerializable .to_xml (self , enc )
0 commit comments