1 from __future__
import print_function
7 from builtins
import range
8 from FWCore.Utilities.Enumerate
import Enumerate
9 from DataFormats.FWLite
import Events, Handle
19 from functools
import reduce
23 filenameRE = re.compile (
r'.+/Validation/Tools/')
32 def warn (*args, **kwargs):
33 """print out warning with line number and rest of arguments"""
35 frame = inspect.stack()[1]
39 filename = filenameRE.sub (
'', filename)
41 blankLines = kwargs.get(
'blankLines', 0)
43 print(
'\n' * blankLines)
44 spaces = kwargs.get(
'spaces', 0)
46 print(
' ' * spaces, end=
' ')
48 print(
"%s (%s): " % (filename, lineNum), end=
' ')
53 print(
"%s (%s):" % (filename, lineNum))
57 """Infrastruture to define general objects and their attributes."""
63 types = Enumerate (
"float int long string",
"type")
64 _objFunc = Enumerate (
"obj func",
"of")
65 _cppType = dict ( {types.float :
'double',
68 types.string :
'std::string' } )
69 _basicSet = set( [types.float, types.int, types.float,
71 _defaultValue = dict ( {types.float : 0.,
74 types.string :
'""' } )
85 _runEventListDone =
False
86 uselessReturnCode = 1 << 7
91 _nonSpacesRE = re.compile (
r'\S')
92 _colonRE = re.compile (
r'\s*:\s*')
93 _singleColonRE = re.compile (
r'(.+?):(.+)')
94 _doubleColonRE = re.compile (
r'(.+?):(.+?):(.+)')
95 _doublePercentRE = re.compile (
r'%%')
96 _parenRE = re.compile (
r'(.+)\((.*)\)')
97 _spacesRE = re.compile (
r'\s+')
98 _dotRE = re.compile (
r'\s*\.\s*')
99 _commaRE = re.compile (
r'\s*,\s*')
100 _singleQuoteRE = re.compile (
r'^\'(.+)\'$')
101 _doubleQuoteRE = re.compile (
r'^\"(.+)\"$')
102 _bracketRE = re.compile (
r'\[\s*(.+?)\s*\]')
103 _commentRE = re.compile (
r'#.+$')
104 _aliasRE = re.compile (
r'alias=(\S+)', re.IGNORECASE)
105 _labelRE = re.compile (
r'label=(\S+)', re.IGNORECASE)
106 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
107 _singletonRE = re.compile (
r'singleton', re.IGNORECASE)
108 _typeRE = re.compile (
r'type=(\S+)', re.IGNORECASE)
109 _defaultRE = re.compile (
r'default=(\S+)', re.IGNORECASE)
110 _shortcutRE = re.compile (
r'shortcut=(\S+)', re.IGNORECASE)
111 _precRE = re.compile (
r'prec=(\S+)', re.IGNORECASE)
112 _formRE = re.compile (
r'form=(\S+)', re.IGNORECASE)
113 _nonAlphaRE = re.compile (
r'\W')
114 _percentAsciiRE = re.compile (
r'%([0-9a-fA-F]{2})')
122 return "%%%02x" % ord (match.group(0))
126 return chr(
int( match.group(1), 16 ) )
130 """Use a web like encoding of characters that are non-alphanumeric"""
131 return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
135 """Decode lines encoded with encodeNonAlphanumerics()"""
136 return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
141 """ User passes in in object and variable names."""
142 if 'varType' not in optionsDict:
143 optionsDict[
'varType'] = GenObject.types.float
144 varType = optionsDict[
'varType']
145 if not GenObject.types.isValidValue (varType):
146 print(
"Type '%s' not valid. Skipping (%s, %s, %s)." % \
147 (varType, obj, var, varType))
149 if 'default' not in optionsDict:
150 optionsDict[
'default'] = GenObject._defaultValue[varType]
151 if obj.startswith (
"_")
or var.startswith (
"_"):
152 print(
"Skipping (%s, %s, %s) because of leading underscore." % \
155 GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
160 """Returns property assoicated with 'key' for variable 'var'
161 of object 'obj'. Returns 'None' if any of the above are not
163 return GenObject._objsDict.get (obj, {}).get (var, {}). get (key,
None)
168 """Adds an equivalence constraint. Must have at least one to
169 compare GO objects."""
170 if obj.startswith (
"_"):
171 print(
"Skipping (%s, %s) because of leading underscore." % \
174 GenObject._equivDict.setdefault (obj,[]).append ( (variable,
180 """Meant for debugging, but ok if called by user"""
182 pprint.pprint (GenObject._objsDict, indent=4)
184 pprint.pprint (GenObject._equivDict, indent=4)
186 pprint.pprint (GenObject._ntupleDict, indent=4)
188 pprint.pprint (GenObject._tofillDict, indent=4)
189 print(
"kitchenSink: ")
190 pprint.pprint (GenObject._kitchenSinkDict, indent=4)
191 print(
"rootClassDict")
192 pprint.pprint (GenObject._rootClassDict, indent=4)
197 """Returns a string of hex value of a checksum of input
199 return hex( reduce(
lambda x, y : x + y,
map(ord, str) ) )[2:]
204 """Returns the name of the equivalent Root object"""
205 return "go_" + objName
210 """Returns the name of the equivalent Root diff object"""
211 return "goDiff_" + objName
216 """Returns the name of the equivalent Root diff container
218 return "goDiffCont_" + objName
223 """Returns a string with the class header for a class
225 retval =
"\nclass %s\n{\n public:\n" % className
226 retval +=
" typedef std::vector< %s > Collection;\n\n" % className
229 retval +=
" %s()" % className
231 retval +=
" %s() :\n" % className
237 """Returns a stringg with the end of a class definition"""
238 retval =
"\n {}\n" + datadec +
"};\n"
239 retval +=
"#ifdef __MAKECINT__\n#pragma link C++ class " + \
240 "vector< %s >+;\n#endif\n\n" % className
246 """Returns a string containing the '.C' file necessary to
247 generate a shared object library with dictionary."""
248 if objName
not in GenObject._objsDict:
250 print(
"Error: GenObject does not know about object '%s'." % objName)
251 raise RuntimeError(
"Failed to create C++ class.")
252 className = GenObject.rootClassName (objName)
253 diffName = GenObject.rootDiffClassName (objName)
254 contName = GenObject.rootDiffContClassName (objName)
255 goClass = GenObject._setupClassHeader (className)
256 diffClass = GenObject._setupClassHeader (diffName)
257 contClass = GenObject._setupClassHeader (contName, noColon =
True)
258 goDataDec = diffDataDec = contDataDec =
"\n // data members\n"
260 for key
in sorted( GenObject._objsDict[objName].
keys() ):
261 if key.startswith (
"_"):
continue
262 varTypeList = GenObject._objsDict[objName][key]
263 cppType = GenObject._cppType[ varTypeList[
'varType'] ]
264 default = varTypeList[
'default']
270 goClass +=
" %s (%s)" % (key, default)
271 goDataDec +=
" %s %s;\n" % (cppType, key)
273 goType = varTypeList[
'varType']
274 if goType
in GenObject._basicSet:
276 diffClass +=
" %s (%s),\n" % (key, default)
277 diffDataDec +=
" %s %s;\n" % (cppType, key)
278 if goType == GenObject.types.string:
280 otherKey =
'other_' + key
281 diffClass +=
" %s (%s)" % (otherKey, default)
282 diffDataDec +=
" %s %s;\n" % (cppType, otherKey)
285 deltaKey =
'delta_' + key
286 diffClass +=
" %s (%s)" % (deltaKey, default)
287 diffDataDec +=
" %s %s;\n" % (cppType, deltaKey)
289 raise RuntimeError(
"Shouldn't be here yet.")
292 if GenObject.isSingleton (objName):
294 contDataDec +=
" %s diff;\n" % diffName
295 contDataDec +=
" void setDiff (const %s &rhs)" % diffName + \
299 contDataDec +=
" void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n"
300 contDataDec +=
" %s::Collection firstOnly;\n" % className
301 contDataDec +=
" %s::Collection secondOnly;\n" % className
302 contDataDec +=
" %s::Collection diff;\n" % diffName
305 goClass += GenObject._finishClassHeader (className, goDataDec)
306 diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
307 contClass += GenObject._finishClassHeader (contName, contDataDec)
308 if objName ==
'runevent':
312 return goClass + diffClass + contClass
317 """Loads Root shared object library associated with all
318 defined GenObjects. Will create library if necessary."""
319 print(
"Loading GO Root Library")
320 key =
"_loadedLibrary"
321 if GenObject._kitchenSinkDict.get (key):
325 GenObject._kitchenSinkDict[key] =
True
327 sourceCode =
"#include <string>\n#include <vector>\n" \
328 +
"using namespace std;\n"
329 for objClassName
in sorted( GenObject._objsDict.keys() ):
330 sourceCode += GenObject._createCppClass (objClassName)
331 GenObjectRootLibDir =
"genobjectrootlibs"
332 if not os.path.exists (GenObjectRootLibDir):
333 os.mkdir (GenObjectRootLibDir)
334 key = GenObject.checksum( sourceCode )
335 basename =
"%s_%s" % (
"GenObject", key)
336 SO =
"%s/%s_C" % (GenObjectRootLibDir, basename)
337 linuxSO =
"%s.so" % SO
338 windowsSO =
"%s.dll" % SO
339 if not os.path.exists (linuxSO)
and not os.path.exists (windowsSO):
341 filename =
"%s/%s.C" % (GenObjectRootLibDir, basename)
342 if not os.path.exists (filename):
343 print(
"creating .C file")
344 target = open (filename,
"w")
345 target.write (sourceCode)
348 print(
"%s exists" % filename)
351 ROOT.gSystem.CompileMacro (filename,
"k")
353 print(
"loading %s" % SO)
354 ROOT.gSystem.Load(SO)
360 """Makes sure that I know how to read root files I made myself"""
361 genObject =
"GenObject"
362 ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
363 ntupleDict[
'_useChain'] =
True
364 ntupleDict[
'_tree'] =
"goTree"
365 for objName
in GenObject._objsDict.keys():
366 rootObjName = GenObject.rootClassName (objName)
367 if GenObject.isSingleton (objName):
368 ntupleDict[objName] = objName
370 ntupleDict[objName] = objName +
"s"
371 tofillDict = GenObject._tofillDict.\
372 setdefault (genObject, {}).\
373 setdefault (objName, {})
374 for varName
in GenObject._objsDict [objName].
keys():
377 if varName.startswith (
"_"):
379 tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
385 """Makes all necessary preparations to load root files created
387 GenObject._tofillGenObject()
388 GenObject._loadGoRootLibrary()
393 """Returns tofill tuple made from string"""
394 parts = GenObject._dotRE.split (fillname)
397 parenMatch = GenObject._parenRE.search (part)
398 mode = GenObject._objFunc.obj
401 part = parenMatch.group (1)
402 mode = GenObject._objFunc.func
404 GenObject._convertStringToParameters \
405 (parenMatch.group (2))
406 partsList.append( (part, mode, parens) )
411 offset = handle.count (
'<') - handle.count(
'>')
415 print(
"Huh? Too few '<' for each '>' in handle '%'" % handle)
417 return handle +
' >' * offset
422 """Loads configuration file"""
426 modeEnum = Enumerate (
"none define tofill ntuple",
"mode")
429 config = open (configFile,
'r')
431 raise RuntimeError(
"Can't open configuration '%s'" % configFile)
432 for lineNum, fullLine
in enumerate (config):
433 fullLine = fullLine.strip()
435 line = GenObject._commentRE.sub (
'', fullLine)
437 if not GenObject._nonSpacesRE.search (line):
443 bracketMatch = GenObject._bracketRE.search (line)
446 section = bracketMatch.group(1)
447 words = GenObject._spacesRE.split( section )
449 raise RuntimeError(
"Don't understand line '%s'(%d)" \
450 % (fullLine, lineNum))
455 colonWords = GenObject._colonRE.split (objName)
456 if len (colonWords) > 3:
457 raise RuntimeError(
"Don't understand line '%s'(%d)" \
458 % (fullLine, lineNum))
459 if len (colonWords) == 1:
463 mode = modeEnum.define
465 if GenObject._singletonRE.match (word):
467 objsDict = GenObject._objsDict.\
468 setdefault (objName, {})
469 objsDict[
'_singleton'] =
True
473 print(
"I don't understand '%s' in section '%s' : %s" \
474 % (word, section, mode))
475 raise RuntimeError(
"Config file parser error '%s'(%d)" \
476 % (fullLine, lineNum))
477 elif len (colonWords) == 2:
481 mode = modeEnum.ntuple
482 ntupleDict = GenObject._ntupleDict.\
483 setdefault (colonWords[0], {})
484 ntupleDict[
'_tree'] = colonWords[1]
489 mode = modeEnum.tofill
490 objName = colonWords [0]
491 tupleName = colonWords [1]
492 tofillName = colonWords [2]
493 ntupleDict = GenObject._ntupleDict.\
494 setdefault (tupleName, {})
495 ntupleDict[objName] = tofillName
498 labelMatch = GenObject._labelRE.search (word)
500 label = tuple( GenObject._commaRE.\
501 split( labelMatch.group (1) ) )
502 ntupleDict.setdefault (
'_label', {}).\
503 setdefault (tofillName,
507 shortcutMatch = GenObject._shortcutRE.search (word)
511 parseVariableTofill ( shortcutMatch.\
513 ntupleDict.setdefault (
'_shortcut', {}).\
514 setdefault (tofillName,
518 typeMatch = GenObject._typeRE.search (word)
522 _fixLostGreaterThans (typeMatch.group(1))
523 handle = Handle( handleString )
524 ntupleDict.setdefault (
'_handle', {}).\
525 setdefault (tofillName,
529 aliasMatch = GenObject._aliasRE.search (word)
531 ntupleDict.setdefault (
'_alias', {}).\
532 setdefault (tofillName,
541 print(
"I don't understand '%s' in section '%s' : %s" \
542 % (word, section, mode))
543 raise RuntimeError(
"Config file parser error '%s'(%d)" \
544 % (fullLine, lineNum))
550 if modeEnum.none == mode:
552 print(
"I don't understand line '%s'." % fullLine)
553 raise RuntimeError(
"Config file parser error '%s'(%d)" \
554 % (fullLine, lineNum))
555 colonWords = GenObject._colonRE.split (line, 1)
556 if len (colonWords) < 2:
558 print(
"I don't understand line '%s'." % fullLine)
559 raise RuntimeError(
"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(
"Config file parser error '%s'(%d)" \
581 % (fullLine, lineNum))
583 halves[1] = float (halves[1])
584 if not halves[1] >= 0:
585 print(
"Problem with -equiv ",\
588 raise RuntimeError(
"Config file parser error '%s'(%d)" \
589 % (fullLine, lineNum))
590 GenObject.setEquivExpression (section,
597 typeMatch = GenObject._typeRE.search (word)
599 GenObject.types.isValidKey (typeMatch.group(1)):
600 varType = typeMatch.group(1).lower()
601 optionsDict[
'varType'] = GenObject.types (varType)
603 defaultMatch = GenObject._defaultRE.search (word)
605 optionsDict[
'default'] = defaultMatch.group(1)
607 precMatch = GenObject._precRE.search (word)
609 optionsDict[
'prec'] = float (precMatch.group (1))
611 formMatch = GenObject._formRE.search (word)
613 form = GenObject._doublePercentRE.\
614 sub (
'%', formMatch.group (1))
615 optionsDict[
'form'] = form
619 print(
"I don't understand '%s' in section '%s'." \
621 raise RuntimeError(
"Config file parser error '%s'(%d)" \
622 % (fullLine, lineNum))
623 GenObject.addObjectVariable (objName, varName, \
631 fillname, pieces = pieces[0], pieces[1:]
638 print(
"I don't understand '%s' in section '%s'." \
640 raise RuntimeError(
"Config file parser error '%s'(%d)" \
641 % (fullLine, lineNum))
642 tofillDict = GenObject._tofillDict.\
643 setdefault (tupleName, {}).\
644 setdefault (objName, {})
645 partsList = GenObject.parseVariableTofill (fillname)
646 tofillDict[varName] = [partsList, optionsDict]
648 for objName
in GenObject._objsDict:
650 if not GenObject.isSingleton (objName):
651 GenObject.addObjectVariable (objName,
'index',
652 varType = GenObject.types.int,
658 """Updates the definition used to go from a Root object to a
659 GenObject. 'tupleName' and 'objName' must already be defined."""
660 parts = GenObject._dotRE.split (fillname)
663 parenMatch = GenObject._parenRE.search (part)
664 mode = GenObject._objFunc.obj
667 part = parenMatch.group (1)
668 mode = GenObject._objFunc.func
670 GenObject._convertStringToParameters \
671 (parenMatch.group (2))
672 partsList.append( (part, mode, parens) )
673 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
679 """Evaluates function described in partsList on obj"""
680 for part
in partsList:
681 if debug: warn (part, spaces=15)
682 obj = getattr (obj, part[0])
683 if debug: warn (obj, spaces=15)
686 if GenObject._objFunc.func == part[1]:
689 if debug: warn (obj, spaces=18)
695 """Creates a GenObject copy of Root object"""
696 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
697 if objName ==
'runevent':
699 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
701 genObj = GenObject (objName)
703 if debug: warn (objName, spaces = 9)
704 for genVar, ntDict
in six.iteritems(tofillObjDict):
705 if debug: warn (genVar, spaces = 12)
707 partsList = ntDict[0]
709 obj = GenObject.evaluateFunction (origObj, partsList, debug)
710 if debug: warn (obj, spaces=12)
711 setattr (genObj, genVar, obj)
714 setattr (genObj,
'index', index)
720 """Copies information from goSourse into Root Object"""
721 objName = goSource._objName
722 for varName
in GenObject._objsDict [objName].
keys():
725 if varName.startswith (
"_"):
727 setattr( rootTarget, varName, goSource (varName) )
732 """Creates the approprite type of Root object and copies the
733 information into it from the GO object."""
734 objName = obj._objName
735 classObj = GenObject._rootClassDict.get (objName)
737 goName = GenObject.rootClassName (objName)
738 classObj = GenObject._rootClassDict[ goName ]
740 for varName
in GenObject._objsDict [objName].
keys():
741 setattr( rootObj, varName, obj (varName) )
747 """Given to GOs, it will create and fill the corresponding
749 objName = obj1._objName
752 diffName = GenObject.rootDiffClassName( objName )
753 rootObj = GenObject._rootClassDict[diffName]()
754 for varName
in GenObject._objsDict [objName].
keys():
755 if varName.startswith (
"_"):
continue
756 goType = GenObject._objsDict[objName][varName][
'varType']
757 if not goType
in GenObject._basicSet:
760 setattr( rootObj, varName, obj1 (varName) )
761 if goType == GenObject.types.string:
763 otherName =
'other_' + varName
764 if obj1 (varName) != obj2 (varName):
766 setattr( rootObj, otherName, obj2 (varName) )
769 setattr( rootObj, otherName,
'' )
772 deltaName =
'delta_' + varName
773 setattr( rootObj, deltaName,
774 obj2 (varName) - obj1 (varName) )
780 otherNtupleName = ""):
781 """Opens the output file, loads all of the necessary shared
782 object libraries, and returns the output file and tree. If
783 'otherNtupleName' is given, it will check and make sure that
784 only objects that are defined in it are written out."""
785 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
786 tree = ROOT.TTree (treeName, treeDescription)
787 GenObject._loadGoRootLibrary()
788 for objName
in sorted (GenObject._objsDict.keys()):
789 classname = GenObject.rootClassName (objName)
791 GenObject._rootClassDict[objName] = \
792 getattr (ROOT, classname)
793 if GenObject.isSingleton (objName):
795 obj = GenObject._rootObjectDict[objName] = rootObj()
796 tree.Branch (objName, classname, obj)
802 GenObject._rootObjectDict[objName] = \
803 ROOT.std.vector( rootObj )()
804 branchName = objName +
"s"
805 vecName =
"vector<%s>" % classname
806 tree.Branch( branchName, vecName, vec)
809 return rootfile, tree
814 diffDescription = '', missingDescription = ''):
815 """Opens the diff output file, loads all of the necessary
816 shared object libraries, and returns the output file and tree.b"""
817 rootfile = ROOT.TFile.Open (outputFile,
"recreate")
818 GenObject._loadGoRootLibrary()
820 diffTree = ROOT.TTree (diffName, diffDescription)
821 runEventObject = getattr (ROOT,
'go_runevent')()
822 diffTree.Branch (
'runevent',
'go_runevent', runEventObject)
823 GenObject._rootClassDict[
'runevent'] = runEventObject
824 for objName
in sorted (GenObject._objsDict.keys()):
825 if objName ==
'runevent':
continue
826 classname = GenObject.rootClassName (objName)
827 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
828 contName = GenObject.rootDiffContClassName (objName)
829 diffName = GenObject.rootDiffClassName (objName)
830 rootObj = GenObject._rootClassDict[contName] = \
831 getattr (ROOT, contName)
832 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
833 obj = GenObject._rootObjectDict[objName] = rootObj()
834 diffTree.Branch (objName, contName, obj)
836 missingTree = ROOT.TTree (missingName, missingDescription)
837 rootRunEventClass = getattr (ROOT,
'go_runevent')
838 firstOnly = GenObject._rootClassDict[
'firstOnly'] = \
839 ROOT.std.vector( rootRunEventClass ) ()
840 secondOnly = GenObject._rootClassDict[
'secondOnly'] = \
841 ROOT.std.vector( rootRunEventClass ) ()
842 missingTree.Branch (
'firstOnly',
'vector<go_runevent>', firstOnly)
843 missingTree.Branch (
'secondOnly',
'vector<go_runevent>', secondOnly)
844 return rootfile, diffTree, missingTree
849 """Fills root objects from GenObject 'event'"""
850 for objName, obj
in sorted (six.iteritems(event)):
851 if GenObject.isSingleton (objName):
853 GenObject._rootObjectCopy (obj,
854 GenObject._rootObjectDict[objName])
857 vec = GenObject._rootObjectDict[objName]
860 vec.push_back( GenObject._rootObjectClone (goObj) )
865 """Fills root diff containers from two GenObject 'event's"""
871 """Returns true if object is a singleton"""
872 return GenObject._objsDict[objName].get(
'_singleton')
877 onlyRunEvent = False):
878 """Loads event information from Root file (as interfaced by
879 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
880 'event' containing lists of objects or singleton object. If
881 'onlyRunEvent' is et to True, then only run and event number
882 is read in from the tree."""
883 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
884 tupleName = GenObject._kitchenSinkDict[eventTree][
'tupleName']
887 isChain = eventTree.__class__.__name__ ==
'TChain'
890 eventTree.GetEntry (eventIndex)
893 eventTree.to(eventIndex)
894 tofillDict = GenObject._tofillDict.get (tupleName)
895 ntupleDict = GenObject._ntupleDict.get (tupleName)
897 print(
"Don't know how to fill from '%s' ntuple." % tupleName)
899 eventBranchName = ntupleDict[
'runevent']
900 for objName
in tofillDict:
901 branchName = ntupleDict[objName]
902 if onlyRunEvent
and branchName != eventBranchName:
911 objects = getattr (eventTree, branchName)
914 shortcut = ntupleDict.get(
'_shortcut', {}).get(branchName)
916 objects = GenObject.evaluateFunction (eventTree, shortcut)
919 handle = ntupleDict.get(
'_handle', {}).get(branchName)
920 label = ntupleDict.get(
'_label' , {}).get(branchName)
921 if not handle
or not label:
922 raise RuntimeError(
"Missing handle or label for '%s'"\
924 if not eventTree.getByLabel (label, handle):
925 raise RuntimeError(
"not able to get %s for %s" \
926 % (label, branchName))
927 objects = handle.product()
929 if GenObject.isSingleton (objName):
930 event[objName] = GenObject.\
931 _genObjectClone (objName,
936 if debug: warn (objName, spaces = 3)
938 for index, obj
in enumerate (objects):
939 event[objName].
append( GenObject.\
940 _genObjectClone (objName,
954 """Prints out event dictionary. Mostly for debugging"""
956 for objName, obj
in sorted (six.iteritems(event)):
959 if GenObject.isSingleton (objName):
960 print(
"%s: %s" % (objName, obj))
962 for objName, obj
in sorted (six.iteritems(event)):
965 if not GenObject.isSingleton (objName):
967 print(
"%s:" % objName)
975 """runs SetAlias on all saved aliases"""
976 aliases = GenObject._ntupleDict[tupleName].get(
'_alias', {})
977 for name, alias
in six.iteritems(aliases):
978 eventTree.SetAlias (name, alias)
983 """Updates an alias for an object for a given tuple"""
984 aliasDict = GenObject._ntupleDict[tupleName][
'_alias']
985 if name
not in aliasDict:
986 raise RuntimeError(
"unknown name '%s' in tuple '%s'" % \
988 aliasDict[name] = alias
993 """Updates an label for an object for a given tuple"""
994 labelDict = GenObject._ntupleDict[tupleName][
'_label']
995 if objectName
not in labelDict:
996 raise RuntimeError(
"unknown name '%s' in tuple '%s'" % \
997 (objectName, tupleName))
998 label = tuple( GenObject._commaRE.split( label ) )
999 labelDict[objectName] = label
1004 """Given the tuple name and list of files, returns either a
1005 TChain or EventTree, and number of entries"""
1006 if "GenObject" == tupleName:
1007 GenObject.prepareToLoadGenObject()
1008 if not isinstance (files, list):
1011 ntupleDict = GenObject._ntupleDict[tupleName]
1012 treeName = ntupleDict[
"_tree"]
1013 if ntupleDict.get(
'_useChain'):
1014 chain = ROOT.TChain (treeName)
1015 for filename
in files:
1016 chain.AddFile (filename)
1017 numEntries = chain.GetEntries()
1020 chain = Events (files, forceEvent=
True)
1021 numEntries = chain.size()
1022 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1023 if numEventsWanted
and numEventsWanted < numEntries:
1024 numEntries = numEventsWanted
1025 chainDict[
'numEntries'] = numEntries
1026 chainDict[
'tupleName' ] = tupleName
1032 """Returns a dictionary of run, event tuples to entryIndicies"""
1034 for entryIndex
in range (numEntries):
1035 event = GenObject.loadEventFromTree (chain,
1037 onlyRunEvent =
True)
1038 runevent = event[
'runevent']
1039 reeDict[ GenObject._re2key (runevent) ] = entryIndex
1047 """Given a GO 'runevent' object, returns a sortable key"""
1050 if not GenObject._runEventListDone:
1051 GenObject._runEventListDone =
True
1052 ignoreSet = set( [
'run',
'event'] )
1053 for varName
in sorted (runevent.__dict__.keys()):
1054 if varName.startswith (
'_')
or varName
in ignoreSet:
1056 form = runevent.getVariableProperty (varName,
"form")
1059 GenObject._runEventList.append ((varName, form))
1060 key =
'run:%d event:%d' % (runevent.run, runevent.event)
1061 for items
in GenObject._runEventList:
1063 form =
' %s:%s' % (varName, items[1])
1064 key += form % runevent.getVariableProperty (varName)
1070 """Given a key, returns a GO 'runevent' object"""
1072 runevent = GenObject (
'runevent')
1073 words = GenObject._spacesRE.split (key)
1075 match = GenObject._singleColonRE.search (word)
1080 runevent.__setattr__ (match.group(1),
int( match.group(2) ))
1086 """Compares the keys of the two dicts and returns three sets:
1087 the overlap, first but not second, and second but not first."""
1092 for key
in firstDict.keys():
1093 if key
in secondDict:
1099 for key
in secondDict.keys():
1100 if key
not in firstDict:
1101 secondOnly.add (key)
1103 return overlap, firstOnly, secondOnly
1108 """Finds the equivalent objects in the two vectors"""
1109 len1, len2 = len (vec1), len (vec2)
1110 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1111 if not len1
or not len2:
1114 noMatch1Set = set(
range(len1) )
1116 noMatch1Set = set ()
1118 noMatch2Set = set(
range(len2) )
1120 noMatch2Set = set ()
1121 if debug: warn (
"Nothing found", sapces=6)
1122 return set(), noMatch1Set, noMatch2Set
1123 objName = vec1[0]._objName
1124 equivList = GenObject._equivDict[objName]
1128 if GenObject._kitchenSinkDict.get (
'strictPairing')
or \
1129 equivList == [(
'index', 0)]:
1131 matchedSet = set (zip ( list(
range( min (len1, len2))),
1132 list(
range( min (len1, len2))) ) )
1136 noMatch1Set = set (
range(len2, len1 + 1))
1141 noMatch2Set = set (
range(len1, len2 + 1))
1144 return matchedSet, noMatch1Set, noMatch2Set
1159 for index1
in range (len1):
1162 for index2
in range (len2):
1166 for equiv
in equivList:
1167 var, precision = equiv[0], equiv[1]
1172 value = abs (val1 - val2) / precision
1181 objList.append( (total, index2) )
1183 firstDict[index1] = objList
1186 for index2
in range (len2):
1189 for index1
in range (len1):
1193 for equiv
in equivList:
1194 var, precision = equiv[0], equiv[1]
1199 value = abs (val2 - val1) / precision
1208 objList.append( (total, index1) )
1210 secondDict[index2] = objList
1215 firstDictKeys = sorted (firstDict.keys())
1216 for index1
in firstDictKeys:
1217 list1 = firstDict[index1]
1221 noMatch1Set.add (index1)
1227 list2 = secondDict.get (index2, [])
1228 if len(list2)
and list2[0][1] == index1:
1229 matchedSet.add( (index1, index2) )
1231 del firstDict[index1]
1232 del secondDict[index2]
1235 noMatch1Set.add (index1)
1236 noMatch2Set = set( secondDict.keys() )
1237 return matchedSet, noMatch1Set, noMatch2Set
1242 """Compares all of the variables making sure they are the same
1243 on the two objects."""
1244 objName = item1._objName
1246 relative = GenObject._kitchenSinkDict.get (
'relative',
False)
1247 for varName
in GenObject._objsDict[objName].
keys():
1248 prec = item1.getVariableProperty (varName,
'prec')
1252 val1 = item1(varName)
1253 val2 = item2(varName)
1254 numerator = 2 * abs (val1 - val2)
1255 denominator =
abs(val1) +
abs(val2)
1260 value = numerator / denominator
1263 problems[varName] = value
1265 value =
abs( item1(varName) - item2(varName) )
1268 problems[varName] = value
1271 if item1(varName) != item2(varName):
1273 val1, val2 = item1(varName), item2(varName)
1275 val1, val2 = val2, val1
1276 problems[varName] =
"%s != %s" % (val1, val2)
1283 """For debugging purposes only. Will deliberately change
1284 values of first tree to verify that script is correctly
1285 finding problems."""
1286 for objName
in sorted (event.keys()):
1287 if "runevent" == objName:
1290 if GenObject.isSingleton (objName):
1294 for obj
in event[objName]:
1296 for varName
in GenObject._objsDict[objName].
keys():
1297 if isinstance (obj.__dict__[varName], str):
1300 randNumber = random.random()
1302 if randNumber < GenObject._kitchenSinkDict[
'blurRate']:
1303 print(
" %s: changing '%s' of '%s:%d'" \
1304 % (where, varName, obj._objName, count))
1307 obj.__dict__[varName] += value
1312 """Given all of the necessary information, this routine will
1313 go through and compare two trees making sure they are
1314 'identical' within requested precision. If 'diffOutputName'
1315 is passed in, a root file with a diffTree and missingTree will
1317 print(
"Comparing Two Trees")
1318 diffOutputName = kwargs.get (
'diffOutputName')
1319 tupleName1 = GenObject._kitchenSinkDict[chain1][
'tupleName']
1320 numEntries1 = GenObject._kitchenSinkDict[chain1][
'numEntries']
1321 tupleName2 = GenObject._kitchenSinkDict[chain2][
'tupleName']
1322 numEntries2 = GenObject._kitchenSinkDict[chain2][
'numEntries']
1323 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1324 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1325 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1326 overlap, firstOnly, secondOnly = \
1327 GenObject.compareRunEventDicts (ree1, ree2)
1329 rootfile, diffTree, missingTree = \
1330 GenObject.setupDiffOutputTree (diffOutputName,
1334 vec = GenObject._rootClassDict[
'firstOnly']
1335 for key
in firstOnly:
1336 runevent = GenObject._key2re (key)
1337 vec.push_back( GenObject._rootObjectClone( runevent ) )
1339 vec = GenObject._rootClassDict[
'secondOnly']
1340 for key
in secondOnly:
1341 runevent = GenObject._key2re (key)
1342 vec.push_back( GenObject._rootObjectClone( runevent ) )
1346 resultsDict.setdefault (
'_runevent', {})[
'firstOnly'] = \
1349 resultsDict.setdefault (
'_runevent', {})[
'secondOnly'] = \
1351 resultsDict[
'eventsCompared'] = len (overlap)
1352 for reTuple
in sorted(overlap):
1356 GenObject._key2re (reTuple,
1357 GenObject._rootClassDict[
'runevent'])
1358 if debug: warn (
'event1', blankLines = 3)
1359 event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1360 if debug: warn (
'event2', blankLines = 3)
1361 event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1362 if GenObject._kitchenSinkDict.get(
'printEvent'):
1364 GenObject.printEvent (event1)
1366 GenObject.printEvent (event2)
1367 if GenObject._kitchenSinkDict.get(
'blur'):
1369 GenObject.blurEvent (event1,
1370 GenObject._kitchenSinkDict[
'blur'],
1372 for objName
in sorted (event1.keys()):
1373 if "runevent" == objName:
1376 if not GenObject._equivDict.get (objName):
1380 if GenObject.isSingleton (objName):
1387 rootObj = GenObject._rootObjectDict[objName]
1389 vec1 = event1[objName]
1390 vec2 = event2[objName]
1391 matchedSet, noMatch1Set, noMatch2Set = \
1392 GenObject.pairEquivalentObjects (vec1, vec2)
1393 if noMatch1Set
or noMatch2Set:
1396 count1 = len (noMatch1Set)
1397 count2 = len (noMatch2Set)
1398 key = (count1, count2)
1399 countDict = resultsDict.\
1400 setdefault (objName, {}).\
1401 setdefault (
'_missing', {})
1402 if key
in countDict:
1409 for index
in sorted(list(noMatch1Set)):
1410 goObj = vec1 [index]
1411 rootObj.firstOnly.push_back ( GenObject.\
1415 for index
in sorted(list(noMatch2Set)):
1416 goObj = vec2 [index]
1417 rootObj.secondOnly.push_back ( GenObject.\
1422 for pair
in sorted(list(matchedSet)):
1424 rootDiffObj = GenObject._rootDiffObject \
1425 ( vec1[ pair[1 - 1] ],
1426 vec2[ pair[2 - 1] ] )
1427 rootObj.diff.push_back ( rootDiffObj )
1428 problems = GenObject.\
1429 compareTwoItems (vec1[ pair[1 - 1] ],
1430 vec2[ pair[2 - 1] ])
1433 for varName
in problems.keys():
1434 countDict = resultsDict.\
1435 setdefault (objName, {}).\
1436 setdefault (
'_var', {})
1437 if varName
in countDict:
1438 countDict[varName] += 1
1440 countDict[varName] = 1
1441 key =
'count_%s' % objName
1442 if key
not in resultsDict:
1443 resultsDict[key] = 0
1444 resultsDict[key] += len (matchedSet)
1463 """Saves a chain as a GO tree"""
1464 print(
"saveTupleAs")
1465 rootfile, tree = GenObject.setupOutputTree (rootFile,
"goTree")
1466 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1467 for entryIndex
in range (numEntries):
1468 event = GenObject.loadEventFromTree (chain, entryIndex)
1469 if GenObject._kitchenSinkDict.get(
'blur'):
1470 where =
"run %d event %d" % (event[
'runevent'].run,
1471 event[
'runevent'].event)
1472 if random.random() < GenObject._kitchenSinkDict.get(
'blur'):
1474 print(
"Dropping", where)
1476 GenObject.blurEvent (event,
1477 GenObject._kitchenSinkDict[
'blur'],
1480 if GenObject._kitchenSinkDict.get(
'printEvent'):
1481 GenObject.printEvent (event)
1482 GenObject._fillRootObjects (event)
1490 """Sets a global flag in _kitchenSinkDict"""
1491 GenObject._kitchenSinkDict [key] = value
1496 """Prints out all events to stdout"""
1497 numEntries = GenObject._kitchenSinkDict[chain][
'numEntries']
1498 debug = GenObject._kitchenSinkDict.get (
'debug',
False)
1499 if debug: warn (numEntries)
1500 for entryIndex
in range (numEntries):
1501 if debug: warn (entryIndex, spaces=3)
1502 event = GenObject.loadEventFromTree (chain, entryIndex)
1503 GenObject.printEvent (event)
1504 if debug:
warn(spaces=3)
1508 """Convert comma-separated string into a python list of
1509 parameters. Currently only understands strings, floats, and
1512 words = GenObject._commaRE.split (string)
1516 match = GenObject._singleQuoteRE.search (word)
1518 retval.append (match.group (1))
1520 match = GenObject._doubleQuoteRE.search (word)
1522 retval.append (match.group (1))
1537 raise RuntimeError(
"Unknown parameter '%s'." % word)
1547 """Class initializer"""
1548 if objName
not in GenObject._objsDict:
1551 print(
"Error: GenObject does not know about object '%s'." % objName)
1552 raise RuntimeError(
"Failed to create GenObject object.")
1558 if key.startswith (
"_"):
1560 self.
setValue (key, varDict[
'default'])
1564 """Wrapper for __setattr___"""
1569 """ Returns property assoicated with 'key' for variable 'var'
1570 of object of the same type as 'self'. Returns 'None' if 'var'
1571 or 'key' is not defined."""
1572 return GenObject._objsDict.get (self.
_objName,
1573 {}).get (var, {}). get (key,
None)
1577 """Controls setting of values."""
1578 if name.startswith (
"_"):
1580 object.__setattr__ (self, name, value)
1587 print(
"Warning: '%s' for class '%s' not setup. Skipping." % \
1592 if GenObject.types.int == varType:
1600 elif GenObject.types.long == varType:
1604 value = long (value)
1607 value = long(
float( value ) )
1608 elif GenObject.types.float == varType:
1610 value = float (value)
1611 elif GenObject.types.string == varType:
1615 object.__setattr__ (self, name, value)
1619 """Makes object callable"""
1620 return object.__getattribute__ (self, key)
1624 """String representation"""
1626 for varName, value
in sorted (six.iteritems(self.__dict__)):
1627 if varName.startswith (
'_'):
continue
1630 format =
"%s:%s " % (varName, form)
1631 retval = retval + format % value
1633 retval = retval +
"%s:%s " % (varName, value)