Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-06-22 02:24:06

0001 /** \class PFLinker
0002  *  Producer meant for the Post PF reconstruction.
0003  *
0004  *  Fills the GsfElectron, Photon and Muon Ref into the PFCandidate
0005  *  Produces the ValueMap between GsfElectronRef/Photon/Mupns with PFCandidateRef
0006  *
0007  *  \author R. Bellan - UCSB <riccardo.bellan@cern.ch>, F. Beaudette - CERN <Florian.Beaudette@cern.ch>
0008  */
0009 
0010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0011 #include "DataFormats/EgammaCandidates/interface/Photon.h"
0012 #include "FWCore/Framework/interface/stream/EDProducer.h"
0013 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0014 #include "FWCore/Framework/interface/Event.h"
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "DataFormats/Common/interface/ValueMap.h"
0017 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0018 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
0019 #include "DataFormats/MuonReco/interface/MuonToMuonMap.h"
0020 
0021 namespace edm {
0022   class EventSetup;
0023 }  // namespace edm
0024 
0025 class PFLinker : public edm::stream::EDProducer<> {
0026 public:
0027   explicit PFLinker(const edm::ParameterSet&);
0028 
0029   ~PFLinker() override;
0030 
0031   void produce(edm::Event&, const edm::EventSetup&) override;
0032   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0033 
0034 private:
0035   template <typename TYPE>
0036   edm::ValueMap<reco::PFCandidatePtr> fillValueMap(
0037       edm::Event& event,
0038       std::string label,
0039       edm::Handle<TYPE>& inputObjCollection,
0040       const std::map<edm::Ref<TYPE>, reco::PFCandidatePtr>& mapToTheCandidate,
0041       const edm::OrphanHandle<reco::PFCandidateCollection>& newPFCandColl) const;
0042 
0043 private:
0044   /// Input PFCandidates
0045   std::vector<edm::EDGetTokenT<reco::PFCandidateCollection>> inputTagPFCandidates_;
0046 
0047   /// Input GsfElectrons
0048   edm::EDGetTokenT<reco::GsfElectronCollection> inputTagGsfElectrons_;
0049 
0050   /// Input Photons
0051   edm::EDGetTokenT<reco::PhotonCollection> inputTagPhotons_;
0052 
0053   /// Input Muons
0054   edm::InputTag muonTag_;
0055   edm::EDGetTokenT<reco::MuonCollection> inputTagMuons_;
0056   edm::EDGetTokenT<reco::MuonToMuonMap> inputTagMuonMap_;
0057   /// name of output collection of PFCandidate
0058   std::string nameOutputPF_;
0059 
0060   /// name of output ValueMap electrons
0061   std::string nameOutputElectronsPF_;
0062 
0063   /// name of output ValueMap photons
0064   std::string nameOutputPhotonsPF_;
0065 
0066   /// name of output merged ValueMap
0067   std::string nameOutputMergedPF_;
0068 
0069   /// Flags - if true: References will be towards new collection ; if false to the original one
0070   bool producePFCandidates_;
0071 
0072   /// Set muon refs and produce the value map?
0073   bool fillMuonRefs_;
0074 
0075   /// Put Electrons within HGCAL coming from SimPFProducer
0076   bool forceElectronsInHGCAL_;
0077 };
0078 
0079 DEFINE_FWK_MODULE(PFLinker);
0080 
0081 void PFLinker::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0082   edm::ParameterSetDescription desc;
0083   desc.add<std::vector<edm::InputTag>>("PFCandidate", {edm::InputTag("particleFlow")});
0084   desc.add<edm::InputTag>("GsfElectrons", {"gedGsfElectrons"});
0085   desc.add<edm::InputTag>("Photons", {"gedPhotons"});
0086   desc.add<edm::InputTag>("Muons", {"muons", "muons1stStep2muonsMap"});
0087   desc.add<bool>("ProducePFCandidates", true);
0088   desc.add<bool>("FillMuonRefs", true);
0089   desc.add<std::string>("OutputPF", "");
0090   desc.add<std::string>("ValueMapElectrons", "electrons");
0091   desc.add<std::string>("ValueMapPhotons", "photons");
0092   desc.add<std::string>("ValueMapMerged", "all");
0093   desc.add<bool>("forceElectronsInHGCAL", false);
0094   descriptions.addWithDefaultLabel(desc);
0095 }
0096 
0097 PFLinker::PFLinker(const edm::ParameterSet& iConfig) {
0098   // vector of InputTag; more than 1 is not for RECO, it is for analysis
0099 
0100   std::vector<edm::InputTag> tags = iConfig.getParameter<std::vector<edm::InputTag>>("PFCandidate");
0101   for (unsigned int i = 0; i < tags.size(); ++i)
0102     inputTagPFCandidates_.push_back(consumes<reco::PFCandidateCollection>(tags[i]));
0103 
0104   inputTagGsfElectrons_ = consumes<reco::GsfElectronCollection>(iConfig.getParameter<edm::InputTag>("GsfElectrons"));
0105 
0106   inputTagPhotons_ = consumes<reco::PhotonCollection>(iConfig.getParameter<edm::InputTag>("Photons"));
0107 
0108   muonTag_ = iConfig.getParameter<edm::InputTag>("Muons");
0109   inputTagMuons_ = consumes<reco::MuonCollection>(edm::InputTag(muonTag_.label()));
0110   inputTagMuonMap_ = consumes<reco::MuonToMuonMap>(muonTag_);
0111 
0112   nameOutputPF_ = iConfig.getParameter<std::string>("OutputPF");
0113 
0114   nameOutputElectronsPF_ = iConfig.getParameter<std::string>("ValueMapElectrons");
0115 
0116   nameOutputPhotonsPF_ = iConfig.getParameter<std::string>("ValueMapPhotons");
0117 
0118   producePFCandidates_ = iConfig.getParameter<bool>("ProducePFCandidates");
0119 
0120   nameOutputMergedPF_ = iConfig.getParameter<std::string>("ValueMapMerged");
0121 
0122   fillMuonRefs_ = iConfig.getParameter<bool>("FillMuonRefs");
0123 
0124   forceElectronsInHGCAL_ = iConfig.getParameter<bool>("forceElectronsInHGCAL");
0125 
0126   // should not produce PFCandidates and read seve
0127   if (producePFCandidates_ && inputTagPFCandidates_.size() > 1) {
0128     edm::LogError("PFLinker")
0129         << " cannot read several collections of PFCandidates and produce a new collection at the same time. "
0130         << std::endl;
0131     assert(false);
0132   }
0133   if (producePFCandidates_) {
0134     produces<reco::PFCandidateCollection>(nameOutputPF_);
0135   }
0136   produces<edm::ValueMap<reco::PFCandidatePtr>>(nameOutputElectronsPF_);
0137   produces<edm::ValueMap<reco::PFCandidatePtr>>(nameOutputPhotonsPF_);
0138   produces<edm::ValueMap<reco::PFCandidatePtr>>(nameOutputMergedPF_);
0139   if (fillMuonRefs_)
0140     produces<edm::ValueMap<reco::PFCandidatePtr>>(muonTag_.label());
0141 }
0142 
0143 PFLinker::~PFLinker() { ; }
0144 
0145 void PFLinker::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0146   auto pfCandidates_p = std::make_unique<reco::PFCandidateCollection>();
0147 
0148   auto gsfElectrons = iEvent.getHandle(inputTagGsfElectrons_);
0149 
0150   std::map<reco::GsfElectronRef, reco::PFCandidatePtr> electronCandidateMap;
0151 
0152   auto photons = iEvent.getHandle(inputTagPhotons_);
0153   std::map<reco::PhotonRef, reco::PFCandidatePtr> photonCandidateMap;
0154 
0155   edm::Handle<reco::MuonToMuonMap> muonMap;
0156   if (fillMuonRefs_)
0157     muonMap = iEvent.getHandle(inputTagMuonMap_);
0158   std::map<reco::MuonRef, reco::PFCandidatePtr> muonCandidateMap;
0159 
0160   unsigned nColPF = inputTagPFCandidates_.size();
0161 
0162   for (unsigned icol = 0; icol < nColPF; ++icol) {
0163     auto pfCandidates = iEvent.getHandle(inputTagPFCandidates_[icol]);
0164     unsigned ncand = pfCandidates->size();
0165 
0166     for (unsigned i = 0; i < ncand; ++i) {
0167       edm::Ptr<reco::PFCandidate> candPtr(pfCandidates, i);
0168       reco::PFCandidate cand(candPtr);
0169 
0170       bool isphoton = cand.particleId() == reco::PFCandidate::gamma && cand.mva_nothing_gamma() > 0.;
0171       bool iselectron = cand.particleId() == reco::PFCandidate::e;
0172       // PFCandidates may have a valid MuonRef though they are not muons.
0173       bool hasNonNullMuonRef = cand.muonRef().isNonnull() && fillMuonRefs_;
0174 
0175       // if not an electron or a photon or a muon just fill the PFCandidate collection
0176       if (!(isphoton || iselectron || hasNonNullMuonRef)) {
0177         pfCandidates_p->push_back(cand);
0178         continue;
0179       }
0180 
0181       if (hasNonNullMuonRef) {
0182         reco::MuonRef muRef = (*muonMap)[cand.muonRef()];
0183         cand.setMuonRef(muRef);
0184         muonCandidateMap[muRef] = candPtr;
0185       }
0186 
0187       // if it is an electron. Find the GsfElectron with the same GsfTrack
0188       if (iselectron) {
0189         const reco::GsfTrackRef& gsfTrackRef(cand.gsfTrackRef());
0190         auto itcheck = find_if(gsfElectrons->begin(), gsfElectrons->end(), [&gsfTrackRef](const auto& ele) {
0191           return (ele.gsfTrack() == gsfTrackRef);
0192         });
0193         if (itcheck == gsfElectrons->end()) {
0194           if (!forceElectronsInHGCAL_) {
0195             std::ostringstream err;
0196             err << " Problem in PFLinker: no GsfElectron " << std::endl;
0197             edm::LogError("PFLinker") << err.str();
0198           } else {
0199             LogDebug("PFLinker") << "Forcing an electron pfCandidate at: " << cand.eta() << " in HGCAL" << std::endl;
0200             pfCandidates_p->push_back(cand);
0201           }
0202           continue;  // Watch out ! Continue
0203         }
0204         reco::GsfElectronRef electronRef(gsfElectrons, itcheck - gsfElectrons->begin());
0205         cand.setGsfElectronRef(electronRef);
0206         cand.setSuperClusterRef(electronRef->superCluster());
0207         // update energy information since now it is done post-particleFlowTmp
0208         cand.setEcalEnergy(electronRef->superCluster()->rawEnergy(), electronRef->ecalEnergy());
0209         cand.setDeltaP(electronRef->p4Error(reco::GsfElectron::P4_COMBINATION));
0210         cand.setP4(electronRef->p4(reco::GsfElectron::P4_COMBINATION));
0211         electronCandidateMap[electronRef] = candPtr;
0212       }
0213 
0214       // if it is a photon, find the one with the same PF super-cluster
0215       if (isphoton) {
0216         const reco::SuperClusterRef& scRef(cand.superClusterRef());
0217         auto itcheck = find_if(
0218             photons->begin(), photons->end(), [&scRef](const auto& photon) { return photon.superCluster() == scRef; });
0219         if (itcheck == photons->end()) {
0220           std::ostringstream err;
0221           err << " Problem in PFLinker: no Photon " << std::endl;
0222           edm::LogError("PFLinker") << err.str();
0223           continue;  // Watch out ! Continue
0224         }
0225         reco::PhotonRef photonRef(photons, itcheck - photons->begin());
0226         cand.setPhotonRef(photonRef);
0227         cand.setSuperClusterRef(photonRef->superCluster());
0228         // update energy information since now it is done post-particleFlowTmp
0229         cand.setEcalEnergy(photonRef->superCluster()->rawEnergy(),
0230                            photonRef->getCorrectedEnergy(reco::Photon::regression2));
0231         cand.setDeltaP(photonRef->getCorrectedEnergyError(reco::Photon::regression2));
0232         cand.setP4(photonRef->p4(reco::Photon::regression2));
0233         photonCandidateMap[photonRef] = candPtr;
0234       }
0235 
0236       pfCandidates_p->push_back(cand);
0237     }
0238     // save the PFCandidates and get a valid handle
0239   }
0240   const edm::OrphanHandle<reco::PFCandidateCollection> pfCandidateRefProd =
0241       (producePFCandidates_) ? iEvent.put(std::move(pfCandidates_p), nameOutputPF_)
0242                              : edm::OrphanHandle<reco::PFCandidateCollection>();
0243 
0244   // now make the valuemaps
0245 
0246   edm::ValueMap<reco::PFCandidatePtr> pfMapGsfElectrons = fillValueMap<reco::GsfElectronCollection>(
0247       iEvent, nameOutputElectronsPF_, gsfElectrons, electronCandidateMap, pfCandidateRefProd);
0248 
0249   edm::ValueMap<reco::PFCandidatePtr> pfMapPhotons = fillValueMap<reco::PhotonCollection>(
0250       iEvent, nameOutputPhotonsPF_, photons, photonCandidateMap, pfCandidateRefProd);
0251 
0252   edm::ValueMap<reco::PFCandidatePtr> pfMapMuons;
0253 
0254   if (fillMuonRefs_) {
0255     auto muons = iEvent.getHandle(inputTagMuons_);
0256 
0257     pfMapMuons =
0258         fillValueMap<reco::MuonCollection>(iEvent, muonTag_.label(), muons, muonCandidateMap, pfCandidateRefProd);
0259   }
0260 
0261   auto pfMapMerged = std::make_unique<edm::ValueMap<reco::PFCandidatePtr>>();
0262   edm::ValueMap<reco::PFCandidatePtr>::Filler pfMapMergedFiller(*pfMapMerged);
0263 
0264   *pfMapMerged += pfMapGsfElectrons;
0265   *pfMapMerged += pfMapPhotons;
0266   if (fillMuonRefs_)
0267     *pfMapMerged += pfMapMuons;
0268 
0269   iEvent.put(std::move(pfMapMerged), nameOutputMergedPF_);
0270 }
0271 
0272 template <typename TYPE>
0273 edm::ValueMap<reco::PFCandidatePtr> PFLinker::fillValueMap(
0274     edm::Event& event,
0275     std::string label,
0276     edm::Handle<TYPE>& inputObjCollection,
0277     const std::map<edm::Ref<TYPE>, reco::PFCandidatePtr>& mapToTheCandidate,
0278     const edm::OrphanHandle<reco::PFCandidateCollection>& newPFCandColl) const {
0279   auto pfMap_p = std::make_unique<edm::ValueMap<reco::PFCandidatePtr>>();
0280   edm::ValueMap<reco::PFCandidatePtr>::Filler filler(*pfMap_p);
0281 
0282   typedef typename std::map<edm::Ref<TYPE>, reco::PFCandidatePtr>::const_iterator MapTYPE_it;
0283 
0284   unsigned nObj = inputObjCollection->size();
0285   std::vector<reco::PFCandidatePtr> values(nObj);
0286 
0287   for (unsigned iobj = 0; iobj < nObj; ++iobj) {
0288     edm::Ref<TYPE> objRef(inputObjCollection, iobj);
0289     MapTYPE_it itcheck = mapToTheCandidate.find(objRef);
0290 
0291     reco::PFCandidatePtr candPtr;
0292 
0293     if (itcheck != mapToTheCandidate.end())
0294       candPtr = producePFCandidates_ ? reco::PFCandidatePtr(newPFCandColl, itcheck->second.key()) : itcheck->second;
0295 
0296     values[iobj] = candPtr;
0297   }
0298 
0299   filler.insert(inputObjCollection, values.begin(), values.end());
0300   filler.fill();
0301   edm::ValueMap<reco::PFCandidatePtr> returnValue = *pfMap_p;
0302   event.put(std::move(pfMap_p), label);
0303   return returnValue;
0304 }