CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/HLTrigger/Tools/python/makeHLTPrescaleTable.py

Go to the documentation of this file.
00001 #!/usr/bin/env python 
00002 from sys import stderr, exit
00003 import commands, os
00004 
00005 from optparse import OptionParser
00006 parser = OptionParser(usage=
00007 """
00008 usage: %prog [options] csv_output_file
00009 
00010 examples:
00011 
00012  %prog out.csv
00013 
00014      produces a table of ALL runs and ALL paths (can take quite some time)
00015 
00016  %prog --path='*ele*' --path='*photon*' out.csv
00017 
00018      select only paths containing 'ele' and 'photon'
00019 
00020 """)
00021 parser.add_option("--firstRun",  dest="firstRun",  help="first run", type="int", metavar="RUN", default="1")
00022 parser.add_option("--lastRun",   dest="lastRun",   help="last run",  type="int", metavar="RUN", default="9999999")
00023 parser.add_option("--groupName", dest="groupName", help="select runs of name like NAME", metavar="NAME", default="Collisions%")
00024 parser.add_option("--rrurl",     dest="rrurl",     help="run registry xmlrpc url", metavar="URL", default="https://cms-service-runregistry-api.web.cern.ch/cms-service-runregistry-api/xmlrpc")
00025 parser.add_option("--overwrite", dest="overwrite", help="force overwriting of output CSV file", action="store_true", default=False)
00026 
00027 parser.add_option("--path",
00028                  dest="pathPatterns",
00029                  default = [],
00030                  action="append",
00031                  metavar="PATTERN",
00032                  help="restrict paths to PATTERN. Note that this can be a single path name or a pattern " +
00033                       "using wildcards (*,?) similar to those used for selecting multiple files (see " +
00034                       "the documentation of the fnmatch module for details). Note also that this option " +
00035                       "can be specified more than once to select multiple paths or patterns. If this option " +
00036                       "is not specified, all paths are considered. Note that the comparison is done " +
00037                       "in a case-INsensitive manner. " +
00038                       "You may have to escape wildcards (with quotes or backslash) in order to avoid "+
00039                       "expansion by the shell"
00040                  )
00041 
00042 # parser.add_option("--jsonOut",   dest="jsonOut",   help="dump prescales in JSON format on FILE", metavar="FILE")
00043 (options, args) = parser.parse_args()
00044 if len(args) != 1:
00045    parser.print_help()
00046    exit(2)
00047 
00048 csv_output_file = args[0]
00049 
00050 if os.path.exists(csv_output_file) and not options.overwrite:
00051    print >> stderr,"cowardly refusing to overwrite existing output file '" + csv_output_file + "'. Run this script without argument to see options for overriding this check."
00052    exit(1)
00053 
00054 #----------------------------------------------------------------------
00055 def getPrescaleTableFromProcessObject(process):
00056    """ returns a dict of hlt key to vector of prescales
00057    mapping """
00058 
00059    retval = {}
00060    for entry in process.PrescaleService.prescaleTable:
00061        retval[entry.pathName.value()] = entry.prescales.value()
00062 
00063    return retval    
00064 
00065 #----------------------------------------------------------------------
00066 
00067 def getProcessObjectFromConfDB(hlt_key):
00068    # print >> stderr,"\t%s ..." % hlt_key
00069    cmd = "edmConfigFromDB --orcoff --configName " + hlt_key
00070    # print >> stderr, "cmd=",cmd
00071    res = commands.getoutput(cmd)
00072 
00073    # potentially dangerous: we're running python code here
00074    # which we get from an external process (confDB).
00075    # we trust that there are no file deletion commands
00076    # in the HLT configurations...
00077 
00078    # for some keys, edmConfigFromDB seems to produce error messages.
00079    # just return None in this case
00080    try:
00081        exec(res)
00082    except:
00083        return None
00084 
00085    return process
00086 
00087 #----------------------------------------------------------------------
00088 def queryRR():
00089    """ returns a dict of run number mapping to the HLT key """
00090 
00091    stderr.write("Querying run registry for range [%d, %d], group name like %s ...\n" % (options.firstRun, options.lastRun, options.groupName))
00092    import xmlrpclib
00093    import xml.dom.minidom
00094    server = xmlrpclib.ServerProxy(options.rrurl)
00095    run_data = server.DataExporter.export('RUN', 'GLOBAL', 'xml_datasets', "{runNumber} >= %d AND {runNumber} <= %d AND {groupName} like '%s' AND {datasetName} = '/Global/Online/ALL'"  % (options.firstRun, options.lastRun, options.groupName))
00096    ret = {}
00097    xml_data = xml.dom.minidom.parseString(run_data)
00098    xml_runs = xml_data.documentElement.getElementsByTagName("RUN_DATASET")
00099    for xml_run in xml_runs:
00100        ret[xml_run.getElementsByTagName("RUN_NUMBER")[0].firstChild.nodeValue] = xml_run.getElementsByTagName("RUN_HLTKEY")[0].firstChild.nodeValue
00101    return ret
00102 
00103 #----------------------------------------------------------------------
00104 # main
00105 #----------------------------------------------------------------------
00106 
00107 # check whether we have a CMSSW environment initalized
00108 if os.system("which edmConfigFromDB") != 0:
00109    print >> stderr,"could not find the command edmConfigFromDB. Did you initialize your CMSSW runtime environment ?"
00110    exit(1)
00111 
00112 runKeys = queryRR()
00113 
00114 # maps from HLT key to prescale information. 
00115 # indexed as: prescaleTable[hlt_key][hlt_path_name]
00116 prescaleTable = {}
00117 
00118 # maps from 
00119 hlt_path_names_table = {}
00120 
00121 # set of all HLT paths seen so far
00122 all_hlt_path_names_seen = set()
00123 
00124 runs = sorted(runKeys.keys())
00125 
00126 # loop over all hlt keys found
00127 
00128 all_hlt_keys_seen = set(runKeys.values())
00129 
00130 print >> stderr,"found %d runs and %d HLT menus" % ( len(runKeys), len(all_hlt_keys_seen))
00131 
00132 index = 1
00133 
00134 for hlt_key in all_hlt_keys_seen:
00135 
00136    print >> stderr,"(%3d/%3d) Querying ConfDB for HLT menu %s" % (index, len(all_hlt_keys_seen) , hlt_key)
00137    process = getProcessObjectFromConfDB(hlt_key)
00138 
00139    if process == None:
00140        print >> stderr,"WARNING: unable to retrieve hlt_key '" + hlt_key + "'"
00141        continue
00142 
00143    prescaleTable[hlt_key] = getPrescaleTableFromProcessObject(process)
00144 
00145    all_path_names = set(process.paths.keys())
00146 
00147    # remember which hlt paths were in this menu
00148    hlt_path_names_table[hlt_key] = all_path_names
00149 
00150    # add this configuration's HLT paths to the list
00151    # of overall path names seen
00152    all_hlt_path_names_seen.update(all_path_names)
00153 
00154    index += 1
00155 
00156 # end of loop over all HLT keys
00157 
00158 # make sure the list of all HLT path names ever seen is sorted
00159 all_hlt_path_names_seen = sorted(all_hlt_path_names_seen)
00160 
00161 #--------------------
00162 # filter paths if required by the user
00163 if len(options.pathPatterns) > 0:
00164    import fnmatch
00165 
00166    tmp = []
00167 
00168    for path in all_hlt_path_names_seen:
00169 
00170        for pattern in options.pathPatterns:
00171            if fnmatch.fnmatch(path.lower(), pattern.lower()):
00172 
00173                # accept this path
00174                tmp.append(path)
00175                break
00176 
00177    all_hlt_path_names_seen = tmp
00178 
00179 # sanity check
00180 
00181 if len(all_hlt_path_names_seen) == 0:
00182    print >> stderr,"no HLT paths found, exiting"
00183    exit(1)
00184 
00185 #--------------------
00186 # now that we know all path names of all runs, produce the CSV
00187 import csv
00188 
00189 previous_hlt_key = None
00190 
00191 fout = open(csv_output_file,"w")
00192 
00193 csv_writer = csv.writer(fout,delimiter=";")
00194 
00195 csv_writer.writerow(['Table of HLT prescale factors'])
00196 csv_writer.writerow([])
00197 csv_writer.writerow(['Explanation:'])
00198 csv_writer.writerow(['number(s) = prescale factor(s), HLT path present in this menu'])
00199 csv_writer.writerow(['empty = HLT path NOT present in this menu'])
00200 csv_writer.writerow(['0 = HLT path present in this menu but prescale factor is zero'])
00201 csv_writer.writerow(['U = could not retrieve menu for this HLT key from confDB'])
00202 csv_writer.writerow([])
00203 csv_writer.writerow([])
00204 
00205 # write the header line
00206 column_names = [ 'run','' ]
00207 column_names.extend(all_hlt_path_names_seen)
00208 csv_writer.writerow(column_names)
00209 
00210 csv_writer.writerow([])
00211 
00212 for run in runs:
00213    hlt_key = runKeys[run]
00214 
00215    if hlt_key == previous_hlt_key:
00216        # the hlt key is the same as for the previous run
00217        # just reuse the existing contents of the variable 'values'
00218        # (apart from the run number)
00219        values[0] = run
00220        csv_writer.writerow(values)
00221        continue
00222 
00223    # HLT key has changed
00224 
00225    # insert a line with the menu's name
00226    #
00227    # check whether we actually could determine the menu
00228    if not hlt_path_names_table.has_key(hlt_key):
00229        # could previously not retrieve the python
00230        # configuration for this key 
00231        #
00232        # put some warnings in the output table
00233 
00234        csv_writer.writerow([hlt_key, "COULD NOT RETRIEVE MENU FROM CONFDB"])
00235 
00236        values = [ run , '' ]
00237        values.extend(len(all_hlt_path_names_seen) * [ "U" ])
00238 
00239        csv_writer.writerow(values)
00240 
00241        previous_hlt_key = hlt_key
00242        continue
00243 
00244    # everything seems ok for this key
00245 
00246    csv_writer.writerow([hlt_key])
00247 
00248    # now put together the list of prescales
00249    values = [ run , '' ]
00250 
00251    # find out which HLT keys were present and which prescale factors
00252    # they had
00253    for hlt_path in all_hlt_path_names_seen:
00254 
00255        if hlt_path in hlt_path_names_table[hlt_key]:
00256            # this HLT path was present in this menu
00257            # check whether there was an entry in the prescale
00258            # table
00259 
00260            # get the prescale factors (list) or just a list with 1
00261            # if this path was not present in the prescale table
00262            # for this menu
00263            prescales = prescaleTable[hlt_key].get(hlt_path, [ 1 ] )
00264 
00265            # merge the values to one comma separated string 
00266            # print "prescales=",prescales
00267            values.append(",".join([str(x) for x in prescales]))
00268 
00269        else:
00270            # path not found for this hlt key. append
00271            # an empty string for this column
00272            values.append('')
00273 
00274    # end loop over hlt paths        
00275 
00276    csv_writer.writerow(values)
00277 
00278    previous_hlt_key = hlt_key
00279 
00280 # end loop over runs
00281 
00282 fout.close()
00283 
00284 print >> stderr,"created CSV file",csv_output_file,". Field delimiter is semicolon."
00285