Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-01 06:11:53

0001 // -*- C++ -*-
0002 //
0003 // Package:    L1Trigger/L1TCaloLayer1
0004 // Class:      L1TCaloLayer1
0005 //
0006 /**\class L1TCaloLayer1 L1TCaloLayer1.cc L1Trigger/L1TCaloLayer1/plugins/L1TCaloLayer1.cc
0007 
0008    Description: [one line class summary]
0009 
0010    Implementation:
0011    [Notes on implementation]
0012 */
0013 //
0014 // Original Author:  Sridhara Rao Dasu
0015 //         Created:  Thu, 08 Oct 2015 09:20:16 GMT
0016 //
0017 //
0018 
0019 // system include files
0020 #include <memory>
0021 
0022 // user include files
0023 #include "FWCore/Framework/interface/Frameworkfwd.h"
0024 #include "FWCore/Framework/interface/stream/EDProducer.h"
0025 
0026 #include "FWCore/Framework/interface/Event.h"
0027 #include "FWCore/Framework/interface/MakerMacros.h"
0028 
0029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0030 
0031 #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
0032 #include "DataFormats/HcalDigi/interface/HcalDigiCollections.h"
0033 
0034 #include "L1Trigger/L1TCaloLayer1/src/UCTLayer1.hh"
0035 #include "L1Trigger/L1TCaloLayer1/src/UCTCrate.hh"
0036 #include "L1Trigger/L1TCaloLayer1/src/UCTCard.hh"
0037 #include "L1Trigger/L1TCaloLayer1/src/UCTRegion.hh"
0038 #include "L1Trigger/L1TCaloLayer1/src/UCTTower.hh"
0039 
0040 #include "L1Trigger/L1TCaloLayer1/src/UCTGeometry.hh"
0041 #include "L1Trigger/L1TCaloLayer1/src/UCTLogging.hh"
0042 
0043 #include "DataFormats/L1TCalorimeter/interface/CaloTower.h"
0044 #include "DataFormats/L1CaloTrigger/interface/L1CaloCollections.h"
0045 #include "DataFormats/L1CaloTrigger/interface/L1CaloRegion.h"
0046 
0047 #include "L1Trigger/L1TCalorimeter/interface/CaloTools.h"
0048 
0049 #include "L1Trigger/L1TCaloLayer1/src/L1TCaloLayer1FetchLUTs.hh"
0050 
0051 using namespace l1t;
0052 using namespace l1tcalo;
0053 
0054 //
0055 // class declaration
0056 //
0057 
0058 class L1TCaloLayer1 : public edm::stream::EDProducer<> {
0059 public:
0060   explicit L1TCaloLayer1(const edm::ParameterSet&);
0061 
0062   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0063 
0064 private:
0065   void produce(edm::Event&, const edm::EventSetup&) override;
0066 
0067   void beginRun(edm::Run const&, edm::EventSetup const&) override;
0068 
0069   // ----------member data ---------------------------
0070 
0071   edm::EDGetTokenT<EcalTrigPrimDigiCollection> ecalTPSource;
0072   edm::EDGetTokenT<HcalTrigPrimDigiCollection> hcalTPSource;
0073   edm::EDPutTokenT<CaloTowerBxCollection> towerPutToken;
0074   edm::EDPutTokenT<L1CaloRegionCollection> regionPutToken;
0075   const L1TCaloLayer1FetchLUTsTokens lutsTokens;
0076 
0077   std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins>> ecalLUT;
0078   std::vector<std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins>> hcalLUT;
0079   std::vector<std::array<std::array<uint32_t, nEtBins>, nHfEtaBins>> hfLUT;
0080   std::vector<unsigned long long int> hcalFBLUT;
0081 
0082   std::vector<unsigned int> ePhiMap;
0083   std::vector<unsigned int> hPhiMap;
0084   std::vector<unsigned int> hfPhiMap;
0085 
0086   std::vector<std::shared_ptr<UCTTower>> twrList;
0087 
0088   bool useLSB;
0089   bool useCalib;
0090   bool useECALLUT;
0091   bool useHCALLUT;
0092   bool useHFLUT;
0093   bool useHCALFBLUT;
0094   bool verbose;
0095   bool unpackHcalMask;
0096   bool unpackEcalMask;
0097   int fwVersion;
0098 
0099   std::unique_ptr<UCTLayer1> layer1;
0100 };
0101 
0102 //
0103 // constants, enums and typedefs
0104 //
0105 
0106 //
0107 // static data member definitions
0108 //
0109 
0110 //
0111 // constructors and destructor
0112 //
0113 L1TCaloLayer1::L1TCaloLayer1(const edm::ParameterSet& iConfig)
0114     : ecalTPSource(consumes<EcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("ecalToken"))),
0115       hcalTPSource(consumes<HcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("hcalToken"))),
0116       towerPutToken{produces<CaloTowerBxCollection>()},
0117       regionPutToken{produces<L1CaloRegionCollection>()},
0118       lutsTokens{esConsumes<edm::Transition::BeginRun>(),
0119                  esConsumes<edm::Transition::BeginRun>(),
0120                  esConsumes<edm::Transition::BeginRun>()},
0121       ePhiMap(72 * 2, 0),
0122       hPhiMap(72 * 2, 0),
0123       hfPhiMap(72 * 2, 0),
0124       useLSB(iConfig.getParameter<bool>("useLSB")),
0125       useCalib(iConfig.getParameter<bool>("useCalib")),
0126       useECALLUT(iConfig.getParameter<bool>("useECALLUT")),
0127       useHCALLUT(iConfig.getParameter<bool>("useHCALLUT")),
0128       useHFLUT(iConfig.getParameter<bool>("useHFLUT")),
0129       useHCALFBLUT(iConfig.getParameter<bool>("useHCALFBLUT")),
0130       verbose(iConfig.getUntrackedParameter<bool>("verbose")),
0131       unpackHcalMask(iConfig.getParameter<bool>("unpackHcalMask")),
0132       unpackEcalMask(iConfig.getParameter<bool>("unpackEcalMask")),
0133       fwVersion(iConfig.getParameter<int>("firmwareVersion")) {
0134   // See UCTLayer1.hh for firmware version definitions
0135   layer1 = std::make_unique<UCTLayer1>(fwVersion);
0136 
0137   vector<UCTCrate*> crates = layer1->getCrates();
0138   for (uint32_t crt = 0; crt < crates.size(); crt++) {
0139     vector<UCTCard*> cards = crates[crt]->getCards();
0140     for (uint32_t crd = 0; crd < cards.size(); crd++) {
0141       vector<UCTRegion*> regions = cards[crd]->getRegions();
0142       for (uint32_t rgn = 0; rgn < regions.size(); rgn++) {
0143         vector<std::shared_ptr<UCTTower>> towers = regions[rgn]->getTowers();
0144         for (uint32_t twr = 0; twr < towers.size(); twr++) {
0145           twrList.push_back(towers[twr]);
0146         }
0147       }
0148     }
0149   }
0150 
0151   // This sort corresponds to the sort condition on
0152   // the output CaloTowerBxCollection
0153   std::sort(twrList.begin(), twrList.end(), [](std::shared_ptr<UCTTower> a, std::shared_ptr<UCTTower> b) {
0154     return CaloTools::caloTowerHash(a->caloEta(), a->caloPhi()) < CaloTools::caloTowerHash(b->caloEta(), b->caloPhi());
0155   });
0156 }
0157 
0158 //
0159 // member functions
0160 //
0161 
0162 // ------------ method called to produce the data  ------------
0163 void L1TCaloLayer1::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0164   using namespace edm;
0165 
0166   edm::Handle<EcalTrigPrimDigiCollection> ecalTPs;
0167   iEvent.getByToken(ecalTPSource, ecalTPs);
0168   edm::Handle<HcalTrigPrimDigiCollection> hcalTPs;
0169   iEvent.getByToken(hcalTPSource, hcalTPs);
0170 
0171   CaloTowerBxCollection towersColl;
0172   L1CaloRegionCollection rgnCollection;
0173 
0174   if (!layer1->clearEvent()) {
0175     LOG_ERROR << "UCT: Failed to clear event" << std::endl;
0176     return;
0177   }
0178 
0179   for (const auto& ecalTp : *ecalTPs) {
0180     if (unpackEcalMask && ((ecalTp.sample(0).raw() >> 13) & 0x1))
0181       continue;
0182     int caloEta = ecalTp.id().ieta();
0183     int caloPhi = ecalTp.id().iphi();
0184     int et = ecalTp.compressedEt();
0185     bool fgVeto = ecalTp.fineGrain();
0186     UCTTowerIndex t = UCTTowerIndex(caloEta, caloPhi);
0187     if (!layer1->setECALData(t, fgVeto, et)) {
0188       LOG_ERROR << "UCT: Failed loading an ECAL tower" << std::endl;
0189       return;
0190     }
0191   }
0192 
0193   if (hcalTPs.isValid()) {
0194     for (const auto& hcalTp : *hcalTPs) {
0195       if (unpackHcalMask && ((hcalTp.sample(0).raw() >> 13) & 0x1))
0196         continue;
0197       int caloEta = hcalTp.id().ieta();
0198       uint32_t absCaloEta = std::abs(caloEta);
0199       // Tower 29 is not used by Layer-1
0200       if (absCaloEta == 29) {
0201         continue;
0202       }
0203       // Prevent usage of HF TPs with Layer-1 emulator if HCAL TPs are old style
0204       else if (hcalTp.id().version() == 0 && absCaloEta > 29) {
0205         continue;
0206       } else if (absCaloEta <= 41) {
0207         int caloPhi = hcalTp.id().iphi();
0208         int et = hcalTp.SOI_compressedEt();
0209         bool fg = hcalTp.t0().fineGrain(0);   // depth
0210         bool fg2 = hcalTp.t0().fineGrain(1);  // prompt
0211         bool fg3 = hcalTp.t0().fineGrain(2);  // delay 1
0212         bool fg4 = hcalTp.t0().fineGrain(3);  // delay 2
0213         // note that hcalTp.t0().fineGrain(4) and hcalTp.t0().fineGrain(5) are the reserved MIP bits (not used for LLP logic)
0214         if (caloPhi <= 72) {
0215           UCTTowerIndex t = UCTTowerIndex(caloEta, caloPhi);
0216           uint32_t featureBits = 0;
0217           if (absCaloEta > 29) {
0218             if (fg)
0219               featureBits |= 0b01;
0220             // fg2 should only be set for HF
0221             if (fg2)
0222               featureBits |= 0b10;
0223           } else if (absCaloEta < 16)
0224             featureBits |= (fg | ((!fg2) & (fg3 | fg4)));  // depth | (!prompt & (delay1 | delay2))
0225           if (!layer1->setHCALData(t, featureBits, et)) {
0226             LOG_ERROR << "caloEta = " << caloEta << "; caloPhi =" << caloPhi << std::endl;
0227             LOG_ERROR << "UCT: Failed loading an HCAL tower" << std::endl;
0228             return;
0229           }
0230         } else {
0231           LOG_ERROR << "Illegal Tower: caloEta = " << caloEta << "; caloPhi =" << caloPhi << "; et = " << et
0232                     << std::endl;
0233         }
0234       } else {
0235         LOG_ERROR << "Illegal Tower: caloEta = " << caloEta << std::endl;
0236       }
0237     }
0238   }
0239 
0240   //Process
0241   if (!layer1->process()) {
0242     LOG_ERROR << "UCT: Failed to process layer 1" << std::endl;
0243   }
0244 
0245   int theBX = 0;  // Currently we only read and process the "hit" BX only
0246 
0247   for (uint32_t twr = 0; twr < twrList.size(); twr++) {
0248     CaloTower caloTower;
0249     caloTower.setHwPt(twrList[twr]->et());          // Bits 0-8 of the 16-bit word per the interface protocol document
0250     caloTower.setHwEtRatio(twrList[twr]->er());     // Bits 9-11 of the 16-bit word per the interface protocol document
0251     caloTower.setHwQual(twrList[twr]->miscBits());  // Bits 12-15 of the 16-bit word per the interface protocol document
0252     caloTower.setHwEta(twrList[twr]->caloEta());    // caloEta = 1-28 and 30-41
0253     caloTower.setHwPhi(twrList[twr]->caloPhi());    // caloPhi = 1-72
0254     caloTower.setHwEtEm(twrList[twr]->getEcalET());   // This is provided as a courtesy - not available to hardware
0255     caloTower.setHwEtHad(twrList[twr]->getHcalET());  // This is provided as a courtesy - not available to hardware
0256     towersColl.push_back(theBX, caloTower);
0257   }
0258 
0259   iEvent.emplace(towerPutToken, std::move(towersColl));
0260 
0261   UCTGeometry g;
0262   vector<UCTCrate*> crates = layer1->getCrates();
0263   for (uint32_t crt = 0; crt < crates.size(); crt++) {
0264     vector<UCTCard*> cards = crates[crt]->getCards();
0265     for (uint32_t crd = 0; crd < cards.size(); crd++) {
0266       vector<UCTRegion*> regions = cards[crd]->getRegions();
0267       for (uint32_t rgn = 0; rgn < regions.size(); rgn++) {
0268         uint32_t rawData = regions[rgn]->rawData();
0269         uint32_t regionData = rawData & 0x0000FFFF;
0270         uint32_t crate = regions[rgn]->getCrate();
0271         uint32_t card = regions[rgn]->getCard();
0272         uint32_t region = regions[rgn]->getRegion();
0273         bool negativeEta = regions[rgn]->isNegativeEta();
0274         uint32_t rPhi = g.getUCTRegionPhiIndex(crate, card);
0275         if (region < NRegionsInCard) {  // We only store the Barrel and Endcap - HF has changed in the upgrade
0276           uint32_t rEta =
0277               10 -
0278               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
0279           if (!negativeEta)
0280             rEta = 11 + region;  // Positive eta portion is offset by 11
0281           rgnCollection.push_back(L1CaloRegion((uint16_t)regionData, (unsigned)rEta, (unsigned)rPhi, (int16_t)0));
0282         }
0283       }
0284     }
0285   }
0286   iEvent.emplace(regionPutToken, std::move(rgnCollection));
0287 }
0288 
0289 // ------------ method called when starting to processes a run  ------------
0290 void L1TCaloLayer1::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
0291   if (!L1TCaloLayer1FetchLUTs(lutsTokens,
0292                               iSetup,
0293                               ecalLUT,
0294                               hcalLUT,
0295                               hfLUT,
0296                               hcalFBLUT,
0297                               ePhiMap,
0298                               hPhiMap,
0299                               hfPhiMap,
0300                               useLSB,
0301                               useCalib,
0302                               useECALLUT,
0303                               useHCALLUT,
0304                               useHFLUT,
0305                               useHCALFBLUT,
0306                               fwVersion)) {
0307     LOG_ERROR << "L1TCaloLayer1::beginRun: failed to fetch LUTS - using unity" << std::endl;
0308     // Andrew's note: Sets these to empty arrays initially, then fills all elements with 32 bits of 1's
0309     // to represent a bit-wise unity, and get around initialization complaints on the (now) created null array.
0310     // I'm not crazy about how this is structured, but c++ appears to not offer a lot of utilities
0311     // for filling std::array's (especially nested ones) without listing out every value by hand, or creating them nulled.
0312     std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> eCalLayer1EtaSideEtArray = {};
0313     std::array<std::array<std::array<uint32_t, nEtBins>, nCalSideBins>, nCalEtaBins> hCalLayer1EtaSideEtArray = {};
0314     std::array<std::array<uint32_t, nEtBins>, nHfEtaBins> hfLayer1EtaEtArray = {};
0315     for (uint32_t i = 0; i < nCalEtaBins; i++) {
0316       for (uint32_t j = 0; j < nCalSideBins; j++) {
0317         for (uint32_t k = 0; k < nEtBins; k++) {
0318           eCalLayer1EtaSideEtArray[i][j][k] = 0xFFFFFFFF;
0319           hCalLayer1EtaSideEtArray[i][j][k] = 0xFFFFFFFF;
0320         }
0321       }
0322     }
0323     for (uint32_t i = 0; i < nHfEtaBins; i++) {
0324       for (uint32_t j = 0; j < nEtBins; j++) {
0325         hfLayer1EtaEtArray[i][j] = 0xFFFFFFFF;
0326       }
0327     }
0328     ecalLUT.push_back(eCalLayer1EtaSideEtArray);
0329     hcalLUT.push_back(hCalLayer1EtaSideEtArray);
0330     hfLUT.push_back(hfLayer1EtaEtArray);
0331   }
0332   for (uint32_t twr = 0; twr < twrList.size(); twr++) {
0333     // Map goes minus 1 .. 72 plus 1 .. 72 -> 0 .. 143
0334     int iphi = twrList[twr]->caloPhi();
0335     int ieta = twrList[twr]->caloEta();
0336     if (ieta < 0) {
0337       iphi -= 1;
0338     } else {
0339       iphi += 71;
0340     }
0341     twrList[twr]->setECALLUT(&ecalLUT[ePhiMap[iphi]]);
0342     twrList[twr]->setHCALLUT(&hcalLUT[hPhiMap[iphi]]);
0343     twrList[twr]->setHFLUT(&hfLUT[hfPhiMap[iphi]]);
0344   }
0345 }
0346 
0347 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0348 void L1TCaloLayer1::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0349   //Description set to reflect default present in simCaloStage2Layer1Digis_cfi.py
0350   //Currently redundant, but could be adjusted to provide defaults in case additional LUT
0351   //checks are added and before other configurations adjust to match.
0352   edm::ParameterSetDescription desc;
0353   desc.add<edm::InputTag>("ecalToken", edm::InputTag("simEcalTriggerPrimitiveDigis"));
0354   desc.add<edm::InputTag>("hcalToken", edm::InputTag("simHcalTriggerPrimitiveDigis"));
0355   desc.add<bool>("useLSB", true);
0356   desc.add<bool>("useCalib", true);
0357   desc.add<bool>("useECALLUT", true);
0358   desc.add<bool>("useHCALLUT", true);
0359   desc.add<bool>("useHFLUT", true);
0360   desc.add<bool>("useHCALFBLUT", false);
0361   desc.addUntracked<bool>("verbose", false);
0362   desc.add<bool>("unpackEcalMask", false);
0363   desc.add<bool>("unpackHcalMask", false);
0364   desc.add<int>("firmwareVersion", 1);
0365   descriptions.addDefault(desc);
0366 }
0367 
0368 //define this as a plug-in
0369 DEFINE_FWK_MODULE(L1TCaloLayer1);
0370 /* vim: set ts=8 sw=2 tw=0 et :*/