CMS 3D CMS Logo

Phase2L1CaloEGammaEmulator.cc
Go to the documentation of this file.
1 /*
2  * Description: Phase 2 RCT and GCT emulator
3  */
4 
5 // system include files
6 #include <ap_int.h>
7 #include <array>
8 #include <cmath>
9 // #include <cstdint>
10 #include <cstdlib> // for rand
11 #include <iostream>
12 #include <fstream>
13 #include <memory>
14 
15 // user include files
23 
32 
33 // ECAL TPs
35 
36 // HCAL TPs
38 
39 // Output tower collection
45 
48 
51 
53 
57 
58 // Declare the Phase2L1CaloEGammaEmulator class and its methods
59 
61 public:
63  ~Phase2L1CaloEGammaEmulator() override = default;
64 
66 
67 private:
68  void produce(edm::Event&, const edm::EventSetup&) override;
69 
73 
75 
81 };
82 
84 
85 // Phase2L1CaloEGammaEmulator initializer, destructor, and produce methods
86 
88  : ecalTPEBToken_(consumes<EcalEBTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("ecalTPEB"))),
89  hcalTPToken_(
90  consumes<edm::SortedCollection<HcalTriggerPrimitiveDigi>>(iConfig.getParameter<edm::InputTag>("hcalTP"))),
91  decoderTag_(esConsumes<CaloTPGTranscoder, CaloTPGRecord>(edm::ESInputTag("", ""))),
92  calib_(iConfig.getParameter<edm::ParameterSet>("calib")),
93  caloGeometryTag_(esConsumes<CaloGeometry, CaloGeometryRecord>(edm::ESInputTag("", ""))),
94  hbTopologyTag_(esConsumes<HcalTopology, HcalRecNumberingRecord>(edm::ESInputTag("", ""))) {
95  produces<l1tp2::CaloCrystalClusterCollection>("RCTClusters");
96  produces<l1tp2::CaloCrystalClusterCollection>("GCTClusters");
97  produces<l1tp2::CaloTowerCollection>("RCTTowers");
98  produces<l1tp2::CaloTowerCollection>("GCTTowers");
99  produces<l1tp2::CaloTowerCollection>("GCTFullTowers");
100  produces<BXVector<l1t::EGamma>>("GCTEGammas");
101  produces<l1tp2::DigitizedClusterCorrelatorCollection>("GCTDigitizedClusterToCorrelator");
102  produces<l1tp2::DigitizedTowerCorrelatorCollection>("GCTDigitizedTowerToCorrelator");
103  produces<l1tp2::DigitizedClusterGTCollection>("GCTDigitizedClusterToGT");
104 }
105 
107  using namespace edm;
108 
109  // Detector geometry
110  const auto& caloGeometry = iSetup.getData(caloGeometryTag_);
111  ebGeometry = caloGeometry.getSubdetectorGeometry(DetId::Ecal, EcalBarrel);
112  hbGeometry = caloGeometry.getSubdetectorGeometry(DetId::Hcal, HcalBarrel);
113  const auto& hbTopology = iSetup.getData(hbTopologyTag_);
114  hcTopology_ = &hbTopology;
115  HcalTrigTowerGeometry theTrigTowerGeometry(hcTopology_);
116 
117  const auto& decoder = iSetup.getData(decoderTag_);
118 
119  //***************************************************//
120  // Declare RCT output collections
121  //***************************************************//
122 
123  auto L1EGXtalClusters = std::make_unique<l1tp2::CaloCrystalClusterCollection>();
124  auto L1CaloTowers = std::make_unique<l1tp2::CaloTowerCollection>();
125 
126  //***************************************************//
127  // Get the ECAL hits
128  //***************************************************//
130  iEvent.getByToken(ecalTPEBToken_, pcalohits);
131 
132  std::vector<p2eg::SimpleCaloHit> ecalhits;
133 
134  for (const auto& hit : *pcalohits.product()) {
135  if (hit.encodedEt() > 0) // hit.encodedEt() returns an int corresponding to 2x the crystal Et
136  {
137  // Et is 10 bit, by keeping the ADC saturation Et at 120 GeV it means that you have to multiply by 0.125 (input LSB)
138  float et = hit.encodedEt() * 0.125;
139  if (et < p2eg::cut_500_MeV) {
140  continue; // Reject hits with < 500 MeV ET
141  }
142 
143  // Get cell coordinates and info
144  auto cell = ebGeometry->getGeometry(hit.id());
145 
146  p2eg::SimpleCaloHit ehit;
147  ehit.setId(hit.id());
148  ehit.setPosition(GlobalVector(cell->getPosition().x(), cell->getPosition().y(), cell->getPosition().z()));
149  ehit.setEnergy(et);
150  ehit.setEt_uint(
151  (ap_uint<10>)hit.encodedEt() >>
152  2); // also save the uint Et, this is to convert between 0.125 (in MC production) and 0.5 (in firmware based code)
153  ehit.setPt();
154  ecalhits.push_back(ehit);
155  }
156  }
157 
158  //***************************************************//
159  // Get the HCAL hits
160  //***************************************************//
161  std::vector<p2eg::SimpleCaloHit> hcalhits;
163  iEvent.getByToken(hcalTPToken_, hbhecoll);
164 
165  for (const auto& hit : *hbhecoll.product()) {
166  float et = decoder.hcaletValue(hit.id(), hit.t0());
167  ap_uint<10> encodedEt = hit.t0().compressedEt();
168  // same thing as SOI_compressedEt() in HcalTriggerPrimitiveDigi.h///
169  if (et <= 0)
170  continue;
171 
172  if (!(hcTopology_->validHT(hit.id()))) {
173  LogError("Phase2L1CaloEGammaEmulator")
174  << " -- Hcal hit DetID not present in HCAL Geom: " << hit.id() << std::endl;
175  throw cms::Exception("Phase2L1CaloEGammaEmulator");
176  continue;
177  }
178  const std::vector<HcalDetId>& hcId = theTrigTowerGeometry.detIds(hit.id());
179  if (hcId.empty()) {
180  LogError("Phase2L1CaloEGammaEmulator") << "Cannot find any HCalDetId corresponding to " << hit.id() << std::endl;
181  throw cms::Exception("Phase2L1CaloEGammaEmulator");
182  continue;
183  }
184  if (hcId[0].subdetId() > 1) {
185  continue;
186  }
187  GlobalVector hcal_tp_position = GlobalVector(0., 0., 0.);
188  for (const auto& hcId_i : hcId) {
189  if (hcId_i.subdetId() > 1) {
190  continue;
191  }
192  // get the first HCAL TP/ cell
193  auto cell = hbGeometry->getGeometry(hcId_i);
194  if (cell == nullptr) {
195  continue;
196  }
197  GlobalVector tmpVector = GlobalVector(cell->getPosition().x(), cell->getPosition().y(), cell->getPosition().z());
198  hcal_tp_position = tmpVector;
199 
200  break;
201  }
202  p2eg::SimpleCaloHit hhit;
203  hhit.setId(hit.id());
204  hhit.setIdHcal(hit.id());
205  hhit.setPosition(hcal_tp_position);
206  hhit.setEnergy(et);
207  hhit.setPt();
208  hhit.setEt_uint(encodedEt);
209  hcalhits.push_back(hhit);
210  }
211 
212  //***************************************************//
213  // Initialize necessary arrays for tower and clusters
214  //***************************************************//
215 
216  // L1 Outputs definition: Arrays that use firmware convention for indexing
217  p2eg::tower_t towerHCALCard
219  [p2eg::n_towers_halfPhi]; // 17x4x36 array (not to be confused with the 12x1 array of ap_uints, towerEtHCAL
221  // There is one vector of clusters per card (up to 12 clusters before stitching across ECAL regions)
222  std::vector<p2eg::Cluster> cluster_list[p2eg::n_towers_halfPhi];
223  // After merging/stitching the clusters, we only take the 8 highest pt per card
224  std::vector<p2eg::Cluster> cluster_list_merged[p2eg::n_towers_halfPhi];
225 
226  //***************************************************//
227  // Fill RCT ECAL regions with ECAL hits
228  //***************************************************//
229  for (int cc = 0; cc < p2eg::n_towers_halfPhi; ++cc) { // Loop over 36 L1 cards
230 
231  p2eg::card rctCard;
232  rctCard.setIdx(cc);
233 
234  for (const auto& hit : ecalhits) {
235  // Check if the hit is in cards 0-35
236  if (hit.isInCard(cc)) {
237  // Get the crystal eta and phi, relative to the bottom left corner of the card
238  // (0 up to 17*5, 0 up to 4*5)
239  int local_iEta = hit.crystalLocaliEta(cc);
240  int local_iPhi = hit.crystalLocaliPhi(cc);
241 
242  // Region number (0-5) depends only on the crystal iEta in the card
243  int regionNumber = p2eg::getRegionNumber(local_iEta);
244 
245  // Tower eta and phi index inside the card (17x4)
246  int inCard_tower_iEta = local_iEta / p2eg::CRYSTALS_IN_TOWER_ETA;
247  int inCard_tower_iPhi = local_iPhi / p2eg::CRYSTALS_IN_TOWER_PHI;
248 
249  // Tower eta and phi index inside the region (3x4)
250  int inRegion_tower_iEta = inCard_tower_iEta % p2eg::TOWER_IN_ETA;
251  int inRegion_tower_iPhi = inCard_tower_iPhi % p2eg::TOWER_IN_PHI;
252 
253  // Crystal eta and phi index inside the 3x4 region (15x20)
254  int inRegion_crystal_iEta = local_iEta % (p2eg::TOWER_IN_ETA * p2eg::CRYSTALS_IN_TOWER_ETA);
255  int inRegion_crystal_iPhi = local_iPhi;
256 
257  // Crystal eta and phi index inside the tower (5x5)
258  int inLink_crystal_iEta = (inRegion_crystal_iEta % p2eg::CRYSTALS_IN_TOWER_ETA);
259  int inLink_crystal_iPhi = (inRegion_crystal_iPhi % p2eg::CRYSTALS_IN_TOWER_PHI);
260 
261  // Add the crystal energy to the rctCard
262  p2eg::region3x4& myRegion = rctCard.getRegion3x4(regionNumber);
263  p2eg::linkECAL& myLink = myRegion.getLinkECAL(inRegion_tower_iEta, inRegion_tower_iPhi);
264  myLink.addCrystalE(inLink_crystal_iEta, inLink_crystal_iPhi, hit.et_uint());
265  }
266  }
267 
268  //***************************************************//
269  // Build RCT towers from HCAL hits
270  //***************************************************//
271  for (const auto& hit : hcalhits) {
272  if (hit.isInCard(cc) && hit.pt() > 0) {
273  // Get crystal eta and phi, relative to the bottom left corner of the card
274  // (0 up to 17*5, 0 up to 4*5)
275  int local_iEta = hit.crystalLocaliEta(cc);
276  int local_iPhi = hit.crystalLocaliPhi(cc);
277 
278  // Region (0-5) the hit falls into
279  int regionNumber = p2eg::getRegionNumber(local_iEta);
280 
281  // Tower eta and phi index inside the card (17x4)
282  int inCard_tower_iEta = int(local_iEta / p2eg::CRYSTALS_IN_TOWER_ETA);
283  int inCard_tower_iPhi = int(local_iPhi / p2eg::CRYSTALS_IN_TOWER_PHI);
284 
285  // Tower eta and phi index inside the region (3x4)
286  int inRegion_tower_iEta = inCard_tower_iEta % p2eg::TOWER_IN_ETA;
287  int inRegion_tower_iPhi = inCard_tower_iPhi % p2eg::TOWER_IN_PHI;
288 
289  // Access the right HCAL region and tower and increment the ET
290  p2eg::towers3x4& myTowers3x4 = rctCard.getTowers3x4(regionNumber);
291  p2eg::towerHCAL& myTower = myTowers3x4.getTowerHCAL(inRegion_tower_iEta, inRegion_tower_iPhi);
292  myTower.addEt(hit.et_uint());
293  }
294  }
295 
296  //***************************************************//
297  // Make clusters in each ECAL region independently
298  //***************************************************//
299  for (int idxRegion = 0; idxRegion < p2eg::N_REGIONS_PER_CARD; idxRegion++) {
300  // ECAL crystals array
302  // HCAL towers in 3x4 region
303  ap_uint<12> towerEtHCAL[p2eg::TOWER_IN_ETA * p2eg::TOWER_IN_PHI];
304 
305  p2eg::region3x4& myRegion = rctCard.getRegion3x4(idxRegion);
306  p2eg::towers3x4& myTowers = rctCard.getTowers3x4(idxRegion);
307 
308  // In each 3x4 region, loop through the links (one link = one tower)
309  for (int iLinkEta = 0; iLinkEta < p2eg::TOWER_IN_ETA; iLinkEta++) {
310  for (int iLinkPhi = 0; iLinkPhi < p2eg::TOWER_IN_PHI; iLinkPhi++) {
311  // Get the ECAL link (one link per tower)
312  p2eg::linkECAL& myLink = myRegion.getLinkECAL(iLinkEta, iLinkPhi);
313 
314  // We have an array of 3x4 links/towers, each link/tower is 5x5 in crystals. We need to convert this to a 15x20 of crystals
315  int ref_iEta = (iLinkEta * p2eg::CRYSTALS_IN_TOWER_ETA);
316  int ref_iPhi = (iLinkPhi * p2eg::CRYSTALS_IN_TOWER_PHI);
317 
318  // In the link, get the crystals (5x5 in each link)
319  for (int iEta = 0; iEta < p2eg::CRYSTALS_IN_TOWER_ETA; iEta++) {
320  for (int iPhi = 0; iPhi < p2eg::CRYSTALS_IN_TOWER_PHI; iPhi++) {
321  // Et as unsigned int
322  ap_uint<10> uEnergy = myLink.getCrystalE(iEta, iPhi);
323 
324  // Fill the 'temporary' array with a crystal object
325  temporary[ref_iEta + iEta][ref_iPhi + iPhi] = p2eg::crystal(uEnergy);
326  }
327  } // end of loop over crystals
328 
329  // HCAL tower ET
330  p2eg::towerHCAL& myTower = myTowers.getTowerHCAL(iLinkEta, iLinkPhi);
331  towerEtHCAL[(iLinkEta * p2eg::TOWER_IN_PHI) + iLinkPhi] = myTower.getEt();
332  }
333  }
334 
335  // Iteratively find four clusters and remove them from 'temporary' as we go, and fill cluster_list
336  for (int c = 0; c < p2eg::N_CLUSTERS_PER_REGION; c++) {
337  p2eg::Cluster newCluster = p2eg::getClusterFromRegion3x4(temporary); // remove cluster from 'temporary'
338  newCluster.setRegionIdx(idxRegion); // add the region number
339  if (newCluster.clusterEnergy() > 0) {
340  // do not push back 0-energy clusters
341  cluster_list[cc].push_back(newCluster);
342  }
343  }
344 
345  // Create towers using remaining ECAL energy, and the HCAL towers were already calculated in towersEtHCAL[12]
346  ap_uint<12> towerEtECAL[12];
347  p2eg::getECALTowersEt(temporary, towerEtECAL);
348 
349  // Fill towerHCALCard and towerECALCard arrays
350  for (int i = 0; i < 12; i++) {
351  // Get the tower's indices in a (17x4) card
352  int iEta = (idxRegion * p2eg::TOWER_IN_ETA) + (i / p2eg::TOWER_IN_PHI);
353  int iPhi = (i % p2eg::TOWER_IN_PHI);
354 
355  // If the region number is 5 (i.e. only 2x4 in towers, skip the third row) N_REGIONS_PER_CARD = 6. i.e. we do not want to consider
356  // i = 8, 9, 10, 11
357  if ((idxRegion == (p2eg::N_REGIONS_PER_CARD - 1)) && (i > 7)) {
358  continue;
359  }
360  towerHCALCard[iEta][iPhi][cc] =
361  p2eg::tower_t(towerEtHCAL[i], 0); // p2eg::tower_t initializer takes an ap-uint<12> for the energy
362  towerECALCard[iEta][iPhi][cc] = p2eg::tower_t(towerEtECAL[i], 0);
363  }
364  }
365 
366  //-------------------------------------------//
367  // Stitching across ECAL regions //
368  //-------------------------------------------//
369  const int nRegionBoundariesEta = (p2eg::N_REGIONS_PER_CARD - 1); // 6 regions -> 5 boundaries to check
370  // Upper and lower boundaries respectively, to check for stitching along
371  int towerEtaBoundaries[nRegionBoundariesEta][2] = {{15, 14}, {12, 11}, {9, 8}, {6, 5}, {3, 2}};
372 
373  for (int iBound = 0; iBound < nRegionBoundariesEta; iBound++) {
375  cluster_list[cc], towerEtaBoundaries[iBound][0], towerEtaBoundaries[iBound][1], cc);
376  }
377 
378  //--------------------------------------------------------------------------------//
379  // Sort the clusters, take the 8 with highest pT, and return extras to tower
380  //--------------------------------------------------------------------------------//
381  if (!cluster_list[cc].empty()) {
382  std::sort(cluster_list[cc].begin(), cluster_list[cc].end(), p2eg::compareClusterET);
383 
384  // If there are more than eight clusters, return the unused energy to the towers
385  for (unsigned int kk = p2eg::n_clusters_4link; kk < cluster_list[cc].size(); ++kk) {
386  p2eg::Cluster cExtra = cluster_list[cc][kk];
387  if (cExtra.clusterEnergy() > 0) {
388  // Increment tower ET
389  // Get tower (eta, phi) (up to (17, 4)) in the RCT card
390  int whichTowerEtaInCard = ((cExtra.region() * p2eg::TOWER_IN_ETA) + cExtra.towerEta());
391  int whichTowerPhiInCard = cExtra.towerPhi();
392  ap_uint<12> oldTowerEt = towerECALCard[whichTowerEtaInCard][whichTowerPhiInCard][cc].et();
393  ap_uint<12> newTowerEt = (oldTowerEt + cExtra.clusterEnergy());
394  ap_uint<4> hoe = towerECALCard[whichTowerEtaInCard][whichTowerPhiInCard][cc].hoe();
395  towerECALCard[whichTowerEtaInCard][whichTowerPhiInCard][cc] = p2eg::tower_t(newTowerEt, hoe);
396  }
397  }
398 
399  // Save up to eight clusters: loop over cluster_list
400  for (unsigned int kk = 0; kk < cluster_list[cc].size(); ++kk) {
401  if (kk >= p2eg::n_clusters_4link)
402  continue;
403  if (cluster_list[cc][kk].clusterEnergy() > 0) {
404  cluster_list_merged[cc].push_back(cluster_list[cc][kk]);
405  }
406  }
407  }
408 
409  //-------------------------------------------//
410  // Calibrate clusters
411  //-------------------------------------------//
412  for (auto& c : cluster_list_merged[cc]) {
413  float realEta = c.realEta(cc);
414  c.calib = calib_(c.getPt(), std::abs(realEta));
415  c.applyCalibration(c.calib);
416  }
417 
418  //-------------------------------------------//
419  // Cluster shower shape flags
420  //-------------------------------------------//
421  for (auto& c : cluster_list_merged[cc]) {
422  c.is_ss = p2eg::passes_ss(c.getPt(), c.realEta(cc), (c.getEt2x5() / c.getEt5x5()));
423  c.is_looseTkss = p2eg::passes_looseTkss(c.getPt(), c.realEta(cc), (c.getEt2x5() / c.getEt5x5()));
424  }
425 
426  //-------------------------------------------//
427  // Calibrate towers
428  //-------------------------------------------//
429  for (int ii = 0; ii < p2eg::n_towers_cardEta; ++ii) { // 17 towers per card in eta
430  for (int jj = 0; jj < p2eg::n_towers_cardPhi; ++jj) { // 4 towers per card in phi
431  float tRealEta = p2eg::getTowerEta_fromAbsID(
432  p2eg::getAbsID_iEta_fromFirmwareCardTowerLink(cc, ii, jj)); // real eta of center of tower
433  double tCalib = calib_(0, tRealEta); // calibration factor
434  towerECALCard[ii][jj][cc].applyCalibration(tCalib);
435  }
436  }
437 
438  //-------------------------------------------//
439  // Calculate tower HoE
440  //-------------------------------------------//
441  for (int ii = 0; ii < p2eg::n_towers_cardEta; ++ii) { // 17 towers per card in eta
442  for (int jj = 0; jj < p2eg::n_towers_cardPhi; ++jj) { // 4 towers per card in phi
443  ap_uint<12> ecalEt = towerECALCard[ii][jj][cc].et();
444  ap_uint<12> hcalEt = towerHCALCard[ii][jj][cc].et();
445  towerECALCard[ii][jj][cc].addHoverEToTower(ecalEt, hcalEt);
446  }
447  }
448 
449  //-----------------------------------------------------------//
450  // Produce output RCT collections for event display and analyzer
451  //-----------------------------------------------------------//
452  for (auto& c : cluster_list_merged[cc]) {
453  reco::Candidate::PolarLorentzVector p4calibrated(c.getPt(), c.realEta(cc), c.realPhi(cc), 0.);
454 
455  // Constructor definition at: https://github.com/cms-l1t-offline/cmssw/blob/l1t-phase2-v3.3.11/DataFormats/L1TCalorimeterPhase2/interface/CaloCrystalCluster.h#L34
456  l1tp2::CaloCrystalCluster cluster(p4calibrated,
457  c.getPt(), // use float
458  0, // float h over e
459  0, // float iso
460  0, // DetId seedCrystal
461  0, // puCorrPt
462  c.getBrems(), // 0, 1, or 2 (as computed in firmware)
463  0, // et2x2 (not calculated)
464  c.getEt2x5(), // et2x5 (as computed in firmware, save float)
465  0, // et3x5 (not calculated)
466  c.getEt5x5(), // et5x5 (as computed in firmware, save float)
467  c.getIsSS(), // standalone WP
468  c.getIsSS(), // electronWP98
469  false, // photonWP80
470  c.getIsSS(), // electronWP90
471  c.getIsLooseTkss(), // looseL1TkMatchWP
472  c.getIsSS() // stage2effMatch
473  );
474 
475  std::map<std::string, float> params;
476  params["standaloneWP_showerShape"] = c.getIsSS();
477  params["trkMatchWP_showerShape"] = c.getIsLooseTkss();
478  cluster.setExperimentalParams(params);
479 
480  L1EGXtalClusters->push_back(cluster);
481  }
482  // Output tower collections
483  for (int ii = 0; ii < p2eg::n_towers_cardEta; ++ii) { // 17 towers per card in eta
484  for (int jj = 0; jj < p2eg::n_towers_cardPhi; ++jj) { // 4 towers per card in phi
485 
486  l1tp2::CaloTower l1CaloTower;
487  l1CaloTower.setEcalTowerEt(towerECALCard[ii][jj][cc].et() * p2eg::ECAL_LSB);
488  l1CaloTower.setHcalTowerEt(towerHCALCard[ii][jj][cc].et() * p2eg::HCAL_LSB);
491  l1CaloTower.setTowerIEta(absToweriEta);
492  l1CaloTower.setTowerIPhi(absToweriPhi);
493  l1CaloTower.setTowerEta(p2eg::getTowerEta_fromAbsID(absToweriEta));
494  l1CaloTower.setTowerPhi(p2eg::getTowerPhi_fromAbsID(absToweriPhi));
495 
496  L1CaloTowers->push_back(l1CaloTower);
497  }
498  }
499  } // end of loop over cards
500 
501  iEvent.put(std::move(L1EGXtalClusters), "RCTClusters");
502  iEvent.put(std::move(L1CaloTowers), "RCTTowers");
503 
504  //*******************************************************************
505  // Do GCT geometry for inputs
506  //*******************************************************************
507 
508  // Loop over GCT cards (three of them)
511 
512  // Initialize the cards (requires towerECALCard, towerHCALCard arrays, and cluster_list_merged)
513  for (unsigned int gcc = 0; gcc < p2eg::N_GCTCARDS; gcc++) {
514  // Each GCT card encompasses 16 RCT cards, listed in GCTcardtoRCTcardnumber[3][16]. i goes from 0 to <16
515  for (int i = 0; i < (p2eg::N_RCTCARDS_PHI * 2); i++) {
516  unsigned int rcc = p2eg::GCTcardtoRCTcardnumber[gcc][i];
517 
518  // Positive eta? Fist row is in positive eta
519  bool isPositiveEta = (i < p2eg::N_RCTCARDS_PHI);
520 
521  // Sum tower ECAL and HCAL energies: 17 towers per link
522  for (int iTower = 0; iTower < p2eg::N_GCTTOWERS_FIBER; iTower++) {
523  // 4 links per card
524  for (int iLink = 0; iLink < p2eg::n_links_card; iLink++) {
525  p2eg::tower_t t0_ecal = towerECALCard[iTower][iLink][rcc];
526  p2eg::tower_t t0_hcal = towerHCALCard[iTower][iLink][rcc];
528  t.et = t0_ecal.et() + t0_hcal.et();
529  t.hoe = t0_ecal.hoe();
530  // Not needed for GCT firmware but will be written into GCT CMSSW outputs : 12 bits each
531  t.ecalEt = t0_ecal.et();
532  t.hcalEt = t0_hcal.et();
533 
534  if (isPositiveEta) {
535  gctCards[gcc].RCTcardEtaPos[i % p2eg::N_RCTCARDS_PHI].RCTtoGCTfiber[iLink].RCTtowers[iTower] = t;
536  } else {
537  gctCards[gcc].RCTcardEtaNeg[i % p2eg::N_RCTCARDS_PHI].RCTtoGCTfiber[iLink].RCTtowers[iTower] = t;
538  }
539  }
540  }
541 
542  // Distribute at most 8 RCT clusters across four links: convert to GCT coordinates
543  for (size_t iCluster = 0; (iCluster < cluster_list_merged[rcc].size()) &&
545  iCluster++) {
546  p2eg::Cluster c0 = cluster_list_merged[rcc][iCluster];
548  c.et = c0.clusterEnergy();
549 
550  // tower Eta: c0.towerEta() refers to the tower iEta INSIDE the region, so we need to convert to tower iEta inside the card
551  c.towEta = (c0.region() * p2eg::TOWER_IN_ETA) + c0.towerEta();
552  c.towPhi = c0.towerPhi();
553  c.crEta = c0.clusterEta();
554  c.crPhi = c0.clusterPhi();
555  c.et5x5 = c0.uint_et5x5();
556  c.et2x5 = c0.uint_et2x5();
557  c.is_ss = c0.getIsSS();
558  c.is_looseTkss = c0.getIsLooseTkss();
559  c.is_iso = c0.getIsIso();
560  c.is_looseTkiso = c0.getIsLooseTkIso();
561  c.brems = c0.getBrems();
562  c.nGCTCard = gcc; // store gct card index as well
563  unsigned int iIdxInGCT = i % p2eg::N_RCTCARDS_PHI;
564  unsigned int iLinkC = iCluster % p2eg::N_RCTGCT_FIBERS;
565  unsigned int iPosC = iCluster / p2eg::N_RCTGCT_FIBERS;
566 
567  if (isPositiveEta) {
568  gctCards[gcc].RCTcardEtaPos[iIdxInGCT].RCTtoGCTfiber[iLinkC].RCTclusters[iPosC] = c;
569  } else {
570  gctCards[gcc].RCTcardEtaNeg[iIdxInGCT].RCTtoGCTfiber[iLinkC].RCTclusters[iPosC] = c;
571  }
572  }
573  // If there were fewer than eight clusters, make sure the remaining fiber clusters are zero'd out.
574  for (size_t iZeroCluster = cluster_list_merged[rcc].size();
576  iZeroCluster++) {
577  unsigned int iIdxInGCT = i % p2eg::N_RCTCARDS_PHI;
578  unsigned int iLinkC = iZeroCluster % p2eg::N_RCTGCT_FIBERS;
579  unsigned int iPosC = iZeroCluster / p2eg::N_RCTGCT_FIBERS;
580 
581  p2eg::RCTcluster_t cZero;
582  cZero.et = 0;
583  cZero.towEta = 0;
584  cZero.towPhi = 0;
585  cZero.crEta = 0;
586  cZero.crPhi = 0;
587  cZero.et5x5 = 0;
588  cZero.et2x5 = 0;
589  cZero.is_ss = false;
590  cZero.is_looseTkss = false;
591  cZero.is_iso = false;
592  cZero.is_looseTkiso = false;
593  cZero.nGCTCard = gcc; // store gct card index as well
594  if (isPositiveEta) {
595  gctCards[gcc].RCTcardEtaPos[iIdxInGCT].RCTtoGCTfiber[iLinkC].RCTclusters[iPosC] = cZero;
596  } else {
597  gctCards[gcc].RCTcardEtaNeg[iIdxInGCT].RCTtoGCTfiber[iLinkC].RCTclusters[iPosC] = cZero;
598  }
599  }
600  }
601  } // end of loop over initializing GCT cards
602 
603  //----------------------------------------------------
604  // Output collections for the GCT emulator
605  //----------------------------------------------------
606  auto L1GCTClusters = std::make_unique<l1tp2::CaloCrystalClusterCollection>();
607  auto L1GCTTowers = std::make_unique<l1tp2::CaloTowerCollection>();
608  auto L1GCTFullTowers = std::make_unique<l1tp2::CaloTowerCollection>();
609  auto L1GCTEGammas = std::make_unique<l1t::EGammaBxCollection>();
610  auto L1DigitizedClusterCorrelator = std::make_unique<l1tp2::DigitizedClusterCorrelatorCollection>();
611  auto L1DigitizedTowerCorrelator = std::make_unique<l1tp2::DigitizedTowerCorrelatorCollection>();
612  auto L1DigitizedClusterGT = std::make_unique<l1tp2::DigitizedClusterGTCollection>();
613 
614  //----------------------------------------------------
615  // Apply the GCT firmware code to each GCT card
616  //----------------------------------------------------
617 
618  for (unsigned int gcc = 0; gcc < p2eg::N_GCTCARDS; gcc++) {
619  p2eg::algo_top(gctCards[gcc],
620  gctToCorr[gcc],
621  gcc,
622  L1GCTClusters,
623  L1GCTTowers,
624  L1GCTFullTowers,
625  L1GCTEGammas,
626  L1DigitizedClusterCorrelator,
627  L1DigitizedTowerCorrelator,
628  L1DigitizedClusterGT,
629  calib_);
630  }
631 
632  iEvent.put(std::move(L1GCTClusters), "GCTClusters");
633  iEvent.put(std::move(L1GCTTowers), "GCTTowers");
634  iEvent.put(std::move(L1GCTFullTowers), "GCTFullTowers");
635  iEvent.put(std::move(L1GCTEGammas), "GCTEGammas");
636  iEvent.put(std::move(L1DigitizedClusterCorrelator), "GCTDigitizedClusterToCorrelator");
637  iEvent.put(std::move(L1DigitizedTowerCorrelator), "GCTDigitizedTowerToCorrelator");
638  iEvent.put(std::move(L1DigitizedClusterGT), "GCTDigitizedClusterToGT");
639 }
640 
642 
644  // l1tPhase2L1CaloEGammaEmulator
646  desc.add<edm::InputTag>("ecalTPEB", edm::InputTag("simEcalEBTriggerPrimitiveDigis"));
647  desc.add<edm::InputTag>("hcalTP", edm::InputTag("simHcalTriggerPrimitiveDigis"));
648  {
650  psd0.add<std::vector<double>>("etaBins",
651  {
652  0.087,
653  0.174,
654  0.261,
655  0.348,
656  0.435,
657  0.522,
658  0.609,
659  0.696,
660  0.783,
661  0.87,
662  0.957,
663  1.044,
664  1.131,
665  1.218,
666  1.305,
667  1.392,
668  1.479,
669  });
670  psd0.add<std::vector<double>>("ptBins",
671  {
672  12,
673  20,
674  30,
675  40,
676  55,
677  90,
678  1000000.0,
679  });
680  psd0.add<std::vector<double>>("scale",
681  {
682  1.298, 1.287,
683  1.309, 1.298,
684  1.309, 1.309,
685  1.309, 1.298,
686  1.309, 1.298,
687  1.309, 1.309,
688  1.309, 1.32,
689  1.309, 1.32,
690  1.309, 1.1742,
691  1.1639, 1.1639,
692  1.1639, 1.1639,
693  1.1639, 1.1639,
694  1.1742, 1.1742,
695  1.1639, 1.1639,
696  1.1742, 1.1639,
697  1.1639, 1.1742,
698  1.1742, 1.1536000000000002,
699  1.11, 1.11,
700  1.11, 1.11,
701  1.11, 1.11,
702  1.11, 1.11,
703  1.11, 1.11,
704  1.11, 1.11,
705  1.11, 1.11,
706  1.11, 1.11,
707  1.1, 1.09,
708  1.09, 1.09,
709  1.09, 1.09,
710  1.09, 1.09,
711  1.09, 1.09,
712  1.09, 1.09,
713  1.09, 1.09,
714  1.09, 1.09,
715  1.09, 1.09,
716  1.07, 1.07,
717  1.07, 1.07,
718  1.07, 1.07,
719  1.07, 1.08,
720  1.07, 1.07,
721  1.08, 1.08,
722  1.07, 1.08,
723  1.08, 1.08,
724  1.08, 1.06,
725  1.06, 1.06,
726  1.06, 1.05,
727  1.05, 1.06,
728  1.06, 1.06,
729  1.06, 1.06,
730  1.06, 1.06,
731  1.06, 1.06,
732  1.06, 1.06,
733  1.04, 1.04,
734  1.04, 1.04,
735  1.05, 1.04,
736  1.05, 1.05,
737  1.05, 1.05,
738  1.05, 1.05,
739  1.05, 1.05,
740  1.05, 1.05,
741  1.05,
742  });
743  desc.add<edm::ParameterSetDescription>("calib", psd0);
744  }
745  descriptions.addWithDefaultLabel(desc);
746 }
747 
748 //define this as a plug-in
size
Write out results.
void applyCalibration(float factor)
bool validHT(const HcalTrigTowerDetId &id) const
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
edm::ESGetToken< CaloTPGTranscoder, CaloTPGRecord > decoderTag_
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
void getECALTowersEt(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 12 > towerEt[12])
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
RCTcluster_t RCTclusters[N_RCTCLUSTERS_FIBER]
void setEcalTowerEt(float et)
Definition: CaloTower.h:49
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
linkECAL & getLinkECAL(int iEta, int iPhi)
void setTowerIPhi(int iPhi)
Definition: CaloTower.h:51
T const * product() const
Definition: Handle.h:70
void setIdHcal(const HcalDetId &idhcal)
static constexpr int n_clusters_4link
void setPosition(const GlobalVector &pos)
void addCrystalE(int iEta, int iPhi, ap_uint< 10 > energy)
void setRegionIdx(int regIdx)
static constexpr int N_GCTTOWERS_FIBER
int getAbsID_iPhi_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink)
void produce(edm::Event &, const edm::EventSetup &) override
const CaloSubdetectorGeometry * hbGeometry
Log< level::Error, false > LogError
l1tp2::ParametricCalibration calib_
static constexpr int N_REGIONS_PER_CARD
static constexpr int N_CLUSTERS_PER_REGION
RCTtower_t RCTtowers[N_RCTTOWERS_FIBER]
edm::EDGetTokenT< edm::SortedCollection< HcalTriggerPrimitiveDigi > > hcalTPToken_
void setHcalTowerEt(float et)
Definition: CaloTower.h:50
static constexpr int CRYSTAL_IN_ETA
void setTowerIEta(int iEta)
Definition: CaloTower.h:52
float getTowerPhi_fromAbsID(int id)
bool passes_looseTkss(float pt, float eta, float ss)
bool passes_ss(float pt, float eta, float ss)
static void fillDescriptions(edm::ConfigurationDescriptions &)
int iEvent
Definition: GenABIO.cc:224
std::vector< HcalDetId > detIds(const HcalTrigTowerDetId &) const
edm::ESGetToken< HcalTopology, HcalRecNumberingRecord > hbTopologyTag_
Cluster getClusterFromRegion3x4(crystal temp[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI])
void setTowerPhi(float phi)
Definition: CaloTower.h:53
edm::EDGetTokenT< EcalEBTrigPrimDigiCollection > ecalTPEBToken_
ap_uint< 5 > towerEta() const
static constexpr float HCAL_LSB
RCTcard_t RCTcardEtaNeg[N_RCTCARDS_PHI]
float getTowerEta_fromAbsID(int id)
static constexpr int N_RCTCARDS_PHI
towerHCAL & getTowerHCAL(int iEta, int iPhi)
void setIdx(int idx)
static constexpr float ECAL_LSB
const CaloSubdetectorGeometry * ebGeometry
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static constexpr int n_towers_cardPhi
static constexpr int N_RCTGCT_FIBERS
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static constexpr int N_RCTCLUSTERS_FIBER
~Phase2L1CaloEGammaEmulator() override=default
void stitchClusterOverRegionBoundary(std::vector< Cluster > &cluster_list, int towerEtaUpper, int towerEtaLower, int cc)
Definition: Phase2L1RCT.h:1475
ParameterDescriptionBase * add(U const &iLabel, T const &value)
int getRegionNumber(const int local_iEta)
static constexpr float cut_500_MeV
virtual std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
void setTowerEta(float eta)
Definition: CaloTower.h:54
ii
Definition: cuy.py:589
unsigned int id
void addEt(ap_uint< 10 > newEt)
static constexpr int TOWER_IN_PHI
edm::ESGetToken< CaloGeometry, CaloGeometryRecord > caloGeometryTag_
ap_uint< 10 > getCrystalE(int iEta, int iPhi)
Phase2L1CaloEGammaEmulator(const edm::ParameterSet &)
static constexpr int TOWER_IN_ETA
static constexpr int N_GCTCARDS
ap_uint< 2 > towerPhi() const
region3x4 & getRegion3x4(int idx)
void setEt_uint(ap_uint< 10 > et_uint)
RCTtoGCTfiber_t RCTtoGCTfiber[N_RCTGCT_FIBERS]
HLT enums.
void setId(const EBDetId &id)
RCTcard_t RCTcardEtaPos[N_RCTCARDS_PHI]
ap_uint< 12 > clusterEnergy() const
towers3x4 & getTowers3x4(int idx)
static constexpr int CRYSTALS_IN_TOWER_ETA
static constexpr int n_towers_halfPhi
static constexpr int n_towers_cardEta
void addHoverEToTower(ap_uint< 12 > ECAL, ap_uint< 12 > HCAL)
static constexpr int n_links_card
void algo_top(const GCTcard_t &GCTcard, GCTtoCorr_t &GCTtoCorr, unsigned int nGCTCard, std::unique_ptr< l1tp2::CaloCrystalClusterCollection > const &gctClusters, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctTowers, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctFullTowers, std::unique_ptr< l1t::EGammaBxCollection > const &gctEGammas, std::unique_ptr< l1tp2::DigitizedClusterCorrelatorCollection > const &gctDigitizedClustersCorrelator, std::unique_ptr< l1tp2::DigitizedTowerCorrelatorCollection > const &gctDigitizedTowersCorrelator, std::unique_ptr< l1tp2::DigitizedClusterGTCollection > const &gctDigitizedClustersGT, l1tp2::ParametricCalibration calib_)
Definition: Phase2L1GCT.h:363
def move(src, dest)
Definition: eostools.py:511
static constexpr int CRYSTAL_IN_PHI
static constexpr int CRYSTALS_IN_TOWER_PHI
Global3DVector GlobalVector
Definition: GlobalVector.h:10
int getAbsID_iEta_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink)
bool compareClusterET(const Cluster &lhs, const Cluster &rhs)
static const unsigned int GCTcardtoRCTcardnumber[N_GCTCARDS][N_RCTCARDS_PHI *2]
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38