CMS 3D CMS Logo

L1TCaloLayer1.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: L1Trigger/L1TCaloLayer1
4 // Class: L1TCaloLayer1
5 //
13 //
14 // Original Author: Sridhara Rao Dasu
15 // Created: Thu, 08 Oct 2015 09:20:16 GMT
16 //
17 //
18 
19 // system include files
20 #include <memory>
21 
22 // user include files
25 
28 
30 
33 
34 #include "L1Trigger/L1TCaloLayer1/src/UCTLayer1.hh"
35 #include "L1Trigger/L1TCaloLayer1/src/UCTCrate.hh"
36 #include "L1Trigger/L1TCaloLayer1/src/UCTCard.hh"
37 #include "L1Trigger/L1TCaloLayer1/src/UCTRegion.hh"
38 #include "L1Trigger/L1TCaloLayer1/src/UCTTower.hh"
39 
40 #include "L1Trigger/L1TCaloLayer1/src/UCTGeometry.hh"
41 #include "L1Trigger/L1TCaloLayer1/src/UCTLogging.hh"
42 
46 
48 
49 #include "L1Trigger/L1TCaloLayer1/src/L1TCaloLayer1FetchLUTs.hh"
50 
51 using namespace l1t;
52 using namespace l1tcalo;
53 
54 //
55 // class declaration
56 //
57 
59 public:
60  explicit L1TCaloLayer1(const edm::ParameterSet&);
61 
62  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
63 
64 private:
65  void produce(edm::Event&, const edm::EventSetup&) override;
66 
67  void beginRun(edm::Run const&, edm::EventSetup const&) override;
68 
69  // ----------member data ---------------------------
70 
75  const L1TCaloLayer1FetchLUTsTokens lutsTokens;
76 
77  std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins>> ecalLUT;
78  std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins>> hcalLUT;
79  std::vector<std::array<std::array<uint32_t, nEtBins>, nHfEtaBins>> hfLUT;
80  std::vector<unsigned long long int> hcalFBLUT;
81 
82  std::vector<unsigned int> ePhiMap;
83  std::vector<unsigned int> hPhiMap;
84  std::vector<unsigned int> hfPhiMap;
85 
86  std::vector<std::shared_ptr<UCTTower>> twrList;
87 
88  bool useLSB;
89  bool useCalib;
90  bool useECALLUT;
91  bool useHCALLUT;
92  bool useHFLUT;
94  bool verbose;
97  int fwVersion;
98 
99  std::unique_ptr<UCTLayer1> layer1;
100 };
101 
102 //
103 // constants, enums and typedefs
104 //
105 
106 //
107 // static data member definitions
108 //
109 
110 //
111 // constructors and destructor
112 //
114  : ecalTPSource(consumes<EcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("ecalToken"))),
115  hcalTPSource(consumes<HcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("hcalToken"))),
116  towerPutToken{produces<CaloTowerBxCollection>()},
117  regionPutToken{produces<L1CaloRegionCollection>()},
118  lutsTokens{esConsumes<edm::Transition::BeginRun>(),
119  esConsumes<edm::Transition::BeginRun>(),
120  esConsumes<edm::Transition::BeginRun>()},
121  ePhiMap(72 * 2, 0),
122  hPhiMap(72 * 2, 0),
123  hfPhiMap(72 * 2, 0),
124  useLSB(iConfig.getParameter<bool>("useLSB")),
125  useCalib(iConfig.getParameter<bool>("useCalib")),
126  useECALLUT(iConfig.getParameter<bool>("useECALLUT")),
127  useHCALLUT(iConfig.getParameter<bool>("useHCALLUT")),
128  useHFLUT(iConfig.getParameter<bool>("useHFLUT")),
129  useHCALFBLUT(iConfig.getParameter<bool>("useHCALFBLUT")),
130  verbose(iConfig.getUntrackedParameter<bool>("verbose")),
131  unpackHcalMask(iConfig.getParameter<bool>("unpackHcalMask")),
132  unpackEcalMask(iConfig.getParameter<bool>("unpackEcalMask")),
133  fwVersion(iConfig.getParameter<int>("firmwareVersion")) {
134  // See UCTLayer1.hh for firmware version definitions
135  layer1 = std::make_unique<UCTLayer1>(fwVersion);
136 
137  vector<UCTCrate*> crates = layer1->getCrates();
138  for (uint32_t crt = 0; crt < crates.size(); crt++) {
139  vector<UCTCard*> cards = crates[crt]->getCards();
140  for (uint32_t crd = 0; crd < cards.size(); crd++) {
141  vector<UCTRegion*> regions = cards[crd]->getRegions();
142  for (uint32_t rgn = 0; rgn < regions.size(); rgn++) {
143  vector<std::shared_ptr<UCTTower>> towers = regions[rgn]->getTowers();
144  for (uint32_t twr = 0; twr < towers.size(); twr++) {
145  twrList.push_back(towers[twr]);
146  }
147  }
148  }
149  }
150 
151  // This sort corresponds to the sort condition on
152  // the output CaloTowerBxCollection
153  std::sort(twrList.begin(), twrList.end(), [](std::shared_ptr<UCTTower> a, std::shared_ptr<UCTTower> b) {
154  return CaloTools::caloTowerHash(a->caloEta(), a->caloPhi()) < CaloTools::caloTowerHash(b->caloEta(), b->caloPhi());
155  });
156 }
157 
158 //
159 // member functions
160 //
161 
162 // ------------ method called to produce the data ------------
164  using namespace edm;
165 
167  iEvent.getByToken(ecalTPSource, ecalTPs);
169  iEvent.getByToken(hcalTPSource, hcalTPs);
170 
171  CaloTowerBxCollection towersColl;
172  L1CaloRegionCollection rgnCollection;
173 
174  if (!layer1->clearEvent()) {
175  LOG_ERROR << "UCT: Failed to clear event" << std::endl;
176  return;
177  }
178 
179  for (const auto& ecalTp : *ecalTPs) {
180  if (unpackEcalMask && ((ecalTp.sample(0).raw() >> 13) & 0x1))
181  continue;
182  int caloEta = ecalTp.id().ieta();
183  int caloPhi = ecalTp.id().iphi();
184  int et = ecalTp.compressedEt();
185  bool fgVeto = ecalTp.fineGrain();
186  UCTTowerIndex t = UCTTowerIndex(caloEta, caloPhi);
187  if (!layer1->setECALData(t, fgVeto, et)) {
188  LOG_ERROR << "UCT: Failed loading an ECAL tower" << std::endl;
189  return;
190  }
191  }
192 
193  if (hcalTPs.isValid()) {
194  for (const auto& hcalTp : *hcalTPs) {
195  if (unpackHcalMask && ((hcalTp.sample(0).raw() >> 13) & 0x1))
196  continue;
197  int caloEta = hcalTp.id().ieta();
198  uint32_t absCaloEta = std::abs(caloEta);
199  // Tower 29 is not used by Layer-1
200  if (absCaloEta == 29) {
201  continue;
202  }
203  // Prevent usage of HF TPs with Layer-1 emulator if HCAL TPs are old style
204  else if (hcalTp.id().version() == 0 && absCaloEta > 29) {
205  continue;
206  } else if (absCaloEta <= 41) {
207  int caloPhi = hcalTp.id().iphi();
208  int et = hcalTp.SOI_compressedEt();
209  bool fg = hcalTp.t0().fineGrain(0); // depth
210  bool fg2 = hcalTp.t0().fineGrain(1); // prompt
211  bool fg3 = hcalTp.t0().fineGrain(2); // delay 1
212  bool fg4 = hcalTp.t0().fineGrain(3); // delay 2
213  // note that hcalTp.t0().fineGrain(4) and hcalTp.t0().fineGrain(5) are the reserved MIP bits (not used for LLP logic)
214  if (caloPhi <= 72) {
215  UCTTowerIndex t = UCTTowerIndex(caloEta, caloPhi);
216  uint32_t featureBits = 0;
217  if (absCaloEta > 29) {
218  if (fg)
219  featureBits |= 0b01;
220  // fg2 should only be set for HF
221  if (fg2)
222  featureBits |= 0b10;
223  } else if (absCaloEta < 16)
224  featureBits |= (fg | ((!fg2) & (fg3 | fg4))); // depth | (!prompt & (delay1 | delay2))
225  if (!layer1->setHCALData(t, featureBits, et)) {
226  LOG_ERROR << "caloEta = " << caloEta << "; caloPhi =" << caloPhi << std::endl;
227  LOG_ERROR << "UCT: Failed loading an HCAL tower" << std::endl;
228  return;
229  }
230  } else {
231  LOG_ERROR << "Illegal Tower: caloEta = " << caloEta << "; caloPhi =" << caloPhi << "; et = " << et
232  << std::endl;
233  }
234  } else {
235  LOG_ERROR << "Illegal Tower: caloEta = " << caloEta << std::endl;
236  }
237  }
238  }
239 
240  //Process
241  if (!layer1->process()) {
242  LOG_ERROR << "UCT: Failed to process layer 1" << std::endl;
243  }
244 
245  int theBX = 0; // Currently we only read and process the "hit" BX only
246 
247  for (uint32_t twr = 0; twr < twrList.size(); twr++) {
248  CaloTower caloTower;
249  caloTower.setHwPt(twrList[twr]->et()); // Bits 0-8 of the 16-bit word per the interface protocol document
250  caloTower.setHwEtRatio(twrList[twr]->er()); // Bits 9-11 of the 16-bit word per the interface protocol document
251  caloTower.setHwQual(twrList[twr]->miscBits()); // Bits 12-15 of the 16-bit word per the interface protocol document
252  caloTower.setHwEta(twrList[twr]->caloEta()); // caloEta = 1-28 and 30-41
253  caloTower.setHwPhi(twrList[twr]->caloPhi()); // caloPhi = 1-72
254  caloTower.setHwEtEm(twrList[twr]->getEcalET()); // This is provided as a courtesy - not available to hardware
255  caloTower.setHwEtHad(twrList[twr]->getHcalET()); // This is provided as a courtesy - not available to hardware
256  towersColl.push_back(theBX, caloTower);
257  }
258 
259  iEvent.emplace(towerPutToken, std::move(towersColl));
260 
261  UCTGeometry g;
262  vector<UCTCrate*> crates = layer1->getCrates();
263  for (uint32_t crt = 0; crt < crates.size(); crt++) {
264  vector<UCTCard*> cards = crates[crt]->getCards();
265  for (uint32_t crd = 0; crd < cards.size(); crd++) {
266  vector<UCTRegion*> regions = cards[crd]->getRegions();
267  for (uint32_t rgn = 0; rgn < regions.size(); rgn++) {
268  uint32_t rawData = regions[rgn]->rawData();
269  uint32_t regionData = rawData & 0x0000FFFF;
270  uint32_t crate = regions[rgn]->getCrate();
271  uint32_t card = regions[rgn]->getCard();
272  uint32_t region = regions[rgn]->getRegion();
273  bool negativeEta = regions[rgn]->isNegativeEta();
274  uint32_t rPhi = g.getUCTRegionPhiIndex(crate, card);
275  if (region < NRegionsInCard) { // We only store the Barrel and Endcap - HF has changed in the upgrade
276  uint32_t rEta =
277  10 -
278  region; // UCT region is 0-6 for B/E but GCT eta goes 0-21, 0-3 -HF, 4-10 -B/E, 11-17 +B/E, 18-21 +HF
279  if (!negativeEta)
280  rEta = 11 + region; // Positive eta portion is offset by 11
281  rgnCollection.push_back(L1CaloRegion((uint16_t)regionData, (unsigned)rEta, (unsigned)rPhi, (int16_t)0));
282  }
283  }
284  }
285  }
286  iEvent.emplace(regionPutToken, std::move(rgnCollection));
287 }
288 
289 // ------------ method called when starting to processes a run ------------
290 void L1TCaloLayer1::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
292  iSetup,
293  ecalLUT,
294  hcalLUT,
295  hfLUT,
296  hcalFBLUT,
297  ePhiMap,
298  hPhiMap,
299  hfPhiMap,
300  useLSB,
301  useCalib,
302  useECALLUT,
303  useHCALLUT,
304  useHFLUT,
305  useHCALFBLUT,
306  fwVersion)) {
307  LOG_ERROR << "L1TCaloLayer1::beginRun: failed to fetch LUTS - using unity" << std::endl;
308  // Andrew's note: Sets these to empty arrays initially, then fills all elements with 32 bits of 1's
309  // to represent a bit-wise unity, and get around initialization complaints on the (now) created null array.
310  // I'm not crazy about how this is structured, but c++ appears to not offer a lot of utilities
311  // for filling std::array's (especially nested ones) without listing out every value by hand, or creating them nulled.
312  std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> eCalLayer1EtaSideEtArray = {};
313  std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> hCalLayer1EtaSideEtArray = {};
314  std::array<std::array<uint32_t, nEtBins>, nHfEtaBins> hfLayer1EtaEtArray = {};
315  for (uint32_t i = 0; i < nCalEtaBins; i++) {
316  for (uint32_t j = 0; j < nCalSideBins; j++) {
317  for (uint32_t k = 0; k < nEtBins; k++) {
318  eCalLayer1EtaSideEtArray[i][j][k] = 0xFFFFFFFF;
319  hCalLayer1EtaSideEtArray[i][j][k] = 0xFFFFFFFF;
320  }
321  }
322  }
323  for (uint32_t i = 0; i < nHfEtaBins; i++) {
324  for (uint32_t j = 0; j < nEtBins; j++) {
325  hfLayer1EtaEtArray[i][j] = 0xFFFFFFFF;
326  }
327  }
328  ecalLUT.push_back(eCalLayer1EtaSideEtArray);
329  hcalLUT.push_back(hCalLayer1EtaSideEtArray);
330  hfLUT.push_back(hfLayer1EtaEtArray);
331  }
332  for (uint32_t twr = 0; twr < twrList.size(); twr++) {
333  // Map goes minus 1 .. 72 plus 1 .. 72 -> 0 .. 143
334  int iphi = twrList[twr]->caloPhi();
335  int ieta = twrList[twr]->caloEta();
336  if (ieta < 0) {
337  iphi -= 1;
338  } else {
339  iphi += 71;
340  }
341  twrList[twr]->setECALLUT(&ecalLUT[ePhiMap[iphi]]);
342  twrList[twr]->setHCALLUT(&hcalLUT[hPhiMap[iphi]]);
343  twrList[twr]->setHFLUT(&hfLUT[hfPhiMap[iphi]]);
344  }
345 }
346 
347 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
349  //Description set to reflect default present in simCaloStage2Layer1Digis_cfi.py
350  //Currently redundant, but could be adjusted to provide defaults in case additional LUT
351  //checks are added and before other configurations adjust to match.
353  desc.add<edm::InputTag>("ecalToken", edm::InputTag("simEcalTriggerPrimitiveDigis"));
354  desc.add<edm::InputTag>("hcalToken", edm::InputTag("simHcalTriggerPrimitiveDigis"));
355  desc.add<bool>("useLSB", true);
356  desc.add<bool>("useCalib", true);
357  desc.add<bool>("useECALLUT", true);
358  desc.add<bool>("useHCALLUT", true);
359  desc.add<bool>("useHFLUT", true);
360  desc.add<bool>("useHCALFBLUT", false);
361  desc.addUntracked<bool>("verbose", false);
362  desc.add<bool>("unpackEcalMask", false);
363  desc.add<bool>("unpackHcalMask", false);
364  desc.add<int>("firmwareVersion", 1);
365  descriptions.addDefault(desc);
366 }
367 
368 //define this as a plug-in
370 /* vim: set ts=8 sw=2 tw=0 et :*/
std::vector< std::shared_ptr< UCTTower > > twrList
std::vector< std::array< std::array< uint32_t, nEtBins >, nHfEtaBins > > hfLUT
std::vector< unsigned int > hfPhiMap
bool verbose
edm::EDGetTokenT< HcalTrigPrimDigiCollection > hcalTPSource
void setHwQual(int qual)
Definition: L1Candidate.h:31
delete x;
Definition: CaloConfig.h:22
std::vector< std::array< std::array< std::array< uint32_t, nEtBins >, nCalSideBins >, nCalEtaBins > > ecalLUT
std::vector< unsigned long long int > hcalFBLUT
void setHwEtHad(int et)
Definition: CaloTower.cc:29
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
std::unique_ptr< UCTLayer1 > layer1
edm::EDPutTokenT< L1CaloRegionCollection > regionPutToken
void produce(edm::Event &, const edm::EventSetup &) override
int iEvent
Definition: GenABIO.cc:224
void addDefault(ParameterSetDescription const &psetDescription)
std::vector< std::array< std::array< std::array< uint32_t, nEtBins >, nCalSideBins >, nCalEtaBins > > hcalLUT
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void setHwEtRatio(int ratio)
Definition: CaloTower.cc:31
edm::EDGetTokenT< EcalTrigPrimDigiCollection > ecalTPSource
void setHwPhi(int phi)
Definition: L1Candidate.h:30
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const L1TCaloLayer1FetchLUTsTokens lutsTokens
double b
Definition: hdecay.h:120
edm::EDPutTokenT< CaloTowerBxCollection > towerPutToken
std::vector< unsigned int > hPhiMap
bool isValid() const
Definition: HandleBase.h:70
L1TCaloLayer1(const edm::ParameterSet &)
HLT enums.
void setHwPt(int pt)
Definition: L1Candidate.h:28
double a
Definition: hdecay.h:121
void beginRun(edm::Run const &, edm::EventSetup const &) override
A calorimeter trigger region (sum of 4x4 trigger towers)
Definition: L1CaloRegion.h:21
void setHwEta(int eta)
Definition: L1Candidate.h:29
std::vector< L1CaloRegion > L1CaloRegionCollection
void setHwEtEm(int et)
Definition: CaloTower.cc:27
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 long long int > &hcalFBLUT, 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, bool useHCALFBLUT, int fwVersion)
std::vector< unsigned int > ePhiMap
def move(src, dest)
Definition: eostools.py:511
#define LOG_ERROR
Definition: CSCDQM_Logger.h:40
Definition: Run.h:45
void push_back(int bx, T object)