CMS 3D CMS Logo

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