File indexing completed on 2024-04-06 12:33:41
0001 from __future__ import print_function
0002
0003
0004
0005
0006
0007 from builtins import range
0008 from FWCore.Utilities.Enumerate import Enumerate
0009 from DataFormats.FWLite import Events, Handle
0010 import re
0011 import os
0012 import copy
0013 import pprint
0014 import random
0015 import sys
0016 import inspect
0017 import ROOT
0018 from functools import reduce
0019 ROOT.gROOT.SetBatch()
0020
0021
0022 filenameRE = re.compile (r'.+/Validation/Tools/')
0023
0024 quietWarn = False
0025
0026 def setQuietWarn (quiet = True):
0027 global quietWarn
0028 quietWarn = quiet
0029
0030
0031 def warn (*args, **kwargs):
0032 """print out warning with line number and rest of arguments"""
0033 if quietWarn: return
0034 frame = inspect.stack()[1]
0035 filename = frame[1]
0036 lineNum = frame[2]
0037
0038 filename = filenameRE.sub ('', filename)
0039
0040 blankLines = kwargs.get('blankLines', 0)
0041 if blankLines:
0042 print('\n' * blankLines)
0043 spaces = kwargs.get('spaces', 0)
0044 if spaces:
0045 print(' ' * spaces, end=' ')
0046 if len (args):
0047 print("%s (%s): " % (filename, lineNum), end=' ')
0048 for arg in args:
0049 print(arg, end=' ')
0050 print()
0051 else:
0052 print("%s (%s):" % (filename, lineNum))
0053
0054
0055 class GenObject (object):
0056 """Infrastruture to define general objects and their attributes."""
0057
0058
0059
0060
0061
0062 types = Enumerate ("float int long string", "type")
0063 _objFunc = Enumerate ("obj func", "of")
0064 _cppType = dict ( {types.float : 'double',
0065 types.int : 'int',
0066 types.long : 'long',
0067 types.string : 'std::string' } )
0068 _basicSet = set( [types.float, types.int, types.float,
0069 types.string] )
0070 _defaultValue = dict ( {types.float : 0.,
0071 types.int : 0,
0072 types.long : 0,
0073 types.string : '""' } )
0074 _objsDict = {}
0075 _equivDict = {}
0076 _ntupleDict = {}
0077 _tofillDict = {}
0078 _rootObjectDict = {}
0079
0080 _rootClassDict = {}
0081
0082 _kitchenSinkDict = {}
0083 _runEventList = []
0084 _runEventListDone = False
0085 uselessReturnCode = 1 << 7
0086
0087
0088
0089
0090 _nonSpacesRE = re.compile (r'\S')
0091 _colonRE = re.compile (r'\s*:\s*')
0092 _singleColonRE = re.compile (r'(.+?):(.+)')
0093 _doubleColonRE = re.compile (r'(.+?):(.+?):(.+)')
0094 _doublePercentRE = re.compile (r'%%')
0095 _parenRE = re.compile (r'(.+)\((.*)\)')
0096 _spacesRE = re.compile (r'\s+')
0097 _dotRE = re.compile (r'\s*\.\s*')
0098 _commaRE = re.compile (r'\s*,\s*')
0099 _singleQuoteRE = re.compile (r'^\'(.+)\'$')
0100 _doubleQuoteRE = re.compile (r'^\"(.+)\"$')
0101 _bracketRE = re.compile (r'\[\s*(.+?)\s*\]')
0102 _commentRE = re.compile (r'#.+$')
0103 _aliasRE = re.compile (r'alias=(\S+)', re.IGNORECASE)
0104 _labelRE = re.compile (r'label=(\S+)', re.IGNORECASE)
0105 _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
0106 _singletonRE = re.compile (r'singleton', re.IGNORECASE)
0107 _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
0108 _defaultRE = re.compile (r'default=(\S+)', re.IGNORECASE)
0109 _shortcutRE = re.compile (r'shortcut=(\S+)', re.IGNORECASE)
0110 _precRE = re.compile (r'prec=(\S+)', re.IGNORECASE)
0111 _formRE = re.compile (r'form=(\S+)', re.IGNORECASE)
0112 _nonAlphaRE = re.compile (r'\W')
0113 _percentAsciiRE = re.compile (r'%([0-9a-fA-F]{2})')
0114
0115
0116
0117
0118
0119 @staticmethod
0120 def char2ascii (match):
0121 return "%%%02x" % ord (match.group(0))
0122
0123 @staticmethod
0124 def ascii2char (match):
0125 return chr( int( match.group(1), 16 ) )
0126
0127 @staticmethod
0128 def encodeNonAlphanumerics (line):
0129 """Use a web like encoding of characters that are non-alphanumeric"""
0130 return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
0131
0132 @staticmethod
0133 def decodeNonAlphanumerics (line):
0134 """Decode lines encoded with encodeNonAlphanumerics()"""
0135 return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
0136
0137
0138 @staticmethod
0139 def addObjectVariable (obj, var, **optionsDict):
0140 """ User passes in in object and variable names."""
0141 if 'varType' not in optionsDict:
0142 optionsDict['varType'] = GenObject.types.float
0143 varType = optionsDict['varType']
0144 if not GenObject.types.isValidValue (varType):
0145 print("Type '%s' not valid. Skipping (%s, %s, %s)." % \
0146 (varType, obj, var, varType))
0147 return
0148 if 'default' not in optionsDict:
0149 optionsDict['default'] = GenObject._defaultValue[varType]
0150 if obj.startswith ("_") or var.startswith ("_"):
0151 print("Skipping (%s, %s, %s) because of leading underscore." % \
0152 (obj, var, varType))
0153 return
0154 GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
0155
0156
0157 @staticmethod
0158 def getVariableProperty (obj, var, key):
0159 """Returns property assoicated with 'key' for variable 'var'
0160 of object 'obj'. Returns 'None' if any of the above are not
0161 defined."""
0162 return GenObject._objsDict.get (obj, {}).get (var, {}). get (key, None)
0163
0164
0165 @staticmethod
0166 def setEquivExpression (obj, variable, precision):
0167 """Adds an equivalence constraint. Must have at least one to
0168 compare GO objects."""
0169 if obj.startswith ("_"):
0170 print("Skipping (%s, %s) because of leading underscore." % \
0171 (obj, expression))
0172 return
0173 GenObject._equivDict.setdefault (obj,[]).append ( (variable,
0174 precision) )
0175
0176
0177 @staticmethod
0178 def printGlobal():
0179 """Meant for debugging, but ok if called by user"""
0180 print("objs: ")
0181 pprint.pprint (GenObject._objsDict, indent=4)
0182 print("equiv: ")
0183 pprint.pprint (GenObject._equivDict, indent=4)
0184 print("ntuple: ")
0185 pprint.pprint (GenObject._ntupleDict, indent=4)
0186 print("tofill: ")
0187 pprint.pprint (GenObject._tofillDict, indent=4)
0188 print("kitchenSink: ")
0189 pprint.pprint (GenObject._kitchenSinkDict, indent=4)
0190 print("rootClassDict")
0191 pprint.pprint (GenObject._rootClassDict, indent=4)
0192
0193
0194 @staticmethod
0195 def checksum (str):
0196 """Returns a string of hex value of a checksum of input
0197 string."""
0198 return hex( reduce( lambda x, y : x + y, map(ord, str) ) )[2:]
0199
0200
0201 @staticmethod
0202 def rootClassName (objName):
0203 """Returns the name of the equivalent Root object"""
0204 return "go_" + objName
0205
0206
0207 @staticmethod
0208 def rootDiffClassName (objName):
0209 """Returns the name of the equivalent Root diff object"""
0210 return "goDiff_" + objName
0211
0212
0213 @staticmethod
0214 def rootDiffContClassName (objName):
0215 """Returns the name of the equivalent Root diff container
0216 object"""
0217 return "goDiffCont_" + objName
0218
0219
0220 @staticmethod
0221 def _setupClassHeader (className, noColon = False):
0222 """Returns a string with the class header for a class
0223 'classname'"""
0224 retval = "\nclass %s\n{\n public:\n" % className
0225 retval += " typedef std::vector< %s > Collection;\n\n" % className
0226
0227 if noColon:
0228 retval += " %s()" % className
0229 else:
0230 retval += " %s() :\n" % className
0231 return retval
0232
0233
0234 @staticmethod
0235 def _finishClassHeader (className, datadec):
0236 """Returns a stringg with the end of a class definition"""
0237 retval = "\n {}\n" + datadec + "};\n"
0238 retval += "#ifdef __MAKECINT__\n#pragma link C++ class " + \
0239 "vector< %s >+;\n#endif\n\n" % className
0240 return retval
0241
0242
0243 @staticmethod
0244 def _createCppClass (objName):
0245 """Returns a string containing the '.C' file necessary to
0246 generate a shared object library with dictionary."""
0247 if objName not in GenObject._objsDict:
0248
0249 print("Error: GenObject does not know about object '%s'." % objName)
0250 raise RuntimeError("Failed to create C++ class.")
0251 className = GenObject.rootClassName (objName)
0252 diffName = GenObject.rootDiffClassName (objName)
0253 contName = GenObject.rootDiffContClassName (objName)
0254 goClass = GenObject._setupClassHeader (className)
0255 diffClass = GenObject._setupClassHeader (diffName)
0256 contClass = GenObject._setupClassHeader (contName, noColon = True)
0257 goDataDec = diffDataDec = contDataDec = "\n // data members\n"
0258 first = True
0259 for key in sorted( GenObject._objsDict[objName].keys() ):
0260 if key.startswith ("_"): continue
0261 varTypeList = GenObject._objsDict[objName][key]
0262 cppType = GenObject._cppType[ varTypeList['varType'] ]
0263 default = varTypeList['default']
0264 if first:
0265 first = False
0266 else:
0267 goClass += ",\n"
0268 diffClass += ',\n'
0269 goClass += " %s (%s)" % (key, default)
0270 goDataDec += " %s %s;\n" % (cppType, key)
0271
0272 goType = varTypeList['varType']
0273 if goType in GenObject._basicSet:
0274
0275 diffClass += " %s (%s),\n" % (key, default)
0276 diffDataDec += " %s %s;\n" % (cppType, key)
0277 if goType == GenObject.types.string:
0278
0279 otherKey = 'other_' + key
0280 diffClass += " %s (%s)" % (otherKey, default)
0281 diffDataDec += " %s %s;\n" % (cppType, otherKey)
0282 else:
0283
0284 deltaKey = 'delta_' + key
0285 diffClass += " %s (%s)" % (deltaKey, default)
0286 diffDataDec += " %s %s;\n" % (cppType, deltaKey)
0287 else:
0288 raise RuntimeError("Shouldn't be here yet.")
0289
0290
0291 if GenObject.isSingleton (objName):
0292
0293 contDataDec += " %s diff;\n" % diffName
0294 contDataDec += " void setDiff (const %s &rhs)" % diffName + \
0295 " { diff = rhs; }\n"
0296 else:
0297
0298 contDataDec += " void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n"
0299 contDataDec += " %s::Collection firstOnly;\n" % className
0300 contDataDec += " %s::Collection secondOnly;\n" % className
0301 contDataDec += " %s::Collection diff;\n" % diffName
0302
0303
0304 goClass += GenObject._finishClassHeader (className, goDataDec)
0305 diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
0306 contClass += GenObject._finishClassHeader (contName, contDataDec)
0307 if objName == 'runevent':
0308
0309 diffClass = ''
0310 contClass = ''
0311 return goClass + diffClass + contClass
0312
0313
0314 @staticmethod
0315 def _loadGoRootLibrary ():
0316 """Loads Root shared object library associated with all
0317 defined GenObjects. Will create library if necessary."""
0318 print("Loading GO Root Library")
0319 key = "_loadedLibrary"
0320 if GenObject._kitchenSinkDict.get (key):
0321
0322 return
0323
0324 GenObject._kitchenSinkDict[key] = True
0325
0326 sourceCode = "#include <string>\n#include <vector>\n" \
0327 + "using namespace std;\n"
0328 for objClassName in sorted( GenObject._objsDict.keys() ):
0329 sourceCode += GenObject._createCppClass (objClassName)
0330 GenObjectRootLibDir = "genobjectrootlibs"
0331 if not os.path.exists (GenObjectRootLibDir):
0332 os.mkdir (GenObjectRootLibDir)
0333 key = GenObject.checksum( sourceCode )
0334 basename = "%s_%s" % ("GenObject", key)
0335 SO = "%s/%s_C" % (GenObjectRootLibDir, basename)
0336 linuxSO = "%s.so" % SO
0337 windowsSO = "%s.dll" % SO
0338 if not os.path.exists (linuxSO) and not os.path.exists (windowsSO):
0339 print("creating SO")
0340 filename = "%s/%s.C" % (GenObjectRootLibDir, basename)
0341 if not os.path.exists (filename):
0342 print("creating .C file")
0343 target = open (filename, "w")
0344 target.write (sourceCode)
0345 target.close()
0346 else:
0347 print("%s exists" % filename)
0348
0349
0350 ROOT.gSystem.CompileMacro (filename, "k")
0351 else:
0352 print("loading %s" % SO)
0353 ROOT.gSystem.Load(SO)
0354 return
0355
0356
0357 @staticmethod
0358 def _tofillGenObject():
0359 """Makes sure that I know how to read root files I made myself"""
0360 genObject = "GenObject"
0361 ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
0362 ntupleDict['_useChain'] = True
0363 ntupleDict['_tree'] = "goTree"
0364 for objName in GenObject._objsDict.keys():
0365 rootObjName = GenObject.rootClassName (objName)
0366 if GenObject.isSingleton (objName):
0367 ntupleDict[objName] = objName
0368 else:
0369 ntupleDict[objName] = objName + "s"
0370 tofillDict = GenObject._tofillDict.\
0371 setdefault (genObject, {}).\
0372 setdefault (objName, {})
0373 for varName in GenObject._objsDict [objName].keys():
0374
0375
0376 if varName.startswith ("_"):
0377 continue
0378 tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
0379 {}]
0380
0381
0382 @staticmethod
0383 def prepareToLoadGenObject():
0384 """Makes all necessary preparations to load root files created
0385 by GenObject."""
0386 GenObject._tofillGenObject()
0387 GenObject._loadGoRootLibrary()
0388
0389
0390 @staticmethod
0391 def parseVariableTofill (fillname):
0392 """Returns tofill tuple made from string"""
0393 parts = GenObject._dotRE.split (fillname)
0394 partsList = []
0395 for part in parts:
0396 parenMatch = GenObject._parenRE.search (part)
0397 mode = GenObject._objFunc.obj
0398 parens = []
0399 if parenMatch:
0400 part = parenMatch.group (1)
0401 mode = GenObject._objFunc.func
0402 parens = \
0403 GenObject._convertStringToParameters \
0404 (parenMatch.group (2))
0405 partsList.append( (part, mode, parens) )
0406 return partsList
0407
0408 @staticmethod
0409 def _fixLostGreaterThans (handle):
0410 offset = handle.count ('<') - handle.count('>')
0411 if not offset:
0412 return handle
0413 if offset < 0:
0414 print("Huh? Too few '<' for each '>' in handle '%'" % handle)
0415 return handle
0416 return handle + ' >' * offset
0417
0418
0419 @staticmethod
0420 def loadConfigFile (configFile):
0421 """Loads configuration file"""
0422 objName = ""
0423 tupleName = ""
0424 tofillName = ""
0425 modeEnum = Enumerate ("none define tofill ntuple", "mode")
0426 mode = modeEnum.none
0427 try:
0428 config = open (configFile, 'r')
0429 except:
0430 raise RuntimeError("Can't open configuration '%s'" % configFile)
0431 for lineNum, fullLine in enumerate (config):
0432 fullLine = fullLine.strip()
0433
0434 line = GenObject._commentRE.sub ('', fullLine)
0435
0436 if not GenObject._nonSpacesRE.search (line):
0437
0438 continue
0439
0440
0441
0442 bracketMatch = GenObject._bracketRE.search (line)
0443 if bracketMatch:
0444
0445 section = bracketMatch.group(1)
0446 words = GenObject._spacesRE.split( section )
0447 if len (words) < 1:
0448 raise RuntimeError("Don't understand line '%s'(%d)" \
0449 % (fullLine, lineNum))
0450
0451
0452 objName = words[0]
0453 words = words[1:]
0454 colonWords = GenObject._colonRE.split (objName)
0455 if len (colonWords) > 3:
0456 raise RuntimeError("Don't understand line '%s'(%d)" \
0457 % (fullLine, lineNum))
0458 if len (colonWords) == 1:
0459
0460
0461
0462 mode = modeEnum.define
0463 for word in words:
0464 if GenObject._singletonRE.match (word):
0465
0466 objsDict = GenObject._objsDict.\
0467 setdefault (objName, {})
0468 objsDict['_singleton'] = True
0469 continue
0470
0471
0472 print("I don't understand '%s' in section '%s' : %s" \
0473 % (word, section, mode))
0474 raise RuntimeError("Config file parser error '%s'(%d)" \
0475 % (fullLine, lineNum))
0476 elif len (colonWords) == 2:
0477
0478
0479
0480 mode = modeEnum.ntuple
0481 ntupleDict = GenObject._ntupleDict.\
0482 setdefault (colonWords[0], {})
0483 ntupleDict['_tree'] = colonWords[1]
0484 else:
0485
0486
0487
0488 mode = modeEnum.tofill
0489 objName = colonWords [0]
0490 tupleName = colonWords [1]
0491 tofillName = colonWords [2]
0492 ntupleDict = GenObject._ntupleDict.\
0493 setdefault (tupleName, {})
0494 ntupleDict[objName] = tofillName
0495 for word in words:
0496
0497 labelMatch = GenObject._labelRE.search (word)
0498 if labelMatch:
0499 label = tuple( GenObject._commaRE.\
0500 split( labelMatch.group (1) ) )
0501 ntupleDict.setdefault ('_label', {}).\
0502 setdefault (tofillName,
0503 label)
0504 continue
0505
0506 shortcutMatch = GenObject._shortcutRE.search (word)
0507 if shortcutMatch:
0508 shortcutFill = \
0509 GenObject.\
0510 parseVariableTofill ( shortcutMatch.\
0511 group(1) )
0512 ntupleDict.setdefault ('_shortcut', {}).\
0513 setdefault (tofillName,
0514 shortcutFill)
0515 continue
0516
0517 typeMatch = GenObject._typeRE.search (word)
0518 if typeMatch:
0519 handleString = \
0520 GenObject.\
0521 _fixLostGreaterThans (typeMatch.group(1))
0522 handle = Handle( handleString )
0523 ntupleDict.setdefault ('_handle', {}).\
0524 setdefault (tofillName,
0525 handle)
0526 continue
0527
0528 aliasMatch = GenObject._aliasRE.search (word)
0529 if aliasMatch:
0530 ntupleDict.setdefault ('_alias', {}).\
0531 setdefault (tofillName,
0532 aliasMatch.\
0533 group(1))
0534 continue
0535
0536 if word == '>':
0537 continue
0538
0539
0540 print("I don't understand '%s' in section '%s' : %s" \
0541 % (word, section, mode))
0542 raise RuntimeError("Config file parser error '%s'(%d)" \
0543 % (fullLine, lineNum))
0544
0545
0546
0547 else:
0548
0549 if modeEnum.none == mode:
0550
0551 print("I don't understand line '%s'." % fullLine)
0552 raise RuntimeError("Config file parser error '%s'(%d)" \
0553 % (fullLine, lineNum))
0554 colonWords = GenObject._colonRE.split (line, 1)
0555 if len (colonWords) < 2:
0556
0557 print("I don't understand line '%s'." % fullLine)
0558 raise RuntimeError("Config file parser error '%s'(%d)" \
0559 % (fullLine, lineNum))
0560 varName = colonWords[0]
0561 option = colonWords[1]
0562 if option:
0563 pieces = GenObject._spacesRE.split (option)
0564 else:
0565 pieces = []
0566 if modeEnum.define == mode:
0567
0568
0569
0570
0571 if varName.startswith("-"):
0572
0573 if "-equiv" == varName.lower():
0574 for part in pieces:
0575 halves = part.split (",")
0576 if 2 != len (halves):
0577 print("Problem with -equiv '%s' in '%s'" % \
0578 (part, section))
0579 raise RuntimeError("Config file parser error '%s'(%d)" \
0580 % (fullLine, lineNum))
0581 if halves[1]:
0582 halves[1] = float (halves[1])
0583 if not halves[1] >= 0:
0584 print("Problem with -equiv ",\
0585 "'%s' in '%s'" % \
0586 (part, section))
0587 raise RuntimeError("Config file parser error '%s'(%d)" \
0588 % (fullLine, lineNum))
0589 GenObject.setEquivExpression (section,
0590 halves[0],
0591 halves[1])
0592 continue
0593
0594 optionsDict = {}
0595 for word in pieces:
0596 typeMatch = GenObject._typeRE.search (word)
0597 if typeMatch and \
0598 GenObject.types.isValidKey (typeMatch.group(1)):
0599 varType = typeMatch.group(1).lower()
0600 optionsDict['varType'] = GenObject.types (varType)
0601 continue
0602 defaultMatch = GenObject._defaultRE.search (word)
0603 if defaultMatch:
0604 optionsDict['default'] = defaultMatch.group(1)
0605 continue
0606 precMatch = GenObject._precRE.search (word)
0607 if precMatch:
0608 optionsDict['prec'] = float (precMatch.group (1))
0609 continue
0610 formMatch = GenObject._formRE.search (word)
0611 if formMatch:
0612 form = GenObject._doublePercentRE.\
0613 sub ('%', formMatch.group (1))
0614 optionsDict['form'] = form
0615 continue
0616
0617
0618 print("I don't understand '%s' in section '%s'." \
0619 % (word, option))
0620 raise RuntimeError("Config file parser error '%s'(%d)" \
0621 % (fullLine, lineNum))
0622 GenObject.addObjectVariable (objName, varName, \
0623 **optionsDict)
0624 else:
0625
0626
0627
0628 if len (pieces) < 1:
0629 continue
0630 fillname, pieces = pieces[0], pieces[1:]
0631
0632
0633 optionsDict = {}
0634 for word in pieces:
0635
0636
0637 print("I don't understand '%s' in section '%s'." \
0638 % (word, option))
0639 raise RuntimeError("Config file parser error '%s'(%d)" \
0640 % (fullLine, lineNum))
0641 tofillDict = GenObject._tofillDict.\
0642 setdefault (tupleName, {}).\
0643 setdefault (objName, {})
0644 partsList = GenObject.parseVariableTofill (fillname)
0645 tofillDict[varName] = [partsList, optionsDict]
0646
0647 for objName in GenObject._objsDict:
0648
0649 if not GenObject.isSingleton (objName):
0650 GenObject.addObjectVariable (objName, 'index',
0651 varType = GenObject.types.int,
0652 form = '%3d')
0653
0654
0655 @staticmethod
0656 def changeVariable (tupleName, objName, varName, fillname):
0657 """Updates the definition used to go from a Root object to a
0658 GenObject. 'tupleName' and 'objName' must already be defined."""
0659 parts = GenObject._dotRE.split (fillname)
0660 partsList = []
0661 for part in parts:
0662 parenMatch = GenObject._parenRE.search (part)
0663 mode = GenObject._objFunc.obj
0664 parens = []
0665 if parenMatch:
0666 part = parenMatch.group (1)
0667 mode = GenObject._objFunc.func
0668 parens = \
0669 GenObject._convertStringToParameters \
0670 (parenMatch.group (2))
0671 partsList.append( (part, mode, parens) )
0672 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
0673
0674
0675
0676 @staticmethod
0677 def evaluateFunction (obj, partsList, debug=False):
0678 """Evaluates function described in partsList on obj"""
0679 for part in partsList:
0680 if debug: warn (part, spaces=15)
0681 obj = getattr (obj, part[0])
0682 if debug: warn (obj, spaces=15)
0683
0684
0685 if GenObject._objFunc.func == part[1]:
0686
0687 obj = obj (*part[2])
0688 if debug: warn (obj, spaces=18)
0689 return obj
0690
0691
0692 @staticmethod
0693 def _genObjectClone (objName, tupleName, obj, index = -1):
0694 """Creates a GenObject copy of Root object"""
0695 debug = GenObject._kitchenSinkDict.get ('debug', False)
0696 if objName == 'runevent':
0697 debug = False
0698 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
0699 .get(objName, {})
0700 genObj = GenObject (objName)
0701 origObj = obj
0702 if debug: warn (objName, spaces = 9)
0703 for genVar, ntDict in tofillObjDict.items():
0704 if debug: warn (genVar, spaces = 12)
0705
0706 partsList = ntDict[0]
0707
0708 obj = GenObject.evaluateFunction (origObj, partsList, debug)
0709 if debug: warn (obj, spaces=12)
0710 setattr (genObj, genVar, obj)
0711
0712 if index >= 0:
0713 setattr (genObj, 'index', index)
0714 return genObj
0715
0716
0717 @staticmethod
0718 def _rootObjectCopy (goSource, rootTarget):
0719 """Copies information from goSourse into Root Object"""
0720 objName = goSource._objName
0721 for varName in GenObject._objsDict [objName].keys():
0722
0723
0724 if varName.startswith ("_"):
0725 continue
0726 setattr( rootTarget, varName, goSource (varName) )
0727
0728
0729 @staticmethod
0730 def _rootObjectClone (obj):
0731 """Creates the approprite type of Root object and copies the
0732 information into it from the GO object."""
0733 objName = obj._objName
0734 classObj = GenObject._rootClassDict.get (objName)
0735 if not classObj:
0736 goName = GenObject.rootClassName (objName)
0737 classObj = GenObject._rootClassDict[ goName ]
0738 rootObj = classObj()
0739 for varName in GenObject._objsDict [objName].keys():
0740 setattr( rootObj, varName, obj (varName) )
0741 return rootObj
0742
0743
0744 @staticmethod
0745 def _rootDiffObject (obj1, obj2, rootObj = 0):
0746 """Given to GOs, it will create and fill the corresponding
0747 root diff object"""
0748 objName = obj1._objName
0749
0750 if not rootObj:
0751 diffName = GenObject.rootDiffClassName( objName )
0752 rootObj = GenObject._rootClassDict[diffName]()
0753 for varName in GenObject._objsDict [objName].keys():
0754 if varName.startswith ("_"): continue
0755 goType = GenObject._objsDict[objName][varName]['varType']
0756 if not goType in GenObject._basicSet:
0757
0758 continue
0759 setattr( rootObj, varName, obj1 (varName) )
0760 if goType == GenObject.types.string:
0761
0762 otherName = 'other_' + varName
0763 if obj1 (varName) != obj2 (varName):
0764
0765 setattr( rootObj, otherName, obj2 (varName) )
0766 else:
0767
0768 setattr( rootObj, otherName, '' )
0769 else:
0770
0771 deltaName = 'delta_' + varName
0772 setattr( rootObj, deltaName,
0773 obj2 (varName) - obj1 (varName) )
0774 return rootObj
0775
0776
0777 @staticmethod
0778 def setupOutputTree (outputFile, treeName, treeDescription = "",
0779 otherNtupleName = ""):
0780 """Opens the output file, loads all of the necessary shared
0781 object libraries, and returns the output file and tree. If
0782 'otherNtupleName' is given, it will check and make sure that
0783 only objects that are defined in it are written out."""
0784 rootfile = ROOT.TFile.Open (outputFile, "recreate")
0785 tree = ROOT.TTree (treeName, treeDescription)
0786 GenObject._loadGoRootLibrary()
0787 for objName in sorted (GenObject._objsDict.keys()):
0788 classname = GenObject.rootClassName (objName)
0789 rootObj = \
0790 GenObject._rootClassDict[objName] = \
0791 getattr (ROOT, classname)
0792 if GenObject.isSingleton (objName):
0793
0794 obj = GenObject._rootObjectDict[objName] = rootObj()
0795 tree.Branch (objName, classname, obj)
0796 else:
0797
0798
0799
0800 vec = \
0801 GenObject._rootObjectDict[objName] = \
0802 ROOT.std.vector( rootObj )()
0803 branchName = objName + "s"
0804 vecName = "vector<%s>" % classname
0805 tree.Branch( branchName, vecName, vec)
0806
0807
0808 return rootfile, tree
0809
0810
0811 @staticmethod
0812 def setupDiffOutputTree (outputFile, diffName, missingName,
0813 diffDescription = '', missingDescription = ''):
0814 """Opens the diff output file, loads all of the necessary
0815 shared object libraries, and returns the output file and tree.b"""
0816 rootfile = ROOT.TFile.Open (outputFile, "recreate")
0817 GenObject._loadGoRootLibrary()
0818
0819 diffTree = ROOT.TTree (diffName, diffDescription)
0820 runEventObject = getattr (ROOT, 'go_runevent')()
0821 diffTree.Branch ('runevent', 'go_runevent', runEventObject)
0822 GenObject._rootClassDict['runevent'] = runEventObject
0823 for objName in sorted (GenObject._objsDict.keys()):
0824 if objName == 'runevent': continue
0825 classname = GenObject.rootClassName (objName)
0826 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
0827 contName = GenObject.rootDiffContClassName (objName)
0828 diffName = GenObject.rootDiffClassName (objName)
0829 rootObj = GenObject._rootClassDict[contName] = \
0830 getattr (ROOT, contName)
0831 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
0832 obj = GenObject._rootObjectDict[objName] = rootObj()
0833 diffTree.Branch (objName, contName, obj)
0834
0835 missingTree = ROOT.TTree (missingName, missingDescription)
0836 rootRunEventClass = getattr (ROOT, 'go_runevent')
0837 firstOnly = GenObject._rootClassDict['firstOnly'] = \
0838 ROOT.std.vector( rootRunEventClass ) ()
0839 secondOnly = GenObject._rootClassDict['secondOnly'] = \
0840 ROOT.std.vector( rootRunEventClass ) ()
0841 missingTree.Branch ('firstOnly', 'vector<go_runevent>', firstOnly)
0842 missingTree.Branch ('secondOnly', 'vector<go_runevent>', secondOnly)
0843 return rootfile, diffTree, missingTree
0844
0845
0846 @staticmethod
0847 def _fillRootObjects (event):
0848 """Fills root objects from GenObject 'event'"""
0849 for objName, obj in sorted (event.items()):
0850 if GenObject.isSingleton (objName):
0851
0852 GenObject._rootObjectCopy (obj,
0853 GenObject._rootObjectDict[objName])
0854 else:
0855
0856 vec = GenObject._rootObjectDict[objName]
0857 vec.clear()
0858 for goObj in obj:
0859 vec.push_back( GenObject._rootObjectClone (goObj) )
0860
0861
0862 @staticmethod
0863 def _fillRootDiffs (event1, event2):
0864 """Fills root diff containers from two GenObject 'event's"""
0865
0866
0867
0868 @staticmethod
0869 def isSingleton (objName):
0870 """Returns true if object is a singleton"""
0871 return GenObject._objsDict[objName].get('_singleton')
0872
0873
0874 @staticmethod
0875 def loadEventFromTree (eventTree, eventIndex,
0876 onlyRunEvent = False):
0877 """Loads event information from Root file (as interfaced by
0878 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
0879 'event' containing lists of objects or singleton object. If
0880 'onlyRunEvent' is et to True, then only run and event number
0881 is read in from the tree."""
0882 debug = GenObject._kitchenSinkDict.get ('debug', False)
0883 tupleName = GenObject._kitchenSinkDict[eventTree]['tupleName']
0884 event = {}
0885
0886 isChain = eventTree.__class__.__name__ == 'TChain'
0887 if isChain:
0888
0889 eventTree.GetEntry (eventIndex)
0890 else:
0891
0892 eventTree.to(eventIndex)
0893 tofillDict = GenObject._tofillDict.get (tupleName)
0894 ntupleDict = GenObject._ntupleDict.get (tupleName)
0895 if not tofillDict:
0896 print("Don't know how to fill from '%s' ntuple." % tupleName)
0897 return
0898 eventBranchName = ntupleDict['runevent']
0899 for objName in tofillDict:
0900 branchName = ntupleDict[objName]
0901 if onlyRunEvent and branchName != eventBranchName:
0902
0903 continue
0904
0905 if not branchName:
0906
0907 continue
0908 if isChain:
0909
0910 objects = getattr (eventTree, branchName)
0911 else:
0912
0913 shortcut = ntupleDict.get('_shortcut', {}).get(branchName)
0914 if shortcut:
0915 objects = GenObject.evaluateFunction (eventTree, shortcut)
0916 else:
0917 eventTree.toBegin()
0918 handle = ntupleDict.get('_handle', {}).get(branchName)
0919 label = ntupleDict.get('_label' , {}).get(branchName)
0920 if not handle or not label:
0921 raise RuntimeError("Missing handle or label for '%s'"\
0922 % branchName)
0923 if not eventTree.getByLabel (label, handle):
0924 raise RuntimeError("not able to get %s for %s" \
0925 % (label, branchName))
0926 objects = handle.product()
0927
0928 if GenObject.isSingleton (objName):
0929 event[objName] = GenObject.\
0930 _genObjectClone (objName,
0931 tupleName,
0932 objects)
0933 continue
0934
0935 if debug: warn (objName, spaces = 3)
0936 event[objName] = []
0937 for index, obj in enumerate (objects):
0938 event[objName].append( GenObject.\
0939 _genObjectClone (objName,
0940 tupleName,
0941 obj,
0942 index) )
0943 del objects
0944
0945
0946
0947
0948 return event
0949
0950
0951 @staticmethod
0952 def printEvent (event):
0953 """Prints out event dictionary. Mostly for debugging"""
0954
0955 for objName, obj in sorted (event.items()):
0956
0957
0958 if GenObject.isSingleton (objName):
0959 print("%s: %s" % (objName, obj))
0960
0961 for objName, obj in sorted (event.items()):
0962
0963
0964 if not GenObject.isSingleton (objName):
0965
0966 print("%s:" % objName)
0967 for single in obj:
0968 print(" ", single)
0969 print()
0970
0971
0972 @staticmethod
0973 def setAliases (eventTree, tupleName):
0974 """runs SetAlias on all saved aliases"""
0975 aliases = GenObject._ntupleDict[tupleName].get('_alias', {})
0976 for name, alias in aliases.items():
0977 eventTree.SetAlias (name, alias)
0978
0979
0980 @staticmethod
0981 def changeAlias (tupleName, name, alias):
0982 """Updates an alias for an object for a given tuple"""
0983 aliasDict = GenObject._ntupleDict[tupleName]['_alias']
0984 if name not in aliasDict:
0985 raise RuntimeError("unknown name '%s' in tuple '%s'" % \
0986 (name, tupleName))
0987 aliasDict[name] = alias
0988
0989
0990 @staticmethod
0991 def changeLabel (tupleName, objectName, label):
0992 """Updates an label for an object for a given tuple"""
0993 labelDict = GenObject._ntupleDict[tupleName]['_label']
0994 if objectName not in labelDict:
0995 raise RuntimeError("unknown name '%s' in tuple '%s'" % \
0996 (objectName, tupleName))
0997 label = tuple( GenObject._commaRE.split( label ) )
0998 labelDict[objectName] = label
0999
1000
1001 @staticmethod
1002 def prepareTuple (tupleName, files, numEventsWanted = 0):
1003 """Given the tuple name and list of files, returns either a
1004 TChain or EventTree, and number of entries"""
1005 if "GenObject" == tupleName:
1006 GenObject.prepareToLoadGenObject()
1007 if not isinstance (files, list):
1008
1009 files = [files]
1010 ntupleDict = GenObject._ntupleDict[tupleName]
1011 treeName = ntupleDict["_tree"]
1012 if ntupleDict.get('_useChain'):
1013 chain = ROOT.TChain (treeName)
1014 for filename in files:
1015 chain.AddFile (filename)
1016 numEntries = chain.GetEntries()
1017
1018 else:
1019 chain = Events (files, forceEvent=True)
1020 numEntries = chain.size()
1021 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1022 if numEventsWanted and numEventsWanted < numEntries:
1023 numEntries = numEventsWanted
1024 chainDict['numEntries'] = numEntries
1025 chainDict['tupleName' ] = tupleName
1026 return chain
1027
1028
1029 @staticmethod
1030 def getRunEventEntryDict (chain, tupleName, numEntries):
1031 """Returns a dictionary of run, event tuples to entryIndicies"""
1032 reeDict = {}
1033 for entryIndex in range (numEntries):
1034 event = GenObject.loadEventFromTree (chain,
1035 entryIndex,
1036 onlyRunEvent = True)
1037 runevent = event['runevent']
1038 reeDict[ GenObject._re2key (runevent) ] = entryIndex
1039
1040 del event
1041 return reeDict
1042
1043
1044 @staticmethod
1045 def _re2key (runevent):
1046 """Given a GO 'runevent' object, returns a sortable key"""
1047
1048
1049 if not GenObject._runEventListDone:
1050 GenObject._runEventListDone = True
1051 ignoreSet = set( ['run', 'event'] )
1052 for varName in sorted (runevent.__dict__.keys()):
1053 if varName.startswith ('_') or varName in ignoreSet:
1054 continue
1055 form = runevent.getVariableProperty (varName, "form")
1056 if not form:
1057 form = '%s'
1058 GenObject._runEventList.append ((varName, form))
1059 key = 'run:%d event:%d' % (runevent.run, runevent.event)
1060 for items in GenObject._runEventList:
1061 varName = items[0]
1062 form = ' %s:%s' % (varName, items[1])
1063 key += form % runevent.getVariableProperty (varName)
1064 return key
1065
1066
1067 @staticmethod
1068 def _key2re (key, runevent=None):
1069 """Given a key, returns a GO 'runevent' object"""
1070 if not runevent:
1071 runevent = GenObject ('runevent')
1072 words = GenObject._spacesRE.split (key)
1073 for word in words:
1074 match = GenObject._singleColonRE.search (word)
1075 if match:
1076
1077
1078
1079 runevent.__setattr__ (match.group(1), int( match.group(2) ))
1080 return runevent
1081
1082
1083 @staticmethod
1084 def compareRunEventDicts (firstDict, secondDict):
1085 """Compares the keys of the two dicts and returns three sets:
1086 the overlap, first but not second, and second but not first."""
1087 overlap = set()
1088 firstOnly = set()
1089 secondOnly = set()
1090
1091 for key in firstDict.keys():
1092 if key in secondDict:
1093 overlap.add (key)
1094 else:
1095 firstOnly.add (key)
1096
1097
1098 for key in secondDict.keys():
1099 if key not in firstDict:
1100 secondOnly.add (key)
1101
1102 return overlap, firstOnly, secondOnly
1103
1104
1105 @staticmethod
1106 def pairEquivalentObjects (vec1, vec2):
1107 """Finds the equivalent objects in the two vectors"""
1108 len1, len2 = len (vec1), len (vec2)
1109 debug = GenObject._kitchenSinkDict.get ('debug', False)
1110 if not len1 or not len2:
1111
1112 if len1:
1113 noMatch1Set = set( range(len1) )
1114 else:
1115 noMatch1Set = set ()
1116 if len2:
1117 noMatch2Set = set( range(len2) )
1118 else:
1119 noMatch2Set = set ()
1120 if debug: warn ("Nothing found", sapces=6)
1121 return set(), noMatch1Set, noMatch2Set
1122 objName = vec1[0]._objName
1123 equivList = GenObject._equivDict[objName]
1124 firstDict = {}
1125 secondDict = {}
1126
1127 if GenObject._kitchenSinkDict.get ('strictPairing') or \
1128 equivList == [('index', 0)]:
1129
1130 matchedSet = set (zip ( list(range( min (len1, len2))),
1131 list(range( min (len1, len2))) ) )
1132 if len1 > len2:
1133
1134
1135 noMatch1Set = set (range(len2, len1 + 1))
1136 else:
1137 noMatch1Set = set()
1138 if len2 > len1:
1139
1140 noMatch2Set = set (range(len1, len2 + 1))
1141 else:
1142 noMatch2Set = set()
1143 return matchedSet, noMatch1Set, noMatch2Set
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 for index1 in range (len1):
1159 objList = []
1160 obj1 = vec1[index1]
1161 for index2 in range (len2):
1162 total = 0.
1163 obj2 = vec2[index2]
1164 ok = True
1165 for equiv in equivList:
1166 var, precision = equiv[0], equiv[1]
1167 val1 = obj1 (var)
1168 val2 = obj2 (var)
1169
1170 if precision:
1171 value = abs (val1 - val2) / precision
1172 if value >= 1.:
1173 ok = False
1174 break
1175 total += value ** 2
1176 elif val1 != val2:
1177 ok = False
1178 break
1179 if ok:
1180 objList.append( (total, index2) )
1181 objList.sort()
1182 firstDict[index1] = objList
1183
1184
1185 for index2 in range (len2):
1186 objList = []
1187 obj2 = vec2[index2]
1188 for index1 in range (len1):
1189 total = 0.
1190 obj1 = vec1[index1]
1191 ok = True
1192 for equiv in equivList:
1193 var, precision = equiv[0], equiv[1]
1194 val2 = obj2 (var)
1195 val1 = obj1 (var)
1196
1197 if precision:
1198 value = abs (val2 - val1) / precision
1199 if value > 1.:
1200 ok = False
1201 break
1202 total += value ** 2
1203 elif val2 != val1:
1204 ok = False
1205 break
1206 if ok:
1207 objList.append( (total, index1) )
1208 objList.sort()
1209 secondDict[index2] = objList
1210
1211
1212 matchedSet = set()
1213 noMatch1Set = set()
1214 firstDictKeys = sorted (firstDict.keys())
1215 for index1 in firstDictKeys:
1216 list1 = firstDict[index1]
1217
1218 if not len (list1):
1219
1220 noMatch1Set.add (index1)
1221 continue
1222
1223 best1 = list1[0]
1224 index2 = best1[1]
1225
1226 list2 = secondDict.get (index2, [])
1227 if len(list2) and list2[0][1] == index1:
1228 matchedSet.add( (index1, index2) )
1229
1230 del firstDict[index1]
1231 del secondDict[index2]
1232 else:
1233
1234 noMatch1Set.add (index1)
1235 noMatch2Set = set( secondDict.keys() )
1236 return matchedSet, noMatch1Set, noMatch2Set
1237
1238
1239 @staticmethod
1240 def compareTwoItems (item1, item2):
1241 """Compares all of the variables making sure they are the same
1242 on the two objects."""
1243 objName = item1._objName
1244 problems = {}
1245 relative = GenObject._kitchenSinkDict.get ('relative', False)
1246 for varName in GenObject._objsDict[objName].keys():
1247 prec = item1.getVariableProperty (varName, 'prec')
1248 if prec:
1249
1250 if relative:
1251 val1 = item1(varName)
1252 val2 = item2(varName)
1253 numerator = 2 * abs (val1 - val2)
1254 denominator = abs(val1) + abs(val2)
1255 if not denominator:
1256
1257
1258 continue
1259 value = numerator / denominator
1260 if value > prec:
1261
1262 problems[varName] = value
1263 else:
1264 value = abs( item1(varName) - item2(varName) )
1265 if value > prec:
1266
1267 problems[varName] = value
1268 else:
1269
1270 if item1(varName) != item2(varName):
1271
1272 val1, val2 = item1(varName), item2(varName)
1273 if val1 > val2:
1274 val1, val2 = val2, val1
1275 problems[varName] = "%s != %s" % (val1, val2)
1276
1277 return problems
1278
1279
1280 @staticmethod
1281 def blurEvent (event, value, where = ""):
1282 """For debugging purposes only. Will deliberately change
1283 values of first tree to verify that script is correctly
1284 finding problems."""
1285 for objName in sorted (event.keys()):
1286 if "runevent" == objName:
1287
1288 continue
1289 if GenObject.isSingleton (objName):
1290
1291 continue
1292 count = 0
1293 for obj in event[objName]:
1294 count += 1
1295 for varName in GenObject._objsDict[objName].keys():
1296 if isinstance (obj.__dict__[varName], str):
1297
1298 continue
1299 randNumber = random.random()
1300
1301 if randNumber < GenObject._kitchenSinkDict['blurRate']:
1302 print(" %s: changing '%s' of '%s:%d'" \
1303 % (where, varName, obj._objName, count))
1304
1305
1306 obj.__dict__[varName] += value
1307
1308
1309 @staticmethod
1310 def compareTwoTrees (chain1, chain2, **kwargs):
1311 """Given all of the necessary information, this routine will
1312 go through and compare two trees making sure they are
1313 'identical' within requested precision. If 'diffOutputName'
1314 is passed in, a root file with a diffTree and missingTree will
1315 be produced."""
1316 print("Comparing Two Trees")
1317 diffOutputName = kwargs.get ('diffOutputName')
1318 tupleName1 = GenObject._kitchenSinkDict[chain1]['tupleName']
1319 numEntries1 = GenObject._kitchenSinkDict[chain1]['numEntries']
1320 tupleName2 = GenObject._kitchenSinkDict[chain2]['tupleName']
1321 numEntries2 = GenObject._kitchenSinkDict[chain2]['numEntries']
1322 debug = GenObject._kitchenSinkDict.get ('debug', False)
1323 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1324 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1325 overlap, firstOnly, secondOnly = \
1326 GenObject.compareRunEventDicts (ree1, ree2)
1327 if diffOutputName:
1328 rootfile, diffTree, missingTree = \
1329 GenObject.setupDiffOutputTree (diffOutputName,
1330 'diffTree',
1331 'missingTree')
1332 if firstOnly:
1333 vec = GenObject._rootClassDict['firstOnly']
1334 for key in firstOnly:
1335 runevent = GenObject._key2re (key)
1336 vec.push_back( GenObject._rootObjectClone( runevent ) )
1337 if secondOnly:
1338 vec = GenObject._rootClassDict['secondOnly']
1339 for key in secondOnly:
1340 runevent = GenObject._key2re (key)
1341 vec.push_back( GenObject._rootObjectClone( runevent ) )
1342 missingTree.Fill()
1343 resultsDict = {}
1344 if firstOnly:
1345 resultsDict.setdefault ('_runevent', {})['firstOnly'] = \
1346 len (firstOnly)
1347 if secondOnly:
1348 resultsDict.setdefault ('_runevent', {})['secondOnly'] = \
1349 len (secondOnly)
1350 resultsDict['eventsCompared'] = len (overlap)
1351 for reTuple in sorted(overlap):
1352
1353
1354 if diffOutputName:
1355 GenObject._key2re (reTuple,
1356 GenObject._rootClassDict['runevent'])
1357 if debug: warn ('event1', blankLines = 3)
1358 event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1359 if debug: warn ('event2', blankLines = 3)
1360 event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1361 if GenObject._kitchenSinkDict.get('printEvent'):
1362 print("event1:")
1363 GenObject.printEvent (event1)
1364 print("event2:")
1365 GenObject.printEvent (event2)
1366 if GenObject._kitchenSinkDict.get('blur'):
1367 where = reTuple
1368 GenObject.blurEvent (event1,
1369 GenObject._kitchenSinkDict['blur'],
1370 where)
1371 for objName in sorted (event1.keys()):
1372 if "runevent" == objName:
1373
1374 continue
1375 if not GenObject._equivDict.get (objName):
1376
1377
1378 continue
1379 if GenObject.isSingleton (objName):
1380
1381 print("singleton")
1382 continue
1383
1384 rootObj = 0
1385 if diffOutputName:
1386 rootObj = GenObject._rootObjectDict[objName]
1387 rootObj.clear()
1388 vec1 = event1[objName]
1389 vec2 = event2[objName]
1390 matchedSet, noMatch1Set, noMatch2Set = \
1391 GenObject.pairEquivalentObjects (vec1, vec2)
1392 if noMatch1Set or noMatch2Set:
1393
1394
1395 count1 = len (noMatch1Set)
1396 count2 = len (noMatch2Set)
1397 key = (count1, count2)
1398 countDict = resultsDict.\
1399 setdefault (objName, {}).\
1400 setdefault ('_missing', {})
1401 if key in countDict:
1402 countDict[key] += 1
1403 else:
1404 countDict[key] = 1
1405
1406 if diffOutputName:
1407
1408 for index in sorted(list(noMatch1Set)):
1409 goObj = vec1 [index]
1410 rootObj.firstOnly.push_back ( GenObject.\
1411 _rootObjectClone \
1412 (goObj) )
1413
1414 for index in sorted(list(noMatch2Set)):
1415 goObj = vec2 [index]
1416 rootObj.secondOnly.push_back ( GenObject.\
1417 _rootObjectClone \
1418 (goObj) )
1419
1420
1421 for pair in sorted(list(matchedSet)):
1422 if diffOutputName:
1423 rootDiffObj = GenObject._rootDiffObject \
1424 ( vec1[ pair[1 - 1] ],
1425 vec2[ pair[2 - 1] ] )
1426 rootObj.diff.push_back ( rootDiffObj )
1427 problems = GenObject.\
1428 compareTwoItems (vec1[ pair[1 - 1] ],
1429 vec2[ pair[2 - 1] ])
1430 if problems.keys():
1431
1432 for varName in problems.keys():
1433 countDict = resultsDict.\
1434 setdefault (objName, {}).\
1435 setdefault ('_var', {})
1436 if varName in countDict:
1437 countDict[varName] += 1
1438 else:
1439 countDict[varName] = 1
1440 key = 'count_%s' % objName
1441 if key not in resultsDict:
1442 resultsDict[key] = 0
1443 resultsDict[key] += len (matchedSet)
1444
1445 del vec1
1446 del vec2
1447
1448 if diffOutputName:
1449 diffTree.Fill()
1450 del event1
1451 del event2
1452
1453 if diffOutputName:
1454 diffTree.Write()
1455 missingTree.Write()
1456 rootfile.Close()
1457 return resultsDict
1458
1459
1460 @staticmethod
1461 def saveTupleAs (chain, rootFile):
1462 """Saves a chain as a GO tree"""
1463 print("saveTupleAs")
1464 rootfile, tree = GenObject.setupOutputTree (rootFile, "goTree")
1465 numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1466 for entryIndex in range (numEntries):
1467 event = GenObject.loadEventFromTree (chain, entryIndex)
1468 if GenObject._kitchenSinkDict.get('blur'):
1469 where = "run %d event %d" % (event['runevent'].run,
1470 event['runevent'].event)
1471 if random.random() < GenObject._kitchenSinkDict.get('blur'):
1472
1473 print("Dropping", where)
1474 continue
1475 GenObject.blurEvent (event,
1476 GenObject._kitchenSinkDict['blur'],
1477 where)
1478
1479 if GenObject._kitchenSinkDict.get('printEvent'):
1480 GenObject.printEvent (event)
1481 GenObject._fillRootObjects (event)
1482 tree.Fill()
1483 tree.Write()
1484 rootfile.Close()
1485
1486
1487 @staticmethod
1488 def setGlobalFlag (key, value):
1489 """Sets a global flag in _kitchenSinkDict"""
1490 GenObject._kitchenSinkDict [key] = value
1491
1492
1493 @staticmethod
1494 def printTuple (chain):
1495 """Prints out all events to stdout"""
1496 numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1497 debug = GenObject._kitchenSinkDict.get ('debug', False)
1498 if debug: warn (numEntries)
1499 for entryIndex in range (numEntries):
1500 if debug: warn (entryIndex, spaces=3)
1501 event = GenObject.loadEventFromTree (chain, entryIndex)
1502 GenObject.printEvent (event)
1503 if debug: warn(spaces=3)
1504
1505 @staticmethod
1506 def _convertStringToParameters (string):
1507 """Convert comma-separated string into a python3 list of
1508 parameters. Currently only understands strings, floats, and
1509 integers."""
1510 retval = []
1511 words = GenObject._commaRE.split (string)
1512 for word in words:
1513 if not len (word):
1514 continue
1515 match = GenObject._singleQuoteRE.search (word)
1516 if match:
1517 retval.append (match.group (1))
1518 continue
1519 match = GenObject._doubleQuoteRE.search (word)
1520 if match:
1521 retval.append (match.group (1))
1522 continue
1523 try:
1524 val = int (word)
1525 retval.append (val)
1526 continue
1527 except:
1528 pass
1529 try:
1530 val = float (word)
1531 retval.append (val)
1532 continue
1533 except:
1534 pass
1535
1536 raise RuntimeError("Unknown parameter '%s'." % word)
1537 return retval
1538
1539
1540
1541
1542
1543
1544
1545 def __init__ (self, objName):
1546 """Class initializer"""
1547 if objName not in GenObject._objsDict:
1548
1549
1550 print("Error: GenObject does not know about object '%s'." % objName)
1551 raise RuntimeError("Failed to create GenObject object.")
1552 self._localObjsDict = GenObject._objsDict [objName]
1553 self._objName = objName;
1554 for key, varDict in self._localObjsDict.items():
1555
1556
1557 if key.startswith ("_"):
1558 continue
1559 self.setValue (key, varDict['default'])
1560
1561
1562 def setValue (self, name, value):
1563 """Wrapper for __setattr___"""
1564 self.__setattr__ (name, value)
1565
1566
1567 def getVariableProperty (self, var, key):
1568 """ Returns property assoicated with 'key' for variable 'var'
1569 of object of the same type as 'self'. Returns 'None' if 'var'
1570 or 'key' is not defined."""
1571 return GenObject._objsDict.get (self._objName,
1572 {}).get (var, {}). get (key, None)
1573
1574
1575 def __setattr__ (self, name, value):
1576 """Controls setting of values."""
1577 if name.startswith ("_"):
1578
1579 object.__setattr__ (self, name, value)
1580 else:
1581
1582
1583
1584 if name not in self._localObjsDict:
1585
1586 print("Warning: '%s' for class '%s' not setup. Skipping." % \
1587 (name, self._objName))
1588 return
1589 varType = self.getVariableProperty (name, 'varType')
1590
1591 if GenObject.types.int == varType:
1592 try:
1593
1594
1595 value = int (value)
1596 except:
1597
1598 value = int( float( value ) )
1599 elif GenObject.types.long == varType:
1600 try:
1601
1602
1603 value = long (value)
1604 except:
1605
1606 value = long( float( value ) )
1607 elif GenObject.types.float == varType:
1608
1609 value = float (value)
1610 elif GenObject.types.string == varType:
1611
1612 value = str (value)
1613
1614 object.__setattr__ (self, name, value)
1615
1616
1617 def __call__ (self, key):
1618 """Makes object callable"""
1619 return object.__getattribute__ (self, key)
1620
1621
1622 def __str__ (self):
1623 """String representation"""
1624 retval = ""
1625 for varName, value in sorted (self.__dict__.items()):
1626 if varName.startswith ('_'): continue
1627 form = self.getVariableProperty (varName, "form")
1628 if form:
1629 format = "%s:%s " % (varName, form)
1630 retval = retval + format % value
1631 else:
1632 retval = retval + "%s:%s " % (varName, value)
1633 return retval