00001
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
00066
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
00082 reflexList = [ ROOT.Reflex.Type.ByName (objectName) ]
00083 if verbose: print reflexList
00084
00085 while reflexList:
00086 reflex = reflexList.pop (0)
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
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
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
00118
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
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
00165
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
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
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) ) )