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