diff --git a/DataFormats/L1TParticleFlow/interface/RegionalOutput.h b/DataFormats/L1TParticleFlow/interface/RegionalOutput.h index feb127232bb18..33c55f682a8ce 100644 --- a/DataFormats/L1TParticleFlow/interface/RegionalOutput.h +++ b/DataFormats/L1TParticleFlow/interface/RegionalOutput.h @@ -93,12 +93,14 @@ namespace l1t { : src_(src), ibegin_(ibegin), iend_(iend) {} }; - RegionalOutput() : refprod_(), values_(), regions_() {} - RegionalOutput(const edm::RefProd& prod) : refprod_(prod), values_(), regions_() {} + RegionalOutput() : refprod_(), values_(), regions_(), etas_(), phis_() {} + RegionalOutput(const edm::RefProd& prod) : refprod_(prod), values_(), regions_(), etas_(), phis_() {} - void addRegion(const std::vector& indices) { + void addRegion(const std::vector& indices, const float eta, const float phi) { regions_.emplace_back((regions_.empty() ? 0 : regions_.back()) + indices.size()); values_.insert(values_.end(), indices.begin(), indices.end()); + etas_.push_back(eta); + phis_.push_back(phi); } edm::ProductID id() const { return refprod_.id(); } @@ -108,16 +110,22 @@ namespace l1t { void clear() { values_.clear(); regions_.clear(); + etas_.clear(); + phis_.clear(); } void shrink_to_fit() { values_.shrink_to_fit(); regions_.shrink_to_fit(); + etas_.shrink_to_fit(); + phis_.shrink_to_fit(); } const_iterator begin() const { return const_iterator(this, 0); } const_iterator end() const { return const_iterator(this, values_.size()); } Region region(unsigned int ireg) const { return Region(this, ireg == 0 ? 0 : regions_[ireg - 1], regions_[ireg]); } + const float eta(unsigned int ireg) const { return etas_[ireg]; } + const float phi(unsigned int ireg) const { return phis_[ireg]; } ref refAt(unsigned int idx) const { return ref(refprod_, values_[idx]); } const value_type& objAt(unsigned int idx) const { return (*refprod_)[values_[idx]]; } @@ -129,6 +137,8 @@ namespace l1t { refprod refprod_; std::vector values_; // list of indices to objects in each region, flattened. std::vector regions_; // for each region, store the index of one-past the last object in values + std::vector etas_; // floatEtaCenter of each PFregion + std::vector phis_; // floatPhiCenter of each PFregion }; } // namespace l1t #endif diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/DeregionizerProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/DeregionizerProducer.cc new file mode 100644 index 0000000000000..7d1eaebcc0bda --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/DeregionizerProducer.cc @@ -0,0 +1,176 @@ +#include + +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h" + +#include "L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.h" +#include "L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.h" + +class DeregionizerProducer : public edm::stream::EDProducer<> { +public: + explicit DeregionizerProducer(const edm::ParameterSet &); + ~DeregionizerProducer() override; + +private: + edm::ParameterSet config_; + edm::EDGetTokenT token_; + l1ct::DeregionizerEmulator emulator_; + bool debug_; + + std::unordered_map clusterRefMap_; + std::unordered_map trackRefMap_; + std::unordered_map muonRefMap_; + + void produce(edm::Event &, const edm::EventSetup &) override; + void hwToEdm_(const std::vector &hwOut, std::vector &edmOut) const; + void setRefs_(l1t::PFCandidate &pf, const l1ct::PuppiObjEmu &p) const; +}; + +DeregionizerProducer::DeregionizerProducer(const edm::ParameterSet &iConfig) + : config_(iConfig), + token_(consumes(iConfig.getParameter("RegionalPuppiCands"))), + emulator_(iConfig), + debug_(iConfig.getUntrackedParameter("debug", 0)) { + produces("Puppi"); + produces("TruncatedPuppi"); +} + +DeregionizerProducer::~DeregionizerProducer() {} + +void DeregionizerProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + clusterRefMap_.clear(); + trackRefMap_.clear(); + muonRefMap_.clear(); + + auto deregColl = std::make_unique(); + auto truncColl = std::make_unique(); + + edm::Handle src; + + iEvent.getByToken(token_, src); + + std::vector regionEtas, regionPhis; + std::vector outputRegions; + std::vector hwOut; + std::vector edmOut; + std::vector hwTruncOut; + std::vector edmTruncOut; + + if (debug_) + edm::LogPrint("DeregionizerProducer") << "\nRegional Puppi Candidates"; + for (unsigned int iReg = 0, nReg = src->nRegions(); iReg < nReg; ++iReg) { + l1ct::OutputRegion tempOutputRegion; + + auto region = src->region(iReg); + float eta = src->eta(iReg); + float phi = src->phi(iReg); + if (debug_) + edm::LogPrint("DeregionizerProducer") << "\nRegion " << iReg << "\n" + << "Eta = " << eta << " and Phi = " << phi << "\n" + << "###########"; + for (int i = 0, n = region.size(); i < n; ++i) { + l1ct::PuppiObjEmu tempPuppi; + const l1t::PFCandidate &cand = region[i]; + clusterRefMap_[&cand] = cand.pfCluster(); + trackRefMap_[&cand] = cand.pfTrack(); + muonRefMap_[&cand] = cand.muon(); + + tempPuppi.initFromBits(cand.encodedPuppi64()); + tempPuppi.srcCand = &cand; + tempOutputRegion.puppi.push_back(tempPuppi); + if (debug_) + edm::LogPrint("DeregionizerProducer") << "pt[" << i << "] = " << tempOutputRegion.puppi.back().hwPt << ", eta[" + << i << "] = " << tempOutputRegion.puppi.back().floatEta() << ", phi[" + << i << "] = " << tempOutputRegion.puppi.back().floatPhi(); + } + if (tempOutputRegion.puppi.size() > 0) { + regionEtas.push_back(eta); + regionPhis.push_back(phi); + outputRegions.push_back(tempOutputRegion); + } + } + + l1ct::DeregionizerInput in = l1ct::DeregionizerInput(regionEtas, regionPhis, outputRegions); + in.setDebug(debug_); + + emulator_.run(in, hwOut, hwTruncOut); + + DeregionizerProducer::hwToEdm_(hwOut, edmOut); + DeregionizerProducer::hwToEdm_(hwTruncOut, edmTruncOut); + + deregColl->swap(edmOut); + truncColl->swap(edmTruncOut); + + iEvent.put(std::move(deregColl), "Puppi"); + iEvent.put(std::move(truncColl), "TruncatedPuppi"); +} + +void DeregionizerProducer::hwToEdm_(const std::vector &hwOut, + std::vector &edmOut) const { + for (const auto &hwPuppi : hwOut) { + l1t::PFCandidate::ParticleType type; + float mass = 0.13f; + if (hwPuppi.hwId.charged()) { + if (hwPuppi.hwId.isMuon()) { + type = l1t::PFCandidate::Muon; + mass = 0.105; + } else if (hwPuppi.hwId.isElectron()) { + type = l1t::PFCandidate::Electron; + mass = 0.005; + } else + type = l1t::PFCandidate::ChargedHadron; + } else { + type = hwPuppi.hwId.isPhoton() ? l1t::PFCandidate::Photon : l1t::PFCandidate::NeutralHadron; + mass = hwPuppi.hwId.isPhoton() ? 0.0 : 0.5; + } + reco::Particle::PolarLorentzVector p4(hwPuppi.floatPt(), hwPuppi.floatEta(), hwPuppi.floatPhi(), mass); + edmOut.emplace_back( + type, hwPuppi.intCharge(), p4, hwPuppi.floatPuppiW(), hwPuppi.intPt(), hwPuppi.intEta(), hwPuppi.intPhi()); + if (hwPuppi.hwId.charged()) { + edmOut.back().setZ0(hwPuppi.floatZ0()); + edmOut.back().setDxy(hwPuppi.floatDxy()); + edmOut.back().setHwZ0(hwPuppi.hwZ0()); + edmOut.back().setHwDxy(hwPuppi.hwDxy()); + edmOut.back().setHwTkQuality(hwPuppi.hwTkQuality()); + } else { + edmOut.back().setHwPuppiWeight(hwPuppi.hwPuppiW()); + edmOut.back().setHwEmID(hwPuppi.hwEmID()); + } + edmOut.back().setEncodedPuppi64(hwPuppi.pack().to_uint64()); + setRefs_(edmOut.back(), hwPuppi); + } +} + +void DeregionizerProducer::setRefs_(l1t::PFCandidate &pf, const l1ct::PuppiObjEmu &p) const { + if (p.srcCand) { + auto match = clusterRefMap_.find(p.srcCand); + if (match == clusterRefMap_.end()) { + throw cms::Exception("CorruptData") << "Invalid cluster pointer in PF candidate id " << p.intId() << " pt " + << p.floatPt() << " eta " << p.floatEta() << " phi " << p.floatPhi(); + } + pf.setPFCluster(match->second); + } + if (p.srcCand) { + auto match = trackRefMap_.find(p.srcCand); + if (match == trackRefMap_.end()) { + throw cms::Exception("CorruptData") << "Invalid track pointer in PF candidate id " << p.intId() << " pt " + << p.floatPt() << " eta " << p.floatEta() << " phi " << p.floatPhi(); + } + pf.setPFTrack(match->second); + } + if (p.srcCand) { + auto match = muonRefMap_.find(p.srcCand); + if (match == muonRefMap_.end()) { + throw cms::Exception("CorruptData") << "Invalid muon pointer in PF candidate id " << p.intId() << " pt " + << p.floatPt() << " eta " << p.floatEta() << " phi " << p.floatPhi(); + } + pf.setMuon(match->second); + } +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(DeregionizerProducer); diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc index 90629d357ab97..c1742c05d6eac 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc @@ -123,7 +123,7 @@ l1t::PFJet L1SeedConePFJetProducer::makeJet_SW(const std::vector L1SeedConePFJetProducer::processEvent_SW(std::vector>& work) const { // The floating point algorithm simulation - std::sort(work.begin(), work.end(), [](edm::Ptr i, edm::Ptr j) { + std::stable_sort(work.begin(), work.end(), [](edm::Ptr i, edm::Ptr j) { return (i->pt() > j->pt()); }); std::vector jets; diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc index ef83b0e3564b6..4383a458eea64 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc @@ -780,7 +780,7 @@ void L1TCorrelatorLayer1Producer::putPuppi(edm::Event &iEvent) const { setRefs_(coll->back(), p); nobj.push_back(coll->size() - 1); } - reg->addRegion(nobj); + reg->addRegion(nobj, event_.pfinputs[ir].region.floatEtaCenter(), event_.pfinputs[ir].region.floatPhiCenter()); } iEvent.put(std::move(coll), "Puppi"); iEvent.put(std::move(reg), "PuppiRegional"); diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TPFCandMultiMerger.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TPFCandMultiMerger.cc index 4dbc8870ccd07..61e629b23097e 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TPFCandMultiMerger.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TPFCandMultiMerger.cc @@ -80,7 +80,7 @@ void L1TPFCandMultiMerger::produce(edm::StreamID, edm::Event& iEvent, const edm: for (auto iter = region.begin(), iend = region.end(); iter != iend; ++iter) { keys.push_back(iter.idx() + offset); } - regout->addRegion(keys); + regout->addRegion(keys, src.eta(ireg), src.phi(ireg)); } } } diff --git a/L1Trigger/Phase2L1ParticleFlow/python/DeregionizerProducer_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/DeregionizerProducer_cfi.py new file mode 100644 index 0000000000000..6d978e7ce668a --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/python/DeregionizerProducer_cfi.py @@ -0,0 +1,11 @@ +import FWCore.ParameterSet.Config as cms + +DeregionizerProducer = cms.EDProducer("DeregionizerProducer", + RegionalPuppiCands = cms.InputTag("l1ctLayer1","PuppiRegional"), + nPuppiFinalBuffer = cms.uint32(128), + nPuppiPerClk = cms.uint32(6), + nPuppiFirstBuffers = cms.uint32(12), + nPuppiSecondBuffers = cms.uint32(32), + nPuppiThirdBuffers = cms.uint32(64), + debug = cms.untracked.bool(False) + ) diff --git a/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.cpp b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.cpp new file mode 100644 index 0000000000000..2c15038d19661 --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include "deregionizer_input.h" + +#ifdef CMSSW_GIT_HASH +#include "L1Trigger/Phase2L1ParticleFlow/src/dbgPrintf.h" +#else +#include "../../utils/dbgPrintf.h" +#endif + +l1ct::DeregionizerInput::DeregionizerInput(std::vector ®ionEtaCenter, + std::vector ®ionPhiCenter, + const std::vector &inputRegions) + : regionEtaCenter_(regionEtaCenter), regionPhiCenter_(regionPhiCenter) { + orderedInRegionsPuppis_ = std::vector > >(nEtaRegions); + for (int i = 0, n = nEtaRegions; i < n; i++) + orderedInRegionsPuppis_[i].resize(nPhiRegions); + initRegions(inputRegions); +} + +// +pi read first & account for 2 small eta regions per phi slice +unsigned int l1ct::DeregionizerInput::orderRegionsInPhi(const float eta, const float phi, const float etaComp) const { + unsigned int y; + if (fabs(phi) < 0.35) + y = (eta < etaComp ? 0 : 1); + else if (fabs(phi) < 1.05) + y = (phi > 0 ? (eta < etaComp ? 2 : 3) : (eta < etaComp ? 16 : 17)); + else if (fabs(phi) < 1.75) + y = (phi > 0 ? (eta < etaComp ? 4 : 5) : (eta < etaComp ? 14 : 15)); + else if (fabs(phi) < 2.45) + y = (phi > 0 ? (eta < etaComp ? 6 : 7) : (eta < etaComp ? 12 : 13)); + else + y = (phi > 0 ? (eta < etaComp ? 8 : 9) : (eta < etaComp ? 10 : 11)); + return y; +} + +void l1ct::DeregionizerInput::initRegions(const std::vector &inputRegions) { + for (int i = 0, n = inputRegions.size(); i < n; i++) { + unsigned int x, y; + float eta = regionEtaCenter_[i]; + float phi = regionPhiCenter_[i]; + + if (fabs(eta) < 0.5) { + x = 0; + y = orderRegionsInPhi(eta, phi, 0.0); + } else if (fabs(eta) < 1.5) { + x = (eta < 0.0 ? 1 : 2); + y = (eta < 0.0 ? orderRegionsInPhi(eta, phi, -1.0) : orderRegionsInPhi(eta, phi, 1.0)); + } else if (fabs(eta) < 2.5) { + x = (eta < 0.0 ? 3 : 4); + y = orderRegionsInPhi(eta, phi, 999.0); // Send all candidates in 3 clks, then wait 3 clks for the barrel + } else /*if ( fabs(eta) < 3.0 )*/ { + x = 5; + y = orderRegionsInPhi(eta, phi, 0.0); // Send eta<0 in 3 clks, eta>0 in the next 3 clks + } + /*else x = 6;*/ // HF + + orderedInRegionsPuppis_[x][y].insert(orderedInRegionsPuppis_[x][y].end(), + inputRegions[i].puppi.begin(), + inputRegions[i].puppi.end()); // For now, merging HF with forward HGCal + + while (!orderedInRegionsPuppis_[x][y].empty() && orderedInRegionsPuppis_[x][y].back().hwPt == 0) + orderedInRegionsPuppis_[x][y].pop_back(); // Zero suppression + } +} + +void l1ct::DeregionizerInput::orderRegions(int order[nEtaRegions]) { + std::vector > > tmpOrderedInRegionsPuppis; + for (int i = 0, n = nEtaRegions; i < n; i++) + tmpOrderedInRegionsPuppis.push_back(orderedInRegionsPuppis_[order[i]]); + orderedInRegionsPuppis_ = tmpOrderedInRegionsPuppis; + + if (debug_) { + for (int i = 0, nx = orderedInRegionsPuppis_.size(); i < nx; i++) { + dbgCout() << "\n"; + dbgCout() << "Eta region index : " << i << "\n"; + for (int j = 0, ny = orderedInRegionsPuppis_[i].size(); j < ny; j++) { + dbgCout() << " ---> Phi region index : " << j << "\n"; + for (int iPup = 0, nPup = orderedInRegionsPuppis_[i][j].size(); iPup < nPup; iPup++) { + dbgCout() << " > puppi[" << iPup << "]" + << " pt = " << orderedInRegionsPuppis_[i][j][iPup].hwPt << "\n"; + } + } + dbgCout() << " ----------------- " + << "\n"; + } + dbgCout() << "Regions ordered!" + << "\n"; + dbgCout() << "\n"; + } +} diff --git a/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.h b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.h new file mode 100644 index 0000000000000..5f17724397174 --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_input.h @@ -0,0 +1,53 @@ +#ifndef L1Trigger_Phase2L1ParticleFlow_newfirmware_deregionizer_input_h +#define L1Trigger_Phase2L1ParticleFlow_newfirmware_deregionizer_input_h + +#include +#ifdef CMSSW_GIT_HASH +#include "../dataformats/layer1_emulator.h" +#else +#include "../../dataformats/layer1_emulator.h" +#endif + +namespace l1ct { + + class DeregionizerInput { + public: + static const unsigned int nEtaRegions = + 6 /*7 with HF*/; // Fold ([-0.5,0.0] and [0.0,+0.5]) and ([+-0.5,+-1.0] and [+-1.0,+-1.5]) eta slices into phi + static const unsigned int nPhiRegions = + 18; // 9 phi slices * 2 to account for the barrel having x2 PF regions per eta slice in the barrel + + DeregionizerInput(std::vector ®ionEtaCenter, + std::vector ®ionPhiCenter, + const std::vector &inputRegions); + + void setDebug(bool debug = true) { debug_ = debug; } + + enum regionIndex { + centralBarl = 0, + negBarl = 1, + posBarl = 2, + negHGCal = 3, + posHGCal = 4, + forwardHGCal = 5 /*, HF = 6*/ + }; + void orderRegions(int order[nEtaRegions]); + + const std::vector > > &orderedInRegionsPuppis() const { + return orderedInRegionsPuppis_; + }; + + private: + std::vector regionEtaCenter_; + std::vector regionPhiCenter_; + std::vector > > orderedInRegionsPuppis_; + + bool debug_ = false; + + unsigned int orderRegionsInPhi(const float eta, const float phi, const float etaComp) const; + void initRegions(const std::vector &inputRegions); + }; + +} // namespace l1ct + +#endif diff --git a/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.cpp new file mode 100644 index 0000000000000..b125d4627c7f9 --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.cpp @@ -0,0 +1,156 @@ +#include "deregionizer_ref.h" + +#include +#include + +#ifdef CMSSW_GIT_HASH +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "L1Trigger/Phase2L1ParticleFlow/src/dbgPrintf.h" + +l1ct::DeregionizerEmulator::DeregionizerEmulator(const edm::ParameterSet &iConfig) + : DeregionizerEmulator(iConfig.getParameter("nPuppiFinalBuffer"), + iConfig.getParameter("nPuppiPerClk"), + iConfig.getParameter("nPuppiFirstBuffers"), + iConfig.getParameter("nPuppiSecondBuffers"), + iConfig.getParameter("nPuppiThirdBuffers")) { + debug_ = iConfig.getUntrackedParameter("debug", false); +} +#else +#include "../../utils/dbgPrintf.h" +#endif + +l1ct::DeregionizerEmulator::DeregionizerEmulator(const unsigned int nPuppiFinalBuffer /*=128*/, + const unsigned int nPuppiPerClk /*=6*/, + const unsigned int nPuppiFirstBuffers /*=12*/, + const unsigned int nPuppiSecondBuffers /*=32*/, + const unsigned int nPuppiThirdBuffers /*=64*/) + : nPuppiFinalBuffer_(nPuppiFinalBuffer), + nPuppiPerClk_(nPuppiPerClk), + nPuppiFirstBuffers_(nPuppiFirstBuffers), + nPuppiSecondBuffers_(nPuppiSecondBuffers), + nPuppiThirdBuffers_(nPuppiThirdBuffers), + debug_(false) { + assert(nPuppiPerClk < nPuppiFirstBuffers && nPuppiFirstBuffers < nPuppiSecondBuffers && + nPuppiSecondBuffers < nPuppiThirdBuffers && nPuppiThirdBuffers <= nPuppiFinalBuffer); +} + +std::vector > l1ct::DeregionizerEmulator::splitPFregions( + const std::vector > > ®ionPuppis, const int i, const int j) { + int k = nPuppiPerClk_ * j; + std::vector > subregionPuppis; + for (int l = 0, n = regionPuppis.size(); l < n; l++) { + const auto &puppis = regionPuppis[l][i]; + std::vector tmp(std::min(puppis.begin() + k, puppis.end()), + std::min(puppis.begin() + k + nPuppiPerClk_, puppis.end())); + subregionPuppis.push_back(tmp); + } + return subregionPuppis; +} + +std::vector l1ct::DeregionizerEmulator::mergeXtoY(const unsigned int X, + const unsigned int Y, + const std::vector &inLeft, + const std::vector &inRight) { + std::vector out; + + out.insert(out.end(), inLeft.begin(), std::min(inLeft.end(), inLeft.begin() + X)); + out.insert(out.end(), inRight.begin(), std::min(inRight.end(), inRight.begin() + Y - X)); + + return out; +} + +void l1ct::DeregionizerEmulator::accumulateToY(const unsigned int Y, + const std::vector &in, + std::vector &out, + std::vector &truncated) { + unsigned int initialOutSize = out.size(); + assert(initialOutSize <= Y); + if (initialOutSize == Y) { + truncated.insert(truncated.end(), in.begin(), in.end()); + return; + } + out.insert(out.end(), in.begin(), std::min(in.end(), in.begin() + Y - initialOutSize)); + if (out.size() == Y) + truncated.insert(truncated.end(), in.begin() + Y - initialOutSize, in.end()); + return; +} + +static void debugPrint(const std::string &header, const std::vector &pup) { + dbgCout() << " --> " << header << "\n"; + for (unsigned int iPup = 0, nPup = pup.size(); iPup < nPup; ++iPup) + dbgCout() << " > puppi[" << iPup << "] pT = " << pup[iPup].hwPt << "\n"; +} + +void l1ct::DeregionizerEmulator::run(const l1ct::DeregionizerInput in, + std::vector &out, + std::vector &truncated) { + const auto ®ionPuppis = in.orderedInRegionsPuppis(); + std::vector intermediateTruncated; + + for (int i = 0, n = in.nPhiRegions; i < n; i++) { + // Each PF region (containing at most 18 puppi candidates) is split in 3(*nPuppiPerClk=18) + for (int j = 0; j < 3; j++) { + std::vector > subregionPuppis = splitPFregions(regionPuppis, i, j); + + // Merge PF regions in pairs + std::vector buffer01 = + mergeXtoY(nPuppiPerClk_, nPuppiFirstBuffers_, subregionPuppis[0], subregionPuppis[1]); + std::vector buffer23 = + mergeXtoY(nPuppiPerClk_, nPuppiFirstBuffers_, subregionPuppis[2], subregionPuppis[3]); + std::vector buffer45 = + mergeXtoY(nPuppiPerClk_, nPuppiFirstBuffers_, subregionPuppis[4], subregionPuppis[5]); + + // Merge 4 first regions together, forward the last 2 + std::vector buffer0123 = + mergeXtoY(nPuppiFirstBuffers_, nPuppiSecondBuffers_, buffer01, buffer23); + std::vector buffer45ext; + accumulateToY(nPuppiSecondBuffers_, buffer45, buffer45ext, intermediateTruncated); + + // Merge all regions together and forward them to the final buffer + std::vector buffer012345 = + mergeXtoY(nPuppiSecondBuffers_, nPuppiThirdBuffers_, buffer0123, buffer45ext); + accumulateToY(nPuppiFinalBuffer_, buffer012345, out, truncated); + + if (debug_) { + dbgCout() << "\n"; + dbgCout() << "Phi region index : " << i << "," << j << "\n"; + + debugPrint("Eta region : 0", subregionPuppis[0]); + debugPrint("Eta region : 1", subregionPuppis[1]); + debugPrint("Eta region : 0+1", buffer01); + dbgCout() << "------------------ " + << "\n"; + + debugPrint("Eta region : 2", subregionPuppis[2]); + debugPrint("Eta region : 3", subregionPuppis[3]); + debugPrint("Eta region : 2+3", buffer23); + dbgCout() << "------------------ " + << "\n"; + + debugPrint("Eta region : 4", subregionPuppis[4]); + debugPrint("Eta region : 5", subregionPuppis[5]); + debugPrint("Eta region : 4+5", buffer45); + dbgCout() << "------------------ " + << "\n"; + + debugPrint("Eta region : 0+1+2+3", buffer0123); + dbgCout() << "------------------ " + << "\n"; + + debugPrint("Eta region : 0+1+2+3+4+5", buffer012345); + dbgCout() << "------------------ " + << "\n"; + + debugPrint("Inclusive", out); + } + } + } + + if (debug_) { + dbgCout() << "\n"; + debugPrint("FINAL ARRAY", out); + dbgCout() << "\n"; + dbgCout() << "Ran successfully!" + << "\n"; + } +} diff --git a/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.h b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.h new file mode 100644 index 0000000000000..d04a4f40f7124 --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/src/newfirmware/deregionizer/deregionizer_ref.h @@ -0,0 +1,52 @@ +#ifndef L1Trigger_Phase2L1ParticleFlow_newfirmware_deregionizer_ref_h +#define L1Trigger_Phase2L1ParticleFlow_newfirmware_deregionizer_ref_h + +#include +#include "deregionizer_input.h" + +namespace edm { + class ParameterSet; +} + +namespace l1ct { + + class DeregionizerEmulator { + public: + DeregionizerEmulator(const unsigned int nPuppiFinalBuffer = 128, + const unsigned int nPuppiPerClk = 6, + const unsigned int nPuppiFirstBuffers = 12, + const unsigned int nPuppiSecondBuffers = 32, + const unsigned int nPuppiThirdBuffers = 64); + + // note: this one will work only in CMSSW + DeregionizerEmulator(const edm::ParameterSet &iConfig); + + ~DeregionizerEmulator(){}; + + void setDebug(bool debug = true) { debug_ = debug; } + + void run(const DeregionizerInput in, + std::vector &out, + std::vector &truncated); + + std::vector > splitPFregions( + const std::vector > > ®ionPuppis, const int i, const int j); + + private: + unsigned int nPuppiFinalBuffer_, nPuppiPerClk_, nPuppiFirstBuffers_, nPuppiSecondBuffers_, nPuppiThirdBuffers_; + bool debug_; + + static std::vector mergeXtoY(const unsigned int X, + const unsigned int Y, + const std::vector &inLeft, + const std::vector &inRight); + + static void accumulateToY(const unsigned int Y, + const std::vector &in, + std::vector &out, + std::vector &truncated); + }; + +} // namespace l1ct + +#endif