6 from FWCore.Utilities.Enumerate
import Enumerate
7 from DataFormats.FWLite
import Events, Handle
17 from functools
import reduce
21 filenameRE = re.compile (
r'.+/Validation/Tools/')
30 def warn (*args, **kwargs):
31 """print out warning with line number and rest of arguments""" 33 frame = inspect.stack()[1]
37 filename = filenameRE.sub (
'', filename)
39 blankLines = kwargs.get(
'blankLines', 0)
41 print '\n' * blankLines
42 spaces = kwargs.get(
'spaces', 0)
46 print "%s (%s): " % (filename, lineNum),
51 print "%s (%s):" % (filename, lineNum)
55 """Infrastruture to define general objects and their attributes.""" 61 types = Enumerate (
"float int long string",
"type")
62 _objFunc = Enumerate (
"obj func",
"of")
63 _cppType = dict ( {types.float :
'double',
66 types.string :
'std::string' } )
67 _basicSet = set( [types.float, types.int, types.float,
69 _defaultValue = dict ( {types.float : 0.,
72 types.string :
'""' } )
83 _runEventListDone =
False 84 uselessReturnCode = 1 << 7
89 _nonSpacesRE = re.compile (
r'\S')
90 _colonRE = re.compile (
r'\s*:\s*')
91 _singleColonRE = re.compile (
r'(.+?):(.+)')
92 _doubleColonRE = re.compile (
r'(.+?):(.+?):(.+)')
93 _doublePercentRE = re.compile (
r'%%')
94 _parenRE = re.compile (
r'(.+)\((.*)\)')
95 _spacesRE = re.compile (
r'\s+')
96 _dotRE = re.compile (
r'\s*\.\s*')
97 _commaRE = re.compile (
r'\s*,\s*')
98 _singleQuoteRE = re.compile (
r'^\'(.+)\'$')
99 _doubleQuoteRE = re.compile (
r'^\"(.+)\"$')
100 _bracketRE = re.compile (
r'\[\s*(.+?)\s*\]')
101 _commentRE = re.compile (
r'#.+$')
102 _aliasRE = re.compile (
r'alias=(\S+)', re.IGNORECASE)
103 _labelRE = re.compile (
r'label=(\S+)', re.IGNORECASE)
104 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
105 _singletonRE = re.compile (
r'singleton', re.IGNORECASE)
106 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
107 _defaultRE = re.compile (
r'default=(\S+)', re.IGNORECASE)
108 _shortcutRE = re.compile (
r'shortcut=(\S+)', re.IGNORECASE)
109 _precRE = re.compile (
r'prec=(\S+)', re.IGNORECASE)
110 _formRE = re.compile (
r'form=(\S+)', re.IGNORECASE)
111 _nonAlphaRE = re.compile (
r'\W')
112 _percentAsciiRE = re.compile (
r'%([0-9a-fA-F]{2})')
120 return "%%%02x" % ord (match.group(0))
124 return chr(
int( match.group(1), 16 ) )
128 """Use a web like encoding of characters that are non-alphanumeric""" 129 return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
133 """Decode lines encoded with encodeNonAlphanumerics()""" 134 return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
139 """ User passes in in object and variable names.""" 140 if 'varType' not in optionsDict:
141 optionsDict[
'varType'] = GenObject.types.float
142 varType = optionsDict[
'varType']
143 if not GenObject.types.isValidValue (varType):
144 print "Type '%s' not valid. Skipping (%s, %s, %s)." % \
145 (varType, obj, var, varType)
147 if 'default' not in optionsDict:
148 optionsDict[
'default'] = GenObject._defaultValue[varType]
149 if obj.startswith (
"_")
or var.startswith (
"_"):
150 print "Skipping (%s, %s, %s) because of leading underscore." % \
153 GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
158 """Returns property assoicated with 'key' for variable 'var' 159 of object 'obj'. Returns 'None' if any of the above are not 161 return GenObject._objsDict.get (obj, {}).get (var, {}). get (key,
None)
166 """Adds an equivalence constraint. Must have at least one to 167 compare GO objects.""" 168 if obj.startswith (
"_"):
169 print "Skipping (%s, %s) because of leading underscore." % \
172 GenObject._equivDict.setdefault (obj,[]).append ( (variable,
178 """Meant for debugging, but ok if called by user""" 180 pprint.pprint (GenObject._objsDict, indent=4)
182 pprint.pprint (GenObject._equivDict, indent=4)
184 pprint.pprint (GenObject._ntupleDict, indent=4)
186 pprint.pprint (GenObject._tofillDict, indent=4)
187 print "kitchenSink: " 188 pprint.pprint (GenObject._kitchenSinkDict, indent=4)
189 print "rootClassDict" 190 pprint.pprint (GenObject._rootClassDict, indent=4)
195 """Returns a string of hex value of a checksum of input 197 return hex( reduce(
lambda x, y : x + y,
map(ord, str) ) )[2:]
202 """Returns the name of the equivalent Root object""" 203 return "go_" + objName
208 """Returns the name of the equivalent Root diff object""" 209 return "goDiff_" + objName
214 """Returns the name of the equivalent Root diff container 216 return "goDiffCont_" + objName
221 """Returns a string with the class header for a class 223 retval =
"\nclass %s\n{\n public:\n" % className
224 retval +=
" typedef std::vector< %s > Collection;\n\n" % className
227 retval +=
" %s()" % className
229 retval +=
" %s() :\n" % className
235 """Returns a stringg with the end of a class definition""" 236 retval =
"\n {}\n" + datadec +
"};\n" 237 retval +=
"#ifdef __MAKECINT__\n#pragma link C++ class " + \
238 "vector< %s >+;\n#endif\n\n" % className
244 """Returns a string containing the '.C' file necessary to 245 generate a shared object library with dictionary.""" 246 if objName
not in GenObject._objsDict:
248 print "Error: GenObject does not know about object '%s'." % objName
249 raise RuntimeError(
"Failed to create C++ class.")
250 className = GenObject.rootClassName (objName)
251 diffName = GenObject.rootDiffClassName (objName)
252 contName = GenObject.rootDiffContClassName (objName)
253 goClass = GenObject._setupClassHeader (className)
254 diffClass = GenObject._setupClassHeader (diffName)
255 contClass = GenObject._setupClassHeader (contName, noColon =
True)
256 goDataDec = diffDataDec = contDataDec =
"\n // data members\n" 258 for key
in sorted( GenObject._objsDict[objName].
keys() ):
259 if key.startswith (
"_"):
continue 260 varTypeList = GenObject._objsDict[objName][key]
261 cppType = GenObject._cppType[ varTypeList[
'varType'] ]
262 default = varTypeList[
'default']
268 goClass +=
" %s (%s)" % (key, default)
269 goDataDec +=
" %s %s;\n" % (cppType, key)
271 goType = varTypeList[
'varType']
272 if goType
in GenObject._basicSet:
274 diffClass +=
" %s (%s),\n" % (key, default)
275 diffDataDec +=
" %s %s;\n" % (cppType, key)
276 if goType == GenObject.types.string:
278 otherKey =
'other_' + key
279 diffClass +=
" %s (%s)" % (otherKey, default)
280 diffDataDec +=
" %s %s;\n" % (cppType, otherKey)
283 deltaKey =
'delta_' + key
284 diffClass +=
" %s (%s)" % (deltaKey, default)
285 diffDataDec +=
" %s %s;\n" % (cppType, deltaKey)
287 raise RuntimeError(
"Shouldn't be here yet.")
290 if GenObject.isSingleton (objName):
292 contDataDec +=
" %s diff;\n" % diffName
293 contDataDec +=
" void setDiff (const %s &rhs)" % diffName + \
297 contDataDec +=
" void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n" 298 contDataDec +=
" %s::Collection firstOnly;\n" % className
299 contDataDec +=
" %s::Collection secondOnly;\n" % className
300 contDataDec +=
" %s::Collection diff;\n" % diffName
303 goClass += GenObject._finishClassHeader (className, goDataDec)
304 diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
305 contClass += GenObject._finishClassHeader (contName, contDataDec)
306 if objName ==
'runevent':
310 return goClass + diffClass + contClass
315 """Loads Root shared object library associated with all 316 defined GenObjects. Will create library if necessary.""" 317 print "Loading GO Root Library" 318 key =
"_loadedLibrary" 319 if GenObject._kitchenSinkDict.get (key):
323 GenObject._kitchenSinkDict[key] =
True 325 sourceCode =
"#include <string>\n#include <vector>\n" \
326 +
"using namespace std;\n" 327 for objClassName
in sorted( GenObject._objsDict.keys() ):
328 sourceCode += GenObject._createCppClass (objClassName)
329 GenObjectRootLibDir =
"genobjectrootlibs" 330 if not os.path.exists (GenObjectRootLibDir):
331 os.mkdir (GenObjectRootLibDir)
332 key = GenObject.checksum( sourceCode )
333 basename =
"%s_%s" % (
"GenObject", key)
334 SO =
"%s/%s_C" % (GenObjectRootLibDir, basename)
335 linuxSO =
"%s.so" % SO
336 windowsSO =
"%s.dll" % SO
337 if not os.path.exists (linuxSO)
and not os.path.exists (windowsSO):
339 filename =
"%s/%s.C" % (GenObjectRootLibDir, basename)
340 if not os.path.exists (filename):
341 print "creating .C file" 342 target = open (filename,
"w")
343 target.write (sourceCode)
346 print "%s exists" % filename
349 ROOT.gSystem.CompileMacro (filename,
"k")
351 print "loading %s" % SO
352 ROOT.gSystem.Load(SO)
358 """Makes sure that I know how to read root files I made myself""" 359 genObject =
"GenObject" 360 ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
361 ntupleDict[
'_useChain'] =
True 362 ntupleDict[
'_tree'] =
"goTree" 363 for objName
in GenObject._objsDict.keys():
364 rootObjName = GenObject.rootClassName (objName)
365 if GenObject.isSingleton (objName):
366 ntupleDict[objName] = objName
368 ntupleDict[objName] = objName +
"s" 369 tofillDict = GenObject._tofillDict.\
370 setdefault (genObject, {}).\
371 setdefault (objName, {})
372 for varName
in GenObject._objsDict [objName].
keys():
375 if varName.startswith (
"_"):
377 tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
383 """Makes all necessary preparations to load root files created 385 GenObject._tofillGenObject()
386 GenObject._loadGoRootLibrary()
391 """Returns tofill tuple made from string""" 392 parts = GenObject._dotRE.split (fillname)
395 parenMatch = GenObject._parenRE.search (part)
396 mode = GenObject._objFunc.obj
399 part = parenMatch.group (1)
400 mode = GenObject._objFunc.func
402 GenObject._convertStringToParameters \
403 (parenMatch.group (2))
404 partsList.append( (part, mode, parens) )
409 offset = handle.count (
'<') - handle.count(
'>')
413 print "Huh? Too few '<' for each '>' in handle '%'" % handle
415 return handle +
' >' * offset
420 """Loads configuration file""" 424 modeEnum = Enumerate (
"none define tofill ntuple",
"mode")
427 config = open (configFile,
'r') 429 raise RuntimeError(
"Can't open configuration '%s'" % configFile)
430 for lineNum, fullLine
in enumerate (config):
431 fullLine = fullLine.strip()
433 line = GenObject._commentRE.sub (
'', fullLine)
435 if not GenObject._nonSpacesRE.search (line):
441 bracketMatch = GenObject._bracketRE.search (line)
444 section = bracketMatch.group(1)
445 words = GenObject._spacesRE.split( section )
447 raise RuntimeError(
"Don't understand line '%s'(%d)" \
448 % (fullLine, lineNum))
453 colonWords = GenObject._colonRE.split (objName)
454 if len (colonWords) > 3:
455 raise RuntimeError(
"Don't understand line '%s'(%d)" \
456 % (fullLine, lineNum))
457 if len (colonWords) == 1:
461 mode = modeEnum.define
463 if GenObject._singletonRE.match (word):
465 objsDict = GenObject._objsDict.\
466 setdefault (objName, {})
467 objsDict[
'_singleton'] =
True 471 print "I don't understand '%s' in section '%s' : %s" \
472 % (word, section, mode)
473 raise RuntimeError(
"Config file parser error '%s'(%d)" \
474 % (fullLine, lineNum))
475 elif len (colonWords) == 2:
479 mode = modeEnum.ntuple
480 ntupleDict = GenObject._ntupleDict.\
481 setdefault (colonWords[0], {})
482 ntupleDict[
'_tree'] = colonWords[1]
487 mode = modeEnum.tofill
488 objName = colonWords [0]
489 tupleName = colonWords [1]
490 tofillName = colonWords [2]
491 ntupleDict = GenObject._ntupleDict.\
492 setdefault (tupleName, {})
493 ntupleDict[objName] = tofillName
496 labelMatch = GenObject._labelRE.search (word)
498 label = tuple( GenObject._commaRE.\
499 split( labelMatch.group (1) ) )
500 ntupleDict.setdefault (
'_label', {}).\
501 setdefault (tofillName,
505 shortcutMatch = GenObject._shortcutRE.search (word)
509 parseVariableTofill ( shortcutMatch.\
511 ntupleDict.setdefault (
'_shortcut', {}).\
512 setdefault (tofillName,
516 typeMatch = GenObject._typeRE.search (word)
520 _fixLostGreaterThans (typeMatch.group(1))
521 handle = Handle( handleString )
522 ntupleDict.setdefault (
'_handle', {}).\
523 setdefault (tofillName,
527 aliasMatch = GenObject._aliasRE.search (word)
529 ntupleDict.setdefault (
'_alias', {}).\
530 setdefault (tofillName,
539 print "I don't understand '%s' in section '%s' : %s" \
540 % (word, section, mode)
541 raise RuntimeError(
"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(
"Config file parser error '%s'(%d)" \
552 % (fullLine, lineNum))
553 colonWords = GenObject._colonRE.split (line, 1)
554 if len (colonWords) < 2:
556 print "I don't understand line '%s'." % fullLine
557 raise RuntimeError(
"Config file parser error '%s'(%d)" \
558 % (fullLine, lineNum))
559 varName = colonWords[0]
560 option = colonWords[1]
562 pieces = GenObject._spacesRE.split (option)
565 if modeEnum.define == mode:
570 if varName.startswith(
"-"):
572 if "-equiv" == varName.lower():
574 halves = part.split (
",")
575 if 2 != len (halves):
576 print "Problem with -equiv '%s' in '%s'" % \
578 raise RuntimeError(
"Config file parser error '%s'(%d)" \
579 % (fullLine, lineNum))
581 halves[1] = float (halves[1])
582 if not halves[1] >= 0:
583 print "Problem with -equiv ",\
586 raise RuntimeError(
"Config file parser error '%s'(%d)" \
587 % (fullLine, lineNum))
588 GenObject.setEquivExpression (section,
595 typeMatch = GenObject._typeRE.search (word)
597 GenObject.types.isValidKey (typeMatch.group(1)):
598 varType = typeMatch.group(1).lower()
599 optionsDict[
'varType'] = GenObject.types (varType)
601 defaultMatch = GenObject._defaultRE.search (word)
603 optionsDict[
'default'] = defaultMatch.group(1)
605 precMatch = GenObject._precRE.search (word)
607 optionsDict[
'prec'] = float (precMatch.group (1))
609 formMatch = GenObject._formRE.search (word)
611 form = GenObject._doublePercentRE.\
612 sub (
'%', formMatch.group (1))
613 optionsDict[
'form'] = form
617 print "I don't understand '%s' in section '%s'." \
619 raise RuntimeError(
"Config file parser error '%s'(%d)" \
620 % (fullLine, lineNum))
621 GenObject.addObjectVariable (objName, varName, \
629 fillname, pieces = pieces[0], pieces[1:]
636 print "I don't understand '%s' in section '%s'." \
638 raise RuntimeError(
"Config file parser error '%s'(%d)" \
639 % (fullLine, lineNum))
640 tofillDict = GenObject._tofillDict.\
641 setdefault (tupleName, {}).\
642 setdefault (objName, {})
643 partsList = GenObject.parseVariableTofill (fillname)
644 tofillDict[varName] = [partsList, optionsDict]
646 for objName
in GenObject._objsDict:
648 if not GenObject.isSingleton (objName):
649 GenObject.addObjectVariable (objName,
'index',
650 varType = GenObject.types.int,
656 """Updates the definition used to go from a Root object to a 657 GenObject. 'tupleName' and 'objName' must already be defined.""" 658 parts = GenObject._dotRE.split (fillname)
661 parenMatch = GenObject._parenRE.search (part)
662 mode = GenObject._objFunc.obj
665 part = parenMatch.group (1)
666 mode = GenObject._objFunc.func
668 GenObject._convertStringToParameters \
669 (parenMatch.group (2))
670 partsList.append( (part, mode, parens) )
671 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
677 """Evaluates function described in partsList on obj""" 678 for part
in partsList:
679 if debug: warn (part, spaces=15)
680 obj = getattr (obj, part[0])
681 if debug: warn (obj, spaces=15)
684 if GenObject._objFunc.func == part[1]:
687 if debug: warn (obj, spaces=18)
693 """Creates a GenObject copy of Root object""" 694 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
695 if objName ==
'runevent':
697 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
699 genObj = GenObject (objName)
701 if debug: warn (objName, spaces = 9)
702 for genVar, ntDict
in six.iteritems(tofillObjDict):
703 if debug: warn (genVar, spaces = 12)
705 partsList = ntDict[0]
707 obj = GenObject.evaluateFunction (origObj, partsList, debug)
708 if debug: warn (obj, spaces=12)
709 setattr (genObj, genVar, obj)
712 setattr (genObj,
'index', index)
718 """Copies information from goSourse into Root Object""" 719 objName = goSource._objName
720 for varName
in GenObject._objsDict [objName].
keys():
723 if varName.startswith (
"_"):
725 setattr( rootTarget, varName, goSource (varName) )
730 """Creates the approprite type of Root object and copies the 731 information into it from the GO object.""" 732 objName = obj._objName
733 classObj = GenObject._rootClassDict.get (objName)
735 goName = GenObject.rootClassName (objName)
736 classObj = GenObject._rootClassDict[ goName ]
738 for varName
in GenObject._objsDict [objName].
keys():
739 setattr( rootObj, varName, obj (varName) )
745 """Given to GOs, it will create and fill the corresponding 747 objName = obj1._objName
750 diffName = GenObject.rootDiffClassName( objName )
751 rootObj = GenObject._rootClassDict[diffName]()
752 for varName
in GenObject._objsDict [objName].
keys():
753 if varName.startswith (
"_"):
continue 754 goType = GenObject._objsDict[objName][varName][
'varType']
755 if not goType
in GenObject._basicSet:
758 setattr( rootObj, varName, obj1 (varName) )
759 if goType == GenObject.types.string:
761 otherName =
'other_' + varName
762 if obj1 (varName) != obj2 (varName):
764 setattr( rootObj, otherName, obj2 (varName) )
767 setattr( rootObj, otherName,
'' )
770 deltaName =
'delta_' + varName
771 setattr( rootObj, deltaName,
772 obj2 (varName) - obj1 (varName) )
778 otherNtupleName =
""):
779 """Opens the output file, loads all of the necessary shared 780 object libraries, and returns the output file and tree. If 781 'otherNtupleName' is given, it will check and make sure that 782 only objects that are defined in it are written out.""" 783 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
784 tree = ROOT.TTree (treeName, treeDescription)
785 GenObject._loadGoRootLibrary()
786 for objName
in sorted (GenObject._objsDict.keys()):
787 classname = GenObject.rootClassName (objName)
789 GenObject._rootClassDict[objName] = \
790 getattr (ROOT, classname)
791 if GenObject.isSingleton (objName):
793 obj = GenObject._rootObjectDict[objName] = rootObj()
794 tree.Branch (objName, classname, obj)
800 GenObject._rootObjectDict[objName] = \
801 ROOT.std.vector( rootObj )()
802 branchName = objName +
"s" 803 vecName =
"vector<%s>" % classname
804 tree.Branch( branchName, vecName, vec)
807 return rootfile, tree
812 diffDescription =
'', missingDescription =
''):
813 """Opens the diff output file, loads all of the necessary 814 shared object libraries, and returns the output file and tree.b""" 815 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
816 GenObject._loadGoRootLibrary()
818 diffTree = ROOT.TTree (diffName, diffDescription)
819 runEventObject = getattr (ROOT,
'go_runevent')()
820 diffTree.Branch (
'runevent',
'go_runevent', runEventObject)
821 GenObject._rootClassDict[
'runevent'] = runEventObject
822 for objName
in sorted (GenObject._objsDict.keys()):
823 if objName ==
'runevent':
continue 824 classname = GenObject.rootClassName (objName)
825 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
826 contName = GenObject.rootDiffContClassName (objName)
827 diffName = GenObject.rootDiffClassName (objName)
828 rootObj = GenObject._rootClassDict[contName] = \
829 getattr (ROOT, contName)
830 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
831 obj = GenObject._rootObjectDict[objName] = rootObj()
832 diffTree.Branch (objName, contName, obj)
834 missingTree = ROOT.TTree (missingName, missingDescription)
835 rootRunEventClass = getattr (ROOT,
'go_runevent')
836 firstOnly = GenObject._rootClassDict[
'firstOnly'] = \
837 ROOT.std.vector( rootRunEventClass ) ()
838 secondOnly = GenObject._rootClassDict[
'secondOnly'] = \
839 ROOT.std.vector( rootRunEventClass ) ()
840 missingTree.Branch (
'firstOnly',
'vector<go_runevent>', firstOnly)
841 missingTree.Branch (
'secondOnly',
'vector<go_runevent>', secondOnly)
842 return rootfile, diffTree, missingTree
847 """Fills root objects from GenObject 'event'""" 848 for objName, obj
in sorted (six.iteritems(event)):
849 if GenObject.isSingleton (objName):
851 GenObject._rootObjectCopy (obj,
852 GenObject._rootObjectDict[objName])
855 vec = GenObject._rootObjectDict[objName]
858 vec.push_back( GenObject._rootObjectClone (goObj) )
863 """Fills root diff containers from two GenObject 'event's""" 869 """Returns true if object is a singleton""" 870 return GenObject._objsDict[objName].
get(
'_singleton')
875 onlyRunEvent =
False):
876 """Loads event information from Root file (as interfaced by 877 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary 878 'event' containing lists of objects or singleton object. If 879 'onlyRunEvent' is et to True, then only run and event number 880 is read in from the tree.""" 881 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
882 tupleName = GenObject._kitchenSinkDict[eventTree][
'tupleName']
885 isChain = eventTree.__class__.__name__ ==
'TChain' 888 eventTree.GetEntry (eventIndex)
891 eventTree.to(eventIndex)
892 tofillDict = GenObject._tofillDict.get (tupleName)
893 ntupleDict = GenObject._ntupleDict.get (tupleName)
895 print "Don't know how to fill from '%s' ntuple." % tupleName
897 eventBranchName = ntupleDict[
'runevent']
898 for objName
in tofillDict:
899 branchName = ntupleDict[objName]
900 if onlyRunEvent
and branchName != eventBranchName:
909 objects = getattr (eventTree, branchName)
912 shortcut = ntupleDict.get(
'_shortcut', {}).
get(branchName)
914 objects = GenObject.evaluateFunction (eventTree, shortcut)
917 handle = ntupleDict.get(
'_handle', {}).
get(branchName)
918 label = ntupleDict.get(
'_label' , {}).
get(branchName)
919 if not handle
or not label:
920 raise RuntimeError(
"Missing handle or label for '%s'"\
922 if not eventTree.getByLabel (label, handle):
923 raise RuntimeError(
"not able to get %s for %s" \
924 % (label, branchName))
925 objects = handle.product()
927 if GenObject.isSingleton (objName):
928 event[objName] = GenObject.\
929 _genObjectClone (objName,
934 if debug: warn (objName, spaces = 3)
936 for index, obj
in enumerate (objects):
937 event[objName].
append( GenObject.\
938 _genObjectClone (objName,
952 """Prints out event dictionary. Mostly for debugging""" 954 for objName, obj
in sorted (six.iteritems(event)):
957 if GenObject.isSingleton (objName):
958 print "%s: %s" % (objName, obj)
960 for objName, obj
in sorted (six.iteritems(event)):
963 if not GenObject.isSingleton (objName):
965 print "%s:" % objName
973 """runs SetAlias on all saved aliases""" 974 aliases = GenObject._ntupleDict[tupleName].
get(
'_alias', {})
975 for name, alias
in six.iteritems(aliases):
976 eventTree.SetAlias (name, alias)
981 """Updates an alias for an object for a given tuple""" 982 aliasDict = GenObject._ntupleDict[tupleName][
'_alias']
983 if name
not in aliasDict:
984 raise RuntimeError(
"unknown name '%s' in tuple '%s'" % \
986 aliasDict[name] = alias
991 """Updates an label for an object for a given tuple""" 992 labelDict = GenObject._ntupleDict[tupleName][
'_label']
993 if objectName
not in labelDict:
994 raise RuntimeError(
"unknown name '%s' in tuple '%s'" % \
995 (objectName, tupleName))
996 label = tuple( GenObject._commaRE.split( label ) )
997 labelDict[objectName] = label
1002 """Given the tuple name and list of files, returns either a 1003 TChain or EventTree, and number of entries""" 1004 if "GenObject" == tupleName:
1005 GenObject.prepareToLoadGenObject()
1006 if not isinstance (files, list):
1009 ntupleDict = GenObject._ntupleDict[tupleName]
1010 treeName = ntupleDict[
"_tree"]
1011 if ntupleDict.get(
'_useChain'):
1012 chain = ROOT.TChain (treeName)
1013 for filename
in files:
1014 chain.AddFile (filename)
1015 numEntries = chain.GetEntries()
1018 chain = Events (files, forceEvent=
True)
1019 numEntries = chain.size()
1020 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1021 if numEventsWanted
and numEventsWanted < numEntries:
1022 numEntries = numEventsWanted
1023 chainDict[
'numEntries'] = numEntries
1024 chainDict[
'tupleName' ] = tupleName
1030 """Returns a dictionary of run, event tuples to entryIndicies""" 1032 for entryIndex
in xrange (numEntries):
1033 event = GenObject.loadEventFromTree (chain,
1035 onlyRunEvent =
True)
1036 runevent = event[
'runevent']
1037 reeDict[ GenObject._re2key (runevent) ] = entryIndex
1045 """Given a GO 'runevent' object, returns a sortable key""" 1048 if not GenObject._runEventListDone:
1049 GenObject._runEventListDone =
True 1050 ignoreSet = set( [
'run',
'event'] )
1051 for varName
in sorted (runevent.__dict__.keys()):
1052 if varName.startswith (
'_')
or varName
in ignoreSet:
1054 form = runevent.getVariableProperty (varName,
"form")
1057 GenObject._runEventList.append ((varName, form))
1058 key =
'run:%d event:%d' % (runevent.run, runevent.event)
1059 for items
in GenObject._runEventList:
1061 form =
' %s:%s' % (varName, items[1])
1062 key += form % runevent.getVariableProperty (varName)
1068 """Given a key, returns a GO 'runevent' object""" 1070 runevent = GenObject (
'runevent')
1071 words = GenObject._spacesRE.split (key)
1073 match = GenObject._singleColonRE.search (word)
1078 runevent.__setattr__ (match.group(1),
int( match.group(2) ))
1084 """Compares the keys of the two dicts and returns three sets: 1085 the overlap, first but not second, and second but not first.""" 1090 for key
in firstDict.keys():
1091 if key
in secondDict:
1097 for key
in secondDict.keys():
1098 if key
not in firstDict:
1099 secondOnly.add (key)
1101 return overlap, firstOnly, secondOnly
1106 """Finds the equivalent objects in the two vectors""" 1107 len1, len2 = len (vec1), len (vec2)
1108 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1109 if not len1
or not len2:
1112 noMatch1Set = set( xrange(len1) )
1114 noMatch1Set = set ()
1116 noMatch2Set = set( xrange(len2) )
1118 noMatch2Set = set ()
1119 if debug: warn (
"Nothing found", sapces=6)
1120 return set(), noMatch1Set, noMatch2Set
1121 objName = vec1[0]._objName
1122 equivList = GenObject._equivDict[objName]
1126 if GenObject._kitchenSinkDict.get (
'strictPairing')
or \
1127 equivList == [(
'index', 0)]:
1129 matchedSet = set (zip ( range( min (len1, len2) ),
1130 range( min (len1, len2) ) ) )
1134 noMatch1Set = set (range(len2, len1 + 1))
1139 noMatch2Set = set (range(len1, len2 + 1))
1142 return matchedSet, noMatch1Set, noMatch2Set
1157 for index1
in xrange (len1):
1160 for index2
in xrange (len2):
1164 for equiv
in equivList:
1165 var, precision = equiv[0], equiv[1]
1170 value = abs (val1 - val2) / precision
1179 objList.append( (total, index2) )
1181 firstDict[index1] = objList
1184 for index2
in xrange (len2):
1187 for index1
in xrange (len1):
1191 for equiv
in equivList:
1192 var, precision = equiv[0], equiv[1]
1197 value = abs (val2 - val1) / precision
1206 objList.append( (total, index1) )
1208 secondDict[index2] = objList
1213 firstDictKeys = sorted (firstDict.keys())
1214 for index1
in firstDictKeys:
1215 list1 = firstDict[index1]
1219 noMatch1Set.add (index1)
1225 list2 = secondDict.get (index2, [])
1226 if len(list2)
and list2[0][1] == index1:
1227 matchedSet.add( (index1, index2) )
1229 del firstDict[index1]
1230 del secondDict[index2]
1233 noMatch1Set.add (index1)
1234 noMatch2Set = set( secondDict.keys() )
1235 return matchedSet, noMatch1Set, noMatch2Set
1240 """Compares all of the variables making sure they are the same 1241 on the two objects.""" 1242 objName = item1._objName
1244 relative = GenObject._kitchenSinkDict.get (
'relative',
False)
1245 for varName
in GenObject._objsDict[objName].
keys():
1246 prec = item1.getVariableProperty (varName,
'prec')
1250 val1 = item1(varName)
1251 val2 = item2(varName)
1252 numerator = 2 * abs (val1 - val2)
1253 denominator =
abs(val1) +
abs(val2)
1258 value = numerator / denominator
1261 problems[varName] = value
1263 value =
abs( item1(varName) - item2(varName) )
1266 problems[varName] = value
1269 if item1(varName) != item2(varName):
1271 val1, val2 = item1(varName), item2(varName)
1273 val1, val2 = val2, val1
1274 problems[varName] =
"%s != %s" % (val1, val2)
1281 """For debugging purposes only. Will deliberately change 1282 values of first tree to verify that script is correctly 1283 finding problems.""" 1284 for objName
in sorted (event.keys()):
1285 if "runevent" == objName:
1288 if GenObject.isSingleton (objName):
1292 for obj
in event[objName]:
1294 for varName
in GenObject._objsDict[objName].
keys():
1295 if isinstance (obj.__dict__[varName], str):
1298 randNumber = random.random()
1300 if randNumber < GenObject._kitchenSinkDict[
'blurRate']:
1301 print " %s: changing '%s' of '%s:%d'" \
1302 % (where, varName, obj._objName, count)
1305 obj.__dict__[varName] += value
1310 """Given all of the necessary information, this routine will 1311 go through and compare two trees making sure they are 1312 'identical' within requested precision. If 'diffOutputName' 1313 is passed in, a root file with a diffTree and missingTree will 1315 print "Comparing Two Trees" 1316 diffOutputName = kwargs.get (
'diffOutputName')
1317 tupleName1 = GenObject._kitchenSinkDict[chain1][
'tupleName']
1318 numEntries1 = GenObject._kitchenSinkDict[chain1][
'numEntries']
1319 tupleName2 = GenObject._kitchenSinkDict[chain2][
'tupleName']
1320 numEntries2 = GenObject._kitchenSinkDict[chain2][
'numEntries']
1321 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1322 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1323 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1324 overlap, firstOnly, secondOnly = \
1325 GenObject.compareRunEventDicts (ree1, ree2)
1327 rootfile, diffTree, missingTree = \
1328 GenObject.setupDiffOutputTree (diffOutputName,
1332 vec = GenObject._rootClassDict[
'firstOnly']
1333 for key
in firstOnly:
1334 runevent = GenObject._key2re (key)
1335 vec.push_back( GenObject._rootObjectClone( runevent ) )
1337 vec = GenObject._rootClassDict[
'secondOnly']
1338 for key
in secondOnly:
1339 runevent = GenObject._key2re (key)
1340 vec.push_back( GenObject._rootObjectClone( runevent ) )
1344 resultsDict.setdefault (
'_runevent', {})[
'firstOnly'] = \
1347 resultsDict.setdefault (
'_runevent', {})[
'secondOnly'] = \
1349 resultsDict[
'eventsCompared'] = len (overlap)
1350 for reTuple
in sorted(overlap):
1354 GenObject._key2re (reTuple,
1355 GenObject._rootClassDict[
'runevent'])
1356 if debug: warn (
'event1', blankLines = 3)
1357 event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1358 if debug: warn (
'event2', blankLines = 3)
1359 event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1360 if GenObject._kitchenSinkDict.get(
'printEvent'):
1362 GenObject.printEvent (event1)
1364 GenObject.printEvent (event2)
1365 if GenObject._kitchenSinkDict.get(
'blur'):
1367 GenObject.blurEvent (event1,
1368 GenObject._kitchenSinkDict[
'blur'],
1370 for objName
in sorted (event1.keys()):
1371 if "runevent" == objName:
1374 if not GenObject._equivDict.get (objName):
1378 if GenObject.isSingleton (objName):
1385 rootObj = GenObject._rootObjectDict[objName]
1387 vec1 = event1[objName]
1388 vec2 = event2[objName]
1389 matchedSet, noMatch1Set, noMatch2Set = \
1390 GenObject.pairEquivalentObjects (vec1, vec2)
1391 if noMatch1Set
or noMatch2Set:
1394 count1 = len (noMatch1Set)
1395 count2 = len (noMatch2Set)
1396 key = (count1, count2)
1397 countDict = resultsDict.\
1398 setdefault (objName, {}).\
1399 setdefault (
'_missing', {})
1400 if key
in countDict:
1407 for index
in sorted(
list(noMatch1Set)):
1408 goObj = vec1 [index]
1409 rootObj.firstOnly.push_back ( GenObject.\
1413 for index
in sorted(
list(noMatch2Set)):
1414 goObj = vec2 [index]
1415 rootObj.secondOnly.push_back ( GenObject.\
1420 for pair
in sorted(
list(matchedSet)):
1422 rootDiffObj = GenObject._rootDiffObject \
1423 ( vec1[ pair[1 - 1] ],
1424 vec2[ pair[2 - 1] ] )
1425 rootObj.diff.push_back ( rootDiffObj )
1426 problems = GenObject.\
1427 compareTwoItems (vec1[ pair[1 - 1] ],
1428 vec2[ pair[2 - 1] ])
1431 for varName
in problems.keys():
1432 countDict = resultsDict.\
1433 setdefault (objName, {}).\
1434 setdefault (
'_var', {})
1435 if varName
in countDict:
1436 countDict[varName] += 1
1438 countDict[varName] = 1
1439 key =
'count_%s' % objName
1440 if key
not in resultsDict:
1441 resultsDict[key] = 0
1442 resultsDict[key] += len (matchedSet)
1461 """Saves a chain as a GO tree""" 1463 rootfile, tree = GenObject.setupOutputTree (rootFile,
"goTree")
1464 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1465 for entryIndex
in xrange (numEntries):
1466 event = GenObject.loadEventFromTree (chain, entryIndex)
1467 if GenObject._kitchenSinkDict.get(
'blur'):
1468 where =
"run %d event %d" % (event[
'runevent'].run,
1469 event[
'runevent'].event)
1470 if random.random() < GenObject._kitchenSinkDict.get(
'blur'):
1472 print "Dropping", where
1474 GenObject.blurEvent (event,
1475 GenObject._kitchenSinkDict[
'blur'],
1478 if GenObject._kitchenSinkDict.get(
'printEvent'):
1479 GenObject.printEvent (event)
1480 GenObject._fillRootObjects (event)
1488 """Sets a global flag in _kitchenSinkDict""" 1489 GenObject._kitchenSinkDict [key] = value
1494 """Prints out all events to stdout""" 1495 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1496 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1497 if debug: warn (numEntries)
1498 for entryIndex
in xrange (numEntries):
1499 if debug: warn (entryIndex, spaces=3)
1500 event = GenObject.loadEventFromTree (chain, entryIndex)
1501 GenObject.printEvent (event)
1502 if debug:
warn(spaces=3)
1506 """Convert comma-separated string into a python list of 1507 parameters. Currently only understands strings, floats, and 1510 words = GenObject._commaRE.split (string)
1514 match = GenObject._singleQuoteRE.search (word)
1516 retval.append (match.group (1))
1518 match = GenObject._doubleQuoteRE.search (word)
1520 retval.append (match.group (1))
1535 raise RuntimeError(
"Unknown parameter '%s'." % word)
1545 """Class initializer""" 1546 if objName
not in GenObject._objsDict:
1549 print "Error: GenObject does not know about object '%s'." % objName
1550 raise RuntimeError(
"Failed to create GenObject object.")
1556 if key.startswith (
"_"):
1558 self.
setValue (key, varDict[
'default'])
1562 """Wrapper for __setattr___""" 1567 """ Returns property assoicated with 'key' for variable 'var' 1568 of object of the same type as 'self'. Returns 'None' if 'var' 1569 or 'key' is not defined.""" 1570 return GenObject._objsDict.get (self.
_objName,
1571 {}).get (var, {}). get (key,
None)
1575 """Controls setting of values.""" 1576 if name.startswith (
"_"):
1578 object.__setattr__ (self, name, value)
1585 print "Warning: '%s' for class '%s' not setup. Skipping." % \
1590 if GenObject.types.int == varType:
1598 elif GenObject.types.long == varType:
1602 value = long (value)
1605 value = long(
float( value ) )
1606 elif GenObject.types.float == varType:
1608 value = float (value)
1609 elif GenObject.types.string == varType:
1613 object.__setattr__ (self, name, value)
1617 """Makes object callable""" 1618 return object.__getattribute__ (self, key)
1622 """String representation""" 1624 for varName, value
in sorted (six.iteritems(self.__dict__)):
1625 if varName.startswith (
'_'):
continue 1628 format =
"%s:%s " % (varName, form)
1629 retval = retval + format % value
1631 retval = retval +
"%s:%s " % (varName, value)
def prepareTuple(tupleName, files, numEventsWanted=0)
def changeVariable(tupleName, objName, varName, fillname)
def encodeNonAlphanumerics(line)
def loadConfigFile(configFile)
def blurEvent(event, value, where="")
def char2ascii(match)
Static Member Functions ##.
def _finishClassHeader(className, datadec)
def setEquivExpression(obj, variable, precision)
def evaluateFunction(obj, partsList, debug=False)
def _rootObjectCopy(goSource, rootTarget)
def _rootObjectClone(obj)
def getVariableProperty(obj, var, key)
def addObjectVariable(obj, var, optionsDict)
def _fillRootObjects(event)
def setGlobalFlag(key, value)
def _convertStringToParameters(string)
def setAliases(eventTree, tupleName)
def compareTwoItems(item1, item2)
def setupDiffOutputTree(outputFile, diffName, missingName, diffDescription='', missingDescription='')
def setQuietWarn(quiet=True)
def setValue(self, name, value)
Abs< T >::type abs(const T &t)
def _genObjectClone(objName, tupleName, obj, index=-1)
def __setattr__(self, name, value)
def changeLabel(tupleName, objectName, label)
def changeAlias(tupleName, name, alias)
def saveTupleAs(chain, rootFile)
def prepareToLoadGenObject()
def rootDiffClassName(objName)
def setupOutputTree(outputFile, treeName, treeDescription="", otherNtupleName="")
def compareRunEventDicts(firstDict, secondDict)
def _createCppClass(objName)
def getRunEventEntryDict(chain, tupleName, numEntries)
def compareTwoTrees(chain1, chain2, kwargs)
def pairEquivalentObjects(vec1, vec2)
def loadEventFromTree(eventTree, eventIndex, onlyRunEvent=False)
def rootDiffContClassName(objName)
def _rootDiffObject(obj1, obj2, rootObj=0)
def _key2re(key, runevent=None)
def rootClassName(objName)
def __init__(self, objName)
Member Functions ##.
def _setupClassHeader(className, noColon=False)
def _fixLostGreaterThans(handle)
def parseVariableTofill(fillname)
def _fillRootDiffs(event1, event2)
T get(const Candidate &c)
def decodeNonAlphanumerics(line)
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