# @(#)root/gdml:$Id$ # Author: Witold Pokorski 05/06/2006 # This is the application-independent part of the GDML 'writer' implementation. # It contains the 'writeFile' method (at the end of the file) which does the actual # formating and writing out of the GDML file as well as the specialized 'add-element' # methods for all the supported GDML elements. These methods are used to build # the content of the GDML document, which is then generatd using the 'writeFile' method. # The constructor of this class takes the output file (.gdml) as argument. # An instance of this class should be passed to the constructor of application-specific # 'writer binding' (in the present case ROOTwriter) as argument. # For any question or remarks concerning this code, please send an email to # Witold.Pokorski@cern.ch. class writer(object): def __init__(self, fname): self.gdmlfile = fname self.define = ['define',{},[]] self.materials = ['materials',{},[]] self.solids = ['solids',{},[]] self.structure = ['structure',{},[]] self.document = ['gdml',{'xmlns:gdml':"http://cern.ch/2001/Schemas/GDML", 'xmlns:xsi':"http://www.w3.org/2001/XMLSchema-instance", 'xsi:noNamespaceSchemaLocation':"gdml.xsd"}, [self.define, self.materials, self.solids, self.structure]] def addPosition(self, name, x, y, z): self.define[2].append(['position',{'name':name, 'x':x, 'y':y, 'z':z, 'unit':'cm'},[]]) def addRotation(self, name, x, y, z): self.define[2].append(['rotation',{'name':name, 'x':x, 'y':y, 'z':z, 'unit':'deg'},[]]) def addMaterial(self, name, a, z, rho): self.materials[2].append(['material', {'name':name, 'Z':z}, [['D',{'value':rho},[]], ['atom',{'value':a},[]]] ] ) def addMixture(self, name, rho, elems): subel = [ ['D',{'value':rho},[]] ] for el in elems.keys(): subel.append(['fraction',{'n':elems[el],'ref':el}, []]) self.materials[2].append(['material',{'name':name}, subel]) def addElement(self, symb, name, z, a): self.materials[2].append(['element', {'name':name, 'formula':symb, 'Z':z}, [['atom', {'value':a},[]] ]]) def addReflSolid(self, name, solid, dx, dy, dz, sx, sy, sz, rx, ry, rz): self.solids[2].append(['reflectedSolid',{'name':name, 'solid':solid, 'dx':dx, 'dy':dy, 'dz':dz, 'sx':sx, 'sy':sy, 'sz':sz, 'rx':rx, 'ry':ry, 'rz':rz},[]]) def addBox(self, name, dx, dy, dz): self.solids[2].append(['box',{'name':name, 'x':dx, 'y':dy, 'z':dz, 'lunit':'cm'},[]]) def addParaboloid(self, name, rlo, rhi, dz): self.solids[2].append(['paraboloid',{'name':name, 'rlo':rlo, 'rhi':rhi, 'dz':dz, 'lunit':'cm'},[]]) def addArb8(self, name, v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y, v7x, v7y, v8x, v8y, dz): self.solids[2].append(['arb8',{'name':name, 'v1x':v1x, 'v1y':v1y, 'v2x':v2x, 'v2y':v2y, 'v3x':v3x, 'v3y':v3y, 'v4x':v4x, 'v4y':v4y, 'v5x':v5x, 'v5y':v5y, 'v6x':v6x, 'v6y':v6y, 'v7x':v7x, 'v7y':v7y, 'v8x':v8x, 'v8y':v8y, 'dz':dz, 'lunit':'cm'},[]]) def addSphere(self, name, rmin, rmax, startphi, deltaphi, starttheta, deltatheta): self.solids[2].append(['sphere',{'name':name, 'rmin':rmin, 'rmax':rmax, 'startphi':startphi, 'deltaphi':deltaphi, 'starttheta':starttheta, 'deltatheta':deltatheta, 'aunit':'deg', 'lunit':'cm'},[]]) def addCone(self, name, z, rmin1, rmin2, rmax1, rmax2, sphi, dphi): self.solids[2].append(['cone',{'name':name, 'z':z, 'rmin1':rmin1, 'rmin2':rmin2, 'rmax1':rmax1, 'rmax2':rmax2, 'startphi':sphi, 'deltaphi':dphi, 'lunit':'cm', 'aunit':'deg'}, []] ) def addPara(self, name, x, y, z, alpha, theta, phi): self.solids[2].append(['para',{'name':name, 'x':x, 'y':y, 'z':z, 'alpha':alpha, 'theta':theta, 'phi':phi, 'lunit':'cm', 'aunit':'deg'}, []] ) def addTrap(self, name, z, theta, phi, y1, x1, x2, alpha1, y2, x3, x4, alpha2): self.solids[2].append(['trap', {'name':name, 'z':z, 'theta':theta, 'phi':phi, 'x1':x1, 'x2':x2, 'x3':x3, 'x4':x4, 'y1':y1, 'y2':y2, 'alpha1':alpha1, 'alpha2':alpha2, 'lunit':'cm', 'aunit':'deg'}, []]) def addTwistedTrap(self, name, z, theta, phi, y1, x1, x2, alpha1, y2, x3, x4, alpha2, twist): self.solids[2].append(['twistTrap', {'name':name, 'z':z, 'theta':theta, 'phi':phi, 'x1':x1, 'x2':x2, 'x3':x3, 'x4':x4, 'y1':y1, 'y2':y2, 'alpha1':alpha1, 'alpha2':alpha2, 'twist':twist, 'aunit':'deg', 'lunit':'cm'}, []]) def addTrd(self, name, x1, x2, y1, y2, z): self.solids[2].append(['trd',{'name':name, 'x1':x1, 'x2':x2, 'y1':y1, 'y2':y2, 'z':z, 'lunit':'cm'}, []]) def addTube(self, name, rmin, rmax, z, startphi, deltaphi): self.solids[2].append(['tube',{'name':name, 'rmin':rmin, 'rmax':rmax, 'z':z, 'startphi':startphi, 'deltaphi':deltaphi, 'lunit':'cm', 'aunit':'deg'},[]]) def addCutTube(self, name, rmin, rmax, z, startphi, deltaphi, lowX, lowY, lowZ, highX, highY, highZ): self.solids[2].append(['cutTube',{'name':name, 'rmin':rmin, 'rmax':rmax, 'z':z, 'startphi':startphi, 'deltaphi':deltaphi, 'lowX':lowX, 'lowY':lowY, 'lowZ':lowZ, 'highX':highX, 'highY':highY, 'highZ':highZ, 'lunit':'cm', 'aunit':'deg'},[]]) def addPolycone(self, name, startphi, deltaphi, zplanes): zpls = [] for zplane in zplanes: zpls.append( ['zplane',{'z':zplane[0], 'rmin':zplane[1], 'rmax':zplane[2]},[]] ) self.solids[2].append(['polycone',{'name':name, 'startphi':startphi, 'deltaphi':deltaphi, 'lunit':'cm', 'aunit':'deg'}, zpls]) def addTorus(self, name, r, rmin, rmax, startphi, deltaphi): self.solids[2].append( ['torus',{'name':name, 'rtor':r, 'rmin':rmin, 'rmax':rmax, 'startphi':startphi, 'deltaphi':deltaphi, 'lunit':'cm', 'aunit':'deg'},[]] ) def addPolyhedra(self, name, startphi, deltaphi, numsides, zplanes): zpls = [] for zplane in zplanes: zpls.append( ['zplane',{'z':zplane[0], 'rmin':zplane[1], 'rmax':zplane[2]},[]] ) self.solids[2].append(['polyhedra',{'name':name, 'startphi':startphi, 'deltaphi':deltaphi, 'numsides':numsides, 'lunit':'cm', 'aunit':'deg'}, zpls]) def addXtrusion(self, name, vertices, sections): elems = [] for vertex in vertices: elems.append( ['twoDimVertex',{'x':vertex[0], 'y':vertex[1]},[]] ) for section in sections: elems.append( ['section',{'zOrder':section[0], 'zPosition':section[1], 'xOffset':section[2], 'yOffset':section[3], 'scalingFactor':section[4]},[]] ) self.solids[2].append(['xtru',{'name':name, 'lunit':'cm'}, elems]) def addEltube(self, name, x, y, z): self.solids[2].append( ['eltube', {'name':name, 'dx':x, 'dy':y, 'dz':z, 'lunit':'cm'},[]] ) def addHype(self, name, rmin, rmax, inst, outst, z): self.solids[2].append( ['hype', {'name':name, 'rmin':rmin, 'rmax':rmax, 'inst':inst, 'outst':outst, 'z':z, 'lunit':'cm', 'aunit':'deg'},[]] ) def addPos(self, subels, type, name, v): if v[0]!=0.0 or v[1]!=0.0 or v[2]!=0.0: subels.append( [type,{'name':name, 'x':v[0], 'y':v[1], 'z':v[2], 'unit':'cm'},[]] ) def addRot(self, subels, type, name, v): if v[0]!=0.0 or v[1]!=0.0 or v[2]!=0.0: subels.append( [type,{'name':name, 'x':v[0], 'y':v[1], 'z':v[2], 'unit':'deg'},[]] ) def addUnion(self, name, lname, ltr, lrot, rname, rtr, rrot): subels = [['first',{'ref':lname},[]], ['second',{'ref':rname},[]]] self.addPos(subels, 'position', rname+'pos', rtr) self.addRot(subels, 'rotation', rname+'rot', rrot) self.addPos(subels, 'firstposition', lname+'pos', ltr) self.addRot(subels, 'firstrotation', lname+'rot', lrot) self.solids[2].append( ['union',{'name':name}, subels]) def addSubtraction(self, name, lname, ltr, lrot, rname, rtr, rrot): subels = [['first',{'ref':lname},[]], ['second',{'ref':rname},[]]] self.addPos(subels, 'position', rname+'pos', rtr) self.addRot(subels, 'rotation', rname+'rot', rrot) self.addPos(subels, 'firstposition', lname+'pos', ltr) self.addRot(subels, 'firstrotation', lname+'rot', lrot) self.solids[2].append( ['subtraction',{'name':name}, subels]) def addIntersection(self, name, lname, ltr, lrot, rname, rtr, rrot): subels = [['first',{'ref':lname},[]], ['second',{'ref':rname},[]]] self.addPos(subels, 'position', rname+'pos', rtr) self.addRot(subels, 'rotation', rname+'rot', rrot) self.addPos(subels, 'firstposition', lname+'pos', ltr) self.addRot(subels, 'firstrotation', lname+'rot', lrot) self.solids[2].append( ['intersection',{'name':name}, subels]) def addVolume(self, volume, solid, material, daughters): subels = [['materialref',{'ref':material},[]], ['solidref',{'ref':solid},[]]] for child in daughters: subsubels = [['volumeref',{'ref':child[0]},[]], ['positionref',{'ref':child[1]},[]]] if child[2]!='': subsubels.append( ['rotationref',{'ref':child[2]},[]] ) subels.append( ['physvol',{}, subsubels]) used = 0 self.structure[2].append(['volume',{'name':volume}, subels, used]) def addAssembly(self, volume, daughters): subels = [] for child in daughters: subsubels = [['volumeref',{'ref':child[0]},[]], ['positionref',{'ref':child[1]},[]]] if child[2]!='': subsubels.append( ['rotationref',{'ref':child[2]},[]] ) subels.append( ['physvol',{}, subsubels]) self.structure[2].append(['assembly',{'name':volume}, subels]) def addSetup(self, name, version, world): self.document[2].append( ['setup',{'name':name, 'version':version}, [ ['world',{'ref':world},[]]] ] ) def writeFile(self): file = open(self.gdmlfile,'w') offset = '' def writeElement(elem, offset): offset = offset + ' ' file.write(offset+'<%s' %(elem[0])) for attr in elem[1].keys(): file.write(' %s="%s"' %(attr,elem[1][attr])) if elem[2].__len__()>0: file.write('>\n') for subel in elem[2]: writeElement(subel, offset) file.write(offset+'\n' %(elem[0])) else: file.write('/>\n') file.write('\n') writeElement(self.document,'')