Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:33:41

0001 #!/usr/bin/env python3
0002 
0003 from __future__ import print_function
0004 from builtins import range
0005 import ROOT
0006 import re
0007 import pprint
0008 import sys
0009 import inspect
0010 import optparse
0011 
0012 defsDict = {
0013     'int'    : '%-40s : form=%%%%8d     type=int',
0014     'float'  : '%-40s : form=%%%%7.2f   prec=',
0015     'str'    : '%-40s : form=%%%%20s    type=string',
0016     'long'   : '%-40s : form=%%%%10d    type=long',
0017     }
0018 
0019 root2GOtypeDict = {
0020     'int'                      : 'int',
0021     'float'                    : 'float',
0022     'double'                   : 'float',
0023     'long'                     : 'long',
0024     'long int'                 : 'long',
0025     'unsigned int'             : 'int',
0026     'bool'                     : 'int',
0027     'string'                   : 'str',
0028     'std::basic_string<char>'  : 'str',
0029     }
0030 
0031 startString = """
0032 # -*- sh -*- For Font lock mode
0033 
0034 ###########################
0035 ## GenObject Definitions ##
0036 ###########################
0037 
0038 # GenObject 'event' definition
0039 [runevent singleton]
0040 run:   type=int
0041 event: type=int
0042 """
0043 
0044 defTemplate = """
0045 #####################
0046 ## %(OBJS)s Definition ##
0047 #####################
0048 
0049 # Nickname and Tree
0050 [%(objs)s:FWLite]
0051 
0052 # 'reco'-tupe 'runevent' 'tofill' information
0053 [runevent:%(objs)s:EventAuxiliary shortcut=eventAuxiliary()]
0054 run:   run()
0055 event: event()
0056 
0057 """
0058 
0059 colonRE        = re.compile (r':')
0060 dotRE          = re.compile (r'\.')
0061 nonAlphaRE     = re.compile (r'\W')
0062 alphaRE        = re.compile (r'(\w+)')
0063 vetoedTypes    = set()
0064 
0065 def getObjectList (objectName, base, verbose = False, memberData = False):
0066     """Get a list of interesting things from this object"""
0067     # The autoloader needs an object before it loads its dictionary.
0068     # So let's give it one.
0069     try:
0070         rootObjConstructor = getattr (ROOT, objectName)
0071     except AttributeError as missingAttr:
0072         if str(missingAttr) in ['double', 'int']:
0073             print("Do not need to describe doubles or ints")
0074             sys.exit(0)
0075         else:
0076             raise
0077 
0078     obj = rootObjConstructor()
0079     alreadySeenFunction = set()
0080     vetoedFunction = set()
0081     etaFound, phiFound = False, False
0082     global vetoedTypes
0083     retval = []
0084     # Put the current class on the queue and start the while loop
0085     classList = [ ROOT.TClass.GetClass(objectName) ]
0086     if verbose: print(classList)
0087     # Uses while because reflixList is really a stack
0088     while classList:
0089         alreadySeenFunction.update(vetoedFunction) # skip functions hidden by derived class
0090         vetoedFunction.clear()
0091         oneclass = classList.pop (0) # get first element
0092         print("Looking at %s" % oneclass.GetName ())
0093         bases = oneclass.GetListOfBases()
0094         funcs = oneclass.GetListOfMethods()
0095         if verbose:
0096             print("baseSize", bases.GetSize())
0097             print("FunctionMemberSize", funcs.GetSize())
0098         for baseIndex in range( bases.GetSize() ) :
0099             classList.append( bases.At(baseIndex).GetClassPointer() )
0100         for index in range( funcs.GetSize() ):
0101             funcMember = funcs.At (index)
0102             # if we've already seen this, don't bother again
0103             name = funcMember.GetName()
0104             if verbose:
0105                 print("name", name)
0106             if name == 'eta':
0107                 etaFound = True
0108             elif name == 'phi':
0109                 phiFound = True
0110             if name in alreadySeenFunction:
0111                 continue
0112             # make sure this is an allowed return type
0113             returnType = funcMember.GetReturnTypeName()
0114             goType     = root2GOtypeDict.get (returnType, None)
0115             if verbose:
0116                 print("   type", returnType, goType)
0117             if not goType:
0118                 vetoedTypes.add (returnType)
0119                 if verbose:
0120                     print("     skipped")
0121                 continue
0122             elif verbose:
0123                 print("     good")
0124             # only bother printout out lines where it is a const function
0125             # and has no input parameters.
0126             if funcMember.Property() & ROOT.kIsConstMethod and not funcMember.GetNargs():
0127                 retval.append( ("%s.%s()" % (base, name), goType))
0128                 alreadySeenFunction.add( name )
0129                 if verbose:
0130                     print("     added")
0131             else :
0132                 vetoedFunction.add( name )
0133                 if verbose:
0134                     print("      failed IsConst() and GetNargs()")
0135         if not memberData:
0136             continue
0137         dataList = oneclass.GetListOfDataMembers()
0138         for index in range( dataList.GetSize() ):
0139             data = dataList.At( index );
0140             name = data.GetName()
0141             dataType = data.GetTypeName()
0142             goType = root2GOtypeDict.get (dataType, None)
0143             if not goType:
0144                 continue
0145             if verbose:
0146                 print("name", name, "dataType", dataType, "goType", goType)
0147             retval.append ( ("%s.%s" % (base, name), goType) )
0148     retval.sort()
0149     return retval, etaFound and phiFound
0150 
0151 
0152 def genObjNameDef (line):
0153     """Returns GenObject name and ntuple definition function"""
0154     words = dotRE.split (line)[1:]
0155     func = ".".join (words)
0156     name =  "_".join (words)
0157     name = nonAlphaRE.sub ('', name)
0158     return name, func
0159 
0160 
0161 def genObjectDef (mylist, tuple, alias, label, type, etaPhiFound):
0162     """Does something, but I can't remembrer what... """
0163     print("tuple %s alias %s label %s type %s" % (tuple, alias, label, type))
0164     # first get the name of the object
0165     firstName = mylist[0][0]
0166     match = alphaRE.match (firstName)
0167     if not match:
0168         raise RuntimeError("firstName doesn't parse correctly. (%s)" \
0169               % firstName)
0170     genName = match.group (1)
0171     genDef =  " ## GenObject %s Definition ##\n[%s]\n" % \
0172              (genName, genName)
0173     if options.index or not etaPhiFound:
0174         # either we told it to always use index OR either eta or phi
0175         # is missing.
0176         genDef += "-equiv: index,0\n";
0177     else:
0178         genDef += "-equiv: eta,0.1 phi,0.1 index,100000\n";
0179     tupleDef = '[%s:%s:%s label=%s type=%s]\n' % \
0180                (genName, tuple, alias, label, type)
0181 
0182     for variable in mylist:
0183         name, func = genObjNameDef (variable[0])
0184         typeInfo   = variable[1]
0185         form = defsDict[ typeInfo ]
0186         genDef   += form % name + '\n'
0187         tupleDef += "%-40s : %s\n" % (name, func)
0188     return genDef, tupleDef
0189 
0190 
0191 if __name__ == "__main__":
0192     # Setup options parser
0193     parser = optparse.OptionParser \
0194              ("usage: %prog [options]  objectName\n" \
0195               "Creates control file for GenObject.")
0196     parser.add_option ('--goName', dest='goName', type='string',
0197                        default='',
0198                        help='GenObject name')
0199     parser.add_option ('--index', dest='index', action='store_true',
0200                        help='use index for matching')
0201     parser.add_option ('--label', dest='label', type='string',
0202                        default = 'dummyLabel',
0203                        help="Tell GO to set an label")
0204     parser.add_option ('--output', dest='output', type='string',
0205                        default = '',
0206                        help="Output (Default 'objectName.txt')")
0207     parser.add_option ('--precision', dest='precision', type='string',
0208                        default = '1e-5',
0209                        help="precision to use for floats (default %default)")
0210     parser.add_option ('--privateMemberData', dest='privateMemberData',
0211                        action='store_true',
0212                        help='include private member data (NOT for comparisons)')
0213     parser.add_option ('--tupleName', dest='tupleName', type='string',
0214                        default = 'reco',
0215                        help="Tuple name (default '%default')")
0216     parser.add_option ('--type', dest='type', type='string',
0217                        default = 'dummyType',
0218                        help="Tell GO to set an type")
0219     parser.add_option ('--verbose', dest='verbose', action='store_true',
0220                        help='Verbose output')
0221     options, args = parser.parse_args()
0222     defsDict['float'] += options.precision
0223     from Validation.Tools.GenObject import GenObject
0224     options.type = GenObject.decodeNonAlphanumerics (options.type)
0225     if len (args) < 1:
0226         raise RuntimeError("Need to provide object name.")
0227     #
0228     objectName = GenObject.decodeNonAlphanumerics (args[0])
0229     goName     = options.goName or colonRE.sub ('', objectName)
0230     outputFile = options.output or goName + '.txt'
0231     ROOT.gROOT.SetBatch()
0232     # load the right libraries, etc.
0233     ROOT.gSystem.Load("libFWCoreFWLite")
0234     ROOT.gSystem.Load("libDataFormatsFWLite")
0235     #ROOT.gSystem.Load("libReflexDict")
0236     ROOT.FWLiteEnabler.enable()
0237     mylist, etaPhiFound = getObjectList (objectName, goName, options.verbose,
0238                                          options.privateMemberData)
0239     if not len (mylist):
0240         print("There are no member functions that are useful for comparison.")
0241         sys.exit (GenObject.uselessReturnCode)
0242     targetFile = open (outputFile, 'w')
0243     genDef, tupleDef = genObjectDef (mylist,
0244                                      options.tupleName,
0245                                      goName,
0246                                      options.label,
0247                                      options.type,
0248                                      etaPhiFound)
0249     targetFile.write (startString)
0250     targetFile.write (genDef)
0251     targetFile.write (defTemplate % {'objs':'reco', 'OBJS':'RECO'})
0252     targetFile.write (tupleDef)
0253     print("Vetoed types:")
0254     pprint.pprint ( sorted( list(vetoedTypes) ) )