CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoParticleFlow/PFProducer/plugins/PFPhotonTranslator.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/PFPhotonTranslator.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/EgammaCandidates/interface/PhotonCore.h"
00012 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00013 #include "DataFormats/EgammaCandidates/interface/PhotonCoreFwd.h"
00014 #include "DataFormats/EgammaCandidates/interface/PhotonFwd.h"
00015 #include "DataFormats/VertexReco/interface/Vertex.h"
00016 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00017 //#include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00018 #include "DataFormats/ParticleFlowReco/interface/PFBlockElement.h"
00019 #include "DataFormats/ParticleFlowReco/interface/PFBlockFwd.h"
00020 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00021 
00022 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00023 #include "RecoEgamma/PhotonIdentification/interface/PhotonIsolationCalculator.h"
00024 #include "RecoEgamma/EgammaIsolationAlgos/interface/EgammaTowerIsolation.h"
00025 
00026 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00027 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00028 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00029 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00030 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00031 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00032 #include "RecoEcal/EgammaCoreTools/interface/PositionCalc.h"
00033 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00034 #include "RecoEcal/EgammaCoreTools/interface/PositionCalc.h"
00035 #include "RecoEgamma/PhotonIdentification/interface/PhotonIsolationCalculator.h"
00036 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterFunctionFactory.h"
00037 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterFunctionBaseClass.h" 
00038 #include "CondFormats/EcalObjects/interface/EcalFunctionParameters.h" 
00039 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterTools.h"
00040 
00041 
00042 #include "DataFormats/Math/interface/Vector3D.h"
00043 #include "DataFormats/Math/interface/LorentzVector.h"
00044 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00045 #include "DataFormats/Common/interface/AssociationVector.h"
00046 
00047 #include <Math/VectorUtil.h>
00048 #include <vector>
00049 #include "TLorentzVector.h"
00050 #include "TMath.h"
00051 
00052 using namespace edm;
00053 using namespace std;
00054 using namespace reco;
00055 
00056 using namespace ROOT::Math::VectorUtil;
00057 typedef math::XYZTLorentzVector LorentzVector;
00058 typedef math::XYZPoint Point;
00059 typedef math::XYZVector Vector;
00060 
00061 
00062 PFPhotonTranslator::PFPhotonTranslator(const edm::ParameterSet & iConfig) {
00063 
00064   //std::cout << "PFPhotonTranslator" << std::endl;
00065 
00066   inputTagPFCandidates_ 
00067     = iConfig.getParameter<edm::InputTag>("PFCandidate");
00068 
00069   
00070   edm::ParameterSet isoVals  = iConfig.getParameter<edm::ParameterSet> ("isolationValues");
00071   inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfChargedHadrons"));
00072   inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfPhotons"));
00073   inputTagIsoVals_.push_back(isoVals.getParameter<edm::InputTag>("pfNeutralHadrons"));
00074   
00075 
00076   PFBasicClusterCollection_ = iConfig.getParameter<std::string>("PFBasicClusters");
00077   PFPreshowerClusterCollection_ = iConfig.getParameter<std::string>("PFPreshowerClusters");
00078   PFSuperClusterCollection_ = iConfig.getParameter<std::string>("PFSuperClusters");
00079 
00080   PFPhotonCoreCollection_ = iConfig.getParameter<std::string>("PFPhotonCores");
00081   PFPhotonCollection_ = iConfig.getParameter<std::string>("PFPhotons");
00082 
00083   vertexProducer_   = iConfig.getParameter<std::string>("primaryVertexProducer");
00084 
00085   barrelEcalHits_   = iConfig.getParameter<edm::InputTag>("barrelEcalHits");
00086   endcapEcalHits_   = iConfig.getParameter<edm::InputTag>("endcapEcalHits");
00087 
00088   hcalTowers_ = iConfig.getParameter<edm::InputTag>("hcalTowers");
00089   hOverEConeSize_   = iConfig.getParameter<double>("hOverEConeSize");
00090 
00091   if (iConfig.exists("emptyIsOk")) emptyIsOk_ = iConfig.getParameter<bool>("emptyIsOk");
00092   else emptyIsOk_=false;
00093 
00094   produces<reco::BasicClusterCollection>(PFBasicClusterCollection_); 
00095   produces<reco::PreshowerClusterCollection>(PFPreshowerClusterCollection_); 
00096   produces<reco::SuperClusterCollection>(PFSuperClusterCollection_); 
00097   produces<reco::PhotonCoreCollection>(PFPhotonCoreCollection_);
00098   produces<reco::PhotonCollection>(PFPhotonCollection_); 
00099 
00100 }
00101 
00102 PFPhotonTranslator::~PFPhotonTranslator() {}
00103 
00104 void PFPhotonTranslator::beginRun(edm::Run& run,const edm::EventSetup & es) {
00105 
00106 }
00107 
00108 void PFPhotonTranslator::produce(edm::Event& iEvent,  
00109                                     const edm::EventSetup& iSetup) { 
00110 
00111   std::auto_ptr<reco::BasicClusterCollection> 
00112     basicClusters_p(new reco::BasicClusterCollection);
00113 
00114   std::auto_ptr<reco::PreshowerClusterCollection>
00115     psClusters_p(new reco::PreshowerClusterCollection);
00116 
00117 
00118   reco::SuperClusterCollection outputSuperClusterCollection;
00119   reco::PhotonCoreCollection outputPhotonCoreCollection;
00120   reco::PhotonCollection outputPhotonCollection;
00121 
00122   outputSuperClusterCollection.clear();
00123   outputPhotonCoreCollection.clear();
00124   outputPhotonCollection.clear();
00125 
00126 
00127   edm::Handle<reco::PFCandidateCollection> pfCandidates;
00128   bool status=fetchCandidateCollection(pfCandidates, 
00129                                        inputTagPFCandidates_, 
00130                                        iEvent );
00131 
00132   Handle<reco::VertexCollection> vertexHandle;
00133 
00134   
00135   IsolationValueMaps isolationValues(inputTagIsoVals_.size());
00136   for (size_t j = 0; j<inputTagIsoVals_.size(); ++j) {
00137     iEvent.getByLabel(inputTagIsoVals_[j], isolationValues[j]);
00138   }
00139   
00140 
00141   // clear the vectors
00142   photPFCandidateIndex_.clear();
00143   basicClusters_.clear();
00144   pfClusters_.clear();
00145   preshowerClusters_.clear();
00146   superClusters_.clear();
00147   basicClusterPtr_.clear();
00148   preshowerClusterPtr_.clear();
00149   CandidatePtr_.clear();
00150   egSCRef_.clear();
00151 
00152 
00153 
00154   // loop on the candidates 
00155   //CC@@
00156   // we need first to create AND put the SuperCluster, 
00157   // basic clusters and presh clusters collection 
00158   // in order to get a working Handle
00159   unsigned ncand=(status)?pfCandidates->size():0;
00160 
00161   unsigned iphot=0;
00162   for( unsigned i=0; i<ncand; ++i ) {
00163 
00164     const reco::PFCandidate& cand = (*pfCandidates)[i];    
00165     if(cand.particleId()!=reco::PFCandidate::gamma) continue; 
00166 
00167     photPFCandidateIndex_.push_back(i);
00168 
00169     basicClusters_.push_back(reco::BasicClusterCollection());
00170     pfClusters_.push_back(std::vector<const reco::PFCluster *>());
00171     preshowerClusters_.push_back(reco::PreshowerClusterCollection());
00172     superClusters_.push_back(reco::SuperClusterCollection());
00173 
00174     reco::PFCandidatePtr ptrToPFPhoton(pfCandidates,i);
00175     CandidatePtr_.push_back(ptrToPFPhoton);  
00176     egSCRef_.push_back(cand.superClusterRef());
00177     //std::cout << "PFPhoton cand " << iphot << std::endl;
00178 
00179     //std::cout << "Cand elements in blocks : " << cand.elementsInBlocks().size() << std::endl;
00180 
00181     for(unsigned iele=0; iele<cand.elementsInBlocks().size(); ++iele) {
00182       // first get the block 
00183       reco::PFBlockRef blockRef = cand.elementsInBlocks()[iele].first;
00184       //
00185       unsigned elementIndex = cand.elementsInBlocks()[iele].second;
00186       // check it actually exists 
00187       if(blockRef.isNull()) continue;
00188       
00189       // then get the elements of the block
00190       const edm::OwnVector< reco::PFBlockElement >&  elements = (*blockRef).elements();
00191       
00192       const reco::PFBlockElement & pfbe (elements[elementIndex]); 
00193       // The first ECAL element should be the cluster associated to the GSF; defined as the seed
00194       if(pfbe.type()==reco::PFBlockElement::ECAL)
00195         {         
00196 
00197           //std::cout << "BlockElement ECAL" << std::endl;
00198           // the Brem photons are saved as daughter PFCandidate; this 
00199           // is convenient to access the corrected energy
00200           //      std::cout << " Found candidate "  << correspondingDaughterCandidate(coCandidate,pfbe) << " " << coCandidate << std::endl;
00201           createBasicCluster(pfbe,basicClusters_[iphot],pfClusters_[iphot],correspondingDaughterCandidate(cand,pfbe));
00202         }
00203       if(pfbe.type()==reco::PFBlockElement::PS1)
00204         {
00205           //std::cout << "BlockElement PS1" << std::endl;
00206           createPreshowerCluster(pfbe,preshowerClusters_[iphot],1);
00207         }
00208       if(pfbe.type()==reco::PFBlockElement::PS2)
00209         {
00210           //std::cout << "BlockElement PS2" << std::endl;
00211           createPreshowerCluster(pfbe,preshowerClusters_[iphot],2);
00212         }    
00213 
00214     }   // loop on the elements
00215 
00216         // save the basic clusters
00217     basicClusters_p->insert(basicClusters_p->end(),basicClusters_[iphot].begin(), basicClusters_[iphot].end());
00218     // save the preshower clusters
00219     psClusters_p->insert(psClusters_p->end(),preshowerClusters_[iphot].begin(),preshowerClusters_[iphot].end());
00220 
00221     ++iphot;
00222 
00223   } // loop on PFCandidates
00224 
00225 
00226    //Save the basic clusters and get an handle as to be able to create valid Refs (thanks to Claude)
00227   //  std::cout << " Number of basic clusters " << basicClusters_p->size() << std::endl;
00228   const edm::OrphanHandle<reco::BasicClusterCollection> bcRefProd = 
00229     iEvent.put(basicClusters_p,PFBasicClusterCollection_);
00230 
00231   //preshower clusters
00232   const edm::OrphanHandle<reco::PreshowerClusterCollection> psRefProd = 
00233     iEvent.put(psClusters_p,PFPreshowerClusterCollection_);
00234 
00235   // now that the Basic clusters are in the event, the Ref can be created
00236   createBasicClusterPtrs(bcRefProd);
00237   // now that the preshower clusters are in the event, the Ref can be created
00238   createPreshowerClusterPtrs(psRefProd);
00239 
00240   // and now the Super cluster can be created with valid references  
00241   //if(status) createSuperClusters(*pfCandidates,*superClusters_p);
00242   if(status) createSuperClusters(*pfCandidates,outputSuperClusterCollection);
00243   
00244   //std::cout << "nb superclusters in collection : "<<outputSuperClusterCollection.size()<<std::endl;
00245 
00246   // Let's put the super clusters in the event
00247   std::auto_ptr<reco::SuperClusterCollection> superClusters_p(new reco::SuperClusterCollection(outputSuperClusterCollection));  
00248   const edm::OrphanHandle<reco::SuperClusterCollection> scRefProd = iEvent.put(superClusters_p,PFSuperClusterCollection_); 
00249 
00250   /*
00251   int ipho=0;
00252   for (reco::SuperClusterCollection::const_iterator gamIter = scRefProd->begin(); gamIter != scRefProd->end(); ++gamIter){
00253     std::cout << "SC i="<<ipho<<" energy="<<gamIter->energy()<<std::endl;
00254     ipho++;
00255   }
00256   */
00257 
00258   
00259   //create photon cores
00260   //if(status) createPhotonCores(pfCandidates, scRefProd, *photonCores_p);
00261   if(status) createPhotonCores(scRefProd, outputPhotonCoreCollection);
00262   
00263   //std::cout << "nb photoncores in collection : "<<outputPhotonCoreCollection.size()<<std::endl;
00264 
00265   // Put the photon cores in the event
00266   std::auto_ptr<reco::PhotonCoreCollection> photonCores_p(new reco::PhotonCoreCollection(outputPhotonCoreCollection));  
00267   //std::cout << "photon core collection put in auto_ptr"<<std::endl;
00268   const edm::OrphanHandle<reco::PhotonCoreCollection> pcRefProd = iEvent.put(photonCores_p,PFPhotonCoreCollection_); 
00269 
00270   //std::cout << "photon core have been put in the event"<<std::endl;
00271   /*
00272   ipho=0;
00273   for (reco::PhotonCoreCollection::const_iterator gamIter = pcRefProd->begin(); gamIter != pcRefProd->end(); ++gamIter){
00274     std::cout << "PhotonCore i="<<ipho<<" energy="<<gamIter->pfSuperCluster()->energy()<<std::endl;
00275     ipho++;
00276   }
00277   */
00278 
00279   //load vertices
00280   reco::VertexCollection vertexCollection;
00281   bool validVertex=true;
00282   iEvent.getByLabel(vertexProducer_, vertexHandle);
00283   if (!vertexHandle.isValid()) {
00284     edm::LogWarning("PhotonProducer") << "Error! Can't get the product primary Vertex Collection "<< "\n";
00285     validVertex=false;
00286   }
00287   if (validVertex) vertexCollection = *(vertexHandle.product());
00288 
00289   //load Ecal rechits
00290   bool validEcalRecHits=true;
00291   Handle<EcalRecHitCollection> barrelHitHandle;
00292   EcalRecHitCollection barrelRecHits;
00293   iEvent.getByLabel(barrelEcalHits_, barrelHitHandle);
00294   if (!barrelHitHandle.isValid()) {
00295     edm::LogError("PhotonProducer") << "Error! Can't get the product "<<barrelEcalHits_.label();
00296     validEcalRecHits=false; 
00297   }
00298   if (  validEcalRecHits)  barrelRecHits = *(barrelHitHandle.product());
00299   
00300   Handle<EcalRecHitCollection> endcapHitHandle;
00301   iEvent.getByLabel(endcapEcalHits_, endcapHitHandle);
00302   EcalRecHitCollection endcapRecHits;
00303   if (!endcapHitHandle.isValid()) {
00304     edm::LogError("PhotonProducer") << "Error! Can't get the product "<<endcapEcalHits_.label();
00305     validEcalRecHits=false; 
00306   }
00307   if( validEcalRecHits) endcapRecHits = *(endcapHitHandle.product());
00308 
00309   //load detector topology & geometry
00310   iSetup.get<CaloGeometryRecord>().get(theCaloGeom_);
00311 
00312   edm::ESHandle<CaloTopology> pTopology;
00313   iSetup.get<CaloTopologyRecord>().get(theCaloTopo_);
00314   const CaloTopology *topology = theCaloTopo_.product();
00315 
00316   // get Hcal towers collection 
00317   Handle<CaloTowerCollection> hcalTowersHandle;
00318   iEvent.getByLabel(hcalTowers_, hcalTowersHandle);
00319 
00320   //create photon collection
00321   if(status) createPhotons(vertexCollection, pcRefProd, topology, &barrelRecHits, &endcapRecHits, hcalTowersHandle, isolationValues, outputPhotonCollection);
00322 
00323   // Put the photons in the event
00324   std::auto_ptr<reco::PhotonCollection> photons_p(new reco::PhotonCollection(outputPhotonCollection));  
00325   //std::cout << "photon collection put in auto_ptr"<<std::endl;
00326   const edm::OrphanHandle<reco::PhotonCollection> photonRefProd = iEvent.put(photons_p,PFPhotonCollection_); 
00327 
00328   //std::cout << "photons have been put in the event"<<std::endl;
00329 
00330   /*
00331   ipho=0;
00332   for (reco::PhotonCollection::const_iterator gamIter = photonRefProd->begin(); gamIter != photonRefProd->end(); ++gamIter){
00333     std::cout << "Photon i="<<ipho<<" energy="<<gamIter->pfSuperCluster()->energy()<<std::endl;
00334     ipho++;
00335   }
00336   */
00337 
00338 
00339   
00340 }
00341 
00342 bool PFPhotonTranslator::fetchCandidateCollection(edm::Handle<reco::PFCandidateCollection>& c, 
00343                                               const edm::InputTag& tag, 
00344                                               const edm::Event& iEvent) const {  
00345   bool found = iEvent.getByLabel(tag, c);
00346 
00347   if(!found && !emptyIsOk_)
00348     {
00349       std::ostringstream  err;
00350       err<<" cannot get PFCandidates: "
00351          <<tag<<std::endl;
00352       edm::LogError("PFPhotonTranslator")<<err.str();
00353     }
00354   return found;
00355       
00356 }
00357 
00358 // The basic cluster is a copy of the PFCluster -> the energy is not corrected 
00359 // It should be possible to get the corrected energy (including the associated PS energy)
00360 // from the PFCandidate daugthers ; Needs some work 
00361 void PFPhotonTranslator::createBasicCluster(const reco::PFBlockElement & PFBE, 
00362                                               reco::BasicClusterCollection & basicClusters, 
00363                                               std::vector<const reco::PFCluster *> & pfClusters,
00364                                               const reco::PFCandidate & coCandidate) const
00365 {
00366   reco::PFClusterRef myPFClusterRef = PFBE.clusterRef();
00367   if(myPFClusterRef.isNull()) return;  
00368 
00369   const reco::PFCluster & myPFCluster (*myPFClusterRef);
00370   pfClusters.push_back(&myPFCluster);
00371   //std::cout << " Creating BC " << myPFCluster.energy() << " " << coCandidate.ecalEnergy() <<" "<<  coCandidate.rawEcalEnergy() <<std::endl;
00372   //std::cout << " # hits " << myPFCluster.hitsAndFractions().size() << std::endl;
00373 
00374 //  basicClusters.push_back(reco::CaloCluster(myPFCluster.energy(),
00375   basicClusters.push_back(reco::CaloCluster(coCandidate.rawEcalEnergy(),
00376                                             myPFCluster.position(),
00377                                             myPFCluster.caloID(),
00378                                             myPFCluster.hitsAndFractions(),
00379                                             myPFCluster.algo(),
00380                                             myPFCluster.seed()));
00381 }
00382 
00383 void PFPhotonTranslator::createPreshowerCluster(const reco::PFBlockElement & PFBE, reco::PreshowerClusterCollection& preshowerClusters,unsigned plane) const
00384 {
00385   reco::PFClusterRef  myPFClusterRef= PFBE.clusterRef();
00386   preshowerClusters.push_back(reco::PreshowerCluster(myPFClusterRef->energy(),myPFClusterRef->position(),
00387                                                myPFClusterRef->hitsAndFractions(),plane));
00388 }
00389 
00390 void PFPhotonTranslator::createBasicClusterPtrs(const edm::OrphanHandle<reco::BasicClusterCollection> & basicClustersHandle )
00391 {
00392   unsigned size=photPFCandidateIndex_.size();
00393   unsigned basicClusterCounter=0;
00394   basicClusterPtr_.resize(size);
00395 
00396   for(unsigned iphot=0;iphot<size;++iphot) // loop on tracks
00397     {
00398       unsigned nbc=basicClusters_[iphot].size();
00399       for(unsigned ibc=0;ibc<nbc;++ibc) // loop on basic clusters
00400         {
00401           //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
00402           reco::CaloClusterPtr bcPtr(basicClustersHandle,basicClusterCounter);
00403           basicClusterPtr_[iphot].push_back(bcPtr);
00404           ++basicClusterCounter;
00405         }
00406     }
00407 }
00408 
00409 void PFPhotonTranslator::createPreshowerClusterPtrs(const edm::OrphanHandle<reco::PreshowerClusterCollection> & preshowerClustersHandle )
00410 {
00411   unsigned size=photPFCandidateIndex_.size();
00412   unsigned psClusterCounter=0;
00413   preshowerClusterPtr_.resize(size);
00414 
00415   for(unsigned iphot=0;iphot<size;++iphot) // loop on tracks
00416     {
00417       unsigned nbc=preshowerClusters_[iphot].size();
00418       for(unsigned ibc=0;ibc<nbc;++ibc) // loop on basic clusters
00419         {
00420           //      std::cout <<  "Track "<< iGSF << " ref " << basicClusterCounter << std::endl;
00421           reco::CaloClusterPtr psPtr(preshowerClustersHandle,psClusterCounter);
00422           preshowerClusterPtr_[iphot].push_back(psPtr);
00423           ++psClusterCounter;
00424         }
00425     }
00426 }
00427 
00428 void PFPhotonTranslator::createSuperClusters(const reco::PFCandidateCollection & pfCand,
00429                                                reco::SuperClusterCollection &superClusters) const
00430 {
00431   unsigned nphot=photPFCandidateIndex_.size();
00432   for(unsigned iphot=0;iphot<nphot;++iphot)
00433     {
00434 
00435       //cout << "SC iphot=" << iphot << endl;
00436 
00437       // Computes energy position a la e/gamma 
00438       double sclusterE=0;
00439       double posX=0.;
00440       double posY=0.;
00441       double posZ=0.;
00442       
00443       unsigned nbasics=basicClusters_[iphot].size();
00444       for(unsigned ibc=0;ibc<nbasics;++ibc)
00445         {
00446           //cout << "BC in SC : iphot="<<iphot<<endl;
00447           
00448           double e = basicClusters_[iphot][ibc].energy();
00449           sclusterE += e;
00450           posX += e * basicClusters_[iphot][ibc].position().X();
00451           posY += e * basicClusters_[iphot][ibc].position().Y();
00452           posZ += e * basicClusters_[iphot][ibc].position().Z();          
00453         }
00454       posX /=sclusterE;
00455       posY /=sclusterE;
00456       posZ /=sclusterE;
00457       
00458       /*
00459       if(pfCand[gsfPFCandidateIndex_[iphot]].gsfTrackRef()!=GsfTrackRef_[iphot])
00460         {
00461           edm::LogError("PFElectronTranslator") << " Major problem in PFElectron Translator" << std::endl;
00462         }
00463       */      
00464 
00465       // compute the width
00466       PFClusterWidthAlgo pfwidth(pfClusters_[iphot]);
00467       
00468       double correctedEnergy=pfCand[photPFCandidateIndex_[iphot]].ecalEnergy();
00469       reco::SuperCluster mySuperCluster(correctedEnergy,math::XYZPoint(posX,posY,posZ));
00470       // protection against empty basic cluster collection ; the value is -2 in this case
00471       if(nbasics)
00472         {
00473 //        std::cout << "SuperCluster creation; energy " << pfCand[gsfPFCandidateIndex_[iphot]].ecalEnergy();
00474 //        std::cout << " " <<   pfCand[gsfPFCandidateIndex_[iphot]].rawEcalEnergy() << std::endl;
00475 //        std::cout << "Seed energy from basic " << basicClusters_[iphot][0].energy() << std::endl;
00476           mySuperCluster.setSeed(basicClusterPtr_[iphot][0]);
00477         }
00478       else
00479         {
00480           //      std::cout << "SuperCluster creation ; seed energy " << 0 << std::endl;
00481           //std::cout << "SuperCluster creation ; energy " << pfCand[photPFCandidateIndex_[iphot]].ecalEnergy();
00482           //std::cout << " " <<   pfCand[photPFCandidateIndex_[iphot]].rawEcalEnergy() << std::endl;
00483 //        std::cout << " No seed found " << 0 << std::endl;       
00484 //        std::cout << " MVA " << pfCand[gsfPFCandidateIndex_[iphot]].mva_e_pi() << std::endl;
00485           mySuperCluster.setSeed(reco::CaloClusterPtr());
00486         }
00487       // the seed should be the first basic cluster
00488 
00489       for(unsigned ibc=0;ibc<nbasics;++ibc)
00490         {
00491           mySuperCluster.addCluster(basicClusterPtr_[iphot][ibc]);
00492           //      std::cout <<"Adding Ref to SC " << basicClusterPtr_[iphot][ibc].index() << std::endl;
00493           const std::vector< std::pair<DetId, float> > & v1 = basicClusters_[iphot][ibc].hitsAndFractions();
00494           //      std::cout << " Number of cells " << v1.size() << std::endl;
00495           for( std::vector< std::pair<DetId, float> >::const_iterator diIt = v1.begin();
00496                diIt != v1.end();
00497                ++diIt ) {
00498             //      std::cout << " Adding DetId " << (diIt->first).rawId() << " " << diIt->second << std::endl;
00499             mySuperCluster.addHitAndFraction(diIt->first,diIt->second);
00500           } // loop over rechits      
00501         }      
00502 
00503       unsigned nps=preshowerClusterPtr_[iphot].size();
00504       for(unsigned ips=0;ips<nps;++ips)
00505         {
00506           mySuperCluster.addPreshowerCluster(preshowerClusterPtr_[iphot][ips]);
00507         }
00508       
00509 
00510       // Set the preshower energy
00511       mySuperCluster.setPreshowerEnergy(pfCand[photPFCandidateIndex_[iphot]].pS1Energy()+
00512                                         pfCand[photPFCandidateIndex_[iphot]].pS2Energy());
00513 
00514       // Set the cluster width
00515       mySuperCluster.setEtaWidth(pfwidth.pflowEtaWidth());
00516       mySuperCluster.setPhiWidth(pfwidth.pflowPhiWidth());
00517       // Force the computation of rawEnergy_ of the reco::SuperCluster
00518       mySuperCluster.rawEnergy();
00519 
00520       //cout << "SC energy="<< mySuperCluster.energy()<<endl;
00521 
00522       superClusters.push_back(mySuperCluster);
00523       //std::cout << "nb super clusters in collection : "<<superClusters.size()<<std::endl;
00524    }
00525 }
00526 
00527 void PFPhotonTranslator::createPhotonCores(const edm::OrphanHandle<reco::SuperClusterCollection> & superClustersHandle, reco::PhotonCoreCollection &photonCores)
00528 {
00529   
00530   //std::cout << "createPhotonCores" << std::endl;
00531 
00532   unsigned nphot=photPFCandidateIndex_.size();
00533 
00534   for(unsigned iphot=0;iphot<nphot;++iphot)
00535     {
00536       //std::cout << "iphot="<<iphot<<std::endl;
00537 
00538       reco::PhotonCore myPhotonCore;
00539 
00540       reco::SuperClusterRef SCref(reco::SuperClusterRef(superClustersHandle, iphot));
00541       
00542       myPhotonCore.setPFlowPhoton(true);
00543       myPhotonCore.setStandardPhoton(false);
00544       myPhotonCore.setPflowSuperCluster(SCref);
00545       myPhotonCore.setSuperCluster(egSCRef_[iphot]);
00546       photonCores.push_back(myPhotonCore);
00547       
00548     }
00549 
00550   //std::cout << "end of createPhotonCores"<<std::endl;
00551 }
00552 
00553 void PFPhotonTranslator::createPhotons(reco::VertexCollection &vertexCollection, const edm::OrphanHandle<reco::PhotonCoreCollection> & photonCoresHandle, const CaloTopology* topology, const EcalRecHitCollection* barrelRecHits, const EcalRecHitCollection* endcapRecHits, const edm::Handle<CaloTowerCollection> & hcalTowersHandle, const IsolationValueMaps& isolationValues, reco::PhotonCollection &photons)
00554 {
00555 
00556   //cout << "createPhotons" << endl;
00557   
00558   unsigned nphot=photPFCandidateIndex_.size();
00559 
00560   for(unsigned iphot=0;iphot<nphot;++iphot)
00561     {
00562       //std::cout << "iphot="<<iphot<<std::endl;
00563 
00564       reco::PhotonCoreRef PCref(reco::PhotonCoreRef(photonCoresHandle, iphot));
00565 
00566       math::XYZPoint vtx(0.,0.,0.);
00567       if (vertexCollection.size()>0) vtx = vertexCollection.begin()->position();
00568       //std::cout << "vtx made" << std::endl;
00569 
00570       math::XYZVector direction =  PCref->pfSuperCluster()->position() - vtx;
00571 
00572       //It could be that pfSC energy gives not the best resolution : use smaller agregates for some cases ?
00573       math::XYZVector P3 = direction.unit() * PCref->pfSuperCluster()->energy();
00574       LorentzVector P4(P3.x(), P3.y(), P3.z(), PCref->pfSuperCluster()->energy());
00575 
00576       reco::Photon myPhoton(P4, PCref->pfSuperCluster()->position(), PCref, vtx);
00577       //cout << "photon created"<<endl;
00578       
00579 
00580       reco::Photon::PflowIsolationVariables myPFIso;
00581       myPFIso.chargedHadronIso=(*isolationValues[0])[CandidatePtr_[iphot]];
00582       myPFIso.photonIso=(*isolationValues[1])[CandidatePtr_[iphot]];
00583       myPFIso.neutralHadronIso=(*isolationValues[2])[CandidatePtr_[iphot]];   
00584       myPhoton.setPflowIsolationVariables(myPFIso);
00585       
00586       //cout << "chargedHadronIso="<<myPhoton.chargedHadronIso()<<" photonIso="<<myPhoton.photonIso()<<" neutralHadronIso="<<myPhoton.neutralHadronIso()<<endl;
00587       
00588 
00589       if (basicClusters_[iphot].size()>0){
00590       // Cluster shape variables
00591       //Algorithms from EcalClusterTools could be adapted to PF photons ? (not based on 5x5 BC)
00592       //It happens that energy computed in eg e5x5 is greater than pfSC energy (EcalClusterTools gathering energies from adjacent crystals even if not belonging to the SC)
00593       const EcalRecHitCollection* hits = 0 ;
00594       int subdet = PCref->pfSuperCluster()->seed()->hitsAndFractions()[0].first.subdetId();
00595       if (subdet==EcalBarrel) hits = barrelRecHits;
00596       else if  (subdet==EcalEndcap) hits = endcapRecHits;
00597       const CaloGeometry* geometry = theCaloGeom_.product();
00598 
00599       float maxXtal =   EcalClusterTools::eMax( *(PCref->pfSuperCluster()->seed()), &(*hits) );
00600       //cout << "maxXtal="<<maxXtal<<endl;
00601       float e1x5    =   EcalClusterTools::e1x5(  *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology)); 
00602       //cout << "e1x5="<<e1x5<<endl;
00603       float e2x5    =   EcalClusterTools::e2x5Max(  *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology)); 
00604       //cout << "e2x5="<<e2x5<<endl;
00605       float e3x3    =   EcalClusterTools::e3x3(  *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology)); 
00606       //cout << "e3x3="<<e3x3<<endl;
00607       float e5x5    =   EcalClusterTools::e5x5( *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology)); 
00608       //cout << "e5x5="<<e5x5<<endl;
00609       std::vector<float> cov =  EcalClusterTools::covariances( *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology), geometry); 
00610       float sigmaEtaEta = sqrt(cov[0]);
00611       //cout << "sigmaEtaEta="<<sigmaEtaEta<<endl;
00612       std::vector<float> locCov =  EcalClusterTools::localCovariances( *(PCref->pfSuperCluster()->seed()), &(*hits), &(*topology)); 
00613       float sigmaIetaIeta = sqrt(locCov[0]);
00614       //cout << "sigmaIetaIeta="<<sigmaIetaIeta<<endl;
00615       //float r9 =e3x3/(PCref->pfSuperCluster()->rawEnergy());
00616 
00617 
00618       // calculate HoE
00619       const CaloTowerCollection* hcalTowersColl = hcalTowersHandle.product();
00620       EgammaTowerIsolation towerIso1(hOverEConeSize_,0.,0.,1,hcalTowersColl) ;  
00621       EgammaTowerIsolation towerIso2(hOverEConeSize_,0.,0.,2,hcalTowersColl) ;  
00622       double HoE1=towerIso1.getTowerESum(&(*PCref->pfSuperCluster()))/PCref->pfSuperCluster()->energy();
00623       double HoE2=towerIso2.getTowerESum(&(*PCref->pfSuperCluster()))/PCref->pfSuperCluster()->energy(); 
00624       //cout << "HoE1="<<HoE1<<endl;
00625       //cout << "HoE2="<<HoE2<<endl;  
00626 
00627       reco::Photon::ShowerShape  showerShape;
00628       showerShape.e1x5= e1x5;
00629       showerShape.e2x5= e2x5;
00630       showerShape.e3x3= e3x3;
00631       showerShape.e5x5= e5x5;
00632       showerShape.maxEnergyXtal =  maxXtal;
00633       showerShape.sigmaEtaEta =    sigmaEtaEta;
00634       showerShape.sigmaIetaIeta =  sigmaIetaIeta;
00635       showerShape.hcalDepth1OverEcal = HoE1;
00636       showerShape.hcalDepth2OverEcal = HoE2;
00637       myPhoton.setShowerShapeVariables ( showerShape ); 
00638       //cout << "shower shape variables filled"<<endl;
00639       }
00640 
00641       photons.push_back(myPhoton);
00642 
00643     }
00644 
00645   //std::cout << "end of createPhotons"<<std::endl;
00646 }
00647 
00648 
00649 const reco::PFCandidate & PFPhotonTranslator::correspondingDaughterCandidate(const reco::PFCandidate & cand, const reco::PFBlockElement & pfbe) const
00650 {
00651   unsigned refindex=pfbe.index();
00652   //  std::cout << " N daughters " << cand.numberOfDaughters() << std::endl;
00653   reco::PFCandidate::const_iterator myDaughterCandidate=cand.begin();
00654   reco::PFCandidate::const_iterator itend=cand.end();
00655 
00656   for(;myDaughterCandidate!=itend;++myDaughterCandidate)
00657     {
00658       const reco::PFCandidate * myPFCandidate = (const reco::PFCandidate*)&*myDaughterCandidate;
00659       if(myPFCandidate->elementsInBlocks().size()!=1)
00660         {
00661           //      std::cout << " Daughter with " << myPFCandidate.elementsInBlocks().size()<< " element in block " << std::endl;
00662           return cand;
00663         }
00664       if(myPFCandidate->elementsInBlocks()[0].second==refindex) 
00665         {
00666           //      std::cout << " Found it " << cand << std::endl;
00667           return *myPFCandidate;
00668         }      
00669     }
00670   return cand;
00671 }
00672