CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/RecoParticleFlow/PFProducer/plugins/PFElectronTranslator.cc

Go to the documentation of this file.
00001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00002 #include "FWCore/Framework/interface/ESHandle.h"
00003 #include "FWCore/Framework/interface/Event.h"
00004 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00005 #include "RecoParticleFlow/PFProducer/plugins/PFElectronTranslator.h"
00006 #include "RecoParticleFlow/PFClusterTools/interface/PFClusterWidthAlgo.h"
00007 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00008 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
00009 #include "DataFormats/EgammaReco/interface/PreshowerCluster.h"
00010 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
00011 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00012 #include "DataFormats/ParticleFlowReco/interface/PFBlockElement.h"
00013 #include "DataFormats/ParticleFlowReco/interface/PFBlockFwd.h"
00014 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00015 
00016 
00017 PFElectronTranslator::PFElectronTranslator(const edm::ParameterSet & iConfig) {
00018   inputTagPFCandidates_ 
00019     = iConfig.getParameter<edm::InputTag>("PFCandidate");
00020   inputTagGSFTracks_
00021     = iConfig.getParameter<edm::InputTag>("GSFTracks");
00022 
00023   PFBasicClusterCollection_ = iConfig.getParameter<std::string>("PFBasicClusters");
00024   PFPreshowerClusterCollection_ = iConfig.getParameter<std::string>("PFPreshowerClusters");
00025   PFSuperClusterCollection_ = iConfig.getParameter<std::string>("PFSuperClusters");
00026   PFMVAValueMap_ = iConfig.getParameter<std::string>("ElectronMVA");
00027   PFSCValueMap_ = iConfig.getParameter<std::string>("ElectronSC");
00028   MVACut_ = (iConfig.getParameter<edm::ParameterSet>("MVACutBlock")).getParameter<double>("MVACut");
00029 
00030   produces<reco::BasicClusterCollection>(PFBasicClusterCollection_); 
00031   produces<reco::PreshowerClusterCollection>(PFPreshowerClusterCollection_); 
00032   produces<reco::SuperClusterCollection>(PFSuperClusterCollection_); 
00033   produces<edm::ValueMap<float> >(PFMVAValueMap_);
00034   produces<edm::ValueMap<reco::SuperClusterRef> >(PFSCValueMap_);
00035 }
00036 
00037 PFElectronTranslator::~PFElectronTranslator() {}
00038 
00039 void PFElectronTranslator::beginRun(edm::Run& run,const edm::EventSetup & es) {}
00040 
00041 void PFElectronTranslator::produce(edm::Event& iEvent,  
00042                                     const edm::EventSetup& iSetup) { 
00043   
00044   std::auto_ptr<reco::SuperClusterCollection> 
00045     superClusters_p(new reco::SuperClusterCollection);
00046 
00047   std::auto_ptr<reco::BasicClusterCollection> 
00048     basicClusters_p(new reco::BasicClusterCollection);
00049 
00050   std::auto_ptr<reco::PreshowerClusterCollection>
00051     psClusters_p(new reco::PreshowerClusterCollection);
00052   
00053   std::auto_ptr<edm::ValueMap<float> > mvaMap_p(new edm::ValueMap<float>());
00054   edm::ValueMap<float>::Filler mvaFiller(*mvaMap_p);
00055 
00056   std::auto_ptr<edm::ValueMap<reco::SuperClusterRef> > 
00057     scMap_p(new edm::ValueMap<reco::SuperClusterRef>());
00058   edm::ValueMap<reco::SuperClusterRef>::Filler scRefFiller(*scMap_p);
00059   
00060 
00061   edm::Handle<reco::PFCandidateCollection> pfCandidates;
00062   bool status=fetchCandidateCollection(pfCandidates, 
00063                                        inputTagPFCandidates_, 
00064                                        iEvent );
00065   
00066   // clear the vectors
00067   GsfTrackRef_.clear();
00068   basicClusters_.clear();
00069   pfClusters_.clear();
00070   preshowerClusters_.clear();
00071   superClusters_.clear();
00072   basicClusterPtr_.clear();
00073   preshowerClusterPtr_.clear();
00074   gsfPFCandidateIndex_.clear();
00075   scMap_.clear();
00076   gsfMvaMap_.clear();
00077  
00078   // loop on the candidates 
00079   //CC@@
00080   // we need first to create AND put the SuperCluster, 
00081   // basic clusters and presh clusters collection 
00082   // in order to get a working Handle
00083   unsigned ncand=(status)?pfCandidates->size():0;
00084   unsigned iGSF=0;
00085   for( unsigned i=0; i<ncand; ++i ) {
00086 
00087     const reco::PFCandidate& cand = (*pfCandidates)[i];    
00088     if(cand.particleId()!=reco::PFCandidate::e) continue; 
00089     if(cand.gsfTrackRef().isNull()) continue;
00090     // Note that -1 will still cut some total garbage candidates 
00091     // Fill the MVA map
00092     gsfMvaMap_[cand.gsfTrackRef()]=cand.mva_e_pi();       
00093     if(cand.mva_e_pi()<MVACut_) continue;
00094 
00095     GsfTrackRef_.push_back(cand.gsfTrackRef());
00096     gsfPFCandidateIndex_.push_back(i);
00097     
00098     basicClusters_.push_back(reco::BasicClusterCollection());
00099     pfClusters_.push_back(std::vector<const reco::PFCluster *>());
00100     preshowerClusters_.push_back(reco::PreshowerClusterCollection());
00101 
00102     for(unsigned iele=0; iele<cand.elementsInBlocks().size(); ++iele) {
00103       // first get the block 
00104       reco::PFBlockRef blockRef = cand.elementsInBlocks()[iele].first;
00105       //
00106       unsigned elementIndex = cand.elementsInBlocks()[iele].second;
00107       // check it actually exists 
00108       if(blockRef.isNull()) continue;
00109       
00110       // then get the elements of the block
00111       const edm::OwnVector< reco::PFBlockElement >&  elements = (*blockRef).elements();
00112       
00113       const reco::PFBlockElement & pfbe (elements[elementIndex]); 
00114       // The first ECAL element should be the cluster associated to the GSF; defined as the seed
00115       if(pfbe.type()==reco::PFBlockElement::ECAL)
00116         {         
00117           //      const reco::PFCandidate * coCandidate = &cand;
00118           // the Brem photons are saved as daughter PFCandidate; this 
00119           // is convenient to access the corrected energy
00120           //      std::cout << " Found candidate "  << correspondingDaughterCandidate(coCandidate,pfbe) << " " << coCandidate << std::endl;
00121           createBasicCluster(pfbe,basicClusters_[iGSF],pfClusters_[iGSF],correspondingDaughterCandidate(cand,pfbe));
00122         }
00123       if(pfbe.type()==reco::PFBlockElement::PS1)
00124         {
00125           createPreshowerCluster(pfbe,preshowerClusters_[iGSF],1);
00126         }
00127       if(pfbe.type()==reco::PFBlockElement::PS2)
00128         {
00129           createPreshowerCluster(pfbe,preshowerClusters_[iGSF],2);
00130         }      
00131           
00132     }   // loop on the elements
00133 
00134     // save the basic clusters
00135     basicClusters_p->insert(basicClusters_p->end(),basicClusters_[iGSF].begin(), basicClusters_[iGSF].end());
00136     // save the preshower clusters
00137     psClusters_p->insert(psClusters_p->end(),preshowerClusters_[iGSF].begin(),preshowerClusters_[iGSF].end());
00138 
00139     ++iGSF;
00140   } // loop on PFCandidates
00141 
00142   
00143    //Save the basic clusters and get an handle as to be able to create valid Refs (thanks to Claude)
00144   //  std::cout << " Number of basic clusters " << basicClusters_p->size() << std::endl;
00145   const edm::OrphanHandle<reco::BasicClusterCollection> bcRefProd = 
00146     iEvent.put(basicClusters_p,PFBasicClusterCollection_);
00147 
00148   //preshower clusters
00149   const edm::OrphanHandle<reco::PreshowerClusterCollection> psRefProd = 
00150     iEvent.put(psClusters_p,PFPreshowerClusterCollection_);
00151 
00152   // now that the Basic clusters are in the event, the Ref can be created
00153   createBasicClusterPtrs(bcRefProd);
00154   // now that the preshower clusters are in the event, the Ref can be created
00155   createPreshowerClusterPtrs(psRefProd);
00156   
00157   // and now the Super cluster can be created with valid references  
00158   if(status) createSuperClusters(*pfCandidates,*superClusters_p);
00159   
00160   // Let's put the super clusters in the event
00161   const edm::OrphanHandle<reco::SuperClusterCollection> scRefProd = iEvent.put(superClusters_p,PFSuperClusterCollection_); 
00162   // create the super cluster Ref
00163   createSuperClusterGsfMapRefs(scRefProd);
00164   
00165   
00166   fillMVAValueMap(iEvent,mvaFiller);
00167   mvaFiller.fill();
00168 
00169   fillSCRefValueMap(iEvent,scRefFiller);
00170   scRefFiller.fill();
00171 
00172   // MVA map
00173   iEvent.put(mvaMap_p,PFMVAValueMap_);
00174   // Gsf-SC map
00175   iEvent.put(scMap_p,PFSCValueMap_);
00176 }
00177 
00178 
00179 
00180 bool PFElectronTranslator::fetchCandidateCollection(edm::Handle<reco::PFCandidateCollection>& c, 
00181                                               const edm::InputTag& tag, 
00182                                               const edm::Event& iEvent) const {  
00183   bool found = iEvent.getByLabel(tag, c);
00184 
00185   if(!found)
00186     {
00187       std::ostringstream  err;
00188       err<<" cannot get PFCandidates: "
00189          <<tag<<std::endl;
00190       edm::LogError("PFElectronTranslator")<<err.str();
00191     }
00192   return found;
00193       
00194 }
00195 
00196 void PFElectronTranslator::fetchGsfCollection(edm::Handle<reco::GsfTrackCollection>& c, 
00197                                               const edm::InputTag& tag, 
00198                                               const edm::Event& iEvent) const {  
00199   bool found = iEvent.getByLabel(tag, c);
00200   
00201   if(!found ) {
00202     std::ostringstream  err;
00203     err<<" cannot get GSFTracks: "
00204        <<tag<<std::endl;
00205     edm::LogError("PFElectronTranslator")<<err.str();
00206     throw cms::Exception( "MissingProduct", err.str());
00207   }  
00208 }
00209 
00210 // The basic cluster is a copy of the PFCluster -> the energy is not corrected 
00211 // It should be possible to get the corrected energy (including the associated PS energy)
00212 // from the PFCandidate daugthers ; Needs some work 
00213 void PFElectronTranslator::createBasicCluster(const reco::PFBlockElement & PFBE, 
00214                                               reco::BasicClusterCollection & basicClusters, 
00215                                               std::vector<const reco::PFCluster *> & pfClusters,
00216                                               const reco::PFCandidate & coCandidate) const
00217 {
00218   reco::PFClusterRef myPFClusterRef= PFBE.clusterRef();
00219   if(myPFClusterRef.isNull()) return;  
00220 
00221   const reco::PFCluster & myPFCluster (*myPFClusterRef);
00222   pfClusters.push_back(&myPFCluster);
00223 //  std::cout << " Creating BC " << myPFCluster.energy() << " " << coCandidate.ecalEnergy() <<" "<<  coCandidate.rawEcalEnergy() <<std::endl;
00224 //  std::cout << " # hits " << myPFCluster.hitsAndFractions().size() << std::endl;
00225 
00226 //  basicClusters.push_back(reco::CaloCluster(myPFCluster.energy(),
00227   basicClusters.push_back(reco::CaloCluster(coCandidate.rawEcalEnergy(),
00228                                             myPFCluster.position(),
00229                                             myPFCluster.caloID(),
00230                                             myPFCluster.hitsAndFractions(),
00231                                             myPFCluster.algo(),
00232                                             myPFCluster.seed()));
00233 }
00234 
00235 
00236 void PFElectronTranslator::createPreshowerCluster(const reco::PFBlockElement & PFBE, reco::PreshowerClusterCollection& preshowerClusters,unsigned plane) const
00237 {
00238   reco::PFClusterRef  myPFClusterRef= PFBE.clusterRef();
00239   preshowerClusters.push_back(reco::PreshowerCluster(myPFClusterRef->energy(),myPFClusterRef->position(),
00240                                                myPFClusterRef->hitsAndFractions(),plane));
00241 }
00242 
00243 void PFElectronTranslator::createBasicClusterPtrs(const edm::OrphanHandle<reco::BasicClusterCollection> & basicClustersHandle )
00244 {
00245   unsigned size=GsfTrackRef_.size();
00246   unsigned basicClusterCounter=0;
00247   basicClusterPtr_.resize(size);
00248 
00249   for(unsigned iGSF=0;iGSF<size;++iGSF) // loop on tracks
00250     {
00251       unsigned nbc=basicClusters_[iGSF].size();
00252       for(unsigned ibc=0;ibc<nbc;++ibc) // loop on basic clusters
00253         {
00254           //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
00255           reco::CaloClusterPtr bcPtr(basicClustersHandle,basicClusterCounter);
00256           basicClusterPtr_[iGSF].push_back(bcPtr);
00257           ++basicClusterCounter;
00258         }
00259     }
00260 }
00261 
00262 void PFElectronTranslator::createPreshowerClusterPtrs(const edm::OrphanHandle<reco::PreshowerClusterCollection> & preshowerClustersHandle )
00263 {
00264   unsigned size=GsfTrackRef_.size();
00265   unsigned psClusterCounter=0;
00266   preshowerClusterPtr_.resize(size);
00267 
00268   for(unsigned iGSF=0;iGSF<size;++iGSF) // loop on tracks
00269     {
00270       unsigned nbc=preshowerClusters_[iGSF].size();
00271       for(unsigned ibc=0;ibc<nbc;++ibc) // loop on basic clusters
00272         {
00273           //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
00274           reco::CaloClusterPtr psPtr(preshowerClustersHandle,psClusterCounter);
00275           preshowerClusterPtr_[iGSF].push_back(psPtr);
00276           ++psClusterCounter;
00277         }
00278     }
00279 }
00280 
00281 void PFElectronTranslator::createSuperClusterGsfMapRefs(const edm::OrphanHandle<reco::SuperClusterCollection> & superClustersHandle )
00282 {
00283   unsigned size=GsfTrackRef_.size();
00284 
00285   for(unsigned iGSF=0;iGSF<size;++iGSF) // loop on tracks
00286     {
00287       edm::Ref<reco::SuperClusterCollection> scRef(superClustersHandle,iGSF);
00288       scMap_[GsfTrackRef_[iGSF]]=scRef;
00289     }
00290 }
00291 
00292 
00293 void PFElectronTranslator::fillMVAValueMap(edm::Event& iEvent, edm::ValueMap<float>::Filler & filler) const
00294 {
00295   edm::Handle<reco::GsfTrackCollection> gsfTracks;
00296   fetchGsfCollection(gsfTracks,
00297                      inputTagGSFTracks_,
00298                      iEvent);
00299   unsigned ngsf=gsfTracks->size();
00300   std::vector<float> values;
00301   for(unsigned igsf=0;igsf<ngsf;++igsf)
00302     {
00303       reco::GsfTrackRef theTrackRef(gsfTracks, igsf);
00304       std::map<reco::GsfTrackRef,float>::const_iterator itcheck=gsfMvaMap_.find(theTrackRef);
00305       if(itcheck==gsfMvaMap_.end())
00306         {
00307           //      edm::LogWarning("PFElectronTranslator") << "MVA Map, missing GSF track ref " << std::endl;
00308           values.push_back(-99.);
00309           //      std::cout << " Push_back -99. " << std::endl;
00310         }
00311       else
00312         {
00313           values.push_back(itcheck->second);      
00314         }
00315     }
00316   filler.insert(gsfTracks,values.begin(),values.end());
00317 }
00318 
00319 
00320 void PFElectronTranslator::fillSCRefValueMap(edm::Event& iEvent, 
00321                                              edm::ValueMap<reco::SuperClusterRef>::Filler & filler) const
00322 {
00323   edm::Handle<reco::GsfTrackCollection> gsfTracks;
00324   fetchGsfCollection(gsfTracks,
00325                      inputTagGSFTracks_,
00326                      iEvent);
00327   unsigned ngsf=gsfTracks->size();
00328   std::vector<reco::SuperClusterRef> values;
00329   for(unsigned igsf=0;igsf<ngsf;++igsf)
00330     {
00331       reco::GsfTrackRef theTrackRef(gsfTracks, igsf);
00332       std::map<reco::GsfTrackRef,reco::SuperClusterRef>::const_iterator itcheck=scMap_.find(theTrackRef);
00333       if(itcheck==scMap_.end())
00334         {
00335           //      edm::LogWarning("PFElectronTranslator") << "SCRef Map, missing GSF track ref" << std::endl;
00336           values.push_back(reco::SuperClusterRef());
00337         }
00338       else
00339         {
00340           values.push_back(itcheck->second);      
00341         }
00342     }
00343   filler.insert(gsfTracks,values.begin(),values.end());
00344 }
00345 
00346 
00347 void PFElectronTranslator::createSuperClusters(const reco::PFCandidateCollection & pfCand,
00348                                                reco::SuperClusterCollection &superClusters) const
00349 {
00350   unsigned nGSF=GsfTrackRef_.size();
00351   for(unsigned iGSF=0;iGSF<nGSF;++iGSF)
00352     {
00353 
00354       // Computes energy position a la e/gamma 
00355       double sclusterE=0;
00356       double posX=0.;
00357       double posY=0.;
00358       double posZ=0.;
00359       
00360       unsigned nbasics=basicClusters_[iGSF].size();
00361       for(unsigned ibc=0;ibc<nbasics;++ibc)
00362         {
00363           double e = basicClusters_[iGSF][ibc].energy();
00364           sclusterE += e;
00365           posX += e * basicClusters_[iGSF][ibc].position().X();
00366           posY += e * basicClusters_[iGSF][ibc].position().Y();
00367           posZ += e * basicClusters_[iGSF][ibc].position().Z();   
00368         }
00369       posX /=sclusterE;
00370       posY /=sclusterE;
00371       posZ /=sclusterE;
00372       
00373       if(pfCand[gsfPFCandidateIndex_[iGSF]].gsfTrackRef()!=GsfTrackRef_[iGSF])
00374         {
00375           edm::LogError("PFElectronTranslator") << " Major problem in PFElectron Translator" << std::endl;
00376         }
00377       
00378       // compute the width
00379       PFClusterWidthAlgo pfwidth(pfClusters_[iGSF]);
00380       
00381       double correctedEnergy=pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
00382       reco::SuperCluster mySuperCluster(correctedEnergy,math::XYZPoint(posX,posY,posZ));
00383       // protection against empty basic cluster collection ; the value is -2 in this case
00384       if(nbasics)
00385         {
00386 //        std::cout << "SuperCluster creation; energy " << pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
00387 //        std::cout << " " <<   pfCand[gsfPFCandidateIndex_[iGSF]].rawEcalEnergy() << std::endl;
00388 //        std::cout << "Seed energy from basic " << basicClusters_[iGSF][0].energy() << std::endl;
00389           mySuperCluster.setSeed(basicClusterPtr_[iGSF][0]);
00390         }
00391       else
00392         {
00393           //      std::cout << "SuperCluster creation ; seed energy " << 0 << std::endl;
00394 //        std::cout << "SuperCluster creation ; energy " << pfCand[gsfPFCandidateIndex_[iGSF]].ecalEnergy();
00395 //        std::cout << " " <<   pfCand[gsfPFCandidateIndex_[iGSF]].rawEcalEnergy() << std::endl;
00396 //        std::cout << " No seed found " << 0 << std::endl;       
00397 //        std::cout << " MVA " << pfCand[gsfPFCandidateIndex_[iGSF]].mva_e_pi() << std::endl;
00398           mySuperCluster.setSeed(reco::CaloClusterPtr());
00399         }
00400       // the seed should be the first basic cluster
00401 
00402       for(unsigned ibc=0;ibc<nbasics;++ibc)
00403         {
00404           mySuperCluster.addCluster(basicClusterPtr_[iGSF][ibc]);
00405           //      std::cout <<"Adding Ref to SC " << basicClusterPtr_[iGSF][ibc].index() << std::endl;
00406           const std::vector< std::pair<DetId, float> > & v1 = basicClusters_[iGSF][ibc].hitsAndFractions();
00407           //      std::cout << " Number of cells " << v1.size() << std::endl;
00408           for( std::vector< std::pair<DetId, float> >::const_iterator diIt = v1.begin();
00409                diIt != v1.end();
00410                ++diIt ) {
00411             //      std::cout << " Adding DetId " << (diIt->first).rawId() << " " << diIt->second << std::endl;
00412             mySuperCluster.addHitAndFraction(diIt->first,diIt->second);
00413           } // loop over rechits      
00414         }      
00415 
00416       unsigned nps=preshowerClusterPtr_[iGSF].size();
00417       for(unsigned ips=0;ips<nps;++ips)
00418         {
00419           mySuperCluster.addPreshowerCluster(preshowerClusterPtr_[iGSF][ips]);
00420         }
00421       
00422 
00423       // Set the preshower energy
00424       mySuperCluster.setPreshowerEnergy(pfCand[gsfPFCandidateIndex_[iGSF]].pS1Energy()+
00425                                         pfCand[gsfPFCandidateIndex_[iGSF]].pS2Energy());
00426 
00427       // Set the cluster width
00428       mySuperCluster.setEtaWidth(pfwidth.pflowEtaWidth());
00429       mySuperCluster.setPhiWidth(pfwidth.pflowPhiWidth());
00430       // Force the computation of rawEnergy_ of the reco::SuperCluster
00431       mySuperCluster.rawEnergy();
00432       superClusters.push_back(mySuperCluster);
00433    }
00434 }
00435 
00436 
00437 const reco::PFCandidate & PFElectronTranslator::correspondingDaughterCandidate(const reco::PFCandidate & cand, const reco::PFBlockElement & pfbe) const
00438 {
00439   unsigned refindex=pfbe.index();
00440   //  std::cout << " N daughters " << cand.numberOfDaughters() << std::endl;
00441   reco::PFCandidate::const_iterator myDaughterCandidate=cand.begin();
00442   reco::PFCandidate::const_iterator itend=cand.end();
00443 
00444   for(;myDaughterCandidate!=itend;++myDaughterCandidate)
00445     {
00446       const reco::PFCandidate * myPFCandidate = (const reco::PFCandidate*)&*myDaughterCandidate;
00447       if(myPFCandidate->elementsInBlocks().size()!=1)
00448         {
00449           //      std::cout << " Daughter with " << myPFCandidate.elementsInBlocks().size()<< " element in block " << std::endl;
00450           return cand;
00451         }
00452       if(myPFCandidate->elementsInBlocks()[0].second==refindex) 
00453         {
00454           //      std::cout << " Found it " << cand << std::endl;
00455           return *myPFCandidate;
00456         }      
00457     }
00458   return cand;
00459 }
00460