CMS 3D CMS Logo

L1TCaloLayer1FetchLUTs.cc
Go to the documentation of this file.
1 // This function fetches Layer1 ECAL and HCAL LUTs from CMSSW configuration
2 // It is provided as a global helper function outside of class structure
3 // so that it can be shared by L1CaloLayer1 and L1CaloLayer1Spy
4 
5 #include <vector>
6 
10 
14 
20 
23 
24 #include "L1TCaloLayer1FetchLUTs.hh"
25 #include "UCTLogging.hh"
26 
27 using namespace l1tcalo;
28 
30  const L1TCaloLayer1FetchLUTsTokens &iTokens,
31  const edm::EventSetup &iSetup,
32  std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> > &eLUT,
33  std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> > &hLUT,
34  std::vector<std::array<std::array<uint32_t, nEtBins>, nHfEtaBins> > &hfLUT,
35  std::vector<unsigned int> &ePhiMap,
36  std::vector<unsigned int> &hPhiMap,
37  std::vector<unsigned int> &hfPhiMap,
38  bool useLSB,
39  bool useCalib,
40  bool useECALLUT,
41  bool useHCALLUT,
42  bool useHFLUT,
43  int fwVersion) {
44  int hfValid = 1;
45  const HcalTrigTowerGeometry &pG = iSetup.getData(iTokens.geom_);
46  if (!pG.use1x1()) {
47  edm::LogError("L1TCaloLayer1FetchLUTs")
48  << "Using Stage2-Layer1 but HCAL Geometry has use1x1 = 0! HF will be suppressed. Check Global Tag, etc.";
49  hfValid = 0;
50  }
51 
52  // CaloParams contains all persisted parameters for Layer 1
53  edm::ESHandle<l1t::CaloParams> paramsHandle = iSetup.getHandle(iTokens.params_);
54  if (not paramsHandle.isValid()) {
55  edm::LogError("L1TCaloLayer1FetchLUTs") << "Missing CaloParams object! Check Global Tag, etc.";
56  return false;
57  }
58  l1t::CaloParamsHelper caloParams(*paramsHandle.product());
59 
60  // Calo Trigger Layer1 output LSB Real ET value
61  double caloLSB = caloParams.towerLsbSum();
62  if (caloLSB != 0.5) {
63  // Lots of things expect this, better give fair warning if not
64  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloLSB (caloParams.towerLsbSum()) != 0.5, actually = " << caloLSB;
65  }
66 
67  // ECal/HCal scale factors will be a x*y*28 array:
68  // ieta = 28 eta scale factors (1 .. 28)
69  // etBin = size of Real ET Bins vector
70  // phiBin = max(Real Phi Bins vector)
71  // So, index = phiBin*etBin*28+etBin*28+ieta
72  auto ecalScaleETBins = caloParams.layer1ECalScaleETBins();
73  auto ecalScalePhiBins = caloParams.layer1ECalScalePhiBins();
74  if (ecalScalePhiBins.empty()) {
75  // Backwards-compatibility (no phi binning)
76  ecalScalePhiBins.resize(36, 0);
77  } else if (ecalScalePhiBins.size() % 36 != 0) {
78  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloParams.layer1ECalScaleETBins().size() is not multiple of 36 !!";
79  return false;
80  }
81  size_t numEcalPhiBins = (*std::max_element(ecalScalePhiBins.begin(), ecalScalePhiBins.end())) + 1;
82  auto ecalSF = caloParams.layer1ECalScaleFactors();
83  if (ecalSF.size() != ecalScaleETBins.size() * numEcalPhiBins * 28) {
84  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloParams.layer1ECalScaleFactors().size() != "
85  "caloParams.layer1ECalScaleETBins().size()*numEcalPhiBins*28 !!";
86  return false;
87  }
88  auto hcalScaleETBins = caloParams.layer1HCalScaleETBins();
89  auto hcalScalePhiBins = caloParams.layer1HCalScalePhiBins();
90  if (hcalScalePhiBins.empty()) {
91  hcalScalePhiBins.resize(36, 0);
92  } else if (hcalScalePhiBins.size() % 36 != 0) {
93  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloParams.layer1HCalScaleETBins().size() is not multiple of 36 !!";
94  return false;
95  }
96  size_t numHcalPhiBins = (*std::max_element(hcalScalePhiBins.begin(), hcalScalePhiBins.end())) + 1;
97  auto hcalSF = caloParams.layer1HCalScaleFactors();
98  if (hcalSF.size() != hcalScaleETBins.size() * numHcalPhiBins * 28) {
99  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloParams.layer1HCalScaleFactors().size() != "
100  "caloParams.layer1HCalScaleETBins().size()*numHcalPhiBins*28 !!";
101  return false;
102  }
103 
104  // HF 1x1 scale factors will be a x*y*12 array:
105  // ieta = 12 eta scale factors (30 .. 41)
106  // etBin = size of Real ET Bins vector
107  // phiBin = max(Real Phi Bins vector)
108  // So, index = phiBin*etBin*12+etBin*12+ieta
109  auto hfScaleETBins = caloParams.layer1HFScaleETBins();
110  auto hfScalePhiBins = caloParams.layer1HFScalePhiBins();
111  if (hfScalePhiBins.empty()) {
112  hfScalePhiBins.resize(36, 0);
113  } else if (hfScalePhiBins.size() % 36 != 0) {
114  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloParams.layer1HFScaleETBins().size() is not multiple of 36 !!";
115  return false;
116  }
117  size_t numHFPhiBins = (*std::max_element(hfScalePhiBins.begin(), hfScalePhiBins.end())) + 1;
118  auto hfSF = caloParams.layer1HFScaleFactors();
119  if (hfSF.size() != hfScaleETBins.size() * numHFPhiBins * 12) {
120  edm::LogError("L1TCaloLayer1FetchLUTs")
121  << "caloParams.layer1HFScaleFactors().size() != caloParams.layer1HFScaleETBins().size()*numHFPhiBins*12 !!";
122  return false;
123  }
124 
125  // Sanity check scale factors exist
126  if (useCalib && (ecalSF.empty() || hcalSF.empty() || hfSF.empty())) {
127  edm::LogError("L1TCaloLayer1FetchLUTs") << "Layer 1 calibrations requested (useCalib = True) but there are missing "
128  "scale factors in CaloParams! Please check conditions setup.";
129  return false;
130  }
131  // get energy scale to convert input from ECAL - this should be linear with LSB = 0.5 GeV
132  const double ecalLSB = 0.5;
133 
134  // get energy scale to convert input from HCAL
135  edm::ESHandle<CaloTPGTranscoder> decoder = iSetup.getHandle(iTokens.decoder_);
136  if (not decoder.isValid()) {
137  edm::LogError("L1TCaloLayer1FetchLUTs") << "Missing CaloTPGTranscoder object! Check Global Tag, etc.";
138  return false;
139  }
140 
141  // TP compression scale is always phi symmetric
142  // We default to 3 since HF has no ieta=41 iphi=1,2
143  auto decodeHcalEt = [&decoder](int iEta, uint32_t compressedEt, uint32_t iPhi = 3) -> double {
144  HcalTriggerPrimitiveSample sample(compressedEt);
145  HcalTrigTowerDetId id(iEta, iPhi);
146  if (std::abs(iEta) >= 30) {
147  id.setVersion(1);
148  }
149  return decoder->hcaletValue(id, sample);
150  };
151 
152  // Make ECal LUT
153  for (uint32_t phiBin = 0; phiBin < numEcalPhiBins; phiBin++) {
154  std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> phiLUT;
155  eLUT.push_back(phiLUT);
156  for (uint32_t etaBin = 0; etaBin < nCalEtaBins; etaBin++) {
157  for (uint32_t fb = 0; fb < nCalSideBins; fb++) {
158  for (uint32_t ecalInput = 0; ecalInput <= 0xFF; ecalInput++) {
159  uint32_t value = ecalInput;
160  if (useECALLUT) {
161  double linearizedECalInput = ecalInput * ecalLSB; // in GeV
162 
163  uint32_t etBin = 0;
164  for (; etBin < ecalScaleETBins.size(); etBin++) {
165  if (linearizedECalInput < ecalScaleETBins[etBin])
166  break;
167  }
168  if (etBin >= ecalScaleETBins.size())
169  etBin = ecalScaleETBins.size() - 1;
170 
171  double calibratedECalInput = linearizedECalInput;
172  if (useCalib)
173  calibratedECalInput *= ecalSF.at(phiBin * ecalScaleETBins.size() * 28 + etBin * 28 + etaBin);
174  if (useLSB)
175  calibratedECalInput /= caloLSB;
176 
177  value = calibratedECalInput;
178  if (fwVersion > 2) {
179  // Saturate if either decompressed value is over 127.5 GeV or input saturated
180  // (meaningless for ecal, since ecalLSB == caloLSB)
181  if (value > 0xFF || ecalInput == 0xFF) {
182  value = 0xFF;
183  }
184  } else {
185  if (value > 0xFF) {
186  value = 0xFF;
187  }
188  }
189  }
190  if (value == 0) {
191  value = (1 << 11);
192  } else {
193  uint32_t et_log2 = ((uint32_t)log2(value)) & 0x7;
194  value |= (et_log2 << 12);
195  }
196  value |= (fb << 10);
197  eLUT[phiBin][etaBin][fb][ecalInput] = value;
198  }
199  }
200  }
201  }
202 
203  // Make HCal LUT
204  for (uint32_t phiBin = 0; phiBin < numHcalPhiBins; phiBin++) {
205  std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> phiLUT;
206  hLUT.push_back(phiLUT);
207  for (uint32_t etaBin = 0; etaBin < nCalEtaBins; etaBin++) {
208  int caloEta = etaBin + 1;
209  int iPhi = 3;
210  auto pos = std::find(hcalScalePhiBins.begin(), hcalScalePhiBins.end(), phiBin);
211  if (pos != hcalScalePhiBins.end()) {
212  // grab an iPhi bin
213  auto index = std::distance(hcalScalePhiBins.begin(), pos);
214  if (index < 18) {
215  caloEta *= -1;
216  iPhi = index * 4 + 1;
217  } else {
218  iPhi = (index - 18) * 4 + 1;
219  }
220  }
221  for (uint32_t fb = 0; fb < nCalSideBins; fb++) {
222  for (uint32_t hcalInput = 0; hcalInput <= 0xFF; hcalInput++) {
223  uint32_t value = hcalInput;
224  if (useHCALLUT) {
225  // hcaletValue defined in L137 of CalibCalorimetry/CaloTPG/src/CaloTPGTranscoderULUT.cc
226  double linearizedHcalInput = decodeHcalEt(caloEta, hcalInput, iPhi); // in GeV
227 
228  uint32_t etBin = 0;
229  for (; etBin < hcalScaleETBins.size(); etBin++) {
230  if (linearizedHcalInput < hcalScaleETBins[etBin])
231  break;
232  }
233  if (etBin >= hcalScaleETBins.size())
234  etBin = hcalScaleETBins.size() - 1;
235 
236  double calibratedHcalInput = linearizedHcalInput;
237  if (useCalib)
238  calibratedHcalInput *= hcalSF.at(phiBin * hcalScaleETBins.size() * 28 + etBin * 28 + etaBin);
239  if (useLSB)
240  calibratedHcalInput /= caloLSB;
241 
242  value = calibratedHcalInput;
243  if (fwVersion > 2) {
244  // Saturate if either decompressed value is over 127.5 GeV or input saturated
245  if (value > 0xFF || hcalInput == 0xFF) {
246  value = 0xFF;
247  }
248  } else {
249  if (value > 0xFF) {
250  value = 0xFF;
251  }
252  }
253  }
254  if (value == 0) {
255  value = (1 << 11);
256  } else {
257  uint32_t et_log2 = ((uint32_t)log2(value)) & 0x7;
258  value |= (et_log2 << 12);
259  }
260  value |= (fb << 10);
261  hLUT[phiBin][etaBin][fb][hcalInput] = value;
262  }
263  }
264  }
265  }
266 
267  // Make HF LUT
268  for (uint32_t phiBin = 0; phiBin < numHFPhiBins; phiBin++) {
269  std::array<std::array<uint32_t, nEtBins>, nHfEtaBins> phiLUT;
270  hfLUT.push_back(phiLUT);
271  for (uint32_t etaBin = 0; etaBin < nHfEtaBins; etaBin++) {
272  int caloEta = etaBin + 30;
273  int iPhi = 3;
274  auto pos = std::find(hfScalePhiBins.begin(), hfScalePhiBins.end(), phiBin);
275  if (pos != hfScalePhiBins.end()) {
276  auto index = std::distance(hfScalePhiBins.begin(), pos);
277  if (index < 18) {
278  caloEta *= -1;
279  iPhi = index * 4 - 1;
280  } else {
281  iPhi = (index - 18) * 4 - 1;
282  }
283  if (iPhi < 0)
284  iPhi = 71;
285  }
286  for (uint32_t etCode = 0; etCode < nEtBins; etCode++) {
287  uint32_t value = etCode;
288  if (useHFLUT) {
289  double linearizedHFInput = 0;
290  if (hfValid) {
291  linearizedHFInput = decodeHcalEt(caloEta, value, iPhi); // in GeV
292  }
293 
294  uint32_t etBin = 0;
295  for (; etBin < hfScaleETBins.size(); etBin++) {
296  if (linearizedHFInput < hfScaleETBins[etBin])
297  break;
298  }
299  if (etBin >= hfScaleETBins.size())
300  etBin = hfScaleETBins.size() - 1;
301 
302  double calibratedHFInput = linearizedHFInput;
303  if (useCalib)
304  calibratedHFInput *= hfSF.at(phiBin * hfScalePhiBins.size() * 12 + etBin * 12 + etaBin);
305  if (useLSB)
306  calibratedHFInput /= caloLSB;
307 
308  if (fwVersion > 2) {
309  uint32_t absCaloEta = std::abs(caloEta);
310  if (absCaloEta > 29 && absCaloEta < 40) {
311  // Divide by two (since two duplicate towers are sent)
312  calibratedHFInput *= 0.5;
313  } else if (absCaloEta == 40 || absCaloEta == 41) {
314  // Divide by four
315  calibratedHFInput *= 0.25;
316  }
317  value = calibratedHFInput;
318  // Saturate if either decompressed value is over 127.5 GeV or input saturated
319  if (value >= 0xFF || etCode == 0xFF) {
320  value = 0x1FD;
321  }
322  } else {
323  value = calibratedHFInput;
324  if (value > 0xFF) {
325  value = 0xFF;
326  }
327  }
328  }
329  hfLUT[phiBin][etaBin][etCode] = value;
330  }
331  }
332  }
333 
334  // plus/minus, 18 CTP7, 4 iPhi each
335  for (uint32_t isPos = 0; isPos < 2; isPos++) {
336  for (uint32_t iPhi = 1; iPhi <= 72; iPhi++) {
337  uint32_t card = floor((iPhi + 1) / 4);
338  if (card > 17)
339  card -= 18;
340  ePhiMap[isPos * 72 + iPhi - 1] = ecalScalePhiBins[isPos * 18 + card];
341  hPhiMap[isPos * 72 + iPhi - 1] = hcalScalePhiBins[isPos * 18 + card];
342  hfPhiMap[isPos * 72 + iPhi - 1] = hfScalePhiBins[isPos * 18 + card];
343  }
344  }
345 
346  return true;
347 }
348 /* vim: set ts=8 sw=2 tw=0 et :*/
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
T const * product() const
Definition: ESHandle.h:86
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool L1TCaloLayer1FetchLUTs(const L1TCaloLayer1FetchLUTsTokens &iTokens, const edm::EventSetup &iSetup, std::vector< std::array< std::array< std::array< uint32_t, nEtBins >, nCalSideBins >, nCalEtaBins > > &eLUT, std::vector< std::array< std::array< std::array< uint32_t, nEtBins >, nCalSideBins >, nCalEtaBins > > &hLUT, std::vector< std::array< std::array< uint32_t, nEtBins >, nHfEtaBins > > &hfLUT, std::vector< unsigned int > &ePhiMap, std::vector< unsigned int > &hPhiMap, std::vector< unsigned int > &hfPhiMap, bool useLSB, bool useCalib, bool useECALLUT, bool useHCALLUT, bool useHFLUT, int fwVersion)
Definition: value.py:1
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:130
bool isValid() const
Definition: ESHandle.h:44