CMS 3D CMS Logo

useReflexToDescribeForGenObject.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from __future__ import print_function
4 from builtins import range
5 import ROOT
6 import re
7 import pprint
8 import sys
9 import inspect
10 import optparse
11 
12 defsDict = {
13  'int' : '%-40s : form=%%%%8d type=int',
14  'float' : '%-40s : form=%%%%7.2f prec=',
15  'str' : '%-40s : form=%%%%20s type=string',
16  'long' : '%-40s : form=%%%%10d type=long',
17  }
18 
19 root2GOtypeDict = {
20  'int' : 'int',
21  'float' : 'float',
22  'double' : 'float',
23  'long' : 'long',
24  'long int' : 'long',
25  'unsigned int' : 'int',
26  'bool' : 'int',
27  'string' : 'str',
28  'std::basic_string<char>' : 'str',
29  }
30 
31 startString = """
32 # -*- sh -*- For Font lock mode
33 
34 ###########################
35 ## GenObject Definitions ##
36 ###########################
37 
38 # GenObject 'event' definition
39 [runevent singleton]
40 run: type=int
41 event: type=int
42 """
43 
44 defTemplate = """
45 #####################
46 ## %(OBJS)s Definition ##
47 #####################
48 
49 # Nickname and Tree
50 [%(objs)s:FWLite]
51 
52 # 'reco'-tupe 'runevent' 'tofill' information
53 [runevent:%(objs)s:EventAuxiliary shortcut=eventAuxiliary()]
54 run: run()
55 event: event()
56 
57 """
58 
59 colonRE = re.compile (r':')
60 dotRE = re.compile (r'\.')
61 nonAlphaRE = re.compile (r'\W')
62 alphaRE = re.compile (r'(\w+)')
63 vetoedTypes = set()
64 
65 def getObjectList (objectName, base, verbose = False, memberData = False):
66  """Get a list of interesting things from this object"""
67  # The autoloader needs an object before it loads its dictionary.
68  # So let's give it one.
69  try:
70  rootObjConstructor = getattr (ROOT, objectName)
71  except AttributeError as missingAttr:
72  if str(missingAttr) in ['double', 'int']:
73  print("Do not need to describe doubles or ints")
74  sys.exit(0)
75  else:
76  raise
77 
78  obj = rootObjConstructor()
79  alreadySeenFunction = set()
80  vetoedFunction = set()
81  etaFound, phiFound = False, False
82  global vetoedTypes
83  retval = []
84  # Put the current class on the queue and start the while loop
85  classList = [ ROOT.TClass.GetClass(objectName) ]
86  if verbose: print(classList)
87  # Uses while because reflixList is really a stack
88  while classList:
89  alreadySeenFunction.update(vetoedFunction) # skip functions hidden by derived class
90  vetoedFunction.clear()
91  oneclass = classList.pop (0) # get first element
92  print("Looking at %s" % oneclass.GetName ())
93  bases = oneclass.GetListOfBases()
94  funcs = oneclass.GetListOfMethods()
95  if verbose:
96  print("baseSize", bases.GetSize())
97  print("FunctionMemberSize", funcs.GetSize())
98  for baseIndex in range( bases.GetSize() ) :
99  classList.append( bases.At(baseIndex).GetClassPointer() )
100  for index in range( funcs.GetSize() ):
101  funcMember = funcs.At (index)
102  # if we've already seen this, don't bother again
103  name = funcMember.GetName()
104  if verbose:
105  print("name", name)
106  if name == 'eta':
107  etaFound = True
108  elif name == 'phi':
109  phiFound = True
110  if name in alreadySeenFunction:
111  continue
112  # make sure this is an allowed return type
113  returnType = funcMember.GetReturnTypeName()
114  goType = root2GOtypeDict.get (returnType, None)
115  if verbose:
116  print(" type", returnType, goType)
117  if not goType:
118  vetoedTypes.add (returnType)
119  if verbose:
120  print(" skipped")
121  continue
122  elif verbose:
123  print(" good")
124  # only bother printout out lines where it is a const function
125  # and has no input parameters.
126  if funcMember.Property() & ROOT.kIsConstMethod and not funcMember.GetNargs():
127  retval.append( ("%s.%s()" % (base, name), goType))
128  alreadySeenFunction.add( name )
129  if verbose:
130  print(" added")
131  else :
132  vetoedFunction.add( name )
133  if verbose:
134  print(" failed IsConst() and GetNargs()")
135  if not memberData:
136  continue
137  dataList = oneclass.GetListOfDataMembers()
138  for index in range( dataList.GetSize() ):
139  data = dataList.At( index );
140  name = data.GetName()
141  dataType = data.GetTypeName()
142  goType = root2GOtypeDict.get (dataType, None)
143  if not goType:
144  continue
145  if verbose:
146  print("name", name, "dataType", dataType, "goType", goType)
147  retval.append ( ("%s.%s" % (base, name), goType) )
148  retval.sort()
149  return retval, etaFound and phiFound
150 
151 
152 def genObjNameDef (line):
153  """Returns GenObject name and ntuple definition function"""
154  words = dotRE.split (line)[1:]
155  func = ".".join (words)
156  name = "_".join (words)
157  name = nonAlphaRE.sub ('', name)
158  return name, func
159 
160 
161 def genObjectDef (mylist, tuple, alias, label, type, etaPhiFound):
162  """Does something, but I can't remembrer what... """
163  print("tuple %s alias %s label %s type %s" % (tuple, alias, label, type))
164  # first get the name of the object
165  firstName = mylist[0][0]
166  match = alphaRE.match (firstName)
167  if not match:
168  raise RuntimeError("firstName doesn't parse correctly. (%s)" \
169  % firstName)
170  genName = match.group (1)
171  genDef = " ## GenObject %s Definition ##\n[%s]\n" % \
172  (genName, genName)
173  if options.index or not etaPhiFound:
174  # either we told it to always use index OR either eta or phi
175  # is missing.
176  genDef += "-equiv: index,0\n";
177  else:
178  genDef += "-equiv: eta,0.1 phi,0.1 index,100000\n";
179  tupleDef = '[%s:%s:%s label=%s type=%s]\n' % \
180  (genName, tuple, alias, label, type)
181 
182  for variable in mylist:
183  name, func = genObjNameDef (variable[0])
184  typeInfo = variable[1]
185  form = defsDict[ typeInfo ]
186  genDef += form % name + '\n'
187  tupleDef += "%-40s : %s\n" % (name, func)
188  return genDef, tupleDef
189 
190 
191 if __name__ == "__main__":
192  # Setup options parser
193  parser = optparse.OptionParser \
194  ("usage: %prog [options] objectName\n" \
195  "Creates control file for GenObject.")
196  parser.add_option ('--goName', dest='goName', type='string',
197  default='',
198  help='GenObject name')
199  parser.add_option ('--index', dest='index', action='store_true',
200  help='use index for matching')
201  parser.add_option ('--label', dest='label', type='string',
202  default = 'dummyLabel',
203  help="Tell GO to set an label")
204  parser.add_option ('--output', dest='output', type='string',
205  default = '',
206  help="Output (Default 'objectName.txt')")
207  parser.add_option ('--precision', dest='precision', type='string',
208  default = '1e-5',
209  help="precision to use for floats (default %default)")
210  parser.add_option ('--privateMemberData', dest='privateMemberData',
211  action='store_true',
212  help='include private member data (NOT for comparisons)')
213  parser.add_option ('--tupleName', dest='tupleName', type='string',
214  default = 'reco',
215  help="Tuple name (default '%default')")
216  parser.add_option ('--type', dest='type', type='string',
217  default = 'dummyType',
218  help="Tell GO to set an type")
219  parser.add_option ('--verbose', dest='verbose', action='store_true',
220  help='Verbose output')
221  options, args = parser.parse_args()
222  defsDict['float'] += options.precision
223  from Validation.Tools.GenObject import GenObject
224  options.type = GenObject.decodeNonAlphanumerics (options.type)
225  if len (args) < 1:
226  raise RuntimeError("Need to provide object name.")
227  #
228  objectName = GenObject.decodeNonAlphanumerics (args[0])
229  goName = options.goName or colonRE.sub ('', objectName)
230  outputFile = options.output or goName + '.txt'
231  ROOT.gROOT.SetBatch()
232  # load the right libraries, etc.
233  ROOT.gSystem.Load("libFWCoreFWLite")
234  ROOT.gSystem.Load("libDataFormatsFWLite")
235  #ROOT.gSystem.Load("libReflexDict")
236  ROOT.FWLiteEnabler.enable()
237  mylist, etaPhiFound = getObjectList (objectName, goName, options.verbose,
238  options.privateMemberData)
239  if not len (mylist):
240  print("There are no member functions that are useful for comparison.")
241  sys.exit (GenObject.uselessReturnCode)
242  targetFile = open (outputFile, 'w')
243  genDef, tupleDef = genObjectDef (mylist,
244  options.tupleName,
245  goName,
246  options.label,
247  options.type,
248  etaPhiFound)
249  targetFile.write (startString)
250  targetFile.write (genDef)
251  targetFile.write (defTemplate % {'objs':'reco', 'OBJS':'RECO'})
252  targetFile.write (tupleDef)
253  print("Vetoed types:")
254  pprint.pprint ( sorted( list(vetoedTypes) ) )
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def genObjectDef(mylist, tuple, alias, label, type, etaPhiFound)
#define str(s)
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
def getObjectList(objectName, base, verbose=False, memberData=False)