00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <memory>
00013
00014
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
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
00126
00127
00128
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
00136 auto_ptr< GsfPFRecTrackCollection >
00137 gsfPFRecTrackCollection(new GsfPFRecTrackCollection);
00138
00139
00140 auto_ptr< GsfPFRecTrackCollection >
00141 gsfPFRecTrackCollectionSecondary(new GsfPFRecTrackCollection);
00142
00143
00144 Handle<GsfTrackCollection> gsftrackscoll;
00145 iEvent.getByLabel(gsfTrackLabel_,gsftrackscoll);
00146
00147
00148 Handle<vector<Trajectory> > TrajectoryCollection;
00149
00150
00151 Handle<PFRecTrackCollection> thePfRecTrackCollection;
00152 iEvent.getByLabel(pfTrackLabel_,thePfRecTrackCollection);
00153 const PFRecTrackCollection& PfRTkColl = *(thePfRecTrackCollection.product());
00154
00155
00156 Handle<PFClusterCollection> theECPfClustCollection;
00157 iEvent.getByLabel(pfEcalClusters_,theECPfClustCollection);
00158 const PFClusterCollection& theEcalClusters = *(theECPfClustCollection.product());
00159
00160
00161 Handle<reco::VertexCollection> thePrimaryVertexColl;
00162 iEvent.getByLabel(primVtxLabel_,thePrimaryVertexColl);
00163
00164
00165
00166
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
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
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
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
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
00320 if(keepGsf == true) {
00321
00322
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
00334
00335 primaryGsfPFRecTracks.push_back(selGsfPFRecTracks[ipfgsf]);
00336
00337
00338
00339
00340
00341 unsigned int primGsfIndex = selGsfPFRecTracks[ipfgsf].trackId();
00342 vector<reco::GsfPFRecTrack> trueGsfPFRecTracks;
00343 if(secondaries.size() > 0) {
00344
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
00354 secpftrack_= GsfPFRecTrack( gsftracks[secGsfIndex].charge(),
00355 reco::PFRecTrack::GSF,
00356 primGsfIndex, secGsfRef,
00357 refsecKF);
00358 }
00359 else{
00360 PFRecTrackRef dummyRef;
00361
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
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
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
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
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
00448
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
00474
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
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
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
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
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
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
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
00643 bool areBothGsfEcalDriven = false;;
00644 bool isSameSC = isSameEgSC(nElSeedRef,iElSeedRef,areBothGsfEcalDriven,SCEnergy);
00645
00646
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
00659
00660
00661
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
00686 secondaries.push_back(igsf);
00687 }
00688 }
00689 }
00690 else {
00691
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
00710 bool isSameLayer = false;
00711 bool iGsfInnermostWithLostHits =
00712 isInnerMostWithLostHits(nGsfTrack,iGsfTrack,isSameLayer);
00713
00714 if(isSameScEgPf) {
00715
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
00726 if (iGsfInnermostWithLostHits) {
00727 n_keepGsf = false;
00728 return n_keepGsf;
00729 }
00730 else if(isSameLayer){
00731
00732
00733
00734
00735
00736
00737
00738
00739 if(isBothGsfTrackerDriven == false) {
00740
00741 if(iEcalDriven) {
00742 n_keepGsf = false;
00743 return n_keepGsf;
00744 }
00745 else {
00746 secondaries.push_back(igsf);
00747 }
00748 }
00749 else {
00750
00751
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
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
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
00824
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
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
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
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
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
00971
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
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
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 }
01004 }
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
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
01035
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
01068
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
01119
01120
01121 reco::HitPattern gsfHitPattern1 = nGsfTrack->hitPattern();
01122 reco::HitPattern gsfHitPattern2 = iGsfTrack->hitPattern();
01123
01124
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
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
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
01218 void
01219 PFElecTkProducer::endRun() {
01220 delete pfTransformer_;
01221 }
01222
01223