Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:19

0001 // -*- C++ -*-
0002 //
0003 // Package:    L1Trigger/skeleton
0004 // Class:      skeleton
0005 //
0006 /**\class skeleton skeleton.cc L1Trigger/skeleton/plugins/skeleton.cc
0007 
0008  Description: [one line class summary]
0009 
0010  Implementation:
0011      [Notes on implementation]
0012 */
0013 //
0014 // Original Author:  James Brooke
0015 //         Created:  Thu, 05 Dec 2013 17:39:27 GMT
0016 //
0017 //
0018 
0019 // system include files
0020 #include <memory>
0021 
0022 // user include files
0023 
0024 #include "FWCore/Framework/interface/EventSetup.h"
0025 #include "FWCore/Framework/interface/Frameworkfwd.h"
0026 #include "FWCore/Framework/interface/stream/EDProducer.h"
0027 #include "FWCore/Framework/interface/ESHandle.h"
0028 #include "FWCore/Framework/interface/Event.h"
0029 #include "FWCore/Framework/interface/MakerMacros.h"
0030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0031 #include "FWCore/Utilities/interface/EDGetToken.h"
0032 #include "FWCore/Utilities/interface/InputTag.h"
0033 #include "FWCore/Utilities/interface/ESGetToken.h"
0034 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0035 
0036 #include "L1Trigger/L1TCalorimeter/interface/Stage2Layer1FirmwareFactory.h"
0037 #include "L1Trigger/L1TCalorimeter/interface/Stage2PreProcessor.h"
0038 
0039 #include "L1Trigger/L1TCalorimeter/interface/CaloParamsHelper.h"
0040 #include "CondFormats/DataRecord/interface/L1TCaloParamsRcd.h"
0041 
0042 #include "CondFormats/L1TObjects/interface/L1CaloEcalScale.h"
0043 #include "CondFormats/DataRecord/interface/L1CaloEcalScaleRcd.h"
0044 #include "CondFormats/L1TObjects/interface/L1CaloHcalScale.h"
0045 #include "CondFormats/DataRecord/interface/L1CaloHcalScaleRcd.h"
0046 
0047 #include "CalibFormats/CaloTPG/interface/CaloTPGTranscoder.h"
0048 #include "CalibFormats/CaloTPG/interface/CaloTPGRecord.h"
0049 
0050 #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
0051 #include "DataFormats/HcalDigi/interface/HcalDigiCollections.h"
0052 
0053 #include "DataFormats/L1TCalorimeter/interface/CaloTower.h"
0054 
0055 #include "L1Trigger/L1TCalorimeter/interface/CaloTools.h"
0056 
0057 //
0058 // class declaration
0059 //
0060 
0061 using namespace l1t;
0062 
0063 class L1TStage2Layer1Producer : public edm::stream::EDProducer<> {
0064 public:
0065   explicit L1TStage2Layer1Producer(const edm::ParameterSet& ps);
0066   ~L1TStage2Layer1Producer() override;
0067 
0068   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0069 
0070 private:
0071   void produce(edm::Event&, const edm::EventSetup&) override;
0072 
0073   void beginRun(edm::Run const&, edm::EventSetup const&) override;
0074 
0075   // ----------member data ---------------------------
0076 
0077   int verbosity_;
0078   bool rctConditions_;
0079 
0080   int bxFirst_, bxLast_;  // bx range to process
0081 
0082   std::vector<edm::EDGetToken> ecalToken_;  // this is a crazy way to store multi-BX info
0083   std::vector<edm::EDGetToken> hcalToken_;  // should be replaced with a BXVector< > or similar
0084 
0085   edm::ESGetToken<L1CaloEcalScale, L1CaloEcalScaleRcd> ecalScaleToken_;
0086   edm::ESGetToken<L1CaloHcalScale, L1CaloHcalScaleRcd> hcalScaleToken_;
0087   edm::ESGetToken<CaloTPGTranscoder, CaloTPGRecord> decoderToken_;
0088   edm::ESGetToken<CaloParams, L1TCaloParamsRcd> paramsToken_;
0089   // parameters
0090   unsigned long long paramsCacheId_;
0091   unsigned fwv_;
0092   CaloParamsHelper* params_;
0093 
0094   // the processor
0095   Stage2Layer1FirmwareFactory factory_;
0096   std::shared_ptr<Stage2PreProcessor> processor_;
0097 };
0098 
0099 L1TStage2Layer1Producer::L1TStage2Layer1Producer(const edm::ParameterSet& ps)
0100     : verbosity_(ps.getParameter<int>("verbosity")),
0101       rctConditions_(ps.getParameter<bool>("rctConditions")),
0102       bxFirst_(ps.getParameter<int>("bxFirst")),
0103       bxLast_(ps.getParameter<int>("bxLast")),
0104       ecalToken_(bxLast_ + 1 - bxFirst_),
0105       hcalToken_(bxLast_ + 1 - bxFirst_),
0106       paramsCacheId_(0),
0107       params_(nullptr) {
0108   // register what you produce
0109   produces<CaloTowerBxCollection>();
0110 
0111   // register what you consume and keep token for later access:
0112   for (int ibx = 0; ibx < bxLast_ + 1 - bxFirst_; ibx++) {
0113     ecalToken_[ibx] = consumes<EcalTrigPrimDigiCollection>(ps.getParameter<edm::InputTag>("ecalToken"));
0114     hcalToken_[ibx] = consumes<HcalTrigPrimDigiCollection>(ps.getParameter<edm::InputTag>("hcalToken"));
0115   }
0116   if (rctConditions_) {
0117     ecalScaleToken_ = esConsumes<L1CaloEcalScale, L1CaloEcalScaleRcd>();
0118     hcalScaleToken_ = esConsumes<L1CaloHcalScale, L1CaloHcalScaleRcd>();
0119   } else {
0120     decoderToken_ = esConsumes<CaloTPGTranscoder, CaloTPGRecord>();
0121   }
0122   paramsToken_ = esConsumes<CaloParams, L1TCaloParamsRcd, edm::Transition::BeginRun>();
0123   // placeholder for the parameters
0124   params_ = new CaloParamsHelper;
0125 
0126   // set firmware version from python config for now
0127   fwv_ = ps.getParameter<int>("firmware");
0128 }
0129 
0130 L1TStage2Layer1Producer::~L1TStage2Layer1Producer() { delete params_; }
0131 
0132 // ------------ method called to produce the data  ------------
0133 void L1TStage2Layer1Producer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0134   LogDebug("l1t|stage 2") << "L1TStage2Layer1Producer::produce function called..." << std::endl;
0135 
0136   // do event setup
0137   // get RCT input scale objects
0138   edm::ESHandle<L1CaloEcalScale> ecalScale;
0139   edm::ESHandle<L1CaloHcalScale> hcalScale;
0140 
0141   edm::ESHandle<CaloTPGTranscoder> decoder;
0142 
0143   if (rctConditions_) {
0144     ecalScale = iSetup.getHandle(ecalScaleToken_);
0145     hcalScale = iSetup.getHandle(hcalScaleToken_);
0146   } else {
0147     decoder = iSetup.getHandle(decoderToken_);
0148   }
0149 
0150   LogDebug("L1TDebug") << "First BX=" << bxFirst_ << ", last BX=" << bxLast_ << ", LSB(E)=" << params_->towerLsbE()
0151                        << ", LSB(H)=" << params_->towerLsbH() << std::endl;
0152 
0153   // output collection
0154   std::unique_ptr<CaloTowerBxCollection> towersColl(new CaloTowerBxCollection);
0155 
0156   // loop over crossings
0157   for (int bx = bxFirst_; bx < bxLast_ + 1; ++bx) {
0158     int ibx = bx - bxFirst_;
0159 
0160     edm::Handle<EcalTrigPrimDigiCollection> ecalTPs;
0161     edm::Handle<HcalTrigPrimDigiCollection> hcalTPs;
0162 
0163     iEvent.getByToken(hcalToken_[ibx], hcalTPs);
0164     iEvent.getByToken(ecalToken_[ibx], ecalTPs);
0165 
0166     // create input and output tower vectors for this BX
0167     std::unique_ptr<std::vector<CaloTower> > localInTowers(
0168         new std::vector<CaloTower>(CaloTools::caloTowerHashMax() + 1));
0169     std::unique_ptr<std::vector<CaloTower> > localOutTowers(
0170         new std::vector<CaloTower>());  //this is later filled to the same size as localInTowers
0171 
0172     // loop over ECAL TPs
0173     EcalTrigPrimDigiCollection::const_iterator ecalItr;
0174     int nEcal = 0;
0175     for (ecalItr = ecalTPs->begin(); ecalItr != ecalTPs->end(); ++ecalItr, ++nEcal) {
0176       int ieta = ecalItr->id().ieta();
0177       int iphi = ecalItr->id().iphi();
0178 
0179       int ietIn = ecalItr->compressedEt();
0180       bool ifg = ecalItr->fineGrain();
0181 
0182       // decompress
0183       double et = 0.;
0184       if (rctConditions_) {
0185         et = ecalScale->et(ietIn, abs(ieta), (ieta > 0));
0186       } else {
0187         et = 0.5 * ietIn;
0188       }
0189 
0190       int ietOut = floor(et / params_->towerLsbE());
0191 
0192       int itow = CaloTools::caloTowerHash(ieta, iphi);
0193       localInTowers->at(itow).setHwEtEm(ietOut);
0194       localInTowers->at(itow).setHwQual(localInTowers->at(itow).hwQual() |
0195                                         (ifg ? 0x8 : 0x0));  //ECAL FG bit is supposed to be on bit 3
0196     }
0197 
0198     // loop over HCAL TPs
0199     HcalTrigPrimDigiCollection::const_iterator hcalItr;
0200     int nHcal = 0;
0201     for (hcalItr = hcalTPs->begin(); hcalItr != hcalTPs->end(); ++hcalItr, ++nHcal) {
0202       int ieta = hcalItr->id().ieta();
0203       int iphi = hcalItr->id().iphi();
0204       int ver = hcalItr->id().version();
0205 
0206       // check for old HF TPs
0207       if (abs(ieta) >= CaloTools::kHFBegin && ver != 1)
0208         continue;
0209 
0210       int ietIn = hcalItr->SOI_compressedEt();
0211       int ifg = hcalItr->SOI_fineGrain();
0212 
0213       // decompress
0214       double et = 0.;
0215 
0216       if (rctConditions_) {
0217         if (abs(ieta) >= CaloTools::kHFBegin)
0218           et = hcalScale->et(ietIn, CaloTools::kHFBegin, (ieta > 0));
0219         else
0220           et = hcalScale->et(ietIn, abs(ieta), (ieta > 0));
0221       } else {
0222         et = decoder->hcaletValue(hcalItr->id(), hcalItr->t0());
0223       }
0224 
0225       int ietOut = floor(et / params_->towerLsbH());
0226 
0227       // get tower index
0228       unsigned itow = CaloTools::caloTowerHash(ieta, iphi);
0229 
0230       if (ietOut > 0)
0231         LogDebug("L1TDebug") << " HCAL TP : " << ieta << ", " << iphi << ", " << ietIn << ", " << et << ", " << ietOut
0232                              << ", " << itow << ", " << CaloTools::caloTowerHashMax() << ", " << localInTowers->size()
0233                              << std::endl;
0234 
0235       localInTowers->at(itow).setHwEtHad(ietOut);
0236       localInTowers->at(itow).setHwQual(localInTowers->at(itow).hwQual() |
0237                                         (ifg ? 0x4 : 0x0));  //HCAL FG bit is supposed to be on bit 2
0238     }
0239 
0240     // now calculate remaining tower quantities
0241     for (int ieta = -1 * CaloTools::kHFEnd; ieta <= CaloTools::kHFEnd; ieta++) {
0242       for (int iphi = 0; iphi <= CaloTools::kHBHENrPhi; iphi++) {
0243         if (!CaloTools::isValidIEtaIPhi(ieta, iphi))
0244           continue;
0245 
0246         unsigned itow = CaloTools::caloTowerHash(ieta, iphi);
0247 
0248         // get ECAL/HCAL raw numbers
0249         int ietEcal = localInTowers->at(itow).hwEtEm();
0250         int ietHcal = localInTowers->at(itow).hwEtHad();
0251 
0252         int iet = ietEcal + ietHcal;
0253 
0254         if (ietHcal > 0)
0255           LogDebug("L1TDebug") << " L1Tow : " << ieta << ", " << iphi << ", " << itow << ", " << iet << ", " << ietEcal
0256                                << ", " << ietHcal << std::endl;
0257 
0258         localInTowers->at(itow).setHwPt(iet);
0259         localInTowers->at(itow).setHwEta(ieta);
0260         localInTowers->at(itow).setHwPhi(iphi);
0261 
0262         int ietby2 = round(double(ietHcal) / 2.);
0263         int ietby4 = round(double(ietHcal) / 4.);
0264 
0265         // if HF, divide energy by two and give half to adjacent tower
0266         if (abs(ieta) > 29 && iphi % 2 == 1) {
0267           localInTowers->at(itow).setHwPt(ietby2);
0268           localInTowers->at(itow).setHwEtHad(ietby2);
0269           int itow_next = CaloTools::caloTowerHash(ieta, iphi + 1);
0270           localInTowers->at(itow_next).setHwPt(ietby2);
0271           localInTowers->at(itow_next).setHwEtHad(ietby2);
0272         }
0273 
0274         if (abs(ieta) > 39 && iphi % 4 == 3) {
0275           localInTowers->at(itow).setHwPt(ietby4);
0276           localInTowers->at(itow).setHwEtHad(ietby4);
0277           int itow_next = CaloTools::caloTowerHash(ieta, iphi + 1);
0278           localInTowers->at(itow_next).setHwPt(ietby4);
0279           localInTowers->at(itow_next).setHwEtHad(ietby4);
0280           itow_next = CaloTools::caloTowerHash(ieta, iphi - 1);
0281           localInTowers->at(itow_next).setHwPt(ietby4);
0282           localInTowers->at(itow_next).setHwEtHad(ietby4);
0283           itow_next = CaloTools::caloTowerHash(ieta, iphi - 2);
0284           localInTowers->at(itow_next).setHwPt(ietby4);
0285           localInTowers->at(itow_next).setHwEtHad(ietby4);
0286         }
0287       }
0288     }
0289 
0290     //    for(std::vector<CaloTower>::const_iterator tower = localInTowers->begin();
0291     //  tower != localInTowers->end();
0292     //  ++tower) {
0293     //      if (tower->hwEta()>30) std::cout << "HF in : " << tower->hwEta() << "," << tower->hwPhi() << "," << tower->hwPt() << "," << tower->hwEtHad() << std::endl;
0294     //    }
0295 
0296     // do the decompression
0297     processor_->processEvent(*localInTowers, *localOutTowers);
0298 
0299     // copy towers to output collection
0300     for (std::vector<CaloTower>::const_iterator tower = localOutTowers->begin(); tower != localOutTowers->end();
0301          ++tower) {
0302       //     if (tower->hwEta()>30) std::cout << "HF out : " << tower->hwEta() << "," << tower->hwPhi() << "," << tower->hwPt() << "," << tower->etHad() << std::endl;
0303       towersColl->push_back(ibx, *tower);
0304     }
0305     LogDebug("L1TDebug") << "BX=" << ibx << ", N(Tower in)=" << localInTowers->size()
0306                          << ", N(Tower out)=" << localOutTowers->size() << std::endl;
0307   }
0308 
0309   iEvent.put(std::move(towersColl));
0310 }
0311 
0312 // ------------ method called when starting to processes a run  ------------
0313 void L1TStage2Layer1Producer::beginRun(edm::Run const& iRun, edm::EventSetup const& iSetup) {
0314   // update parameters and algorithms at run start, if they have changed
0315   // update params first because the firmware factory relies on pointer to params
0316 
0317   // parameters
0318 
0319   unsigned long long id = iSetup.get<L1TCaloParamsRcd>().cacheIdentifier();
0320 
0321   if (id != paramsCacheId_) {
0322     paramsCacheId_ = id;
0323 
0324     edm::ESHandle<CaloParams> paramsHandle = iSetup.getHandle(paramsToken_);
0325 
0326     // replace our local copy of the parameters with a new one using placement new
0327     params_->~CaloParamsHelper();
0328     params_ = new (params_) CaloParamsHelper(*paramsHandle.product());
0329 
0330     LogDebug("L1TDebug") << *params_ << std::endl;
0331 
0332     if (!params_) {
0333       edm::LogError("l1t|caloStage2") << "Could not retrieve params from Event Setup" << std::endl;
0334     }
0335   }
0336 
0337   // firmware
0338 
0339   if (!processor_) {  // in future, also check if the firmware cache ID has changed !
0340 
0341     //     m_fwv = ; // get new firmware version in future
0342 
0343     // Set the current algorithm version based on DB pars from database:
0344     processor_ = factory_.create(fwv_, params_);
0345 
0346     LogDebug("L1TDebug") << "Processor object : " << (processor_ ? 1 : 0) << std::endl;
0347 
0348     if (!processor_) {
0349       // we complain here once per run
0350       edm::LogError("l1t|caloStage2") << "Layer 1 firmware could not be configured.\n";
0351     }
0352   }
0353 }
0354 
0355 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0356 void L1TStage2Layer1Producer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0357   //The following says we do not know what parameters are allowed so do no validation
0358   // Please change this to state exactly what you do use, even if it is no parameters
0359   edm::ParameterSetDescription desc;
0360   desc.setUnknown();
0361   descriptions.addDefault(desc);
0362 }
0363 
0364 //define this as a plug-in
0365 DEFINE_FWK_MODULE(L1TStage2Layer1Producer);