Collada XML layout
====================
::
import os
import lxml.etree as ET
parse_ = lambda _:ET.parse(os.path.expandvars(_)).getroot()
COLLADA_NS = "http://www.collada.org/2005/11/COLLADASchema"
xml = parse_("$LOCAL_BASE/env/geant4/geometry/xdae/g4_01.dae")
::
In [249]: len(xml.findall(".//*"))
Out[249]: 24776
Element examination
---------------------
library_nodes
~~~~~~~~~~~~~
::
libnodes = xml.findall("{%s}library_nodes" % COLLADA_NS )[0]
libnodeurl = [node.attrib['id'] for node in libnodes.findall("*")]
In [292]: len(libnodeurl)
Out[292]: 249
In [293]: len(set(libnodeurl))
Out[293]: 249
instance_node
~~~~~~~~~~~~~~
::
urls = [nn.attrib['url'][1:] for nn in xml.findall(".//{%s}instance_node" % COLLADA_NS )]
In [253]: len(urls)
Out[253]: 5643
In [281]: len(set(urls))
Out[281]: 249
In [283]: set(urls)
Out[283]:
set(['__dd__Geometry__AdDetails__lvGasDistributionBoxE0xa904a88',
'__dd__Geometry__CalibrationSources__lvGe68AirTop0xa8fee28',
'__dd__Geometry__PoolDetails__lvTopCornerCableTray0xa9880d0',
'__dd__Geometry__PoolDetails__lvInnShortParCableTray0xa9075d0',
'__dd__Geometry__AdDetails__lvGDBTopFlange0xa9048b0',
'__dd__Geometry__CalibrationBox__lvGdLSInCalibTubAbvLid0xa9028d8',
...
In [294]: set(libnodeurl) == set(urls) # all the 249 urls are used from instance_node referents
Out[294]: True
Only 249 distinct url references, corresponding to logical volumes.
So, for subcopying need to add instance_node referents to library_nodes.
node
~~~~~~
::
nodeid = [n.attrib['id'] for n in xml.findall(".//{%s}node" % COLLADA_NS )]
In [274]: len(nodeid)
Out[274]: 5892
In [282]: len(set(nodeid))
Out[282]: 5892
In [284]: set(nodeid)
Out[284]:
set(['__dd__Geometry__RPCSupport__lvNearHbeamBigUnit--pvNearThwartLongAIRightDownY60xa8cc388',
'__dd__Geometry__Pool__lvNearPoolOWS--pvVetoPmtNearOutFacein--pvNearOutFaceinWall5--pvNearOutFaceinWall5..8--pvVetoPmtUnit--pvPmtMount--pvMountRib1s--pvMountRib1s..2--pvMountRib1unit0xa9c29e8',
'__dd__Geometry__RPCSupport__lvNearHbeamSmallUnit--pvNearThwartLongAIUpY20xa8c6928',
'__dd__Geometry__Pool__lvNearPoolOWS--pvVetoPmtNearOutFacein--pvNearOutFaceinWall9--pvNearOutFaceinWall9..4--pvVetoPmtUnit--pvPmtMount--pvMountRib3s--pvMountRib3s..2--pvMountRib3unit0xa9ed818',
'__dd__Geometry__Pool__lvNearPoolOWS--pvVetoPmtNearOutFacein--pvNearOutFaceinWall3--pvNearOutFaceinWall3..1--pvVetoPmtUnit--pvPmtMount--pvMountRib1s--pvMountRib1s..1--pvMountRib1unit0xa99b208',
'__dd__Geometry__Pool__lvNearPoolOWS--pvVetoPmtNearOutFacein--pvNearOutFaceinWall8--pvNearOutFaceinWall8..7--pvVetoPmtUnit--pvPmtMount--pvMountRib3s--pvMountRib3s..1--pvMountRib3unit0xa9dcc58',
'__dd__Geometry__Pool__lvNearPoolIWS--pvVetoPmtNearInn--pvNearInnWall7--pvNearInnWall7..10--pvVetoPmtUnit--pvPmtMount--pvMountRib3s--pvMountRib3s..1--pvMountRib3unit0xa958630',
...
In [302]: set([len(n.findall("*")) for n in xml.findall(".//{%s}node" % COLLADA_NS )])
Out[302]: set([1, 2, 3, 36, 5, 6, 7, 73, 10, 11, 12, 1620, 179, 9, 521, 55, 4, 2939]) # distinct child counts for every node
In [308]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==1, xml.findall(".//{%s}node" % COLLADA_NS ))])
165
In [307]: print "\n".join([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==1, xml.findall(".//{%s}node" % COLLADA_NS ))]) # all 1 child nodes, mostly instance_geometry
...
In [311]: print "\n".join([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==2, xml.findall(".//{%s}node" % COLLADA_NS ))][0:1])
6.12303e-17 1 0 -910
-1 6.12303e-17 0 0
0 0 1 0
0.0 0.0 0.0 1.0
In [313]: print "\n".join([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==2, xml.findall(".//{%s}node" % COLLADA_NS ))][100:101])
1 0 0 0
0 1 0 3695
0 0 1 -143
0.0 0.0 0.0 1.0
::
In [325]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==1, xml.findall(".//{%s}node" % COLLADA_NS ))])
165
In [314]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==2, xml.findall(".//{%s}node" % COLLADA_NS ))])
5683
In [315]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==3, xml.findall(".//{%s}node" % COLLADA_NS ))])
9
In [316]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==4, xml.findall(".//{%s}node" % COLLADA_NS ))])
4
In [317]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==5, xml.findall(".//{%s}node" % COLLADA_NS ))])
5
In [318]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==6, xml.findall(".//{%s}node" % COLLADA_NS ))])
6
In [319]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==7, xml.findall(".//{%s}node" % COLLADA_NS ))])
5
In [320]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==8, xml.findall(".//{%s}node" % COLLADA_NS ))])
0
In [321]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==9, xml.findall(".//{%s}node" % COLLADA_NS ))])
2
In [322]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==10, xml.findall(".//{%s}node" % COLLADA_NS ))])
3
In [323]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==11, xml.findall(".//{%s}node" % COLLADA_NS ))])
1
In [324]: print len([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==12, xml.findall(".//{%s}node" % COLLADA_NS ))])
2
All nodeid are distinct, corresponding to physical volumes.
Eleven child example
~~~~~~~~~~~~~~~~~~~~~~
::
In [326]: print "\n".join([ET.tostring(n) for n in filter(lambda _:len(_.findall("*"))==11, xml.findall(".//{%s}node" % COLLADA_NS ))])
1 0 0 0
0 1 0 0
0 0 1 150
0.0 0.0 0.0 1.0
1 0 0 8150
0 1 0 0
0 0 1 0
0.0 0.0 0.0 1.0
0.707107 0.707107 0 6603.82
-0.707107 0.707107 0 3603.82
0 0 1 0
0.0 0.0 0.0 1.0
6.12303e-17 1 0 0
-1 6.12303e-17 0 5150
0 0 1 0
0.0 0.0 0.0 1.0
-0.707107 0.707107 0 -6603.82
-0.707107 -0.707107 0 3603.82
0 0 1 0
0.0 0.0 0.0 1.0
-1 1.22461e-16 0 -8150
-1.22461e-16 -1 0 0
0 0 1 0
0.0 0.0 0.0 1.0
-0.707107 -0.707107 0 -6603.82
0.707107 -0.707107 0 -3603.82
0 0 1 0
0.0 0.0 0.0 1.0
6.12303e-17 -1 0 0
1 6.12303e-17 0 -5150
0 0 1 0
0.0 0.0 0.0 1.0
0.707107 -0.707107 0 6603.82
0.707107 0.707107 0 -3603.82
0 0 1 0
0.0 0.0 0.0 1.0
1 0 0 0
0 1 0 0
0 0 1 -5150
0.0 0.0 0.0 1.0