Newer
Older
Markus Frank
committed
# $Id: Handle.h 570 2013-05-17 07:47:11Z markus.frank $
#==========================================================================
# AIDA Detector description implementation for LCD
#--------------------------------------------------------------------------
# Copyright (C) Organisation européenne pour la Recherche nucléaire (CERN)
# All rights reserved.
#
# For the licensing terms see $DD4hepINSTALL/LICENSE.
# For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
#
#==========================================================================
from math import cos, sin, pi, tan
from os import path, listdir
Pere Mato
committed
from functools import partial
import SystemOfUnits
import math
Pere Mato
committed
from ROOT import SetOwnership, DD4hep, TGeoMixture, TGeoMedium, gGeoManager, TNamed
LCDD = DD4hep.Geometry.LCDD
Constant = DD4hep.Geometry.Constant
Material = DD4hep.Geometry.Material
VisAttr = DD4hep.Geometry.VisAttr
Pere Mato
committed
AlignmentEntry = DD4hep.Geometry.AlignmentEntry
Pere Mato
committed
Limit = DD4hep.Geometry.Limit
DetElement = DD4hep.Geometry.DetElement
Box = DD4hep.Geometry.Box
Tube = DD4hep.Geometry.Tube
Trapezoid = DD4hep.Geometry.Trapezoid
Volume = DD4hep.Geometry.Volume
PlacedVolume = DD4hep.Geometry.PlacedVolume
Position = DD4hep.Geometry.Position
Rotation = DD4hep.Geometry.Rotation
Handle = DD4hep.Geometry.Handle
Pere Mato
committed
Readout = DD4hep.Geometry.Readout
GridXYZ = DD4hep.Geometry.GridXYZ
GlobalGridXY = DD4hep.Geometry.GlobalGridXY
CartesianGridXY = DD4hep.Geometry.CartesianGridXY
Pere Mato
committed
ProjectiveCylinder = DD4hep.Geometry.ProjectiveCylinder
NonProjectiveCylinder = DD4hep.Geometry.NonProjectiveCylinder
ProjectiveZPlane = DD4hep.Geometry.ProjectiveZPlane
Pere Mato
committed
IDDescriptor = DD4hep.Geometry.IDDescriptor
Pere Mato
committed
_toDictionary = DD4hep.Geometry._toDictionary
import xml.etree.ElementTree as xml
unique_mat_id = 0x7FFEFEED
constants = {}
constants.update(SystemOfUnits.__dict__)
Pere Mato
committed
constants.update(math.__dict__)
drivers = {}
drivers.update(math.__dict__)
Pere Mato
committed
drivers.update(DD4hep.Geometry.__dict__)
#---Enhancing the Element class with dedicated accessors--------------------------
Pere Mato
committed
def _getInt(self,attrib): return int(eval(self.get(attrib).replace('(int)',''),constants))
def _getFloat(self,*attrib):
sval = self.get(attrib[0], None)
if not sval and len(attrib) > 1: return attrib[1]
else: return float(eval(sval.replace('(int)',''), constants))
Pere Mato
committed
def _getBool(self,attrib):
return self.get(attrib, '').lower() in ('true', 'yes', 'on')
xml._ElementInterface.getI = _getInt
xml._ElementInterface.getF = _getFloat
xml._ElementInterface.getB = _getBool
Pere Mato
committed
xml._ElementInterface.name = property(lambda self: self.get('name'))
xml._ElementInterface.type = property(lambda self: self.get('type'))
xml._ElementInterface.vis = property(lambda self: self.get('vis'))
xml._ElementInterface.ref = property(lambda self: self.get('ref'))
xml._ElementInterface.value = property(lambda self: self.getF('value'))
Pere Mato
committed
xml._ElementInterface.material = property(lambda self: self.get('material'))
xml._ElementInterface.module = property(lambda self: self.get('module'))
xml._ElementInterface.id = property(lambda self: self.getI('id'))
xml._ElementInterface.number = property(lambda self: self.getI('number'))
Pere Mato
committed
xml._ElementInterface.x1 = property(lambda self: self.getF('x1'))
xml._ElementInterface.x2 = property(lambda self: self.getF('x2'))
xml._ElementInterface.x = property(lambda self: self.getF('x'))
xml._ElementInterface.y = property(lambda self: self.getF('y'))
xml._ElementInterface.z = property(lambda self: self.getF('z'))
xml._ElementInterface.zstart = property(lambda self: self.getF('zstart'))
xml._ElementInterface.offset = property(lambda self: self.getF('offset'))
xml._ElementInterface.radius = property(lambda self: self.getF('radius'))
xml._ElementInterface.zhalf = property(lambda self: self.getF('zhalf'))
Pere Mato
committed
xml._ElementInterface.phi0 = property(lambda self: self.getF('phi0'))
xml._ElementInterface.r = property(lambda self: self.getF('r'))
xml._ElementInterface.dz = property(lambda self: self.getF('dz'))
xml._ElementInterface.thickness = property(lambda self: self.getF('thickness'))
xml._ElementInterface.length = property(lambda self: self.getF('length'))
xml._ElementInterface.width = property(lambda self: self.getF('width'))
xml._ElementInterface.inner_r = property(lambda self: self.getF('inner_r'))
xml._ElementInterface.outer_r = property(lambda self: self.getF('outer_r'))
xml._ElementInterface.z_length = property(lambda self: self.getF('z_length'))
xml._ElementInterface.rmin = property(lambda self: self.getF('rmin'))
xml._ElementInterface.rmax = property(lambda self: self.getF('rmax'))
def getRotation(rot):
Pere Mato
committed
if rot is not None : return Rotation(rot.getF('x',0.0),rot.getF('y',0.0), rot.getF('z',0.0))
else : return Rotation()
Pere Mato
committed
Pere Mato
committed
if pos is not None : return Position(pos.getF('x',0.0),pos.getF('y',0.0), pos.getF('z',0.0))
else : return Position()
drivers['getRotation'] = getRotation
drivers['getPosition'] = getPosition
Pere Mato
committed
#---------------------------------------------------------------------------------
if not args:
args = [path.join(path.dirname(__file__),'drivers')]
for arg in args:
if path.exists(arg):
if path.isfile(arg):
print "Loading driver file ... %s" % arg
execfile(arg, drivers)
elif path.isdir(arg):
for f in listdir(arg) :
if path.splitext(f)[1] == '.py':
print "Loading driver file ... %s" % path.join(arg,f)
execfile(path.join(arg,f), drivers)
else: raise "Path '%s' is not a directory or file" % arg
else: raise "Path '%s' does not exists" % arg
#---------------------------------------------------------------------------------
def process_xmlfile(lcdd, file):
Pere Mato
committed
file = file.replace('file:','')
root = xml.parse(file).getroot()
Pere Mato
committed
tags = ('includes', 'define', 'materials', 'properties', 'limits', 'display',
'readouts', 'detectors', 'alignments', 'fields', 'sensitive_detectors')
if root.tag in tags :
process_tag(lcdd, root)
else :
for tag in tags:
for e in root.findall(tag):
process_tag(lcdd, e)
Pere Mato
committed
def process_tag(lcdd, elem):
if elem.tag == 'detectors' :
lcdd.init() # call init before processing 'detectors' (need world volume)
procs = globals().get('process_%s'% elem.tag, None)
if not procs :
procs = drivers.get('process_%s'% elem.tag, None)
if procs :
apply(procs,(lcdd, elem))
else : print 'XML tag %s not processed!!! No function found.' % elem.tag
#--------------------------------------------------------------------------------
print 'Converting Compact file: ', xmlfile
lcdd = LCDD.getInstance()
process_xmlfile(lcdd, xmlfile)
return lcdd
#---------------------------------------------------------------------------------
def process_includes(lcdd, elem):
for c in elem.findall('gdmlFile'):
print 'Adding Gdml file ...', c.get('ref')
Pere Mato
committed
fname = c.get('ref').replace('file:','')
if not path.isabs(fname): fname = path.join(path.dirname(current_xmlfile),fname)
process_xmlfile(lcdd, fname)
for c in elem.findall('pyBuilder'):
print 'Adding PyBuilder ...', c.get('ref')
Pere Mato
committed
fname = c.get('ref')
if not path.isabs(fname): fname = path.join(path.dirname(current_xmlfile),fname)
load_drivers(fname)
Pere Mato
committed
for c in elem.findall('alignment'):
print 'Adding Alignment file ...', c.get('ref')
fname = c.get('ref').replace('file:','')
if not path.isabs(fname): fname = path.join(path.dirname(current_xmlfile),fname)
process_xmlfile(lcdd, fname)
#---------------------------------------------------------------------------------
def process_info(lcdd, elem):
pass
#---------------------------------------------------------------------------------
def process_define(lcdd, elem):
for c in elem.findall('constant'):
#print 'Adding constant ...', c.get('name')
lcdd.addConstant(Constant(c.get('name'),c.get('value')))
_toDictionary(c.get('name'),c.get('value')) #-- Make it known to the evaluator
constants[c.get('name')] = c.getF('value')
#---------------------------------------------------------------------------------
def process_element(lcdd, elem):
#print 'Adding element ...', elem.get('name')
ename = elem.get('name')
Pere Mato
committed
tab = gGeoManager.GetElementTable()
element = tab.FindElement(ename)
if not element:
atom = elem.find('atom')
tab.AddElement(atom.get('name'), atom.get('formula'), atom.getI('Z'), atom.getI('value'))
#---------------------------------------------------------------------------------
def process_materials(lcdd, elem):
for m in elem.findall('material'):
process_material(lcdd, m)
#---------------------------------------------------------------------------------
# <material formula="Ac" name="Actinium" state="solid" >
# <RL type="X0" unit="cm" value="0.601558" />
# <NIL type="lambda" unit="cm" value="21.2048" />
# <D type="density" unit="g/cm3" value="10.07" />
# <composite n="1" ref="Ac" />
#</material>
#<material name="G10">
# <D type="density" value="1.7" unit="g/cm3"/>
# <fraction n="0.08" ref="Cl"/>
# <fraction n="0.773" ref="Quartz"/>
# <fraction n="0.147" ref="Epoxy"/>
#</material>
def process_material(lcdd, m):
#print 'Adding material ...', m.get('name')
radlen = m.find('RL')
intlen = m.find('NIL')
composites = m.findall('fraction') or m.findall('composite')
Pere Mato
committed
table = gGeoManager.GetElementTable()
mat = TGeoMixture(m.name, len(composites), eval(density.get('value')+'*'+density.get('unit')+'/(g/cm3)',constants))
SetOwnership( mat, False )
rl = (radlen is not None) and eval(radlen.get('value')+'*'+radlen.get('unit'),constants) or 0.0
il = (intlen is not None) and eval(intlen.get('value')+'*'+intlen.get('unit'),constants) or 0.0
#mat.SetRadLen(-rl, -il)
elts = [mat.GetElement(i).GetName() for i in range(mat.GetNelements())]
for c in composites:
if c.tag == 'composite' : fraction = c.getI('n')
elif c.tag == 'fraction' : fraction = c.getF('n')
if table.FindElement(nam):
mat.AddElement(table.FindElement(nam), fraction)
Pere Mato
committed
elif gGeoManager.GetMaterial(nam):
mat.AddElement(gGeoManager.GetMaterial(nam), fraction)
else:
raise 'Something going very wrong. Undefined material:' + nam
if not medium:
global unique_mat_id
unique_mat_id = unique_mat_id - 1
SetOwnership(medium, False)
medium.SetTitle('material')
medium.SetUniqueID(unique_mat_id)
Pere Mato
committed
lcdd.addMaterial(Handle(medium))
#----------------------------------------------------------------------------------
def process_display(lcdd, elem):
for v in elem.findall('vis'):
#print 'Adding vis ...', v.name
Pere Mato
committed
r,g,b = 1.,1.,1.
if 'r' in v.keys() : r = v.getF('r')
if 'g' in v.keys() : g = v.getF('g')
if 'b' in v.keys() : b = v.getF('b')
Pere Mato
committed
visattr.setColor(r,g,b)
if 'showDaughters' in v.keys() : visattr.setShowDaughters(v.getB('showDaughters'))
if 'visible' in v.keys() : visattr.setVisible(v.getB('visible'))
if 'alpha' in v.keys() : visattr.setAlpha(v.getF('alpha'))
Pere Mato
committed
if 'lineStyle' in v.keys() :
ls = v.get('lineStyle')
if ls == 'unbroken' : visattr.setLineStyle(VisAttr.SOLID)
if ls == 'broken' : visattr.setLineStyle(VisAttr.DASHED)
else:
visattr.setLineStyle(VisAttr.SOLID)
if 'drawingStyle' in v.keys() :
ds = v.get('drawingStyle')
if ds == 'wireframe' : visattr.setDrawingStyle(VisAttr.WIREFRAME)
#print visattr.toString()
lcdd.addVisAttribute(visattr)
def process_limits(lcdd, elem):
# <limit name="step_length_max" particles="*" value="5.0" unit="mm" />
for l in elem.findall('limit'):
limit = Limit(lcdd.document(), l.get('name'))
limit.setParticles(l.get('particles'))
limit.setValue(l.getF('value'))
limit.setUnit(l.get('unit'))
lcdd.addLimit(limit)
#-----------------------------------------------------------------------------------
def process_detectors(lcdd, elem):
for d in elem.findall('detector'):
procs = drivers.get('detector_%s'% d.get('type'), None)
if procs :
detector = apply(procs,(lcdd, d))
lcdd.addDetector(detector)
else :
print 'Detector type %s not found' % d.get('type')
Pere Mato
committed
#-----------------------------------------------------------------------------------
def process_alignments(lcdd, elem):
for a in elem.findall('alignment'):
process_alignment(lcdd, a)
#-----------------------------------------------------------------------------------
def process_alignment(lcdd, elem):
alignment = AlignmentEntry(lcdd, elem.name)
pos = getPosition(elem.find('position'))
rot = getRotation(elem.find('rotation'))
print pos.isNull(), rot.isNull()
alignment.align(pos,rot)
return alignment
Pere Mato
committed
#-----------------------------------------------------------------------------------
def process_readouts(lcdd, elem):
for a in elem.findall('readout'):
process_readout(lcdd, a)
Pere Mato
committed
Pere Mato
committed
#-----------------------------------------------------------------------------------
def process_readout(lcdd, elem):
readout = Readout(elem.name)
seg = elem.find('segmentation')
if seg is not None:
procs = globals().get('create_%s'% seg.get('type'), None)
if not procs :
procs = drivers.get('create_%s'% seg.get('type'), None)
if procs :
segment = apply(procs,(lcdd, seg))
readout.setSegmentation(segment)
else :
print 'Segmentation type %s not found' % seg.get('type')
id = elem.find('id')
if id is not None:
idSpec = IDDescriptor(id.text)
idSpec.SetName(elem.name)
readout.setIDDescriptor(idSpec)
lcdd.addIDSpecification(idSpec)
lcdd.addReadout(readout)
#---Segmentations--------------------------------------------------------------------
def create_GridXYZ(lcdd, elem) :
obj = GridXYZ()
if 'gridSizeX' in elem.keys() : obj.setGridSizeX(elem.getF('gridSizeX'))
if 'gridSizeY' in elem.keys() : obj.setGridSizeY(elem.getF('gridSizeY'))
if 'gridSizeZ' in elem.keys() : obj.setGridSizeZ(elem.getF('gridSizeZ'))
return obj
def create_GlobalGridXY(lcdd, elem) :
obj = GlobalGridXY()
if 'gridSizeX' in elem.keys() : obj.setGridSizeX(elem.getF('gridSizeX'))
if 'gridSizeY' in elem.keys() : obj.setGridSizeY(elem.getF('gridSizeY'))
return obj
def create_CartesianGridXY(lcdd, elem) :
obj = CartesianGridXY()
if 'gridSizeX' in elem.keys() : obj.setGridSizeX(elem.getF('gridSizeX'))
if 'gridSizeY' in elem.keys() : obj.setGridSizeY(elem.getF('gridSizeY'))
return obj
Pere Mato
committed
def create_ProjectiveCylinder(lcdd, elem) :
obj = ProjectiveCylinder()
if 'phiBins' in elem.keys() : obj.setPhiBins(elem.getI('phiBins'))
if 'thetaBins' in elem.keys() : obj.setThetaBins(elem.getI('thetaBins'))
Pere Mato
committed
return obj
Pere Mato
committed
def create_NonProjectiveCylinder(lcdd, elem) :
obj = NonProjectiveCylinder()
if 'gridSizePhi' in elem.keys() : obj.setThetaBinSize(elem.getF('gridSizePhi'))
if 'gridSizeZ' in elem.keys() : obj.setPhiBinSize(elem.getI('gridSizeZ'))
return obj
def create_ProjectiveZPlane(lcdd, elem) :
obj = ProjectiveZPlaner()
if 'phiBins' in elem.keys() : obj.setPhiBins(elem.getI('phiBins'))
if 'thetaBins' in elem.keys() : obj.setThetaBins(elem.getI('thetaBins'))
return obj