CMS 3D CMS Logo

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