Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:21:11

0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 #include "FWCore/Framework/interface/Event.h"
0003 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0004 #include "CommonTools/ParticleFlow/interface/PFClusterWidthAlgo.h"
0005 #include "RecoEcal/EgammaCoreTools/interface/Mustache.h"
0006 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0007 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateElectronExtra.h"
0008 #include "DataFormats/EgammaReco/interface/PreshowerCluster.h"
0009 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
0010 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
0011 #include "DataFormats/EgammaCandidates/interface/GsfElectronCore.h"
0012 #include "DataFormats/ParticleFlowReco/interface/PFBlockElement.h"
0013 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementGsfTrack.h"
0014 #include "FWCore/Framework/interface/stream/EDProducer.h"
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "DataFormats/Common/interface/ValueMap.h"
0017 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
0018 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
0019 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
0020 #include "CondFormats/EcalObjects/interface/EcalMustacheSCParameters.h"
0021 #include "CondFormats/DataRecord/interface/EcalMustacheSCParametersRcd.h"
0022 
0023 class DetId;
0024 namespace edm {
0025   class EventSetup;
0026 }  // namespace edm
0027 
0028 class PFElectronTranslator : public edm::stream::EDProducer<> {
0029 public:
0030   explicit PFElectronTranslator(const edm::ParameterSet&);
0031   ~PFElectronTranslator() override;
0032 
0033   void produce(edm::Event&, const edm::EventSetup&) override;
0034 
0035   typedef std::vector<edm::Handle<edm::ValueMap<double>>> IsolationValueMaps;
0036 
0037 private:
0038   // to retrieve the collection from the event
0039   bool fetchCandidateCollection(edm::Handle<reco::PFCandidateCollection>& c,
0040                                 const edm::InputTag& tag,
0041                                 const edm::Event& iEvent) const;
0042   // to retrieve the collection from the event
0043   void fetchGsfCollection(edm::Handle<reco::GsfTrackCollection>& c,
0044                           const edm::InputTag& tag,
0045                           const edm::Event& iEvent) const;
0046 
0047   // makes a basic cluster from PFBlockElement and add it to the collection ; the corrected energy is taken
0048   // from the PFCandidate
0049   void createBasicCluster(const reco::PFBlockElement&,
0050                           reco::BasicClusterCollection& basicClusters,
0051                           std::vector<const reco::PFCluster*>&,
0052                           const reco::PFCandidate& coCandidate) const;
0053   // makes a preshower cluster from of PFBlockElement and add it to the collection
0054   void createPreshowerCluster(const reco::PFBlockElement& PFBE,
0055                               reco::PreshowerClusterCollection& preshowerClusters,
0056                               unsigned plane) const;
0057 
0058   // make a super cluster from its ingredients and add it to the collection
0059   void createSuperClusters(const reco::PFCandidateCollection&, reco::SuperClusterCollection& superClusters) const;
0060 
0061   // make GsfElectronCores from ingredients
0062   void createGsfElectronCores(reco::GsfElectronCoreCollection&) const;
0063 
0064   // create the basic cluster Ptr
0065   void createBasicClusterPtrs(const edm::OrphanHandle<reco::BasicClusterCollection>& basicClustersHandle);
0066 
0067   // create the preshower cluster Refs
0068   void createPreshowerClusterPtrs(const edm::OrphanHandle<reco::PreshowerClusterCollection>& preshowerClustersHandle);
0069 
0070   // create the super cluster Refs
0071   void createSuperClusterGsfMapRefs(const edm::OrphanHandle<reco::SuperClusterCollection>& superClustersHandle);
0072 
0073   // create the GsfElectronCore Refs
0074   void createGsfElectronCoreRefs(const edm::OrphanHandle<reco::GsfElectronCoreCollection>& gsfElectronCoreHandle);
0075 
0076   // create the GsfElectrons
0077   void createGsfElectrons(const reco::PFCandidateCollection&,
0078                           const IsolationValueMaps& isolationValues,
0079                           reco::GsfElectronCollection&);
0080 
0081   // The following methods are used to fill the value maps
0082   void fillMVAValueMap(edm::Event& iEvent, edm::ValueMap<float>::Filler& filler);
0083   void fillValueMap(edm::Event& iEvent, edm::ValueMap<float>::Filler& filler) const;
0084   void fillSCRefValueMap(edm::Event& iEvent, edm::ValueMap<reco::SuperClusterRef>::Filler& filler) const;
0085   void getAmbiguousGsfTracks(const reco::PFBlockElement& PFBE, std::vector<reco::GsfTrackRef>&) const;
0086 
0087   const reco::PFCandidate& correspondingDaughterCandidate(const reco::PFCandidate& cand,
0088                                                           const reco::PFBlockElement& pfbe) const;
0089 
0090 private:
0091   edm::InputTag inputTagPFCandidates_;
0092   edm::InputTag inputTagPFCandidateElectrons_;
0093   edm::InputTag inputTagGSFTracks_;
0094   std::vector<edm::InputTag> inputTagIsoVals_;
0095   std::string PFBasicClusterCollection_;
0096   std::string PFPreshowerClusterCollection_;
0097   std::string PFSuperClusterCollection_;
0098   std::string PFMVAValueMap_;
0099   std::string PFSCValueMap_;
0100   std::string GsfElectronCoreCollection_;
0101   std::string GsfElectronCollection_;
0102   double MVACut_;
0103   bool checkStatusFlag_;
0104 
0105   // The following vectors correspond to a GSF track, but the order is not
0106   // the order of the tracks in the GSF track collection
0107   std::vector<reco::GsfTrackRef> GsfTrackRef_;
0108   // the list of candidatePtr
0109   std::vector<reco::CandidatePtr> CandidatePtr_;
0110   //the list of KfTrackRef
0111   std::vector<reco::TrackRef> kfTrackRef_;
0112   // the list of ambiguous tracks
0113   std::vector<std::vector<reco::GsfTrackRef>> ambiguousGsfTracks_;
0114   // the collection of basic clusters associated to a GSF track
0115   std::vector<reco::BasicClusterCollection> basicClusters_;
0116   // the correcsponding PFCluster ref
0117   std::vector<std::vector<const reco::PFCluster*>> pfClusters_;
0118   // the collection of preshower clusters associated to a GSF track
0119   std::vector<reco::PreshowerClusterCollection> preshowerClusters_;
0120   // the super cluster collection (actually only one) associated to a GSF track
0121   std::vector<reco::SuperClusterCollection> superClusters_;
0122   // the references to the basic clusters associated to a GSF track
0123   std::vector<reco::CaloClusterPtrVector> basicClusterPtr_;
0124   // the references to the basic clusters associated to a GSF track
0125   std::vector<reco::CaloClusterPtrVector> preshowerClusterPtr_;
0126   // the references to the GsfElectonCore associated to a GSF track
0127   std::vector<reco::GsfElectronCoreRef> gsfElectronCoreRefs_;
0128   // keep track of the index of the PF Candidate
0129   std::vector<int> gsfPFCandidateIndex_;
0130   // maps to ease the creation of the Value Maps
0131   std::map<reco::GsfTrackRef, reco::SuperClusterRef> scMap_;
0132   std::map<reco::GsfTrackRef, float> gsfMvaMap_;
0133 
0134   // Mustache SC parameters
0135   edm::ESGetToken<EcalMustacheSCParameters, EcalMustacheSCParametersRcd> ecalMustacheSCParametersToken_;
0136   const EcalMustacheSCParameters* mustacheSCParams_;
0137 
0138   bool emptyIsOk_;
0139 };
0140 
0141 DEFINE_FWK_MODULE(PFElectronTranslator);
0142 
0143 PFElectronTranslator::PFElectronTranslator(const edm::ParameterSet& iConfig) {
0144   inputTagPFCandidates_ = iConfig.getParameter<edm::InputTag>("PFCandidate");
0145   inputTagPFCandidateElectrons_ = iConfig.getParameter<edm::InputTag>("PFCandidateElectron");
0146   inputTagGSFTracks_ = iConfig.getParameter<edm::InputTag>("GSFTracks");
0147 
0148   bool useIsolationValues = iConfig.getParameter<bool>("useIsolationValues");
0149   if (useIsolationValues) {
0150     if (!iConfig.exists("isolationValues"))
0151       throw cms::Exception("PFElectronTranslator|InternalError") << "Missing ParameterSet isolationValues";
0152     else {
0153       edm::ParameterSet isoVals = iConfig.getParameter<edm::ParameterSet>("isolationValues");
0154       inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfSumChargedHadronPt"));
0155       inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfSumPhotonEt"));
0156       inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfSumNeutralHadronEt"));
0157       inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfSumPUPt"));
0158     }
0159   }
0160 
0161   PFBasicClusterCollection_ = iConfig.getParameter<std::string>("PFBasicClusters");
0162   PFPreshowerClusterCollection_ = iConfig.getParameter<std::string>("PFPreshowerClusters");
0163   PFSuperClusterCollection_ = iConfig.getParameter<std::string>("PFSuperClusters");
0164   GsfElectronCoreCollection_ = iConfig.getParameter<std::string>("PFGsfElectronCore");
0165   GsfElectronCollection_ = iConfig.getParameter<std::string>("PFGsfElectron");
0166 
0167   PFMVAValueMap_ = iConfig.getParameter<std::string>("ElectronMVA");
0168   PFSCValueMap_ = iConfig.getParameter<std::string>("ElectronSC");
0169   MVACut_ = (iConfig.getParameter<edm::ParameterSet>("MVACutBlock")).getParameter<double>("MVACut");
0170   checkStatusFlag_ = iConfig.getParameter<bool>("CheckStatusFlag");
0171 
0172   if (iConfig.exists("emptyIsOk"))
0173     emptyIsOk_ = iConfig.getParameter<bool>("emptyIsOk");
0174   else
0175     emptyIsOk_ = false;
0176 
0177   ecalMustacheSCParametersToken_ = esConsumes<EcalMustacheSCParameters, EcalMustacheSCParametersRcd>();
0178 
0179   produces<reco::BasicClusterCollection>(PFBasicClusterCollection_);
0180   produces<reco::PreshowerClusterCollection>(PFPreshowerClusterCollection_);
0181   produces<reco::SuperClusterCollection>(PFSuperClusterCollection_);
0182   produces<reco::GsfElectronCoreCollection>(GsfElectronCoreCollection_);
0183   produces<reco::GsfElectronCollection>(GsfElectronCollection_);
0184   produces<edm::ValueMap<float>>(PFMVAValueMap_);
0185   produces<edm::ValueMap<reco::SuperClusterRef>>(PFSCValueMap_);
0186 }
0187 
0188 PFElectronTranslator::~PFElectronTranslator() {}
0189 
0190 void PFElectronTranslator::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0191   mustacheSCParams_ = &iSetup.getData(ecalMustacheSCParametersToken_);
0192 
0193   auto gsfElectronCores_p = std::make_unique<reco::GsfElectronCoreCollection>();
0194 
0195   auto gsfElectrons_p = std::make_unique<reco::GsfElectronCollection>();
0196 
0197   auto superClusters_p = std::make_unique<reco::SuperClusterCollection>();
0198 
0199   auto basicClusters_p = std::make_unique<reco::BasicClusterCollection>();
0200 
0201   auto psClusters_p = std::make_unique<reco::PreshowerClusterCollection>();
0202 
0203   auto mvaMap_p = std::make_unique<edm::ValueMap<float>>();
0204   edm::ValueMap<float>::Filler mvaFiller(*mvaMap_p);
0205 
0206   auto scMap_p = std::make_unique<edm::ValueMap<reco::SuperClusterRef>>();
0207   edm::ValueMap<reco::SuperClusterRef>::Filler scRefFiller(*scMap_p);
0208 
0209   edm::Handle<reco::PFCandidateCollection> pfCandidates;
0210   bool status = fetchCandidateCollection(pfCandidates, inputTagPFCandidates_, iEvent);
0211 
0212   IsolationValueMaps isolationValues(inputTagIsoVals_.size());
0213   for (size_t j = 0; j < inputTagIsoVals_.size(); ++j) {
0214     iEvent.getByLabel(inputTagIsoVals_[j], isolationValues[j]);
0215   }
0216 
0217   // clear the vectors
0218   GsfTrackRef_.clear();
0219   CandidatePtr_.clear();
0220   ambiguousGsfTracks_.clear();
0221   kfTrackRef_.clear();
0222   basicClusters_.clear();
0223   pfClusters_.clear();
0224   preshowerClusters_.clear();
0225   superClusters_.clear();
0226   basicClusterPtr_.clear();
0227   preshowerClusterPtr_.clear();
0228   gsfPFCandidateIndex_.clear();
0229   gsfElectronCoreRefs_.clear();
0230   scMap_.clear();
0231 
0232   // loop on the candidates
0233   //CC@@
0234   // we need first to create AND put the SuperCluster,
0235   // basic clusters and presh clusters collection
0236   // in order to get a working Handle
0237   unsigned ncand = (status) ? pfCandidates->size() : 0;
0238   unsigned iGSF = 0;
0239   for (unsigned i = 0; i < ncand; ++i) {
0240     const reco::PFCandidate& cand = (*pfCandidates)[i];
0241     if (cand.particleId() != reco::PFCandidate::e)
0242       continue;
0243     if (cand.gsfTrackRef().isNull())
0244       continue;
0245     // Note that -1 will still cut some total garbage candidates
0246     // Fill the MVA map
0247     if (cand.mva_e_pi() < MVACut_)
0248       continue;
0249 
0250     // Check the status flag
0251     if (checkStatusFlag_ && !cand.electronExtraRef()->electronStatus(reco::PFCandidateElectronExtra::Selected)) {
0252       continue;
0253     }
0254 
0255     GsfTrackRef_.push_back(cand.gsfTrackRef());
0256     kfTrackRef_.push_back(cand.trackRef());
0257     gsfPFCandidateIndex_.push_back(i);
0258 
0259     reco::PFCandidatePtr ptrToPFElectron(pfCandidates, i);
0260     //CandidatePtr_.push_back(ptrToPFElectron->sourceCandidatePtr(0));
0261     CandidatePtr_.push_back(ptrToPFElectron);
0262 
0263     basicClusters_.push_back(reco::BasicClusterCollection());
0264     pfClusters_.push_back(std::vector<const reco::PFCluster*>());
0265     preshowerClusters_.push_back(reco::PreshowerClusterCollection());
0266     ambiguousGsfTracks_.push_back(std::vector<reco::GsfTrackRef>());
0267 
0268     for (unsigned iele = 0; iele < cand.elementsInBlocks().size(); ++iele) {
0269       // first get the block
0270       reco::PFBlockRef blockRef = cand.elementsInBlocks()[iele].first;
0271       //
0272       unsigned elementIndex = cand.elementsInBlocks()[iele].second;
0273       // check it actually exists
0274       if (blockRef.isNull())
0275         continue;
0276 
0277       // then get the elements of the block
0278       const edm::OwnVector<reco::PFBlockElement>& elements = (*blockRef).elements();
0279 
0280       const reco::PFBlockElement& pfbe(elements[elementIndex]);
0281       // The first ECAL element should be the cluster associated to the GSF; defined as the seed
0282       if (pfbe.type() == reco::PFBlockElement::ECAL) {
0283         //    const reco::PFCandidate * coCandidate = &cand;
0284         // the Brem photons are saved as daughter PFCandidate; this
0285         // is convenient to access the corrected energy
0286         //    std::cout << " Found candidate "  << correspondingDaughterCandidate(coCandidate,pfbe) << " " << coCandidate << std::endl;
0287         createBasicCluster(pfbe, basicClusters_[iGSF], pfClusters_[iGSF], correspondingDaughterCandidate(cand, pfbe));
0288       }
0289       if (pfbe.type() == reco::PFBlockElement::PS1) {
0290         createPreshowerCluster(pfbe, preshowerClusters_[iGSF], 1);
0291       }
0292       if (pfbe.type() == reco::PFBlockElement::PS2) {
0293         createPreshowerCluster(pfbe, preshowerClusters_[iGSF], 2);
0294       }
0295       if (pfbe.type() == reco::PFBlockElement::GSF) {
0296         getAmbiguousGsfTracks(pfbe, ambiguousGsfTracks_[iGSF]);
0297       }
0298 
0299     }  // loop on the elements
0300 
0301     // save the basic clusters
0302     basicClusters_p->insert(basicClusters_p->end(), basicClusters_[iGSF].begin(), basicClusters_[iGSF].end());
0303     // save the preshower clusters
0304     psClusters_p->insert(psClusters_p->end(), preshowerClusters_[iGSF].begin(), preshowerClusters_[iGSF].end());
0305 
0306     ++iGSF;
0307   }  // loop on PFCandidates
0308 
0309   //Save the basic clusters and get an handle as to be able to create valid Refs (thanks to Claude)
0310   //  std::cout << " Number of basic clusters " << basicClusters_p->size() << std::endl;
0311   const edm::OrphanHandle<reco::BasicClusterCollection> bcRefProd =
0312       iEvent.put(std::move(basicClusters_p), PFBasicClusterCollection_);
0313 
0314   //preshower clusters
0315   const edm::OrphanHandle<reco::PreshowerClusterCollection> psRefProd =
0316       iEvent.put(std::move(psClusters_p), PFPreshowerClusterCollection_);
0317 
0318   // now that the Basic clusters are in the event, the Ref can be created
0319   createBasicClusterPtrs(bcRefProd);
0320   // now that the preshower clusters are in the event, the Ref can be created
0321   createPreshowerClusterPtrs(psRefProd);
0322 
0323   // and now the Super cluster can be created with valid references
0324   if (status)
0325     createSuperClusters(*pfCandidates, *superClusters_p);
0326 
0327   // Let's put the super clusters in the event
0328   const edm::OrphanHandle<reco::SuperClusterCollection> scRefProd =
0329       iEvent.put(std::move(superClusters_p), PFSuperClusterCollection_);
0330   // create the super cluster Ref
0331   createSuperClusterGsfMapRefs(scRefProd);
0332 
0333   // Now create the GsfElectronCoers
0334   createGsfElectronCores(*gsfElectronCores_p);
0335   // Put them in the as to get to be able to build a Ref
0336   const edm::OrphanHandle<reco::GsfElectronCoreCollection> gsfElectronCoreRefProd =
0337       iEvent.put(std::move(gsfElectronCores_p), GsfElectronCoreCollection_);
0338 
0339   // now create the Refs
0340   createGsfElectronCoreRefs(gsfElectronCoreRefProd);
0341 
0342   // now make the GsfElectron
0343   createGsfElectrons(*pfCandidates, isolationValues, *gsfElectrons_p);
0344   iEvent.put(std::move(gsfElectrons_p), GsfElectronCollection_);
0345 
0346   fillMVAValueMap(iEvent, mvaFiller);
0347   mvaFiller.fill();
0348 
0349   fillSCRefValueMap(iEvent, scRefFiller);
0350   scRefFiller.fill();
0351 
0352   // MVA map
0353   iEvent.put(std::move(mvaMap_p), PFMVAValueMap_);
0354   // Gsf-SC map
0355   iEvent.put(std::move(scMap_p), PFSCValueMap_);
0356 }
0357 
0358 bool PFElectronTranslator::fetchCandidateCollection(edm::Handle<reco::PFCandidateCollection>& c,
0359                                                     const edm::InputTag& tag,
0360                                                     const edm::Event& iEvent) const {
0361   bool found = iEvent.getByLabel(tag, c);
0362 
0363   if (!found && !emptyIsOk_) {
0364     std::ostringstream err;
0365     err << " cannot get PFCandidates: " << tag << std::endl;
0366     edm::LogError("PFElectronTranslator") << err.str();
0367   }
0368   return found;
0369 }
0370 
0371 void PFElectronTranslator::fetchGsfCollection(edm::Handle<reco::GsfTrackCollection>& c,
0372                                               const edm::InputTag& tag,
0373                                               const edm::Event& iEvent) const {
0374   bool found = iEvent.getByLabel(tag, c);
0375 
0376   if (!found) {
0377     std::ostringstream err;
0378     err << " cannot get GSFTracks: " << tag << std::endl;
0379     edm::LogError("PFElectronTranslator") << err.str();
0380     throw cms::Exception("MissingProduct", err.str());
0381   }
0382 }
0383 
0384 // The basic cluster is a copy of the PFCluster -> the energy is not corrected
0385 // It should be possible to get the corrected energy (including the associated PS energy)
0386 // from the PFCandidate daugthers ; Needs some work
0387 void PFElectronTranslator::createBasicCluster(const reco::PFBlockElement& PFBE,
0388                                               reco::BasicClusterCollection& basicClusters,
0389                                               std::vector<const reco::PFCluster*>& pfClusters,
0390                                               const reco::PFCandidate& coCandidate) const {
0391   const reco::PFClusterRef& myPFClusterRef = PFBE.clusterRef();
0392   if (myPFClusterRef.isNull())
0393     return;
0394 
0395   const reco::PFCluster& myPFCluster(*myPFClusterRef);
0396   pfClusters.push_back(&myPFCluster);
0397   //  std::cout << " Creating BC " << myPFCluster.energy() << " " << coCandidate.ecalEnergy() <<" "<<  coCandidate.rawEcalEnergy() <<std::endl;
0398   //  std::cout << " # hits " << myPFCluster.hitsAndFractions().size() << std::endl;
0399 
0400   //  basicClusters.push_back(reco::CaloCluster(myPFCluster.energy(),
0401   basicClusters.push_back(reco::CaloCluster(
0402       //        myPFCluster.energy(),
0403       coCandidate.rawEcalEnergy(),
0404       myPFCluster.position(),
0405       myPFCluster.caloID(),
0406       myPFCluster.hitsAndFractions(),
0407       myPFCluster.algo(),
0408       myPFCluster.seed()));
0409 }
0410 
0411 void PFElectronTranslator::createPreshowerCluster(const reco::PFBlockElement& PFBE,
0412                                                   reco::PreshowerClusterCollection& preshowerClusters,
0413                                                   unsigned plane) const {
0414   const reco::PFClusterRef& myPFClusterRef = PFBE.clusterRef();
0415   preshowerClusters.push_back(reco::PreshowerCluster(
0416       myPFClusterRef->energy(), myPFClusterRef->position(), myPFClusterRef->hitsAndFractions(), plane));
0417 }
0418 
0419 void PFElectronTranslator::createBasicClusterPtrs(
0420     const edm::OrphanHandle<reco::BasicClusterCollection>& basicClustersHandle) {
0421   unsigned size = GsfTrackRef_.size();
0422   unsigned basicClusterCounter = 0;
0423   basicClusterPtr_.resize(size);
0424 
0425   for (unsigned iGSF = 0; iGSF < size; ++iGSF)  // loop on tracks
0426   {
0427     unsigned nbc = basicClusters_[iGSF].size();
0428     for (unsigned ibc = 0; ibc < nbc; ++ibc)  // loop on basic clusters
0429     {
0430       //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
0431       reco::CaloClusterPtr bcPtr(basicClustersHandle, basicClusterCounter);
0432       basicClusterPtr_[iGSF].push_back(bcPtr);
0433       ++basicClusterCounter;
0434     }
0435   }
0436 }
0437 
0438 void PFElectronTranslator::createPreshowerClusterPtrs(
0439     const edm::OrphanHandle<reco::PreshowerClusterCollection>& preshowerClustersHandle) {
0440   unsigned size = GsfTrackRef_.size();
0441   unsigned psClusterCounter = 0;
0442   preshowerClusterPtr_.resize(size);
0443 
0444   for (unsigned iGSF = 0; iGSF < size; ++iGSF)  // loop on tracks
0445   {
0446     unsigned nbc = preshowerClusters_[iGSF].size();
0447     for (unsigned ibc = 0; ibc < nbc; ++ibc)  // loop on basic clusters
0448     {
0449       //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
0450       reco::CaloClusterPtr psPtr(preshowerClustersHandle, psClusterCounter);
0451       preshowerClusterPtr_[iGSF].push_back(psPtr);
0452       ++psClusterCounter;
0453     }
0454   }
0455 }
0456 
0457 void PFElectronTranslator::createSuperClusterGsfMapRefs(
0458     const edm::OrphanHandle<reco::SuperClusterCollection>& superClustersHandle) {
0459   unsigned size = GsfTrackRef_.size();
0460 
0461   for (unsigned iGSF = 0; iGSF < size; ++iGSF)  // loop on tracks
0462   {
0463     edm::Ref<reco::SuperClusterCollection> scRef(superClustersHandle, iGSF);
0464     scMap_[GsfTrackRef_[iGSF]] = scRef;
0465   }
0466 }
0467 
0468 void PFElectronTranslator::fillMVAValueMap(edm::Event& iEvent, edm::ValueMap<float>::Filler& filler) {
0469   gsfMvaMap_.clear();
0470   edm::Handle<reco::PFCandidateCollection> pfCandidates;
0471   bool status = fetchCandidateCollection(pfCandidates, inputTagPFCandidateElectrons_, iEvent);
0472 
0473   unsigned ncand = (status) ? pfCandidates->size() : 0;
0474   for (unsigned i = 0; i < ncand; ++i) {
0475     const reco::PFCandidate& cand = (*pfCandidates)[i];
0476     if (cand.particleId() != reco::PFCandidate::e)
0477       continue;
0478     if (cand.gsfTrackRef().isNull())
0479       continue;
0480     // Fill the MVA map
0481     gsfMvaMap_[cand.gsfTrackRef()] = cand.mva_e_pi();
0482   }
0483 
0484   edm::Handle<reco::GsfTrackCollection> gsfTracks;
0485   fetchGsfCollection(gsfTracks, inputTagGSFTracks_, iEvent);
0486   unsigned ngsf = gsfTracks->size();
0487   std::vector<float> values;
0488   for (unsigned igsf = 0; igsf < ngsf; ++igsf) {
0489     reco::GsfTrackRef theTrackRef(gsfTracks, igsf);
0490     std::map<reco::GsfTrackRef, float>::const_iterator itcheck = gsfMvaMap_.find(theTrackRef);
0491     if (itcheck == gsfMvaMap_.end()) {
0492       //      edm::LogWarning("PFElectronTranslator") << "MVA Map, missing GSF track ref " << std::endl;
0493       values.push_back(-99.);
0494       //      std::cout << " Push_back -99. " << std::endl;
0495     } else {
0496       //      std::cout <<  " Value " << itcheck->second << std::endl;
0497       values.push_back(itcheck->second);
0498     }
0499   }
0500   filler.insert(gsfTracks, values.begin(), values.end());
0501 }
0502 
0503 void PFElectronTranslator::fillSCRefValueMap(edm::Event& iEvent,
0504                                              edm::ValueMap<reco::SuperClusterRef>::Filler& filler) const {
0505   edm::Handle<reco::GsfTrackCollection> gsfTracks;
0506   fetchGsfCollection(gsfTracks, inputTagGSFTracks_, iEvent);
0507   unsigned ngsf = gsfTracks->size();
0508   std::vector<reco::SuperClusterRef> values;
0509   for (unsigned igsf = 0; igsf < ngsf; ++igsf) {
0510     reco::GsfTrackRef theTrackRef(gsfTracks, igsf);
0511     std::map<reco::GsfTrackRef, reco::SuperClusterRef>::const_iterator itcheck = scMap_.find(theTrackRef);
0512     if (itcheck == scMap_.end()) {
0513       //      edm::LogWarning("PFElectronTranslator") << "SCRef Map, missing GSF track ref" << std::endl;
0514       values.push_back(reco::SuperClusterRef());
0515     } else {
0516       values.push_back(itcheck->second);
0517     }
0518   }
0519   filler.insert(gsfTracks, values.begin(), values.end());
0520 }
0521 
0522 void PFElectronTranslator::createSuperClusters(const reco::PFCandidateCollection& pfCand,
0523                                                reco::SuperClusterCollection& superClusters) const {
0524   unsigned nGSF = GsfTrackRef_.size();
0525   for (unsigned iGSF = 0; iGSF < nGSF; ++iGSF) {
0526     // Computes energy position a la e/gamma
0527     double sclusterE = 0;
0528     double posX = 0.;
0529     double posY = 0.;
0530     double posZ = 0.;
0531 
0532     unsigned nbasics = basicClusters_[iGSF].size();
0533     for (unsigned ibc = 0; ibc < nbasics; ++ibc) {
0534       double e = basicClusters_[iGSF][ibc].energy();
0535       sclusterE += e;
0536       posX += e * basicClusters_[iGSF][ibc].position().X();
0537       posY += e * basicClusters_[iGSF][ibc].position().Y();
0538       posZ += e * basicClusters_[iGSF][ibc].position().Z();
0539     }
0540     posX /= sclusterE;
0541     posY /= sclusterE;
0542     posZ /= sclusterE;
0543 
0544     if (pfCand[gsfPFCandidateIndex_[iGSF]].gsfTrackRef() != GsfTrackRef_[iGSF]) {
0545       edm::LogError("PFElectronTranslator") << " Major problem in PFElectron Translator" << std::endl;
0546     }
0547 
0548     // compute the width
0549     PFClusterWidthAlgo pfwidth(pfClusters_[iGSF]);
0550 
0551     double correctedEnergy = pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
0552     reco::SuperCluster mySuperCluster(correctedEnergy, math::XYZPoint(posX, posY, posZ));
0553     // protection against empty basic cluster collection ; the value is -2 in this case
0554     if (nbasics) {
0555       //      std::cout << "SuperCluster creation; energy " << pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
0556       //      std::cout << " " <<   pfCand[gsfPFCandidateIndex_[iGSF]].rawEcalEnergy() << std::endl;
0557       //      std::cout << "Seed energy from basic " << basicClusters_[iGSF][0].energy() << std::endl;
0558       mySuperCluster.setSeed(basicClusterPtr_[iGSF][0]);
0559     } else {
0560       //      std::cout << "SuperCluster creation ; seed energy " << 0 << std::endl;
0561       //      std::cout << "SuperCluster creation ; energy " << pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
0562       //      std::cout << " " <<   pfCand[gsfPFCandidateIndex_[iGSF]].rawEcalEnergy() << std::endl;
0563       //      std::cout << " No seed found " << 0 << std::endl;
0564       //      std::cout << " MVA " << pfCand[gsfPFCandidateIndex_[iGSF]].mva_e_pi() << std::endl;
0565       mySuperCluster.setSeed(reco::CaloClusterPtr());
0566     }
0567     // the seed should be the first basic cluster
0568 
0569     for (unsigned ibc = 0; ibc < nbasics; ++ibc) {
0570       mySuperCluster.addCluster(basicClusterPtr_[iGSF][ibc]);
0571       //      std::cout <<"Adding Ref to SC " << basicClusterPtr_[iGSF][ibc].index() << std::endl;
0572       const std::vector<std::pair<DetId, float>>& v1 = basicClusters_[iGSF][ibc].hitsAndFractions();
0573       //      std::cout << " Number of cells " << v1.size() << std::endl;
0574       for (std::vector<std::pair<DetId, float>>::const_iterator diIt = v1.begin(); diIt != v1.end(); ++diIt) {
0575         //      std::cout << " Adding DetId " << (diIt->first).rawId() << " " << diIt->second << std::endl;
0576         mySuperCluster.addHitAndFraction(diIt->first, diIt->second);
0577       }  // loop over rechits
0578     }
0579 
0580     unsigned nps = preshowerClusterPtr_[iGSF].size();
0581     for (unsigned ips = 0; ips < nps; ++ips) {
0582       mySuperCluster.addPreshowerCluster(preshowerClusterPtr_[iGSF][ips]);
0583     }
0584 
0585     // Set the preshower energy
0586     mySuperCluster.setPreshowerEnergy(pfCand[gsfPFCandidateIndex_[iGSF]].pS1Energy() +
0587                                       pfCand[gsfPFCandidateIndex_[iGSF]].pS2Energy());
0588 
0589     // Set the cluster width
0590     mySuperCluster.setEtaWidth(pfwidth.pflowEtaWidth());
0591     mySuperCluster.setPhiWidth(pfwidth.pflowPhiWidth());
0592     // Force the computation of rawEnergy_ of the reco::SuperCluster
0593     mySuperCluster.rawEnergy();
0594     superClusters.push_back(mySuperCluster);
0595   }
0596 }
0597 
0598 const reco::PFCandidate& PFElectronTranslator::correspondingDaughterCandidate(const reco::PFCandidate& cand,
0599                                                                               const reco::PFBlockElement& pfbe) const {
0600   unsigned refindex = pfbe.index();
0601   //  std::cout << " N daughters " << cand.numberOfDaughters() << std::endl;
0602   reco::PFCandidate::const_iterator myDaughterCandidate = cand.begin();
0603   reco::PFCandidate::const_iterator itend = cand.end();
0604 
0605   for (; myDaughterCandidate != itend; ++myDaughterCandidate) {
0606     const reco::PFCandidate* myPFCandidate = (const reco::PFCandidate*)&*myDaughterCandidate;
0607     if (myPFCandidate->elementsInBlocks().size() != 1) {
0608       //      std::cout << " Daughter with " << myPFCandidate.elementsInBlocks().size()<< " element in block " << std::endl;
0609       return cand;
0610     }
0611     if (myPFCandidate->elementsInBlocks()[0].second == refindex) {
0612       //      std::cout << " Found it " << cand << std::endl;
0613       return *myPFCandidate;
0614     }
0615   }
0616   return cand;
0617 }
0618 
0619 void PFElectronTranslator::createGsfElectronCores(reco::GsfElectronCoreCollection& gsfElectronCores) const {
0620   unsigned nGSF = GsfTrackRef_.size();
0621   for (unsigned iGSF = 0; iGSF < nGSF; ++iGSF) {
0622     reco::GsfElectronCore myElectronCore(GsfTrackRef_[iGSF]);
0623     myElectronCore.setCtfTrack(kfTrackRef_[iGSF], -1.);
0624     std::map<reco::GsfTrackRef, reco::SuperClusterRef>::const_iterator itcheck = scMap_.find(GsfTrackRef_[iGSF]);
0625     if (itcheck != scMap_.end())
0626       myElectronCore.setParentSuperCluster(itcheck->second);
0627     gsfElectronCores.push_back(myElectronCore);
0628   }
0629 }
0630 
0631 void PFElectronTranslator::createGsfElectronCoreRefs(
0632     const edm::OrphanHandle<reco::GsfElectronCoreCollection>& gsfElectronCoreHandle) {
0633   unsigned size = GsfTrackRef_.size();
0634 
0635   for (unsigned iGSF = 0; iGSF < size; ++iGSF)  // loop on tracks
0636   {
0637     edm::Ref<reco::GsfElectronCoreCollection> elecCoreRef(gsfElectronCoreHandle, iGSF);
0638     gsfElectronCoreRefs_.push_back(elecCoreRef);
0639   }
0640 }
0641 
0642 void PFElectronTranslator::getAmbiguousGsfTracks(const reco::PFBlockElement& PFBE,
0643                                                  std::vector<reco::GsfTrackRef>& tracks) const {
0644   const reco::PFBlockElementGsfTrack* GsfEl = dynamic_cast<const reco::PFBlockElementGsfTrack*>(&PFBE);
0645   if (GsfEl == nullptr)
0646     return;
0647   const std::vector<reco::GsfPFRecTrackRef>& ambPFRecTracks(GsfEl->GsftrackRefPF()->convBremGsfPFRecTrackRef());
0648   unsigned ntracks = ambPFRecTracks.size();
0649   for (unsigned it = 0; it < ntracks; ++it) {
0650     tracks.push_back(ambPFRecTracks[it]->gsfTrackRef());
0651   }
0652 }
0653 
0654 void PFElectronTranslator::createGsfElectrons(const reco::PFCandidateCollection& pfcand,
0655                                               const IsolationValueMaps& isolationValues,
0656                                               reco::GsfElectronCollection& gsfelectrons) {
0657   unsigned size = GsfTrackRef_.size();
0658 
0659   for (unsigned iGSF = 0; iGSF < size; ++iGSF)  // loop on tracks
0660   {
0661     const reco::PFCandidate& pfCandidate(pfcand[gsfPFCandidateIndex_[iGSF]]);
0662     // Electron
0663     reco::GsfElectron myElectron(gsfElectronCoreRefs_[iGSF]);
0664     // Warning set p4 error !
0665     myElectron.setP4(reco::GsfElectron::P4_PFLOW_COMBINATION, pfCandidate.p4(), pfCandidate.deltaP(), true);
0666 
0667     // MVA inputs
0668     reco::GsfElectron::MvaInput myMvaInput;
0669     myMvaInput.earlyBrem = pfCandidate.electronExtraRef()->mvaVariable(reco::PFCandidateElectronExtra::MVA_FirstBrem);
0670     myMvaInput.lateBrem = pfCandidate.electronExtraRef()->mvaVariable(reco::PFCandidateElectronExtra::MVA_LateBrem);
0671     myMvaInput.deltaEta =
0672         pfCandidate.electronExtraRef()->mvaVariable(reco::PFCandidateElectronExtra::MVA_DeltaEtaTrackCluster);
0673     myMvaInput.sigmaEtaEta = pfCandidate.electronExtraRef()->sigmaEtaEta();
0674     myMvaInput.hadEnergy = pfCandidate.electronExtraRef()->hadEnergy();
0675 
0676     // Mustache
0677     reco::Mustache myMustache(mustacheSCParams_);
0678     myMustache.MustacheID(
0679         *(myElectron.parentSuperCluster()), myMvaInput.nClusterOutsideMustache, myMvaInput.etOutsideMustache);
0680 
0681     myElectron.setMvaInput(myMvaInput);
0682 
0683     // MVA output
0684     reco::GsfElectron::MvaOutput myMvaOutput;
0685     myMvaOutput.status = pfCandidate.electronExtraRef()->electronStatus();
0686     myMvaOutput.mva_e_pi = pfCandidate.mva_e_pi();
0687     myElectron.setMvaOutput(myMvaOutput);
0688 
0689     // ambiguous tracks
0690     unsigned ntracks = ambiguousGsfTracks_[iGSF].size();
0691     for (unsigned it = 0; it < ntracks; ++it) {
0692       myElectron.addAmbiguousGsfTrack(ambiguousGsfTracks_[iGSF][it]);
0693     }
0694 
0695     // isolation
0696     if (!isolationValues.empty()) {
0697       reco::GsfElectron::PflowIsolationVariables myPFIso;
0698       myPFIso.sumChargedHadronPt = (*isolationValues[0])[CandidatePtr_[iGSF]];
0699       myPFIso.sumPhotonEt = (*isolationValues[1])[CandidatePtr_[iGSF]];
0700       myPFIso.sumNeutralHadronEt = (*isolationValues[2])[CandidatePtr_[iGSF]];
0701       myPFIso.sumPUPt = (*isolationValues[3])[CandidatePtr_[iGSF]];
0702       myElectron.setPfIsolationVariables(myPFIso);
0703     }
0704 
0705     gsfelectrons.push_back(myElectron);
0706   }
0707 }