CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/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 "DataFormats/EgammaReco/interface/ElectronSeed.h"
00028 #include "DataFormats/EgammaReco/interface/ElectronSeedFwd.h"
00029 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00030 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00031 #include "MagneticField/Engine/interface/MagneticField.h"
00032 #include "DataFormats/ParticleFlowReco/interface/PFClusterFwd.h"
00033 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00034 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00035 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00036 #include "DataFormats/VertexReco/interface/Vertex.h"
00037 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00038 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedTrackerVertex.h"
00039 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertexFwd.h"
00040 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
00041 #include "DataFormats/ParticleFlowReco/interface/PFConversionFwd.h"
00042 #include "DataFormats/ParticleFlowReco/interface/PFConversion.h"
00043 #include "DataFormats/ParticleFlowReco/interface/PFV0Fwd.h"
00044 #include "DataFormats/ParticleFlowReco/interface/PFV0.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 
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   useFifthStep_ = iConfig.getParameter<bool>("useFifthTrackingStep");
00092   useFifthStepSec_ = iConfig.getParameter<bool>("useFifthTrackingStepForSecondaries");
00093   maxPtConvReco_ = iConfig.getParameter<double>("MaxConvBremRecoPT");
00094   detaGsfSC_ = iConfig.getParameter<double>("MinDEtaGsfSC");
00095   dphiGsfSC_ = iConfig.getParameter<double>("MinDPhiGsfSC");
00096   SCEne_ = iConfig.getParameter<double>("MinSCEnergy");
00097   
00098   // set parameter for convBremFinder
00099   useConvBremFinder_ =     iConfig.getParameter<bool>("useConvBremFinder");
00100   mvaConvBremFinderID_
00101     = iConfig.getParameter<double>("pf_convBremFinderID_mvaCut");
00102   
00103   string mvaWeightFileConvBrem
00104     = iConfig.getParameter<string>("pf_convBremFinderID_mvaWeightFile");
00105   
00106   
00107   if(useConvBremFinder_) 
00108     path_mvaWeightFileConvBrem_ = edm::FileInPath ( mvaWeightFileConvBrem.c_str() ).fullPath();
00109 
00110 }
00111 
00112 
00113 PFElecTkProducer::~PFElecTkProducer()
00114 {
00115  
00116   delete pfTransformer_;
00117   delete convBremFinder_;
00118 }
00119 
00120 
00121 //
00122 // member functions
00123 //
00124 
00125 // ------------ method called to produce the data  ------------
00126 void
00127 PFElecTkProducer::produce(Event& iEvent, const EventSetup& iSetup)
00128 {
00129   LogDebug("PFElecTkProducer")<<"START event: "<<iEvent.id().event()
00130                               <<" in run "<<iEvent.id().run();
00131 
00132   //create the empty collections 
00133   auto_ptr< GsfPFRecTrackCollection > 
00134     gsfPFRecTrackCollection(new GsfPFRecTrackCollection);
00135 
00136   
00137   auto_ptr< GsfPFRecTrackCollection > 
00138     gsfPFRecTrackCollectionSecondary(new GsfPFRecTrackCollection);
00139 
00140   //read collections of tracks
00141   Handle<GsfTrackCollection> gsftrackscoll;
00142   iEvent.getByLabel(gsfTrackLabel_,gsftrackscoll);
00143 
00144   //read collections of trajectories
00145   Handle<vector<Trajectory> > TrajectoryCollection;
00146  
00147   //read pfrectrack collection
00148   Handle<PFRecTrackCollection> thePfRecTrackCollection;
00149   iEvent.getByLabel(pfTrackLabel_,thePfRecTrackCollection);
00150   const PFRecTrackCollection& PfRTkColl = *(thePfRecTrackCollection.product());
00151 
00152   // PFClusters
00153   Handle<PFClusterCollection> theECPfClustCollection;
00154   iEvent.getByLabel(pfEcalClusters_,theECPfClustCollection);
00155   const PFClusterCollection& theEcalClusters = *(theECPfClustCollection.product());
00156 
00157   //Primary Vertexes
00158   Handle<reco::VertexCollection> thePrimaryVertexColl;
00159   iEvent.getByLabel(primVtxLabel_,thePrimaryVertexColl);
00160 
00161 
00162 
00163   // Displaced Vertex
00164   Handle< reco::PFDisplacedTrackerVertexCollection > pfNuclears; 
00165   if( useNuclear_ ) {
00166     bool found = iEvent.getByLabel(pfNuclear_, pfNuclears);
00167     
00168     
00169     if(!found )
00170       LogError("PFElecTkProducer")<<" cannot get PFNuclear : "
00171                                   <<  pfNuclear_
00172                                   << " please set useNuclear=False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00173   }
00174 
00175   // Conversions 
00176   Handle< reco::PFConversionCollection > pfConversions;
00177   if( useConversions_ ) {
00178     bool found = iEvent.getByLabel(pfConv_,pfConversions);
00179     if(!found )
00180       LogError("PFElecTkProducer")<<" cannot get PFConversions : "
00181                                   << pfConv_ 
00182                                   << " please set useConversions=False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00183   }
00184 
00185   // V0
00186   Handle< reco::PFV0Collection > pfV0;
00187   if( useV0_ ) {
00188     bool found = iEvent.getByLabel(pfV0_, pfV0);
00189     
00190     if(!found )
00191       LogError("PFElecTkProducer")<<" cannot get PFV0 : "
00192                                   << pfV0_
00193                                   << " please set useV0=False  RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00194   }
00195   
00196   
00197 
00198   GsfTrackCollection gsftracks = *(gsftrackscoll.product());    
00199   vector<Trajectory> tjvec(0);
00200   if (trajinev_){
00201     bool foundTraj = iEvent.getByLabel(gsfTrackLabel_,TrajectoryCollection); 
00202     if(!foundTraj) 
00203       LogError("PFElecTkProducer")
00204         <<" cannot get Trajectories of : "
00205         <<  gsfTrackLabel_
00206         << " please set TrajInEvents = False in RecoParticleFlow/PFTracking/python/pfTrackElec_cfi.py" << endl;
00207     
00208     tjvec= *(TrajectoryCollection.product());
00209   }
00210   
00211 
00212   vector<reco::GsfPFRecTrack> selGsfPFRecTracks(0);
00213   selGsfPFRecTracks.clear();
00214   
00215   
00216   for (unsigned int igsf=0; igsf<gsftracks.size();igsf++) {
00217     
00218     GsfTrackRef trackRef(gsftrackscoll, igsf);
00219     
00220     int kf_ind=FindPfRef(PfRTkColl,gsftracks[igsf],false);
00221     
00222     if (kf_ind>=0) {
00223       
00224       PFRecTrackRef kf_ref(thePfRecTrackCollection,
00225                            kf_ind);
00226       pftrack_=GsfPFRecTrack( gsftracks[igsf].charge(), 
00227                               reco::PFRecTrack::GSF, 
00228                               igsf, trackRef,
00229                               kf_ref);
00230     } else  {
00231       PFRecTrackRef dummyRef;
00232       pftrack_=GsfPFRecTrack( gsftracks[igsf].charge(), 
00233                               reco::PFRecTrack::GSF, 
00234                               igsf, trackRef,
00235                               dummyRef);
00236     }
00237     
00238     
00239     bool validgsfbrem = false;
00240     if(trajinev_) {
00241       validgsfbrem = pfTransformer_->addPointsAndBrems(pftrack_, 
00242                                                        gsftracks[igsf], 
00243                                                        tjvec[igsf],
00244                                                        modemomentum_);
00245     } else {
00246       validgsfbrem = pfTransformer_->addPointsAndBrems(pftrack_, 
00247                                                        gsftracks[igsf], 
00248                                                        mtsTransform_);
00249     }
00250     
00251     bool passSel = true;
00252     if(applySel_) 
00253       passSel = applySelection(gsftracks[igsf]);      
00254     
00255     
00256     if(validgsfbrem && passSel) 
00257       selGsfPFRecTracks.push_back(pftrack_);
00258   }
00259   if(selGsfPFRecTracks.size() > 0) {
00260     for(unsigned int ipfgsf=0; ipfgsf<selGsfPFRecTracks.size();ipfgsf++) {
00261       
00262       vector<unsigned int> secondaries(0);
00263       secondaries.clear();
00264       bool keepGsf = true;
00265       
00266       if(applyGsfClean_) {
00267         keepGsf = resolveGsfTracks(selGsfPFRecTracks,ipfgsf,secondaries);
00268       }
00269       
00270       //is primary? 
00271       if(keepGsf == true) {
00272         PFRecTrackRef refprimKF =  selGsfPFRecTracks[ipfgsf].kfPFRecTrackRef();
00273         
00274         // SKIP 5TH STEP IF REQUESTED
00275         if(refprimKF.isNonnull()) {
00276           if(useFifthStep_ == false) {
00277             bool isFifthStepTrack = isFifthStep(refprimKF);
00278             if(isFifthStepTrack)
00279               continue;
00280           }
00281         }
00282         
00283 
00284         // Find kf tracks from converted brem photons
00285         if(convBremFinder_->foundConvBremPFRecTrack(thePfRecTrackCollection,thePrimaryVertexColl,
00286                                                     pfNuclears,pfConversions,pfV0,
00287                                                     useNuclear_,useConversions_,useV0_,
00288                                                     theEcalClusters,selGsfPFRecTracks[ipfgsf])) {
00289           const vector<PFRecTrackRef>& convBremPFRecTracks (convBremFinder_->getConvBremPFRecTracks());
00290           for(unsigned int ii = 0; ii<convBremPFRecTracks.size(); ii++) {
00291             selGsfPFRecTracks[ipfgsf].addConvBremPFRecTrackRef(convBremPFRecTracks[ii]);
00292           }
00293         }
00294         
00295         // save primaries gsf tracks
00296         gsfPFRecTrackCollection->push_back(selGsfPFRecTracks[ipfgsf]);
00297         
00298         
00299         
00300         // NOTE:: THE TRACKID IS USED TO LINK THE PRIMARY GSF TRACK. THIS NEEDS 
00301         // TO BE CHANGED AS SOON AS IT IS POSSIBLE TO CHANGE DATAFORMATS
00302         // A MODIFICATION HERE IMPLIES A MODIFICATION IN PFBLOCKALGO.CC/H
00303         unsigned int primGsfIndex = selGsfPFRecTracks[ipfgsf].trackId();
00304         if(secondaries.size() > 0) {
00305           // loop on secondaries gsf tracks (from converted brems)
00306           for(unsigned int isecpfgsf=0; isecpfgsf<secondaries.size();isecpfgsf++) {
00307             
00308             PFRecTrackRef refsecKF =  selGsfPFRecTracks[(secondaries[isecpfgsf])].kfPFRecTrackRef();
00309             
00310             // SKIP 5TH STEP IF REQUESTED
00311             if(refsecKF.isNonnull()) {
00312               if(useFifthStepSec_ == false) {
00313                 bool isFifthStepTrack = isFifthStep(refsecKF);
00314                 if(isFifthStepTrack)
00315                   continue;
00316               }
00317             }
00318             
00319             unsigned int secGsfIndex = selGsfPFRecTracks[(secondaries[isecpfgsf])].trackId();
00320             GsfTrackRef secGsfRef = selGsfPFRecTracks[(secondaries[isecpfgsf])].gsfTrackRef();
00321 
00322             if(refsecKF.isNonnull()) {
00323               // NOTE::IT SAVED THE TRACKID OF THE PRIMARY!!! THIS IS USED IN PFBLOCKALGO.CC/H
00324               secpftrack_= GsfPFRecTrack( gsftracks[secGsfIndex].charge(), 
00325                                           reco::PFRecTrack::GSF, 
00326                                           primGsfIndex, secGsfRef,
00327                                           refsecKF);
00328             }
00329             else{
00330               PFRecTrackRef dummyRef;
00331               // NOTE::IT SAVED THE TRACKID OF THE PRIMARY!!! THIS IS USED IN PFBLOCKALGO.CC/H
00332               secpftrack_= GsfPFRecTrack( gsftracks[secGsfIndex].charge(), 
00333                                           reco::PFRecTrack::GSF, 
00334                                           primGsfIndex, secGsfRef,
00335                                           dummyRef);
00336             }
00337 
00338             bool validgsfbrem = false;
00339             if(trajinev_) {
00340               validgsfbrem = pfTransformer_->addPointsAndBrems(secpftrack_,
00341                                                                gsftracks[secGsfIndex], 
00342                                                                tjvec[secGsfIndex],
00343                                                                modemomentum_);
00344             } else {
00345               validgsfbrem = pfTransformer_->addPointsAndBrems(secpftrack_,
00346                                                                gsftracks[secGsfIndex], 
00347                                                                mtsTransform_);
00348             }         
00349 
00350             if(validgsfbrem) 
00351               gsfPFRecTrackCollectionSecondary->push_back(secpftrack_);
00352           }
00353         }
00354       }
00355     }
00356   }
00357   
00358   iEvent.put(gsfPFRecTrackCollection);
00359   iEvent.put(gsfPFRecTrackCollectionSecondary,"Secondary");
00360   
00361   
00362 }
00363 // ------------- method for find the corresponding kf pfrectrack ---------------------
00364 int
00365 PFElecTkProducer::FindPfRef(const reco::PFRecTrackCollection  & PfRTkColl, 
00366                             reco::GsfTrack gsftk,
00367                             bool otherColl){
00368 
00369 
00370   if (&(*gsftk.seedRef())==0) return -1;
00371   ElectronSeedRef ElSeedRef=gsftk.extra()->seedRef().castTo<ElectronSeedRef>();
00372   //CASE 1 ELECTRONSEED DOES NOT HAVE A REF TO THE CKFTRACK
00373   if (ElSeedRef->ctfTrack().isNull()){
00374     reco::PFRecTrackCollection::const_iterator pft=PfRTkColl.begin();
00375     reco::PFRecTrackCollection::const_iterator pftend=PfRTkColl.end();
00376     unsigned int i_pf=0;
00377     int ibest=-1;
00378     unsigned int ish_max=0;
00379     float dr_min=1000;
00380     //SEARCH THE PFRECTRACK THAT SHARES HITS WITH THE ELECTRON SEED
00381     for(;pft!=pftend;++pft){
00382       unsigned int ish=0;
00383       
00384       float dph= fabs(pft->trackRef()->phi()-gsftk.phi()); 
00385       if (dph>TMath::Pi()) dph-= TMath::TwoPi();
00386       float det=fabs(pft->trackRef()->eta()-gsftk.eta());
00387       float dr =sqrt(dph*dph+det*det);  
00388       
00389       trackingRecHit_iterator  hhit=
00390         pft->trackRef()->recHitsBegin();
00391       trackingRecHit_iterator  hhit_end=
00392         pft->trackRef()->recHitsEnd();
00393       
00394     
00395       
00396       for(;hhit!=hhit_end;++hhit){
00397         if (!(*hhit)->isValid()) continue;
00398         TrajectorySeed::const_iterator hit=
00399           gsftk.seedRef()->recHits().first;
00400         TrajectorySeed::const_iterator hit_end=
00401           gsftk.seedRef()->recHits().second;
00402         for(;hit!=hit_end;++hit){
00403           if (!(hit->isValid())) continue;
00404           if((*hhit)->sharesInput(&*(hit),TrackingRecHit::all))  ish++; 
00405         //   if((hit->geographicalId()==(*hhit)->geographicalId())&&
00406         //     (((*hhit)->localPosition()-hit->localPosition()).mag()<0.01)) ish++;
00407         }       
00408         
00409       }
00410       
00411 
00412       if ((ish>ish_max)||
00413           ((ish==ish_max)&&(dr<dr_min))){
00414         ish_max=ish;
00415         dr_min=dr;
00416         ibest=i_pf;
00417       }
00418       
00419    
00420     
00421       i_pf++;
00422     }
00423     if (ibest<0) return -1;
00424     
00425     if((ish_max==0) || (dr_min>0.05))return -1;
00426     if(otherColl && (ish_max==0)) return -1;
00427     return ibest;
00428   }
00429   else{
00430     //ELECTRON SEED HAS A REFERENCE
00431    
00432     reco::PFRecTrackCollection::const_iterator pft=PfRTkColl.begin();
00433     reco::PFRecTrackCollection::const_iterator pftend=PfRTkColl.end();
00434     unsigned int i_pf=0;
00435     
00436     for(;pft!=pftend;++pft){
00437       //REF COMPARISON
00438       if (pft->trackRef()==ElSeedRef->ctfTrack()){
00439         return i_pf;
00440       }
00441       i_pf++;
00442     }
00443   }
00444   return -1;
00445 }
00446 bool PFElecTkProducer::isFifthStep(reco::PFRecTrackRef pfKfTrack) {
00447 
00448   bool isFithStep = false;
00449   
00450 
00451   TrackRef kfref = pfKfTrack->trackRef();
00452   unsigned int Algo = 0; 
00453   switch (kfref->algo()) {
00454   case TrackBase::ctf:
00455   case TrackBase::iter0:
00456   case TrackBase::iter1:
00457     Algo = 0;
00458     break;
00459   case TrackBase::iter2:
00460     Algo = 1;
00461     break;
00462   case TrackBase::iter3:
00463     Algo = 2;
00464     break;
00465   case TrackBase::iter4:
00466     Algo = 3;
00467     break;
00468   case TrackBase::iter5:
00469     Algo = 4;
00470     break;
00471   default:
00472     Algo = 5;
00473     break;
00474   }
00475   if ( Algo >= 4 ) {
00476     isFithStep = true;
00477   }
00478 
00479   return isFithStep;
00480 }
00481 // -- method to apply gsf electron selection to EcalDriven seeds
00482 bool 
00483 PFElecTkProducer::applySelection(reco::GsfTrack gsftk) {
00484   if (&(*gsftk.seedRef())==0) return false;
00485   ElectronSeedRef ElSeedRef=gsftk.extra()->seedRef().castTo<ElectronSeedRef>();
00486 
00487   bool passCut = false;
00488   if (ElSeedRef->ctfTrack().isNull()){
00489     if(ElSeedRef->caloCluster().isNull()) return passCut;
00490     SuperClusterRef scRef = ElSeedRef->caloCluster().castTo<SuperClusterRef>();
00491     //do this just to know if exist a SC? 
00492     if(scRef.isNonnull()) {
00493       float caloEne = scRef->energy();
00494       float feta = fabs(scRef->eta()-gsftk.etaMode());
00495       float fphi = fabs(scRef->phi()-gsftk.phiMode());
00496       if (fphi>TMath::Pi()) fphi-= TMath::TwoPi();
00497       if(caloEne > SCEne_ && feta < detaGsfSC_ && fabs(fphi) < dphiGsfSC_)
00498         passCut = true;
00499     }
00500   }
00501   else {
00502     // get all the gsf found by tracker driven
00503     passCut = true;
00504   }
00505   return passCut;
00506 }
00507 bool 
00508 PFElecTkProducer::resolveGsfTracks(const vector<reco::GsfPFRecTrack>  & GsfPFVec, 
00509                                    unsigned int ngsf, 
00510                                    vector<unsigned int> &secondaries) {
00511 
00512 
00513   reco::GsfTrackRef nGsfTrack = GsfPFVec[ngsf].gsfTrackRef();
00514 
00515   if (&(*nGsfTrack->seedRef())==0) return false;    
00516   ElectronSeedRef nElSeedRef=nGsfTrack->extra()->seedRef().castTo<ElectronSeedRef>();
00517   
00518 
00519   bool n_keepGsf = true;
00520   const math::XYZPoint nxyz = nGsfTrack->innerPosition();
00521   int nhits=nGsfTrack->numberOfValidHits();
00522   int ncharge = nGsfTrack->chargeMode();
00523   TrajectoryStateOnSurface outTSOS = mtsTransform_.outerStateOnSurface((*nGsfTrack));
00524   TrajectoryStateOnSurface inTSOS = mtsTransform_.innerStateOnSurface((*nGsfTrack));
00525   GlobalVector ninnMom;
00526 
00527   int outCharge = -2;
00528   int inCharge = -2;
00529   float nPin =  nGsfTrack->pMode();
00530   if(outTSOS.isValid())
00531     outCharge = mtsMode_->chargeFromMode(outTSOS);        
00532   if(inTSOS.isValid()){
00533     inCharge = mtsMode_->chargeFromMode(inTSOS);
00534     mtsMode_->momentumFromModeCartesian(inTSOS,ninnMom);
00535     nPin = ninnMom.mag();
00536   }
00537 
00538   float nchi2 = nGsfTrack->chi2();
00539   float neta = nGsfTrack->innerMomentum().eta();
00540   float nphi = nGsfTrack->innerMomentum().phi();
00541   float ndist = sqrt(nxyz.x()*nxyz.x()+
00542                      nxyz.y()*nxyz.y()+
00543                      nxyz.z()*nxyz.z());
00544   
00545 
00546   
00547   for (unsigned int igsf=0; igsf< GsfPFVec.size();igsf++) {
00548     if(igsf != ngsf ) {
00549 
00550       reco::GsfTrackRef iGsfTrack = GsfPFVec[igsf].gsfTrackRef();
00551 
00552       float ieta = iGsfTrack->innerMomentum().eta();
00553       float iphi = iGsfTrack->innerMomentum().phi();
00554       float feta = fabs(neta - ieta);
00555       float fphi = fabs(nphi - iphi);
00556       if (fphi>TMath::Pi()) fphi-= TMath::TwoPi();     
00557       const math::XYZPoint ixyz = iGsfTrack->innerPosition();
00558       float idist = sqrt(ixyz.x()*ixyz.x()+
00559                          ixyz.y()*ixyz.y()+
00560                          ixyz.z()*ixyz.z());
00561       
00562       float minBremDphi =  selectSecondaries(GsfPFVec[ngsf],GsfPFVec[igsf]);
00563   
00564       if(feta < 0.05 && (fabs(fphi) < 0.3 ||  minBremDphi < 0.05)) {
00565 
00566         TrajectoryStateOnSurface i_outTSOS = mtsTransform_.outerStateOnSurface((*iGsfTrack));
00567         TrajectoryStateOnSurface i_inTSOS = mtsTransform_.innerStateOnSurface((*iGsfTrack));
00568         GlobalVector i_innMom;
00569         int i_outCharge = -2;
00570         int i_inCharge = -2;
00571         float iPin = iGsfTrack->pMode();
00572         if(i_outTSOS.isValid())
00573           i_outCharge = mtsMode_->chargeFromMode(i_outTSOS);      
00574         if(i_inTSOS.isValid()){
00575           i_inCharge = mtsMode_->chargeFromMode(i_inTSOS);
00576           mtsMode_->momentumFromModeCartesian(i_inTSOS,i_innMom);  
00577           iPin = i_innMom.mag();
00578         }
00579 
00580         if (&(*iGsfTrack->seedRef())==0) continue;    
00581         ElectronSeedRef iElSeedRef=iGsfTrack->extra()->seedRef().castTo<ElectronSeedRef>();
00582         
00583         // First Case: both gsf track have a reference to a SC: cleaning using SC 
00584         if(nElSeedRef->caloCluster().isNonnull() && iElSeedRef->caloCluster().isNonnull()) {
00585 
00586           SuperClusterRef nscRef = nElSeedRef->caloCluster().castTo<SuperClusterRef>();
00587           if(nscRef.isNull()) {
00588             n_keepGsf = false;
00589             return n_keepGsf;
00590           }    
00591           float nEP = nscRef->energy()/nPin;
00592           SuperClusterRef iscRef = iElSeedRef->caloCluster().castTo<SuperClusterRef>();
00593           if(iscRef.isNonnull()) {
00594             if(nscRef == iscRef) {
00595               float iEP =  iscRef->energy()/iPin;
00596              
00597               
00598               trackingRecHit_iterator  nhit=nGsfTrack->recHitsBegin();
00599               trackingRecHit_iterator  nhit_end=nGsfTrack->recHitsEnd();
00600               unsigned int tmp_sh = 0;
00601               for (;nhit!=nhit_end;++nhit){
00602                 if ((*nhit)->isValid()){
00603                   trackingRecHit_iterator  ihit=iGsfTrack->recHitsBegin();
00604                   trackingRecHit_iterator  ihit_end=iGsfTrack->recHitsEnd();
00605                   for (;ihit!=ihit_end;++ihit){
00606                     if ((*ihit)->isValid()) {
00607                       if((*nhit)->sharesInput(&*(*ihit),TrackingRecHit::all))  tmp_sh++; 
00608                     }
00609                   }
00610                 }
00611               }
00612               if (tmp_sh>0) {
00613                 // if same SC take the closest or if same
00614                 // distance the best E/p
00615                 if (idist < (ndist-5)) {
00616                   n_keepGsf = false;
00617                   return n_keepGsf;
00618                 }
00619                 else if(ndist > (idist-5)){
00620                   if(fabs(iEP-1) < fabs(nEP-1)) {
00621                     n_keepGsf = false;
00622                     return n_keepGsf;
00623                   }
00624                   else{
00625                     if(minBremDphi < 0.05) 
00626                       secondaries.push_back(igsf);
00627                   }
00628                 }
00629                 else {
00630                   // save secondaries gsf track (put selection)
00631                   if(minBremDphi < 0.05) 
00632                     secondaries.push_back(igsf);
00633                 }
00634               }                       
00635             }
00636           }
00637         }
00638         else {
00639           // Second Case: One Gsf has reference to a SC and the other one not or both not
00640           // Cleaning using: radious first hit
00641          
00642           int ihits=iGsfTrack->numberOfValidHits();
00643           float ichi2 = iGsfTrack->chi2();
00644           int icharge = iGsfTrack->chargeMode();
00645           
00646           if (idist < (ndist-5)) {
00647             n_keepGsf = false;
00648             return n_keepGsf;
00649           }
00650           else if(ndist > (idist-5)){
00651             // Thirt Case:  One Gsf has reference to a SC and the other one not or both not
00652             // gsf tracks starts from the same layer
00653             // check number of sharing modules (at least 50%)
00654             // check number of sharing hits (at least 2)
00655             // check charge flip inner/outer
00656             
00657             unsigned int sharedMod = 0;
00658             unsigned int sharedHits = 0;
00659             
00660             trackingRecHit_iterator  nhit=nGsfTrack->recHitsBegin();
00661             trackingRecHit_iterator  nhit_end=nGsfTrack->recHitsEnd();
00662             for (;nhit!=nhit_end;++nhit){
00663               if ((*nhit)->isValid()){
00664                 trackingRecHit_iterator  ihit=iGsfTrack->recHitsBegin();
00665                 trackingRecHit_iterator  ihit_end=iGsfTrack->recHitsEnd();
00666                 for (;ihit!=ihit_end;++ihit){
00667                   if ((*ihit)->isValid()) {
00668                     if((*ihit)->geographicalId()==(*nhit)->geographicalId()) sharedMod++;
00669                     if((*nhit)->sharesInput(&*(*ihit),TrackingRecHit::all))  sharedHits++; 
00670                   }
00671                 }
00672               }
00673             }
00674             unsigned int den = ihits;
00675             if(nhits < ihits)
00676               den = nhits;
00677             if (den == 0) den = 1;          
00678             float fracMod = sharedMod*1./den*1.;
00679             
00680             TrajectoryStateOnSurface i_outTSOS = mtsTransform_.outerStateOnSurface((*iGsfTrack));
00681             TrajectoryStateOnSurface i_inTSOS = mtsTransform_.innerStateOnSurface((*iGsfTrack));
00682             int i_outCharge = -2;
00683             int i_inCharge = -2;
00684             if(i_outTSOS.isValid())
00685               i_outCharge = mtsMode_->chargeFromMode(i_outTSOS);          
00686             if(i_inTSOS.isValid())
00687             i_inCharge = mtsMode_->chargeFromMode(i_inTSOS);
00688             
00689             
00690             if(fracMod > 0.5 && sharedHits > 1 && icharge == ncharge && i_outCharge == i_inCharge) {
00691               if(ihits > nhits) {
00692                 n_keepGsf = false;
00693                 return n_keepGsf;
00694               }
00695               else if(ihits == nhits  && ichi2 < nchi2) {
00696                 n_keepGsf = false;
00697                 return n_keepGsf;
00698               }
00699               else {
00700                 if(minBremDphi < 0.05) 
00701                   secondaries.push_back(igsf);
00702               }
00703             }
00704             if(fracMod > 0.3 && sharedHits > 1 && outCharge != -2 && inCharge != outCharge) {
00705               n_keepGsf = false;
00706               return n_keepGsf;
00707             }
00708             else {
00709               if(minBremDphi < 0.05) 
00710                 secondaries.push_back(igsf);
00711             }
00712           } // end elseif
00713           else {
00714             if(minBremDphi < 0.05) 
00715               secondaries.push_back(igsf);
00716           }
00717         }
00718       }
00719     }
00720   }
00721 
00722   return n_keepGsf;
00723 }
00724 float 
00725 PFElecTkProducer::selectSecondaries(const reco::GsfPFRecTrack primGsf,
00726                                     const reco::GsfPFRecTrack secGsf) {
00727   //   bool isValidSecondary = false;
00728   
00729 
00730   float minDeta = 1000.; 
00731   float minDphi = 1000.; 
00732 
00733   // possible other selections
00734   // secondary p < primary p 
00735   
00736   // temporary: discard gsf with pMode() > 49 
00737   // or KF pt>49  (no pre-ided)
00738  
00739   PFRecTrackRef refsecKF =  secGsf.kfPFRecTrackRef();
00740   if(refsecKF.isNonnull()) {
00741     TrackRef kfref = refsecKF->trackRef();
00742     if(kfref->pt() > maxPtConvReco_)
00743       return minDphi;
00744   }
00745   
00746   reco::GsfTrackRef secGsfTrack = secGsf.gsfTrackRef();
00747   if(secGsfTrack->ptMode() > maxPtConvReco_)
00748     return minDphi;
00749   
00750 
00751 
00752   std::vector<reco::PFBrem> primPFBrem = primGsf.PFRecBrem();
00753   std::vector<reco::PFBrem> secPFBrem = secGsf.PFRecBrem();
00754 
00755 
00756   unsigned int cbrem = 0;
00757 
00758   for (unsigned isbrem = 0; isbrem < secPFBrem.size(); isbrem++) {
00759     if(secPFBrem[isbrem].indTrajPoint() == 99) continue;
00760     const reco::PFTrajectoryPoint& atSecECAL 
00761       = secPFBrem[isbrem].extrapolatedPoint( reco::PFTrajectoryPoint::ECALEntrance );
00762     if( ! atSecECAL.isValid() ) continue;
00763     float secEta = atSecECAL.positionREP().Eta();
00764     float secPhi  = atSecECAL.positionREP().Phi();
00765 
00766 
00767     for(unsigned ipbrem = 0; ipbrem < primPFBrem.size(); ipbrem++) {
00768       if(primPFBrem[ipbrem].indTrajPoint() == 99) continue;
00769       const reco::PFTrajectoryPoint& atPrimECAL 
00770         = primPFBrem[ipbrem].extrapolatedPoint( reco::PFTrajectoryPoint::ECALEntrance );
00771       if( ! atPrimECAL.isValid() ) continue;
00772       float primEta = atPrimECAL.positionREP().Eta();
00773       float primPhi = atPrimECAL.positionREP().Phi();
00774       
00775       float deta = fabs(primEta - secEta);
00776       float dphi = fabs(primPhi - secPhi);
00777       if (dphi>TMath::Pi()) dphi-= TMath::TwoPi();     
00778       if(fabs(dphi) < minDphi) {           
00779         minDeta = deta;
00780         minDphi = fabs(dphi);
00781       }
00782     }
00783     
00784     
00785     cbrem++;
00786     if(cbrem == 2) 
00787       break;
00788   }
00789   return minDphi;
00790 }
00791 // ------------ method called once each job just before starting event loop  ------------
00792 void 
00793 PFElecTkProducer::beginRun(edm::Run& run,
00794                            const EventSetup& iSetup)
00795 {
00796   ESHandle<MagneticField> magneticField;
00797   iSetup.get<IdealMagneticFieldRecord>().get(magneticField);
00798 
00799   ESHandle<TrackerGeometry> tracker;
00800   iSetup.get<TrackerDigiGeometryRecord>().get(tracker);
00801 
00802 
00803   mtsTransform_ = MultiTrajectoryStateTransform(tracker.product(),magneticField.product());
00804   
00805 
00806   pfTransformer_= new PFTrackTransformer(math::XYZVector(magneticField->inTesla(GlobalPoint(0,0,0))));
00807   
00808   
00809   edm::ESHandle<TransientTrackBuilder> builder;
00810   iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder", builder);
00811   TransientTrackBuilder thebuilder = *(builder.product());
00812   
00813 
00814   if(useConvBremFinder_) {
00815     FILE * fileConvBremID = fopen(path_mvaWeightFileConvBrem_.c_str(), "r");
00816     if (fileConvBremID) {
00817       fclose(fileConvBremID);
00818     }
00819     else {
00820       string err = "PFElecTkProducer: cannot open weight file '";
00821       err += path_mvaWeightFileConvBrem_;
00822       err += "'";
00823       throw invalid_argument( err );
00824     }
00825   }
00826   convBremFinder_ = new ConvBremPFTrackFinder(thebuilder,mvaConvBremFinderID_,path_mvaWeightFileConvBrem_);
00827 
00828 }
00829 
00830 // ------------ method called once each job just after ending the event loop  ------------
00831 void 
00832 PFElecTkProducer::endRun() {
00833   delete pfTransformer_;
00834 }
00835 
00836 //define this as a plug-in