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  std::vector< std::array< std::array< std::array<uint32_t, nEtBins>, nCalSideBins >, nCalEtaBins> > &eLUT,
31  std::vector< std::array< std::array< std::array<uint32_t, nEtBins>, nCalSideBins >, nCalEtaBins> > &hLUT,
32  std::vector< std::array< std::array<uint32_t, nEtBins>, nHfEtaBins > > &hfLUT,
33  std::vector<unsigned int> &ePhiMap,
34  std::vector<unsigned int> &hPhiMap,
35  std::vector<unsigned int> &hfPhiMap,
36  bool useLSB,
37  bool useCalib,
38  bool useECALLUT,
39  bool useHCALLUT,
40  bool useHFLUT) {
41 
42  int hfValid = 1;
44  iSetup.get<CaloGeometryRecord>().get(pG);
45  if (! pG->use1x1()){
46  edm::LogError("L1TCaloLayer1FetchLUTs") << "Using Stage2-Layer1 but HCAL Geometry has use1x1 = 0! HF will be suppressed. Check Global Tag, etc.";
47  hfValid = 0;
48  }
49 
50  // CaloParams contains all persisted parameters for Layer 1
51  edm::ESHandle<l1t::CaloParams> paramsHandle;
52  iSetup.get<L1TCaloStage2ParamsRcd>().get(paramsHandle);
53  if ( paramsHandle.product() == nullptr ) {
54  edm::LogError("L1TCaloLayer1FetchLUTs") << "Missing CaloParams object! Check Global Tag, etc.";
55  return false;
56  }
57  l1t::CaloParamsHelper caloParams(*paramsHandle.product());
58 
59  // Calo Trigger Layer1 output LSB Real ET value
60  double caloLSB = caloParams.towerLsbSum();
61  if ( caloLSB != 0.5 ) {
62  // Lots of things expect this, better give fair warning if not
63  edm::LogError("L1TCaloLayer1FetchLUTs") << "caloLSB (caloParams.towerLsbSum()) != 0.5, actually = " << caloLSB;
64  }
65 
66  // ECal/HCal scale factors will be a x*y*28 array:
67  // ieta = 28 eta scale factors (1 .. 28)
68  // etBin = size of Real ET Bins vector
69  // phiBin = max(Real Phi Bins vector)
70  // So, index = phiBin*etBin*28+etBin*28+ieta
71  auto ecalScaleETBins = caloParams.layer1ECalScaleETBins();
72  auto ecalScalePhiBins = caloParams.layer1ECalScalePhiBins();
73  if ( ecalScalePhiBins.empty() ) {
74  // Backwards-compatibility (no phi binning)
75  ecalScalePhiBins.resize(36, 0);
76  }
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() != caloParams.layer1ECalScaleETBins().size()*numEcalPhiBins*28 !!";
85  return false;
86  }
87  auto hcalScaleETBins = caloParams.layer1HCalScaleETBins();
88  auto hcalScalePhiBins = caloParams.layer1HCalScalePhiBins();
89  if ( hcalScalePhiBins.empty() ) {
90  hcalScalePhiBins.resize(36, 0);
91  }
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() != caloParams.layer1HCalScaleETBins().size()*numHcalPhiBins*28 !!";
100  return false;
101  }
102 
103  // HF 1x1 scale factors will be a x*y*12 array:
104  // ieta = 12 eta scale factors (30 .. 41)
105  // etBin = size of Real ET Bins vector
106  // phiBin = max(Real Phi Bins vector)
107  // So, index = phiBin*etBin*12+etBin*12+ieta
108  auto hfScaleETBins = caloParams.layer1HFScaleETBins();
109  auto hfScalePhiBins = caloParams.layer1HFScalePhiBins();
110  if ( hfScalePhiBins.empty() ) {
111  hfScalePhiBins.resize(36, 0);
112  }
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") << "caloParams.layer1HFScaleFactors().size() != caloParams.layer1HFScaleETBins().size()*numHFPhiBins*12 !!";
121  return false;
122  }
123 
124  // Sanity check scale factors exist
125  if ( useCalib && (ecalSF.size()==0 || hcalSF.size()==0 || hfSF.size()==0) ) {
126  edm::LogError("L1TCaloLayer1FetchLUTs") << "Layer 1 calibrations requested (useCalib = True) but there are missing scale factors in CaloParams! Please check conditions setup.";
127  return false;
128  }
129  // get energy scale to convert input from ECAL - this should be linear with LSB = 0.5 GeV
130  const double ecalLSB = 0.5;
131 
132  // get energy scale to convert input from HCAL
134  iSetup.get<CaloTPGRecord>().get(decoder);
135  if ( decoder.product() == nullptr ) {
136  edm::LogError("L1TCaloLayer1FetchLUTs") << "Missing CaloTPGTranscoder object! Check Global Tag, etc.";
137  return false;
138  }
139 
140  // TP compression scale is always phi symmetric
141  // We default to 3 since HF has no ieta=41 iphi=1,2
142  auto decodeHcalEt = [&decoder](int iEta, uint32_t compressedEt, uint32_t iPhi=3) -> double {
143  HcalTriggerPrimitiveSample sample(compressedEt);
144  HcalTrigTowerDetId id(iEta, iPhi);
145  if ( std::abs(iEta) >= 30 ) {
146  id.setVersion(1);
147  }
148  return decoder->hcaletValue(id, sample);
149  };
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]) break;
166  }
167  if ( etBin >= ecalScaleETBins.size() ) etBin = ecalScaleETBins.size()-1;
168 
169  double calibratedECalInput = linearizedECalInput;
170  if (useCalib) calibratedECalInput *= ecalSF.at(phiBin*ecalScaleETBins.size()*28 + etBin*28 + etaBin);
171  if (useLSB) calibratedECalInput /= caloLSB;
172 
173  value = calibratedECalInput;
174  if(value > 0xFF) {
175  value = 0xFF;
176  }
177  }
178  if(value == 0) {
179  value = (1 << 11);
180  }
181  else {
182  uint32_t et_log2 = ((uint32_t) log2(value)) & 0x7;
183  value |= (et_log2 << 12);
184  }
185  value |= (fb << 10);
186  eLUT[phiBin][etaBin][fb][ecalInput] = value;
187  }
188  }
189  }
190  }
191 
192  // Make HCal LUT
193  for(uint32_t phiBin=0; phiBin<numHcalPhiBins; phiBin++) {
194  std::array< std::array< std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> phiLUT;
195  hLUT.push_back(phiLUT);
196  for(uint32_t etaBin = 0; etaBin < nCalEtaBins; etaBin++) {
197  int caloEta = etaBin+1;
198  int iPhi = 3;
199  auto pos = std::find(hcalScalePhiBins.begin(), hcalScalePhiBins.end(), phiBin);
200  if (pos!=hcalScalePhiBins.end()) {
201  // grab an iPhi bin
202  auto index = std::distance(hcalScalePhiBins.begin(),pos);
203  if (index<18) {
204  caloEta*=-1;
205  iPhi = index*4+1;
206  }
207  else {
208  iPhi = (index-18)*4+1;
209  }
210  }
211  for(uint32_t fb = 0; fb < nCalSideBins; fb++) {
212  for(uint32_t hcalInput = 0; hcalInput <= 0xFF; hcalInput++) {
213  uint32_t value = hcalInput;
214  if(useHCALLUT) {
215  // hcaletValue defined in L137 of CalibCalorimetry/CaloTPG/src/CaloTPGTranscoderULUT.cc
216  double linearizedHcalInput = decodeHcalEt(caloEta, hcalInput, iPhi); // in GeV
217 
218  uint32_t etBin = 0;
219  for(; etBin < hcalScaleETBins.size(); etBin++) {
220  if(linearizedHcalInput < hcalScaleETBins[etBin]) break;
221  }
222  if ( etBin >= hcalScaleETBins.size() ) etBin = hcalScaleETBins.size()-1;
223 
224  double calibratedHcalInput = linearizedHcalInput;
225  if(useCalib) calibratedHcalInput *= hcalSF.at(phiBin*hcalScaleETBins.size()*28 + etBin*28 + etaBin);
226  if(useLSB) calibratedHcalInput /= caloLSB;
227 
228  value = calibratedHcalInput;
229  if(value > 0xFF) {
230  value = 0xFF;
231  }
232  }
233  if(value == 0) {
234  value = (1 << 11);
235  }
236  else {
237  uint32_t et_log2 = ((uint32_t) log2(value)) & 0x7;
238  value |= (et_log2 << 12);
239  }
240  value |= (fb << 10);
241  hLUT[phiBin][etaBin][fb][hcalInput] = value;
242  }
243  }
244  }
245  }
246 
247  // Make HF LUT
248  for(uint32_t phiBin=0; phiBin<numHFPhiBins; phiBin++) {
249  std::array< std::array<uint32_t, nEtBins>, nHfEtaBins> phiLUT;
250  hfLUT.push_back(phiLUT);
251  for(uint32_t etaBin = 0; etaBin < nHfEtaBins; etaBin++) {
252  int caloEta = etaBin+30;
253  int iPhi = 3;
254  auto pos = std::find(hfScalePhiBins.begin(), hfScalePhiBins.end(), phiBin);
255  if (pos!=hfScalePhiBins.end()) {
256  auto index = std::distance(hfScalePhiBins.begin(),pos);
257  if (index<18) {
258  caloEta*=-1;
259  iPhi = index*4-1;
260  }
261  else {
262  iPhi = (index-18)*4-1;
263  }
264  if (iPhi < 0) iPhi = 71;
265  }
266  for(uint32_t etCode = 0; etCode < nEtBins; etCode++) {
267  uint32_t value = etCode;
268  if(useHFLUT) {
269 
270  double linearizedHFInput = 0;
271  if (hfValid){
272  linearizedHFInput = decodeHcalEt(caloEta, value, iPhi); // in GeV
273  }
274 
275  uint32_t etBin = 0;
276  for(; etBin < hfScaleETBins.size(); etBin++) {
277  if(linearizedHFInput < hfScaleETBins[etBin]) break;
278  }
279  if ( etBin >= hfScaleETBins.size() ) etBin = hfScaleETBins.size()-1;
280 
281  double calibratedHFInput = linearizedHFInput;
282  if(useCalib) calibratedHFInput *= hfSF.at(phiBin*hfScalePhiBins.size()*12+etBin*12+etaBin);
283  if(useLSB) calibratedHFInput /= caloLSB;
284 
285  value = calibratedHFInput;
286  if(value > 0xFF) {
287  value = 0xFF;
288  }
289  }
290  hfLUT[phiBin][etaBin][etCode] = value;
291  }
292  }
293  }
294 
295  // plus/minus, 18 CTP7, 4 iPhi each
296  for(uint32_t isPos=0; isPos<2; isPos++) {
297  for(uint32_t iPhi=1; iPhi<=72; iPhi++) {
298  uint32_t card = floor((iPhi+1)/4);
299  if (card>17) card-=18;
300  ePhiMap[isPos*72+iPhi-1] = ecalScalePhiBins[isPos*18+card];
301  hPhiMap[isPos*72+iPhi-1] = hcalScalePhiBins[isPos*18+card];
302  hfPhiMap[isPos*72+iPhi-1] = hfScalePhiBins[isPos*18+card];
303  }
304  }
305 
306  return true;
307 }
308 /* vim: set ts=8 sw=2 tw=0 et :*/
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)
#define nullptr
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Definition: value.py:1
const T & get() const
Definition: EventSetup.h:55
double towerLsbSum() const
virtual double hcaletValue(const int &ieta, const int &iphi, const int &version, const int &compressedValue) const =0
T const * product() const
Definition: ESHandle.h:86