2424
2525import numpy as np
2626
27- DEBUG_PRINT = True
27+ DEBUG_PRINT = False
2828
2929CIFTI_MAP_TYPES = ('CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
3030 'CIFTI_INDEX_TYPE_PARCELS' ,
@@ -100,17 +100,19 @@ def get_metadata(self):
100100 self .data_as_dict [ele .name ] = ele .value
101101 return self .data_as_dict
102102
103- def to_xml (self ):
103+ def to_xml (self , prefix = '' , indent = ' ' ):
104104 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
107108 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
114116 return res
115117
116118 def print_summary (self ):
@@ -137,10 +139,10 @@ def get_labels_as_dict(self):
137139 self .labels_as_dict [ele .key ] = ele .label
138140 return self .labels_as_dict
139141
140- def to_xml (self ):
142+ def to_xml (self , prefix = '' , indent = ' ' ):
141143 if len (self .labels ) == 0 :
142- return "<LabelTable/> \n "
143- res = "<LabelTable>\n "
144+ return ''
145+ res = "%s <LabelTable>\n " % prefix
144146 for ele in self .labels :
145147 col = ''
146148 if not ele .red is None :
@@ -151,10 +153,10 @@ def to_xml(self):
151153 col += ' Blue="%s"' % str (ele .blue )
152154 if not ele .alpha is None :
153155 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
158160 return res
159161
160162 def print_summary (self ):
@@ -244,6 +246,16 @@ def set_label_table(self, label_table):
244246 else :
245247 print ("Not a valid CiftiLabelTable instance" )
246248
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+
247259
248260class CiftiSurface (object ):
249261 """Class for Surface """
@@ -254,13 +266,30 @@ def __init__(self, brainStructure=None, surfaceNumberOfVertices=None):
254266 self .brainStructure = brainStructure
255267 self .surfaceNumberOfVertices = surfaceNumberOfVertices
256268
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
257277
258278class CiftiVoxelIndicesIJK (object ):
259279 indices = np .array
260280
261281 def __init__ (self , indices = None ):
262282 self .indices = indices
263283
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+
264293
265294class CiftiVertices (object ):
266295
@@ -271,6 +300,14 @@ def __init__(self, brain_structure=None, vertices=None):
271300 self .vertices = vertices
272301 self .brainStructure = brain_structure
273302
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+
274311
275312class CiftiParcel (object ):
276313 """Class for Parcel"""
@@ -314,6 +351,16 @@ def remove_cifti_vertices(self, ith):
314351 self .vertices .pop (ith )
315352 self .numVA -= 1
316353
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+
317364
318365class CiftiTransformationMatrixVoxelIndicesIJKtoXYZ (object ):
319366
@@ -324,6 +371,16 @@ def __init__(self, meter_exponent=None, matrix=None):
324371 self .meterExponent = meter_exponent
325372 self .matrix = matrix
326373
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+
327384
328385class CiftiVolume (object ):
329386
@@ -334,13 +391,29 @@ def __init__(self, volume_dimensions=None, transform_matrix=None):
334391 self .volumeDimensions = volume_dimensions
335392 self .transformationMatrixVoxelIndicesIJKtoXYZ = transform_matrix
336393
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+
337403
338404class CiftiVertexIndices (object ):
339405 indices = np .array
340406
341407 def __init__ (self , indices = None ):
342408 self .indices = indices
343409
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+
344417
345418class CiftiBrainModel (object ):
346419
@@ -363,8 +436,12 @@ def __init__(self, index_offset=None, index_count=None, model_type=None,
363436
364437 if voxel_indices_ijk is not None :
365438 self .voxelIndicesIJK = voxel_indices_ijk
439+ else :
440+ self .voxelIndicesIJK = CiftiVoxelIndicesIJK ()
366441 if vertex_indices is not None :
367442 self .vertexIndices = vertex_indices
443+ else :
444+ self .vertexIndices = CiftiVertexIndices ()
368445
369446 @property
370447 def voxelIndicesIJK (self ):
@@ -384,6 +461,27 @@ def vertexIndices(self, value):
384461 assert isinstance (value , CiftiVertexIndices )
385462 self ._vertexIndices = value
386463
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+
387485
388486class CiftiMatrixIndicesMap (object ):
389487 """Class for Matrix Indices Map
@@ -529,6 +627,32 @@ def remove_cifti_volume(self):
529627 """ Removes the volume element from the CiftiMatrixIndicesMap """
530628 self .volume = None
531629
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+
532656
533657class CiftiMatrix (object ):
534658
@@ -582,6 +706,17 @@ def remove_cifti_matrix_indices_map(self, ith):
582706 self .mims .pop (ith )
583707 self .numMIM -= 1
584708
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+
585720
586721class CiftiHeader (object ):
587722 ''' Class for Cifti2 header extension '''
@@ -595,6 +730,12 @@ def __init__(self, matrix=None, version="2.0"):
595730 self .matrix = matrix
596731 self .version = version
597732
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+
598739
599740class Outputter (object ):
600741
@@ -742,6 +883,7 @@ def StartElementHandler(self, name, attrs):
742883 parent = self .struct_state [- 1 ]
743884 assert isinstance (parent , (CiftiParcel , CiftiBrainModel ))
744885 parent .voxelIndicesIJK = CiftiVoxelIndicesIJK ()
886+
745887 self .write_to = 'VoxelIndices'
746888 elif name == "Volume" :
747889 mim = self .struct_state [- 1 ]
0 commit comments