CMS 3D CMS Logo

convertParamsToOnlineFormat.py
Go to the documentation of this file.
1 #!/bin/env python
2 
3 import argparse
4 import FWCore.ParameterSet.Config as cms
5 from importlib import import_module
6 import os
7 import sys
8 import xml.etree.ElementTree as ET
9 
10 
11 # Pairwise generator: returns pairs of adjacent elements in a list / other iterable
12 def pairwiseGen(aList):
13  for i in xrange(len(aList)-1):
14  yield (aList[i], aList[i+1])
15 
16 def parseOfflineLUTfile(aRelPath):
17  # Find file by looking under directories listed in 'CMSSW_SEARCH_PATH' as outlined in https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideEdmFileInPath
18  searchPaths = os.getenv('CMSSW_SEARCH_PATH').split(':')
19  resolvedPath = None
20  for baseDir in searchPaths:
21  print "Looking for '" + aRelPath + "' under '" + baseDir + "'"
22  if os.path.isfile(os.path.join(baseDir, aRelPath)):
23  print " success!"
24  resolvedPath = os.path.join(baseDir, aRelPath)
25  break
26  if resolvedPath is None:
27  raise RuntimeError("Could not find LUT file '" + aRelPath + "' under directories in 'CMSSW_SEARCH_PATH'")
28 
29  with open(resolvedPath) as f:
30  entries = []
31  line_nr = 0
32  for line in f:
33  line_nr += 1
34  # Ignore comment lines
35  if line.startswith('#') or line == '\n':
36  continue
37 
38  # Remove trailing comments from data lines
39  stripped_line = line[:line.find('#')]
40 
41  # Split line into list of whitespace-separated items
42  items = stripped_line.split()
43  if len(items) != 2:
44  print "ERROR parsing file", resolvedPath, "on line", line_nr, "'" + line + "' : Splitting on whitespace produced", len(items), "items"
45  sys.exit(1)
46 
47  entries.append( (int(items[0]), int(items[1])) )
48 
49  # Sort the LUT
50  entries.sort(key= lambda x : x[0])
51  # Check that the LUT is not empty
52  if len(entries) == 0:
53  print "ERROR parsing file", resolvedPath, ": No LUT entries defined in the file"
54  sys.exit(1)
55 
56  # Check that no items from the LUT are missing
57  if entries[0][0] != 0:
58  print "ERROR parsing file", resolvedPath, ": LUT entries before index", entries[0][0], "are not defined"
59  sys.exit(1)
60 
61  for x1, x2 in pairwiseGen(entries):
62  if x1[0] != (x2[0]-1):
63  print "ERROR parsing file", resolvedPath, ": ", x2[0] - x1[0] - 1,"LUT entries between indices", x1[0], "and", x2[0], "are not defined"
64  sys.exit(1)
65 
66  return [x[1] for x in entries]
67 
68 
70 
71  def divideByEgLsb(aParam):
72  return int(aParam.value() / aModule.egLsb.value())
73 
74  def divideByTauLsb(aParam):
75  return int(aParam.value() / aModule.tauLsb.value())
76 
77  def divideByJetLsb(aParam):
78  return int(aParam.value() / aModule.jetLsb.value())
79 
80 
81  result = [
82  (('mp_common', 'sdfile'), None, ''),
83  (('mp_common', 'algoRev'), None, ''),
84  (('mp_common', 'leptonSeedThreshold'), '2_ClusterSeedThreshold.mif', divideByEgLsb(aModule.egSeedThreshold)),
85  (('mp_common', 'leptonTowerThreshold'), '3_ClusterThreshold.mif', divideByEgLsb(aModule.egNeighbourThreshold)),
86  (('mp_common', 'pileUpTowerThreshold'), '4_PileUpThreshold.mif', 0x0)
87  ]
88 
89  result += [
90  (('mp_egamma', 'egammaRelaxationThreshold'), '10_EgRelaxThr.mif', divideByEgLsb(aModule.egMaxPtHOverE)),
91  (('mp_egamma', 'egammaMaxEta'), '5_EgammaTauEtaMax.mif', aModule.egEtaCut.value()),
92  (('mp_egamma', 'egammaBypassCuts'), 'BypassEgVeto.mif', bool(aModule.egBypassEGVetos.value())),
93  (('mp_egamma', 'egammaHOverECut_iEtaLT15'), '_RatioCutLt15.mif', aModule.egHOverEcutBarrel.value()),
94  (('mp_egamma', 'egammaHOverECut_iEtaGTEq15'), '_RatioCutGe15.mif', aModule.egHOverEcutEndcap.value()),
95  (('mp_egamma', 'egammaBypassExtendedHOverE'), '_BypassExtHE.mif', bool(aModule.egBypassExtHOverE)),
96  (('mp_egamma', 'egammaEnergyCalibLUT'), 'C_EgammaCalibration_12to18.mif', parseOfflineLUTfile(aModule.egCalibrationLUTFile.value())),
97  (('mp_egamma', 'egammaIsoLUT1'), 'D_EgammaIsolation1_13to9.mif', parseOfflineLUTfile(aModule.egIsoLUTFile.value())),
98  (('mp_egamma', 'egammaIsoLUT2'), 'D_EgammaIsolation2_13to9.mif', parseOfflineLUTfile(aModule.egIsoLUTFile2.value()))
99  ]
100 
101  result += [
102  (('mp_tau', 'tauMaxEta'), '5_EgammaTauEtaMax.mif', aModule.isoTauEtaMax.value()),
103  (('mp_tau', 'tauEnergyCalibLUT'), 'I_TauCalibration_11to18.mif', parseOfflineLUTfile(aModule.tauCalibrationLUTFile.value())),
104  (('mp_tau', 'tauIsoLUT'), 'H_TauIsolation_12to9.mif', parseOfflineLUTfile(aModule.tauIsoLUTFile.value()))
105  ]
106 
107  result += [
108  (('mp_jet', 'jetSeedThreshold'), '1_JetSeedThreshold.mif', divideByJetLsb(aModule.jetSeedThreshold)),
109  (('mp_jet', 'jetMaxEta'), '6_JetEtaMax.mif', 0x00028),
110  (('mp_jet', 'HTMHT_maxJetEta'), '7_RingEtaMax.mif', aModule.etSumEtaMax[1]), # assert == etSumEtaMax[3] ?
111  (('mp_jet', 'HT_jetThreshold'), '8_HtThreshold.mif', int(aModule.etSumEtThreshold[1] / aModule.etSumLsb.value())),
112  (('mp_jet', 'MHT_jetThreshold'), '9_MHtThreshold.mif', int(aModule.etSumEtThreshold[3] / aModule.etSumLsb.value())),
113  (('mp_jet', 'jetBypassPileUpSub'), 'BypassJetPUS.mif', bool(aModule.jetBypassPUS.value())),
114  (('mp_jet', 'jetEnergyCalibLUT'), 'L_JetCalibration_11to18.mif', aModule.jetCalibrationLUTFile)
115  ]
116 
117  result += [
118  (('mp_sums', 'towerCountThreshold'), 'HeavyIonThr.mif', int(aModule.etSumEtThreshold[4] / aModule.etSumLsb.value()) ),
119  (('mp_sums', 'towerCountMaxEta'), 'HeavyIonEta.mif', aModule.etSumEtaMax[4]),
120  (('mp_sums', 'ETMET_maxTowerEta'), '7_RingEtaMax.mif', aModule.etSumEtaMax[0]), # assert == etSumEtaMax[2] ?
121  (('mp_sums', 'ecalET_towerThresholdLUT'), 'X_EcalTHR_11to9.mif', aModule.etSumEcalSumPUSLUTFile),
122  (('mp_sums', 'ET_towerThresholdLUT'), 'X_ETTHR_11to9.mif', aModule.etSumMetPUSLUTFile),
123  (('mp_sums', 'MET_towerThresholdLUT'), 'X_METTHR_11to9.mif', aModule.etSumMetPUSLUTFile)
124  ]
125 
126  result += [
127  (('demux', 'sdfile'), None, ''),
128  (('demux', 'algoRev'), None, 0xcafe)
129  ]
130 
131  result = [(a, b, parseOfflineLUTfile(c.value()) if type(c) is cms.FileInPath else c) for a, b, c in result]
132 
133  return result
134 
135 
136 def getXmlParameterMap(aModule):
137  result = {}
138  for xmlDetails, mifName, value in getFullListOfParameters(aModule):
139  if xmlDetails is not None:
140  if xmlDetails[0] in result:
141  result[xmlDetails[0]] += [(xmlDetails[1], value)]
142  else:
143  result[xmlDetails[0]] = [(xmlDetails[1], value)]
144 
145  return result
146 
147 
148 def getMifParameterMap(aModule):
149 
150  fullList = getFullListOfParameters(aModule)
151 
152  return {mifFileName : value for (_, mifFileName, value) in fullList if mifFileName is not None}
153 
154 
155 # Stolen from https://stackoverflow.com/questions/3095434/inserting-newlines-in-xml-file-generated-via-xml-etree-elementtree-in-python
156 def indent(elem, level=0):
157  i = "\n" + level*" "
158  if len(elem):
159  if not elem.text or not elem.text.strip():
160  elem.text = i + " "
161  if not elem.tail or not elem.tail.strip():
162  elem.tail = i
163  for elem in elem:
164  indent(elem, level+1)
165  if not elem.tail or not elem.tail.strip():
166  elem.tail = i
167  else:
168  if level and (not elem.tail or not elem.tail.strip()):
169  elem.tail = i
170 
171 def createMIF(aFilePath, aValue):
172  print "Writing MIF file:", aFilePath
173  with open(aFilePath, 'w') as f:
174  if type(aValue) is bool:
175  aValue = (1 if aValue else 0)
176 
177  if type(aValue) is int:
178  f.write( hex(aValue) )
179  elif type(aValue) is list:
180  f.write("\n".join([hex(x) for x in aValue]))
181  else:
182  raise RuntimeError("Do not know how to deal with parameter of type " + str(type(aValue)))
183 
184 
185 def createXML(parameters, contextId, outputFilePath):
186  topNode = ET.Element('algo', id='calol2')
187  contextNode = ET.SubElement(topNode, 'context', id=contextId)
188  for paramId, value in parameters:
189  if type(value) is bool:
190  ET.SubElement(contextNode, 'param', id=paramId, type='bool').text = str(value).lower()
191  elif type(value) is int:
192  ET.SubElement(contextNode, 'param', id=paramId, type='uint').text = "0x{0:05X}".format(value)
193  elif type(value) is str:
194  ET.SubElement(contextNode, 'param', id=paramId, type='string').text = value
195  elif type(value) is list:
196  ET.SubElement(contextNode, 'param', id=paramId, type='vector:uint').text = "\n " + ",\n ".join(["0x{0:05X}".format(x) for x in value]) + "\n "
197  else:
198  raise RuntimeError("Do not know how to deal with parameter '" + paramId + "' of type " + str(type(value)))
199  indent(topNode)
200 
201  print "Writing XML file:", outputFilePath
202  with open(outputFilePath, 'w') as f:
203  f.write(ET.tostring(topNode))
204 
205 
206 
207 if __name__ == '__main__':
208 
209  parser = argparse.ArgumentParser()
210 
211  parser.add_argument('params_cfi', help='Name of CMSSW cfi python file specifying the values for the calo parameters')
212  parser.add_argument('output_dir', help='Directory for MIF/XML output files')
213 
214  outputFormatGroup = parser.add_mutually_exclusive_group(required=True)
215  outputFormatGroup.add_argument('--mif', action='store_true')
216  outputFormatGroup.add_argument('--xml', action='store_true')
217 
218  args = parser.parse_args()
219 
220  moduleName = 'L1Trigger.L1TCalorimeter.' + args.params_cfi
221  print "Importing calo params from module:", moduleName
222  caloParams = import_module(moduleName).caloStage2Params
223 
224  print caloParams.egCalibrationLUTFile.value()
225  print caloParams.egIsoLUTFile.value()
226  print caloParams.egIsoLUTFile2.value()
227  os.mkdir(args.output_dir)
228 
229  if args.mif:
230  for fileName, value in getMifParameterMap(caloParams).iteritems():
231  createMIF(args.output_dir + '/' + fileName, value)
232  else:
233  for fileTag, paramList in getXmlParameterMap(caloParams).iteritems():
234  createXML(paramList, 'MainProcessor' if fileTag.startswith('mp') else 'Demux', args.output_dir + '/algo_' + fileTag + '.xml')
def createXML(parameters, contextId, outputFilePath)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
double split
Definition: MVATrainer.cc:139