00001
00002
00003
00004
00005
00006 from FWCore.Utilities.Enumerate import Enumerate
00007 from DataFormats.FWLite import Events, Handle
00008 import re
00009 import os
00010 import copy
00011 import pprint
00012 import random
00013 import sys
00014 import inspect
00015 import ROOT
00016 ROOT.gROOT.SetBatch()
00017
00018
00019 filenameRE = re.compile (r'.+/Validation/Tools/')
00020
00021 quietWarn = False
00022
00023 def setQuietWarn (quiet = True):
00024 global quietWarn
00025 quietWarn = quiet
00026
00027
00028 def warn (*args, **kwargs):
00029 """print out warning with line number and rest of arguments"""
00030 if quietWarn: return
00031 frame = inspect.stack()[1]
00032 filename = frame[1]
00033 lineNum = frame[2]
00034
00035 filename = filenameRE.sub ('', filename)
00036
00037 blankLines = kwargs.get('blankLines', 0)
00038 if blankLines:
00039 print '\n' * blankLines
00040 spaces = kwargs.get('spaces', 0)
00041 if spaces:
00042 print ' ' * spaces,
00043 if len (args):
00044 print "%s (%s): " % (filename, lineNum),
00045 for arg in args:
00046 print arg,
00047 print
00048 else:
00049 print "%s (%s):" % (filename, lineNum)
00050
00051
00052 class GenObject (object):
00053 """Infrastruture to define general objects and their attributes."""
00054
00055
00056
00057
00058
00059 types = Enumerate ("float int long string", "type")
00060 _objFunc = Enumerate ("obj func", "of")
00061 _cppType = dict ( {types.float : 'double',
00062 types.int : 'int',
00063 types.long : 'long',
00064 types.string : 'std::string' } )
00065 _basicSet = set( [types.float, types.int, types.float,
00066 types.string] )
00067 _defaultValue = dict ( {types.float : 0.,
00068 types.int : 0,
00069 types.long : 0L,
00070 types.string : '""' } )
00071 _objsDict = {}
00072 _equivDict = {}
00073 _ntupleDict = {}
00074 _tofillDict = {}
00075 _rootObjectDict = {}
00076
00077 _rootClassDict = {}
00078
00079 _kitchenSinkDict = {}
00080 _runEventList = []
00081 _runEventListDone = False
00082 uselessReturnCode = 1 << 7
00083
00084
00085
00086
00087 _nonSpacesRE = re.compile (r'\S')
00088 _colonRE = re.compile (r'\s*:\s*')
00089 _singleColonRE = re.compile (r'(.+?):(.+)')
00090 _doubleColonRE = re.compile (r'(.+?):(.+?):(.+)')
00091 _doublePercentRE = re.compile (r'%%')
00092 _parenRE = re.compile (r'(.+)\((.*)\)')
00093 _spacesRE = re.compile (r'\s+')
00094 _dotRE = re.compile (r'\s*\.\s*')
00095 _commaRE = re.compile (r'\s*,\s*')
00096 _singleQuoteRE = re.compile (r'^\'(.+)\'$')
00097 _doubleQuoteRE = re.compile (r'^\"(.+)\"$')
00098 _bracketRE = re.compile (r'\[\s*(.+?)\s*\]')
00099 _commentRE = re.compile (r'#.+$')
00100 _aliasRE = re.compile (r'alias=(\S+)', re.IGNORECASE)
00101 _labelRE = re.compile (r'label=(\S+)', re.IGNORECASE)
00102 _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
00103 _singletonRE = re.compile (r'singleton', re.IGNORECASE)
00104 _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
00105 _defaultRE = re.compile (r'default=(\S+)', re.IGNORECASE)
00106 _shortcutRE = re.compile (r'shortcut=(\S+)', re.IGNORECASE)
00107 _precRE = re.compile (r'prec=(\S+)', re.IGNORECASE)
00108 _formRE = re.compile (r'form=(\S+)', re.IGNORECASE)
00109 _nonAlphaRE = re.compile (r'\W')
00110 _percentAsciiRE = re.compile (r'%([0-9a-fA-F]{2})')
00111
00112
00113
00114
00115
00116 @staticmethod
00117 def char2ascii (match):
00118 return "%%%02x" % ord (match.group(0))
00119
00120 @staticmethod
00121 def ascii2char (match):
00122 return chr( int( match.group(1), 16 ) )
00123
00124 @staticmethod
00125 def encodeNonAlphanumerics (line):
00126 """Use a web like encoding of characters that are non-alphanumeric"""
00127 return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
00128
00129 @staticmethod
00130 def decodeNonAlphanumerics (line):
00131 """Decode lines encoded with encodeNonAlphanumerics()"""
00132 return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
00133
00134
00135 @staticmethod
00136 def addObjectVariable (obj, var, **optionsDict):
00137 """ User passes in in object and variable names."""
00138 if not optionsDict.has_key ('varType'):
00139 optionsDict['varType'] = GenObject.types.float
00140 varType = optionsDict['varType']
00141 if not GenObject.types.isValidValue (varType):
00142 print "Type '%s' not valid. Skipping (%s, %s, %s)." % \
00143 (varType, obj, var, varType)
00144 return
00145 if not optionsDict.has_key ('default'):
00146 optionsDict['default'] = GenObject._defaultValue[varType]
00147 if obj.startswith ("_") or var.startswith ("_"):
00148 print "Skipping (%s, %s, %s) because of leading underscore." % \
00149 (obj, var, varType)
00150 return
00151 GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
00152
00153
00154 @staticmethod
00155 def getVariableProperty (obj, var, key):
00156 """Returns property assoicated with 'key' for variable 'var'
00157 of object 'obj'. Returns 'None' if any of the above are not
00158 defined."""
00159 return GenObject._objsDict.get (obj, {}).get (var, {}). get (key, None)
00160
00161
00162 @staticmethod
00163 def setEquivExpression (obj, variable, precision):
00164 """Adds an equivalence constraint. Must have at least one to
00165 compare GO objects."""
00166 if obj.startswith ("_"):
00167 print "Skipping (%s, %s) because of leading underscore." % \
00168 (obj, expression)
00169 return
00170 GenObject._equivDict.setdefault (obj,[]).append ( (variable,
00171 precision) )
00172
00173
00174 @staticmethod
00175 def printGlobal():
00176 """Meant for debugging, but ok if called by user"""
00177 print "objs: "
00178 pprint.pprint (GenObject._objsDict, indent=4)
00179 print "equiv: "
00180 pprint.pprint (GenObject._equivDict, indent=4)
00181 print "ntuple: "
00182 pprint.pprint (GenObject._ntupleDict, indent=4)
00183 print "tofill: "
00184 pprint.pprint (GenObject._tofillDict, indent=4)
00185 print "kitchenSink: "
00186 pprint.pprint (GenObject._kitchenSinkDict, indent=4)
00187 print "rootClassDict"
00188 pprint.pprint (GenObject._rootClassDict, indent=4)
00189
00190
00191 @staticmethod
00192 def checksum (str):
00193 """Returns a string of hex value of a checksum of input
00194 string."""
00195 return hex( reduce( lambda x, y : x + y, map(ord, str) ) )[2:]
00196
00197
00198 @staticmethod
00199 def rootClassName (objName):
00200 """Returns the name of the equivalent Root object"""
00201 return "go_" + objName
00202
00203
00204 @staticmethod
00205 def rootDiffClassName (objName):
00206 """Returns the name of the equivalent Root diff object"""
00207 return "goDiff_" + objName
00208
00209
00210 @staticmethod
00211 def rootDiffContClassName (objName):
00212 """Returns the name of the equivalent Root diff container
00213 object"""
00214 return "goDiffCont_" + objName
00215
00216
00217 @staticmethod
00218 def _setupClassHeader (className, noColon = False):
00219 """Returns a string with the class header for a class
00220 'classname'"""
00221 retval = "\nclass %s\n{\n public:\n" % className
00222 retval += " typedef std::vector< %s > Collection;\n\n" % className
00223
00224 if noColon:
00225 retval += " %s()" % className
00226 else:
00227 retval += " %s() :\n" % className
00228 return retval
00229
00230
00231 @staticmethod
00232 def _finishClassHeader (className, datadec):
00233 """Returns a stringg with the end of a class definition"""
00234 retval = "\n {}\n" + datadec + "};\n"
00235 retval += "#ifdef __MAKECINT__\n#pragma link C++ class " + \
00236 "vector< %s >+;\n#endif\n\n" % className
00237 return retval
00238
00239
00240 @staticmethod
00241 def _createCppClass (objName):
00242 """Returns a string containing the '.C' file necessary to
00243 generate a shared object library with dictionary."""
00244 if not GenObject._objsDict.has_key (objName):
00245
00246 print "Error: GenObject does not know about object '%s'." % objName
00247 raise RuntimeError, "Failed to create C++ class."
00248 className = GenObject.rootClassName (objName)
00249 diffName = GenObject.rootDiffClassName (objName)
00250 contName = GenObject.rootDiffContClassName (objName)
00251 goClass = GenObject._setupClassHeader (className)
00252 diffClass = GenObject._setupClassHeader (diffName)
00253 contClass = GenObject._setupClassHeader (contName, noColon = True)
00254 goDataDec = diffDataDec = contDataDec = "\n // data members\n"
00255 first = True
00256 for key in sorted( GenObject._objsDict[objName].keys() ):
00257 if key.startswith ("_"): continue
00258 varTypeList = GenObject._objsDict[objName][key]
00259 cppType = GenObject._cppType[ varTypeList['varType'] ]
00260 default = varTypeList['default']
00261 if first:
00262 first = False
00263 else:
00264 goClass += ",\n"
00265 diffClass += ',\n'
00266 goClass += " %s (%s)" % (key, default)
00267 goDataDec += " %s %s;\n" % (cppType, key)
00268
00269 goType = varTypeList['varType']
00270 if goType in GenObject._basicSet:
00271
00272 diffClass += " %s (%s),\n" % (key, default)
00273 diffDataDec += " %s %s;\n" % (cppType, key)
00274 if goType == GenObject.types.string:
00275
00276 otherKey = 'other_' + key
00277 diffClass += " %s (%s)" % (otherKey, default)
00278 diffDataDec += " %s %s;\n" % (cppType, otherKey)
00279 else:
00280
00281 deltaKey = 'delta_' + key
00282 diffClass += " %s (%s)" % (deltaKey, default)
00283 diffDataDec += " %s %s;\n" % (cppType, deltaKey)
00284 else:
00285 raise RuntimeError, "Shouldn't be here yet."
00286
00287
00288 if GenObject.isSingleton (objName):
00289
00290 contDataDec += " %s diff;\n" % diffName
00291 contDataDec += " void setDiff (const %s &rhs)" % diffName + \
00292 " { diff = rhs; }\n"
00293 else:
00294
00295 contDataDec += " void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n"
00296 contDataDec += " %s::Collection firstOnly;\n" % className
00297 contDataDec += " %s::Collection secondOnly;\n" % className
00298 contDataDec += " %s::Collection diff;\n" % diffName
00299
00300
00301 goClass += GenObject._finishClassHeader (className, goDataDec)
00302 diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
00303 contClass += GenObject._finishClassHeader (contName, contDataDec)
00304 if objName == 'runevent':
00305
00306 diffClass = ''
00307 contClass = ''
00308 return goClass + diffClass + contClass
00309
00310
00311 @staticmethod
00312 def _loadGoRootLibrary ():
00313 """Loads Root shared object library associated with all
00314 defined GenObjects. Will create library if necessary."""
00315 print "Loading GO Root Library"
00316 key = "_loadedLibrary"
00317 if GenObject._kitchenSinkDict.get (key):
00318
00319 return
00320
00321 GenObject._kitchenSinkDict[key] = True
00322
00323 sourceCode = "#include <string>\n#include <vector>\n" \
00324 + "using namespace std;\n"
00325 for objClassName in sorted( GenObject._objsDict.keys() ):
00326 sourceCode += GenObject._createCppClass (objClassName)
00327 GenObjectRootLibDir = "genobjectrootlibs"
00328 if not os.path.exists (GenObjectRootLibDir):
00329 os.mkdir (GenObjectRootLibDir)
00330 key = GenObject.checksum( sourceCode )
00331 basename = "%s_%s" % ("GenObject", key)
00332 SO = "%s/%s_C" % (GenObjectRootLibDir, basename)
00333 linuxSO = "%s.so" % SO
00334 windowsSO = "%s.dll" % SO
00335 if not os.path.exists (linuxSO) and not os.path.exists (windowsSO):
00336 print "creating SO"
00337 filename = "%s/%s.C" % (GenObjectRootLibDir, basename)
00338 if not os.path.exists (filename):
00339 print "creating .C file"
00340 target = open (filename, "w")
00341 target.write (sourceCode)
00342 target.close()
00343 else:
00344 print "%s exists" % filename
00345
00346
00347 ROOT.gSystem.CompileMacro (filename, "k")
00348 else:
00349 print "loading %s" % SO
00350 ROOT.gSystem.Load(SO)
00351 return
00352
00353
00354 @staticmethod
00355 def _tofillGenObject():
00356 """Makes sure that I know how to read root files I made myself"""
00357 genObject = "GenObject"
00358 ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
00359 ntupleDict['_useChain'] = True
00360 ntupleDict['_tree'] = "goTree"
00361 for objName in GenObject._objsDict.keys():
00362 rootObjName = GenObject.rootClassName (objName)
00363 if GenObject.isSingleton (objName):
00364 ntupleDict[objName] = objName
00365 else:
00366 ntupleDict[objName] = objName + "s"
00367 tofillDict = GenObject._tofillDict.\
00368 setdefault (genObject, {}).\
00369 setdefault (objName, {})
00370 for varName in GenObject._objsDict [objName].keys():
00371
00372
00373 if varName.startswith ("_"):
00374 continue
00375 tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
00376 {}]
00377
00378
00379 @staticmethod
00380 def prepareToLoadGenObject():
00381 """Makes all necessary preparations to load root files created
00382 by GenObject."""
00383 GenObject._tofillGenObject()
00384 GenObject._loadGoRootLibrary()
00385
00386
00387 @staticmethod
00388 def parseVariableTofill (fillname):
00389 """Returns tofill tuple made from string"""
00390 parts = GenObject._dotRE.split (fillname)
00391 partsList = []
00392 for part in parts:
00393 parenMatch = GenObject._parenRE.search (part)
00394 mode = GenObject._objFunc.obj
00395 parens = []
00396 if parenMatch:
00397 part = parenMatch.group (1)
00398 mode = GenObject._objFunc.func
00399 parens = \
00400 GenObject._convertStringToParameters \
00401 (parenMatch.group (2))
00402 partsList.append( (part, mode, parens) )
00403 return partsList
00404
00405 @staticmethod
00406 def _fixLostGreaterThans (handle):
00407 offset = handle.count ('<') - handle.count('>')
00408 if not offset:
00409 return handle
00410 if offset < 0:
00411 print "Huh? Too few '<' for each '>' in handle '%'" % handle
00412 return handle
00413 return handle + ' >' * offset
00414
00415
00416 @staticmethod
00417 def loadConfigFile (configFile):
00418 """Loads configuration file"""
00419 objName = ""
00420 tupleName = ""
00421 tofillName = ""
00422 modeEnum = Enumerate ("none define tofill ntuple", "mode")
00423 mode = modeEnum.none
00424 try:
00425 config = open (configFile, 'r')
00426 except:
00427 raise RuntimeError, "Can't open configuration '%s'" % configFile
00428 for lineNum, fullLine in enumerate (config):
00429 fullLine = fullLine.strip()
00430
00431 line = GenObject._commentRE.sub ('', fullLine)
00432
00433 if not GenObject._nonSpacesRE.search (line):
00434
00435 continue
00436
00437
00438
00439 bracketMatch = GenObject._bracketRE.search (line)
00440 if bracketMatch:
00441
00442 section = bracketMatch.group(1)
00443 words = GenObject._spacesRE.split( section )
00444 if len (words) < 1:
00445 raise RuntimeError, "Don't understand line '%s'(%d)" \
00446 % (fullLine, lineNum)
00447
00448
00449 objName = words[0]
00450 words = words[1:]
00451 colonWords = GenObject._colonRE.split (objName)
00452 if len (colonWords) > 3:
00453 raise RuntimeError, "Don't understand line '%s'(%d)" \
00454 % (fullLine, lineNum)
00455 if len (colonWords) == 1:
00456
00457
00458
00459 mode = modeEnum.define
00460 for word in words:
00461 if GenObject._singletonRE.match (word):
00462
00463 objsDict = GenObject._objsDict.\
00464 setdefault (objName, {})
00465 objsDict['_singleton'] = True
00466 continue
00467
00468
00469 print "I don't understand '%s' in section '%s' : %s" \
00470 % (word, section, mode)
00471 raise RuntimeError, \
00472 "Config file parser error '%s'(%d)" \
00473 % (fullLine, lineNum)
00474 elif len (colonWords) == 2:
00475
00476
00477
00478 mode = modeEnum.ntuple
00479 ntupleDict = GenObject._ntupleDict.\
00480 setdefault (colonWords[0], {})
00481 ntupleDict['_tree'] = colonWords[1]
00482 else:
00483
00484
00485
00486 mode = modeEnum.tofill
00487 objName = colonWords [0]
00488 tupleName = colonWords [1]
00489 tofillName = colonWords [2]
00490 ntupleDict = GenObject._ntupleDict.\
00491 setdefault (tupleName, {})
00492 ntupleDict[objName] = tofillName
00493 for word in words:
00494
00495 labelMatch = GenObject._labelRE.search (word)
00496 if labelMatch:
00497 label = tuple( GenObject._commaRE.\
00498 split( labelMatch.group (1) ) )
00499 ntupleDict.setdefault ('_label', {}).\
00500 setdefault (tofillName,
00501 label)
00502 continue
00503
00504 shortcutMatch = GenObject._shortcutRE.search (word)
00505 if shortcutMatch:
00506 shortcutFill = \
00507 GenObject.\
00508 parseVariableTofill ( shortcutMatch.\
00509 group(1) )
00510 ntupleDict.setdefault ('_shortcut', {}).\
00511 setdefault (tofillName,
00512 shortcutFill)
00513 continue
00514
00515 typeMatch = GenObject._typeRE.search (word)
00516 if typeMatch:
00517 handleString = \
00518 GenObject.\
00519 _fixLostGreaterThans (typeMatch.group(1))
00520 handle = Handle( handleString )
00521 ntupleDict.setdefault ('_handle', {}).\
00522 setdefault (tofillName,
00523 handle)
00524 continue
00525
00526 aliasMatch = GenObject._aliasRE.search (word)
00527 if aliasMatch:
00528 ntupleDict.setdefault ('_alias', {}).\
00529 setdefault (tofillName,
00530 aliasMatch.\
00531 group(1))
00532 continue
00533
00534 if word == '>':
00535 continue
00536
00537
00538 print "I don't understand '%s' in section '%s' : %s" \
00539 % (word, section, mode)
00540 raise RuntimeError, \
00541 "Config file parser error '%s'(%d)" \
00542 % (fullLine, lineNum)
00543
00544
00545
00546 else:
00547
00548 if modeEnum.none == mode:
00549
00550 print "I don't understand line '%s'." % fullLine
00551 raise RuntimeError, \
00552 "Config file parser error '%s'(%d)" \
00553 % (fullLine, lineNum)
00554 colonWords = GenObject._colonRE.split (line, 1)
00555 if len (colonWords) < 2:
00556
00557 print "I don't understand line '%s'." % fullLine
00558 raise RuntimeError, \
00559 "Config file parser error '%s'(%d)" \
00560 % (fullLine, lineNum)
00561 varName = colonWords[0]
00562 option = colonWords[1]
00563 if option:
00564 pieces = GenObject._spacesRE.split (option)
00565 else:
00566 pieces = []
00567 if modeEnum.define == mode:
00568
00569
00570
00571
00572 if varName.startswith("-"):
00573
00574 if "-equiv" == varName.lower():
00575 for part in pieces:
00576 halves = part.split (",")
00577 if 2 != len (halves):
00578 print "Problem with -equiv '%s' in '%s'" % \
00579 (part, section)
00580 raise RuntimeError, \
00581 "Config file parser error '%s'(%d)" \
00582 % (fullLine, lineNum)
00583 if halves[1]:
00584 halves[1] = float (halves[1])
00585 if not halves[1] >= 0:
00586 print "Problem with -equiv ",\
00587 "'%s' in '%s'" % \
00588 (part, section)
00589 raise RuntimeError, \
00590 "Config file parser error '%s'(%d)" \
00591 % (fullLine, lineNum)
00592 GenObject.setEquivExpression (section,
00593 halves[0],
00594 halves[1])
00595 continue
00596
00597 optionsDict = {}
00598 for word in pieces:
00599 typeMatch = GenObject._typeRE.search (word)
00600 if typeMatch and \
00601 GenObject.types.isValidKey (typeMatch.group(1)):
00602 varType = typeMatch.group(1).lower()
00603 optionsDict['varType'] = GenObject.types (varType)
00604 continue
00605 defaultMatch = GenObject._defaultRE.search (word)
00606 if defaultMatch:
00607 optionsDict['default'] = defaultMatch.group(1)
00608 continue
00609 precMatch = GenObject._precRE.search (word)
00610 if precMatch:
00611 optionsDict['prec'] = float (precMatch.group (1))
00612 continue
00613 formMatch = GenObject._formRE.search (word)
00614 if formMatch:
00615 form = GenObject._doublePercentRE.\
00616 sub ('%', formMatch.group (1))
00617 optionsDict['form'] = form
00618 continue
00619
00620
00621 print "I don't understand '%s' in section '%s'." \
00622 % (word, option)
00623 raise RuntimeError, \
00624 "Config file parser error '%s'(%d)" \
00625 % (fullLine, lineNum)
00626 GenObject.addObjectVariable (objName, varName, \
00627 **optionsDict)
00628 else:
00629
00630
00631
00632 if len (pieces) < 1:
00633 continue
00634 fillname, pieces = pieces[0], pieces[1:]
00635
00636
00637 optionsDict = {}
00638 for word in pieces:
00639
00640
00641 print "I don't understand '%s' in section '%s'." \
00642 % (word, option)
00643 raise RuntimeError, \
00644 "Config file parser error '%s'(%d)" \
00645 % (fullLine, lineNum)
00646 tofillDict = GenObject._tofillDict.\
00647 setdefault (tupleName, {}).\
00648 setdefault (objName, {})
00649 partsList = GenObject.parseVariableTofill (fillname)
00650 tofillDict[varName] = [partsList, optionsDict]
00651
00652 for objName in GenObject._objsDict:
00653
00654 if not GenObject.isSingleton (objName):
00655 GenObject.addObjectVariable (objName, 'index',
00656 varType = GenObject.types.int,
00657 form = '%3d')
00658
00659
00660 @staticmethod
00661 def changeVariable (tupleName, objName, varName, fillname):
00662 """Updates the definition used to go from a Root object to a
00663 GenObject. 'tupleName' and 'objName' must already be defined."""
00664 parts = GenObject._dotRE.split (fillname)
00665 partsList = []
00666 for part in parts:
00667 parenMatch = GenObject._parenRE.search (part)
00668 mode = GenObject._objFunc.obj
00669 parens = []
00670 if parenMatch:
00671 part = parenMatch.group (1)
00672 mode = GenObject._objFunc.func
00673 parens = \
00674 GenObject._convertStringToParameters \
00675 (parenMatch.group (2))
00676 partsList.append( (part, mode, parens) )
00677 GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
00678
00679
00680
00681 @staticmethod
00682 def evaluateFunction (obj, partsList, debug=False):
00683 """Evaluates function described in partsList on obj"""
00684 for part in partsList:
00685 if debug: warn (part, spaces=15)
00686 obj = getattr (obj, part[0])
00687 if debug: warn (obj, spaces=15)
00688
00689
00690 if GenObject._objFunc.func == part[1]:
00691
00692 obj = obj (*part[2])
00693 if debug: warn (obj, spaces=18)
00694 return obj
00695
00696
00697 @staticmethod
00698 def _genObjectClone (objName, tupleName, obj, index = -1):
00699 """Creates a GenObject copy of Root object"""
00700 debug = GenObject._kitchenSinkDict.get ('debug', False)
00701 if objName == 'runevent':
00702 debug = False
00703 tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
00704 .get(objName, {})
00705 genObj = GenObject (objName)
00706 origObj = obj
00707 if debug: warn (objName, spaces = 9)
00708 for genVar, ntDict in tofillObjDict.iteritems():
00709 if debug: warn (genVar, spaces = 12)
00710
00711 partsList = ntDict[0]
00712
00713 obj = GenObject.evaluateFunction (origObj, partsList, debug)
00714 if debug: warn (obj, spaces=12)
00715 setattr (genObj, genVar, obj)
00716
00717 if index >= 0:
00718 setattr (genObj, 'index', index)
00719 return genObj
00720
00721
00722 @staticmethod
00723 def _rootObjectCopy (goSource, rootTarget):
00724 """Copies information from goSourse into Root Object"""
00725 objName = goSource._objName
00726 for varName in GenObject._objsDict [objName].keys():
00727
00728
00729 if varName.startswith ("_"):
00730 continue
00731 setattr( rootTarget, varName, goSource (varName) )
00732
00733
00734 @staticmethod
00735 def _rootObjectClone (obj):
00736 """Creates the approprite type of Root object and copies the
00737 information into it from the GO object."""
00738 objName = obj._objName
00739 classObj = GenObject._rootClassDict.get (objName)
00740 if not classObj:
00741 goName = GenObject.rootClassName (objName)
00742 classObj = GenObject._rootClassDict[ goName ]
00743 rootObj = classObj()
00744 for varName in GenObject._objsDict [objName].keys():
00745 setattr( rootObj, varName, obj (varName) )
00746 return rootObj
00747
00748
00749 @staticmethod
00750 def _rootDiffObject (obj1, obj2, rootObj = 0):
00751 """Given to GOs, it will create and fill the corresponding
00752 root diff object"""
00753 objName = obj1._objName
00754
00755 if not rootObj:
00756 diffName = GenObject.rootDiffClassName( objName )
00757 rootObj = GenObject._rootClassDict[diffName]()
00758 for varName in GenObject._objsDict [objName].keys():
00759 if varName.startswith ("_"): continue
00760 goType = GenObject._objsDict[objName][varName]['varType']
00761 if not goType in GenObject._basicSet:
00762
00763 continue
00764 setattr( rootObj, varName, obj1 (varName) )
00765 if goType == GenObject.types.string:
00766
00767 otherName = 'other_' + varName
00768 if obj1 (varName) != obj2 (varName):
00769
00770 setattr( rootObj, otherName, obj2 (varName) )
00771 else:
00772
00773 setattr( rootObj, otherName, '' )
00774 else:
00775
00776 deltaName = 'delta_' + varName
00777 setattr( rootObj, deltaName,
00778 obj2 (varName) - obj1 (varName) )
00779 return rootObj
00780
00781
00782 @staticmethod
00783 def setupOutputTree (outputFile, treeName, treeDescription = "",
00784 otherNtupleName = ""):
00785 """Opens the output file, loads all of the necessary shared
00786 object libraries, and returns the output file and tree. If
00787 'otherNtupleName' is given, it will check and make sure that
00788 only objects that are defined in it are written out."""
00789 rootfile = ROOT.TFile.Open (outputFile, "recreate")
00790 tree = ROOT.TTree (treeName, treeDescription)
00791 GenObject._loadGoRootLibrary()
00792 for objName in sorted (GenObject._objsDict.keys()):
00793 classname = GenObject.rootClassName (objName)
00794 rootObj = \
00795 GenObject._rootClassDict[objName] = \
00796 getattr (ROOT, classname)
00797 if GenObject.isSingleton (objName):
00798
00799 obj = GenObject._rootObjectDict[objName] = rootObj()
00800 tree.Branch (objName, classname, obj)
00801 else:
00802
00803
00804
00805 vec = \
00806 GenObject._rootObjectDict[objName] = \
00807 ROOT.std.vector( rootObj )()
00808 branchName = objName + "s"
00809 vecName = "vector<%s>" % classname
00810 tree.Branch( branchName, vecName, vec)
00811
00812
00813 return rootfile, tree
00814
00815
00816 @staticmethod
00817 def setupDiffOutputTree (outputFile, diffName, missingName,
00818 diffDescription = '', missingDescription = ''):
00819 """Opens the diff output file, loads all of the necessary
00820 shared object libraries, and returns the output file and tree.b"""
00821 rootfile = ROOT.TFile.Open (outputFile, "recreate")
00822 GenObject._loadGoRootLibrary()
00823
00824 diffTree = ROOT.TTree (diffName, diffDescription)
00825 runEventObject = getattr (ROOT, 'go_runevent')()
00826 diffTree.Branch ('runevent', 'go_runevent', runEventObject)
00827 GenObject._rootClassDict['runevent'] = runEventObject
00828 for objName in sorted (GenObject._objsDict.keys()):
00829 if objName == 'runevent': continue
00830 classname = GenObject.rootClassName (objName)
00831 GenObject._rootClassDict[classname] = getattr (ROOT, classname)
00832 contName = GenObject.rootDiffContClassName (objName)
00833 diffName = GenObject.rootDiffClassName (objName)
00834 rootObj = GenObject._rootClassDict[contName] = \
00835 getattr (ROOT, contName)
00836 GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
00837 obj = GenObject._rootObjectDict[objName] = rootObj()
00838 diffTree.Branch (objName, contName, obj)
00839
00840 missingTree = ROOT.TTree (missingName, missingDescription)
00841 rootRunEventClass = getattr (ROOT, 'go_runevent')
00842 firstOnly = GenObject._rootClassDict['firstOnly'] = \
00843 ROOT.std.vector( rootRunEventClass ) ()
00844 secondOnly = GenObject._rootClassDict['secondOnly'] = \
00845 ROOT.std.vector( rootRunEventClass ) ()
00846 missingTree.Branch ('firstOnly', 'vector<go_runevent>', firstOnly)
00847 missingTree.Branch ('secondOnly', 'vector<go_runevent>', secondOnly)
00848 return rootfile, diffTree, missingTree
00849
00850
00851 @staticmethod
00852 def _fillRootObjects (event):
00853 """Fills root objects from GenObject 'event'"""
00854 for objName, obj in sorted (event.iteritems()):
00855 if GenObject.isSingleton (objName):
00856
00857 GenObject._rootObjectCopy (obj,
00858 GenObject._rootObjectDict[objName])
00859 else:
00860
00861 vec = GenObject._rootObjectDict[objName]
00862 vec.clear()
00863 for goObj in obj:
00864 vec.push_back( GenObject._rootObjectClone (goObj) )
00865
00866
00867 @staticmethod
00868 def _fillRootDiffs (event1, event2):
00869 """Fills root diff containers from two GenObject 'event's"""
00870
00871
00872
00873 @staticmethod
00874 def isSingleton (objName):
00875 """Returns true if object is a singleton"""
00876 return GenObject._objsDict[objName].get('_singleton')
00877
00878
00879 @staticmethod
00880 def loadEventFromTree (eventTree, eventIndex,
00881 onlyRunEvent = False):
00882 """Loads event information from Root file (as interfaced by
00883 'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
00884 'event' containing lists of objects or singleton object. If
00885 'onlyRunEvent' is et to True, then only run and event number
00886 is read in from the tree."""
00887 debug = GenObject._kitchenSinkDict.get ('debug', False)
00888 tupleName = GenObject._kitchenSinkDict[eventTree]['tupleName']
00889 event = {}
00890
00891 isChain = eventTree.__class__.__name__ == 'TChain'
00892 if isChain:
00893
00894 eventTree.GetEntry (eventIndex)
00895 else:
00896
00897 eventTree.to(eventIndex)
00898 tofillDict = GenObject._tofillDict.get (tupleName)
00899 ntupleDict = GenObject._ntupleDict.get (tupleName)
00900 if not tofillDict:
00901 print "Don't know how to fill from '%s' ntuple." % tupleName
00902 return
00903 eventBranchName = ntupleDict['runevent']
00904 for objName in tofillDict:
00905 branchName = ntupleDict[objName]
00906 if onlyRunEvent and branchName != eventBranchName:
00907
00908 continue
00909
00910 if not branchName:
00911
00912 continue
00913 if isChain:
00914
00915 objects = getattr (eventTree, branchName)
00916 else:
00917
00918 shortcut = ntupleDict.get('_shortcut', {}).get(branchName)
00919 if shortcut:
00920 objects = GenObject.evaluateFunction (eventTree, shortcut)
00921 else:
00922 eventTree.toBegin()
00923 handle = ntupleDict.get('_handle', {}).get(branchName)
00924 label = ntupleDict.get('_label' , {}).get(branchName)
00925 if not handle or not label:
00926 raise RuntimeError, "Missing handle or label for '%s'"\
00927 % branchName
00928 if not eventTree.getByLabel (label, handle):
00929 raise RuntimeError, "not able to get %s for %s" \
00930 % (label, branchName)
00931 objects = handle.product()
00932
00933 if GenObject.isSingleton (objName):
00934 event[objName] = GenObject.\
00935 _genObjectClone (objName,
00936 tupleName,
00937 objects)
00938 continue
00939
00940 if debug: warn (objName, spaces = 3)
00941 event[objName] = []
00942 for index, obj in enumerate (objects):
00943 event[objName].append( GenObject.\
00944 _genObjectClone (objName,
00945 tupleName,
00946 obj,
00947 index) )
00948 del objects
00949
00950
00951
00952
00953 return event
00954
00955
00956 @staticmethod
00957 def printEvent (event):
00958 """Prints out event dictionary. Mostly for debugging"""
00959
00960 for objName, obj in sorted (event.iteritems()):
00961
00962
00963 if GenObject.isSingleton (objName):
00964 print "%s: %s" % (objName, obj)
00965
00966 for objName, obj in sorted (event.iteritems()):
00967
00968
00969 if not GenObject.isSingleton (objName):
00970
00971 print "%s:" % objName
00972 for single in obj:
00973 print " ", single
00974 print
00975
00976
00977 @staticmethod
00978 def setAliases (eventTree, tupleName):
00979 """runs SetAlias on all saved aliases"""
00980 aliases = GenObject._ntupleDict[tupleName].get('_alias', {})
00981 for name, alias in aliases.iteritems():
00982 eventTree.SetAlias (name, alias)
00983
00984
00985 @staticmethod
00986 def changeAlias (tupleName, name, alias):
00987 """Updates an alias for an object for a given tuple"""
00988 aliasDict = GenObject._ntupleDict[tupleName]['_alias']
00989 if not aliasDict.has_key (name):
00990 raise RuntimeError, "unknown name '%s' in tuple '%s'" % \
00991 (name, tupleName)
00992 aliasDict[name] = alias
00993
00994
00995 @staticmethod
00996 def changeLabel (tupleName, objectName, label):
00997 """Updates an label for an object for a given tuple"""
00998 labelDict = GenObject._ntupleDict[tupleName]['_label']
00999 if not labelDict.has_key (objectName):
01000 raise RuntimeError, "unknown name '%s' in tuple '%s'" % \
01001 (objectName, tupleName)
01002 label = tuple( GenObject._commaRE.split( label ) )
01003 labelDict[objectName] = label
01004
01005
01006 @staticmethod
01007 def prepareTuple (tupleName, files, numEventsWanted = 0):
01008 """Given the tuple name and list of files, returns either a
01009 TChain or EventTree, and number of entries"""
01010 if "GenObject" == tupleName:
01011 GenObject.prepareToLoadGenObject()
01012 if not isinstance (files, list):
01013
01014 files = [files]
01015 ntupleDict = GenObject._ntupleDict[tupleName]
01016 treeName = ntupleDict["_tree"]
01017 if ntupleDict.get('_useChain'):
01018 chain = ROOT.TChain (treeName)
01019 for filename in files:
01020 chain.AddFile (filename)
01021 numEntries = chain.GetEntries()
01022
01023 else:
01024 chain = Events (files, forceEvent=True)
01025 numEntries = chain.size()
01026 chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
01027 if numEventsWanted and numEventsWanted < numEntries:
01028 numEntries = numEventsWanted
01029 chainDict['numEntries'] = numEntries
01030 chainDict['tupleName' ] = tupleName
01031 return chain
01032
01033
01034 @staticmethod
01035 def getRunEventEntryDict (chain, tupleName, numEntries):
01036 """Returns a dictionary of run, event tuples to entryIndicies"""
01037 reeDict = {}
01038 for entryIndex in xrange (numEntries):
01039 event = GenObject.loadEventFromTree (chain,
01040 entryIndex,
01041 onlyRunEvent = True)
01042 runevent = event['runevent']
01043 reeDict[ GenObject._re2key (runevent) ] = entryIndex
01044
01045 del event
01046 return reeDict
01047
01048
01049 @staticmethod
01050 def _re2key (runevent):
01051 """Given a GO 'runevent' object, returns a sortable key"""
01052
01053
01054 if not GenObject._runEventListDone:
01055 GenObject._runEventListDone = True
01056 ignoreSet = set( ['run', 'event'] )
01057 for varName in sorted (runevent.__dict__.keys()):
01058 if varName.startswith ('_') or varName in ignoreSet:
01059 continue
01060 form = runevent.getVariableProperty (varName, "form")
01061 if not form:
01062 form = '%s'
01063 GenObject._runEventList.append ((varName, form))
01064 key = 'run:%d event:%d' % (runevent.run, runevent.event)
01065 for items in GenObject._runEventList:
01066 varName = items[0]
01067 form = ' %s:%s' % (varName, items[1])
01068 key += form % runevent.getVariableProperty (varName)
01069 return key
01070
01071
01072 @staticmethod
01073 def _key2re (key, runevent=None):
01074 """Given a key, returns a GO 'runevent' object"""
01075 if not runevent:
01076 runevent = GenObject ('runevent')
01077 words = GenObject._spacesRE.split (key)
01078 for word in words:
01079 match = GenObject._singleColonRE.search (word)
01080 if match:
01081
01082
01083
01084 runevent.__setattr__ (match.group(1), int( match.group(2) ))
01085 return runevent
01086
01087
01088 @staticmethod
01089 def compareRunEventDicts (firstDict, secondDict):
01090 """Compares the keys of the two dicts and returns three sets:
01091 the overlap, first but not second, and second but not first."""
01092 overlap = set()
01093 firstOnly = set()
01094 secondOnly = set()
01095
01096 for key in firstDict.keys():
01097 if secondDict.has_key (key):
01098 overlap.add (key)
01099 else:
01100 firstOnly.add (key)
01101
01102
01103 for key in secondDict.keys():
01104 if not firstDict.has_key (key):
01105 secondOnly.add (key)
01106
01107 return overlap, firstOnly, secondOnly
01108
01109
01110 @staticmethod
01111 def pairEquivalentObjects (vec1, vec2):
01112 """Finds the equivalent objects in the two vectors"""
01113 len1, len2 = len (vec1), len (vec2)
01114 debug = GenObject._kitchenSinkDict.get ('debug', False)
01115 if not len1 or not len2:
01116
01117 if len1:
01118 noMatch1Set = set( xrange(len1) )
01119 else:
01120 noMatch1Set = set ()
01121 if len2:
01122 noMatch2Set = set( xrange(len2) )
01123 else:
01124 noMatch2Set = set ()
01125 if debug: warn ("Nothing found", sapces=6)
01126 return set(), noMatch1Set, noMatch2Set
01127 objName = vec1[0]._objName
01128 equivList = GenObject._equivDict[objName]
01129 firstDict = {}
01130 secondDict = {}
01131
01132 if GenObject._kitchenSinkDict.get ('strictPairing') or \
01133 equivList == [('index', 0)]:
01134
01135 matchedSet = set (zip ( range( min (len1, len2) ),
01136 range( min (len1, len2) ) ) )
01137 if len1 > len2:
01138
01139
01140 noMatch1Set = set (range(len2, len1 + 1))
01141 else:
01142 noMatch1Set = set()
01143 if len2 > len1:
01144
01145 noMatch2Set = set (range(len1, len2 + 1))
01146 else:
01147 noMatch2Set = set()
01148 return matchedSet, noMatch1Set, noMatch2Set
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 for index1 in xrange (len1):
01164 objList = []
01165 obj1 = vec1[index1]
01166 for index2 in xrange (len2):
01167 total = 0.
01168 obj2 = vec2[index2]
01169 ok = True
01170 for equiv in equivList:
01171 var, precision = equiv[0], equiv[1]
01172 val1 = obj1 (var)
01173 val2 = obj2 (var)
01174
01175 if precision:
01176 value = abs (val1 - val2) / precision
01177 if value >= 1.:
01178 ok = False
01179 break
01180 total += value ** 2
01181 elif val1 != val2:
01182 ok = False
01183 break
01184 if ok:
01185 objList.append( (total, index2) )
01186 objList.sort()
01187 firstDict[index1] = objList
01188
01189
01190 for index2 in xrange (len2):
01191 objList = []
01192 obj2 = vec2[index2]
01193 for index1 in xrange (len1):
01194 total = 0.
01195 obj1 = vec1[index1]
01196 ok = True
01197 for equiv in equivList:
01198 var, precision = equiv[0], equiv[1]
01199 val2 = obj2 (var)
01200 val1 = obj1 (var)
01201
01202 if precision:
01203 value = abs (val2 - val1) / precision
01204 if value > 1.:
01205 ok = False
01206 break
01207 total += value ** 2
01208 elif val2 != val1:
01209 ok = False
01210 break
01211 if ok:
01212 objList.append( (total, index1) )
01213 objList.sort()
01214 secondDict[index2] = objList
01215
01216
01217 matchedSet = set()
01218 noMatch1Set = set()
01219 firstDictKeys = sorted (firstDict.keys())
01220 for index1 in firstDictKeys:
01221 list1 = firstDict[index1]
01222
01223 if not len (list1):
01224
01225 noMatch1Set.add (index1)
01226 continue
01227
01228 best1 = list1[0]
01229 index2 = best1[1]
01230
01231 list2 = secondDict.get (index2, [])
01232 if len(list2) and list2[0][1] == index1:
01233 matchedSet.add( (index1, index2) )
01234
01235 del firstDict[index1]
01236 del secondDict[index2]
01237 else:
01238
01239 noMatch1Set.add (index1)
01240 noMatch2Set = set( secondDict.keys() )
01241 return matchedSet, noMatch1Set, noMatch2Set
01242
01243
01244 @staticmethod
01245 def compareTwoItems (item1, item2):
01246 """Compares all of the variables making sure they are the same
01247 on the two objects."""
01248 objName = item1._objName
01249 problems = {}
01250 relative = GenObject._kitchenSinkDict.get ('relative', False)
01251 for varName in GenObject._objsDict[objName].keys():
01252 prec = item1.getVariableProperty (varName, 'prec')
01253 if prec:
01254
01255 if relative:
01256 val1 = item1(varName)
01257 val2 = item2(varName)
01258 numerator = 2 * abs (val1 - val2)
01259 denominator = abs(val1) + abs(val2)
01260 if not denominator:
01261
01262
01263 continue
01264 value = numerator / denominator
01265 if value > prec:
01266
01267 problems[varName] = value
01268 else:
01269 value = abs( item1(varName) - item2(varName) )
01270 if value > prec:
01271
01272 problems[varName] = value
01273 else:
01274
01275 if item1(varName) != item2(varName):
01276
01277 val1, val2 = item1(varName), item2(varName)
01278 if val1 > val2:
01279 val1, val2 = val2, val1
01280 problems[varName] = "%s != %s" % (val1, val2)
01281
01282 return problems
01283
01284
01285 @staticmethod
01286 def blurEvent (event, value, where = ""):
01287 """For debugging purposes only. Will deliberately change
01288 values of first tree to verify that script is correctly
01289 finding problems."""
01290 for objName in sorted (event.keys()):
01291 if "runevent" == objName:
01292
01293 continue
01294 if GenObject.isSingleton (objName):
01295
01296 continue
01297 count = 0
01298 for obj in event[objName]:
01299 count += 1
01300 for varName in GenObject._objsDict[objName].keys():
01301 if isinstance (obj.__dict__[varName], str):
01302
01303 continue
01304 randNumber = random.random()
01305
01306 if randNumber < GenObject._kitchenSinkDict['blurRate']:
01307 print " %s: changing '%s' of '%s:%d'" \
01308 % (where, varName, obj._objName, count)
01309
01310
01311 obj.__dict__[varName] += value
01312
01313
01314 @staticmethod
01315 def compareTwoTrees (chain1, chain2, **kwargs):
01316 """Given all of the necessary information, this routine will
01317 go through and compare two trees making sure they are
01318 'identical' within requested precision. If 'diffOutputName'
01319 is passed in, a root file with a diffTree and missingTree will
01320 be produced."""
01321 print "Comparing Two Trees"
01322 diffOutputName = kwargs.get ('diffOutputName')
01323 tupleName1 = GenObject._kitchenSinkDict[chain1]['tupleName']
01324 numEntries1 = GenObject._kitchenSinkDict[chain1]['numEntries']
01325 tupleName2 = GenObject._kitchenSinkDict[chain2]['tupleName']
01326 numEntries2 = GenObject._kitchenSinkDict[chain2]['numEntries']
01327 debug = GenObject._kitchenSinkDict.get ('debug', False)
01328 ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
01329 ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
01330 overlap, firstOnly, secondOnly = \
01331 GenObject.compareRunEventDicts (ree1, ree2)
01332 if diffOutputName:
01333 rootfile, diffTree, missingTree = \
01334 GenObject.setupDiffOutputTree (diffOutputName,
01335 'diffTree',
01336 'missingTree')
01337 if firstOnly:
01338 vec = GenObject._rootClassDict['firstOnly']
01339 for key in firstOnly:
01340 runevent = GenObject._key2re (key)
01341 vec.push_back( GenObject._rootObjectClone( runevent ) )
01342 if secondOnly:
01343 vec = GenObject._rootClassDict['secondOnly']
01344 for key in secondOnly:
01345 runevent = GenObject._key2re (key)
01346 vec.push_back( GenObject._rootObjectClone( runevent ) )
01347 missingTree.Fill()
01348 resultsDict = {}
01349 if firstOnly:
01350 resultsDict.setdefault ('_runevent', {})['firstOnly'] = \
01351 len (firstOnly)
01352 if secondOnly:
01353 resultsDict.setdefault ('_runevent', {})['secondOnly'] = \
01354 len (secondOnly)
01355 resultsDict['eventsCompared'] = len (overlap)
01356 for reTuple in sorted(overlap):
01357
01358
01359 if diffOutputName:
01360 GenObject._key2re (reTuple,
01361 GenObject._rootClassDict['runevent'])
01362 if debug: warn ('event1', blankLines = 3)
01363 event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
01364 if debug: warn ('event2', blankLines = 3)
01365 event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
01366 if GenObject._kitchenSinkDict.get('printEvent'):
01367 print "event1:"
01368 GenObject.printEvent (event1)
01369 print "event2:"
01370 GenObject.printEvent (event2)
01371 if GenObject._kitchenSinkDict.get('blur'):
01372 where = reTuple
01373 GenObject.blurEvent (event1,
01374 GenObject._kitchenSinkDict['blur'],
01375 where)
01376 for objName in sorted (event1.keys()):
01377 if "runevent" == objName:
01378
01379 continue
01380 if not GenObject._equivDict.get (objName):
01381
01382
01383 continue
01384 if GenObject.isSingleton (objName):
01385
01386 print "singleton"
01387 continue
01388
01389 rootObj = 0
01390 if diffOutputName:
01391 rootObj = GenObject._rootObjectDict[objName]
01392 rootObj.clear()
01393 vec1 = event1[objName]
01394 vec2 = event2[objName]
01395 matchedSet, noMatch1Set, noMatch2Set = \
01396 GenObject.pairEquivalentObjects (vec1, vec2)
01397 if noMatch1Set or noMatch2Set:
01398
01399
01400 count1 = len (noMatch1Set)
01401 count2 = len (noMatch2Set)
01402 key = (count1, count2)
01403 countDict = resultsDict.\
01404 setdefault (objName, {}).\
01405 setdefault ('_missing', {})
01406 if countDict.has_key (key):
01407 countDict[key] += 1
01408 else:
01409 countDict[key] = 1
01410
01411 if diffOutputName:
01412
01413 for index in sorted(list(noMatch1Set)):
01414 goObj = vec1 [index]
01415 rootObj.firstOnly.push_back ( GenObject.\
01416 _rootObjectClone \
01417 (goObj) )
01418
01419 for index in sorted(list(noMatch2Set)):
01420 goObj = vec2 [index]
01421 rootObj.secondOnly.push_back ( GenObject.\
01422 _rootObjectClone \
01423 (goObj) )
01424
01425
01426 for pair in sorted(list(matchedSet)):
01427 if diffOutputName:
01428 rootDiffObj = GenObject._rootDiffObject \
01429 ( vec1[ pair[1 - 1] ],
01430 vec2[ pair[2 - 1] ] )
01431 rootObj.diff.push_back ( rootDiffObj )
01432 problems = GenObject.\
01433 compareTwoItems (vec1[ pair[1 - 1] ],
01434 vec2[ pair[2 - 1] ])
01435 if problems.keys():
01436
01437 for varName in problems.keys():
01438 countDict = resultsDict.\
01439 setdefault (objName, {}).\
01440 setdefault ('_var', {})
01441 if countDict.has_key (varName):
01442 countDict[varName] += 1
01443 else:
01444 countDict[varName] = 1
01445 key = 'count_%s' % objName
01446 if not resultsDict.has_key (key):
01447 resultsDict[key] = 0
01448 resultsDict[key] += len (matchedSet)
01449
01450 del vec1
01451 del vec2
01452
01453 if diffOutputName:
01454 diffTree.Fill()
01455 del event1
01456 del event2
01457
01458 if diffOutputName:
01459 diffTree.Write()
01460 missingTree.Write()
01461 rootfile.Close()
01462 return resultsDict
01463
01464
01465 @staticmethod
01466 def saveTupleAs (chain, rootFile):
01467 """Saves a chain as a GO tree"""
01468 print "saveTupleAs"
01469 rootfile, tree = GenObject.setupOutputTree (rootFile, "goTree")
01470 numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
01471 for entryIndex in xrange (numEntries):
01472 event = GenObject.loadEventFromTree (chain, entryIndex)
01473 if GenObject._kitchenSinkDict.get('blur'):
01474 where = "run %d event %d" % (event['runevent'].run,
01475 event['runevent'].event)
01476 if random.random() < GenObject._kitchenSinkDict.get('blur'):
01477
01478 print "Dropping", where
01479 continue
01480 GenObject.blurEvent (event,
01481 GenObject._kitchenSinkDict['blur'],
01482 where)
01483
01484 if GenObject._kitchenSinkDict.get('printEvent'):
01485 GenObject.printEvent (event)
01486 GenObject._fillRootObjects (event)
01487 tree.Fill()
01488 tree.Write()
01489 rootfile.Close()
01490
01491
01492 @staticmethod
01493 def setGlobalFlag (key, value):
01494 """Sets a global flag in _kitchenSinkDict"""
01495 GenObject._kitchenSinkDict [key] = value
01496
01497
01498 @staticmethod
01499 def printTuple (chain):
01500 """Prints out all events to stdout"""
01501 numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
01502 debug = GenObject._kitchenSinkDict.get ('debug', False)
01503 if debug: warn (numEntries)
01504 for entryIndex in xrange (numEntries):
01505 if debug: warn (entryIndex, spaces=3)
01506 event = GenObject.loadEventFromTree (chain, entryIndex)
01507 GenObject.printEvent (event)
01508 if debug: warn(spaces=3)
01509
01510 @staticmethod
01511 def _convertStringToParameters (string):
01512 """Convert comma-separated string into a python list of
01513 parameters. Currently only understands strings, floats, and
01514 integers."""
01515 retval = []
01516 words = GenObject._commaRE.split (string)
01517 for word in words:
01518 if not len (word):
01519 continue
01520 match = GenObject._singleQuoteRE.search (word)
01521 if match:
01522 retval.append (match.group (1))
01523 continue
01524 match = GenObject._doubleQuoteRE.search (word)
01525 if match:
01526 retval.append (match.group (1))
01527 continue
01528 try:
01529 val = int (word)
01530 retval.append (val)
01531 continue
01532 except:
01533 pass
01534 try:
01535 val = float (word)
01536 retval.append (val)
01537 continue
01538 except:
01539 pass
01540
01541 raise RuntimeError, "Unknown parameter '%s'." % word
01542 return retval
01543
01544
01545
01546
01547
01548
01549
01550 def __init__ (self, objName):
01551 """Class initializer"""
01552 if not GenObject._objsDict.has_key (objName):
01553
01554
01555 print "Error: GenObject does not know about object '%s'." % objName
01556 raise RuntimeError, "Failed to create GenObject object."
01557 self._localObjsDict = GenObject._objsDict [objName]
01558 self._objName = objName;
01559 for key, varDict in self._localObjsDict.iteritems():
01560
01561
01562 if key.startswith ("_"):
01563 continue
01564 self.setValue (key, varDict['default'])
01565
01566
01567 def setValue (self, name, value):
01568 """Wrapper for __setattr___"""
01569 self.__setattr__ (name, value)
01570
01571
01572 def getVariableProperty (self, var, key):
01573 """ Returns property assoicated with 'key' for variable 'var'
01574 of object of the same type as 'self'. Returns 'None' if 'var'
01575 or 'key' is not defined."""
01576 return GenObject._objsDict.get (self._objName,
01577 {}).get (var, {}). get (key, None)
01578
01579
01580 def __setattr__ (self, name, value):
01581 """Controls setting of values."""
01582 if name.startswith ("_"):
01583
01584 object.__setattr__ (self, name, value)
01585 else:
01586
01587
01588
01589 if not self._localObjsDict.has_key (name):
01590
01591 print "Warning: '%s' for class '%s' not setup. Skipping." % \
01592 (name, self._objName)
01593 return
01594 varType = self.getVariableProperty (name, 'varType')
01595
01596 if GenObject.types.int == varType:
01597 try:
01598
01599
01600 value = int (value)
01601 except:
01602
01603 value = int( float( value ) )
01604 elif GenObject.types.long == varType:
01605 try:
01606
01607
01608 value = long (value)
01609 except:
01610
01611 value = long( float( value ) )
01612 elif GenObject.types.float == varType:
01613
01614 value = float (value)
01615 elif GenObject.types.string == varType:
01616
01617 value = str (value)
01618
01619 object.__setattr__ (self, name, value)
01620
01621
01622 def __call__ (self, key):
01623 """Makes object callable"""
01624 return object.__getattribute__ (self, key)
01625
01626
01627 def __str__ (self):
01628 """String representation"""
01629 retval = ""
01630 for varName, value in sorted (self.__dict__.iteritems()):
01631 if varName.startswith ('_'): continue
01632 form = self.getVariableProperty (varName, "form")
01633 if form:
01634 format = "%s:%s " % (varName, form)
01635 retval = retval + format % value
01636 else:
01637 retval = retval + "%s:%s " % (varName, value)
01638 return retval
01639