6 from FWCore.Utilities.Enumerate
import Enumerate
7 from DataFormats.FWLite
import Events, Handle
19 filenameRE = re.compile (
r'.+/Validation/Tools/')
28 def warn (*args, **kwargs):
29 """print out warning with line number and rest of arguments"""
31 frame = inspect.stack()[1]
35 filename = filenameRE.sub (
'', filename)
37 blankLines = kwargs.get(
'blankLines', 0)
39 print '\n' * blankLines
40 spaces = kwargs.get(
'spaces', 0)
44 print "%s (%s): " % (filename, lineNum),
49 print "%s (%s):" % (filename, lineNum)
53 """Infrastruture to define general objects and their attributes."""
59 types = Enumerate (
"float int long string",
"type")
60 _objFunc = Enumerate (
"obj func",
"of")
61 _cppType = dict ( {types.float :
'double',
64 types.string :
'std::string' } )
65 _basicSet = set( [types.float, types.int, types.float,
67 _defaultValue = dict ( {types.float : 0.,
70 types.string :
'""' } )
81 _runEventListDone =
False
82 uselessReturnCode = 1 << 7
87 _nonSpacesRE = re.compile (
r'\S')
88 _colonRE = re.compile (
r'\s*:\s*')
89 _singleColonRE = re.compile (
r'(.+?):(.+)')
90 _doubleColonRE = re.compile (
r'(.+?):(.+?):(.+)')
91 _doublePercentRE = re.compile (
r'%%')
92 _parenRE = re.compile (
r'(.+)\((.*)\)')
93 _spacesRE = re.compile (
r'\s+')
94 _dotRE = re.compile (
r'\s*\.\s*')
95 _commaRE = re.compile (
r'\s*,\s*')
96 _singleQuoteRE = re.compile (
r'^\'(.+)\'$')
97 _doubleQuoteRE = re.compile (
r'^\"(.+)\"$')
98 _bracketRE = re.compile (
r'\[\s*(.+?)\s*\]')
99 _commentRE = re.compile (
r'#.+$')
100 _aliasRE = re.compile (
r'alias=(\S+)', re.IGNORECASE)
101 _labelRE = re.compile (
r'label=(\S+)', re.IGNORECASE)
102 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
103 _singletonRE = re.compile (
r'singleton', re.IGNORECASE)
104 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
105 _defaultRE = re.compile (
r'default=(\S+)', re.IGNORECASE)
106 _shortcutRE = re.compile (
r'shortcut=(\S+)', re.IGNORECASE)
107 _precRE = re.compile (
r'prec=(\S+)', re.IGNORECASE)
108 _formRE = re.compile (
r'form=(\S+)', re.IGNORECASE)
109 _nonAlphaRE = re.compile (
r'\W')
110 _percentAsciiRE = re.compile (
r'%([0-9a-fA-F]{2})')
117 def char2ascii (match):
118 return "%%%02x" % ord (match.group(0))
121 def ascii2char (match):
122 return chr( int( match.group(1), 16 ) )
125 def encodeNonAlphanumerics (line):
126 """Use a web like encoding of characters that are non-alphanumeric"""
127 return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
130 def decodeNonAlphanumerics (line):
131 """Decode lines encoded with encodeNonAlphanumerics()"""
132 return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
136 def addObjectVariable (obj, var, **optionsDict):
137 """ User passes in in object and variable names."""
138 if not optionsDict.has_key (
'varType'):
139 optionsDict[
'varType'] = GenObject.types.float
140 varType = optionsDict[
'varType']
141 if not GenObject.types.isValidValue (varType):
142 print "Type '%s' not valid. Skipping (%s, %s, %s)." % \
143 (varType, obj, var, varType)
145 if not optionsDict.has_key (
'default'):
146 optionsDict[
'default'] = GenObject._defaultValue[varType]
147 if obj.startswith (
"_")
or var.startswith (
"_"):
148 print "Skipping (%s, %s, %s) because of leading underscore." % \
151 GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
155 def getVariableProperty (obj, var, key):
156 """Returns property assoicated with 'key' for variable 'var'
157 of object 'obj'. Returns 'None' if any of the above are not
159 return GenObject._objsDict.get (obj, {}).get (var, {}). get (key,
None)
163 def setEquivExpression (obj, variable, precision):
164 """Adds an equivalence constraint. Must have at least one to
165 compare GO objects."""
166 if obj.startswith (
"_"):
167 print "Skipping (%s, %s) because of leading underscore." % \
170 GenObject._equivDict.setdefault (obj,[]).append ( (variable,
176 """Meant for debugging, but ok if called by user"""
178 pprint.pprint (GenObject._objsDict, indent=4)
180 pprint.pprint (GenObject._equivDict, indent=4)
182 pprint.pprint (GenObject._ntupleDict, indent=4)
184 pprint.pprint (GenObject._tofillDict, indent=4)
185 print "kitchenSink: "
186 pprint.pprint (GenObject._kitchenSinkDict, indent=4)
187 print "rootClassDict"
188 pprint.pprint (GenObject._rootClassDict, indent=4)
193 """Returns a string of hex value of a checksum of input
195 return hex( reduce(
lambda x, y : x + y,
map(ord, str) ) )[2:]
199 def rootClassName (objName):
200 """Returns the name of the equivalent Root object"""
201 return "go_" + objName
205 def rootDiffClassName (objName):
206 """Returns the name of the equivalent Root diff object"""
207 return "goDiff_" + objName
211 def rootDiffContClassName (objName):
212 """Returns the name of the equivalent Root diff container
214 return "goDiffCont_" + objName
218 def _setupClassHeader (className, noColon = False):
219 """Returns a string with the class header for a class
221 retval =
"\nclass %s\n{\n public:\n" % className
222 retval +=
" typedef std::vector< %s > Collection;\n\n" % className
225 retval +=
" %s()" % className
227 retval +=
" %s() :\n" % className
232 def _finishClassHeader (className, datadec):
233 """Returns a stringg with the end of a class definition"""
234 retval =
"\n {}\n" + datadec +
"};\n"
235 retval +=
"#ifdef __MAKECINT__\n#pragma link C++ class " + \
236 "vector< %s >+;\n#endif\n\n" % className
241 def _createCppClass (objName):
242 """Returns a string containing the '.C' file necessary to
243 generate a shared object library with dictionary."""
244 if not GenObject._objsDict.has_key (objName):
246 print "Error: GenObject does not know about object '%s'." % objName
247 raise RuntimeError,
"Failed to create C++ class."
248 className = GenObject.rootClassName (objName)
249 diffName = GenObject.rootDiffClassName (objName)
250 contName = GenObject.rootDiffContClassName (objName)
251 goClass = GenObject._setupClassHeader (className)
252 diffClass = GenObject._setupClassHeader (diffName)
253 contClass = GenObject._setupClassHeader (contName, noColon =
True)
254 goDataDec = diffDataDec = contDataDec =
"\n // data members\n"
256 for key
in sorted( GenObject._objsDict[objName].
keys() ):
257 if key.startswith (
"_"):
continue
258 varTypeList = GenObject._objsDict[objName][key]
259 cppType = GenObject._cppType[ varTypeList[
'varType'] ]
260 default = varTypeList[
'default']
266 goClass +=
" %s (%s)" % (key, default)
267 goDataDec +=
" %s %s;\n" % (cppType, key)
269 goType = varTypeList[
'varType']
270 if goType
in GenObject._basicSet:
272 diffClass +=
" %s (%s),\n" % (key, default)
273 diffDataDec +=
" %s %s;\n" % (cppType, key)
274 if goType == GenObject.types.string:
276 otherKey =
'other_' + key
277 diffClass +=
" %s (%s)" % (otherKey, default)
278 diffDataDec +=
" %s %s;\n" % (cppType, otherKey)
281 deltaKey =
'delta_' + key
282 diffClass +=
" %s (%s)" % (deltaKey, default)
283 diffDataDec +=
" %s %s;\n" % (cppType, deltaKey)
285 raise RuntimeError,
"Shouldn't be here yet."
288 if GenObject.isSingleton (objName):
290 contDataDec +=
" %s diff;\n" % diffName
291 contDataDec +=
" void setDiff (const %s &rhs)" % diffName + \
295 contDataDec +=
" void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n"
296 contDataDec +=
" %s::Collection firstOnly;\n" % className
297 contDataDec +=
" %s::Collection secondOnly;\n" % className
298 contDataDec +=
" %s::Collection diff;\n" % diffName
301 goClass += GenObject._finishClassHeader (className, goDataDec)
302 diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
303 contClass += GenObject._finishClassHeader (contName, contDataDec)
304 if objName ==
'runevent':
308 return goClass + diffClass + contClass
312 def _loadGoRootLibrary ():
313 """Loads Root shared object library associated with all
314 defined GenObjects. Will create library if necessary."""
315 print "Loading GO Root Library"
316 key =
"_loadedLibrary"
317 if GenObject._kitchenSinkDict.get (key):
321 GenObject._kitchenSinkDict[key] =
True
323 sourceCode =
"#include <string>\n#include <vector>\n" \
324 +
"using namespace std;\n"
325 for objClassName
in sorted( GenObject._objsDict.keys() ):
326 sourceCode += GenObject._createCppClass (objClassName)
327 GenObjectRootLibDir =
"genobjectrootlibs"
328 if not os.path.exists (GenObjectRootLibDir):
329 os.mkdir (GenObjectRootLibDir)
330 key = GenObject.checksum( sourceCode )
331 basename =
"%s_%s" % (
"GenObject", key)
332 SO =
"%s/%s_C" % (GenObjectRootLibDir, basename)
333 linuxSO =
"%s.so" % SO
334 windowsSO =
"%s.dll" % SO
335 if not os.path.exists (linuxSO)
and not os.path.exists (windowsSO):
337 filename =
"%s/%s.C" % (GenObjectRootLibDir, basename)
338 if not os.path.exists (filename):
339 print "creating .C file"
340 target = open (filename,
"w")
341 target.write (sourceCode)
344 print "%s exists" % filename
347 ROOT.gSystem.CompileMacro (filename,
"k")
349 print "loading %s" % SO
350 ROOT.gSystem.Load(SO)
355 def _tofillGenObject():
356 """Makes sure that I know how to read root files I made myself"""
357 genObject =
"GenObject"
358 ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
359 ntupleDict[
'_useChain'] =
True
360 ntupleDict[
'_tree'] =
"goTree"
361 for objName
in GenObject._objsDict.keys():
362 rootObjName = GenObject.rootClassName (objName)
363 if GenObject.isSingleton (objName):
364 ntupleDict[objName] = objName
366 ntupleDict[objName] = objName +
"s"
367 tofillDict = GenObject._tofillDict.\
368 setdefault (genObject, {}).\
369 setdefault (objName, {})
370 for varName
in GenObject._objsDict [objName].
keys():
373 if varName.startswith (
"_"):
375 tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
380 def prepareToLoadGenObject():
381 """Makes all necessary preparations to load root files created
383 GenObject._tofillGenObject()
384 GenObject._loadGoRootLibrary()
388 def parseVariableTofill (fillname):
389 """Returns tofill tuple made from string"""
390 parts = GenObject._dotRE.split (fillname)
393 parenMatch = GenObject._parenRE.search (part)
394 mode = GenObject._objFunc.obj
397 part = parenMatch.group (1)
398 mode = GenObject._objFunc.func
400 GenObject._convertStringToParameters \
401 (parenMatch.group (2))
402 partsList.append( (part, mode, parens) )
406 def _fixLostGreaterThans (handle):
407 offset = handle.count (
'<') - handle.count(
'>')
411 print "Huh? Too few '<' for each '>' in handle '%'" % handle
413 return handle +
' >' * offset
417 def loadConfigFile (configFile):
418 """Loads configuration file"""
422 modeEnum = Enumerate (
"none define tofill ntuple",
"mode")
425 config = open (configFile,
'r')
427 raise RuntimeError,
"Can't open configuration '%s'" % configFile
428 for lineNum, fullLine
in enumerate (config):
429 fullLine = fullLine.strip()
431 line = GenObject._commentRE.sub (
'', fullLine)
433 if not GenObject._nonSpacesRE.search (line):
439 bracketMatch = GenObject._bracketRE.search (line)
442 section = bracketMatch.group(1)
443 words = GenObject._spacesRE.split( section )
445 raise RuntimeError,
"Don't understand line '%s'(%d)" \
446 % (fullLine, lineNum)
451 colonWords = GenObject._colonRE.split (objName)
452 if len (colonWords) > 3:
453 raise RuntimeError,
"Don't understand line '%s'(%d)" \
454 % (fullLine, lineNum)
455 if len (colonWords) == 1:
459 mode = modeEnum.define
461 if GenObject._singletonRE.match (word):
463 objsDict = GenObject._objsDict.\
464 setdefault (objName, {})
465 objsDict[
'_singleton'] =
True
469 print "I don't understand '%s' in section '%s' : %s" \
470 % (word, section, mode)
471 raise RuntimeError, \
472 "Config file parser error '%s'(%d)" \
473 % (fullLine, lineNum)
474 elif len (colonWords) == 2:
478 mode = modeEnum.ntuple
479 ntupleDict = GenObject._ntupleDict.\
480 setdefault (colonWords[0], {})
481 ntupleDict[
'_tree'] = colonWords[1]
486 mode = modeEnum.tofill
487 objName = colonWords [0]
488 tupleName = colonWords [1]
489 tofillName = colonWords [2]
490 ntupleDict = GenObject._ntupleDict.\
491 setdefault (tupleName, {})
492 ntupleDict[objName] = tofillName
495 labelMatch = GenObject._labelRE.search (word)
497 label = tuple( GenObject._commaRE.\
498 split( labelMatch.group (1) ) )
499 ntupleDict.setdefault (
'_label', {}).\
500 setdefault (tofillName,
504 shortcutMatch = GenObject._shortcutRE.search (word)
508 parseVariableTofill ( shortcutMatch.\
510 ntupleDict.setdefault (
'_shortcut', {}).\
511 setdefault (tofillName,
515 typeMatch = GenObject._typeRE.search (word)
519 _fixLostGreaterThans (typeMatch.group(1))
520 handle = Handle( handleString )
521 ntupleDict.setdefault (
'_handle', {}).\
522 setdefault (tofillName,
526 aliasMatch = GenObject._aliasRE.search (word)
528 ntupleDict.setdefault (
'_alias', {}).\
529 setdefault (tofillName,
538 print "I don't understand '%s' in section '%s' : %s" \
539 % (word, section, mode)
540 raise RuntimeError, \
541 "Config file parser error '%s'(%d)" \
542 % (fullLine, lineNum)
548 if modeEnum.none == mode:
550 print "I don't understand line '%s'." % fullLine
551 raise RuntimeError, \
552 "Config file parser error '%s'(%d)" \
553 % (fullLine, lineNum)
554 colonWords = GenObject._colonRE.split (line, 1)
555 if len (colonWords) < 2:
557 print "I don't understand line '%s'." % fullLine
558 raise RuntimeError, \
559 "Config file parser error '%s'(%d)" \
560 % (fullLine, lineNum)
561 varName = colonWords[0]
562 option = colonWords[1]
564 pieces = GenObject._spacesRE.split (option)
567 if modeEnum.define == mode:
572 if varName.startswith(
"-"):
574 if "-equiv" == varName.lower():
576 halves = part.split (
",")
577 if 2 != len (halves):
578 print "Problem with -equiv '%s' in '%s'" % \
580 raise RuntimeError, \
581 "Config file parser error '%s'(%d)" \
582 % (fullLine, lineNum)
584 halves[1] = float (halves[1])
585 if not halves[1] >= 0:
586 print "Problem with -equiv ",\
589 raise RuntimeError, \
590 "Config file parser error '%s'(%d)" \
591 % (fullLine, lineNum)
592 GenObject.setEquivExpression (section,
599 typeMatch = GenObject._typeRE.search (word)
601 GenObject.types.isValidKey (typeMatch.group(1)):
602 varType = typeMatch.group(1).lower()
603 optionsDict[
'varType'] = GenObject.types (varType)
605 defaultMatch = GenObject._defaultRE.search (word)
607 optionsDict[
'default'] = defaultMatch.group(1)
609 precMatch = GenObject._precRE.search (word)
611 optionsDict[
'prec'] = float (precMatch.group (1))
613 formMatch = GenObject._formRE.search (word)
615 form = GenObject._doublePercentRE.\
616 sub (
'%', formMatch.group (1))
617 optionsDict[
'form'] = form
621 print "I don't understand '%s' in section '%s'." \
623 raise RuntimeError, \
624 "Config file parser error '%s'(%d)" \
625 % (fullLine, lineNum)
626 GenObject.addObjectVariable (objName, varName, \
634 fillname, pieces = pieces[0], pieces[1:]
641 print "I don't understand '%s' in section '%s'." \
643 raise RuntimeError, \
644 "Config file parser error '%s'(%d)" \
645 % (fullLine, lineNum)
646 tofillDict = GenObject._tofillDict.\
647 setdefault (tupleName, {}).\
648 setdefault (objName, {})
649 partsList = GenObject.parseVariableTofill (fillname)
650 tofillDict[varName] = [partsList, optionsDict]
652 for objName
in GenObject._objsDict:
654 if not GenObject.isSingleton (objName):
655 GenObject.addObjectVariable (objName,
'index',
656 varType = GenObject.types.int,
661 def changeVariable (tupleName, objName, varName, fillname):
662 """Updates the definition used to go from a Root object to a
663 GenObject. 'tupleName' and 'objName' must already be defined."""
664 parts = GenObject._dotRE.split (fillname)
667 parenMatch = GenObject._parenRE.search (part)
668 mode = GenObject._objFunc.obj
671 part = parenMatch.group (1)
672 mode = GenObject._objFunc.func
674 GenObject._convertStringToParameters \
675 (parenMatch.group (2))
676 partsList.append( (part, mode, parens) )
677 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
682 def evaluateFunction (obj, partsList, debug=False):
683 """Evaluates function described in partsList on obj"""
684 for part
in partsList:
685 if debug: warn (part, spaces=15)
686 obj = getattr (obj, part[0])
687 if debug: warn (obj, spaces=15)
690 if GenObject._objFunc.func == part[1]:
693 if debug: warn (obj, spaces=18)
698 def _genObjectClone (objName, tupleName, obj, index = -1):
699 """Creates a GenObject copy of Root object"""
700 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
701 if objName ==
'runevent':
703 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
705 genObj = GenObject (objName)
707 if debug: warn (objName, spaces = 9)
708 for genVar, ntDict
in tofillObjDict.iteritems():
709 if debug: warn (genVar, spaces = 12)
711 partsList = ntDict[0]
713 obj = GenObject.evaluateFunction (origObj, partsList, debug)
714 if debug: warn (obj, spaces=12)
715 setattr (genObj, genVar, obj)
718 setattr (genObj,
'index', index)
723 def _rootObjectCopy (goSource, rootTarget):
724 """Copies information from goSourse into Root Object"""
725 objName = goSource._objName
726 for varName
in GenObject._objsDict [objName].
keys():
729 if varName.startswith (
"_"):
731 setattr( rootTarget, varName, goSource (varName) )
735 def _rootObjectClone (obj):
736 """Creates the approprite type of Root object and copies the
737 information into it from the GO object."""
738 objName = obj._objName
739 classObj = GenObject._rootClassDict.get (objName)
741 goName = GenObject.rootClassName (objName)
742 classObj = GenObject._rootClassDict[ goName ]
744 for varName
in GenObject._objsDict [objName].
keys():
745 setattr( rootObj, varName, obj (varName) )
750 def _rootDiffObject (obj1, obj2, rootObj = 0):
751 """Given to GOs, it will create and fill the corresponding
753 objName = obj1._objName
756 diffName = GenObject.rootDiffClassName( objName )
757 rootObj = GenObject._rootClassDict[diffName]()
758 for varName
in GenObject._objsDict [objName].
keys():
759 if varName.startswith (
"_"):
continue
760 goType = GenObject._objsDict[objName][varName][
'varType']
761 if not goType
in GenObject._basicSet:
764 setattr( rootObj, varName, obj1 (varName) )
765 if goType == GenObject.types.string:
767 otherName =
'other_' + varName
768 if obj1 (varName) != obj2 (varName):
770 setattr( rootObj, otherName, obj2 (varName) )
773 setattr( rootObj, otherName,
'' )
776 deltaName =
'delta_' + varName
777 setattr( rootObj, deltaName,
778 obj2 (varName) - obj1 (varName) )
783 def setupOutputTree (outputFile, treeName, treeDescription = "",
784 otherNtupleName =
""):
785 """Opens the output file, loads all of the necessary shared
786 object libraries, and returns the output file and tree. If
787 'otherNtupleName' is given, it will check and make sure that
788 only objects that are defined in it are written out."""
789 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
790 tree = ROOT.TTree (treeName, treeDescription)
791 GenObject._loadGoRootLibrary()
792 for objName
in sorted (GenObject._objsDict.keys()):
793 classname = GenObject.rootClassName (objName)
795 GenObject._rootClassDict[objName] = \
796 getattr (ROOT, classname)
797 if GenObject.isSingleton (objName):
799 obj = GenObject._rootObjectDict[objName] = rootObj()
800 tree.Branch (objName, classname, obj)
806 GenObject._rootObjectDict[objName] = \
807 ROOT.std.vector( rootObj )()
808 branchName = objName +
"s"
809 vecName =
"vector<%s>" % classname
810 tree.Branch( branchName, vecName, vec)
813 return rootfile, tree
817 def setupDiffOutputTree (outputFile, diffName, missingName,
818 diffDescription =
'', missingDescription =
''):
819 """Opens the diff output file, loads all of the necessary
820 shared object libraries, and returns the output file and tree.b"""
821 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
822 GenObject._loadGoRootLibrary()
824 diffTree = ROOT.TTree (diffName, diffDescription)
825 runEventObject = getattr (ROOT,
'go_runevent')()
826 diffTree.Branch (
'runevent',
'go_runevent', runEventObject)
827 GenObject._rootClassDict[
'runevent'] = runEventObject
828 for objName
in sorted (GenObject._objsDict.keys()):
829 if objName ==
'runevent':
continue
830 classname = GenObject.rootClassName (objName)
831 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
832 contName = GenObject.rootDiffContClassName (objName)
833 diffName = GenObject.rootDiffClassName (objName)
834 rootObj = GenObject._rootClassDict[contName] = \
835 getattr (ROOT, contName)
836 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
837 obj = GenObject._rootObjectDict[objName] = rootObj()
838 diffTree.Branch (objName, contName, obj)
840 missingTree = ROOT.TTree (missingName, missingDescription)
841 rootRunEventClass = getattr (ROOT,
'go_runevent')
842 firstOnly = GenObject._rootClassDict[
'firstOnly'] = \
843 ROOT.std.vector( rootRunEventClass ) ()
844 secondOnly = GenObject._rootClassDict[
'secondOnly'] = \
845 ROOT.std.vector( rootRunEventClass ) ()
846 missingTree.Branch (
'firstOnly',
'vector<go_runevent>', firstOnly)
847 missingTree.Branch (
'secondOnly',
'vector<go_runevent>', secondOnly)
848 return rootfile, diffTree, missingTree
852 def _fillRootObjects (event):
853 """Fills root objects from GenObject 'event'"""
854 for objName, obj
in sorted (event.iteritems()):
855 if GenObject.isSingleton (objName):
857 GenObject._rootObjectCopy (obj,
858 GenObject._rootObjectDict[objName])
861 vec = GenObject._rootObjectDict[objName]
864 vec.push_back( GenObject._rootObjectClone (goObj) )
868 def _fillRootDiffs (event1, event2):
869 """Fills root diff containers from two GenObject 'event's"""
874 def isSingleton (objName):
875 """Returns true if object is a singleton"""
876 return GenObject._objsDict[objName].
get(
'_singleton')
880 def loadEventFromTree (eventTree, eventIndex,
881 onlyRunEvent =
False):
882 """Loads event information from Root file (as interfaced by
883 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
884 'event' containing lists of objects or singleton object. If
885 'onlyRunEvent' is et to True, then only run and event number
886 is read in from the tree."""
887 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
888 tupleName = GenObject._kitchenSinkDict[eventTree][
'tupleName']
891 isChain = eventTree.__class__.__name__ ==
'TChain'
894 eventTree.GetEntry (eventIndex)
897 eventTree.to(eventIndex)
898 tofillDict = GenObject._tofillDict.get (tupleName)
899 ntupleDict = GenObject._ntupleDict.get (tupleName)
901 print "Don't know how to fill from '%s' ntuple." % tupleName
903 eventBranchName = ntupleDict[
'runevent']
904 for objName
in tofillDict:
905 branchName = ntupleDict[objName]
906 if onlyRunEvent
and branchName != eventBranchName:
915 objects = getattr (eventTree, branchName)
918 shortcut = ntupleDict.get(
'_shortcut', {}).
get(branchName)
920 objects = GenObject.evaluateFunction (eventTree, shortcut)
923 handle = ntupleDict.get(
'_handle', {}).
get(branchName)
924 label = ntupleDict.get(
'_label' , {}).
get(branchName)
925 if not handle
or not label:
926 raise RuntimeError,
"Missing handle or label for '%s'"\
928 if not eventTree.getByLabel (label, handle):
929 raise RuntimeError,
"not able to get %s for %s" \
930 % (label, branchName)
931 objects = handle.product()
933 if GenObject.isSingleton (objName):
934 event[objName] = GenObject.\
935 _genObjectClone (objName,
940 if debug: warn (objName, spaces = 3)
942 for index, obj
in enumerate (objects):
943 event[objName].
append( GenObject.\
944 _genObjectClone (objName,
957 def printEvent (event):
958 """Prints out event dictionary. Mostly for debugging"""
960 for objName, obj
in sorted (event.iteritems()):
963 if GenObject.isSingleton (objName):
964 print "%s: %s" % (objName, obj)
966 for objName, obj
in sorted (event.iteritems()):
969 if not GenObject.isSingleton (objName):
971 print "%s:" % objName
978 def setAliases (eventTree, tupleName):
979 """runs SetAlias on all saved aliases"""
980 aliases = GenObject._ntupleDict[tupleName].
get(
'_alias', {})
981 for name, alias
in aliases.iteritems():
982 eventTree.SetAlias (name, alias)
986 def changeAlias (tupleName, name, alias):
987 """Updates an alias for an object for a given tuple"""
988 aliasDict = GenObject._ntupleDict[tupleName][
'_alias']
989 if not aliasDict.has_key (name):
990 raise RuntimeError,
"unknown name '%s' in tuple '%s'" % \
992 aliasDict[name] = alias
996 def changeLabel (tupleName, objectName, label):
997 """Updates an label for an object for a given tuple"""
998 labelDict = GenObject._ntupleDict[tupleName][
'_label']
999 if not labelDict.has_key (objectName):
1000 raise RuntimeError,
"unknown name '%s' in tuple '%s'" % \
1001 (objectName, tupleName)
1002 label = tuple( GenObject._commaRE.split( label ) )
1003 labelDict[objectName] = label
1007 def prepareTuple (tupleName, files, numEventsWanted = 0):
1008 """Given the tuple name and list of files, returns either a
1009 TChain or EventTree, and number of entries"""
1010 if "GenObject" == tupleName:
1011 GenObject.prepareToLoadGenObject()
1012 if not isinstance (files, list):
1015 ntupleDict = GenObject._ntupleDict[tupleName]
1016 treeName = ntupleDict[
"_tree"]
1017 if ntupleDict.get(
'_useChain'):
1018 chain = ROOT.TChain (treeName)
1019 for filename
in files:
1020 chain.AddFile (filename)
1021 numEntries = chain.GetEntries()
1024 chain = Events (files, forceEvent=
True)
1025 numEntries = chain.size()
1026 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1027 if numEventsWanted
and numEventsWanted < numEntries:
1028 numEntries = numEventsWanted
1029 chainDict[
'numEntries'] = numEntries
1030 chainDict[
'tupleName' ] = tupleName
1035 def getRunEventEntryDict (chain, tupleName, numEntries):
1036 """Returns a dictionary of run, event tuples to entryIndicies"""
1038 for entryIndex
in xrange (numEntries):
1039 event = GenObject.loadEventFromTree (chain,
1041 onlyRunEvent =
True)
1042 runevent = event[
'runevent']
1043 reeDict[ GenObject._re2key (runevent) ] = entryIndex
1050 def _re2key (runevent):
1051 """Given a GO 'runevent' object, returns a sortable key"""
1054 if not GenObject._runEventListDone:
1055 GenObject._runEventListDone =
True
1056 ignoreSet = set( [
'run',
'event'] )
1057 for varName
in sorted (runevent.__dict__.keys()):
1058 if varName.startswith (
'_')
or varName
in ignoreSet:
1060 form = runevent.getVariableProperty (varName,
"form")
1063 GenObject._runEventList.append ((varName, form))
1064 key =
'run:%d event:%d' % (runevent.run, runevent.event)
1065 for items
in GenObject._runEventList:
1067 form =
' %s:%s' % (varName, items[1])
1068 key += form % runevent.getVariableProperty (varName)
1073 def _key2re (key, runevent=None):
1074 """Given a key, returns a GO 'runevent' object"""
1076 runevent = GenObject (
'runevent')
1077 words = GenObject._spacesRE.split (key)
1079 match = GenObject._singleColonRE.search (word)
1084 runevent.__setattr__ (match.group(1), int( match.group(2) ))
1089 def compareRunEventDicts (firstDict, secondDict):
1090 """Compares the keys of the two dicts and returns three sets:
1091 the overlap, first but not second, and second but not first."""
1096 for key
in firstDict.keys():
1097 if secondDict.has_key (key):
1103 for key
in secondDict.keys():
1104 if not firstDict.has_key (key):
1105 secondOnly.add (key)
1107 return overlap, firstOnly, secondOnly
1111 def pairEquivalentObjects (vec1, vec2):
1112 """Finds the equivalent objects in the two vectors"""
1113 len1, len2 = len (vec1), len (vec2)
1114 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1115 if not len1
or not len2:
1118 noMatch1Set = set( xrange(len1) )
1120 noMatch1Set = set ()
1122 noMatch2Set = set( xrange(len2) )
1124 noMatch2Set = set ()
1125 if debug: warn (
"Nothing found", sapces=6)
1126 return set(), noMatch1Set, noMatch2Set
1127 objName = vec1[0]._objName
1128 equivList = GenObject._equivDict[objName]
1132 if GenObject._kitchenSinkDict.get (
'strictPairing')
or \
1133 equivList == [(
'index', 0)]:
1135 matchedSet = set (zip ( range( min (len1, len2) ),
1136 range( min (len1, len2) ) ) )
1140 noMatch1Set = set (range(len2, len1 + 1))
1145 noMatch2Set = set (range(len1, len2 + 1))
1148 return matchedSet, noMatch1Set, noMatch2Set
1163 for index1
in xrange (len1):
1166 for index2
in xrange (len2):
1170 for equiv
in equivList:
1171 var, precision = equiv[0], equiv[1]
1176 value = abs (val1 - val2) / precision
1185 objList.append( (total, index2) )
1187 firstDict[index1] = objList
1190 for index2
in xrange (len2):
1193 for index1
in xrange (len1):
1197 for equiv
in equivList:
1198 var, precision = equiv[0], equiv[1]
1203 value = abs (val2 - val1) / precision
1212 objList.append( (total, index1) )
1214 secondDict[index2] = objList
1219 firstDictKeys = sorted (firstDict.keys())
1220 for index1
in firstDictKeys:
1221 list1 = firstDict[index1]
1225 noMatch1Set.add (index1)
1231 list2 = secondDict.get (index2, [])
1232 if len(list2)
and list2[0][1] == index1:
1233 matchedSet.add( (index1, index2) )
1235 del firstDict[index1]
1236 del secondDict[index2]
1239 noMatch1Set.add (index1)
1240 noMatch2Set = set( secondDict.keys() )
1241 return matchedSet, noMatch1Set, noMatch2Set
1245 def compareTwoItems (item1, item2):
1246 """Compares all of the variables making sure they are the same
1247 on the two objects."""
1248 objName = item1._objName
1250 relative = GenObject._kitchenSinkDict.get (
'relative',
False)
1251 for varName
in GenObject._objsDict[objName].
keys():
1252 prec = item1.getVariableProperty (varName,
'prec')
1256 val1 = item1(varName)
1257 val2 = item2(varName)
1258 numerator = 2 * abs (val1 - val2)
1259 denominator =
abs(val1) +
abs(val2)
1264 value = numerator / denominator
1267 problems[varName] = value
1269 value =
abs( item1(varName) - item2(varName) )
1272 problems[varName] = value
1275 if item1(varName) != item2(varName):
1277 val1, val2 = item1(varName), item2(varName)
1279 val1, val2 = val2, val1
1280 problems[varName] =
"%s != %s" % (val1, val2)
1286 def blurEvent (event, value, where = ""):
1287 """For debugging purposes only. Will deliberately change
1288 values of first tree to verify that script is correctly
1289 finding problems."""
1290 for objName
in sorted (event.keys()):
1291 if "runevent" == objName:
1294 if GenObject.isSingleton (objName):
1298 for obj
in event[objName]:
1300 for varName
in GenObject._objsDict[objName].
keys():
1301 if isinstance (obj.__dict__[varName], str):
1304 randNumber = random.random()
1306 if randNumber < GenObject._kitchenSinkDict[
'blurRate']:
1307 print " %s: changing '%s' of '%s:%d'" \
1308 % (where, varName, obj._objName, count)
1311 obj.__dict__[varName] += value
1315 def compareTwoTrees (chain1, chain2, **kwargs):
1316 """Given all of the necessary information, this routine will
1317 go through and compare two trees making sure they are
1318 'identical' within requested precision. If 'diffOutputName'
1319 is passed in, a root file with a diffTree and missingTree will
1321 print "Comparing Two Trees"
1322 diffOutputName = kwargs.get (
'diffOutputName')
1323 tupleName1 = GenObject._kitchenSinkDict[chain1][
'tupleName']
1324 numEntries1 = GenObject._kitchenSinkDict[chain1][
'numEntries']
1325 tupleName2 = GenObject._kitchenSinkDict[chain2][
'tupleName']
1326 numEntries2 = GenObject._kitchenSinkDict[chain2][
'numEntries']
1327 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1328 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1329 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1330 overlap, firstOnly, secondOnly = \
1331 GenObject.compareRunEventDicts (ree1, ree2)
1333 rootfile, diffTree, missingTree = \
1334 GenObject.setupDiffOutputTree (diffOutputName,
1338 vec = GenObject._rootClassDict[
'firstOnly']
1339 for key
in firstOnly:
1340 runevent = GenObject._key2re (key)
1341 vec.push_back( GenObject._rootObjectClone( runevent ) )
1343 vec = GenObject._rootClassDict[
'secondOnly']
1344 for key
in secondOnly:
1345 runevent = GenObject._key2re (key)
1346 vec.push_back( GenObject._rootObjectClone( runevent ) )
1350 resultsDict.setdefault (
'_runevent', {})[
'firstOnly'] = \
1353 resultsDict.setdefault (
'_runevent', {})[
'secondOnly'] = \
1355 resultsDict[
'eventsCompared'] = len (overlap)
1356 for reTuple
in sorted(overlap):
1360 GenObject._key2re (reTuple,
1361 GenObject._rootClassDict[
'runevent'])
1362 if debug: warn (
'event1', blankLines = 3)
1363 event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1364 if debug: warn (
'event2', blankLines = 3)
1365 event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1366 if GenObject._kitchenSinkDict.get(
'printEvent'):
1368 GenObject.printEvent (event1)
1370 GenObject.printEvent (event2)
1371 if GenObject._kitchenSinkDict.get(
'blur'):
1373 GenObject.blurEvent (event1,
1374 GenObject._kitchenSinkDict[
'blur'],
1376 for objName
in sorted (event1.keys()):
1377 if "runevent" == objName:
1380 if not GenObject._equivDict.get (objName):
1384 if GenObject.isSingleton (objName):
1391 rootObj = GenObject._rootObjectDict[objName]
1393 vec1 = event1[objName]
1394 vec2 = event2[objName]
1395 matchedSet, noMatch1Set, noMatch2Set = \
1396 GenObject.pairEquivalentObjects (vec1, vec2)
1397 if noMatch1Set
or noMatch2Set:
1400 count1 = len (noMatch1Set)
1401 count2 = len (noMatch2Set)
1402 key = (count1, count2)
1403 countDict = resultsDict.\
1404 setdefault (objName, {}).\
1405 setdefault (
'_missing', {})
1406 if countDict.has_key (key):
1413 for index
in sorted(
list(noMatch1Set)):
1414 goObj = vec1 [index]
1415 rootObj.firstOnly.push_back ( GenObject.\
1419 for index
in sorted(
list(noMatch2Set)):
1420 goObj = vec2 [index]
1421 rootObj.secondOnly.push_back ( GenObject.\
1426 for pair
in sorted(
list(matchedSet)):
1428 rootDiffObj = GenObject._rootDiffObject \
1429 ( vec1[ pair[1 - 1] ],
1430 vec2[ pair[2 - 1] ] )
1431 rootObj.diff.push_back ( rootDiffObj )
1432 problems = GenObject.\
1433 compareTwoItems (vec1[ pair[1 - 1] ],
1434 vec2[ pair[2 - 1] ])
1437 for varName
in problems.keys():
1438 countDict = resultsDict.\
1439 setdefault (objName, {}).\
1440 setdefault (
'_var', {})
1441 if countDict.has_key (varName):
1442 countDict[varName] += 1
1444 countDict[varName] = 1
1445 key =
'count_%s' % objName
1446 if not resultsDict.has_key (key):
1447 resultsDict[key] = 0
1448 resultsDict[key] += len (matchedSet)
1466 def saveTupleAs (chain, rootFile):
1467 """Saves a chain as a GO tree"""
1469 rootfile, tree = GenObject.setupOutputTree (rootFile,
"goTree")
1470 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1471 for entryIndex
in xrange (numEntries):
1472 event = GenObject.loadEventFromTree (chain, entryIndex)
1473 if GenObject._kitchenSinkDict.get(
'blur'):
1474 where =
"run %d event %d" % (event[
'runevent'].run,
1475 event[
'runevent'].event)
1476 if random.random() < GenObject._kitchenSinkDict.get(
'blur'):
1478 print "Dropping", where
1480 GenObject.blurEvent (event,
1481 GenObject._kitchenSinkDict[
'blur'],
1484 if GenObject._kitchenSinkDict.get(
'printEvent'):
1485 GenObject.printEvent (event)
1486 GenObject._fillRootObjects (event)
1493 def setGlobalFlag (key, value):
1494 """Sets a global flag in _kitchenSinkDict"""
1495 GenObject._kitchenSinkDict [key] = value
1499 def printTuple (chain):
1500 """Prints out all events to stdout"""
1501 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1502 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1503 if debug: warn (numEntries)
1504 for entryIndex
in xrange (numEntries):
1505 if debug: warn (entryIndex, spaces=3)
1506 event = GenObject.loadEventFromTree (chain, entryIndex)
1507 GenObject.printEvent (event)
1508 if debug:
warn(spaces=3)
1511 def _convertStringToParameters (string):
1512 """Convert comma-separated string into a python list of
1513 parameters. Currently only understands strings, floats, and
1516 words = GenObject._commaRE.split (string)
1520 match = GenObject._singleQuoteRE.search (word)
1522 retval.append (match.group (1))
1524 match = GenObject._doubleQuoteRE.search (word)
1526 retval.append (match.group (1))
1541 raise RuntimeError,
"Unknown parameter '%s'." % word
1551 """Class initializer"""
1552 if not GenObject._objsDict.has_key (objName):
1555 print "Error: GenObject does not know about object '%s'." % objName
1556 raise RuntimeError,
"Failed to create GenObject object."
1557 self._localObjsDict = GenObject._objsDict [objName]
1558 self._objName = objName;
1559 for key, varDict
in self._localObjsDict.iteritems():
1562 if key.startswith (
"_"):
1564 self.setValue (key, varDict[
'default'])
1568 """Wrapper for __setattr___"""
1569 self.__setattr__ (name, value)
1572 def getVariableProperty (self, var, key):
1573 """ Returns property assoicated with 'key' for variable 'var'
1574 of object of the same type as 'self'. Returns 'None' if 'var'
1575 or 'key' is not defined."""
1576 return GenObject._objsDict.get (self._objName,
1577 {}).get (var, {}). get (key,
None)
1580 def __setattr__ (self, name, value):
1581 """Controls setting of values."""
1582 if name.startswith (
"_"):
1584 object.__setattr__ (self, name, value)
1589 if not self._localObjsDict.has_key (name):
1591 print "Warning: '%s' for class '%s' not setup. Skipping." % \
1592 (name, self._objName)
1594 varType = self.getVariableProperty (name,
'varType')
1596 if GenObject.types.int == varType:
1603 value = int( float( value ) )
1604 elif GenObject.types.long == varType:
1608 value = long (value)
1611 value = long( float( value ) )
1612 elif GenObject.types.float == varType:
1614 value = float (value)
1615 elif GenObject.types.string == varType:
1619 object.__setattr__ (self, name, value)
1622 def __call__ (self, key):
1623 """Makes object callable"""
1624 return object.__getattribute__ (self, key)
1628 """String representation"""
1630 for varName, value
in sorted (self.__dict__.iteritems()):
1631 if varName.startswith (
'_'):
continue
1632 form = self.getVariableProperty (varName,
"form")
1634 format =
"%s:%s " % (varName, form)
1635 retval = retval + format % value
1637 retval = retval +
"%s:%s " % (varName, value)
bool setValue(Container &, const reco::JetBaseRef &, const JetExtendedData &)
associate jet with value. Returns false and associate nothing if jet is already associated ...
Abs< T >::type abs(const T &t)
T get(const Candidate &c)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run