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 = 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:]
654 print "I don't understand '%s' in section '%s'." \
656 raise RuntimeError, \
657 "Config file parser error '%s'(%d)" \
658 % (fullLine, lineNum)
659 tofillDict = GenObject._tofillDict.\
660 setdefault (tupleName, {}).\
661 setdefault (objName, {})
662 partsList = GenObject.parseVariableTofill (fillname)
663 tofillDict[varName] = [partsList, optionsDict]
665 for objName
in GenObject._objsDict:
667 if not GenObject.isSingleton (objName):
668 GenObject.addObjectVariable (objName,
'index',
669 varType = GenObject.types.int,
674 def changeVariable (tupleName, objName, varName, fillname):
675 """Updates the definition used to go from a Root object to a
676 GenObject. 'tupleName' and 'objName' must already be defined."""
677 parts = GenObject._dotRE.split (fillname)
680 parenMatch = GenObject._parenRE.search (part)
681 mode = GenObject._objFunc.obj
684 part = parenMatch.group (1)
685 mode = GenObject._objFunc.func
687 GenObject._convertStringToParameters \
688 (parenMatch.group (2))
689 partsList.append( (part, mode, parens) )
690 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
695 def evaluateFunction (obj, partsList, debug=False):
696 """Evaluates function described in partsList on obj"""
697 for part
in partsList:
698 if debug: warn (part, spaces=15)
699 obj = getattr (obj, part[0])
700 if debug: warn (obj, spaces=15)
703 if GenObject._objFunc.func == part[1]:
706 if debug: warn (obj, spaces=18)
711 def _genObjectClone (objName, tupleName, obj, index = -1):
712 """Creates a GenObject copy of Root object"""
713 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
714 if objName ==
'runevent':
716 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
718 genObj = GenObject (objName)
720 if debug: warn (objName, spaces = 9)
721 for genVar, ntDict
in tofillObjDict.iteritems():
722 if debug: warn (genVar, spaces = 12)
724 partsList = ntDict[0]
726 obj = GenObject.evaluateFunction (origObj, partsList, debug)
737 if debug: warn (obj, spaces=12)
738 setattr (genObj, genVar, obj)
741 setattr (genObj,
'index', index)
746 def _rootObjectCopy (goSource, rootTarget):
747 """Copies information from goSourse into Root Object"""
748 objName = goSource._objName
749 for varName
in GenObject._objsDict [objName].
keys():
752 if varName.startswith (
"_"):
754 setattr( rootTarget, varName, goSource (varName) )
758 def _rootObjectClone (obj):
759 """Creates the approprite type of Root object and copies the
760 information into it from the GO object."""
761 objName = obj._objName
762 classObj = GenObject._rootClassDict.get (objName)
764 goName = GenObject.rootClassName (objName)
765 classObj = GenObject._rootClassDict[ goName ]
767 for varName
in GenObject._objsDict [objName].
keys():
768 setattr( rootObj, varName, obj (varName) )
773 def _rootDiffObject (obj1, obj2, rootObj = 0):
774 """Given to GOs, it will create and fill the corresponding
776 objName = obj1._objName
779 diffName = GenObject.rootDiffClassName( objName )
780 rootObj = GenObject._rootClassDict[diffName]()
781 for varName
in GenObject._objsDict [objName].
keys():
782 if varName.startswith (
"_"):
continue
783 goType = GenObject._objsDict[objName][varName][
'varType']
784 if not goType
in GenObject._basicSet:
787 setattr( rootObj, varName, obj1 (varName) )
788 if goType == GenObject.types.string:
790 otherName =
'other_' + varName
791 if obj1 (varName) != obj2 (varName):
793 setattr( rootObj, otherName, obj2 (varName) )
796 setattr( rootObj, otherName,
'' )
799 deltaName =
'delta_' + varName
800 setattr( rootObj, deltaName,
801 obj2 (varName) - obj1 (varName) )
806 def setupOutputTree (outputFile, treeName, treeDescription = "",
807 otherNtupleName =
""):
808 """Opens the output file, loads all of the necessary shared
809 object libraries, and returns the output file and tree. If
810 'otherNtupleName' is given, it will check and make sure that
811 only objects that are defined in it are written out."""
812 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
813 tree = ROOT.TTree (treeName, treeDescription)
814 GenObject._loadGoRootLibrary()
815 for objName
in sorted (GenObject._objsDict.keys()):
816 classname = GenObject.rootClassName (objName)
818 GenObject._rootClassDict[objName] = \
819 getattr (ROOT, classname)
820 if GenObject.isSingleton (objName):
822 obj = GenObject._rootObjectDict[objName] = rootObj()
823 tree.Branch (objName, classname, obj)
829 GenObject._rootObjectDict[objName] = \
830 ROOT.std.vector( rootObj )()
831 branchName = objName +
"s"
832 vecName =
"vector<%s>" % classname
833 tree.Branch( branchName, vecName, vec)
836 return rootfile, tree
840 def setupDiffOutputTree (outputFile, diffName, missingName,
841 diffDescription =
'', missingDescription =
''):
842 """Opens the diff output file, loads all of the necessary
843 shared object libraries, and returns the output file and tree.b"""
844 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
845 GenObject._loadGoRootLibrary()
847 diffTree = ROOT.TTree (diffName, diffDescription)
848 runEventObject = getattr (ROOT,
'go_runevent')()
849 diffTree.Branch (
'runevent',
'go_runevent', runEventObject)
850 GenObject._rootClassDict[
'runevent'] = runEventObject
851 for objName
in sorted (GenObject._objsDict.keys()):
852 if objName ==
'runevent':
continue
853 classname = GenObject.rootClassName (objName)
854 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
855 contName = GenObject.rootDiffContClassName (objName)
856 diffName = GenObject.rootDiffClassName (objName)
857 rootObj = GenObject._rootClassDict[contName] = \
858 getattr (ROOT, contName)
859 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
860 obj = GenObject._rootObjectDict[objName] = rootObj()
861 diffTree.Branch (objName, contName, obj)
863 missingTree = ROOT.TTree (missingName, missingDescription)
864 rootRunEventClass = getattr (ROOT,
'go_runevent')
865 firstOnly = GenObject._rootClassDict[
'firstOnly'] = \
866 ROOT.std.vector( rootRunEventClass ) ()
867 secondOnly = GenObject._rootClassDict[
'secondOnly'] = \
868 ROOT.std.vector( rootRunEventClass ) ()
869 missingTree.Branch (
'firstOnly',
'vector<go_runevent>', firstOnly)
870 missingTree.Branch (
'secondOnly',
'vector<go_runevent>', secondOnly)
871 return rootfile, diffTree, missingTree
875 def _fillRootObjects (event):
876 """Fills root objects from GenObject 'event'"""
877 for objName, obj
in sorted (event.iteritems()):
878 if GenObject.isSingleton (objName):
880 GenObject._rootObjectCopy (obj,
881 GenObject._rootObjectDict[objName])
884 vec = GenObject._rootObjectDict[objName]
887 vec.push_back( GenObject._rootObjectClone (goObj) )
891 def _fillRootDiffs (event1, event2):
892 """Fills root diff containers from two GenObject 'event's"""
897 def isSingleton (objName):
898 """Returns true if object is a singleton"""
899 return GenObject._objsDict[objName].
get(
'_singleton')
903 def loadEventFromTree (eventTree, eventIndex,
904 onlyRunEvent =
False):
905 """Loads event information from Root file (as interfaced by
906 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
907 'event' containing lists of objects or singleton object. If
908 'onlyRunEvent' is et to True, then only run and event number
909 is read in from the tree."""
910 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
911 tupleName = GenObject._kitchenSinkDict[eventTree][
'tupleName']
914 isChain = eventTree.__class__.__name__ ==
'TChain'
917 eventTree.GetEntry (eventIndex)
920 eventTree.to(eventIndex)
921 tofillDict = GenObject._tofillDict.get (tupleName)
922 ntupleDict = GenObject._ntupleDict.get (tupleName)
924 print "Don't know how to fill from '%s' ntuple." % tupleName
926 eventBranchName = ntupleDict[
'runevent']
927 for objName
in tofillDict:
928 branchName = ntupleDict[objName]
929 if onlyRunEvent
and branchName != eventBranchName:
938 objects = getattr (eventTree, branchName)
941 shortcut = ntupleDict.get(
'_shortcut', {}).
get(branchName)
943 objects = GenObject.evaluateFunction (eventTree, shortcut)
946 handle = ntupleDict.get(
'_handle', {}).
get(branchName)
947 label = ntupleDict.get(
'_label' , {}).
get(branchName)
948 if not handle
or not label:
949 raise RuntimeError,
"Missing handle or label for '%s'"\
951 if not eventTree.getByLabel (label, handle):
952 raise RuntimeError,
"not able to get %s for %s" \
953 % (label, branchName)
954 objects = handle.product()
956 if GenObject.isSingleton (objName):
957 event[objName] = GenObject.\
958 _genObjectClone (objName,
963 if debug: warn (objName, spaces = 3)
965 for index, obj
in enumerate (objects):
966 event[objName].
append( GenObject.\
967 _genObjectClone (objName,
980 def printEvent (event):
981 """Prints out event dictionary. Mostly for debugging"""
983 for objName, obj
in sorted (event.iteritems()):
986 if GenObject.isSingleton (objName):
987 print "%s: %s" % (objName, obj)
989 for objName, obj
in sorted (event.iteritems()):
992 if not GenObject.isSingleton (objName):
994 print "%s:" % objName
1001 def setAliases (eventTree, tupleName):
1002 """runs SetAlias on all saved aliases"""
1003 aliases = GenObject._ntupleDict[tupleName].
get(
'_alias', {})
1004 for name, alias
in aliases.iteritems():
1005 eventTree.SetAlias (name, alias)
1009 def changeAlias (tupleName, name, alias):
1010 """Updates an alias for an object for a given tuple"""
1011 aliasDict = GenObject._ntupleDict[tupleName][
'_alias']
1012 if not aliasDict.has_key (name):
1013 raise RuntimeError,
"unknown name '%s' in tuple '%s'" % \
1015 aliasDict[name] = alias
1019 def changeLabel (tupleName, objectName, label):
1020 """Updates an label for an object for a given tuple"""
1021 labelDict = GenObject._ntupleDict[tupleName][
'_label']
1022 if not labelDict.has_key (objectName):
1023 raise RuntimeError,
"unknown name '%s' in tuple '%s'" % \
1024 (objectName, tupleName)
1025 label = tuple( GenObject._commaRE.split( label ) )
1026 labelDict[objectName] = label
1030 def prepareTuple (tupleName, files, numEventsWanted = 0):
1031 """Given the tuple name and list of files, returns either a
1032 TChain or EventTree, and number of entries"""
1033 if "GenObject" == tupleName:
1034 GenObject.prepareToLoadGenObject()
1035 if not isinstance (files, list):
1038 ntupleDict = GenObject._ntupleDict[tupleName]
1039 treeName = ntupleDict[
"_tree"]
1040 if ntupleDict.get(
'_useChain'):
1041 chain = ROOT.TChain (treeName)
1042 for filename
in files:
1043 chain.AddFile (filename)
1044 numEntries = chain.GetEntries()
1047 chain = Events (files, forceEvent=
True)
1048 numEntries = chain.size()
1049 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1050 if numEventsWanted
and numEventsWanted < numEntries:
1051 numEntries = numEventsWanted
1052 chainDict[
'numEntries'] = numEntries
1053 chainDict[
'tupleName' ] = tupleName
1058 def getRunEventEntryDict (chain, tupleName, numEntries):
1059 """Returns a dictionary of run, event tuples to entryIndicies"""
1061 for entryIndex
in xrange (numEntries):
1062 event = GenObject.loadEventFromTree (chain,
1064 onlyRunEvent =
True)
1065 runevent = event[
'runevent']
1066 reeDict[ GenObject._re2key (runevent) ] = entryIndex
1073 def _re2key (runevent):
1074 """Given a GO 'runevent' object, returns a sortable key"""
1077 if not GenObject._runEventListDone:
1078 GenObject._runEventListDone =
True
1079 ignoreSet = set( [
'run',
'event'] )
1080 for varName
in sorted (runevent.__dict__.keys()):
1081 if varName.startswith (
'_')
or varName
in ignoreSet:
1083 form = runevent.getVariableProperty (varName,
"form")
1086 GenObject._runEventList.append ((varName, form))
1087 key =
'run:%d event:%d' % (runevent.run, runevent.event)
1088 for items
in GenObject._runEventList:
1090 form =
' %s:%s' % (varName, items[1])
1091 key += form % runevent.getVariableProperty (varName)
1096 def _key2re (key, runevent=None):
1097 """Given a key, returns a GO 'runevent' object"""
1099 runevent = GenObject (
'runevent')
1100 words = GenObject._spacesRE.split (key)
1102 match = GenObject._singleColonRE.search (word)
1107 runevent.__setattr__ (match.group(1), int( match.group(2) ))
1112 def compareRunEventDicts (firstDict, secondDict):
1113 """Compares the keys of the two dicts and returns three sets:
1114 the overlap, first but not second, and second but not first."""
1119 for key
in firstDict.keys():
1120 if secondDict.has_key (key):
1126 for key
in secondDict.keys():
1127 if not firstDict.has_key (key):
1128 secondOnly.add (key)
1130 return overlap, firstOnly, secondOnly
1134 def pairEquivalentObjects (vec1, vec2):
1135 """Finds the equivalent objects in the two vectors"""
1136 len1, len2 = len (vec1), len (vec2)
1137 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1138 if not len1
or not len2:
1141 noMatch1Set = set( xrange(len1) )
1143 noMatch1Set = set ()
1145 noMatch2Set = set( xrange(len2) )
1147 noMatch2Set = set ()
1148 if debug: warn (
"Nothing found", sapces=6)
1149 return set(), noMatch1Set, noMatch2Set
1150 objName = vec1[0]._objName
1151 equivList = GenObject._equivDict[objName]
1156 for index1
in xrange (len1):
1159 for index2
in xrange (len2):
1163 for equiv
in equivList:
1164 var, precision = equiv[0], equiv[1]
1169 value = abs (val1 - val2) / precision
1178 objList.append( (total, index2) )
1180 firstDict[index1] = objList
1183 for index2
in xrange (len2):
1186 for index1
in xrange (len1):
1190 for equiv
in equivList:
1191 var, precision = equiv[0], equiv[1]
1196 value = abs (val2 - val1) / precision
1205 objList.append( (total, index1) )
1207 secondDict[index2] = objList
1212 firstDictKeys = sorted (firstDict.keys())
1213 for index1
in firstDictKeys:
1214 list1 = firstDict[index1]
1218 noMatch1Set.add (index1)
1224 list2 = secondDict.get (index2, [])
1225 if len(list2)
and list2[0][1] == index1:
1226 matchedSet.add( (index1, index2) )
1228 del firstDict[index1]
1229 del secondDict[index2]
1232 noMatch1Set.add (index1)
1233 noMatch2Set = set( secondDict.keys() )
1234 return matchedSet, noMatch1Set, noMatch2Set
1238 def compareTwoItems (item1, item2):
1239 """Compares all of the variables making sure they are the same
1240 on the two objects."""
1241 objName = item1._objName
1243 relative = GenObject._kitchenSinkDict.get (
'relative',
False)
1244 for varName
in GenObject._objsDict[objName].
keys():
1245 prec = item1.getVariableProperty (varName,
'prec')
1249 val1 = item1(varName)
1250 val2 = item2(varName)
1251 numerator = 2 * abs (val1 - val2)
1252 denominator =
abs(val1) +
abs(val2)
1257 value = numerator / denominator
1260 problems[varName] = value
1262 value =
abs( item1(varName) - item2(varName) )
1265 problems[varName] = value
1268 if item1(varName) != item2(varName):
1270 val1, val2 = item1(varName), item2(varName)
1272 val1, val2 = val2, val1
1273 problems[varName] =
"%s != %s" % (val1, val2)
1279 def blurEvent (event, value, where = ""):
1280 """For debugging purposes only. Will deliberately change
1281 values of first tree to verify that script is correctly
1282 finding problems."""
1283 for objName
in sorted (event.keys()):
1284 if "runevent" == objName:
1287 if GenObject.isSingleton (objName):
1291 for obj
in event[objName]:
1293 for varName
in GenObject._objsDict[objName].
keys():
1294 if isinstance (obj.__dict__[varName], str):
1297 randNumber = random.random()
1299 if randNumber < GenObject._kitchenSinkDict[
'blurRate']:
1300 print " %s: changing '%s' of '%s:%d'" \
1301 % (where, varName, obj._objName, count)
1304 obj.__dict__[varName] += value
1308 def compareTwoTrees (chain1, chain2, **kwargs):
1309 """Given all of the necessary information, this routine will
1310 go through and compare two trees making sure they are
1311 'identical' within requested precision. If 'diffOutputName'
1312 is passed in, a root file with a diffTree and missingTree will
1314 print "Comparing Two Trees"
1315 diffOutputName = kwargs.get (
'diffOutputName')
1316 tupleName1 = GenObject._kitchenSinkDict[chain1][
'tupleName']
1317 numEntries1 = GenObject._kitchenSinkDict[chain1][
'numEntries']
1318 tupleName2 = GenObject._kitchenSinkDict[chain2][
'tupleName']
1319 numEntries2 = GenObject._kitchenSinkDict[chain2][
'numEntries']
1320 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1321 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1322 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1323 overlap, firstOnly, secondOnly = \
1324 GenObject.compareRunEventDicts (ree1, ree2)
1326 rootfile, diffTree, missingTree = \
1327 GenObject.setupDiffOutputTree (diffOutputName,
1331 vec = GenObject._rootClassDict[
'firstOnly']
1332 for key
in firstOnly:
1333 runevent = GenObject._key2re (key)
1334 vec.push_back( GenObject._rootObjectClone( runevent ) )
1336 vec = GenObject._rootClassDict[
'secondOnly']
1337 for key
in secondOnly:
1338 runevent = GenObject._key2re (key)
1339 vec.push_back( GenObject._rootObjectClone( runevent ) )
1343 resultsDict.setdefault (
'_runevent', {})[
'firstOnly'] = \
1346 resultsDict.setdefault (
'_runevent', {})[
'secondOnly'] = \
1348 resultsDict[
'eventsCompared'] = len (overlap)
1349 for reTuple
in sorted(overlap):
1353 GenObject._key2re (reTuple,
1354 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):
1384 rootObj = GenObject._rootObjectDict[objName]
1386 vec1 = event1[objName]
1387 vec2 = event2[objName]
1388 matchedSet, noMatch1Set, noMatch2Set = \
1389 GenObject.pairEquivalentObjects (vec1, vec2)
1390 if noMatch1Set
or noMatch2Set:
1393 count1 = len (noMatch1Set)
1394 count2 = len (noMatch2Set)
1395 key = (count1, count2)
1396 countDict = resultsDict.\
1397 setdefault (objName, {}).\
1398 setdefault (
'_missing', {})
1399 if countDict.has_key (key):
1406 for index
in sorted(
list(noMatch1Set)):
1407 goObj = vec1 [index]
1408 rootObj.firstOnly.push_back ( GenObject.\
1412 for index
in sorted(
list(noMatch2Set)):
1413 goObj = vec2 [index]
1414 rootObj.secondOnly.push_back ( GenObject.\
1419 for pair
in sorted(
list(matchedSet)):
1421 rootObj.diff.push_back ( GenObject._rootDiffObject \
1422 ( vec1[ pair[1 - 1] ],
1423 vec2[ pair[2 - 1] ] ) )
1424 problems = GenObject.\
1425 compareTwoItems (vec1[ pair[1 - 1] ],
1426 vec2[ pair[2 - 1] ])
1429 for varName
in problems.keys():
1430 countDict = resultsDict.\
1431 setdefault (objName, {}).\
1432 setdefault (
'_var', {})
1433 if countDict.has_key (varName):
1434 countDict[varName] += 1
1436 countDict[varName] = 1
1437 key =
'count_%s' % objName
1438 if not resultsDict.has_key (key):
1439 resultsDict[key] = 0
1440 resultsDict[key] += len (matchedSet)
1458 def saveTupleAs (chain, rootFile):
1459 """Saves a chain as a GO tree"""
1461 rootfile, tree = GenObject.setupOutputTree (rootFile,
"goTree")
1462 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1463 for entryIndex
in xrange (numEntries):
1464 event = GenObject.loadEventFromTree (chain, entryIndex)
1465 if GenObject._kitchenSinkDict.get(
'blur'):
1466 where =
"run %d event %d" % (event[
'runevent'].run,
1467 event[
'runevent'].event)
1468 if random.random() < GenObject._kitchenSinkDict.get(
'blur'):
1470 print "Dropping", where
1472 GenObject.blurEvent (event,
1473 GenObject._kitchenSinkDict[
'blur'],
1476 if GenObject._kitchenSinkDict.get(
'printEvent'):
1477 GenObject.printEvent (event)
1478 GenObject._fillRootObjects (event)
1485 def setGlobalFlag (key, value):
1486 """Sets a global flag in _kitchenSinkDict"""
1487 GenObject._kitchenSinkDict [key] = value
1491 def printTuple (chain):
1492 """Prints out all events to stdout"""
1493 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1494 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1495 if debug: warn (numEntries)
1496 for entryIndex
in xrange (numEntries):
1497 if debug: warn (entryIndex, spaces=3)
1498 event = GenObject.loadEventFromTree (chain, entryIndex)
1499 GenObject.printEvent (event)
1500 if debug:
warn(spaces=3)
1503 def _convertStringToParameters (string):
1504 """Convert comma-separated string into a python list of
1505 parameters. Currently only understands strings, floats, and
1508 words = GenObject._commaRE.split (string)
1512 match = GenObject._singleQuoteRE.search (word)
1514 retval.append (match.group (1))
1516 match = GenObject._doubleQuoteRE.search (word)
1518 retval.append (match.group (1))
1533 raise RuntimeError,
"Unknown parameter '%s'." % word
1543 """Class initializer"""
1544 if not GenObject._objsDict.has_key (objName):
1547 print "Error: GenObject does not know about object '%s'." % objName
1548 raise RuntimeError,
"Failed to create GenObject object."
1549 self._localObjsDict = GenObject._objsDict [objName]
1550 self._objName = objName;
1551 for key, varDict
in self._localObjsDict.iteritems():
1554 if key.startswith (
"_"):
1556 self.setValue (key, varDict[
'default'])
1560 """Wrapper for __setattr___"""
1561 self.__setattr__ (name, value)
1564 def getVariableProperty (self, var, key):
1565 """ Returns property assoicated with 'key' for variable 'var'
1566 of object of the same type as 'self'. Returns 'None' if 'var'
1567 or 'key' is not defined."""
1568 return GenObject._objsDict.get (self._objName,
1569 {}).get (var, {}). get (key,
None)
1572 def __setattr__ (self, name, value):
1573 """Controls setting of values."""
1574 if name.startswith (
"_"):
1576 object.__setattr__ (self, name, value)
1581 if not self._localObjsDict.has_key (name):
1583 print "Warning: '%s' for class '%s' not setup. Skipping." % \
1584 (name, self._objName)
1586 varType = self.getVariableProperty (name,
'varType')
1588 if GenObject.types.int == varType:
1595 value = int( float( value ) )
1596 elif GenObject.types.long == varType:
1600 value = long (value)
1603 value = long( float( value ) )
1604 elif GenObject.types.float == varType:
1606 value = float (value)
1607 elif GenObject.types.string == varType:
1611 object.__setattr__ (self, name, value)
1614 def __call__ (self, key):
1615 """Makes object callable"""
1616 return object.__getattribute__ (self, key)
1620 """String representation"""
1622 for varName, value
in sorted (self.__dict__.iteritems()):
1623 if varName.startswith (
'_'):
continue
1624 form = self.getVariableProperty (varName,
"form")
1626 format =
"%s:%s " % (varName, form)
1627 retval = retval + format % value
1629 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 ...
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