CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoParticleFlow/PFTracking/plugins/PFElecTkProducer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    PFTracking
00004 // Class:      PFElecTkProducer
00005 // 
00006 // Original Author:  Michele Pioppi
00007 //         Created:  Tue Jan 23 15:26:39 CET 2007
00008 
00009 
00010 
00011 // system include files
00012 #include <memory>
00013 
00014 // user include files
00015 #include "RecoParticleFlow/PFTracking/interface/PFElecTkProducer.h"
00016 #include "RecoParticleFlow/PFTracking/interface/PFTrackTransformer.h"
00017 #include "RecoParticleFlow/PFTracking/interface/ConvBremPFTrackFinder.h"
00018 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
00019 #include "MagneticField/Engine/interface/MagneticField.h"
00020 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00021 #include "FWCore/Framework/interface/ESHandle.h"
00022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00023 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00024 #include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
00025 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
00026 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
00027 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00028 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00029 #include "MagneticField/Engine/interface/MagneticField.h"
00030 #include "DataFormats/ParticleFlowReco/interface/PFClusterFwd.h"
00031 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00032 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00033 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00034 #include "DataFormats/VertexReco/interface/Vertex.h"
00035 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00036 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedTrackerVertex.h"
00037 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertexFwd.h"
00038 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
00039 #include "DataFormats/ParticleFlowReco/interface/PFConversionFwd.h"
00040 #include "DataFormats/ParticleFlowReco/interface/PFConversion.h"
00041 #include "DataFormats/ParticleFlowReco/interface/PFV0Fwd.h"
00042 #include "DataFormats/ParticleFlowReco/interface/PFV0.h"
00043 #include "RecoParticleFlow/PFClusterTools/interface/LinkByRecHit.h"
00044 #include "RecoParticleFlow/PFClusterTools/interface/ClusterClusterMapping.h"
00045 
00046 #include "TMath.h"
00047 using namespace std;
00048 using namespace edm;
00049 using namespace reco;
00050 PFElecTkProducer::PFElecTkProducer(const ParameterSet& iConfig):
00051   conf_(iConfig),
00052   pfTransformer_(0),
00053   convBremFinder_(0)
00054 {
00055   LogInfo("PFElecTkProducer")<<"PFElecTkProducer started";
00056 
00057   gsfTrackLabel_ = iConfig.getParameter<InputTag>
00058     ("GsfTrackModuleLabel");
00059 
00060   pfTrackLabel_ = iConfig.getParameter<InputTag>
00061     ("PFRecTrackLabel");
00062 
00063   primVtxLabel_ = iConfig.getParameter<InputTag>
00064     ("PrimaryVertexLabel");
00065 
00066   pfEcalClusters_ = iConfig.getParameter<InputTag>
00067     ("PFEcalClusters");
00068 
00069   pfNuclear_ = iConfig.getParameter<InputTag>
00070     ("PFNuclear");
00071   
00072   pfConv_ = iConfig.getParameter<InputTag>
00073     ("PFConversions");
00074   
00075   pfV0_ = iConfig.getParameter<InputTag>
00076     ("PFV0");
00077 
00078   useNuclear_ = iConfig.getParameter<bool>("useNuclear");
00079   useConversions_ = iConfig.getParameter<bool>("useConversions");
00080   useV0_ = iConfig.getParameter<bool>("useV0");
00081   debugGsfCleaning_ = iConfig.getParameter<bool>("debugGsfCleaning");
00082 
00083   produces<GsfPFRecTrackCollection>();
00084   produces<GsfPFRecTrackCollection>( "Secondary" ).setBranchAlias( "secondary" );
00085 
00086 
00087   trajinev_ = iConfig.getParameter<bool>("TrajInEvents");
00088   modemomentum_ = iConfig.getParameter<bool>("ModeMomentum");
00089   applySel_ = iConfig.getParameter<bool>("applyEGSelection");
00090   applyGsfClean_ = iConfig.getParameter<bool>("applyGsfTrackCleaning");
00091   applyAngularGsfClean_ = iConfig.getParameter<bool>("applyAlsoGsfAngularCleaning");
00092   detaCutGsfClean_ =  iConfig.getParameter<double>("maxDEtaGsfAngularCleaning");
00093   dphiCutGsfClean_ =  iConfig.getParameter<double>("maxDPhiBremTangGsfAngularCleaning");
00094   useFifthStepForTrackDriven_ = iConfig.getParameter<bool>("useFifthStepForTrackerDrivenGsf");
00095   useFifthStepForEcalDriven_ = iConfig.getParameter<bool>("useFifthStepForEcalDrivenGsf");
00096   maxPtConvReco_ = iConfig.getParameter<double>("MaxConvBremRecoPT");
00097   detaGsfSC_ = iConfig.getParameter<double>("MinDEtaGsfSC");
00098   dphiGsfSC_ = iConfig.getParameter<double>("MinDPhiGsfSC");
00099   SCEne_ = iConfig.getParameter<double>("MinSCEnergy");
00100   
00101   // set parameter for convBremFinder
00102   useConvBremFinder_ =     iConfig.getParameter<bool>("useConvBremFinder");
00103   mvaConvBremFinderID_
00104     = iConfig.getParameter<double>("pf_convBremFinderID_mvaCut");
00105   
00106   string mvaWeightFileConvBrem
00107     = iConfig.getParameter<string>("pf_convBremFinderID_mvaWeightFile");
00108   
00109   
00110   if(useConvBremFinder_) 
00111     path_mvaWeightFileConvBrem_ = edm::FileInPath ( mvaWeightFileConvBrem.c_str() ).fullPath();
00112 
00113 }
00114 
00115 
00116 PFElecTkProducer::~PFElecTkProducer()
00117 {
00118  
00119   delete pfTransformer_;
00120   delete convBremFinder_;
00121 }
00122 
00123 
00124 //
00125 // member functions
00126 //
00127 
00128 // ------------ method called to produce the data  ------------
00129 void
00130 PFElecTkProducer::produce(Event& iEvent, const EventSetup& iSetup)
00131 {
00132   LogDebug("PFElecTkProducer")<<"START event: "<<iEvent.id().event()
00133                               <<" in run "<<iEvent.id().run();
00134 
00135   //create the empty collections 
00136   auto_ptr< GsfPFRecTrackCollection > 
00137     gsfPFRecTrackCollection(new GsfPFRecTrackCollection);
00138 
00139   
00140   auto_ptr< GsfPFRecTrackCollection > 
00141     gsfPFRecTrackCollectionSecondary(new GsfPFRecTrackCollection);
00142 
00143   //read collections of tracks
00144   Handle<GsfTrackCollection> gsftrackscoll;
00145   iEvent.getByLabel(gsfTrackLabel_,gsftrackscoll);
00146 
00147   //read collections of trajectories
00148   Handle<vector<Trajectory> > TrajectoryCollection;
00149  
00150   //read pfrectrack collection
00151   Handle<PFRecTrackCollection> thePfRecTrackCollection;
00152   iEvent.getByLabel(pfTrackLabel_,thePfRecTrackCollection);
00153   const PFRecTrackCollection& PfRTkColl = *(thePfRecTrackCollection.product());
00154 
00155   // PFClusters
00156   Handle<PFClusterCollection> theECPfClustCollection;
00157   iEvent.getByLabel(pfEcalClusters_,theECPfClustCollection);
00158   const PFClusterCollection& theEcalClusters = *(theECPfClustCollection.product());
00159 
00160   //Primary Vertexes
00161   Handle<reco::VertexCollection> thePrimaryVertexColl;
00162   iEvent.getByLabel(primVtxLabel_,thePrimaryVertexColl);
00163 
00164 
00165 
00166   // Displaced Vertex
00167   Handle< reco::PFDisplacedTrackerVertexCollection > pfNuclears; 
00168   if( useNuclear_ ) {
00169     bool found = iEvent.getByLabel(pfNuclear_, pfNuclears);
00170     
00171     
00172     if(!found )
00173       LogError("PFElecTkProducer")<<" cannot get PFNuclear : "
00174                                   <<  pfNuclear_
00175                                   << " please set useNuclear=False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00176   }
00177 
00178   // Conversions 
00179   Handle< reco::PFConversionCollection > pfConversions;
00180   if( useConversions_ ) {
00181     bool found = iEvent.getByLabel(pfConv_,pfConversions);
00182     if(!found )
00183       LogError("PFElecTkProducer")<<" cannot get PFConversions : "
00184                                   << pfConv_ 
00185                                   << " please set useConversions=False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00186   }
00187 
00188   // V0
00189   Handle< reco::PFV0Collection > pfV0;
00190   if( useV0_ ) {
00191     bool found = iEvent.getByLabel(pfV0_, pfV0);
00192     
00193     if(!found )
00194       LogError("PFElecTkProducer")<<" cannot get PFV0 : "
00195                                   << pfV0_
00196                                   << " please set useV0=False  RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00197   }
00198   
00199   
00200 
00201   GsfTrackCollection gsftracks = *(gsftrackscoll.product());    
00202   vector<Trajectory> tjvec(0);
00203   if (trajinev_){
00204     bool foundTraj = iEvent.getByLabel(gsfTrackLabel_,TrajectoryCollection); 
00205     if(!foundTraj) 
00206       LogError("PFElecTkProducer")
00207         <<" cannot get Trajectories of : "
00208         <<  gsfTrackLabel_
00209         << " please set TrajInEvents = False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00210     
00211     tjvec= *(TrajectoryCollection.product());
00212   }
00213   
00214   
00215   vector<reco::GsfPFRecTrack> selGsfPFRecTracks;
00216   vector<reco::GsfPFRecTrack> primaryGsfPFRecTracks;
00217   std::map<unsigned int, std::vector<reco::GsfPFRecTrack> >  GsfPFMap;
00218   
00219 
00220   for (unsigned int igsf=0; igsf<gsftracks.size();igsf++) {
00221     
00222     GsfTrackRef trackRef(gsftrackscoll, igsf);
00223 
00224     int kf_ind=FindPfRef(PfRTkColl,gsftracks[igsf],false);
00225     
00226     if (kf_ind>=0) {
00227       
00228       PFRecTrackRef kf_ref(thePfRecTrackCollection,
00229                            kf_ind);
00230 
00231       // remove fifth step tracks
00232       if( useFifthStepForEcalDriven_ == false
00233           || useFifthStepForTrackDriven_ == false) {
00234         bool isFifthStepTrack = isFifthStep(kf_ref);
00235         bool isEcalDriven = true;
00236         bool isTrackerDriven = true;
00237         
00238         if (&(*trackRef->seedRef())==0) {
00239           isEcalDriven = false;
00240           isTrackerDriven = false;
00241         }
00242         else {
00243           ElectronSeedRef SeedRef= trackRef->extra()->seedRef().castTo<ElectronSeedRef>();
00244           if(SeedRef->caloCluster().isNull())
00245             isEcalDriven = false;
00246           if(SeedRef->ctfTrack().isNull())
00247             isTrackerDriven = false;
00248         }
00249         //note: the same track could be both ecalDriven and trackerDriven
00250         if(isFifthStepTrack && 
00251            isEcalDriven &&
00252            isTrackerDriven == false &&
00253            useFifthStepForEcalDriven_ == false) {
00254           continue;
00255         }
00256 
00257         if(isFifthStepTrack && 
00258            isTrackerDriven  && 
00259            isEcalDriven == false && 
00260            useFifthStepForTrackDriven_ == false) {
00261           continue;
00262         }
00263 
00264         if(isFifthStepTrack && 
00265            isTrackerDriven && 
00266            isEcalDriven && 
00267            useFifthStepForTrackDriven_ == false &&
00268            useFifthStepForEcalDriven_ == false) {
00269           continue;
00270         }
00271       }
00272       
00273       pftrack_=GsfPFRecTrack( gsftracks[igsf].charge(), 
00274                               reco::PFRecTrack::GSF, 
00275                               igsf, trackRef,
00276                               kf_ref);
00277     } else  {
00278       PFRecTrackRef dummyRef;
00279       pftrack_=GsfPFRecTrack( gsftracks[igsf].charge(), 
00280                               reco::PFRecTrack::GSF, 
00281                               igsf, trackRef,
00282                               dummyRef);
00283     }
00284     
00285     
00286     bool validgsfbrem = false;
00287     if(trajinev_) {
00288       validgsfbrem = pfTransformer_->addPointsAndBrems(pftrack_, 
00289                                                        gsftracks[igsf], 
00290                                                        tjvec[igsf],
00291                                                        modemomentum_);
00292     } else {
00293       validgsfbrem = pfTransformer_->addPointsAndBrems(pftrack_, 
00294                                                        gsftracks[igsf], 
00295                                                        mtsTransform_);
00296     }
00297     
00298     bool passSel = true;
00299     if(applySel_) 
00300       passSel = applySelection(gsftracks[igsf]);      
00301 
00302     if(validgsfbrem && passSel) 
00303       selGsfPFRecTracks.push_back(pftrack_);
00304   }
00305   
00306 
00307   unsigned int count_primary = 0;
00308   if(selGsfPFRecTracks.size() > 0) {
00309     for(unsigned int ipfgsf=0; ipfgsf<selGsfPFRecTracks.size();ipfgsf++) {
00310       
00311       vector<unsigned int> secondaries(0);
00312       secondaries.clear();
00313       bool keepGsf = true;
00314 
00315       if(applyGsfClean_) {
00316         keepGsf = resolveGsfTracks(selGsfPFRecTracks,ipfgsf,secondaries,theEcalClusters);
00317       }
00318  
00319       //is primary? 
00320       if(keepGsf == true) {
00321 
00322         // Find kf tracks from converted brem photons
00323         if(convBremFinder_->foundConvBremPFRecTrack(thePfRecTrackCollection,thePrimaryVertexColl,
00324                                                     pfNuclears,pfConversions,pfV0,
00325                                                     useNuclear_,useConversions_,useV0_,
00326                                                     theEcalClusters,selGsfPFRecTracks[ipfgsf])) {
00327           const vector<PFRecTrackRef>& convBremPFRecTracks(convBremFinder_->getConvBremPFRecTracks());
00328           for(unsigned int ii = 0; ii<convBremPFRecTracks.size(); ii++) {
00329             selGsfPFRecTracks[ipfgsf].addConvBremPFRecTrackRef(convBremPFRecTracks[ii]);
00330           }
00331         }
00332         
00333         // save primaries gsf tracks
00334         //      gsfPFRecTrackCollection->push_back(selGsfPFRecTracks[ipfgsf]);
00335         primaryGsfPFRecTracks.push_back(selGsfPFRecTracks[ipfgsf]);
00336         
00337         
00338         // NOTE:: THE TRACKID IS USED TO LINK THE PRIMARY GSF TRACK. THIS NEEDS 
00339         // TO BE CHANGED AS SOON AS IT IS POSSIBLE TO CHANGE DATAFORMATS
00340         // A MODIFICATION HERE IMPLIES A MODIFICATION IN PFBLOCKALGO.CC/H
00341         unsigned int primGsfIndex = selGsfPFRecTracks[ipfgsf].trackId();
00342         vector<reco::GsfPFRecTrack> trueGsfPFRecTracks;
00343         if(secondaries.size() > 0) {
00344           // loop on secondaries gsf tracks (from converted brems)
00345           for(unsigned int isecpfgsf=0; isecpfgsf<secondaries.size();isecpfgsf++) {
00346             
00347             PFRecTrackRef refsecKF =  selGsfPFRecTracks[(secondaries[isecpfgsf])].kfPFRecTrackRef();
00348             
00349             unsigned int secGsfIndex = selGsfPFRecTracks[(secondaries[isecpfgsf])].trackId();
00350             GsfTrackRef secGsfRef = selGsfPFRecTracks[(secondaries[isecpfgsf])].gsfTrackRef();
00351 
00352             if(refsecKF.isNonnull()) {
00353               // NOTE::IT SAVED THE TRACKID OF THE PRIMARY!!! THIS IS USED IN PFBLOCKALGO.CC/H
00354               secpftrack_= GsfPFRecTrack( gsftracks[secGsfIndex].charge(), 
00355                                           reco::PFRecTrack::GSF, 
00356                                           primGsfIndex, secGsfRef,
00357                                           refsecKF);
00358             }
00359             else{
00360               PFRecTrackRef dummyRef;
00361               // NOTE::IT SAVED THE TRACKID OF THE PRIMARY!!! THIS IS USED IN PFBLOCKALGO.CC/H
00362               secpftrack_= GsfPFRecTrack( gsftracks[secGsfIndex].charge(), 
00363                                           reco::PFRecTrack::GSF, 
00364                                           primGsfIndex, secGsfRef,
00365                                           dummyRef);
00366             }
00367 
00368             bool validgsfbrem = false;
00369             if(trajinev_) {
00370               validgsfbrem = pfTransformer_->addPointsAndBrems(secpftrack_,
00371                                                                gsftracks[secGsfIndex], 
00372                                                                tjvec[secGsfIndex],
00373                                                                modemomentum_);
00374             } else {
00375               validgsfbrem = pfTransformer_->addPointsAndBrems(secpftrack_,
00376                                                                gsftracks[secGsfIndex], 
00377                                                                mtsTransform_);
00378             }         
00379 
00380             if(validgsfbrem) {
00381               gsfPFRecTrackCollectionSecondary->push_back(secpftrack_);
00382               trueGsfPFRecTracks.push_back(secpftrack_);
00383             }       
00384           }
00385         }
00386         GsfPFMap.insert(pair<unsigned int,std::vector<reco::GsfPFRecTrack> >(count_primary,trueGsfPFRecTracks));
00387         trueGsfPFRecTracks.clear();
00388         count_primary++;
00389       }
00390     }
00391   }
00392   
00393   
00394   const edm::OrphanHandle<GsfPFRecTrackCollection> gsfPfRefProd = 
00395     iEvent.put(gsfPFRecTrackCollectionSecondary,"Secondary");
00396   
00397   
00398   //now the secondary GsfPFRecTracks are in the event, the Ref can be created
00399   createGsfPFRecTrackRef(gsfPfRefProd,primaryGsfPFRecTracks,GsfPFMap);
00400   
00401   for(unsigned int iGSF = 0; iGSF<primaryGsfPFRecTracks.size();iGSF++){
00402     gsfPFRecTrackCollection->push_back(primaryGsfPFRecTracks[iGSF]);
00403   }
00404   iEvent.put(gsfPFRecTrackCollection);
00405 
00406   selGsfPFRecTracks.clear();
00407   GsfPFMap.clear();
00408   primaryGsfPFRecTracks.clear();
00409 }
00410 
00411 // create the secondary GsfPFRecTracks Ref
00412 void
00413 PFElecTkProducer::createGsfPFRecTrackRef(const edm::OrphanHandle<reco::GsfPFRecTrackCollection>& gsfPfHandle,
00414                                          std::vector<reco::GsfPFRecTrack>& gsfPFRecTrackPrimary,
00415                                          const std::map<unsigned int, std::vector<reco::GsfPFRecTrack> >& MapPrimSec) {
00416   unsigned int cgsf=0;
00417   unsigned int csecgsf=0;
00418   for (std::map<unsigned int, std::vector<reco::GsfPFRecTrack> >::const_iterator igsf = MapPrimSec.begin();
00419        igsf != MapPrimSec.end(); igsf++,cgsf++) {
00420     vector<reco::GsfPFRecTrack> SecGsfPF = igsf->second;
00421     for (unsigned int iSecGsf=0; iSecGsf < SecGsfPF.size(); iSecGsf++) {
00422       edm::Ref<reco::GsfPFRecTrackCollection> refgprt(gsfPfHandle,csecgsf);
00423       gsfPFRecTrackPrimary[cgsf].addConvBremGsfPFRecTrackRef(refgprt);
00424       ++csecgsf;
00425     }
00426   }
00427 
00428   return;
00429 }
00430 // ------------- method for find the corresponding kf pfrectrack ---------------------
00431 int
00432 PFElecTkProducer::FindPfRef(const reco::PFRecTrackCollection  & PfRTkColl, 
00433                             reco::GsfTrack gsftk,
00434                             bool otherColl){
00435 
00436 
00437   if (&(*gsftk.seedRef())==0) return -1;
00438   ElectronSeedRef ElSeedRef=gsftk.extra()->seedRef().castTo<ElectronSeedRef>();
00439   //CASE 1 ELECTRONSEED DOES NOT HAVE A REF TO THE CKFTRACK
00440   if (ElSeedRef->ctfTrack().isNull()){
00441     reco::PFRecTrackCollection::const_iterator pft=PfRTkColl.begin();
00442     reco::PFRecTrackCollection::const_iterator pftend=PfRTkColl.end();
00443     unsigned int i_pf=0;
00444     int ibest=-1;
00445     unsigned int ish_max=0;
00446     float dr_min=1000;
00447     //SEARCH THE PFRECTRACK THAT SHARES HITS WITH THE ELECTRON SEED
00448     // Here the cpu time can be improved. 
00449     for(;pft!=pftend;++pft){
00450       unsigned int ish=0;
00451       
00452       float dph= fabs(pft->trackRef()->phi()-gsftk.phi()); 
00453       if (dph>TMath::Pi()) dph-= TMath::TwoPi();
00454       float det=fabs(pft->trackRef()->eta()-gsftk.eta());
00455       float dr =sqrt(dph*dph+det*det);  
00456       
00457       trackingRecHit_iterator  hhit=
00458         pft->trackRef()->recHitsBegin();
00459       trackingRecHit_iterator  hhit_end=
00460         pft->trackRef()->recHitsEnd();
00461       
00462     
00463       
00464       for(;hhit!=hhit_end;++hhit){
00465         if (!(*hhit)->isValid()) continue;
00466         TrajectorySeed::const_iterator hit=
00467           gsftk.seedRef()->recHits().first;
00468         TrajectorySeed::const_iterator hit_end=
00469           gsftk.seedRef()->recHits().second;
00470         for(;hit!=hit_end;++hit){
00471           if (!(hit->isValid())) continue;
00472           if((*hhit)->sharesInput(&*(hit),TrackingRecHit::all))  ish++; 
00473         //   if((hit->geographicalId()==(*hhit)->geographicalId())&&
00474         //     (((*hhit)->localPosition()-hit->localPosition()).mag()<0.01)) ish++;
00475         }       
00476         
00477       }
00478       
00479 
00480       if ((ish>ish_max)||
00481           ((ish==ish_max)&&(dr<dr_min))){
00482         ish_max=ish;
00483         dr_min=dr;
00484         ibest=i_pf;
00485       }
00486       
00487    
00488     
00489       i_pf++;
00490     }
00491     if (ibest<0) return -1;
00492     
00493     if((ish_max==0) || (dr_min>0.05))return -1;
00494     if(otherColl && (ish_max==0)) return -1;
00495     return ibest;
00496   }
00497   else{
00498     //ELECTRON SEED HAS A REFERENCE
00499    
00500     reco::PFRecTrackCollection::const_iterator pft=PfRTkColl.begin();
00501     reco::PFRecTrackCollection::const_iterator pftend=PfRTkColl.end();
00502     unsigned int i_pf=0;
00503     
00504     for(;pft!=pftend;++pft){
00505       //REF COMPARISON
00506       if (pft->trackRef()==ElSeedRef->ctfTrack()){
00507         return i_pf;
00508       }
00509       i_pf++;
00510     }
00511   }
00512   return -1;
00513 }
00514 bool PFElecTkProducer::isFifthStep(reco::PFRecTrackRef pfKfTrack) {
00515 
00516   bool isFithStep = false;
00517   
00518 
00519   TrackRef kfref = pfKfTrack->trackRef();
00520   unsigned int Algo = 0; 
00521   switch (kfref->algo()) {
00522   case TrackBase::undefAlgorithm:
00523   case TrackBase::ctf:
00524   case TrackBase::iter0:
00525   case TrackBase::iter1:
00526   case TrackBase::iter2:
00527     Algo = 0;
00528     break;
00529   case TrackBase::iter3:
00530     Algo = 1;
00531     break;
00532   case TrackBase::iter4:
00533     Algo = 2;
00534     break;
00535   case TrackBase::iter5:
00536     Algo = 3;
00537     break;
00538   case TrackBase::iter6:
00539     Algo = 4;
00540     break;
00541   default:
00542     Algo = 5;
00543     break;
00544   }
00545   if ( Algo >= 4 ) {
00546     isFithStep = true;
00547   }
00548 
00549   return isFithStep;
00550 }
00551 // -- method to apply gsf electron selection to EcalDriven seeds
00552 bool 
00553 PFElecTkProducer::applySelection(reco::GsfTrack gsftk) {
00554   if (&(*gsftk.seedRef())==0) return false;
00555   ElectronSeedRef ElSeedRef=gsftk.extra()->seedRef().castTo<ElectronSeedRef>();
00556 
00557   bool passCut = false;
00558   if (ElSeedRef->ctfTrack().isNull()){
00559     if(ElSeedRef->caloCluster().isNull()) return passCut;
00560     SuperClusterRef scRef = ElSeedRef->caloCluster().castTo<SuperClusterRef>();
00561     //do this just to know if exist a SC? 
00562     if(scRef.isNonnull()) {
00563       float caloEne = scRef->energy();
00564       float feta = fabs(scRef->eta()-gsftk.etaMode());
00565       float fphi = fabs(scRef->phi()-gsftk.phiMode());
00566       if (fphi>TMath::Pi()) fphi-= TMath::TwoPi();
00567       if(caloEne > SCEne_ && feta < detaGsfSC_ && fabs(fphi) < dphiGsfSC_)
00568         passCut = true;
00569     }
00570   }
00571   else {
00572     // get all the gsf found by tracker driven
00573     passCut = true;
00574   }
00575   return passCut;
00576 }
00577 bool 
00578 PFElecTkProducer::resolveGsfTracks(const vector<reco::GsfPFRecTrack>  & GsfPFVec, 
00579                                    unsigned int ngsf, 
00580                                    vector<unsigned int> &secondaries,
00581                                    const reco::PFClusterCollection & theEClus) {
00582   bool debugCleaning = debugGsfCleaning_;
00583   bool n_keepGsf = true;
00584 
00585   reco::GsfTrackRef nGsfTrack = GsfPFVec[ngsf].gsfTrackRef();
00586   
00587   if (&(*nGsfTrack->seedRef())==0) return false;    
00588   ElectronSeedRef nElSeedRef=nGsfTrack->extra()->seedRef().castTo<ElectronSeedRef>();
00589 
00590 
00591   TrajectoryStateOnSurface inTSOS = mtsTransform_.innerStateOnSurface((*nGsfTrack));
00592   GlobalVector ninnMom;
00593   float nPin =  nGsfTrack->pMode();
00594   if(inTSOS.isValid()){
00595     mtsMode_->momentumFromModeCartesian(inTSOS,ninnMom);
00596     nPin = ninnMom.mag();
00597   }
00598 
00599   float neta = nGsfTrack->innerMomentum().eta();
00600   float nphi = nGsfTrack->innerMomentum().phi();
00601   
00602 
00603 
00604   
00605   if(debugCleaning)
00606     cout << " PFElecTkProducer:: considering track " << nGsfTrack->pt() 
00607          << " eta,phi " <<  nGsfTrack->eta() << ", " <<  nGsfTrack->phi()  << endl;
00608   
00609   
00610   for (unsigned int igsf=0; igsf< GsfPFVec.size();igsf++) {
00611     if(igsf != ngsf ) {
00612       reco::GsfTrackRef iGsfTrack = GsfPFVec[igsf].gsfTrackRef();
00613 
00614       if(debugCleaning)
00615         cout << " PFElecTkProducer:: and  comparing with track " << iGsfTrack->pt() 
00616              << " eta,phi " <<  iGsfTrack->eta() << ", " <<  iGsfTrack->phi()  << endl;
00617       
00618       float ieta = iGsfTrack->innerMomentum().eta();
00619       float iphi = iGsfTrack->innerMomentum().phi();
00620       float feta = fabs(neta - ieta);
00621       float fphi = fabs(nphi - iphi);
00622       if (fphi>TMath::Pi()) fphi-= TMath::TwoPi();     
00623   
00624 
00625       // apply a superloose preselection only to avoid un-useful cpu time: hard-coded for this reason
00626       if(feta < 0.5 && fabs(fphi) < 1.0) {
00627         if(debugCleaning)
00628           cout << " Entering angular superloose preselection " << endl;
00629         
00630         TrajectoryStateOnSurface i_inTSOS = mtsTransform_.innerStateOnSurface((*iGsfTrack));
00631         GlobalVector i_innMom;
00632         float iPin = iGsfTrack->pMode();
00633         if(i_inTSOS.isValid()){
00634           mtsMode_->momentumFromModeCartesian(i_inTSOS,i_innMom);  
00635           iPin = i_innMom.mag();
00636         }
00637 
00638         if (&(*iGsfTrack->seedRef())==0) continue;   
00639         ElectronSeedRef iElSeedRef=iGsfTrack->extra()->seedRef().castTo<ElectronSeedRef>();
00640 
00641         float SCEnergy = -1.;
00642         // Check if two tracks match the same SC     
00643         bool areBothGsfEcalDriven = false;;
00644         bool isSameSC = isSameEgSC(nElSeedRef,iElSeedRef,areBothGsfEcalDriven,SCEnergy);
00645         
00646         // CASE1 both GsfTracks ecalDriven and match the same SC
00647         if(areBothGsfEcalDriven ) {
00648           if(isSameSC) {
00649             float nEP = SCEnergy/nPin;
00650             float iEP =  SCEnergy/iPin;
00651             if(debugCleaning)
00652               cout << " Entering SAME supercluster case " 
00653                    << " nEP " << nEP 
00654                    << " iEP " << iEP << endl;
00655             
00656             
00657             
00658             // if same SC take the closest or if same
00659             // distance the best E/p
00660             
00661             // Innermost using LostHits technology
00662             bool isSameLayer = false;
00663             bool iGsfInnermostWithLostHits = 
00664               isInnerMostWithLostHits(nGsfTrack,iGsfTrack,isSameLayer);
00665             
00666             
00667             if(debugCleaning)
00668               cout << " iGsf is InnerMostWithLostHits " << iGsfInnermostWithLostHits
00669                    << " isSameLayer " << isSameLayer  << endl;
00670             
00671             if (iGsfInnermostWithLostHits) {
00672               n_keepGsf = false;
00673               return n_keepGsf;
00674             }
00675             else if(isSameLayer){
00676               if(fabs(iEP-1) < fabs(nEP-1)) {
00677                 n_keepGsf = false;
00678                 return n_keepGsf;
00679               }
00680               else{
00681                 secondaries.push_back(igsf);
00682               }
00683             }
00684             else {
00685               // save secondaries gsf track (put selection)
00686             secondaries.push_back(igsf);
00687             }
00688           } // end same SC case
00689         }
00690         else {
00691           // enter in the condition where at least one track is trackerDriven
00692           float minBremDphi =  minTangDist(GsfPFVec[ngsf],GsfPFVec[igsf]);
00693           float nETot = 0.;
00694           float iETot = 0.;
00695           bool isBothGsfTrackerDriven = false;
00696           bool nEcalDriven = false;
00697           bool iEcalDriven = false;
00698           bool isSameScEgPf = isSharingEcalEnergyWithEgSC(GsfPFVec[ngsf],
00699                                                           GsfPFVec[igsf],
00700                                                           nElSeedRef,
00701                                                           iElSeedRef,
00702                                                           theEClus,
00703                                                           isBothGsfTrackerDriven,
00704                                                           nEcalDriven,
00705                                                           iEcalDriven,
00706                                                           nETot,
00707                                                           iETot);
00708 
00709           // check if the first hit of iGsfTrack < nGsfTrack          
00710           bool isSameLayer = false;
00711           bool iGsfInnermostWithLostHits = 
00712             isInnerMostWithLostHits(nGsfTrack,iGsfTrack,isSameLayer);
00713 
00714           if(isSameScEgPf) {
00715             // CASE 2 : One Gsf has reference to a SC and the other one not or both not
00716                     
00717             if(debugCleaning) {
00718               cout << " Sharing ECAL energy passed " 
00719                    << " nEtot " << nETot 
00720                    << " iEtot " << iETot << endl;
00721               if(isBothGsfTrackerDriven) 
00722                 cout << " Both Track are trackerDriven " << endl;
00723             }
00724 
00725             // Innermost using LostHits technology
00726             if (iGsfInnermostWithLostHits) {
00727               n_keepGsf = false;
00728               return n_keepGsf;
00729             }
00730             else if(isSameLayer){
00731               // Thirt Case:  One Gsf has reference to a SC and the other one not or both not
00732               // gsf tracks starts from the same layer
00733               // check number of sharing modules (at least 50%)
00734               // check number of sharing hits (at least 2)
00735               // check charge flip inner/outer
00736 
00737              
00738                 // they share energy
00739               if(isBothGsfTrackerDriven == false) {
00740                 // if at least one Gsf track is EcalDriven choose that one.
00741                 if(iEcalDriven) {
00742                   n_keepGsf = false;
00743                   return n_keepGsf;
00744                 }
00745                 else {
00746                   secondaries.push_back(igsf);
00747                 }
00748               }
00749               else {
00750                 // if both tracks are tracker driven choose that one with the best E/p
00751                 // with ETot = max(En,Ei)
00752 
00753                 float ETot = -1;
00754                 if(nETot != iETot) {
00755                   if(nETot > iETot)
00756                     ETot = nETot;
00757                   else 
00758                     ETot = iETot;
00759                 }
00760                 else {
00761                   ETot = nETot;
00762                 }
00763                 float nEP = ETot/nPin;
00764                 float iEP = ETot/iPin;
00765                 
00766                 
00767                 if(debugCleaning) 
00768                   cout << " nETot " << nETot
00769                        << " iETot " << iETot 
00770                        << " ETot " << ETot << endl 
00771                        << " nPin " << nPin
00772                        << " iPin " << iPin 
00773                        << " nEP " << nEP 
00774                        << " iEP " << iEP << endl;
00775                 
00776         
00777                 if(fabs(iEP-1) < fabs(nEP-1)) {
00778                   n_keepGsf = false;
00779                   return n_keepGsf;
00780                 }
00781                 else{
00782                   secondaries.push_back(igsf);
00783                 }
00784               }
00785             }
00786             else {
00787               secondaries.push_back(igsf);
00788             }
00789           }
00790           else if(feta < detaCutGsfClean_ && minBremDphi < dphiCutGsfClean_) {
00791             // very close tracks
00792             bool secPushedBack = false;
00793             if(nEcalDriven == false && nETot == 0.) {
00794               n_keepGsf = false;
00795               return n_keepGsf;
00796             }
00797             else if(iEcalDriven == false && iETot == 0.) {
00798               secondaries.push_back(igsf);
00799               secPushedBack = true;
00800             }
00801             if(debugCleaning)
00802               cout << " Close Tracks " 
00803                    << " feta " << feta << " fabs(fphi) " << fabs(fphi) 
00804                    << " minBremDphi " <<  minBremDphi 
00805                    << " nETot " << nETot 
00806                    << " iETot " << iETot 
00807                    << " nLostHits " <<  nGsfTrack->trackerExpectedHitsInner().numberOfLostHits() 
00808                    << " iLostHits " << iGsfTrack->trackerExpectedHitsInner().numberOfLostHits() << endl;
00809             
00810             // apply selection only if one track has lost hits
00811             if(applyAngularGsfClean_) {
00812               if (iGsfInnermostWithLostHits) {
00813                 n_keepGsf = false;
00814                 return n_keepGsf;
00815               }
00816               else if(isSameLayer == false) {
00817                 if(secPushedBack == false) 
00818                   secondaries.push_back(igsf);
00819               }
00820             }
00821           }
00822           else if(feta < 0.1 && minBremDphi < 0.2){
00823             // failed all the conditions, discard only tracker driven tracks
00824             // with no PFClusters linked. 
00825             if(debugCleaning)
00826               cout << " Close Tracks and failed all the conditions " 
00827                    << " feta " << feta << " fabs(fphi) " << fabs(fphi) 
00828                    << " minBremDphi " <<  minBremDphi 
00829                    << " nETot " << nETot 
00830                    << " iETot " << iETot 
00831                    << " nLostHits " <<  nGsfTrack->trackerExpectedHitsInner().numberOfLostHits() 
00832                    << " iLostHits " << iGsfTrack->trackerExpectedHitsInner().numberOfLostHits() << endl;
00833             
00834             if(nEcalDriven == false && nETot == 0.) {
00835               n_keepGsf = false;
00836               return n_keepGsf;
00837             }
00838             // Here I do not push back the secondary because considered fakes...
00839           }
00840         }
00841       }
00842     }
00843   }
00844   
00845   return n_keepGsf;
00846 }
00847 float 
00848 PFElecTkProducer::minTangDist(const reco::GsfPFRecTrack& primGsf,
00849                               const reco::GsfPFRecTrack& secGsf) {
00850 
00851   float minDeta = 1000.; 
00852   float minDphi = 1000.; 
00853 
00854 
00855   std::vector<reco::PFBrem> primPFBrem = primGsf.PFRecBrem();
00856   std::vector<reco::PFBrem> secPFBrem = secGsf.PFRecBrem();
00857 
00858 
00859   unsigned int cbrem = 0;
00860   for (unsigned isbrem = 0; isbrem < secPFBrem.size(); isbrem++) {
00861     if(secPFBrem[isbrem].indTrajPoint() == 99) continue;
00862     const reco::PFTrajectoryPoint& atSecECAL 
00863       = secPFBrem[isbrem].extrapolatedPoint( reco::PFTrajectoryPoint::ECALEntrance );
00864     if( ! atSecECAL.isValid() ) continue;
00865     float secEta = atSecECAL.positionREP().Eta();
00866     float secPhi  = atSecECAL.positionREP().Phi();
00867 
00868     unsigned int sbrem = 0;
00869     for(unsigned ipbrem = 0; ipbrem < primPFBrem.size(); ipbrem++) {
00870       if(primPFBrem[ipbrem].indTrajPoint() == 99) continue;
00871       const reco::PFTrajectoryPoint& atPrimECAL 
00872         = primPFBrem[ipbrem].extrapolatedPoint( reco::PFTrajectoryPoint::ECALEntrance );
00873       if( ! atPrimECAL.isValid() ) continue;
00874       sbrem++;
00875       if(sbrem <= 3) {
00876         float primEta = atPrimECAL.positionREP().Eta();
00877         float primPhi = atPrimECAL.positionREP().Phi();
00878         
00879         float deta = fabs(primEta - secEta);
00880         float dphi = fabs(primPhi - secPhi);
00881         if (dphi>TMath::Pi()) dphi-= TMath::TwoPi();     
00882         if(fabs(dphi) < minDphi) {         
00883           minDeta = deta;
00884           minDphi = fabs(dphi);
00885         }
00886       }
00887     }
00888     
00889     
00890     cbrem++;
00891     if(cbrem == 3) 
00892       break;
00893   }
00894   return minDphi;
00895 }
00896 bool 
00897 PFElecTkProducer::isSameEgSC(const reco::ElectronSeedRef& nSeedRef,
00898                              const reco::ElectronSeedRef& iSeedRef,
00899                              bool& bothGsfEcalDriven,
00900                              float& SCEnergy) {
00901   
00902   bool isSameSC = false;
00903 
00904   if(nSeedRef->caloCluster().isNonnull() && iSeedRef->caloCluster().isNonnull()) {
00905     SuperClusterRef nscRef = nSeedRef->caloCluster().castTo<SuperClusterRef>();
00906     SuperClusterRef iscRef = iSeedRef->caloCluster().castTo<SuperClusterRef>();
00907 
00908     if(nscRef.isNonnull() && iscRef.isNonnull()) {
00909       bothGsfEcalDriven = true;
00910       if(nscRef == iscRef) {
00911         isSameSC = true;
00912         // retrieve the supercluster energy
00913         SCEnergy = nscRef->energy();
00914       }
00915     }
00916   }
00917   return isSameSC;
00918 }
00919 bool 
00920 PFElecTkProducer::isSharingEcalEnergyWithEgSC(const reco::GsfPFRecTrack& nGsfPFRecTrack,
00921                                               const reco::GsfPFRecTrack& iGsfPFRecTrack,
00922                                               const reco::ElectronSeedRef& nSeedRef,
00923                                               const reco::ElectronSeedRef& iSeedRef,
00924                                               const reco::PFClusterCollection& theEClus,
00925                                               bool& bothGsfTrackerDriven,
00926                                               bool& nEcalDriven,
00927                                               bool& iEcalDriven,
00928                                               float& nEnergy,
00929                                               float& iEnergy) {
00930   
00931   bool isSharingEnergy = false;
00932 
00933   //which is EcalDriven?
00934   bool oneEcalDriven = true;
00935   SuperClusterRef scRef;
00936   GsfPFRecTrack gsfPfTrack;
00937 
00938   if(nSeedRef->caloCluster().isNonnull()) {
00939     scRef = nSeedRef->caloCluster().castTo<SuperClusterRef>();
00940     nEnergy = scRef->energy();
00941     nEcalDriven = true;
00942     gsfPfTrack = iGsfPFRecTrack;
00943   }
00944   else if(iSeedRef->caloCluster().isNonnull()){
00945     scRef = iSeedRef->caloCluster().castTo<SuperClusterRef>();
00946     iEnergy = scRef->energy();
00947     iEcalDriven = true;
00948     gsfPfTrack = nGsfPFRecTrack;
00949   }
00950   else{
00951      oneEcalDriven = false;
00952   }
00953   
00954   if(oneEcalDriven) {
00955     //run a basic reconstruction for the particle flow
00956 
00957     vector<PFCluster> vecPFClusters;
00958     vecPFClusters.clear();
00959 
00960     for (PFClusterCollection::const_iterator clus = theEClus.begin();
00961          clus != theEClus.end();
00962          clus++ ) {
00963       PFCluster clust = *clus;
00964       clust.calculatePositionREP();
00965 
00966       float deta = fabs(scRef->position().eta() - clust.position().eta());
00967       float dphi = fabs(scRef->position().phi() - clust.position().phi());
00968       if (dphi>TMath::Pi()) dphi-= TMath::TwoPi();
00969  
00970       // Angle preselection between the supercluster and pfclusters
00971       // this is needed just to save some cpu-time for this is hard-coded     
00972       if(deta < 0.5 && fabs(dphi) < 1.0) {
00973         bool foundLink = false;
00974         double distGsf = gsfPfTrack.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ?
00975           LinkByRecHit::testTrackAndClusterByRecHit(gsfPfTrack , clust ) : -1.;
00976         // check if it touch the GsfTrack
00977         if(distGsf > 0.) {
00978           if(nEcalDriven) 
00979             iEnergy += clust.energy();
00980           else
00981             nEnergy += clust.energy();
00982           vecPFClusters.push_back(clust);
00983           foundLink = true;
00984         }
00985         // check if it touch the Brem-tangents
00986         if(foundLink == false) {
00987           vector<PFBrem> primPFBrem = gsfPfTrack.PFRecBrem();
00988           for(unsigned ipbrem = 0; ipbrem < primPFBrem.size(); ipbrem++) {
00989             if(primPFBrem[ipbrem].indTrajPoint() == 99) continue;
00990             const reco::PFRecTrack& pfBremTrack = primPFBrem[ipbrem];
00991             double dist = pfBremTrack.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ?
00992               LinkByRecHit::testTrackAndClusterByRecHit(pfBremTrack , clust, true ) : -1.;
00993             if(dist > 0.) {
00994               if(nEcalDriven) 
00995                 iEnergy += clust.energy();
00996               else
00997                 nEnergy += clust.energy();
00998               vecPFClusters.push_back(clust);
00999               foundLink = true;
01000             }
01001           }     
01002         }  
01003       } // END if anble preselection
01004     } // PFClusters Loop
01005     if(vecPFClusters.size() > 0 ) {
01006       for(unsigned int pf = 0; pf < vecPFClusters.size(); pf++) {
01007         bool isCommon = ClusterClusterMapping::overlap(vecPFClusters[pf],*scRef);
01008         if(isCommon) {
01009           isSharingEnergy = true;
01010         }
01011         break;
01012       }
01013     }
01014   }
01015   else {
01016     // both tracks are trackerDriven, try ECAL energy matching also in this case.
01017 
01018     bothGsfTrackerDriven = true;
01019     vector<PFCluster> nPFCluster;
01020     vector<PFCluster> iPFCluster;
01021 
01022     nPFCluster.clear();
01023     iPFCluster.clear();
01024 
01025     for (PFClusterCollection::const_iterator clus = theEClus.begin();
01026          clus != theEClus.end();
01027          clus++ ) {
01028       PFCluster clust = *clus;
01029       clust.calculatePositionREP();
01030       
01031       float ndeta = fabs(nGsfPFRecTrack.gsfTrackRef()->eta() - clust.position().eta());
01032       float ndphi = fabs(nGsfPFRecTrack.gsfTrackRef()->phi() - clust.position().phi());
01033       if (ndphi>TMath::Pi()) ndphi-= TMath::TwoPi();
01034       // Apply loose preselection with the track
01035       // just to save cpu time, for this hard-coded
01036       if(ndeta < 0.5 && fabs(ndphi) < 1.0) {
01037         bool foundNLink = false;
01038         
01039         double distGsf = nGsfPFRecTrack.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ?
01040           LinkByRecHit::testTrackAndClusterByRecHit(nGsfPFRecTrack , clust ) : -1.;
01041         if(distGsf > 0.) {
01042           nPFCluster.push_back(clust);
01043           nEnergy += clust.energy();
01044           foundNLink = true;
01045         }
01046         if(foundNLink == false) {
01047           const vector<PFBrem>& primPFBrem = nGsfPFRecTrack.PFRecBrem();
01048           for(unsigned ipbrem = 0; ipbrem < primPFBrem.size(); ipbrem++) {
01049             if(primPFBrem[ipbrem].indTrajPoint() == 99) continue;
01050             const reco::PFRecTrack& pfBremTrack = primPFBrem[ipbrem];
01051             if(foundNLink == false) {
01052               double dist = pfBremTrack.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ?
01053                 LinkByRecHit::testTrackAndClusterByRecHit(pfBremTrack , clust, true ) : -1.;
01054               if(dist > 0.) {
01055                 nPFCluster.push_back(clust);
01056                 nEnergy += clust.energy();
01057                 foundNLink = true;
01058               }
01059             }
01060           }
01061         }
01062       }
01063 
01064       float ideta = fabs(iGsfPFRecTrack.gsfTrackRef()->eta() - clust.position().eta());
01065       float idphi = fabs(iGsfPFRecTrack.gsfTrackRef()->phi() - clust.position().phi());
01066       if (idphi>TMath::Pi()) idphi-= TMath::TwoPi();
01067       // Apply loose preselection with the track
01068       // just to save cpu time, for this hard-coded
01069       if(ideta < 0.5 && fabs(idphi) < 1.0) {
01070         bool foundILink = false;
01071         double dist = iGsfPFRecTrack.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ?
01072           LinkByRecHit::testTrackAndClusterByRecHit(iGsfPFRecTrack , clust ) : -1.;
01073         if(dist > 0.) {
01074           iPFCluster.push_back(clust);
01075           iEnergy += clust.energy();
01076           foundILink = true;
01077         }
01078         if(foundILink == false) {
01079           vector<PFBrem> primPFBrem = iGsfPFRecTrack.PFRecBrem();
01080           for(unsigned ipbrem = 0; ipbrem < primPFBrem.size(); ipbrem++) {
01081             if(primPFBrem[ipbrem].indTrajPoint() == 99) continue;
01082             const reco::PFRecTrack& pfBremTrack = primPFBrem[ipbrem];
01083             if(foundILink == false) {
01084               double dist = LinkByRecHit::testTrackAndClusterByRecHit(pfBremTrack , clust, true );
01085               if(dist > 0.) {
01086                 iPFCluster.push_back(clust);
01087                 iEnergy += clust.energy();
01088                 foundILink = true;
01089               }
01090             }
01091           }
01092         }
01093       }
01094     }
01095 
01096 
01097     if(nPFCluster.size() > 0 && iPFCluster.size() > 0) {
01098       for(unsigned int npf = 0; npf < nPFCluster.size(); npf++) {
01099         for(unsigned int ipf = 0; ipf < iPFCluster.size(); ipf++) {
01100           bool isCommon = ClusterClusterMapping::overlap(nPFCluster[npf],iPFCluster[ipf]);
01101           if(isCommon) {
01102             isSharingEnergy = true;
01103             break;
01104           }
01105         }
01106         if(isSharingEnergy)
01107           break;
01108       }
01109     }
01110   }
01111 
01112   return isSharingEnergy;
01113 }
01114 bool PFElecTkProducer::isInnerMost(const reco::GsfTrackRef& nGsfTrack,
01115                                    const reco::GsfTrackRef& iGsfTrack,
01116                                    bool& sameLayer) {
01117   
01118   // copied by the class RecoEgamma/EgammaElectronAlgos/src/EgAmbiguityTools.cc
01119   // obsolete but the code is kept: now using lost hits method
01120 
01121   reco::HitPattern gsfHitPattern1 = nGsfTrack->hitPattern();
01122   reco::HitPattern gsfHitPattern2 = iGsfTrack->hitPattern();
01123   
01124   // retrieve first valid hit
01125   int gsfHitCounter1 = 0 ;
01126   trackingRecHit_iterator elHitsIt1 ;
01127   for
01128     ( elHitsIt1 = nGsfTrack->recHitsBegin() ;
01129      elHitsIt1 != nGsfTrack->recHitsEnd() ;
01130      elHitsIt1++, gsfHitCounter1++ )
01131     { if (((**elHitsIt1).isValid())) break ; }
01132   
01133   int gsfHitCounter2 = 0 ;
01134   trackingRecHit_iterator elHitsIt2 ;
01135   for
01136     ( elHitsIt2 = iGsfTrack->recHitsBegin() ;
01137      elHitsIt2 != iGsfTrack->recHitsEnd() ;
01138      elHitsIt2++, gsfHitCounter2++ )
01139     { if (((**elHitsIt2).isValid())) break ; }
01140   
01141   uint32_t gsfHit1 = gsfHitPattern1.getHitPattern(gsfHitCounter1) ;
01142   uint32_t gsfHit2 = gsfHitPattern2.getHitPattern(gsfHitCounter2) ;
01143   
01144   
01145   if (gsfHitPattern1.getSubStructure(gsfHit1)!=gsfHitPattern2.getSubStructure(gsfHit2))
01146    { 
01147      return (gsfHitPattern2.getSubStructure(gsfHit2)<gsfHitPattern1.getSubStructure(gsfHit1)); 
01148    }
01149   else if (gsfHitPattern1.getLayer(gsfHit1)!=gsfHitPattern2.getLayer(gsfHit2))
01150     { 
01151       return (gsfHitPattern2.getLayer(gsfHit2)<gsfHitPattern1.getLayer(gsfHit1)); 
01152     }
01153   else
01154    { 
01155      sameLayer = true;
01156      return  false; 
01157    }
01158 }
01159 bool PFElecTkProducer::isInnerMostWithLostHits(const reco::GsfTrackRef& nGsfTrack,
01160                                                const reco::GsfTrackRef& iGsfTrack,
01161                                                bool& sameLayer) {
01162   
01163   // define closest using the lost hits on the expectedhitsineer
01164   unsigned int nLostHits = nGsfTrack->trackerExpectedHitsInner().numberOfLostHits();
01165   unsigned int iLostHits = iGsfTrack->trackerExpectedHitsInner().numberOfLostHits();
01166   
01167   if (nLostHits!=iLostHits) {
01168     return (nLostHits > iLostHits);
01169   } 
01170   else {
01171     sameLayer = true;
01172     return  false; 
01173   }
01174 }
01175 
01176 
01177 
01178 // ------------ method called once each job just before starting event loop  ------------
01179 void 
01180 PFElecTkProducer::beginRun(edm::Run& run,
01181                            const EventSetup& iSetup)
01182 {
01183   ESHandle<MagneticField> magneticField;
01184   iSetup.get<IdealMagneticFieldRecord>().get(magneticField);
01185 
01186   ESHandle<TrackerGeometry> tracker;
01187   iSetup.get<TrackerDigiGeometryRecord>().get(tracker);
01188 
01189 
01190   mtsTransform_ = MultiTrajectoryStateTransform(tracker.product(),magneticField.product());
01191   
01192 
01193   pfTransformer_= new PFTrackTransformer(math::XYZVector(magneticField->inTesla(GlobalPoint(0,0,0))));
01194   
01195   
01196   edm::ESHandle<TransientTrackBuilder> builder;
01197   iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder", builder);
01198   TransientTrackBuilder thebuilder = *(builder.product());
01199   
01200 
01201   if(useConvBremFinder_) {
01202     FILE * fileConvBremID = fopen(path_mvaWeightFileConvBrem_.c_str(), "r");
01203     if (fileConvBremID) {
01204       fclose(fileConvBremID);
01205     }
01206     else {
01207       string err = "PFElecTkProducer: cannot open weight file '";
01208       err += path_mvaWeightFileConvBrem_;
01209       err += "'";
01210       throw invalid_argument( err );
01211     }
01212   }
01213   convBremFinder_ = new ConvBremPFTrackFinder(thebuilder,mvaConvBremFinderID_,path_mvaWeightFileConvBrem_);
01214 
01215 }
01216 
01217 // ------------ method called once each job just after ending the event loop  ------------
01218 void 
01219 PFElecTkProducer::endRun() {
01220   delete pfTransformer_;
01221 }
01222 
01223 //define this as a plug-in