24
24
25
25
import numpy as np
26
26
27
- DEBUG_PRINT = True
27
+ DEBUG_PRINT = False
28
28
29
29
CIFTI_MAP_TYPES = ('CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
30
30
'CIFTI_INDEX_TYPE_PARCELS' ,
@@ -100,17 +100,19 @@ def get_metadata(self):
100
100
self .data_as_dict [ele .name ] = ele .value
101
101
return self .data_as_dict
102
102
103
- def to_xml (self ):
103
+ def to_xml (self , prefix = '' , indent = ' ' ):
104
104
if len (self .data ) == 0 :
105
- return "<MetaData/>\n "
106
- res = "<MetaData>\n "
105
+ return ''
106
+ res = "%s<MetaData>\n " % prefix
107
+ preindent = prefix + indent
107
108
for ele in self .data :
108
- nvpair = """<MD>
109
- \t <Name><![CDATA[%s]]></Name>
110
- \t <Value><![CDATA[%s]]></Value>
111
- </MD>\n """ % (ele .name , ele .value )
112
- res = res + nvpair
113
- res = res + "</MetaData>\n "
109
+ nvpair = """%s<MD>
110
+ %s<Name>%s</Name>
111
+ %s<Value>%s</Value>
112
+ %s</MD>\n """ % (preindent , preindent + indent , ele .name , preindent + indent ,
113
+ ele .value , preindent )
114
+ res += nvpair
115
+ res += "%s</MetaData>\n " % prefix
114
116
return res
115
117
116
118
def print_summary (self ):
@@ -137,10 +139,10 @@ def get_labels_as_dict(self):
137
139
self .labels_as_dict [ele .key ] = ele .label
138
140
return self .labels_as_dict
139
141
140
- def to_xml (self ):
142
+ def to_xml (self , prefix = '' , indent = ' ' ):
141
143
if len (self .labels ) == 0 :
142
- return "<LabelTable/> \n "
143
- res = "<LabelTable>\n "
144
+ return ''
145
+ res = "%s <LabelTable>\n " % prefix
144
146
for ele in self .labels :
145
147
col = ''
146
148
if not ele .red is None :
@@ -151,10 +153,10 @@ def to_xml(self):
151
153
col += ' Blue="%s"' % str (ele .blue )
152
154
if not ele .alpha is None :
153
155
col += ' Alpha="%s"' % str (ele .alpha )
154
- lab = """\t <Label Key="%s"%s><![CDATA[%s]]></Label>\n """ % \
155
- (str (ele .key ), col , ele .label )
156
- res = res + lab
157
- res = res + " </LabelTable>\n "
156
+ lab = """%s <Label Key="%s"%s><![CDATA[%s]]></Label>\n """ % \
157
+ (prefix + indent , str (ele .key ), col , ele .label )
158
+ res += lab
159
+ res += "%s </LabelTable>\n " % prefix
158
160
return res
159
161
160
162
def print_summary (self ):
@@ -244,6 +246,16 @@ def set_label_table(self, label_table):
244
246
else :
245
247
print ("Not a valid CiftiLabelTable instance" )
246
248
249
+ def to_xml (self , prefix = '' , indent = ' ' ):
250
+ if self .map_name is None :
251
+ return ''
252
+ res = "%s<NamedMap>\n " % prefix
253
+ res += self .meta .to_xml (prefix = prefix + indent , indent = indent )
254
+ res += self .label_table .to_xml (prefix = prefix + indent , indent = indent )
255
+ res += "%s<MapName>%s</MapName>\n " % (prefix + indent , self .map_name )
256
+ res += "%s</NamedMap>\n " % prefix
257
+ return res
258
+
247
259
248
260
class CiftiSurface (object ):
249
261
"""Class for Surface """
@@ -254,13 +266,30 @@ def __init__(self, brainStructure=None, surfaceNumberOfVertices=None):
254
266
self .brainStructure = brainStructure
255
267
self .surfaceNumberOfVertices = surfaceNumberOfVertices
256
268
269
+ def to_xml (self , prefix = '' , indent = ' ' ):
270
+ if self .brainStructure is None :
271
+ return ''
272
+ res = ('%s<Surface BrainStructure="%s" '
273
+ 'SurfaceNumberOfVertices"%s" />\n ' ) % (prefix ,
274
+ self .brainStructure ,
275
+ self .surfaceNumberOfVertices )
276
+ return res
257
277
258
278
class CiftiVoxelIndicesIJK (object ):
259
279
indices = np .array
260
280
261
281
def __init__ (self , indices = None ):
262
282
self .indices = indices
263
283
284
+ def to_xml (self , prefix = '' , indent = ' ' ):
285
+ if self .indices is None :
286
+ return ''
287
+ res = '%s<VoxelIndicesIJK>' % prefix
288
+ for row in self .indices :
289
+ res += ' ' .join (row .astype (str ).tolist ()) + '\n '
290
+ res += '</VoxelIndicesIJK>\n '
291
+ return res
292
+
264
293
265
294
class CiftiVertices (object ):
266
295
@@ -271,6 +300,14 @@ def __init__(self, brain_structure=None, vertices=None):
271
300
self .vertices = vertices
272
301
self .brainStructure = brain_structure
273
302
303
+ def to_xml (self , prefix = '' , indent = ' ' ):
304
+ if self .vertices is None :
305
+ return ''
306
+ res = '%s<Vertices BrainStructure="%s">' % (prefix , self .brainStructure )
307
+ res += ' ' .join (self .vertices .astype (str ).tolist ())
308
+ res += '</Vertices>\n '
309
+ return res
310
+
274
311
275
312
class CiftiParcel (object ):
276
313
"""Class for Parcel"""
@@ -314,6 +351,16 @@ def remove_cifti_vertices(self, ith):
314
351
self .vertices .pop (ith )
315
352
self .numVA -= 1
316
353
354
+ def to_xml (self , prefix = '' , indent = ' ' ):
355
+ if self .name is None :
356
+ return ''
357
+ res = '%s<Parcel Name="%s">\n ' % (prefix , self .name )
358
+ res += self .voxelIndicesIJK .to_xml (prefix = prefix + indent , indent = indent )
359
+ for vertices in self .vertices :
360
+ res += vertices .to_xml (prefix = prefix + indent , indent = indent )
361
+ res += "%s</Parcel>\n " % prefix
362
+ return res
363
+
317
364
318
365
class CiftiTransformationMatrixVoxelIndicesIJKtoXYZ (object ):
319
366
@@ -324,6 +371,16 @@ def __init__(self, meter_exponent=None, matrix=None):
324
371
self .meterExponent = meter_exponent
325
372
self .matrix = matrix
326
373
374
+ def to_xml (self , prefix = '' , indent = ' ' ):
375
+ if self .matrix is None :
376
+ return ''
377
+ res = ('%s<TransformationMatrixVoxelIndices'
378
+ 'IJKtoXYZ MeterExponend="%d">' ) % (prefix , self .meterExponent )
379
+ for row in self .matrix :
380
+ res += '\n ' + ' ' .join (['%.10f' % val for val in row ])
381
+ res += "</TransformationMatrixVoxelIndicesIJKtoXYZ>\n "
382
+ return res
383
+
327
384
328
385
class CiftiVolume (object ):
329
386
@@ -334,13 +391,29 @@ def __init__(self, volume_dimensions=None, transform_matrix=None):
334
391
self .volumeDimensions = volume_dimensions
335
392
self .transformationMatrixVoxelIndicesIJKtoXYZ = transform_matrix
336
393
394
+ def to_xml (self , prefix = '' , indent = ' ' ):
395
+ if not self .volumeDimensions :
396
+ return ''
397
+ res = '%s<Volume VolumeDimensions="%s">\n ' % (prefix ,
398
+ ',' .join ([str (val ) for val in self .volumeDimensions ]))
399
+ res += self .transformationMatrixVoxelIndicesIJKtoXYZ .to_xml (prefix = prefix + '\t ' )
400
+ res += "%s</Volume>\n " % prefix
401
+ return res
402
+
337
403
338
404
class CiftiVertexIndices (object ):
339
405
indices = np .array
340
406
341
407
def __init__ (self , indices = None ):
342
408
self .indices = indices
343
409
410
+ def to_xml (self , prefix = '' , indent = ' ' ):
411
+ if self .indices is None :
412
+ return ''
413
+ indices = ' ' .join (self .indices .astype (str ).tolist ())
414
+ res = '%s<VertexIndices>%s</VertexIndices>\n ' % (prefix , indices )
415
+ return res
416
+
344
417
345
418
class CiftiBrainModel (object ):
346
419
@@ -363,8 +436,12 @@ def __init__(self, index_offset=None, index_count=None, model_type=None,
363
436
364
437
if voxel_indices_ijk is not None :
365
438
self .voxelIndicesIJK = voxel_indices_ijk
439
+ else :
440
+ self .voxelIndicesIJK = CiftiVoxelIndicesIJK ()
366
441
if vertex_indices is not None :
367
442
self .vertexIndices = vertex_indices
443
+ else :
444
+ self .vertexIndices = CiftiVertexIndices ()
368
445
369
446
@property
370
447
def voxelIndicesIJK (self ):
@@ -384,6 +461,27 @@ def vertexIndices(self, value):
384
461
assert isinstance (value , CiftiVertexIndices )
385
462
self ._vertexIndices = value
386
463
464
+ def to_xml (self , prefix = '' , indent = ' ' ):
465
+ if self .indexOffset is None :
466
+ return ''
467
+ attrs = []
468
+ for key in ['IndexOffset' , 'IndexCount' , 'ModelType' , 'BrainStructure' ,
469
+ 'SurfaceNumberOfVertices' ]:
470
+ attr = key [0 ].lower () + key [1 :]
471
+ value = getattr (self , attr )
472
+ if value is not None :
473
+ attrs += ['%s="%s"' % (key , value )]
474
+ attrs = ' ' .join (attrs )
475
+ res = '%s<BrainModel %s>\n ' % (prefix , attrs )
476
+ if self .voxelIndicesIJK :
477
+ res += self .voxelIndicesIJK .to_xml (prefix = prefix + indent ,
478
+ indent = indent )
479
+ if self .vertexIndices :
480
+ res += self .vertexIndices .to_xml (prefix = prefix + indent ,
481
+ indent = indent )
482
+ res += "%s</BrainModel>\n " % prefix
483
+ return res
484
+
387
485
388
486
class CiftiMatrixIndicesMap (object ):
389
487
"""Class for Matrix Indices Map
@@ -529,6 +627,32 @@ def remove_cifti_volume(self):
529
627
""" Removes the volume element from the CiftiMatrixIndicesMap """
530
628
self .volume = None
531
629
630
+ def to_xml (self , prefix = '' , indent = ' ' ):
631
+ if self .appliesToMatrixDimension is None :
632
+ return ''
633
+ attrs = []
634
+ for key in ['AppliesToMatrixDimension' , 'IndicesMapToDataType' ,
635
+ 'NumberOfSeriesPoints' , 'SeriesExponent' , 'SeriesStart' ,
636
+ 'SeriesStep' , 'SeriesUnit' ]:
637
+ attr = key [0 ].lower () + key [1 :]
638
+ value = getattr (self , attr )
639
+ if value is not None :
640
+ attrs += ['%s="%s"' % (key , value )]
641
+ attrs = ' ' .join (attrs )
642
+ res = '%s<MatrixIndicesMap %s>\n ' % (prefix , attrs )
643
+ for named_map in self .namedMaps :
644
+ res += named_map .to_xml (prefix = prefix + indent , indent = indent )
645
+ for surface in self .surfaces :
646
+ res += surface .to_xml (prefix = prefix + indent , indent = indent )
647
+ for parcel in self .parcels :
648
+ res += parcel .to_xml (prefix = prefix + indent , indent = indent )
649
+ if self .volume :
650
+ res += self .volume .to_xml (prefix = prefix + indent , indent = indent )
651
+ for model in self .brainModels :
652
+ res += model .to_xml (prefix = prefix + indent , indent = indent )
653
+ res += "%s</MatrixIndicesMap>\n " % prefix
654
+ return res
655
+
532
656
533
657
class CiftiMatrix (object ):
534
658
@@ -582,6 +706,17 @@ def remove_cifti_matrix_indices_map(self, ith):
582
706
self .mims .pop (ith )
583
707
self .numMIM -= 1
584
708
709
+ def to_xml (self , prefix = '' , indent = ' ' ):
710
+ if self .numMIM == 0 :
711
+ return ''
712
+ res = '%s<Matrix>\n ' % prefix
713
+ if self .meta :
714
+ res += self .meta .to_xml (prefix = prefix + indent , indent = indent )
715
+ for mim in self .mims :
716
+ res += mim .to_xml (prefix = prefix + indent , indent = indent )
717
+ res += "%s</Matrix>\n " % prefix
718
+ return res
719
+
585
720
586
721
class CiftiHeader (object ):
587
722
''' Class for Cifti2 header extension '''
@@ -595,6 +730,12 @@ def __init__(self, matrix=None, version="2.0"):
595
730
self .matrix = matrix
596
731
self .version = version
597
732
733
+ def to_xml (self , prefix = '' , indent = ' ' ):
734
+ res = '%s<CIFTI Version="%s">\n ' % (prefix , self .version )
735
+ res += self .matrix .to_xml (prefix = prefix + indent , indent = indent )
736
+ res += "%s</CIFTI>\n " % prefix
737
+ return res
738
+
598
739
599
740
class Outputter (object ):
600
741
@@ -742,6 +883,7 @@ def StartElementHandler(self, name, attrs):
742
883
parent = self .struct_state [- 1 ]
743
884
assert isinstance (parent , (CiftiParcel , CiftiBrainModel ))
744
885
parent .voxelIndicesIJK = CiftiVoxelIndicesIJK ()
886
+
745
887
self .write_to = 'VoxelIndices'
746
888
elif name == "Volume" :
747
889
mim = self .struct_state [- 1 ]
0 commit comments