CMS 3D CMS Logo

cmstools.py

Go to the documentation of this file.
00001 """Python helper tools for CMS FWLite
00002 
00003 benedikt.hegner@cern.ch
00004 
00005 """
00006 import re
00007 import ROOT
00008 import exceptions
00009 ### define tab completion
00010 try:
00011   import readline #cmscompleter
00012   readline.parse_and_bind('tab: complete')
00013 except:
00014   print 'WARNING: Could not load tab completion'
00015 
00016 
00017 # for adding iterators at runtime
00018 import iterators
00019 
00020 
00021 ### workaround iterator generators for ROOT classes
00022 def all(container):
00023 
00024   # loop over ROOT::TTree and similar
00025   if hasattr(container,'GetEntries'):
00026     try:
00027       entries = container.GetEntries()
00028       for entry in xrange(entries):
00029         yield entry
00030     except:
00031         raise cmserror("Looping of %s failed" %container) 
00032 
00033   # loop over std::vectors and similar
00034   elif hasattr(container, 'size'):
00035     try:
00036       entries = container.size()
00037       for entry in xrange(entries):
00038         yield container[entry]
00039     except:
00040       pass
00041 
00042  # loop over containers with begin and end iterators
00043 def loop(begin, end):
00044     """Convert a pair of C++ iterators into a python generator"""
00045     while (begin != end):
00046         yield begin.__deref__()  #*b
00047         begin.__preinc__()       #++b 
00048 
00049 ### auto branch types (Chris Jones)
00050 def createBranchBuffer(branch):
00051     reColons = re.compile(r'::')
00052     reCloseTemplate =re.compile(r'>')
00053     reOpenTemplate =re.compile(r'<')
00054     branchType = ROOT.branchToClass(branch)
00055     #buffer = eval ('ROOT.'+reColons.sub(".",reOpenTemplate.sub("(ROOT.",reCloseTemplate.sub(")",branchType.GetName())))+'()')
00056     buffer = ROOT.MakeRootClass(branchType.GetName()) ()
00057     if( branch.GetName()[-1] != '.') and (branch.GetName()!="EventAuxiliary"):
00058         branch.SetAddress(buffer)
00059     else:
00060         branch.SetAddress(ROOT.AddressOf(buffer))
00061     return buffer
00062 
00063 
00064 class EventTree(object):
00065       def __init__(self,obj):
00066           if isinstance(obj, ROOT.TTree):
00067               self._tree = obj
00068           elif isinstance(obj, ROOT.TFile):
00069               self._tree = obj.Get("Events")
00070           elif isinstance(obj, str):
00071               self._tree = ROOT.TFile.Open(obj).Get("Events")
00072           else:
00073               raise cmserror("EventTree accepts only TTrees, TFiles and filenames")
00074           self._usedBranches = dict()
00075           self._index = -1
00076           self._aliases = self._tree.GetListOfAliases()
00077       def branch(self,name):
00078           # support for aliases
00079           alias = self._tree.GetAlias(name)
00080           if alias != '': name = alias 
00081           # access the branch in ttree
00082           if name in self._usedBranches:
00083               return self._usedBranches[name]
00084           self._usedBranches[name]=EventBranch(self,name)
00085           return self._usedBranches[name]
00086       def cppCode(self, name):
00087           """C++ code for accessing the product inside the full framework"""
00088           alias = self._tree.GetAlias(name)
00089           if alias != '': name = alias
00090           tmpBranch = self._tree.GetBranch(name)
00091           typeString = ROOT.branchToClass(tmpBranch).GetName()
00092           if "edm::Wrapper" in typeString:
00093               typeString = typeString.replace("<edm::Wrapper","")
00094               typeString = typeString.rstrip(">")
00095           nameParts = name.split("_")
00096           if nameParts[2] == "":
00097               cppCode = 'edm::Handle<%s > dummy;\nevent.getByLabel("%s", dummy);'\
00098                         %(typeString, nameParts[1])
00099           else:
00100               cppCode = 'edm::Handle<%s > dummy;\nevent.getByLabel("%s", "%s", dummy);'\
00101                         %(typeString, nameParts[1], nameParts[2])
00102           return cppCode
00103       def getListOfAliases(self):
00104           return self._aliases
00105       def SetAlias (self, alias, fullName):
00106           self.tree().SetAlias(alias, fullName)
00107       def index(self):
00108           return self._index
00109       def tree(self):
00110           return self._tree
00111       def __setBranchIndicies(self):
00112           for branch in self._usedBranches.itervalues():
00113               branch.setIndex(self._index)
00114       def __getattr__(self, name):
00115           return self.branch(name)
00116       def __getitem__(self,key):
00117           if key <0 or key > self._tree.GetEntries():
00118               raise IndexError
00119           self._index = key
00120           self.__setBranchIndicies()
00121           self._tree.GetEntry(self._index,0)
00122           return Event(self)
00123       def __iter__(self):
00124           # flushing/initializing the root buffers 
00125           entry = 0
00126           self._index = entry
00127           self.__setBranchIndicies()
00128           self._tree.GetEntry(self._index,0)
00129           # the real loop
00130           for entry in xrange(self._tree.GetEntries()):
00131               self._index = entry
00132               self.__setBranchIndicies()
00133               self._tree.GetEntry(self._index,0)
00134               yield Event(self)    # TODO: don't return a new object but update the old one 
00135               
00136 
00137 class Event(object):
00138     def __init__(self, eventTree):
00139         self._eventTree = eventTree
00140 
00141     def getProduct(self, name):
00142         return iterators.addIterator(self._eventTree.branch(name)())
00143 
00144     def __getattr__(self, name):
00145         return iterators.addIterator(self._eventTree.branch(name)())
00146 
00147 
00148 class EventBranch(object):
00149     def __init__(self,parent,name):
00150         self._branch = parent.tree().GetBranch(name)
00151         if self._branch == None:
00152             raise cmserror("Unknown branch "+name)
00153         self._buffer = createBranchBuffer(self._branch)
00154         self._index = parent.index()
00155         self._readData = False
00156     def setIndex(self,index):
00157         self._index = index
00158         self._readData = False
00159     def __readData(self):
00160         self._branch.GetEntry(self._index)
00161         self._readData = True
00162 
00163     # replace this by __getattr__ to allow branch.attr instead of branch().attr
00164     def __call__(self):
00165         if not self._readData:
00166             self.__readData()
00167         return self._buffer
00168 
00169 
00170 class cmserror(exceptions.StandardError):
00171     def __init__(self, message):
00172           length = len(message)+7   #7=len("ERROR: ")
00173           print "="*length
00174           print "ERROR:", message
00175           print "="*length

Generated on Tue Jun 9 17:41:49 2009 for CMSSW by  doxygen 1.5.4