Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-01 23:40:46

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