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