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