# @(#)root/gdml:$Id$ # Author: Witold Pokorski 05/06/2006 from math import * import libPyROOT import ROOT import math import re # This class provides ROOT binding for the 'writer' class. It implements specific # methods for all the supported TGeo classes which call the appropriate 'add-element' # methods from the 'writer' class. # The list of presently supported classes is the following: # Materials: # TGeoElement # TGeoMaterial # GeoMixture # Solids: # TGeoBBox # TGeoArb8 # TGeoTubeSeg # TGeoConeSeg # TGeoCtub # TGeoPcon # TGeoTrap # TGeoGtra # TGeoTrd2 # TGeoSphere # TGeoPara # TGeoTorus # TGeoHype # TGeoPgon # TGeoXtru # TGeoEltu # TGeoParaboloid # TGeoCompositeShape (subtraction, union, intersection) # Geometry: # TGeoVolume # In addition the class contains three methods 'dumpMaterials', 'dumpSolids' and 'examineVol' # which retrieve from the memory the materials, the solids and the geometry tree # respectively. The user should instanciate this class passing and instance of 'writer' # class as argument. In order to export the geometry in the form of a GDML file, # the three methods (dumpMaterials, dumpSolids and examineVol) should be called. # The argument of 'dumpMaterials' method should be the list of materials, # the argument of the 'dumpSolids' method should be the list of solids and # the argument of the 'examineVol' method should be the top volume of # the geometry tree. # For any question or remarks concerning this code, please send an email to # Witold.Pokorski@cern.ch. class ROOTwriter(object): def __init__(self, writer): self.writer = writer self.elements = [] self.volumeCount = 0 self.nodeCount = 0 self.shapesCount = 0 self.bvols = [] self.vols = [] self.volsUseCount = {} self.sortedVols = [] self.nodes = [] self.bnodes = [] self.solList = [] self.geomgr = ROOT.gGeoManager self.geomgr.SetAllIndex() pass def genName(self, name): re.sub('$', '', name) return name def rotXYZ(self, r): rad = 180/acos(-1) cosb = math.sqrt( r[0]*r[0] + r[1]*r[1] ) if cosb > 0.00001 : #I didn't find a proper constant to use here, so I just put a value that works with all the examples on a linux machine (P4) a = atan2( r[5], r[8] ) * rad b = atan2( -r[2], cosb ) * rad c = atan2( r[1], r[0] ) * rad else: a = atan2( -r[7], r[4] ) * rad b = atan2( -r[2], cosb ) * rad c = 0. return (a, b, c) def TGeoBBox(self, solid): self.writer.addBox(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDX(), 2*solid.GetDY(), 2*solid.GetDZ()) def TGeoParaboloid(self, solid): self.writer.addParaboloid(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRlo(), solid.GetRhi(), solid.GetDz()) def TGeoSphere(self, solid): self.writer.addSphere(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRmin(), solid.GetRmax(), solid.GetPhi1(), solid.GetPhi2() - solid.GetPhi1(), solid.GetTheta1(), solid.GetTheta2() - solid.GetTheta1()) def TGeoArb8(self, solid): self.writer.addArb8(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetVertices()[0], solid.GetVertices()[1], solid.GetVertices()[2], solid.GetVertices()[3], solid.GetVertices()[4], solid.GetVertices()[5], solid.GetVertices()[6], solid.GetVertices()[7], solid.GetVertices()[8], solid.GetVertices()[9], solid.GetVertices()[10], solid.GetVertices()[11], solid.GetVertices()[12], solid.GetVertices()[13], solid.GetVertices()[14], solid.GetVertices()[15], solid.GetDz()) def TGeoConeSeg(self, solid): self.writer.addCone(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDz(), solid.GetRmin1(), solid.GetRmin2(), solid.GetRmax1(), solid.GetRmax2(), solid.GetPhi1(), solid.GetPhi2() - solid.GetPhi1()) def TGeoCone(self, solid): self.writer.addCone(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDz(), solid.GetRmin1(), solid.GetRmin2(), solid.GetRmax1(), solid.GetRmax2(), 0, 360) def TGeoPara(self, solid): self.writer.addPara(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetX(), solid.GetY(), solid.GetZ(), solid.GetAlpha(), solid.GetTheta(), solid.GetPhi()) def TGeoTrap(self, solid): self.writer.addTrap(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDz(), solid.GetTheta(), solid.GetPhi(), 2*solid.GetH1(), 2*solid.GetBl1(), 2*solid.GetTl1(), solid.GetAlpha1(), 2*solid.GetH2(), 2*solid.GetBl2(), 2*solid.GetTl2(), solid.GetAlpha2()) def TGeoGtra(self, solid): self.writer.addTwistedTrap(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDz(), solid.GetTheta(), solid.GetPhi(), 2*solid.GetH1(), 2*solid.GetBl1(), 2*solid.GetTl1(), solid.GetAlpha1(), 2*solid.GetH2(), 2*solid.GetBl2(), 2*solid.GetTl2(), solid.GetAlpha2(), solid.GetTwistAngle()) def TGeoTrd1(self, solid): self.writer.addTrd(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDx1(), 2*solid.GetDx2(), 2*solid.GetDy(), 2*solid.GetDy(), 2*solid.GetDz()) def TGeoTrd2(self, solid): self.writer.addTrd(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), 2*solid.GetDx1(), 2*solid.GetDx2(), 2*solid.GetDy1(), 2*solid.GetDy2(), 2*solid.GetDz()) def TGeoTubeSeg(self, solid): self.writer.addTube(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRmin(), solid.GetRmax(), 2*solid.GetDz(), solid.GetPhi1(), solid.GetPhi2()-solid.GetPhi1()) def TGeoCtub(self, solid): self.writer.addCutTube(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRmin(), solid.GetRmax(), 2*solid.GetDz(), solid.GetPhi1(), solid.GetPhi2()-solid.GetPhi1(), solid.GetNlow()[0], solid.GetNlow()[1], solid.GetNlow()[2], solid.GetNhigh()[0], solid.GetNhigh()[1], solid.GetNhigh()[2]) def TGeoTube(self, solid): self.writer.addTube(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRmin(), solid.GetRmax(), 2*solid.GetDz(), 0, 360) def TGeoPcon(self, solid): zplanes = [] for i in range(solid.GetNz()): zplanes.append( (solid.GetZ(i), solid.GetRmin(i), solid.GetRmax(i)) ) self.writer.addPolycone(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetPhi1(), solid.GetDphi(), zplanes) def TGeoTorus(self, solid): self.writer.addTorus(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetR(), solid.GetRmin(), solid.GetRmax(), solid.GetPhi1(), solid.GetDphi()) def TGeoPgon(self, solid): zplanes = [] for i in range(solid.GetNz()): zplanes.append( (solid.GetZ(i), solid.GetRmin(i), solid.GetRmax(i)) ) self.writer.addPolyhedra(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetPhi1(), solid.GetDphi(), solid.GetNedges(), zplanes) def TGeoXtru(self, solid): vertices = [] sections = [] for i in range(solid.GetNvert()): vertices.append( (solid.GetX(i), solid.GetY(i)) ) for i in range(solid.GetNz()): sections.append( (i, solid.GetZ(i), solid.GetXOffset(i), solid.GetYOffset(i), solid.GetScale(i)) ) self.writer.addXtrusion(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), vertices, sections) def TGeoEltu(self, solid): self.writer.addEltube(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetA(), solid.GetB(), solid.GetDz()) def TGeoHype(self, solid): self.writer.addHype(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetRmin(), solid.GetRmax(), solid.GetStIn(), solid.GetStOut(), 2*solid.GetDz()) def TGeoUnion(self, solid): lrot = self.rotXYZ(solid.GetBoolNode().GetLeftMatrix().Inverse().GetRotationMatrix()) rrot = self.rotXYZ(solid.GetBoolNode().GetRightMatrix().Inverse().GetRotationMatrix()) if ([solid.GetBoolNode().GetLeftShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetLeftShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetLeftShape().__class__.__name__)(solid.GetBoolNode().GetLeftShape()) self.shapesCount = self.shapesCount + 1 if ([solid.GetBoolNode().GetRightShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetRightShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetRightShape().__class__.__name__)(solid.GetBoolNode().GetRightShape()) self.shapesCount = self.shapesCount + 1 self.writer.addUnion(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetBoolNode().GetLeftShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetLeftShape())[0]), solid.GetBoolNode().GetLeftMatrix().GetTranslation(), lrot, solid.GetBoolNode().GetRightShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetRightShape())[0]), solid.GetBoolNode().GetRightMatrix().GetTranslation(), rrot) def TGeoIntersection(self, solid): lrot = self.rotXYZ(solid.GetBoolNode().GetLeftMatrix().Inverse().GetRotationMatrix()) rrot = self.rotXYZ(solid.GetBoolNode().GetRightMatrix().Inverse().GetRotationMatrix()) if ([solid.GetBoolNode().GetLeftShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetLeftShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetLeftShape().__class__.__name__)(solid.GetBoolNode().GetLeftShape()) self.shapesCount = self.shapesCount + 1 if ([solid.GetBoolNode().GetRightShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetRightShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetRightShape().__class__.__name__)(solid.GetBoolNode().GetRightShape()) self.shapesCount = self.shapesCount + 1 self.writer.addIntersection(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetBoolNode().GetLeftShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetLeftShape())[0]), solid.GetBoolNode().GetLeftMatrix().GetTranslation(), lrot, solid.GetBoolNode().GetRightShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetRightShape())[0]), solid.GetBoolNode().GetRightMatrix().GetTranslation(), rrot) def TGeoSubtraction(self, solid): lrot = self.rotXYZ(solid.GetBoolNode().GetLeftMatrix().Inverse().GetRotationMatrix()) rrot = self.rotXYZ(solid.GetBoolNode().GetRightMatrix().Inverse().GetRotationMatrix()) if ([solid.GetBoolNode().GetLeftShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetLeftShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetLeftShape().__class__.__name__)(solid.GetBoolNode().GetLeftShape()) self.shapesCount = self.shapesCount + 1 if ([solid.GetBoolNode().GetRightShape(), 0]) in self.solList: self.solList[self.solList.index([solid.GetBoolNode().GetRightShape(), 0])][1] = 1 eval('self.'+solid.GetBoolNode().GetRightShape().__class__.__name__)(solid.GetBoolNode().GetRightShape()) self.shapesCount = self.shapesCount + 1 self.writer.addSubtraction(self.genName(solid.GetName())+'_'+str(libPyROOT.AddressOf(solid)[0]), solid.GetBoolNode().GetLeftShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetLeftShape())[0]), solid.GetBoolNode().GetLeftMatrix().GetTranslation(), lrot, solid.GetBoolNode().GetRightShape().GetName()+'_'+str(libPyROOT.AddressOf(solid.GetBoolNode().GetRightShape())[0]), solid.GetBoolNode().GetRightMatrix().GetTranslation(), rrot) def TGeoCompositeShape(self, solid): eval('self.'+solid.GetBoolNode().__class__.__name__)(solid) def dumpMaterials(self, matlist): print 'Info in : Found ', matlist.GetSize(),' materials' for mat in matlist: if not mat.IsMixture(): self.writer.addMaterial(self.genName(mat.GetName()), mat.GetA(), mat.GetZ(), mat.GetDensity()) else: elems = {} for index in range(mat.GetNelements()): elems[mat.GetElement(index).GetName()] = mat.GetWmixt()[index] el = mat.GetElement(index) if el not in self.elements: self.elements.append(el) self.writer.addElement(mat.GetElement(index).GetTitle(), mat.GetElement(index).GetName(), mat.GetZmixt()[index], mat.GetAmixt()[index]) self.writer.addMixture(self.genName(mat.GetName()), mat.GetDensity(), elems) def dumpSolids(self, shapelist): print 'Info in : Found ', shapelist.GetEntries(), ' shapes' for shape in shapelist: self.solList.append([shape, 0]) for sol in self.solList: if sol[1] == 0: sol[1] = 1 #print eval('self.'+sol[0].__class__.__name__)(sol[0]) eval('self.'+sol[0].__class__.__name__)(sol[0]) self.shapesCount = self.shapesCount + 1 print 'Info in : Dumped ', self.shapesCount, ' shapes' def orderVolumes(self, volume): index = str(volume.GetNumber())+"_"+str(libPyROOT.AddressOf(volume)[0]) daughters = volume.GetNodes() if len(self.sortedVols)0: self.volsUseCount[index] = self.volsUseCount[index]-1 if self.volsUseCount[index]==0: self.sortedVols.append(volume) if daughters: for node in daughters: self.orderVolumes(node.GetVolume()) self.nodeCount = self.nodeCount+1 if self.nodeCount%10000==0: print '[FIRST STAGE] Node count: ', self.nodeCount elif len(self.sortedVols)