CMS 3D CMS Logo

useReflexToDescribeForGenObject.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
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) ) )
def genObjectDef(mylist, tuple, alias, label, type, etaPhiFound)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
#define str(s)
def getObjectList(objectName, base, verbose=False, memberData=False)