Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-10 01:53:52

0001 
0002 #include <vector>
0003 #include <numeric>
0004 
0005 ////////////////////
0006 // FRAMEWORK HEADERS
0007 #include "FWCore/Framework/interface/global/EDProducer.h"
0008 #include "FWCore/Framework/interface/Event.h"
0009 #include "FWCore/Utilities/interface/InputTag.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 
0012 #include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
0013 #include "DataFormats/L1TParticleFlow/interface/PFJet.h"
0014 #include "DataFormats/Math/interface/deltaR.h"
0015 
0016 // bitwise emulation headers
0017 #include "L1Trigger/Phase2L1ParticleFlow/interface/jetmet/L1SeedConePFJetEmulator.h"
0018 #include "DataFormats/L1TParticleFlow/interface/gt_datatypes.h"
0019 
0020 class L1SeedConePFJetProducer : public edm::global::EDProducer<> {
0021 public:
0022   explicit L1SeedConePFJetProducer(const edm::ParameterSet&);
0023   ~L1SeedConePFJetProducer() override;
0024 
0025 private:
0026   /// ///////////////// ///
0027   /// MANDATORY METHODS ///
0028   void produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const override;
0029   /// ///////////////// ///
0030 
0031   float coneSize;
0032   unsigned nJets;
0033   bool HW;
0034   bool debug;
0035   L1SCJetEmu emulator;
0036   edm::EDGetTokenT<std::vector<l1t::PFCandidate>> l1PFToken;
0037 
0038   std::vector<l1t::PFJet> processEvent_SW(std::vector<edm::Ptr<l1t::PFCandidate>>& parts) const;
0039   std::vector<l1t::PFJet> processEvent_HW(std::vector<edm::Ptr<l1t::PFCandidate>>& parts) const;
0040 
0041   l1t::PFJet makeJet_SW(const std::vector<edm::Ptr<l1t::PFCandidate>>& parts) const;
0042 
0043   static std::pair<std::vector<L1SCJetEmu::Particle>,
0044                    std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>>>
0045   convertEDMToHW(std::vector<edm::Ptr<l1t::PFCandidate>>& edmParticles);
0046 
0047   static std::vector<l1t::PFJet> convertHWToEDM(
0048       std::vector<L1SCJetEmu::Jet> hwJets,
0049       std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>> constituentMap);
0050 };
0051 
0052 L1SeedConePFJetProducer::L1SeedConePFJetProducer(const edm::ParameterSet& cfg)
0053     : coneSize(cfg.getParameter<double>("coneSize")),
0054       nJets(cfg.getParameter<unsigned>("nJets")),
0055       HW(cfg.getParameter<bool>("HW")),
0056       debug(cfg.getParameter<bool>("debug")),
0057       emulator(L1SCJetEmu(debug, coneSize, nJets)),
0058       l1PFToken(consumes<std::vector<l1t::PFCandidate>>(cfg.getParameter<edm::InputTag>("L1PFObjects"))) {
0059   produces<l1t::PFJetCollection>();
0060 }
0061 
0062 void L1SeedConePFJetProducer::produce(edm::StreamID /*unused*/,
0063                                       edm::Event& iEvent,
0064                                       const edm::EventSetup& iSetup) const {
0065   std::unique_ptr<l1t::PFJetCollection> newPFJetCollection(new l1t::PFJetCollection);
0066 
0067   edm::Handle<l1t::PFCandidateCollection> l1PFCandidates;
0068   iEvent.getByToken(l1PFToken, l1PFCandidates);
0069 
0070   std::vector<edm::Ptr<l1t::PFCandidate>> particles;
0071   for (unsigned i = 0; i < (*l1PFCandidates).size(); i++) {
0072     particles.push_back(edm::Ptr<l1t::PFCandidate>(l1PFCandidates, i));
0073   }
0074 
0075   std::vector<l1t::PFJet> jets;
0076   if (HW) {
0077     jets = processEvent_HW(particles);
0078   } else {
0079     jets = processEvent_SW(particles);
0080   }
0081 
0082   std::sort(jets.begin(), jets.end(), [](l1t::PFJet i, l1t::PFJet j) { return (i.pt() > j.pt()); });
0083   newPFJetCollection->swap(jets);
0084   iEvent.put(std::move(newPFJetCollection));
0085 }
0086 
0087 /////////////
0088 // DESTRUCTOR
0089 L1SeedConePFJetProducer::~L1SeedConePFJetProducer() {}
0090 
0091 l1t::PFJet L1SeedConePFJetProducer::makeJet_SW(const std::vector<edm::Ptr<l1t::PFCandidate>>& parts) const {
0092   l1t::PFCandidate seed = *parts.at(0);
0093 
0094   auto sumpt = [](float a, const edm::Ptr<l1t::PFCandidate>& b) { return a + b->pt(); };
0095 
0096   // Sum the pt
0097   float pt = std::accumulate(parts.begin(), parts.end(), 0., sumpt);
0098 
0099   // pt weighted d eta
0100   std::vector<float> pt_deta;
0101   pt_deta.resize(parts.size());
0102   std::transform(parts.begin(), parts.end(), pt_deta.begin(), [&seed, &pt](const edm::Ptr<l1t::PFCandidate>& part) {
0103     return (part->pt() / pt) * (part->eta() - seed.eta());
0104   });
0105   // Accumulate the pt weighted etas. Init to the seed eta, start accumulating at begin()+1 to skip seed
0106   float eta = std::accumulate(pt_deta.begin() + 1, pt_deta.end(), seed.eta());
0107 
0108   // pt weighted d phi
0109   std::vector<float> pt_dphi;
0110   pt_dphi.resize(parts.size());
0111   std::transform(parts.begin(), parts.end(), pt_dphi.begin(), [&seed, &pt](const edm::Ptr<l1t::PFCandidate>& part) {
0112     return (part->pt() / pt) * reco::deltaPhi(part->phi(), seed.phi());
0113   });
0114   // Accumulate the pt weighted phis. Init to the seed phi, start accumulating at begin()+1 to skip seed
0115   float phi = std::accumulate(pt_dphi.begin() + 1, pt_dphi.end(), seed.phi());
0116 
0117   l1t::PFJet jet(pt, eta, phi);
0118   for (auto it = parts.begin(); it != parts.end(); it++) {
0119     jet.addConstituent(*it);
0120   }
0121 
0122   return jet;
0123 }
0124 
0125 std::vector<l1t::PFJet> L1SeedConePFJetProducer::processEvent_SW(std::vector<edm::Ptr<l1t::PFCandidate>>& work) const {
0126   // The floating point algorithm simulation
0127   std::stable_sort(work.begin(), work.end(), [](edm::Ptr<l1t::PFCandidate> i, edm::Ptr<l1t::PFCandidate> j) {
0128     return (i->pt() > j->pt());
0129   });
0130   std::vector<l1t::PFJet> jets;
0131   jets.reserve(nJets);
0132   while (!work.empty() && jets.size() < nJets) {
0133     // Take the first (highest pt) candidate as a seed
0134     edm::Ptr<l1t::PFCandidate> seed = work.at(0);
0135     // Get the particles within a _coneSize of the seed
0136     std::vector<edm::Ptr<l1t::PFCandidate>> particlesInCone;
0137     std::copy_if(
0138         work.begin(), work.end(), std::back_inserter(particlesInCone), [&](const edm::Ptr<l1t::PFCandidate>& part) {
0139           return reco::deltaR<l1t::PFCandidate, l1t::PFCandidate>(*seed, *part) <= coneSize;
0140         });
0141     jets.push_back(makeJet_SW(particlesInCone));
0142     // remove the clustered particles
0143     work.erase(std::remove_if(work.begin(),
0144                               work.end(),
0145                               [&](const edm::Ptr<l1t::PFCandidate>& part) {
0146                                 return reco::deltaR<l1t::PFCandidate, l1t::PFCandidate>(*seed, *part) <= coneSize;
0147                               }),
0148                work.end());
0149   }
0150   return jets;
0151 }
0152 
0153 std::vector<l1t::PFJet> L1SeedConePFJetProducer::processEvent_HW(std::vector<edm::Ptr<l1t::PFCandidate>>& work) const {
0154   // The fixed point emulator
0155   // Convert the EDM format to the hardware format, and call the standalone emulator
0156   std::pair<std::vector<L1SCJetEmu::Particle>, std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>>>
0157       particles = convertEDMToHW(work);
0158   std::vector<L1SCJetEmu::Jet> jets = emulator.emulateEvent(particles.first);
0159   return convertHWToEDM(jets, particles.second);
0160 }
0161 
0162 std::pair<std::vector<L1SCJetEmu::Particle>, std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>>>
0163 L1SeedConePFJetProducer::convertEDMToHW(std::vector<edm::Ptr<l1t::PFCandidate>>& edmParticles) {
0164   std::vector<l1ct::PuppiObjEmu> hwParticles;
0165   std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>> candidateMap;
0166   std::for_each(edmParticles.begin(), edmParticles.end(), [&](edm::Ptr<l1t::PFCandidate>& edmParticle) {
0167     l1ct::PuppiObjEmu particle;
0168     particle.initFromBits(edmParticle->encodedPuppi64());
0169     particle.srcCand = edmParticle.get();
0170     candidateMap.insert(std::make_pair(edmParticle.get(), edmParticle));
0171     hwParticles.push_back(particle);
0172   });
0173   return std::make_pair(hwParticles, candidateMap);
0174 }
0175 
0176 std::vector<l1t::PFJet> L1SeedConePFJetProducer::convertHWToEDM(
0177     std::vector<L1SCJetEmu::Jet> hwJets,
0178     std::unordered_map<const l1t::PFCandidate*, edm::Ptr<l1t::PFCandidate>> constituentMap) {
0179   std::vector<l1t::PFJet> edmJets;
0180   std::for_each(hwJets.begin(), hwJets.end(), [&](L1SCJetEmu::Jet jet) {
0181     l1t::PFJet edmJet(
0182         jet.floatPt(), jet.floatEta(), jet.floatPhi(), /*mass=*/0., jet.intPt(), jet.intEta(), jet.intPhi());
0183     // get back the references to the constituents
0184     std::vector<edm::Ptr<l1t::PFCandidate>> constituents;
0185     std::for_each(jet.constituents.begin(), jet.constituents.end(), [&](auto constituent) {
0186       edmJet.addConstituent(constituentMap[constituent.srcCand]);
0187     });
0188     l1gt::Jet gtJet = jet.toGT();
0189     edmJet.setEncodedJet(jet.toGT().pack());
0190     edmJets.push_back(edmJet);
0191   });
0192   return edmJets;
0193 }
0194 
0195 #include "FWCore/Framework/interface/MakerMacros.h"
0196 DEFINE_FWK_MODULE(L1SeedConePFJetProducer);