CMS 3D CMS Logo

GenObject.py
Go to the documentation of this file.
1 ## Note: Please do not use or modify any data or functions with a
2 ## leading underscore. If you "mess" with the internal structure,
3 ## the classes may not function as intended.
4 
5 
6 from FWCore.Utilities.Enumerate import Enumerate
7 from DataFormats.FWLite import Events, Handle
8 import re
9 import os
10 import copy
11 import pprint
12 import random
13 import sys
14 import inspect
15 import ROOT
16 from functools import reduce
17 ROOT.gROOT.SetBatch()
18 
19 # regex for reducing 'warn()' filenames
20 filenameRE = re.compile (r'.+/Validation/Tools/')
21 # Whether warn() should print anythingg
22 quietWarn = False
23 
24 def setQuietWarn (quiet = True):
25  global quietWarn
26  quietWarn = quiet
27 
28 
29 def warn (*args, **kwargs):
30  """print out warning with line number and rest of arguments"""
31  if quietWarn: return
32  frame = inspect.stack()[1]
33  filename = frame[1]
34  lineNum = frame[2]
35  #print filename, filenameRE
36  filename = filenameRE.sub ('', filename)
37  #print "after '%s'" % filename
38  blankLines = kwargs.get('blankLines', 0)
39  if blankLines:
40  print '\n' * blankLines
41  spaces = kwargs.get('spaces', 0)
42  if spaces:
43  print ' ' * spaces,
44  if len (args):
45  print "%s (%s): " % (filename, lineNum),
46  for arg in args:
47  print arg,
48  print
49  else:
50  print "%s (%s):" % (filename, lineNum)
51 
52 
53 class GenObject (object):
54  """Infrastruture to define general objects and their attributes."""
55 
56  ########################
57  ## Static Member Data ##
58  ########################
59 
60  types = Enumerate ("float int long string", "type")
61  _objFunc = Enumerate ("obj func", "of")
62  _cppType = dict ( {types.float : 'double',
63  types.int : 'int',
64  types.long : 'long',
65  types.string : 'std::string' } )
66  _basicSet = set( [types.float, types.int, types.float,
67  types.string] )
68  _defaultValue = dict ( {types.float : 0.,
69  types.int : 0,
70  types.long : 0,
71  types.string : '""' } )
72  _objsDict = {} # info about GenObjects
73  _equivDict = {} # hold info about 'equivalent' muons
74  _ntupleDict = {} # information about different ntuples
75  _tofillDict = {} # information on how to fill from different ntuples
76  _rootObjectDict = {} # hold objects and stl::vectors to objects
77  # hooked up to a root tree
78  _rootClassDict = {} # holds classes (not instances) associated with
79  # a given GenObject
80  _kitchenSinkDict = {} # dictionary that holds everything else...
81  _runEventList = []
82  _runEventListDone = False
83  uselessReturnCode = 1 << 7 # pick a unique return code
84 
85  ####################
86  ## Compile Regexs ##
87  ####################
88  _nonSpacesRE = re.compile (r'\S')
89  _colonRE = re.compile (r'\s*:\s*')
90  _singleColonRE = re.compile (r'(.+?):(.+)')
91  _doubleColonRE = re.compile (r'(.+?):(.+?):(.+)')
92  _doublePercentRE = re.compile (r'%%')
93  _parenRE = re.compile (r'(.+)\((.*)\)')
94  _spacesRE = re.compile (r'\s+')
95  _dotRE = re.compile (r'\s*\.\s*')
96  _commaRE = re.compile (r'\s*,\s*')
97  _singleQuoteRE = re.compile (r'^\'(.+)\'$')
98  _doubleQuoteRE = re.compile (r'^\"(.+)\"$')
99  _bracketRE = re.compile (r'\[\s*(.+?)\s*\]')
100  _commentRE = re.compile (r'#.+$')
101  _aliasRE = re.compile (r'alias=(\S+)', re.IGNORECASE)
102  _labelRE = re.compile (r'label=(\S+)', re.IGNORECASE)
103  _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
104  _singletonRE = re.compile (r'singleton', re.IGNORECASE)
105  _typeRE = re.compile (r'type=(\S+)', re.IGNORECASE)
106  _defaultRE = re.compile (r'default=(\S+)', re.IGNORECASE)
107  _shortcutRE = re.compile (r'shortcut=(\S+)', re.IGNORECASE)
108  _precRE = re.compile (r'prec=(\S+)', re.IGNORECASE)
109  _formRE = re.compile (r'form=(\S+)', re.IGNORECASE)
110  _nonAlphaRE = re.compile (r'\W')
111  _percentAsciiRE = re.compile (r'%([0-9a-fA-F]{2})')
112 
113  #############################
114  ## Static Member Functions ##
115  #############################
116 
117  @staticmethod
118  def char2ascii (match):
119  return "%%%02x" % ord (match.group(0))
120 
121  @staticmethod
122  def ascii2char (match):
123  return chr( int( match.group(1), 16 ) )
124 
125  @staticmethod
127  """Use a web like encoding of characters that are non-alphanumeric"""
128  return GenObject._nonAlphaRE.sub( GenObject.char2ascii, line )
129 
130  @staticmethod
132  """Decode lines encoded with encodeNonAlphanumerics()"""
133  return GenObject._percentAsciiRE.sub( GenObject.ascii2char, line )
134 
135 
136  @staticmethod
137  def addObjectVariable (obj, var, **optionsDict):
138  """ User passes in in object and variable names."""
139  if 'varType' not in optionsDict:
140  optionsDict['varType'] = GenObject.types.float
141  varType = optionsDict['varType']
142  if not GenObject.types.isValidValue (varType):
143  print "Type '%s' not valid. Skipping (%s, %s, %s)." % \
144  (varType, obj, var, varType)
145  return
146  if 'default' not in optionsDict:
147  optionsDict['default'] = GenObject._defaultValue[varType]
148  if obj.startswith ("_") or var.startswith ("_"):
149  print "Skipping (%s, %s, %s) because of leading underscore." % \
150  (obj, var, varType)
151  return
152  GenObject._objsDict.setdefault (obj, {}).setdefault (var, optionsDict)
153 
154 
155  @staticmethod
156  def getVariableProperty (obj, var, key):
157  """Returns property assoicated with 'key' for variable 'var'
158  of object 'obj'. Returns 'None' if any of the above are not
159  defined."""
160  return GenObject._objsDict.get (obj, {}).get (var, {}). get (key, None)
161 
162 
163  @staticmethod
164  def setEquivExpression (obj, variable, precision):
165  """Adds an equivalence constraint. Must have at least one to
166  compare GO objects."""
167  if obj.startswith ("_"):
168  print "Skipping (%s, %s) because of leading underscore." % \
169  (obj, expression)
170  return
171  GenObject._equivDict.setdefault (obj,[]).append ( (variable,
172  precision) )
173 
174 
175  @staticmethod
176  def printGlobal():
177  """Meant for debugging, but ok if called by user"""
178  print "objs: "
179  pprint.pprint (GenObject._objsDict, indent=4)
180  print "equiv: "
181  pprint.pprint (GenObject._equivDict, indent=4)
182  print "ntuple: "
183  pprint.pprint (GenObject._ntupleDict, indent=4)
184  print "tofill: "
185  pprint.pprint (GenObject._tofillDict, indent=4)
186  print "kitchenSink: "
187  pprint.pprint (GenObject._kitchenSinkDict, indent=4)
188  print "rootClassDict"
189  pprint.pprint (GenObject._rootClassDict, indent=4)
190 
191 
192  @staticmethod
193  def checksum (str):
194  """Returns a string of hex value of a checksum of input
195  string."""
196  return hex( reduce( lambda x, y : x + y, map(ord, str) ) )[2:]
197 
198 
199  @staticmethod
200  def rootClassName (objName):
201  """Returns the name of the equivalent Root object"""
202  return "go_" + objName
203 
204 
205  @staticmethod
206  def rootDiffClassName (objName):
207  """Returns the name of the equivalent Root diff object"""
208  return "goDiff_" + objName
209 
210 
211  @staticmethod
212  def rootDiffContClassName (objName):
213  """Returns the name of the equivalent Root diff container
214  object"""
215  return "goDiffCont_" + objName
216 
217 
218  @staticmethod
219  def _setupClassHeader (className, noColon = False):
220  """Returns a string with the class header for a class
221  'classname'"""
222  retval = "\nclass %s\n{\n public:\n" % className
223  retval += " typedef std::vector< %s > Collection;\n\n" % className
224  # constructor
225  if noColon:
226  retval += " %s()" % className
227  else:
228  retval += " %s() :\n" % className
229  return retval
230 
231 
232  @staticmethod
233  def _finishClassHeader (className, datadec):
234  """Returns a stringg with the end of a class definition"""
235  retval = "\n {}\n" + datadec + "};\n"
236  retval += "#ifdef __MAKECINT__\n#pragma link C++ class " + \
237  "vector< %s >+;\n#endif\n\n" % className
238  return retval
239 
240 
241  @staticmethod
242  def _createCppClass (objName):
243  """Returns a string containing the '.C' file necessary to
244  generate a shared object library with dictionary."""
245  if objName not in GenObject._objsDict:
246  # not good
247  print "Error: GenObject does not know about object '%s'." % objName
248  raise RuntimeError("Failed to create C++ class.")
249  className = GenObject.rootClassName (objName)
250  diffName = GenObject.rootDiffClassName (objName)
251  contName = GenObject.rootDiffContClassName (objName)
252  goClass = GenObject._setupClassHeader (className)
253  diffClass = GenObject._setupClassHeader (diffName)
254  contClass = GenObject._setupClassHeader (contName, noColon = True)
255  goDataDec = diffDataDec = contDataDec = "\n // data members\n"
256  first = True
257  for key in sorted( GenObject._objsDict[objName].keys() ):
258  if key.startswith ("_"): continue
259  varTypeList = GenObject._objsDict[objName][key]
260  cppType = GenObject._cppType[ varTypeList['varType'] ]
261  default = varTypeList['default']
262  if first:
263  first = False
264  else:
265  goClass += ",\n"
266  diffClass += ',\n'
267  goClass += " %s (%s)" % (key, default)
268  goDataDec += " %s %s;\n" % (cppType, key)
269  # is this a basic class?
270  goType = varTypeList['varType']
271  if goType in GenObject._basicSet:
272  # basic type
273  diffClass += " %s (%s),\n" % (key, default)
274  diffDataDec += " %s %s;\n" % (cppType, key)
275  if goType == GenObject.types.string:
276  # string
277  otherKey = 'other_' + key
278  diffClass += " %s (%s)" % (otherKey, default)
279  diffDataDec += " %s %s;\n" % (cppType, otherKey)
280  else:
281  # float, long, or int
282  deltaKey = 'delta_' + key
283  diffClass += " %s (%s)" % (deltaKey, default)
284  diffDataDec += " %s %s;\n" % (cppType, deltaKey)
285  else:
286  raise RuntimeError("Shouldn't be here yet.")
287  # definition
288  # do contClass
289  if GenObject.isSingleton (objName):
290  # singleton
291  contDataDec += " %s diff;\n" % diffName
292  contDataDec += " void setDiff (const %s &rhs)" % diffName + \
293  " { diff = rhs; }\n"
294  else:
295  # vector of objects
296  contDataDec += " void clear() {firstOnly.clear(); secondOnly.clear(); diff.clear(); }\n"
297  contDataDec += " %s::Collection firstOnly;\n" % className
298  contDataDec += " %s::Collection secondOnly;\n" % className
299  contDataDec += " %s::Collection diff;\n" % diffName
300  # give me a way to clear them all at once
301  # Finish off the classes
302  goClass += GenObject._finishClassHeader (className, goDataDec)
303  diffClass += GenObject._finishClassHeader (diffName, diffDataDec)
304  contClass += GenObject._finishClassHeader (contName, contDataDec)
305  if objName == 'runevent':
306  # we don't want a diff class for this
307  diffClass = ''
308  contClass = ''
309  return goClass + diffClass + contClass
310 
311 
312  @staticmethod
314  """Loads Root shared object library associated with all
315  defined GenObjects. Will create library if necessary."""
316  print "Loading GO Root Library"
317  key = "_loadedLibrary"
318  if GenObject._kitchenSinkDict.get (key):
319  # Already done, don't do it again:
320  return
321  # Mark it as done
322  GenObject._kitchenSinkDict[key] = True
323  # Generate source code
324  sourceCode = "#include <string>\n#include <vector>\n" \
325  + "using namespace std;\n"
326  for objClassName in sorted( GenObject._objsDict.keys() ):
327  sourceCode += GenObject._createCppClass (objClassName)
328  GenObjectRootLibDir = "genobjectrootlibs"
329  if not os.path.exists (GenObjectRootLibDir):
330  os.mkdir (GenObjectRootLibDir)
331  key = GenObject.checksum( sourceCode )
332  basename = "%s_%s" % ("GenObject", key)
333  SO = "%s/%s_C" % (GenObjectRootLibDir, basename)
334  linuxSO = "%s.so" % SO
335  windowsSO = "%s.dll" % SO
336  if not os.path.exists (linuxSO) and not os.path.exists (windowsSO):
337  print "creating SO"
338  filename = "%s/%s.C" % (GenObjectRootLibDir, basename)
339  if not os.path.exists (filename):
340  print "creating .C file"
341  target = open (filename, "w")
342  target.write (sourceCode)
343  target.close()
344  else:
345  print "%s exists" % filename
346  ## command = "echo .L %s+ | root.exe -b" % filename
347  ## os.system (command)
348  ROOT.gSystem.CompileMacro (filename, "k")
349  else:
350  print "loading %s" % SO
351  ROOT.gSystem.Load(SO)
352  return
353 
354 
355  @staticmethod
357  """Makes sure that I know how to read root files I made myself"""
358  genObject = "GenObject"
359  ntupleDict = GenObject._ntupleDict.setdefault (genObject, {})
360  ntupleDict['_useChain'] = True
361  ntupleDict['_tree'] = "goTree"
362  for objName in GenObject._objsDict.keys():
363  rootObjName = GenObject.rootClassName (objName)
364  if GenObject.isSingleton (objName):
365  ntupleDict[objName] = objName
366  else:
367  ntupleDict[objName] = objName + "s"
368  tofillDict = GenObject._tofillDict.\
369  setdefault (genObject, {}).\
370  setdefault (objName, {})
371  for varName in GenObject._objsDict [objName].keys():
372  # if the key starts with an '_', then it is not a
373  # variable, so don't treat it as one.
374  if varName.startswith ("_"):
375  continue
376  tofillDict[varName] = [ [(varName, GenObject._objFunc.obj)],
377  {}]
378 
379 
380  @staticmethod
382  """Makes all necessary preparations to load root files created
383  by GenObject."""
384  GenObject._tofillGenObject()
385  GenObject._loadGoRootLibrary()
386 
387 
388  @staticmethod
389  def parseVariableTofill (fillname):
390  """Returns tofill tuple made from string"""
391  parts = GenObject._dotRE.split (fillname)
392  partsList = []
393  for part in parts:
394  parenMatch = GenObject._parenRE.search (part)
395  mode = GenObject._objFunc.obj
396  parens = []
397  if parenMatch:
398  part = parenMatch.group (1)
399  mode = GenObject._objFunc.func
400  parens = \
401  GenObject._convertStringToParameters \
402  (parenMatch.group (2))
403  partsList.append( (part, mode, parens) )
404  return partsList
405 
406  @staticmethod
407  def _fixLostGreaterThans (handle):
408  offset = handle.count ('<') - handle.count('>')
409  if not offset:
410  return handle
411  if offset < 0:
412  print "Huh? Too few '<' for each '>' in handle '%'" % handle
413  return handle
414  return handle + ' >' * offset
415 
416 
417  @staticmethod
418  def loadConfigFile (configFile):
419  """Loads configuration file"""
420  objName = ""
421  tupleName = ""
422  tofillName = ""
423  modeEnum = Enumerate ("none define tofill ntuple", "mode")
424  mode = modeEnum.none
425  try:
426  config = open (configFile, 'r')
427  except:
428  raise RuntimeError("Can't open configuration '%s'" % configFile)
429  for lineNum, fullLine in enumerate (config):
430  fullLine = fullLine.strip()
431  # get rid of comments
432  line = GenObject._commentRE.sub ('', fullLine)
433  # Is there anything on this line?
434  if not GenObject._nonSpacesRE.search (line):
435  # Nothing to see here folks. Keep moving....
436  continue
437  ###################
438  ## Bracket Match ##
439  ###################
440  bracketMatch = GenObject._bracketRE.search (line)
441  if bracketMatch:
442  # a header
443  section = bracketMatch.group(1)
444  words = GenObject._spacesRE.split( section )
445  if len (words) < 1:
446  raise RuntimeError("Don't understand line '%s'(%d)" \
447  % (fullLine, lineNum))
448  # The first word is the object name
449  # reset the rest of the list
450  objName = words[0]
451  words = words[1:]
452  colonWords = GenObject._colonRE.split (objName)
453  if len (colonWords) > 3:
454  raise RuntimeError("Don't understand line '%s'(%d)" \
455  % (fullLine, lineNum))
456  if len (colonWords) == 1:
457  ##########################
458  ## GenObject Definition ##
459  ##########################
460  mode = modeEnum.define
461  for word in words:
462  if GenObject._singletonRE.match (word):
463  #GenObject._singletonSet.add (objName)
464  objsDict = GenObject._objsDict.\
465  setdefault (objName, {})
466  objsDict['_singleton'] = True
467  continue
468  # If we're still here, then we didn't have a valid
469  # option. Complain vociferously
470  print "I don't understand '%s' in section '%s' : %s" \
471  % (word, section, mode)
472  raise RuntimeError("Config file parser error '%s'(%d)" \
473  % (fullLine, lineNum))
474  elif len (colonWords) == 2:
475  #######################
476  ## Ntuple Definition ##
477  #######################
478  mode = modeEnum.ntuple
479  ntupleDict = GenObject._ntupleDict.\
480  setdefault (colonWords[0], {})
481  ntupleDict['_tree'] = colonWords[1]
482  else:
483  ##########################
484  ## Object 'tofill' Info ##
485  ##########################
486  mode = modeEnum.tofill
487  objName = colonWords [0]
488  tupleName = colonWords [1]
489  tofillName = colonWords [2]
490  ntupleDict = GenObject._ntupleDict.\
491  setdefault (tupleName, {})
492  ntupleDict[objName] = tofillName
493  for word in words:
494  # label
495  labelMatch = GenObject._labelRE.search (word)
496  if labelMatch:
497  label = tuple( GenObject._commaRE.\
498  split( labelMatch.group (1) ) )
499  ntupleDict.setdefault ('_label', {}).\
500  setdefault (tofillName,
501  label)
502  continue
503  # shortcut
504  shortcutMatch = GenObject._shortcutRE.search (word)
505  if shortcutMatch:
506  shortcutFill = \
507  GenObject.\
508  parseVariableTofill ( shortcutMatch.\
509  group(1) )
510  ntupleDict.setdefault ('_shortcut', {}).\
511  setdefault (tofillName,
512  shortcutFill)
513  continue
514  # type/handle
515  typeMatch = GenObject._typeRE.search (word)
516  if typeMatch:
517  handleString = \
518  GenObject.\
519  _fixLostGreaterThans (typeMatch.group(1))
520  handle = Handle( handleString )
521  ntupleDict.setdefault ('_handle', {}).\
522  setdefault (tofillName,
523  handle)
524  continue
525  # alias
526  aliasMatch = GenObject._aliasRE.search (word)
527  if aliasMatch:
528  ntupleDict.setdefault ('_alias', {}).\
529  setdefault (tofillName,
530  aliasMatch.\
531  group(1))
532  continue
533  # is this a lost '<'
534  if word == '>':
535  continue
536  # If we're still here, then we didn't have a valid
537  # option. Complain vociferously
538  print "I don't understand '%s' in section '%s' : %s" \
539  % (word, section, mode)
540  raise RuntimeError("Config file parser error '%s'(%d)" \
541  % (fullLine, lineNum))
542  ##############
543  ## Variable ##
544  ##############
545  else:
546  # a variable
547  if modeEnum.none == mode:
548  # Poorly formatted 'section' tag
549  print "I don't understand line '%s'." % fullLine
550  raise RuntimeError("Config file parser error '%s'(%d)" \
551  % (fullLine, lineNum))
552  colonWords = GenObject._colonRE.split (line, 1)
553  if len (colonWords) < 2:
554  # Poorly formatted 'section' tag
555  print "I don't understand line '%s'." % fullLine
556  raise RuntimeError("Config file parser error '%s'(%d)" \
557  % (fullLine, lineNum))
558  varName = colonWords[0]
559  option = colonWords[1]
560  if option:
561  pieces = GenObject._spacesRE.split (option)
562  else:
563  pieces = []
564  if modeEnum.define == mode:
565  #########################
566  ## Variable Definition ##
567  #########################
568  # is this a variable or an option?
569  if varName.startswith("-"):
570  # this is an option
571  if "-equiv" == varName.lower():
572  for part in pieces:
573  halves = part.split (",")
574  if 2 != len (halves):
575  print "Problem with -equiv '%s' in '%s'" % \
576  (part, section)
577  raise RuntimeError("Config file parser error '%s'(%d)" \
578  % (fullLine, lineNum))
579  if halves[1]:
580  halves[1] = float (halves[1])
581  if not halves[1] >= 0:
582  print "Problem with -equiv ",\
583  "'%s' in '%s'" % \
584  (part, section)
585  raise RuntimeError("Config file parser error '%s'(%d)" \
586  % (fullLine, lineNum))
587  GenObject.setEquivExpression (section,
588  halves[0],
589  halves[1])
590  continue
591  # If we're here, then this is a variable
592  optionsDict = {}
593  for word in pieces:
594  typeMatch = GenObject._typeRE.search (word)
595  if typeMatch and \
596  GenObject.types.isValidKey (typeMatch.group(1)):
597  varType = typeMatch.group(1).lower()
598  optionsDict['varType'] = GenObject.types (varType)
599  continue
600  defaultMatch = GenObject._defaultRE.search (word)
601  if defaultMatch:
602  optionsDict['default'] = defaultMatch.group(1)
603  continue
604  precMatch = GenObject._precRE.search (word)
605  if precMatch:
606  optionsDict['prec'] = float (precMatch.group (1))
607  continue
608  formMatch = GenObject._formRE.search (word)
609  if formMatch:
610  form = GenObject._doublePercentRE.\
611  sub ('%', formMatch.group (1))
612  optionsDict['form'] = form
613  continue
614  # If we're still here, then we didn't have a valid
615  # option. Complain vociferously
616  print "I don't understand '%s' in section '%s'." \
617  % (word, option)
618  raise RuntimeError("Config file parser error '%s'(%d)" \
619  % (fullLine, lineNum))
620  GenObject.addObjectVariable (objName, varName, \
621  **optionsDict)
622  else: # if modeEnum.define != mode
623  ############################
624  ## Variable 'tofill' Info ##
625  ############################
626  if len (pieces) < 1:
627  continue
628  fillname, pieces = pieces[0], pieces[1:]
629  # I don't yet have any options available here, but
630  # I'm keeping the code here for when I add them.
631  optionsDict = {}
632  for word in pieces:
633  # If we're still here, then we didn't have a valid
634  # option. Complain vociferously
635  print "I don't understand '%s' in section '%s'." \
636  % (word, option)
637  raise RuntimeError("Config file parser error '%s'(%d)" \
638  % (fullLine, lineNum))
639  tofillDict = GenObject._tofillDict.\
640  setdefault (tupleName, {}).\
641  setdefault (objName, {})
642  partsList = GenObject.parseVariableTofill (fillname)
643  tofillDict[varName] = [partsList, optionsDict]
644  # for line
645  for objName in GenObject._objsDict:
646  # if this isn't a singleton, add 'index' as a variable
647  if not GenObject.isSingleton (objName):
648  GenObject.addObjectVariable (objName, 'index',
649  varType = GenObject.types.int,
650  form = '%3d')
651 
652 
653  @staticmethod
654  def changeVariable (tupleName, objName, varName, fillname):
655  """Updates the definition used to go from a Root object to a
656  GenObject. 'tupleName' and 'objName' must already be defined."""
657  parts = GenObject._dotRE.split (fillname)
658  partsList = []
659  for part in parts:
660  parenMatch = GenObject._parenRE.search (part)
661  mode = GenObject._objFunc.obj
662  parens = []
663  if parenMatch:
664  part = parenMatch.group (1)
665  mode = GenObject._objFunc.func
666  parens = \
667  GenObject._convertStringToParameters \
668  (parenMatch.group (2))
669  partsList.append( (part, mode, parens) )
670  GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
671 
672 
673 
674  @staticmethod
675  def evaluateFunction (obj, partsList, debug=False):
676  """Evaluates function described in partsList on obj"""
677  for part in partsList:
678  if debug: warn (part, spaces=15)
679  obj = getattr (obj, part[0])
680  if debug: warn (obj, spaces=15)
681  # if this is a function instead of a data member, make
682  # sure you call it with its arguments:
683  if GenObject._objFunc.func == part[1]:
684  # Arguments are stored as a list in part[2]
685  obj = obj (*part[2])
686  if debug: warn (obj, spaces=18)
687  return obj
688 
689 
690  @staticmethod
691  def _genObjectClone (objName, tupleName, obj, index = -1):
692  """Creates a GenObject copy of Root object"""
693  debug = GenObject._kitchenSinkDict.get ('debug', False)
694  if objName == 'runevent':
695  debug = False
696  tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
697  .get(objName, {})
698  genObj = GenObject (objName)
699  origObj = obj
700  if debug: warn (objName, spaces = 9)
701  for genVar, ntDict in tofillObjDict.iteritems():
702  if debug: warn (genVar, spaces = 12)
703  # lets work our way down the list
704  partsList = ntDict[0]
705  # start off with the original object
706  obj = GenObject.evaluateFunction (origObj, partsList, debug)
707  if debug: warn (obj, spaces=12)
708  setattr (genObj, genVar, obj)
709  # Do I need to store the index of this object?
710  if index >= 0:
711  setattr (genObj, 'index', index)
712  return genObj
713 
714 
715  @staticmethod
716  def _rootObjectCopy (goSource, rootTarget):
717  """Copies information from goSourse into Root Object"""
718  objName = goSource._objName
719  for varName in GenObject._objsDict [objName].keys():
720  # if the key starts with an '_', then it is not a
721  # variable, so don't treat it as one.
722  if varName.startswith ("_"):
723  continue
724  setattr( rootTarget, varName, goSource (varName) )
725 
726 
727  @staticmethod
728  def _rootObjectClone (obj):
729  """Creates the approprite type of Root object and copies the
730  information into it from the GO object."""
731  objName = obj._objName
732  classObj = GenObject._rootClassDict.get (objName)
733  if not classObj:
734  goName = GenObject.rootClassName (objName)
735  classObj = GenObject._rootClassDict[ goName ]
736  rootObj = classObj()
737  for varName in GenObject._objsDict [objName].keys():
738  setattr( rootObj, varName, obj (varName) )
739  return rootObj
740 
741 
742  @staticmethod
743  def _rootDiffObject (obj1, obj2, rootObj = 0):
744  """Given to GOs, it will create and fill the corresponding
745  root diff object"""
746  objName = obj1._objName
747  # if we don't already have a root object, create one
748  if not rootObj:
749  diffName = GenObject.rootDiffClassName( objName )
750  rootObj = GenObject._rootClassDict[diffName]()
751  for varName in GenObject._objsDict [objName].keys():
752  if varName.startswith ("_"): continue
753  goType = GenObject._objsDict[objName][varName]['varType']
754  if not goType in GenObject._basicSet:
755  # not yet
756  continue
757  setattr( rootObj, varName, obj1 (varName) )
758  if goType == GenObject.types.string:
759  # string
760  otherName = 'other_' + varName
761  if obj1 (varName) != obj2 (varName):
762  # don't agree
763  setattr( rootObj, otherName, obj2 (varName) )
764  else:
765  # agree
766  setattr( rootObj, otherName, '' )
767  else:
768  # float, long, or int
769  deltaName = 'delta_' + varName
770  setattr( rootObj, deltaName,
771  obj2 (varName) - obj1 (varName) )
772  return rootObj
773 
774 
775  @staticmethod
776  def setupOutputTree (outputFile, treeName, treeDescription = "",
777  otherNtupleName = ""):
778  """Opens the output file, loads all of the necessary shared
779  object libraries, and returns the output file and tree. If
780  'otherNtupleName' is given, it will check and make sure that
781  only objects that are defined in it are written out."""
782  rootfile = ROOT.TFile.Open (outputFile, "recreate")
783  tree = ROOT.TTree (treeName, treeDescription)
784  GenObject._loadGoRootLibrary()
785  for objName in sorted (GenObject._objsDict.keys()):
786  classname = GenObject.rootClassName (objName)
787  rootObj = \
788  GenObject._rootClassDict[objName] = \
789  getattr (ROOT, classname)
790  if GenObject.isSingleton (objName):
791  # singleton object
792  obj = GenObject._rootObjectDict[objName] = rootObj()
793  tree.Branch (objName, classname, obj)
794  else:
795  # vector of objects - PLEASE don't forget the '()' on
796  # the end of the declaration. Without this, you are
797  # defining a type, not instantiating an object.
798  vec = \
799  GenObject._rootObjectDict[objName] = \
800  ROOT.std.vector( rootObj )()
801  branchName = objName + "s"
802  vecName = "vector<%s>" % classname
803  tree.Branch( branchName, vecName, vec)
804  # end else if isSingleton
805  # end for objName
806  return rootfile, tree
807 
808 
809  @staticmethod
810  def setupDiffOutputTree (outputFile, diffName, missingName,
811  diffDescription = '', missingDescription = ''):
812  """Opens the diff output file, loads all of the necessary
813  shared object libraries, and returns the output file and tree.b"""
814  rootfile = ROOT.TFile.Open (outputFile, "recreate")
815  GenObject._loadGoRootLibrary()
816  # diff tree
817  diffTree = ROOT.TTree (diffName, diffDescription)
818  runEventObject = getattr (ROOT, 'go_runevent')()
819  diffTree.Branch ('runevent', 'go_runevent', runEventObject)
820  GenObject._rootClassDict['runevent'] = runEventObject
821  for objName in sorted (GenObject._objsDict.keys()):
822  if objName == 'runevent': continue
823  classname = GenObject.rootClassName (objName)
824  GenObject._rootClassDict[classname] = getattr (ROOT, classname)
825  contName = GenObject.rootDiffContClassName (objName)
826  diffName = GenObject.rootDiffClassName (objName)
827  rootObj = GenObject._rootClassDict[contName] = \
828  getattr (ROOT, contName)
829  GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
830  obj = GenObject._rootObjectDict[objName] = rootObj()
831  diffTree.Branch (objName, contName, obj)
832  # missing tree
833  missingTree = ROOT.TTree (missingName, missingDescription)
834  rootRunEventClass = getattr (ROOT, 'go_runevent')
835  firstOnly = GenObject._rootClassDict['firstOnly'] = \
836  ROOT.std.vector( rootRunEventClass ) ()
837  secondOnly = GenObject._rootClassDict['secondOnly'] = \
838  ROOT.std.vector( rootRunEventClass ) ()
839  missingTree.Branch ('firstOnly', 'vector<go_runevent>', firstOnly)
840  missingTree.Branch ('secondOnly', 'vector<go_runevent>', secondOnly)
841  return rootfile, diffTree, missingTree
842 
843 
844  @staticmethod
845  def _fillRootObjects (event):
846  """Fills root objects from GenObject 'event'"""
847  for objName, obj in sorted (event.iteritems()):
848  if GenObject.isSingleton (objName):
849  # Just one
850  GenObject._rootObjectCopy (obj,
851  GenObject._rootObjectDict[objName])
852  else:
853  # a vector
854  vec = GenObject._rootObjectDict[objName]
855  vec.clear()
856  for goObj in obj:
857  vec.push_back( GenObject._rootObjectClone (goObj) )
858 
859 
860  @staticmethod
861  def _fillRootDiffs (event1, event2):
862  """Fills root diff containers from two GenObject 'event's"""
863 
864 
865 
866  @staticmethod
867  def isSingleton (objName):
868  """Returns true if object is a singleton"""
869  return GenObject._objsDict[objName].get('_singleton')
870 
871 
872  @staticmethod
873  def loadEventFromTree (eventTree, eventIndex,
874  onlyRunEvent = False):
875  """Loads event information from Root file (as interfaced by
876  'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
877  'event' containing lists of objects or singleton object. If
878  'onlyRunEvent' is et to True, then only run and event number
879  is read in from the tree."""
880  debug = GenObject._kitchenSinkDict.get ('debug', False)
881  tupleName = GenObject._kitchenSinkDict[eventTree]['tupleName']
882  event = {}
883  # is this a cint tree
884  isChain = eventTree.__class__.__name__ == 'TChain'
885  if isChain:
886  # This means that 'eventTree' is a ROOT.TChain
887  eventTree.GetEntry (eventIndex)
888  else:
889  # This means that 'eventTree' is a FWLite Events
890  eventTree.to(eventIndex)
891  tofillDict = GenObject._tofillDict.get (tupleName)
892  ntupleDict = GenObject._ntupleDict.get (tupleName)
893  if not tofillDict:
894  print "Don't know how to fill from '%s' ntuple." % tupleName
895  return
896  eventBranchName = ntupleDict['runevent']
897  for objName in tofillDict:
898  branchName = ntupleDict[objName]
899  if onlyRunEvent and branchName != eventBranchName:
900  # not now
901  continue
902  # Have we been given 'tofill' info for this object?
903  if not branchName:
904  # guess not
905  continue
906  if isChain:
907  # Root TChain
908  objects = getattr (eventTree, branchName)
909  else:
910  # FWLite
911  shortcut = ntupleDict.get('_shortcut', {}).get(branchName)
912  if shortcut:
913  objects = GenObject.evaluateFunction (eventTree, shortcut)
914  else:
915  eventTree.toBegin()
916  handle = ntupleDict.get('_handle', {}).get(branchName)
917  label = ntupleDict.get('_label' , {}).get(branchName)
918  if not handle or not label:
919  raise RuntimeError("Missing handle or label for '%s'"\
920  % branchName)
921  if not eventTree.getByLabel (label, handle):
922  raise RuntimeError("not able to get %s for %s" \
923  % (label, branchName))
924  objects = handle.product()
925  # is this a singleton?
926  if GenObject.isSingleton (objName):
927  event[objName] = GenObject.\
928  _genObjectClone (objName,
929  tupleName,
930  objects)
931  continue
932  # if we're here then we have a vector of items
933  if debug: warn (objName, spaces = 3)
934  event[objName] = []
935  for index, obj in enumerate (objects):
936  event[objName].append( GenObject.\
937  _genObjectClone (objName,
938  tupleName,
939  obj,
940  index) )
941  del objects
942  # end for obj
943  ## if not isChain:
944  ## del rootEvent
945  # end for objName
946  return event
947 
948 
949  @staticmethod
950  def printEvent (event):
951  """Prints out event dictionary. Mostly for debugging"""
952  # Print out all singletons first
953  for objName, obj in sorted (event.iteritems()):
954  #obj = event[objName]
955  # is this a singleton?
956  if GenObject.isSingleton (objName):
957  print "%s: %s" % (objName, obj)
958  # Now print out all vectors
959  for objName, obj in sorted (event.iteritems()):
960  #obj = event[objName]
961  # is this a singleton?
962  if not GenObject.isSingleton (objName):
963  # o.k. obj is a vector
964  print "%s:" % objName
965  for single in obj:
966  print " ", single
967  print
968 
969 
970  @staticmethod
971  def setAliases (eventTree, tupleName):
972  """runs SetAlias on all saved aliases"""
973  aliases = GenObject._ntupleDict[tupleName].get('_alias', {})
974  for name, alias in aliases.iteritems():
975  eventTree.SetAlias (name, alias)
976 
977 
978  @staticmethod
979  def changeAlias (tupleName, name, alias):
980  """Updates an alias for an object for a given tuple"""
981  aliasDict = GenObject._ntupleDict[tupleName]['_alias']
982  if name not in aliasDict:
983  raise RuntimeError("unknown name '%s' in tuple '%s'" % \
984  (name, tupleName))
985  aliasDict[name] = alias
986 
987 
988  @staticmethod
989  def changeLabel (tupleName, objectName, label):
990  """Updates an label for an object for a given tuple"""
991  labelDict = GenObject._ntupleDict[tupleName]['_label']
992  if objectName not in labelDict:
993  raise RuntimeError("unknown name '%s' in tuple '%s'" % \
994  (objectName, tupleName))
995  label = tuple( GenObject._commaRE.split( label ) )
996  labelDict[objectName] = label
997 
998 
999  @staticmethod
1000  def prepareTuple (tupleName, files, numEventsWanted = 0):
1001  """Given the tuple name and list of files, returns either a
1002  TChain or EventTree, and number of entries"""
1003  if "GenObject" == tupleName:
1004  GenObject.prepareToLoadGenObject()
1005  if not isinstance (files, list):
1006  # If this isn't a list, make it one
1007  files = [files]
1008  ntupleDict = GenObject._ntupleDict[tupleName]
1009  treeName = ntupleDict["_tree"]
1010  if ntupleDict.get('_useChain'):
1011  chain = ROOT.TChain (treeName)
1012  for filename in files:
1013  chain.AddFile (filename)
1014  numEntries = chain.GetEntries()
1015  # Are we using a chain or EventTree here?
1016  else:
1017  chain = Events (files, forceEvent=True)
1018  numEntries = chain.size()
1019  chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1020  if numEventsWanted and numEventsWanted < numEntries:
1021  numEntries = numEventsWanted
1022  chainDict['numEntries'] = numEntries
1023  chainDict['tupleName' ] = tupleName
1024  return chain
1025 
1026 
1027  @staticmethod
1028  def getRunEventEntryDict (chain, tupleName, numEntries):
1029  """Returns a dictionary of run, event tuples to entryIndicies"""
1030  reeDict = {}
1031  for entryIndex in xrange (numEntries):
1032  event = GenObject.loadEventFromTree (chain,
1033  entryIndex,
1034  onlyRunEvent = True)
1035  runevent = event['runevent']
1036  reeDict[ GenObject._re2key (runevent) ] = entryIndex
1037  #reeDict[ "one two three" ] = entryIndex
1038  del event
1039  return reeDict
1040 
1041 
1042  @staticmethod
1043  def _re2key (runevent):
1044  """Given a GO 'runevent' object, returns a sortable key"""
1045  # if we don't know how to make this object yet, let's figure
1046  # it out
1047  if not GenObject._runEventListDone:
1048  GenObject._runEventListDone = True
1049  ignoreSet = set( ['run', 'event'] )
1050  for varName in sorted (runevent.__dict__.keys()):
1051  if varName.startswith ('_') or varName in ignoreSet:
1052  continue
1053  form = runevent.getVariableProperty (varName, "form")
1054  if not form:
1055  form = '%s'
1056  GenObject._runEventList.append ((varName, form))
1057  key = 'run:%d event:%d' % (runevent.run, runevent.event)
1058  for items in GenObject._runEventList:
1059  varName = items[0]
1060  form = ' %s:%s' % (varName, items[1])
1061  key += form % runevent.getVariableProperty (varName)
1062  return key
1063 
1064 
1065  @staticmethod
1066  def _key2re (key, runevent=None):
1067  """Given a key, returns a GO 'runevent' object"""
1068  if not runevent:
1069  runevent = GenObject ('runevent')
1070  words = GenObject._spacesRE.split (key)
1071  for word in words:
1072  match = GenObject._singleColonRE.search (word)
1073  if match:
1074  # for now, I'm assuming everything in the runevent
1075  # tuple is an integer. If this isn't the case, I'll
1076  # have to come back and be more clever here.
1077  runevent.__setattr__ (match.group(1), int( match.group(2) ))
1078  return runevent
1079 
1080 
1081  @staticmethod
1082  def compareRunEventDicts (firstDict, secondDict):
1083  """Compares the keys of the two dicts and returns three sets:
1084  the overlap, first but not second, and second but not first."""
1085  overlap = set()
1086  firstOnly = set()
1087  secondOnly = set()
1088  # loop over the keys of the first dict and compare to second dict
1089  for key in firstDict.keys():
1090  if key in secondDict:
1091  overlap.add (key)
1092  else:
1093  firstOnly.add (key)
1094  # now loop over keys of second dict and only check for missing
1095  # entries in first dict
1096  for key in secondDict.keys():
1097  if key not in firstDict:
1098  secondOnly.add (key)
1099  # All done
1100  return overlap, firstOnly, secondOnly
1101 
1102 
1103  @staticmethod
1104  def pairEquivalentObjects (vec1, vec2):
1105  """Finds the equivalent objects in the two vectors"""
1106  len1, len2 = len (vec1), len (vec2)
1107  debug = GenObject._kitchenSinkDict.get ('debug', False)
1108  if not len1 or not len2:
1109  # Nothing to see here folks. Keep moving.
1110  if len1:
1111  noMatch1Set = set( xrange(len1) )
1112  else:
1113  noMatch1Set = set ()
1114  if len2:
1115  noMatch2Set = set( xrange(len2) )
1116  else:
1117  noMatch2Set = set ()
1118  if debug: warn ("Nothing found", sapces=6)
1119  return set(), noMatch1Set, noMatch2Set
1120  objName = vec1[0]._objName
1121  equivList = GenObject._equivDict[objName]
1122  firstDict = {}
1123  secondDict = {}
1124  # let's see if we're only using 'index' and nothing else
1125  if GenObject._kitchenSinkDict.get ('strictPairing') or \
1126  equivList == [('index', 0)]:
1127  # we're only matching on index, nothing else matters
1128  matchedSet = set (zip ( range( min (len1, len2) ),
1129  range( min (len1, len2) ) ) )
1130  if len1 > len2:
1131  # since main pairing goes from 0..len2-1, we now want
1132  # to go from len2..len1 inclusive
1133  noMatch1Set = set (range(len2, len1 + 1))
1134  else:
1135  noMatch1Set = set()
1136  if len2 > len1:
1137  # same logic as above
1138  noMatch2Set = set (range(len1, len2 + 1))
1139  else:
1140  noMatch2Set = set()
1141  return matchedSet, noMatch1Set, noMatch2Set
1142  ## # If we're still here, that means that we aren't matching on
1143  ## # just index. Instead of jumping to O(N^2), let's assume that
1144  ## # both branches have everything in order and try to pair like
1145  ## # that. Anything not paired will be checked in a third pass.
1146  ## unpairedFirst = []
1147  ## unpairedSecond = []
1148  ## for index in xrange( min (len1, len2) ):
1149  ## obj1 = vec1[index1]
1150  ## total = 0.
1151  ## obj2 = vec2[index2]
1152  ## ok = True
1153 
1154  # First, look for vec2 objects that are equivalent to a
1155  # given vec1 object.
1156  for index1 in xrange (len1):
1157  objList = []
1158  obj1 = vec1[index1]
1159  for index2 in xrange (len2):
1160  total = 0.
1161  obj2 = vec2[index2]
1162  ok = True
1163  for equiv in equivList:
1164  var, precision = equiv[0], equiv[1]
1165  val1 = obj1 (var)
1166  val2 = obj2 (var)
1167  # Do we check equality or a precision
1168  if precision:
1169  value = abs (val1 - val2) / precision
1170  if value >= 1.:
1171  ok = False
1172  break
1173  total += value ** 2
1174  elif val1 != val2:
1175  ok = False
1176  break
1177  if ok:
1178  objList.append( (total, index2) )
1179  objList.sort()
1180  firstDict[index1] = objList
1181  # Now do the same thing, but this time look for vec1 objects
1182  # that are equivalent to a given vec2 object
1183  for index2 in xrange (len2):
1184  objList = []
1185  obj2 = vec2[index2]
1186  for index1 in xrange (len1):
1187  total = 0.
1188  obj1 = vec1[index1]
1189  ok = True
1190  for equiv in equivList:
1191  var, precision = equiv[0], equiv[1]
1192  val2 = obj2 (var)
1193  val1 = obj1 (var)
1194  # Do we check equality or a precision
1195  if precision:
1196  value = abs (val2 - val1) / precision
1197  if value > 1.:
1198  ok = False
1199  break
1200  total += value ** 2
1201  elif val2 != val1:
1202  ok = False
1203  break
1204  if ok:
1205  objList.append( (total, index1) )
1206  objList.sort()
1207  secondDict[index2] = objList
1208  # O.k. Now that we have the candidate matches, lets see who is
1209  # really matched.
1210  matchedSet = set()
1211  noMatch1Set = set()
1212  firstDictKeys = sorted (firstDict.keys())
1213  for index1 in firstDictKeys:
1214  list1 = firstDict[index1]
1215  # do I have a match?
1216  if not len (list1):
1217  # no match
1218  noMatch1Set.add (index1)
1219  continue
1220  # we've got at least one match
1221  best1 = list1[0]
1222  index2 = best1[1]
1223  # Does this one match me?
1224  list2 = secondDict.get (index2, [])
1225  if len(list2) and list2[0][1] == index1:
1226  matchedSet.add( (index1, index2) )
1227  # get rid of the 2nd key hash
1228  del firstDict[index1]
1229  del secondDict[index2]
1230  else:
1231  # no match
1232  noMatch1Set.add (index1)
1233  noMatch2Set = set( secondDict.keys() )
1234  return matchedSet, noMatch1Set, noMatch2Set
1235 
1236 
1237  @staticmethod
1238  def compareTwoItems (item1, item2):
1239  """Compares all of the variables making sure they are the same
1240  on the two objects."""
1241  objName = item1._objName
1242  problems = {}
1243  relative = GenObject._kitchenSinkDict.get ('relative', False)
1244  for varName in GenObject._objsDict[objName].keys():
1245  prec = item1.getVariableProperty (varName, 'prec')
1246  if prec:
1247  # we want to check within a precision
1248  if relative:
1249  val1 = item1(varName)
1250  val2 = item2(varName)
1251  numerator = 2 * abs (val1 - val2)
1252  denominator = abs(val1) + abs(val2)
1253  if not denominator:
1254  # both are exactly zero, so there's no
1255  # disagreement here.
1256  continue
1257  value = numerator / denominator
1258  if value > prec:
1259  # we've got a problem
1260  problems[varName] = value
1261  else:
1262  value = abs( item1(varName) - item2(varName) )
1263  if value > prec:
1264  # we've got a problem
1265  problems[varName] = value
1266  else:
1267  # we want to check equality
1268  if item1(varName) != item2(varName):
1269  # we have a problem. sort the values
1270  val1, val2 = item1(varName), item2(varName)
1271  if val1 > val2:
1272  val1, val2 = val2, val1
1273  problems[varName] = "%s != %s" % (val1, val2)
1274  # end for
1275  return problems
1276 
1277 
1278  @staticmethod
1279  def blurEvent (event, value, where = ""):
1280  """For debugging purposes only. Will deliberately change
1281  values of first tree to verify that script is correctly
1282  finding problems."""
1283  for objName in sorted (event.keys()):
1284  if "runevent" == objName:
1285  # runevent is a special case. We don't compare these
1286  continue
1287  if GenObject.isSingleton (objName):
1288  # I'll add this in later. For now, just skip it
1289  continue
1290  count = 0
1291  for obj in event[objName]:
1292  count += 1
1293  for varName in GenObject._objsDict[objName].keys():
1294  if isinstance (obj.__dict__[varName], str):
1295  # don't bother
1296  continue
1297  randNumber = random.random()
1298  #print "rN", randNumber
1299  if randNumber < GenObject._kitchenSinkDict['blurRate']:
1300  print " %s: changing '%s' of '%s:%d'" \
1301  % (where, varName, obj._objName, count)
1302  ## print "objdict", obj.__dict__.get(varName), ':',\
1303  ## value
1304  obj.__dict__[varName] += value
1305 
1306 
1307  @staticmethod
1308  def compareTwoTrees (chain1, chain2, **kwargs):
1309  """Given all of the necessary information, this routine will
1310  go through and compare two trees making sure they are
1311  'identical' within requested precision. If 'diffOutputName'
1312  is passed in, a root file with a diffTree and missingTree will
1313  be produced."""
1314  print "Comparing Two Trees"
1315  diffOutputName = kwargs.get ('diffOutputName')
1316  tupleName1 = GenObject._kitchenSinkDict[chain1]['tupleName']
1317  numEntries1 = GenObject._kitchenSinkDict[chain1]['numEntries']
1318  tupleName2 = GenObject._kitchenSinkDict[chain2]['tupleName']
1319  numEntries2 = GenObject._kitchenSinkDict[chain2]['numEntries']
1320  debug = GenObject._kitchenSinkDict.get ('debug', False)
1321  ree1 = GenObject.getRunEventEntryDict (chain1, tupleName1, numEntries1)
1322  ree2 = GenObject.getRunEventEntryDict (chain2, tupleName2, numEntries2)
1323  overlap, firstOnly, secondOnly = \
1324  GenObject.compareRunEventDicts (ree1, ree2)
1325  if diffOutputName:
1326  rootfile, diffTree, missingTree = \
1327  GenObject.setupDiffOutputTree (diffOutputName,
1328  'diffTree',
1329  'missingTree')
1330  if firstOnly:
1331  vec = GenObject._rootClassDict['firstOnly']
1332  for key in firstOnly:
1333  runevent = GenObject._key2re (key)
1334  vec.push_back( GenObject._rootObjectClone( runevent ) )
1335  if secondOnly:
1336  vec = GenObject._rootClassDict['secondOnly']
1337  for key in secondOnly:
1338  runevent = GenObject._key2re (key)
1339  vec.push_back( GenObject._rootObjectClone( runevent ) )
1340  missingTree.Fill()
1341  resultsDict = {}
1342  if firstOnly:
1343  resultsDict.setdefault ('_runevent', {})['firstOnly'] = \
1344  len (firstOnly)
1345  if secondOnly:
1346  resultsDict.setdefault ('_runevent', {})['secondOnly'] = \
1347  len (secondOnly)
1348  resultsDict['eventsCompared'] = len (overlap)
1349  for reTuple in sorted(overlap):
1350  # if we are filling the diff tree, then save the run and
1351  # event information.
1352  if diffOutputName:
1353  GenObject._key2re (reTuple,
1354  GenObject._rootClassDict['runevent'])
1355  if debug: warn ('event1', blankLines = 3)
1356  event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1357  if debug: warn ('event2', blankLines = 3)
1358  event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1359  if GenObject._kitchenSinkDict.get('printEvent'):
1360  print "event1:"
1361  GenObject.printEvent (event1)
1362  print "event2:"
1363  GenObject.printEvent (event2)
1364  if GenObject._kitchenSinkDict.get('blur'):
1365  where = reTuple
1366  GenObject.blurEvent (event1,
1367  GenObject._kitchenSinkDict['blur'],
1368  where)
1369  for objName in sorted (event1.keys()):
1370  if "runevent" == objName:
1371  # runevent is a special case. We don't compare these
1372  continue
1373  if not GenObject._equivDict.get (objName):
1374  # we don't know how to compare these objects, so
1375  # skip them.
1376  continue
1377  if GenObject.isSingleton (objName):
1378  # I'll add this in later. For now, just skip it
1379  print "singleton"
1380  continue
1381  # Get ready to calculate root diff object if necessary
1382  rootObj = 0
1383  if diffOutputName:
1384  rootObj = GenObject._rootObjectDict[objName]
1385  rootObj.clear()
1386  vec1 = event1[objName]
1387  vec2 = event2[objName]
1388  matchedSet, noMatch1Set, noMatch2Set = \
1389  GenObject.pairEquivalentObjects (vec1, vec2)
1390  if noMatch1Set or noMatch2Set:
1391  ## print "No match 1", noMatch1Set
1392  ## print "No match 2", noMatch2Set
1393  count1 = len (noMatch1Set)
1394  count2 = len (noMatch2Set)
1395  key = (count1, count2)
1396  countDict = resultsDict.\
1397  setdefault (objName, {}).\
1398  setdefault ('_missing', {})
1399  if key in countDict:
1400  countDict[key] += 1
1401  else:
1402  countDict[key] = 1
1403  # should be calculating root diff objects
1404  if diffOutputName:
1405  # first set
1406  for index in sorted(list(noMatch1Set)):
1407  goObj = vec1 [index]
1408  rootObj.firstOnly.push_back ( GenObject.\
1409  _rootObjectClone \
1410  (goObj) )
1411  # second set
1412  for index in sorted(list(noMatch2Set)):
1413  goObj = vec2 [index]
1414  rootObj.secondOnly.push_back ( GenObject.\
1415  _rootObjectClone \
1416  (goObj) )
1417  # o.k. Now that we have them matched, let's compare
1418  # the proper items:
1419  for pair in sorted(list(matchedSet)):
1420  if diffOutputName:
1421  rootDiffObj = GenObject._rootDiffObject \
1422  ( vec1[ pair[1 - 1] ],
1423  vec2[ pair[2 - 1] ] )
1424  rootObj.diff.push_back ( rootDiffObj )
1425  problems = GenObject.\
1426  compareTwoItems (vec1[ pair[1 - 1] ],
1427  vec2[ pair[2 - 1] ])
1428  if problems.keys():
1429  # pprint.pprint (problems)
1430  for varName in problems.keys():
1431  countDict = resultsDict.\
1432  setdefault (objName, {}).\
1433  setdefault ('_var', {})
1434  if varName in countDict:
1435  countDict[varName] += 1
1436  else:
1437  countDict[varName] = 1
1438  key = 'count_%s' % objName
1439  if key not in resultsDict:
1440  resultsDict[key] = 0
1441  resultsDict[key] += len (matchedSet)
1442  # try cleaning up
1443  del vec1
1444  del vec2
1445  # end for objName
1446  if diffOutputName:
1447  diffTree.Fill()
1448  del event1
1449  del event2
1450  # end for overlap
1451  if diffOutputName:
1452  diffTree.Write()
1453  missingTree.Write()
1454  rootfile.Close()
1455  return resultsDict
1456 
1457 
1458  @staticmethod
1459  def saveTupleAs (chain, rootFile):
1460  """Saves a chain as a GO tree"""
1461  print "saveTupleAs"
1462  rootfile, tree = GenObject.setupOutputTree (rootFile, "goTree")
1463  numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1464  for entryIndex in xrange (numEntries):
1465  event = GenObject.loadEventFromTree (chain, entryIndex)
1466  if GenObject._kitchenSinkDict.get('blur'):
1467  where = "run %d event %d" % (event['runevent'].run,
1468  event['runevent'].event)
1469  if random.random() < GenObject._kitchenSinkDict.get('blur'):
1470  # dropping event
1471  print "Dropping", where
1472  continue
1473  GenObject.blurEvent (event,
1474  GenObject._kitchenSinkDict['blur'],
1475  where)
1476  # check to see if we should drop the event
1477  if GenObject._kitchenSinkDict.get('printEvent'):
1478  GenObject.printEvent (event)
1479  GenObject._fillRootObjects (event)
1480  tree.Fill()
1481  tree.Write()
1482  rootfile.Close()
1483 
1484 
1485  @staticmethod
1486  def setGlobalFlag (key, value):
1487  """Sets a global flag in _kitchenSinkDict"""
1488  GenObject._kitchenSinkDict [key] = value
1489 
1490 
1491  @staticmethod
1492  def printTuple (chain):
1493  """Prints out all events to stdout"""
1494  numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1495  debug = GenObject._kitchenSinkDict.get ('debug', False)
1496  if debug: warn (numEntries)
1497  for entryIndex in xrange (numEntries):
1498  if debug: warn (entryIndex, spaces=3)
1499  event = GenObject.loadEventFromTree (chain, entryIndex)
1500  GenObject.printEvent (event)
1501  if debug: warn(spaces=3)
1502 
1503  @staticmethod
1505  """Convert comma-separated string into a python list of
1506  parameters. Currently only understands strings, floats, and
1507  integers."""
1508  retval = []
1509  words = GenObject._commaRE.split (string)
1510  for word in words:
1511  if not len (word):
1512  continue
1513  match = GenObject._singleQuoteRE.search (word)
1514  if match:
1515  retval.append (match.group (1))
1516  continue
1517  match = GenObject._doubleQuoteRE.search (word)
1518  if match:
1519  retval.append (match.group (1))
1520  continue
1521  try:
1522  val = int (word)
1523  retval.append (val)
1524  continue
1525  except:
1526  pass
1527  try:
1528  val = float (word)
1529  retval.append (val)
1530  continue
1531  except:
1532  pass
1533  # if we're still here, we've got a problem
1534  raise RuntimeError("Unknown parameter '%s'." % word)
1535  return retval
1536 
1537 
1538  ######################
1539  ## Member Functions ##
1540  ######################
1541 
1542 
1543  def __init__ (self, objName):
1544  """Class initializer"""
1545  if objName not in GenObject._objsDict:# or \
1546  #not GenObject._equivDict.has_key (objName) :
1547  # not good
1548  print "Error: GenObject does not know about object '%s'." % objName
1549  raise RuntimeError("Failed to create GenObject object.")
1550  self._localObjsDict = GenObject._objsDict [objName]
1551  self._objName = objName;
1552  for key, varDict in self._localObjsDict.iteritems():
1553  # if the key starts with an '_', then it is not a
1554  # variable, so don't treat it as one.
1555  if key.startswith ("_"):
1556  continue
1557  self.setValue (key, varDict['default'])
1558 
1559 
1560  def setValue (self, name, value):
1561  """Wrapper for __setattr___"""
1562  self.__setattr__ (name, value)
1563 
1564 
1565  def getVariableProperty (self, var, key):
1566  """ Returns property assoicated with 'key' for variable 'var'
1567  of object of the same type as 'self'. Returns 'None' if 'var'
1568  or 'key' is not defined."""
1569  return GenObject._objsDict.get (self._objName,
1570  {}).get (var, {}). get (key, None)
1571 
1572 
1573  def __setattr__ (self, name, value):
1574  """Controls setting of values."""
1575  if name.startswith ("_"):
1576  # The internal version. Set anything you want.
1577  object.__setattr__ (self, name, value)
1578  else:
1579  # user version - Make sure this variable has already been
1580 
1581  # defined for this type:
1582  if name not in self._localObjsDict:
1583  # this variable has not been defined
1584  print "Warning: '%s' for class '%s' not setup. Skipping." % \
1585  (name, self._objName)
1586  return
1587  varType = self.getVariableProperty (name, 'varType')
1588  # if this is an int, make sure it stays an int
1589  if GenObject.types.int == varType:
1590  try:
1591  # This will work with integers, floats, and string
1592  # representations of integers.
1593  value = int (value)
1594  except:
1595  # This works with string representations of floats
1596  value = int( float( value ) )
1597  elif GenObject.types.long == varType:
1598  try:
1599  # This will work with integers, floats, and string
1600  # representations of integers.
1601  value = long (value)
1602  except:
1603  # This works with string representations of floats
1604  value = long( float( value ) )
1605  elif GenObject.types.float == varType:
1606  # Make sure it's a float
1607  value = float (value)
1608  elif GenObject.types.string == varType:
1609  # make sure it's a string
1610  value = str (value)
1611  # if we're still here, set it
1612  object.__setattr__ (self, name, value)
1613 
1614 
1615  def __call__ (self, key):
1616  """Makes object callable"""
1617  return object.__getattribute__ (self, key)
1618 
1619 
1620  def __str__ (self):
1621  """String representation"""
1622  retval = ""
1623  for varName, value in sorted (self.__dict__.iteritems()):
1624  if varName.startswith ('_'): continue
1625  form = self.getVariableProperty (varName, "form")
1626  if form:
1627  format = "%s:%s " % (varName, form)
1628  retval = retval + format % value
1629  else:
1630  retval = retval + "%s:%s " % (varName, value)
1631  return retval
def prepareTuple(tupleName, files, numEventsWanted=0)
Definition: GenObject.py:1000
def changeVariable(tupleName, objName, varName, fillname)
Definition: GenObject.py:654
def encodeNonAlphanumerics(line)
Definition: GenObject.py:126
def loadConfigFile(configFile)
Definition: GenObject.py:418
def blurEvent(event, value, where="")
Definition: GenObject.py:1279
def char2ascii(match)
Static Member Functions ##.
Definition: GenObject.py:118
def _finishClassHeader(className, datadec)
Definition: GenObject.py:233
def setEquivExpression(obj, variable, precision)
Definition: GenObject.py:164
def _loadGoRootLibrary()
Definition: GenObject.py:313
def evaluateFunction(obj, partsList, debug=False)
Definition: GenObject.py:675
def _rootObjectCopy(goSource, rootTarget)
Definition: GenObject.py:716
def _rootObjectClone(obj)
Definition: GenObject.py:728
def getVariableProperty(obj, var, key)
Definition: GenObject.py:156
def addObjectVariable(obj, var, optionsDict)
Definition: GenObject.py:137
def printEvent(event)
Definition: GenObject.py:950
def _fillRootObjects(event)
Definition: GenObject.py:845
def printTuple(chain)
Definition: GenObject.py:1492
def setGlobalFlag(key, value)
Definition: GenObject.py:1486
def _convertStringToParameters(string)
Definition: GenObject.py:1504
def setAliases(eventTree, tupleName)
Definition: GenObject.py:971
def warn(args, kwargs)
Definition: GenObject.py:29
def compareTwoItems(item1, item2)
Definition: GenObject.py:1238
def ascii2char(match)
Definition: GenObject.py:122
def setupDiffOutputTree(outputFile, diffName, missingName, diffDescription='', missingDescription='')
Definition: GenObject.py:811
def setQuietWarn(quiet=True)
Definition: GenObject.py:24
def setValue(self, name, value)
Definition: GenObject.py:1560
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
def _genObjectClone(objName, tupleName, obj, index=-1)
Definition: GenObject.py:691
def __setattr__(self, name, value)
Definition: GenObject.py:1573
def changeLabel(tupleName, objectName, label)
Definition: GenObject.py:989
def changeAlias(tupleName, name, alias)
Definition: GenObject.py:979
def saveTupleAs(chain, rootFile)
Definition: GenObject.py:1459
def prepareToLoadGenObject()
Definition: GenObject.py:381
def __call__(self, key)
Definition: GenObject.py:1615
def rootDiffClassName(objName)
Definition: GenObject.py:206
def setupOutputTree(outputFile, treeName, treeDescription="", otherNtupleName="")
Definition: GenObject.py:777
def compareRunEventDicts(firstDict, secondDict)
Definition: GenObject.py:1082
def _createCppClass(objName)
Definition: GenObject.py:242
def getRunEventEntryDict(chain, tupleName, numEntries)
Definition: GenObject.py:1028
def compareTwoTrees(chain1, chain2, kwargs)
Definition: GenObject.py:1308
def pairEquivalentObjects(vec1, vec2)
Definition: GenObject.py:1104
def loadEventFromTree(eventTree, eventIndex, onlyRunEvent=False)
Definition: GenObject.py:874
def rootDiffContClassName(objName)
Definition: GenObject.py:212
def _rootDiffObject(obj1, obj2, rootObj=0)
Definition: GenObject.py:743
def _key2re(key, runevent=None)
Definition: GenObject.py:1066
def rootClassName(objName)
Definition: GenObject.py:200
def __init__(self, objName)
Member Functions ##.
Definition: GenObject.py:1543
def isSingleton(objName)
Definition: GenObject.py:867
def _setupClassHeader(className, noColon=False)
Definition: GenObject.py:219
def _fixLostGreaterThans(handle)
Definition: GenObject.py:407
def parseVariableTofill(fillname)
Definition: GenObject.py:389
double split
Definition: MVATrainer.cc:139
def _re2key(runevent)
Definition: GenObject.py:1043
def _fillRootDiffs(event1, event2)
Definition: GenObject.py:861
T get(const Candidate &c)
Definition: component.h:55
def decodeNonAlphanumerics(line)
Definition: GenObject.py:131
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run