CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/Validation/Tools/scripts/useReflexToDescribeForGenObject.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import ROOT
00004 import re
00005 import pprint
00006 import sys
00007 import inspect
00008 import optparse
00009 
00010 defsDict = {
00011     'int'    : '%-40s : form=%%%%8d     type=int',
00012     'float'  : '%-40s : form=%%%%7.2f   prec=',
00013     'str'    : '%-40s : form=%%%%20s    type=string',
00014     'long'   : '%-40s : form=%%%%10d    type=long',
00015     }
00016 
00017 root2GOtypeDict = {
00018     'int'                      : 'int',
00019     'float'                    : 'float',
00020     'double'                   : 'float',
00021     'long'                     : 'long',
00022     'long int'                 : 'long',
00023     'unsigned int'             : 'int',
00024     'bool'                     : 'int',
00025     'string'                   : 'str',
00026     'std::basic_string<char>'  : 'str',
00027     }
00028 
00029 startString = """
00030 # -*- sh -*- For Font lock mode
00031 
00032 ###########################
00033 ## GenObject Definitions ##
00034 ###########################
00035 
00036 # GenObject 'event' definition
00037 [runevent singleton]
00038 run:   type=int
00039 event: type=int
00040 """
00041 
00042 defTemplate = """
00043 #####################
00044 ## %(OBJS)s Definition ##
00045 #####################
00046 
00047 # Nickname and Tree
00048 [%(objs)s:FWLite]
00049 
00050 # 'reco'-tupe 'runevent' 'tofill' information
00051 [runevent:%(objs)s:EventAuxiliary shortcut=eventAuxiliary()]
00052 run:   run()
00053 event: event()
00054 
00055 """
00056 
00057 colonRE        = re.compile (r':')
00058 dotRE          = re.compile (r'\.')
00059 nonAlphaRE     = re.compile (r'\W')
00060 alphaRE        = re.compile (r'(\w+)')
00061 vetoedTypes    = set()
00062 
00063 def getObjectList (objectName, base, verbose = False, memberData = False):
00064     """Get a list of interesting things from this object"""
00065     # The autoloader needs an object before it loads its dictionary.
00066     # So let's give it one.
00067     try:
00068         rootObjConstructor = getattr (ROOT, objectName)
00069     except AttributeError as missingAttr:
00070         if str(missingAttr) in ['double', 'int']:
00071             print "Do not need to describe doubles or ints"
00072             sys.exit(0)
00073         else:
00074             raise
00075 
00076     obj = rootObjConstructor()
00077     alreadySeenFunction = set()
00078     etaFound, phiFound = False, False
00079     global vetoedTypes
00080     retval = []
00081     # Put the current class on the queue and start the while loop
00082     reflexList = [ ROOT.Reflex.Type.ByName (objectName) ]
00083     if verbose: print reflexList
00084     # Uses while because reflixList is really a stack
00085     while reflexList:
00086         reflex = reflexList.pop (0) # get first element
00087         print "Looking at %s" % reflex.Name (0xffffffff)
00088         if verbose:
00089             print "baseSize", reflex.BaseSize()
00090             print "FunctionMemberSize", reflex.FunctionMemberSize()
00091         for baseIndex in range( reflex.BaseSize() ) :
00092             reflexList.append( reflex.BaseAt(baseIndex).ToType() )
00093         for index in range( reflex.FunctionMemberSize() ):
00094             funcMember = reflex.FunctionMemberAt (index)
00095             # if we've already seen this, don't bother again
00096             name = funcMember.Name()
00097             if verbose:
00098                 print "name", name
00099             if name == 'eta':
00100                 etaFound = True
00101             elif name == 'phi':
00102                 phiFound = True
00103             if name in alreadySeenFunction:
00104                 continue
00105             # make sure this is an allowed return type
00106             returnType = funcMember.TypeOf().ReturnType().Name (0xffffffff)
00107             goType     = root2GOtypeDict.get (returnType, None)
00108             if verbose:
00109                 print "   type", returnType, goType
00110             if not goType:
00111                 vetoedTypes.add (returnType)
00112                 if verbose:
00113                     print "     skipped"
00114                 continue
00115             elif verbose:
00116                 print "     good"
00117             # only bother printout out lines where it is a const function
00118             # and has no input parameters.
00119             if funcMember.IsConst() and not funcMember.FunctionParameterSize():
00120                 retval.append( ("%s.%s()" % (base, name), goType))
00121                 alreadySeenFunction.add( name )
00122                 if verbose:
00123                     print "     added"
00124             elif verbose:
00125                 print "      failed IsConst() and FunctionParameterSize()"
00126         if not memberData:
00127             continue
00128         for index in range( reflex.DataMemberSize() ):
00129             data = reflex.DataMemberAt( index );
00130             name = data.Name()
00131             dataType = data.MemberType().__class__.__name__
00132             goType = root2GOtypeDict.get (dataType, None)
00133             if not goType:
00134                 continue
00135             if verbose:
00136                 print "name", name, "dataType", dataType, "goType", goType
00137             retval.append ( ("%s.%s" % (base, name), goType) )
00138     retval.sort()
00139     return retval, etaFound and phiFound
00140 
00141 
00142 def genObjNameDef (line):
00143     """Returns GenObject name and ntuple definition function"""
00144     words = dotRE.split (line)[1:]
00145     func = ".".join (words)
00146     name =  "_".join (words)
00147     name = nonAlphaRE.sub ('', name)
00148     return name, func
00149 
00150 
00151 def genObjectDef (mylist, tuple, alias, label, type, etaPhiFound):
00152     """Does something, but I can't remembrer what... """
00153     print "tuple %s alias %s label %s type %s" % (tuple, alias, label, type)
00154     # first get the name of the object
00155     firstName = mylist[0][0]
00156     match = alphaRE.match (firstName)
00157     if not match:
00158         raise RuntimeError, "firstName doesn't parse correctly. (%s)" \
00159               % firstName
00160     genName = match.group (1)
00161     genDef =  " ## GenObject %s Definition ##\n[%s]\n" % \
00162              (genName, genName)
00163     if options.index or not etaPhiFound:
00164         # either we told it to always use index OR either eta or phi
00165         # is missing.
00166         genDef += "-equiv: index,0\n";
00167     else:
00168         genDef += "-equiv: eta,0.1 phi,0.1 index,100000\n";
00169     tupleDef = '[%s:%s:%s label=%s type=%s]\n' % \
00170                (genName, tuple, alias, label, type)
00171 
00172     for variable in mylist:
00173         name, func = genObjNameDef (variable[0])
00174         typeInfo   = variable[1]
00175         form = defsDict[ typeInfo ]
00176         genDef   += form % name + '\n'
00177         tupleDef += "%-40s : %s\n" % (name, func)
00178     return genDef, tupleDef
00179 
00180 
00181 if __name__ == "__main__":
00182     # Setup options parser
00183     parser = optparse.OptionParser \
00184              ("usage: %prog [options]  objectName\n" \
00185               "Creates control file for GenObject.")
00186     parser.add_option ('--goName', dest='goName', type='string',
00187                        default='',
00188                        help='GenObject name')
00189     parser.add_option ('--index', dest='index', action='store_true',
00190                        help='use index for matching')
00191     parser.add_option ('--label', dest='label', type='string',
00192                        default = 'dummyLabel',
00193                        help="Tell GO to set an label")
00194     parser.add_option ('--output', dest='output', type='string',
00195                        default = '',
00196                        help="Output (Default 'objectName.txt')")
00197     parser.add_option ('--precision', dest='precision', type='string',
00198                        default = '1e-5',
00199                        help="precision to use for floats (default %default)")
00200     parser.add_option ('--privateMemberData', dest='privateMemberData',
00201                        action='store_true',
00202                        help='include private member data (NOT for comparisons)')
00203     parser.add_option ('--tupleName', dest='tupleName', type='string',
00204                        default = 'reco',
00205                        help="Tuple name (default '%default')")
00206     parser.add_option ('--type', dest='type', type='string',
00207                        default = 'dummyType',
00208                        help="Tell GO to set an type")
00209     parser.add_option ('--verbose', dest='verbose', action='store_true',
00210                        help='Verbose output')
00211     options, args = parser.parse_args()
00212     defsDict['float'] += options.precision
00213     from Validation.Tools.GenObject import GenObject
00214     options.type = GenObject.decodeNonAlphanumerics (options.type)
00215     if len (args) < 1:
00216         raise RuntimeError, "Need to provide object name."
00217     #
00218     objectName = GenObject.decodeNonAlphanumerics (args[0])
00219     goName     = options.goName or colonRE.sub ('', objectName)
00220     outputFile = options.output or goName + '.txt'
00221     ROOT.gROOT.SetBatch()
00222     # load the right libraries, etc.
00223     ROOT.gSystem.Load("libFWCoreFWLite")
00224     ROOT.gSystem.Load("libDataFormatsFWLite")
00225     ROOT.gSystem.Load("libReflexDict")
00226     ROOT.AutoLibraryLoader.enable()
00227     mylist, etaPhiFound = getObjectList (objectName, goName, options.verbose,
00228                                          options.privateMemberData)
00229     if not len (mylist):
00230         print "There are no member functions that are useful for comparison."
00231         sys.exit (GenObject.uselessReturnCode)
00232     targetFile = open (outputFile, 'w')
00233     genDef, tupleDef = genObjectDef (mylist,
00234                                      options.tupleName,
00235                                      goName,
00236                                      options.label,
00237                                      options.type,
00238                                      etaPhiFound)
00239     targetFile.write (startString)
00240     targetFile.write (genDef)
00241     targetFile.write (defTemplate % {'objs':'reco', 'OBJS':'RECO'})
00242     targetFile.write (tupleDef)
00243     print "Vetoed types:"
00244     pprint.pprint ( sorted( list(vetoedTypes) ) )