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 = 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  ## parts = GenObject._dotRE.split (fillname)
636  ## partsList = []
637  ## for part in parts:
638  ## parenMatch = GenObject._parenRE.search (part)
639  ## mode = GenObject._objFunc.obj
640  ## parens = []
641  ## if parenMatch:
642  ## part = parenMatch.group (1)
643  ## mode = GenObject._objFunc.func
644  ## parens = \
645  ## GenObject._convertStringToParameters \
646  ## (parenMatch.group (2))
647  ## partsList.append( (part, mode, parens) )
648  # I don't yet have any options available here, but
649  # I'm keeping the code here for when I add them.
650  optionsDict = {}
651  for word in pieces:
652  # If we're still here, then we didn't have a valid
653  # option. Complain vociferously
654  print "I don't understand '%s' in section '%s'." \
655  % (word, option)
656  raise RuntimeError, \
657  "Config file parser error '%s'(%d)" \
658  % (fullLine, lineNum)
659  tofillDict = GenObject._tofillDict.\
660  setdefault (tupleName, {}).\
661  setdefault (objName, {})
662  partsList = GenObject.parseVariableTofill (fillname)
663  tofillDict[varName] = [partsList, optionsDict]
664  # for line
665  for objName in GenObject._objsDict:
666  # if this isn't a singleton, add 'index' as a variable
667  if not GenObject.isSingleton (objName):
668  GenObject.addObjectVariable (objName, 'index',
669  varType = GenObject.types.int,
670  form = '%3d')
671 
672 
673  @staticmethod
674  def changeVariable (tupleName, objName, varName, fillname):
675  """Updates the definition used to go from a Root object to a
676  GenObject. 'tupleName' and 'objName' must already be defined."""
677  parts = GenObject._dotRE.split (fillname)
678  partsList = []
679  for part in parts:
680  parenMatch = GenObject._parenRE.search (part)
681  mode = GenObject._objFunc.obj
682  parens = []
683  if parenMatch:
684  part = parenMatch.group (1)
685  mode = GenObject._objFunc.func
686  parens = \
687  GenObject._convertStringToParameters \
688  (parenMatch.group (2))
689  partsList.append( (part, mode, parens) )
690  GenObject._tofillDict[tupleName][objName][varName] = [partsList, {}]
691 
692 
693 
694  @staticmethod
695  def evaluateFunction (obj, partsList, debug=False):
696  """Evaluates function described in partsList on obj"""
697  for part in partsList:
698  if debug: warn (part, spaces=15)
699  obj = getattr (obj, part[0])
700  if debug: warn (obj, spaces=15)
701  # if this is a function instead of a data member, make
702  # sure you call it with its arguments:
703  if GenObject._objFunc.func == part[1]:
704  # Arguments are stored as a list in part[2]
705  obj = obj (*part[2])
706  if debug: warn (obj, spaces=18)
707  return obj
708 
709 
710  @staticmethod
711  def _genObjectClone (objName, tupleName, obj, index = -1):
712  """Creates a GenObject copy of Root object"""
713  debug = GenObject._kitchenSinkDict.get ('debug', False)
714  if objName == 'runevent':
715  debug = False
716  tofillObjDict = GenObject._tofillDict.get(tupleName, {})\
717  .get(objName, {})
718  genObj = GenObject (objName)
719  origObj = obj
720  if debug: warn (objName, spaces = 9)
721  for genVar, ntDict in tofillObjDict.iteritems():
722  if debug: warn (genVar, spaces = 12)
723  # lets work our way down the list
724  partsList = ntDict[0]
725  # start off with the original object
726  obj = GenObject.evaluateFunction (origObj, partsList, debug)
727  ## for part in partsList:
728  ## if debug: warn (part, spaces=15)
729  ## obj = getattr (obj, part[0])
730  ## if debug: warn (obj, spaces=15)
731  ## # if this is a function instead of a data member, make
732  ## # sure you call it with its arguments:
733  ## if GenObject._objFunc.func == part[1]:
734  ## # Arguments are stored as a list in part[2]
735  ## obj = obj (*part[2])
736  ## if debug: warn (obj, spaces=18)
737  if debug: warn (obj, spaces=12)
738  setattr (genObj, genVar, obj)
739  # Do I need to store the index of this object?
740  if index >= 0:
741  setattr (genObj, 'index', index)
742  return genObj
743 
744 
745  @staticmethod
746  def _rootObjectCopy (goSource, rootTarget):
747  """Copies information from goSourse into Root Object"""
748  objName = goSource._objName
749  for varName in GenObject._objsDict [objName].keys():
750  # if the key starts with an '_', then it is not a
751  # variable, so don't treat it as one.
752  if varName.startswith ("_"):
753  continue
754  setattr( rootTarget, varName, goSource (varName) )
755 
756 
757  @staticmethod
758  def _rootObjectClone (obj):
759  """Creates the approprite type of Root object and copies the
760  information into it from the GO object."""
761  objName = obj._objName
762  classObj = GenObject._rootClassDict.get (objName)
763  if not classObj:
764  goName = GenObject.rootClassName (objName)
765  classObj = GenObject._rootClassDict[ goName ]
766  rootObj = classObj()
767  for varName in GenObject._objsDict [objName].keys():
768  setattr( rootObj, varName, obj (varName) )
769  return rootObj
770 
771 
772  @staticmethod
773  def _rootDiffObject (obj1, obj2, rootObj = 0):
774  """Given to GOs, it will create and fill the corresponding
775  root diff object"""
776  objName = obj1._objName
777  # if we don't already have a root object, create one
778  if not rootObj:
779  diffName = GenObject.rootDiffClassName( objName )
780  rootObj = GenObject._rootClassDict[diffName]()
781  for varName in GenObject._objsDict [objName].keys():
782  if varName.startswith ("_"): continue
783  goType = GenObject._objsDict[objName][varName]['varType']
784  if not goType in GenObject._basicSet:
785  # not yet
786  continue
787  setattr( rootObj, varName, obj1 (varName) )
788  if goType == GenObject.types.string:
789  # string
790  otherName = 'other_' + varName
791  if obj1 (varName) != obj2 (varName):
792  # don't agree
793  setattr( rootObj, otherName, obj2 (varName) )
794  else:
795  # agree
796  setattr( rootObj, otherName, '' )
797  else:
798  # float, long, or int
799  deltaName = 'delta_' + varName
800  setattr( rootObj, deltaName,
801  obj2 (varName) - obj1 (varName) )
802  return rootObj
803 
804 
805  @staticmethod
806  def setupOutputTree (outputFile, treeName, treeDescription = "",
807  otherNtupleName = ""):
808  """Opens the output file, loads all of the necessary shared
809  object libraries, and returns the output file and tree. If
810  'otherNtupleName' is given, it will check and make sure that
811  only objects that are defined in it are written out."""
812  rootfile = ROOT.TFile.Open (outputFile, "recreate")
813  tree = ROOT.TTree (treeName, treeDescription)
814  GenObject._loadGoRootLibrary()
815  for objName in sorted (GenObject._objsDict.keys()):
816  classname = GenObject.rootClassName (objName)
817  rootObj = \
818  GenObject._rootClassDict[objName] = \
819  getattr (ROOT, classname)
820  if GenObject.isSingleton (objName):
821  # singleton object
822  obj = GenObject._rootObjectDict[objName] = rootObj()
823  tree.Branch (objName, classname, obj)
824  else:
825  # vector of objects - PLEASE don't forget the '()' on
826  # the end of the declaration. Without this, you are
827  # defining a type, not instantiating an object.
828  vec = \
829  GenObject._rootObjectDict[objName] = \
830  ROOT.std.vector( rootObj )()
831  branchName = objName + "s"
832  vecName = "vector<%s>" % classname
833  tree.Branch( branchName, vecName, vec)
834  # end else if isSingleton
835  # end for objName
836  return rootfile, tree
837 
838 
839  @staticmethod
840  def setupDiffOutputTree (outputFile, diffName, missingName,
841  diffDescription = '', missingDescription = ''):
842  """Opens the diff output file, loads all of the necessary
843  shared object libraries, and returns the output file and tree.b"""
844  rootfile = ROOT.TFile.Open (outputFile, "recreate")
845  GenObject._loadGoRootLibrary()
846  # diff tree
847  diffTree = ROOT.TTree (diffName, diffDescription)
848  runEventObject = getattr (ROOT, 'go_runevent')()
849  diffTree.Branch ('runevent', 'go_runevent', runEventObject)
850  GenObject._rootClassDict['runevent'] = runEventObject
851  for objName in sorted (GenObject._objsDict.keys()):
852  if objName == 'runevent': continue
853  classname = GenObject.rootClassName (objName)
854  GenObject._rootClassDict[classname] = getattr (ROOT, classname)
855  contName = GenObject.rootDiffContClassName (objName)
856  diffName = GenObject.rootDiffClassName (objName)
857  rootObj = GenObject._rootClassDict[contName] = \
858  getattr (ROOT, contName)
859  GenObject._rootClassDict[diffName] = getattr (ROOT, diffName)
860  obj = GenObject._rootObjectDict[objName] = rootObj()
861  diffTree.Branch (objName, contName, obj)
862  # missing tree
863  missingTree = ROOT.TTree (missingName, missingDescription)
864  rootRunEventClass = getattr (ROOT, 'go_runevent')
865  firstOnly = GenObject._rootClassDict['firstOnly'] = \
866  ROOT.std.vector( rootRunEventClass ) ()
867  secondOnly = GenObject._rootClassDict['secondOnly'] = \
868  ROOT.std.vector( rootRunEventClass ) ()
869  missingTree.Branch ('firstOnly', 'vector<go_runevent>', firstOnly)
870  missingTree.Branch ('secondOnly', 'vector<go_runevent>', secondOnly)
871  return rootfile, diffTree, missingTree
872 
873 
874  @staticmethod
875  def _fillRootObjects (event):
876  """Fills root objects from GenObject 'event'"""
877  for objName, obj in sorted (event.iteritems()):
878  if GenObject.isSingleton (objName):
879  # Just one
880  GenObject._rootObjectCopy (obj,
881  GenObject._rootObjectDict[objName])
882  else:
883  # a vector
884  vec = GenObject._rootObjectDict[objName]
885  vec.clear()
886  for goObj in obj:
887  vec.push_back( GenObject._rootObjectClone (goObj) )
888 
889 
890  @staticmethod
891  def _fillRootDiffs (event1, event2):
892  """Fills root diff containers from two GenObject 'event's"""
893 
894 
895 
896  @staticmethod
897  def isSingleton (objName):
898  """Returns true if object is a singleton"""
899  return GenObject._objsDict[objName].get('_singleton')
900 
901 
902  @staticmethod
903  def loadEventFromTree (eventTree, eventIndex,
904  onlyRunEvent = False):
905  """Loads event information from Root file (as interfaced by
906  'cmstools.EventTree' or 'ROOT.TChain'). Returns a dictionary
907  'event' containing lists of objects or singleton object. If
908  'onlyRunEvent' is et to True, then only run and event number
909  is read in from the tree."""
910  debug = GenObject._kitchenSinkDict.get ('debug', False)
911  tupleName = GenObject._kitchenSinkDict[eventTree]['tupleName']
912  event = {}
913  # is this a cint tree
914  isChain = eventTree.__class__.__name__ == 'TChain'
915  if isChain:
916  # This means that 'eventTree' is a ROOT.TChain
917  eventTree.GetEntry (eventIndex)
918  else:
919  # This means that 'eventTree' is a FWLite Events
920  eventTree.to(eventIndex)
921  tofillDict = GenObject._tofillDict.get (tupleName)
922  ntupleDict = GenObject._ntupleDict.get (tupleName)
923  if not tofillDict:
924  print "Don't know how to fill from '%s' ntuple." % tupleName
925  return
926  eventBranchName = ntupleDict['runevent']
927  for objName in tofillDict:
928  branchName = ntupleDict[objName]
929  if onlyRunEvent and branchName != eventBranchName:
930  # not now
931  continue
932  # Have we been given 'tofill' info for this object?
933  if not branchName:
934  # guess not
935  continue
936  if isChain:
937  # Root TChain
938  objects = getattr (eventTree, branchName)
939  else:
940  # FWLite
941  shortcut = ntupleDict.get('_shortcut', {}).get(branchName)
942  if shortcut:
943  objects = GenObject.evaluateFunction (eventTree, shortcut)
944  else:
945  eventTree.toBegin()
946  handle = ntupleDict.get('_handle', {}).get(branchName)
947  label = ntupleDict.get('_label' , {}).get(branchName)
948  if not handle or not label:
949  raise RuntimeError, "Missing handle or label for '%s'"\
950  % branchName
951  if not eventTree.getByLabel (label, handle):
952  raise RuntimeError, "not able to get %s for %s" \
953  % (label, branchName)
954  objects = handle.product()
955  # is this a singleton?
956  if GenObject.isSingleton (objName):
957  event[objName] = GenObject.\
958  _genObjectClone (objName,
959  tupleName,
960  objects)
961  continue
962  # if we're here then we have a vector of items
963  if debug: warn (objName, spaces = 3)
964  event[objName] = []
965  for index, obj in enumerate (objects):
966  event[objName].append( GenObject.\
967  _genObjectClone (objName,
968  tupleName,
969  obj,
970  index) )
971  del objects
972  # end for obj
973  ## if not isChain:
974  ## del rootEvent
975  # end for objName
976  return event
977 
978 
979  @staticmethod
980  def printEvent (event):
981  """Prints out event dictionary. Mostly for debugging"""
982  # Print out all singletons first
983  for objName, obj in sorted (event.iteritems()):
984  #obj = event[objName]
985  # is this a singleton?
986  if GenObject.isSingleton (objName):
987  print "%s: %s" % (objName, obj)
988  # Now print out all vectors
989  for objName, obj in sorted (event.iteritems()):
990  #obj = event[objName]
991  # is this a singleton?
992  if not GenObject.isSingleton (objName):
993  # o.k. obj is a vector
994  print "%s:" % objName
995  for single in obj:
996  print " ", single
997  print
998 
999 
1000  @staticmethod
1001  def setAliases (eventTree, tupleName):
1002  """runs SetAlias on all saved aliases"""
1003  aliases = GenObject._ntupleDict[tupleName].get('_alias', {})
1004  for name, alias in aliases.iteritems():
1005  eventTree.SetAlias (name, alias)
1006 
1007 
1008  @staticmethod
1009  def changeAlias (tupleName, name, alias):
1010  """Updates an alias for an object for a given tuple"""
1011  aliasDict = GenObject._ntupleDict[tupleName]['_alias']
1012  if not aliasDict.has_key (name):
1013  raise RuntimeError, "unknown name '%s' in tuple '%s'" % \
1014  (name, tupleName)
1015  aliasDict[name] = alias
1016 
1017 
1018  @staticmethod
1019  def changeLabel (tupleName, objectName, label):
1020  """Updates an label for an object for a given tuple"""
1021  labelDict = GenObject._ntupleDict[tupleName]['_label']
1022  if not labelDict.has_key (objectName):
1023  raise RuntimeError, "unknown name '%s' in tuple '%s'" % \
1024  (objectName, tupleName)
1025  label = tuple( GenObject._commaRE.split( label ) )
1026  labelDict[objectName] = label
1027 
1028 
1029  @staticmethod
1030  def prepareTuple (tupleName, files, numEventsWanted = 0):
1031  """Given the tuple name and list of files, returns either a
1032  TChain or EventTree, and number of entries"""
1033  if "GenObject" == tupleName:
1034  GenObject.prepareToLoadGenObject()
1035  if not isinstance (files, list):
1036  # If this isn't a list, make it one
1037  files = [files]
1038  ntupleDict = GenObject._ntupleDict[tupleName]
1039  treeName = ntupleDict["_tree"]
1040  if ntupleDict.get('_useChain'):
1041  chain = ROOT.TChain (treeName)
1042  for filename in files:
1043  chain.AddFile (filename)
1044  numEntries = chain.GetEntries()
1045  # Are we using a chain or EventTree here?
1046  else:
1047  chain = Events (files, forceEvent=True)
1048  numEntries = chain.size()
1049  chainDict = GenObject._kitchenSinkDict.setdefault (chain, {})
1050  if numEventsWanted and numEventsWanted < numEntries:
1051  numEntries = numEventsWanted
1052  chainDict['numEntries'] = numEntries
1053  chainDict['tupleName' ] = tupleName
1054  return chain
1055 
1056 
1057  @staticmethod
1058  def getRunEventEntryDict (chain, tupleName, numEntries):
1059  """Returns a dictionary of run, event tuples to entryIndicies"""
1060  reeDict = {}
1061  for entryIndex in xrange (numEntries):
1062  event = GenObject.loadEventFromTree (chain,
1063  entryIndex,
1064  onlyRunEvent = True)
1065  runevent = event['runevent']
1066  reeDict[ GenObject._re2key (runevent) ] = entryIndex
1067  #reeDict[ "one two three" ] = entryIndex
1068  del event
1069  return reeDict
1070 
1071 
1072  @staticmethod
1073  def _re2key (runevent):
1074  """Given a GO 'runevent' object, returns a sortable key"""
1075  # if we don't know how to make this object yet, let's figure
1076  # it out
1077  if not GenObject._runEventListDone:
1078  GenObject._runEventListDone = True
1079  ignoreSet = set( ['run', 'event'] )
1080  for varName in sorted (runevent.__dict__.keys()):
1081  if varName.startswith ('_') or varName in ignoreSet:
1082  continue
1083  form = runevent.getVariableProperty (varName, "form")
1084  if not form:
1085  form = '%s'
1086  GenObject._runEventList.append ((varName, form))
1087  key = 'run:%d event:%d' % (runevent.run, runevent.event)
1088  for items in GenObject._runEventList:
1089  varName = items[0]
1090  form = ' %s:%s' % (varName, items[1])
1091  key += form % runevent.getVariableProperty (varName)
1092  return key
1093 
1094 
1095  @staticmethod
1096  def _key2re (key, runevent=None):
1097  """Given a key, returns a GO 'runevent' object"""
1098  if not runevent:
1099  runevent = GenObject ('runevent')
1100  words = GenObject._spacesRE.split (key)
1101  for word in words:
1102  match = GenObject._singleColonRE.search (word)
1103  if match:
1104  # for now, I'm assuming everything in the runevent
1105  # tuple is an integer. If this isn't the case, I'll
1106  # have to come back and be more clever here.
1107  runevent.__setattr__ (match.group(1), int( match.group(2) ))
1108  return runevent
1109 
1110 
1111  @staticmethod
1112  def compareRunEventDicts (firstDict, secondDict):
1113  """Compares the keys of the two dicts and returns three sets:
1114  the overlap, first but not second, and second but not first."""
1115  overlap = set()
1116  firstOnly = set()
1117  secondOnly = set()
1118  # loop over the keys of the first dict and compare to second dict
1119  for key in firstDict.keys():
1120  if secondDict.has_key (key):
1121  overlap.add (key)
1122  else:
1123  firstOnly.add (key)
1124  # now loop over keys of second dict and only check for missing
1125  # entries in first dict
1126  for key in secondDict.keys():
1127  if not firstDict.has_key (key):
1128  secondOnly.add (key)
1129  # All done
1130  return overlap, firstOnly, secondOnly
1131 
1132 
1133  @staticmethod
1134  def pairEquivalentObjects (vec1, vec2):
1135  """Finds the equivalent objects in the two vectors"""
1136  len1, len2 = len (vec1), len (vec2)
1137  debug = GenObject._kitchenSinkDict.get ('debug', False)
1138  if not len1 or not len2:
1139  # Nothing to see here folks. Keep moving.
1140  if len1:
1141  noMatch1Set = set( xrange(len1) )
1142  else:
1143  noMatch1Set = set ()
1144  if len2:
1145  noMatch2Set = set( xrange(len2) )
1146  else:
1147  noMatch2Set = set ()
1148  if debug: warn ("Nothing found", sapces=6)
1149  return set(), noMatch1Set, noMatch2Set
1150  objName = vec1[0]._objName
1151  equivList = GenObject._equivDict[objName]
1152  firstDict = {}
1153  secondDict = {}
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  #print 'retuple', reTuple
1356  if debug: warn ('event1', blankLines = 3)
1357  event1 = GenObject.loadEventFromTree (chain1, ree1 [reTuple])
1358  if debug: warn ('event2', blankLines = 3)
1359  event2 = GenObject.loadEventFromTree (chain2, ree2 [reTuple])
1360  if GenObject._kitchenSinkDict.get('printEvent'):
1361  print "event1:"
1362  GenObject.printEvent (event1)
1363  print "event2:"
1364  GenObject.printEvent (event2)
1365  if GenObject._kitchenSinkDict.get('blur'):
1366  where = reTuple
1367  GenObject.blurEvent (event1,
1368  GenObject._kitchenSinkDict['blur'],
1369  where)
1370  for objName in sorted (event1.keys()):
1371  if "runevent" == objName:
1372  # runevent is a special case. We don't compare these
1373  continue
1374  if not GenObject._equivDict.get (objName):
1375  # we don't know how to compare these objects, so
1376  # skip them.
1377  continue
1378  if GenObject.isSingleton (objName):
1379  # I'll add this in later. For now, just skip it
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 countDict.has_key (key):
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  rootObj.diff.push_back ( GenObject._rootDiffObject \
1422  ( vec1[ pair[1 - 1] ],
1423  vec2[ pair[2 - 1] ] ) )
1424  problems = GenObject.\
1425  compareTwoItems (vec1[ pair[1 - 1] ],
1426  vec2[ pair[2 - 1] ])
1427  if problems.keys():
1428  # pprint.pprint (problems)
1429  for varName in problems.keys():
1430  countDict = resultsDict.\
1431  setdefault (objName, {}).\
1432  setdefault ('_var', {})
1433  if countDict.has_key (varName):
1434  countDict[varName] += 1
1435  else:
1436  countDict[varName] = 1
1437  key = 'count_%s' % objName
1438  if not resultsDict.has_key (key):
1439  resultsDict[key] = 0
1440  resultsDict[key] += len (matchedSet)
1441  # try cleaning up
1442  del vec1
1443  del vec2
1444  # end for objName
1445  if diffOutputName:
1446  diffTree.Fill()
1447  del event1
1448  del event2
1449  # end for overlap
1450  if diffOutputName:
1451  diffTree.Write()
1452  missingTree.Write()
1453  rootfile.Close()
1454  return resultsDict
1455 
1456 
1457  @staticmethod
1458  def saveTupleAs (chain, rootFile):
1459  """Saves a chain as a GO tree"""
1460  print "saveTupleAs"
1461  rootfile, tree = GenObject.setupOutputTree (rootFile, "goTree")
1462  numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1463  for entryIndex in xrange (numEntries):
1464  event = GenObject.loadEventFromTree (chain, entryIndex)
1465  if GenObject._kitchenSinkDict.get('blur'):
1466  where = "run %d event %d" % (event['runevent'].run,
1467  event['runevent'].event)
1468  if random.random() < GenObject._kitchenSinkDict.get('blur'):
1469  # dropping event
1470  print "Dropping", where
1471  continue
1472  GenObject.blurEvent (event,
1473  GenObject._kitchenSinkDict['blur'],
1474  where)
1475  # check to see if we should drop the event
1476  if GenObject._kitchenSinkDict.get('printEvent'):
1477  GenObject.printEvent (event)
1478  GenObject._fillRootObjects (event)
1479  tree.Fill()
1480  tree.Write()
1481  rootfile.Close()
1482 
1483 
1484  @staticmethod
1485  def setGlobalFlag (key, value):
1486  """Sets a global flag in _kitchenSinkDict"""
1487  GenObject._kitchenSinkDict [key] = value
1488 
1489 
1490  @staticmethod
1491  def printTuple (chain):
1492  """Prints out all events to stdout"""
1493  numEntries = GenObject._kitchenSinkDict[chain]['numEntries']
1494  debug = GenObject._kitchenSinkDict.get ('debug', False)
1495  if debug: warn (numEntries)
1496  for entryIndex in xrange (numEntries):
1497  if debug: warn (entryIndex, spaces=3)
1498  event = GenObject.loadEventFromTree (chain, entryIndex)
1499  GenObject.printEvent (event)
1500  if debug: warn(spaces=3)
1501 
1502  @staticmethod
1503  def _convertStringToParameters (string):
1504  """Convert comma-separated string into a python list of
1505  parameters. Currently only understands strings, floats, and
1506  integers."""
1507  retval = []
1508  words = GenObject._commaRE.split (string)
1509  for word in words:
1510  if not len (word):
1511  continue
1512  match = GenObject._singleQuoteRE.search (word)
1513  if match:
1514  retval.append (match.group (1))
1515  continue
1516  match = GenObject._doubleQuoteRE.search (word)
1517  if match:
1518  retval.append (match.group (1))
1519  continue
1520  try:
1521  val = int (word)
1522  retval.append (val)
1523  continue
1524  except:
1525  pass
1526  try:
1527  val = float (word)
1528  retval.append (val)
1529  continue
1530  except:
1531  pass
1532  # if we're still here, we've got a problem
1533  raise RuntimeError, "Unknown parameter '%s'." % word
1534  return retval
1535 
1536 
1537  ######################
1538  ## Member Functions ##
1539  ######################
1540 
1541 
1542  def __init__ (self, objName):
1543  """Class initializer"""
1544  if not GenObject._objsDict.has_key (objName):# or \
1545  #not GenObject._equivDict.has_key (objName) :
1546  # not good
1547  print "Error: GenObject does not know about object '%s'." % objName
1548  raise RuntimeError, "Failed to create GenObject object."
1549  self._localObjsDict = GenObject._objsDict [objName]
1550  self._objName = objName;
1551  for key, varDict in self._localObjsDict.iteritems():
1552  # if the key starts with an '_', then it is not a
1553  # variable, so don't treat it as one.
1554  if key.startswith ("_"):
1555  continue
1556  self.setValue (key, varDict['default'])
1557 
1558 
1559  def setValue (self, name, value):
1560  """Wrapper for __setattr___"""
1561  self.__setattr__ (name, value)
1562 
1563 
1564  def getVariableProperty (self, var, key):
1565  """ Returns property assoicated with 'key' for variable 'var'
1566  of object of the same type as 'self'. Returns 'None' if 'var'
1567  or 'key' is not defined."""
1568  return GenObject._objsDict.get (self._objName,
1569  {}).get (var, {}). get (key, None)
1570 
1571 
1572  def __setattr__ (self, name, value):
1573  """Controls setting of values."""
1574  if name.startswith ("_"):
1575  # The internal version. Set anything you want.
1576  object.__setattr__ (self, name, value)
1577  else:
1578  # user version - Make sure this variable has already been
1579 
1580  # defined for this type:
1581  if not self._localObjsDict.has_key (name):
1582  # this variable has not been defined
1583  print "Warning: '%s' for class '%s' not setup. Skipping." % \
1584  (name, self._objName)
1585  return
1586  varType = self.getVariableProperty (name, 'varType')
1587  # if this is an int, make sure it stays an int
1588  if GenObject.types.int == varType:
1589  try:
1590  # This will work with integers, floats, and string
1591  # representations of integers.
1592  value = int (value)
1593  except:
1594  # This works with string representations of floats
1595  value = int( float( value ) )
1596  elif GenObject.types.long == varType:
1597  try:
1598  # This will work with integers, floats, and string
1599  # representations of integers.
1600  value = long (value)
1601  except:
1602  # This works with string representations of floats
1603  value = long( float( value ) )
1604  elif GenObject.types.float == varType:
1605  # Make sure it's a float
1606  value = float (value)
1607  elif GenObject.types.string == varType:
1608  # make sure it's a string
1609  value = str (value)
1610  # if we're still here, set it
1611  object.__setattr__ (self, name, value)
1612 
1613 
1614  def __call__ (self, key):
1615  """Makes object callable"""
1616  return object.__getattribute__ (self, key)
1617 
1618 
1619  def __str__ (self):
1620  """String representation"""
1621  retval = ""
1622  for varName, value in sorted (self.__dict__.iteritems()):
1623  if varName.startswith ('_'): continue
1624  form = self.getVariableProperty (varName, "form")
1625  if form:
1626  format = "%s:%s " % (varName, form)
1627  retval = retval + format % value
1628  else:
1629  retval = retval + "%s:%s " % (varName, value)
1630  return retval
1631 
def warn
Definition: GenObject.py:28
#define abs(x)
Definition: mlp_lapack.h:159
bool setValue(Container &, const reco::JetBaseRef &, const JetExtendedData &)
associate jet with value. Returns false and associate nothing if jet is already associated ...
dictionary map
Definition: Association.py:160
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:56
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