Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-10-01 01:02:13

0001 #include "DataFormats/L1TCorrelator/interface/TkElectron.h"
0002 #include "DataFormats/L1TCorrelator/interface/TkElectronFwd.h"
0003 #include "DataFormats/L1TCorrelator/interface/TkEm.h"
0004 #include "DataFormats/L1TCorrelator/interface/TkEmFwd.h"
0005 #include "DataFormats/L1Trigger/interface/EGamma.h"
0006 
0007 #include "FWCore/Framework/interface/Event.h"
0008 #include "FWCore/Framework/interface/global/EDProducer.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 #include "FWCore/Utilities/interface/InputTag.h"
0011 #include "FWCore/Utilities/interface/transform.h"
0012 
0013 #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h"
0014 #include "L1Trigger/Phase2L1ParticleFlow/interface/egamma/l2egsorter_ref.h"
0015 //#include "L1Trigger/Phase2L1ParticleFlow/src/newfirmware/egamma/l2egsorter_ref.cpp"
0016 #include "L1Trigger/Phase2L1ParticleFlow/interface/egamma/l2egencoder_ref.h"
0017 //#include "L1Trigger/Phase2L1ParticleFlow/src/newfirmware/egamma/l2egencoder_ref.cpp"
0018 
0019 #include "L1Trigger/DemonstratorTools/interface/BoardDataWriter.h"
0020 #include "L1Trigger/DemonstratorTools/interface/utilities.h"
0021 
0022 #include <iostream>
0023 #include <vector>
0024 
0025 using namespace l1ct;
0026 
0027 class L1TCtL2EgProducer : public edm::global::EDProducer<> {
0028 public:
0029   explicit L1TCtL2EgProducer(const edm::ParameterSet &);
0030   ~L1TCtL2EgProducer() override;
0031 
0032 private:
0033   ap_uint<64> encodeLayer1(const EGIsoObjEmu &egiso) const;
0034   ap_uint<128> encodeLayer1(const EGIsoEleObjEmu &egiso) const;
0035 
0036   std::vector<ap_uint<64>> encodeLayer1(const std::vector<EGIsoObjEmu> &photons) const;
0037   std::vector<ap_uint<64>> encodeLayer1(const std::vector<EGIsoEleObjEmu> &electrons) const;
0038 
0039   std::vector<ap_uint<64>> encodeLayer1EgObjs(unsigned int nObj,
0040                                               const std::vector<EGIsoObjEmu> &photons,
0041                                               const std::vector<EGIsoEleObjEmu> &electrons) const;
0042 
0043   void produce(edm::StreamID, edm::Event &, const edm::EventSetup &) const override;
0044 
0045   void endJob() override;
0046 
0047   struct RefRemapper {
0048     typedef TTTrack<Ref_Phase2TrackerDigi_> L1TTTrackType;
0049 
0050     BXVector<edm::Ref<BXVector<l1t::EGamma>>> oldRefs;
0051     std::map<edm::Ref<BXVector<l1t::EGamma>>, edm::Ref<BXVector<l1t::EGamma>>> old2newRefMap;
0052     std::vector<std::pair<edm::Ref<l1t::EGammaBxCollection>, edm::Ptr<L1TTTrackType>>> origRefAndPtr;
0053   };
0054 
0055   void convertToEmu(const l1t::TkElectron &tkele, RefRemapper &refRemapper, l1ct::OutputBoard &boarOut) const;
0056   void convertToEmu(const l1t::TkEm &tkele, RefRemapper &refRemapper, l1ct::OutputBoard &boarOut) const;
0057 
0058   template <class T>
0059   class PFInstanceInputs {
0060   public:
0061     typedef std::vector<std::pair<edm::EDGetTokenT<T>, std::vector<int>>> InputTokenAndChannels;
0062     PFInstanceInputs(L1TCtL2EgProducer *prod, const std::vector<edm::ParameterSet> &confs) {
0063       for (const auto &conf : confs) {
0064         const auto &producer_tag = conf.getParameter<edm::InputTag>("pfProducer");
0065         tokensAndChannels_.push_back(std::make_pair(
0066             prod->consumes<T>(edm::InputTag(producer_tag.label(), producer_tag.instance(), producer_tag.process())),
0067             conf.getParameter<std::vector<int>>("channels")));
0068       }
0069     }
0070 
0071     const InputTokenAndChannels &tokensAndChannels() const { return tokensAndChannels_; }
0072 
0073   private:
0074     InputTokenAndChannels tokensAndChannels_;
0075   };
0076 
0077   class PatternWriter {
0078   public:
0079     PatternWriter(const edm::ParameterSet &conf) : dataWriter_(nullptr) {
0080       unsigned int nFramesPerBX = conf.getParameter<uint32_t>("nFramesPerBX");
0081 
0082       std::map<l1t::demo::LinkId, std::pair<l1t::demo::ChannelSpec, std::vector<size_t>>> channelSpecs;
0083 
0084       for (const auto &channelConf : conf.getParameter<std::vector<edm::ParameterSet>>("channels")) {
0085         unsigned int inTMUX = channelConf.getParameter<uint32_t>("TMUX");
0086         unsigned int eventGap =
0087             inTMUX * nFramesPerBX - channelConf.getParameter<uint32_t>("nWords");  // assuming 96bit (= 3/2 word)
0088                                                                                    // words  = TMUX*9-2*3/2*words
0089         std::vector<uint32_t> chns = channelConf.getParameter<std::vector<uint32_t>>("channels");
0090         channelSpecs[l1t::demo::LinkId{channelConf.getParameter<std::string>("interface"),
0091                                        channelConf.getParameter<uint32_t>("id")}] =
0092             std::make_pair(l1t::demo::ChannelSpec{inTMUX, eventGap},
0093                            std::vector<size_t>(std::begin(chns), std::end(chns)));
0094       }
0095 
0096       dataWriter_ = std::make_unique<l1t::demo::BoardDataWriter>(
0097           l1t::demo::parseFileFormat(conf.getParameter<std::string>("format")),
0098           conf.getParameter<std::string>("outputFilename"),
0099           nFramesPerBX,
0100           conf.getParameter<uint32_t>("TMUX"),
0101           conf.getParameter<uint32_t>("maxLinesPerFile"),
0102           channelSpecs);
0103     }
0104 
0105     void addEvent(const l1t::demo::EventData &eventData) { dataWriter_->addEvent(eventData); }
0106 
0107     void flush() { dataWriter_->flush(); }
0108 
0109   private:
0110     std::unique_ptr<l1t::demo::BoardDataWriter> dataWriter_;
0111   };
0112 
0113   template <class TT, class T>
0114   void merge(const PFInstanceInputs<T> &instance,
0115              edm::Event &iEvent,
0116              RefRemapper &refRemapper,
0117              std::unique_ptr<TT> &out) const {
0118     edm::Handle<T> handle;
0119     for (const auto &tokenAndChannel : instance.tokensAndChannels()) {
0120       iEvent.getByToken(tokenAndChannel.first, handle);
0121       populate(out, handle, tokenAndChannel.second, refRemapper);
0122     }
0123     remapRefs(iEvent, out, refRemapper);
0124   }
0125 
0126   template <class TT>
0127   void remapRefs(edm::Event &iEvent, std::unique_ptr<TT> &out, RefRemapper &refRemapper) const {}
0128 
0129   void remapRefs(edm::Event &iEvent, std::unique_ptr<BXVector<l1t::EGamma>> &out, RefRemapper &refRemapper) const {
0130     edm::RefProd<BXVector<l1t::EGamma>> ref_egs = iEvent.getRefBeforePut<BXVector<l1t::EGamma>>(tkEGInstanceLabel_);
0131     edm::Ref<BXVector<l1t::EGamma>>::key_type idx = 0;
0132     for (std::size_t ix = 0; ix < out->size(); ix++) {
0133       refRemapper.old2newRefMap[refRemapper.oldRefs[ix]] = edm::Ref<BXVector<l1t::EGamma>>(ref_egs, idx++);
0134     }
0135   }
0136 
0137   template <class TT, class T>
0138   void populate(std::unique_ptr<T> &out,
0139                 const edm::Handle<TT> &in,
0140                 const std::vector<int> &links,
0141                 RefRemapper &refRemapper) const {
0142     assert(links.size() == in->nRegions());
0143     for (unsigned int iBoard = 0, nBoard = in->nRegions(); iBoard < nBoard; ++iBoard) {
0144       auto region = in->region(iBoard);
0145       int linkID = links[iBoard];
0146       if (linkID < 0)
0147         continue;
0148       // std::cout << "Board eta: " << in->eta(iBoard) << " phi: " << in->phi(iBoard) << " link: " << linkID << std::endl;
0149       for (const auto &obj : region) {
0150         convertToEmu(obj, refRemapper, out->at(linkID));
0151       }
0152     }
0153   }
0154 
0155   void populate(std::unique_ptr<BXVector<l1t::EGamma>> &out,
0156                 const edm::Handle<BXVector<l1t::EGamma>> &in,
0157                 const std::vector<int> &links,
0158                 RefRemapper &refRemapper) const {
0159     edm::Ref<BXVector<l1t::EGamma>>::key_type idx = 0;
0160     for (int bx = in->getFirstBX(); bx <= in->getLastBX(); bx++) {
0161       for (auto egee_itr = in->begin(bx); egee_itr != in->end(bx); egee_itr++) {
0162         out->push_back(bx, *egee_itr);
0163         // this to ensure that the old ref and the new object have the same
0164         // index in the BXVector collection so that we can still match them no
0165         // matter which BX we will insert next
0166         refRemapper.oldRefs.push_back(bx, edm::Ref<BXVector<l1t::EGamma>>(in, idx++));
0167       }
0168     }
0169   }
0170 
0171   template <class Tout, class Tin>
0172   void putEgObjects(edm::Event &iEvent,
0173                     const RefRemapper &refRemapper,
0174                     const std::string &label,
0175                     const std::vector<Tin> emulated) const {
0176     auto egobjs = std::make_unique<Tout>();
0177     for (const auto &emu : emulated) {
0178       if (emu.hwPt == 0)
0179         continue;
0180       auto obj = convertFromEmu(emu, refRemapper);
0181       egobjs->push_back(obj);
0182     }
0183     iEvent.put(std::move(egobjs), label);
0184   }
0185 
0186   l1t::TkEm convertFromEmu(const l1ct::EGIsoObjEmu &emu, const RefRemapper &refRemapper) const;
0187   l1t::TkElectron convertFromEmu(const l1ct::EGIsoEleObjEmu &emu, const RefRemapper &refRemapper) const;
0188 
0189   PFInstanceInputs<BXVector<l1t::EGamma>> tkEGInputs_;
0190   PFInstanceInputs<l1t::TkEmRegionalOutput> tkEmInputs_;
0191   PFInstanceInputs<l1t::TkElectronRegionalOutput> tkEleInputs_;
0192   std::string tkEGInstanceLabel_;
0193   std::string tkEmInstanceLabel_;
0194   std::string tkEleInstanceLabel_;
0195   l1ct::L2EgSorterEmulator l2egsorter;
0196   l1ct::L2EgEncoderEmulator l2encoder;
0197   bool doInPtrn_;
0198   bool doOutPtrn_;
0199   std::unique_ptr<PatternWriter> inPtrnWrt_;
0200   std::unique_ptr<PatternWriter> outPtrnWrt_;
0201 };
0202 
0203 L1TCtL2EgProducer::L1TCtL2EgProducer(const edm::ParameterSet &conf)
0204     : tkEGInputs_(this, conf.getParameter<std::vector<edm::ParameterSet>>("tkEgs")),
0205       tkEmInputs_(this, conf.getParameter<std::vector<edm::ParameterSet>>("tkEms")),
0206       tkEleInputs_(this, conf.getParameter<std::vector<edm::ParameterSet>>("tkElectrons")),
0207       tkEGInstanceLabel_(conf.getParameter<std::string>("egStaInstanceLabel")),
0208       tkEmInstanceLabel_(conf.getParameter<std::string>("tkEmInstanceLabel")),
0209       tkEleInstanceLabel_(conf.getParameter<std::string>("tkEleInstanceLabel")),
0210       l2egsorter(conf.getParameter<edm::ParameterSet>("sorter")),
0211       l2encoder(conf.getParameter<edm::ParameterSet>("encoder")),
0212       doInPtrn_(conf.getParameter<bool>("writeInPattern")),
0213       doOutPtrn_(conf.getParameter<bool>("writeOutPattern")),
0214       inPtrnWrt_(nullptr),
0215       outPtrnWrt_(nullptr) {
0216   produces<BXVector<l1t::EGamma>>(tkEGInstanceLabel_);
0217   produces<l1t::TkEmCollection>(tkEmInstanceLabel_);
0218   produces<l1t::TkElectronCollection>(tkEleInstanceLabel_);
0219 
0220   if (doInPtrn_) {
0221     inPtrnWrt_ = std::make_unique<PatternWriter>(conf.getParameter<edm::ParameterSet>("inPatternFile"));
0222   }
0223   if (doOutPtrn_) {
0224     outPtrnWrt_ = std::make_unique<PatternWriter>(conf.getParameter<edm::ParameterSet>("outPatternFile"));
0225   }
0226 }
0227 
0228 L1TCtL2EgProducer::~L1TCtL2EgProducer() {}
0229 
0230 ap_uint<64> L1TCtL2EgProducer::encodeLayer1(const EGIsoObjEmu &egiso) const {
0231   ap_uint<64> ret = 0;
0232   ret(EGIsoObjEmu::BITWIDTH, 0) = egiso.pack();
0233   return ret;
0234 }
0235 
0236 ap_uint<128> L1TCtL2EgProducer::encodeLayer1(const EGIsoEleObjEmu &egiso) const {
0237   ap_uint<128> ret = 0;
0238   ret(EGIsoEleObjEmu::BITWIDTH, 0) = egiso.pack();
0239   return ret;
0240 }
0241 
0242 std::vector<ap_uint<64>> L1TCtL2EgProducer::encodeLayer1(const std::vector<EGIsoObjEmu> &photons) const {
0243   std::vector<ap_uint<64>> ret;
0244   ret.reserve(photons.size());
0245   for (const auto &phot : photons) {
0246     ret.push_back(encodeLayer1(phot));
0247   }
0248   return ret;
0249 }
0250 
0251 std::vector<ap_uint<64>> L1TCtL2EgProducer::encodeLayer1(const std::vector<EGIsoEleObjEmu> &electrons) const {
0252   std::vector<ap_uint<64>> ret;
0253   ret.reserve(2 * electrons.size());
0254   for (const auto &ele : electrons) {
0255     auto eleword = encodeLayer1(ele);
0256     ret.push_back(eleword(63, 0));
0257     ret.push_back(eleword(127, 64));
0258   }
0259   return ret;
0260 }
0261 
0262 std::vector<ap_uint<64>> L1TCtL2EgProducer::encodeLayer1EgObjs(unsigned int nObj,
0263                                                                const std::vector<EGIsoObjEmu> &photons,
0264                                                                const std::vector<EGIsoEleObjEmu> &electrons) const {
0265   std::vector<ap_uint<64>> ret;
0266   auto encoded_photons = encodeLayer1(photons);
0267   encoded_photons.resize(nObj, {0});
0268   auto encoded_eles = encodeLayer1(electrons);
0269   encoded_eles.resize(2 * nObj, {0});
0270 
0271   std::copy(encoded_photons.begin(), encoded_photons.end(), std::back_inserter(ret));
0272   std::copy(encoded_eles.begin(), encoded_eles.end(), std::back_inserter(ret));
0273 
0274   return ret;
0275 }
0276 
0277 void L1TCtL2EgProducer::produce(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &) const {
0278   RefRemapper refmapper;
0279 
0280   auto outEgs = std::make_unique<BXVector<l1t::EGamma>>();
0281   merge(tkEGInputs_, iEvent, refmapper, outEgs);
0282   iEvent.put(std::move(outEgs), tkEGInstanceLabel_);
0283 
0284   auto boards = std::make_unique<std::vector<l1ct::OutputBoard>>(l2egsorter.nInputBoards());
0285 
0286   merge(tkEleInputs_, iEvent, refmapper, boards);
0287   merge(tkEmInputs_, iEvent, refmapper, boards);
0288 
0289   if (doInPtrn_) {
0290     l1t::demo::EventData inData;
0291     for (unsigned int ibrd = 0; ibrd < boards->size(); ibrd++) {
0292       inData.add(
0293           {"eglayer1", ibrd},
0294           encodeLayer1EgObjs(l2egsorter.nInputObjPerBoard(), (*boards)[ibrd].egphoton, (*boards)[ibrd].egelectron));
0295     }
0296     inPtrnWrt_->addEvent(inData);
0297   }
0298 
0299   std::vector<EGIsoObjEmu> out_photons_emu;
0300   std::vector<EGIsoEleObjEmu> out_eles_emu;
0301   l2egsorter.run(*boards, out_photons_emu, out_eles_emu);
0302 
0303   if (doOutPtrn_) {
0304     l1t::demo::EventData outData;
0305     outData.add({"eglayer2", 0}, l2encoder.encodeLayer2EgObjs(out_photons_emu, out_eles_emu));
0306     outPtrnWrt_->addEvent(outData);
0307   }
0308 
0309   putEgObjects<l1t::TkEmCollection>(iEvent, refmapper, tkEmInstanceLabel_, out_photons_emu);
0310   putEgObjects<l1t::TkElectronCollection>(iEvent, refmapper, tkEleInstanceLabel_, out_eles_emu);
0311 }
0312 
0313 void L1TCtL2EgProducer::endJob() {
0314   // Writing pending events to file before exiting
0315   if (doOutPtrn_)
0316     outPtrnWrt_->flush();
0317   if (doInPtrn_)
0318     inPtrnWrt_->flush();
0319 }
0320 
0321 void L1TCtL2EgProducer::convertToEmu(const l1t::TkElectron &tkele,
0322                                      RefRemapper &refRemapper,
0323                                      l1ct::OutputBoard &boarOut) const {
0324   EGIsoEleObjEmu emu;
0325   emu.initFromBits(tkele.egBinaryWord<EGIsoEleObj::BITWIDTH>());
0326   emu.srcCluster = nullptr;
0327   emu.srcTrack = nullptr;
0328   auto refEg = tkele.EGRef();
0329   const auto newref = refRemapper.old2newRefMap.find(refEg);
0330   if (newref != refRemapper.old2newRefMap.end()) {
0331     refEg = newref->second;
0332   }
0333   refRemapper.origRefAndPtr.push_back(std::make_pair(refEg, tkele.trkPtr()));
0334   emu.sta_idx = refRemapper.origRefAndPtr.size() - 1;
0335   // NOTE: The emulator and FW data-format stores absolute iso while the CMSSW object stores relative iso
0336   emu.setHwIso(EGIsoEleObjEmu::IsoType::TkIso, l1ct::Scales::makeIso(tkele.trkIsol() * tkele.pt()));
0337   emu.setHwIso(EGIsoEleObjEmu::IsoType::PfIso, l1ct::Scales::makeIso(tkele.pfIsol() * tkele.pt()));
0338   // std::cout << "[convertToEmu] TkEle pt: " << emu.hwPt << " eta: " << emu.hwEta << " phi: " << emu.hwPhi << " staidx: " << emu.sta_idx << std::endl;
0339 
0340   boarOut.egelectron.push_back(emu);
0341 }
0342 
0343 void L1TCtL2EgProducer::convertToEmu(const l1t::TkEm &tkem,
0344                                      RefRemapper &refRemapper,
0345                                      l1ct::OutputBoard &boarOut) const {
0346   EGIsoObjEmu emu;
0347   emu.initFromBits(tkem.egBinaryWord<EGIsoObj::BITWIDTH>());
0348   emu.srcCluster = nullptr;
0349   auto refEg = tkem.EGRef();
0350   const auto newref = refRemapper.old2newRefMap.find(refEg);
0351   if (newref != refRemapper.old2newRefMap.end()) {
0352     refEg = newref->second;
0353   }
0354   refRemapper.origRefAndPtr.push_back(std::make_pair(refEg, edm::Ptr<RefRemapper::L1TTTrackType>(nullptr, 0)));
0355   emu.sta_idx = refRemapper.origRefAndPtr.size() - 1;
0356   // NOTE: The emulator and FW data-format stores absolute iso while the CMSSW object stores relative iso
0357   emu.setHwIso(EGIsoObjEmu::IsoType::TkIso, l1ct::Scales::makeIso(tkem.trkIsol() * tkem.pt()));
0358   emu.setHwIso(EGIsoObjEmu::IsoType::PfIso, l1ct::Scales::makeIso(tkem.pfIsol() * tkem.pt()));
0359   emu.setHwIso(EGIsoObjEmu::IsoType::TkIsoPV, l1ct::Scales::makeIso(tkem.trkIsolPV() * tkem.pt()));
0360   emu.setHwIso(EGIsoObjEmu::IsoType::PfIsoPV, l1ct::Scales::makeIso(tkem.pfIsolPV() * tkem.pt()));
0361   // std::cout << "[convertToEmu] TkEM pt: " << emu.hwPt << " eta: " << emu.hwEta << " phi: " << emu.hwPhi << " staidx: " << emu.sta_idx << std::endl;
0362   boarOut.egphoton.push_back(emu);
0363 }
0364 
0365 l1t::TkEm L1TCtL2EgProducer::convertFromEmu(const l1ct::EGIsoObjEmu &egiso, const RefRemapper &refRemapper) const {
0366   // std::cout << "[convertFromEmu] TkEm pt: " << egiso.hwPt << " eta: " << egiso.hwEta << " phi: " << egiso.hwPhi << " staidx: " << egiso.sta_idx << std::endl;
0367   // NOTE: the TkEM object is created with the accuracy as in GT object (not the Correlator internal one)!
0368   const auto gteg = egiso.toGT();
0369   reco::Candidate::PolarLorentzVector mom(
0370       l1gt::Scales::floatPt(gteg.v3.pt), l1gt::Scales::floatEta(gteg.v3.eta), l1gt::Scales::floatPhi(gteg.v3.phi), 0.);
0371   // NOTE: The emulator and FW data-format stores absolute iso while the CMSSW object stores relative iso
0372   l1t::TkEm tkem(reco::Candidate::LorentzVector(mom),
0373                  refRemapper.origRefAndPtr[egiso.sta_idx].first,
0374                  egiso.floatRelIso(l1ct::EGIsoObjEmu::IsoType::TkIso),
0375                  egiso.floatRelIso(l1ct::EGIsoObjEmu::IsoType::TkIsoPV));
0376   tkem.setHwQual(gteg.quality);
0377   tkem.setPFIsol(egiso.floatRelIso(l1ct::EGIsoObjEmu::IsoType::PfIso));
0378   tkem.setPFIsolPV(egiso.floatRelIso(l1ct::EGIsoObjEmu::IsoType::PfIsoPV));
0379   tkem.setEgBinaryWord(gteg.pack());
0380   return tkem;
0381 }
0382 
0383 l1t::TkElectron L1TCtL2EgProducer::convertFromEmu(const l1ct::EGIsoEleObjEmu &egele,
0384                                                   const RefRemapper &refRemapper) const {
0385   // std::cout << "[convertFromEmu] TkEle pt: " << egele.hwPt << " eta: " << egele.hwEta << " phi: " << egele.hwPhi << " staidx: " << egele.sta_idx << std::endl;
0386   // NOTE: the TkElectron object is created with the accuracy as in GT object (not the Correlator internal one)!
0387   const auto gteg = egele.toGT();
0388   reco::Candidate::PolarLorentzVector mom(
0389       l1gt::Scales::floatPt(gteg.v3.pt), l1gt::Scales::floatEta(gteg.v3.eta), l1gt::Scales::floatPhi(gteg.v3.phi), 0.);
0390   // NOTE: The emulator and FW data-format stores absolute iso while the CMSSW object stores relative iso
0391   l1t::TkElectron tkele(reco::Candidate::LorentzVector(mom),
0392                         refRemapper.origRefAndPtr[egele.sta_idx].first,
0393                         refRemapper.origRefAndPtr[egele.sta_idx].second,
0394                         egele.floatRelIso(l1ct::EGIsoEleObjEmu::IsoType::TkIso));
0395   tkele.setHwQual(gteg.quality);
0396   tkele.setPFIsol(egele.floatRelIso(l1ct::EGIsoEleObjEmu::IsoType::PfIso));
0397   tkele.setEgBinaryWord(gteg.pack());
0398   return tkele;
0399 }
0400 
0401 #include "FWCore/Framework/interface/MakerMacros.h"
0402 DEFINE_FWK_MODULE(L1TCtL2EgProducer);