Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:26:31

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