00001 #include "RecoParticleFlow/PFProducer/interface/PFMuonAlgo.h"
00002 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00003 #include "DataFormats/ParticleFlowReco/interface/PFBlockElement.h"
00004 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementTrack.h"
00005 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementGsfTrack.h"
00006 #include "DataFormats/TrackReco/interface/Track.h"
00007 #include "DataFormats/MuonReco/interface/Muon.h"
00008 #include "DataFormats/MuonReco/interface/MuonSelectors.h"
00009 #include "DataFormats/MuonReco/interface/MuonCocktails.h"
00010 #include <iostream>
00011
00012
00013 using namespace std;
00014 using namespace reco;
00015 using namespace boost;
00016
00017 PFMuonAlgo::PFMuonAlgo() {
00018 pfCosmicsMuonCleanedCandidates_ = std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00019 pfCleanedTrackerAndGlobalMuonCandidates_= std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00020 pfFakeMuonCleanedCandidates_= std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00021 pfPunchThroughMuonCleanedCandidates_= std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00022 pfPunchThroughHadronCleanedCandidates_= std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00023 pfAddedMuonCandidates_= std::auto_ptr<reco::PFCandidateCollection>(new reco::PFCandidateCollection);
00024
00025 }
00026
00027
00028
00029 void PFMuonAlgo::setParameters(const edm::ParameterSet& iConfig )
00030 {
00031
00032 if(iConfig.exists("maxDPtOPt"))
00033 maxDPtOPt_ = iConfig.getParameter<double>("maxDPtOPt");
00034 else
00035 maxDPtOPt_=1.0;
00036
00037 if(iConfig.exists("minTrackerHits"))
00038 minTrackerHits_ = iConfig.getParameter<int>("minTrackerHits");
00039 else
00040 minTrackerHits_ = 8;
00041
00042 if(iConfig.exists("minPixelHits"))
00043 minPixelHits_ = iConfig.getParameter<int>("minPixelHits");
00044 else
00045 minPixelHits_ = 1;
00046
00047 if(iConfig.exists("trackQuality"))
00048 trackQuality_ = reco::TrackBase::qualityByName(iConfig.getParameter<std::string>("trackQuality"));
00049 else
00050 trackQuality_ = reco::TrackBase::qualityByName("highPurity");
00051
00052 if(iConfig.exists("ptErrorScale"))
00053 errorCompScale_ = iConfig.getParameter<double>("ptErrorScale");
00054 else
00055 errorCompScale_ = 4.;
00056
00057 if(iConfig.exists("eventFractionForCleaning"))
00058 eventFractionCleaning_ = iConfig.getParameter<double>("eventFractionForCleaning");
00059 else
00060 eventFractionCleaning_ = 0.75;
00061
00062 if(iConfig.exists("dzPV"))
00063 dzPV_ = iConfig.getParameter<double>("dzPV");
00064 else
00065 dzPV_ = 0.2;
00066
00067 if(iConfig.exists("postMuonCleaning"))
00068 postCleaning_ = iConfig.getParameter<bool>("postMuonCleaning");
00069 else
00070 postCleaning_ = false;
00071
00072 if(iConfig.exists("minPtForPostCleaning"))
00073 minPostCleaningPt_ = iConfig.getParameter<double>("minPtForPostCleaning");
00074 else
00075 minPostCleaningPt_ = 20.;
00076
00077 if(iConfig.exists("eventFactorForCosmics"))
00078 eventFactorCosmics_ = iConfig.getParameter<double>("eventFactorForCosmics");
00079 else
00080 eventFactorCosmics_ = 10.;
00081
00082
00083 if(iConfig.exists("metSignificanceForCleaning"))
00084 metSigForCleaning_ = iConfig.getParameter<double>("metSignificanceForCleaning");
00085 else
00086 metSigForCleaning_ = 3.;
00087
00088 if(iConfig.exists("metSignificanceForRejection"))
00089 metSigForRejection_ = iConfig.getParameter<double>("metSignificanceForRejection");
00090 else
00091 metSigForRejection_ = 4.;
00092
00093 if(iConfig.exists("metFactorForCleaning"))
00094 metFactorCleaning_ = iConfig.getParameter<double>("metFactorForCleaning");
00095 else
00096 metFactorCleaning_ = 4.;
00097
00098 if(iConfig.exists("eventFractionForRejection"))
00099 eventFractionRejection_ = iConfig.getParameter<double>("eventFractionForRejection");
00100 else
00101 eventFractionRejection_ = 0.75;
00102
00103 if(iConfig.exists("metFactorForRejection"))
00104 metFactorRejection_ = iConfig.getParameter<double>("metFactorForRejection");
00105 else
00106 metFactorRejection_ =4.;
00107
00108 if(iConfig.exists("metFactorForHighEta"))
00109 metFactorHighEta_ = iConfig.getParameter<double>("metFactorForHighEta");
00110 else
00111 metFactorHighEta_=4;
00112
00113 if(iConfig.exists("ptFactorForHighEta"))
00114 ptFactorHighEta_ = iConfig.getParameter<double>("ptFactorForHighEta");
00115 else
00116 ptFactorHighEta_ = 2.;
00117
00118 if(iConfig.exists("metFactorForFakes"))
00119 metFactorFake_ = iConfig.getParameter<double>("metFactorForFakes");
00120 else
00121 metFactorFake_ = 4.;
00122
00123 if(iConfig.exists("minMomentumForPunchThrough"))
00124 minPunchThroughMomentum_ = iConfig.getParameter<double>("minMomentumForPunchThrough");
00125 else
00126 minPunchThroughMomentum_=100.;
00127
00128 if(iConfig.exists("minEnergyForPunchThrough"))
00129 minPunchThroughEnergy_ = iConfig.getParameter<double>("minEnergyForPunchThrough");
00130 else
00131 minPunchThroughEnergy_ = 100.;
00132
00133 if(iConfig.exists("punchThroughFactor"))
00134 punchThroughFactor_ = iConfig.getParameter<double>("punchThroughFactor");
00135 else
00136 punchThroughFactor_ = 3.;
00137
00138 if(iConfig.exists("punchThroughMETFactor"))
00139 punchThroughMETFactor_ = iConfig.getParameter<double>("punchThroughMETFactor");
00140 else
00141 punchThroughMETFactor_ = 4.;
00142
00143 if(iConfig.exists("cosmicRejectionDistance"))
00144 cosmicRejDistance_ = iConfig.getParameter<double>("cosmicRejectionDistance");
00145 else
00146 cosmicRejDistance_ = 1.0;
00147 }
00148
00149
00150
00151
00152 bool
00153 PFMuonAlgo::isMuon( const reco::PFBlockElement& elt ) {
00154
00155 const reco::PFBlockElementTrack* eltTrack
00156 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00157
00158 assert ( eltTrack );
00159 reco::MuonRef muonRef = eltTrack->muonRef();
00160
00161 return isMuon(muonRef);
00162
00163 }
00164
00165 bool
00166 PFMuonAlgo::isLooseMuon( const reco::PFBlockElement& elt ) {
00167
00168
00169 const reco::PFBlockElementTrack* eltTrack
00170 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00171
00172
00173
00174 assert ( eltTrack );
00175
00176
00177 reco::MuonRef muonRef = eltTrack->muonRef();
00178
00179
00180 return isLooseMuon(muonRef);
00181
00182 }
00183
00184 bool
00185 PFMuonAlgo::isGlobalTightMuon( const reco::PFBlockElement& elt ) {
00186
00187 const reco::PFBlockElementTrack* eltTrack
00188 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00189
00190 assert ( eltTrack );
00191 reco::MuonRef muonRef = eltTrack->muonRef();
00192
00193 return isGlobalTightMuon(muonRef);
00194
00195 }
00196
00197 bool
00198 PFMuonAlgo::isGlobalLooseMuon( const reco::PFBlockElement& elt ) {
00199
00200 const reco::PFBlockElementTrack* eltTrack
00201 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00202
00203 assert ( eltTrack );
00204 reco::MuonRef muonRef = eltTrack->muonRef();
00205
00206 return isGlobalLooseMuon(muonRef);
00207
00208 }
00209
00210 bool
00211 PFMuonAlgo::isTrackerTightMuon( const reco::PFBlockElement& elt ) {
00212
00213 const reco::PFBlockElementTrack* eltTrack
00214 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00215
00216 assert ( eltTrack );
00217 reco::MuonRef muonRef = eltTrack->muonRef();
00218
00219 return isTrackerTightMuon(muonRef);
00220
00221 }
00222
00223 bool
00224 PFMuonAlgo::isIsolatedMuon( const reco::PFBlockElement& elt ) {
00225
00226 const reco::PFBlockElementTrack* eltTrack
00227 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
00228
00229 assert ( eltTrack );
00230 reco::MuonRef muonRef = eltTrack->muonRef();
00231
00232 return isIsolatedMuon(muonRef);
00233
00234 }
00235
00236 bool
00237 PFMuonAlgo::isMuon(const reco::MuonRef& muonRef ){
00238
00239 return isGlobalTightMuon(muonRef) || isTrackerTightMuon(muonRef) || isIsolatedMuon(muonRef);
00240 }
00241
00242 bool
00243 PFMuonAlgo::isLooseMuon(const reco::MuonRef& muonRef ){
00244
00245 return isGlobalLooseMuon(muonRef) || isTrackerLooseMuon(muonRef);
00246
00247 }
00248
00249 bool
00250 PFMuonAlgo::isGlobalTightMuon( const reco::MuonRef& muonRef ) {
00251
00252 if ( !muonRef.isNonnull() ) return false;
00253
00254 if ( !muonRef->isGlobalMuon() ) return false;
00255 if ( !muonRef->isStandAloneMuon() ) return false;
00256
00257
00258 if ( muonRef->isTrackerMuon() ) {
00259
00260 bool result = muon::isGoodMuon(*muonRef,muon::GlobalMuonPromptTight);
00261
00262 bool isTM2DCompatibilityTight = muon::isGoodMuon(*muonRef,muon::TM2DCompatibilityTight);
00263 int nMatches = muonRef->numberOfMatches();
00264 bool quality = nMatches > 2 || isTM2DCompatibilityTight;
00265
00266 return result && quality;
00267
00268 } else {
00269
00270 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
00271
00272
00273 bool result = false;
00274
00275
00276
00277 if ( ( standAloneMu->hitPattern().numberOfValidMuonDTHits() < 22 &&
00278 standAloneMu->hitPattern().numberOfValidMuonCSCHits() < 15 ) ||
00279 standAloneMu->normalizedChi2() > 10. ||
00280 standAloneMu->ptError()/standAloneMu->pt() > 0.20 ) {
00281 result = false;
00282 } else {
00283
00284 reco::TrackRef combinedMu = muonRef->combinedMuon();
00285 reco::TrackRef trackerMu = muonRef->track();
00286
00287
00288 if ( combinedMu->normalizedChi2() > standAloneMu->normalizedChi2() ) {
00289
00290
00291
00292
00293
00294
00295 result = standAloneMu->pt() > trackerMu->pt() ;
00296 } else {
00297
00298
00299 result =
00300 combinedMu->ptError()/combinedMu->pt() <
00301 std::min(0.20,standAloneMu->ptError()/standAloneMu->pt());
00302 }
00303 }
00304
00305 return result;
00306 }
00307
00308 return false;
00309
00310 }
00311
00312 bool
00313 PFMuonAlgo::isTrackerTightMuon( const reco::MuonRef& muonRef ) {
00314
00315 if ( !muonRef.isNonnull() ) return false;
00316
00317 if(!muonRef->isTrackerMuon()) return false;
00318
00319 reco::TrackRef trackerMu = muonRef->track();
00320 const reco::Track& track = *trackerMu;
00321
00322 unsigned nTrackerHits = track.hitPattern().numberOfValidTrackerHits();
00323
00324 if(nTrackerHits<=12) return false;
00325
00326 bool isAllArbitrated = muon::isGoodMuon(*muonRef,muon::AllArbitrated);
00327
00328 bool isTM2DCompatibilityTight = muon::isGoodMuon(*muonRef,muon::TM2DCompatibilityTight);
00329
00330 if(!isAllArbitrated || !isTM2DCompatibilityTight) return false;
00331
00332 if((trackerMu->ptError()/trackerMu->pt() > 0.10)){
00333
00334 return false;
00335 }
00336 return true;
00337
00338 }
00339
00340 bool
00341 PFMuonAlgo::isGlobalLooseMuon( const reco::MuonRef& muonRef ) {
00342
00343 if ( !muonRef.isNonnull() ) return false;
00344 if ( !muonRef->isGlobalMuon() ) return false;
00345 if ( !muonRef->isStandAloneMuon() ) return false;
00346
00347 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
00348 reco::TrackRef combinedMu = muonRef->combinedMuon();
00349 reco::TrackRef trackerMu = muonRef->track();
00350
00351 unsigned nMuonHits =
00352 standAloneMu->hitPattern().numberOfValidMuonDTHits() +
00353 2*standAloneMu->hitPattern().numberOfValidMuonCSCHits();
00354
00355 bool quality = false;
00356
00357 if ( muonRef->isTrackerMuon() ){
00358
00359 bool result = combinedMu->normalizedChi2() < 100.;
00360
00361 bool laststation =
00362 muon::isGoodMuon(*muonRef,muon::TMLastStationAngTight);
00363
00364 int nMatches = muonRef->numberOfMatches();
00365
00366 quality = laststation && nMuonHits > 12 && nMatches > 1;
00367
00368 return result && quality;
00369
00370 }
00371 else{
00372
00373
00374
00375 if ( nMuonHits <=15 ||
00376 standAloneMu->normalizedChi2() > 10. ||
00377 standAloneMu->ptError()/standAloneMu->pt() > 0.20 ) {
00378 quality = false;
00379 }
00380 else {
00381
00382 if ( combinedMu->normalizedChi2() > standAloneMu->normalizedChi2() ) {
00383
00384
00385
00386
00387
00388
00389
00390
00391 if(standAloneMu->pt() > trackerMu->pt() || combinedMu->normalizedChi2()<5.) quality = true;
00392 }
00393 else {
00394
00395
00396 if(combinedMu->ptError()/combinedMu->pt() < std::min(0.20,standAloneMu->ptError()/standAloneMu->pt()))
00397 quality = true;
00398
00399 }
00400 }
00401 }
00402
00403
00404 return quality;
00405
00406 }
00407
00408
00409 bool
00410 PFMuonAlgo::isTrackerLooseMuon( const reco::MuonRef& muonRef ) {
00411
00412 if ( !muonRef.isNonnull() ) return false;
00413 if(!muonRef->isTrackerMuon()) return false;
00414
00415 reco::TrackRef trackerMu = muonRef->track();
00416
00417 if(trackerMu->ptError()/trackerMu->pt() > 0.20) return false;
00418
00419
00420 if(trackerMu->pt()>20.) return false;
00421
00422 bool isAllArbitrated = muon::isGoodMuon(*muonRef,muon::AllArbitrated);
00423 bool isTMLastStationAngTight = muon::isGoodMuon(*muonRef,muon::TMLastStationAngTight);
00424
00425 bool quality = isAllArbitrated && isTMLastStationAngTight;
00426
00427 return quality;
00428
00429 }
00430
00431 bool
00432 PFMuonAlgo::isIsolatedMuon( const reco::MuonRef& muonRef ){
00433
00434
00435 if ( !muonRef.isNonnull() ) return false;
00436 if ( !muonRef->isIsolationValid() ) return false;
00437
00438
00439 if ( !muonRef->isGlobalMuon() ) return false;
00440
00441
00442
00443 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
00444
00445 if ( !muonRef->isTrackerMuon() ){
00446 if(standAloneMu->hitPattern().numberOfValidMuonDTHits() == 0 &&
00447 standAloneMu->hitPattern().numberOfValidMuonCSCHits() ==0) return false;
00448 }
00449
00450
00451
00452 reco::TrackRef combinedMu = muonRef->combinedMuon();
00453 double smallestMuPt = combinedMu->pt();
00454
00455 if(standAloneMu->pt()<smallestMuPt) smallestMuPt = standAloneMu->pt();
00456
00457 if(muonRef->isTrackerMuon())
00458 {
00459 reco::TrackRef trackerMu = muonRef->track();
00460 if(trackerMu->pt() < smallestMuPt) smallestMuPt= trackerMu->pt();
00461 }
00462
00463 double sumPtR03 = muonRef->isolationR03().sumPt;
00464 double emEtR03 = muonRef->isolationR03().emEt;
00465 double hadEtR03 = muonRef->isolationR03().hadEt;
00466
00467 double relIso = (sumPtR03 + emEtR03 + hadEtR03)/smallestMuPt;
00468
00469 if(relIso<0.1) return true;
00470 else return false;
00471 }
00472
00473 bool
00474 PFMuonAlgo::isTightMuonPOG(const reco::MuonRef& muonRef) {
00475
00476 if(!muon::isGoodMuon(*muonRef,muon::GlobalMuonPromptTight)) return false;
00477
00478 if(!muonRef->isTrackerMuon()) return false;
00479
00480 if(muonRef->numberOfMatches()<2) return false;
00481
00482
00483 const reco::TrackRef& combinedMuon = muonRef->globalTrack();
00484
00485 if(combinedMuon->hitPattern().numberOfValidTrackerHits()<11) return false;
00486
00487 if(combinedMuon->hitPattern().numberOfValidPixelHits()==0) return false;
00488
00489 if(combinedMuon->hitPattern().numberOfValidMuonHits()==0) return false;
00490
00491 return true;
00492
00493 }
00494
00495 void
00496 PFMuonAlgo::printMuonProperties(const reco::MuonRef& muonRef){
00497
00498 if ( !muonRef.isNonnull() ) return;
00499
00500 bool isGL = muonRef->isGlobalMuon();
00501 bool isTR = muonRef->isTrackerMuon();
00502 bool isST = muonRef->isStandAloneMuon();
00503
00504 std::cout<<" GL: "<<isGL<<" TR: "<<isTR<<" ST: "<<isST<<std::endl;
00505 std::cout<<" nMatches "<<muonRef->numberOfMatches()<<std::endl;
00506
00507 if ( muonRef->isGlobalMuon() ){
00508 reco::TrackRef combinedMu = muonRef->combinedMuon();
00509 std::cout<<" GL, pt: " << combinedMu->pt()
00510 << " +/- " << combinedMu->ptError()/combinedMu->pt()
00511 << " chi**2 GBL : " << combinedMu->normalizedChi2()<<std::endl;
00512 std::cout<< " Total Muon Hits : " << combinedMu->hitPattern().numberOfValidMuonHits()
00513 << "/" << combinedMu->hitPattern().numberOfLostMuonHits()
00514 << " DT Hits : " << combinedMu->hitPattern().numberOfValidMuonDTHits()
00515 << "/" << combinedMu->hitPattern().numberOfLostMuonDTHits()
00516 << " CSC Hits : " << combinedMu->hitPattern().numberOfValidMuonCSCHits()
00517 << "/" << combinedMu->hitPattern().numberOfLostMuonCSCHits()
00518 << " RPC Hits : " << combinedMu->hitPattern().numberOfValidMuonRPCHits()
00519 << "/" << combinedMu->hitPattern().numberOfLostMuonRPCHits()<<std::endl;
00520
00521 std::cout<<" # of Valid Tracker Hits "<<combinedMu->hitPattern().numberOfValidTrackerHits()<<std::endl;
00522 std::cout<<" # of Valid Pixel Hits "<<combinedMu->hitPattern().numberOfValidPixelHits()<<std::endl;
00523 }
00524 if ( muonRef->isStandAloneMuon() ){
00525 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
00526 std::cout<<" ST, pt: " << standAloneMu->pt()
00527 << " +/- " << standAloneMu->ptError()/standAloneMu->pt()
00528 << " eta : " << standAloneMu->eta()
00529 << " DT Hits : " << standAloneMu->hitPattern().numberOfValidMuonDTHits()
00530 << "/" << standAloneMu->hitPattern().numberOfLostMuonDTHits()
00531 << " CSC Hits : " << standAloneMu->hitPattern().numberOfValidMuonCSCHits()
00532 << "/" << standAloneMu->hitPattern().numberOfLostMuonCSCHits()
00533 << " RPC Hits : " << standAloneMu->hitPattern().numberOfValidMuonRPCHits()
00534 << "/" << standAloneMu->hitPattern().numberOfLostMuonRPCHits()
00535 << " chi**2 STA : " << standAloneMu->normalizedChi2()<<std::endl;
00536 }
00537
00538
00539 if ( muonRef->isTrackerMuon() ){
00540 reco::TrackRef trackerMu = muonRef->track();
00541 const reco::Track& track = *trackerMu;
00542 std::cout<<" TR, pt: " << trackerMu->pt()
00543 << " +/- " << trackerMu->ptError()/trackerMu->pt()
00544 << " chi**2 TR : " << trackerMu->normalizedChi2()<<std::endl;
00545 std::cout<<" nTrackerHits "<<track.hitPattern().numberOfValidTrackerHits()<<std::endl;
00546 std::cout<< "TMLastStationAngLoose "
00547 << muon::isGoodMuon(*muonRef,muon::TMLastStationAngLoose) << std::endl
00548 << "TMLastStationAngTight "
00549 << muon::isGoodMuon(*muonRef,muon::TMLastStationAngTight) << std::endl
00550 << "TMLastStationLoose "
00551 << muon::isGoodMuon(*muonRef,muon::TMLastStationLoose) << std::endl
00552 << "TMLastStationTight "
00553 << muon::isGoodMuon(*muonRef,muon::TMLastStationTight) << std::endl
00554 << "TMOneStationLoose "
00555 << muon::isGoodMuon(*muonRef,muon::TMOneStationLoose) << std::endl
00556 << "TMOneStationTight "
00557 << muon::isGoodMuon(*muonRef,muon::TMOneStationTight) << std::endl
00558 << "TMLastStationOptimizedLowPtLoose "
00559 << muon::isGoodMuon(*muonRef,muon::TMLastStationOptimizedLowPtLoose) << std::endl
00560 << "TMLastStationOptimizedLowPtTight "
00561 << muon::isGoodMuon(*muonRef,muon::TMLastStationOptimizedLowPtTight) << std::endl
00562 << "TMLastStationOptimizedBarrelLowPtLoose "
00563 << muon::isGoodMuon(*muonRef,muon::TMLastStationOptimizedBarrelLowPtLoose) << std::endl
00564 << "TMLastStationOptimizedBarrelLowPtTight "
00565 << muon::isGoodMuon(*muonRef,muon::TMLastStationOptimizedBarrelLowPtTight) << std::endl
00566 << std::endl;
00567
00568 }
00569
00570 std::cout<< "TM2DCompatibilityLoose "
00571 << muon::isGoodMuon(*muonRef,muon::TM2DCompatibilityLoose) << std::endl
00572 << "TM2DCompatibilityTight "
00573 << muon::isGoodMuon(*muonRef,muon::TM2DCompatibilityTight) << std::endl;
00574
00575
00576
00577 if ( muonRef->isGlobalMuon() && muonRef->isTrackerMuon() && muonRef->isStandAloneMuon() ){
00578 reco::TrackRef combinedMu = muonRef->combinedMuon();
00579 reco::TrackRef trackerMu = muonRef->track();
00580 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
00581
00582 double sigmaCombined = combinedMu->ptError()/(combinedMu->pt()*combinedMu->pt());
00583 double sigmaTracker = trackerMu->ptError()/(trackerMu->pt()*trackerMu->pt());
00584 double sigmaStandAlone = standAloneMu->ptError()/(standAloneMu->pt()*standAloneMu->pt());
00585
00586 bool combined = combinedMu->ptError()/combinedMu->pt() < 0.20;
00587 bool tracker = trackerMu->ptError()/trackerMu->pt() < 0.20;
00588 bool standAlone = standAloneMu->ptError()/standAloneMu->pt() < 0.20;
00589
00590 double delta1 = combined && tracker ?
00591 fabs(1./combinedMu->pt() -1./trackerMu->pt())
00592 /sqrt(sigmaCombined*sigmaCombined + sigmaTracker*sigmaTracker) : 100.;
00593 double delta2 = combined && standAlone ?
00594 fabs(1./combinedMu->pt() -1./standAloneMu->pt())
00595 /sqrt(sigmaCombined*sigmaCombined + sigmaStandAlone*sigmaStandAlone) : 100.;
00596 double delta3 = standAlone && tracker ?
00597 fabs(1./standAloneMu->pt() -1./trackerMu->pt())
00598 /sqrt(sigmaStandAlone*sigmaStandAlone + sigmaTracker*sigmaTracker) : 100.;
00599
00600 double delta =
00601 standAloneMu->hitPattern().numberOfValidMuonDTHits()+
00602 standAloneMu->hitPattern().numberOfValidMuonCSCHits() > 0 ?
00603 std::min(delta3,std::min(delta1,delta2)) : std::max(delta3,std::max(delta1,delta2));
00604
00605 std::cout << "delta = " << delta << " delta1 "<<delta1<<" delta2 "<<delta2<<" delta3 "<<delta3<<std::endl;
00606
00607 double ratio =
00608 combinedMu->ptError()/combinedMu->pt()
00609 / (trackerMu->ptError()/trackerMu->pt());
00610
00611 std::cout<<" ratio "<<ratio<<" combined mu pt "<<combinedMu->pt()<<std::endl;
00612
00613
00614
00615 }
00616
00617 double sumPtR03 = muonRef->isolationR03().sumPt;
00618 double emEtR03 = muonRef->isolationR03().emEt;
00619 double hadEtR03 = muonRef->isolationR03().hadEt;
00620 double relIsoR03 = (sumPtR03 + emEtR03 + hadEtR03)/muonRef->pt();
00621 double sumPtR05 = muonRef->isolationR05().sumPt;
00622 double emEtR05 = muonRef->isolationR05().emEt;
00623 double hadEtR05 = muonRef->isolationR05().hadEt;
00624 double relIsoR05 = (sumPtR05 + emEtR05 + hadEtR05)/muonRef->pt();
00625 std::cout<<" 0.3 Radion Rel Iso: "<<relIsoR03<<" sumPt "<<sumPtR03<<" emEt "<<emEtR03<<" hadEt "<<hadEtR03<<std::endl;
00626 std::cout<<" 0.5 Radion Rel Iso: "<<relIsoR05<<" sumPt "<<sumPtR05<<" emEt "<<emEtR05<<" hadEt "<<hadEtR05<<std::endl;
00627 return;
00628
00629 }
00630
00631
00632
00633 std::vector<reco::Muon::MuonTrackTypePair> PFMuonAlgo::goodMuonTracks(const reco::MuonRef& muon,bool includeSA) {
00634 return muonTracks(muon,includeSA,maxDPtOPt_);
00635 }
00636
00637
00638
00639 std::vector<reco::Muon::MuonTrackTypePair> PFMuonAlgo::muonTracks(const reco::MuonRef& muon,bool includeSA,double dpt) {
00640
00641
00642
00643 std::vector<reco::Muon::MuonTrackTypePair> out;
00644
00645
00646 if(muon->globalTrack().isNonnull())
00647 if(muon->globalTrack()->ptError()/muon->globalTrack()->pt()<dpt)
00648 out.push_back(std::make_pair(muon->globalTrack(),reco::Muon::CombinedTrack));
00649
00650 if(muon->innerTrack().isNonnull())
00651 if(muon->innerTrack()->ptError()/muon->innerTrack()->pt()<dpt)
00652 out.push_back(std::make_pair(muon->innerTrack(),reco::Muon::InnerTrack));
00653
00654 bool pickyExists=false;
00655 if(muon->pickyTrack().isNonnull()) {
00656 if(muon->pickyTrack()->ptError()/muon->pickyTrack()->pt()<dpt)
00657 out.push_back(std::make_pair(muon->pickyTrack(),reco::Muon::Picky));
00658 pickyExists=true;
00659 }
00660
00661
00662
00663
00664 if(muon->tpfmsTrack().isNonnull() && ((pickyExists && muon->tpfmsTrack()->ptError()/muon->tpfmsTrack()->pt()<muon->pickyTrack()->ptError()/muon->pickyTrack()->pt())||(!pickyExists)) )
00665 if(muon->tpfmsTrack()->ptError()/muon->tpfmsTrack()->pt()<dpt)
00666 out.push_back(std::make_pair(muon->tpfmsTrack(),reco::Muon::TPFMS));
00667
00668 if(includeSA && muon->outerTrack().isNonnull())
00669 if(muon->outerTrack()->ptError()/muon->outerTrack()->pt()<dpt)
00670 out.push_back(std::make_pair(muon->outerTrack(),reco::Muon::OuterTrack));
00671
00672 return out;
00673
00674 }
00675
00676
00677
00678
00679
00681
00682
00683
00684
00685 bool PFMuonAlgo::reconstructMuon(reco::PFCandidate& candidate, const reco::MuonRef& muon, bool allowLoose) {
00686 using namespace std;
00687 using namespace reco;
00688
00689 if (!muon.isNonnull())
00690 return false;
00691
00692
00693
00694 bool isMu=false;
00695
00696 if(allowLoose)
00697 isMu = isMuon(muon) || isLooseMuon(muon);
00698 else
00699 isMu = isMuon(muon);
00700
00701 if( !isMu)
00702 return false;
00703
00704
00705
00706
00707
00708
00709 std::vector<reco::Muon::MuonTrackTypePair> validTracks = goodMuonTracks(muon);
00710 if (!allowLoose)
00711 validTracks = goodMuonTracks(muon);
00712 else
00713 validTracks = muonTracks(muon);
00714
00715 if( validTracks.size() ==0)
00716 return false;
00717
00718
00719
00720
00721 reco::Muon::MuonTrackTypePair bestTrackPair = muon::tevOptimized(*muon);
00722
00723 TrackRef bestTrack = bestTrackPair.first;
00724 MuonTrackType trackType = bestTrackPair.second;
00725
00726
00727
00728 MuonTrackTypePair trackPairWithSmallestError = getTrackWithSmallestError(validTracks);
00729 TrackRef trackWithSmallestError = trackPairWithSmallestError.first;
00730
00731 if( trackType == reco::Muon::InnerTrack &&
00732 (!bestTrack->quality(trackQuality_) ||
00733 bestTrack->ptError()/bestTrack->pt()> errorCompScale_*trackWithSmallestError->ptError()/trackWithSmallestError->pt() )) {
00734 bestTrack = trackWithSmallestError;
00735 trackType = trackPairWithSmallestError.second;
00736 }
00737 else if (trackType != reco::Muon::InnerTrack &&
00738 bestTrack->ptError()/bestTrack->pt()> errorCompScale_*trackWithSmallestError->ptError()/trackWithSmallestError->pt()) {
00739 bestTrack = trackWithSmallestError;
00740 trackType = trackPairWithSmallestError.second;
00741
00742 }
00743
00744
00745 changeTrack(candidate,std::make_pair(bestTrack,trackType));
00746 candidate.setMuonRef( muon );
00747
00748 return true;
00749 }
00750
00751
00752
00753
00754 void PFMuonAlgo::changeTrack(reco::PFCandidate& candidate,const MuonTrackTypePair& track) {
00755 using namespace reco;
00756 reco::TrackRef bestTrack = track.first;
00757 MuonTrackType trackType = track.second;
00758
00759 double px = bestTrack->px();
00760 double py = bestTrack->py();
00761 double pz = bestTrack->pz();
00762 double energy = sqrt(bestTrack->p()*bestTrack->p() + 0.13957*0.13957);
00763
00764 candidate.setCharge(bestTrack->charge()>0 ? 1 : -1);
00765 candidate.setP4(math::XYZTLorentzVector(px,py,pz,energy));
00766 candidate.setParticleType(reco::PFCandidate::mu);
00767
00768 candidate.setMuonTrackType(trackType);
00769 if(trackType == reco::Muon::InnerTrack)
00770 candidate.setVertexSource( PFCandidate::kTrkMuonVertex );
00771 else if(trackType == reco::Muon::CombinedTrack)
00772 candidate.setVertexSource( PFCandidate::kComMuonVertex );
00773 else if(trackType == reco::Muon::TPFMS)
00774 candidate.setVertexSource( PFCandidate::kTPFMSMuonVertex );
00775 else if(trackType == reco::Muon::Picky)
00776 candidate.setVertexSource( PFCandidate::kPickyMuonVertex );
00777 }
00778
00779
00780 reco::Muon::MuonTrackTypePair
00781 PFMuonAlgo::getTrackWithSmallestError(const std::vector<reco::Muon::MuonTrackTypePair>& tracks) {
00782 TrackPtErrorSorter sorter;
00783 return *std::min_element(tracks.begin(),tracks.end(),sorter);
00784 }
00785
00786
00787
00788
00789
00790 void PFMuonAlgo::estimateEventQuantities(const reco::PFCandidateCollection* pfc)
00791 {
00792
00793 sumetPU_ = 0.0;
00794 METX_=0.;
00795 METY_=0.;
00796 for (unsigned short i=1 ;i<vertices_->size();++i ) {
00797 if ( !vertices_->at(i).isValid() || vertices_->at(i).isFake() ) continue;
00798 vertices_->at(i);
00799 for ( reco::Vertex::trackRef_iterator itr = vertices_->at(i).tracks_begin();
00800 itr < vertices_->at(i).tracks_end(); ++itr ) {
00801 sumetPU_ += (*itr)->pt();
00802 }
00803 }
00804 sumetPU_ /= 0.65;
00805
00806 sumet_=0.0;
00807 double METXCh=0.0;
00808 double METYCh=0.0;
00809 double METXNeut=0.0;
00810 double METYNeut=0.0;
00811
00812
00813 for(reco::PFCandidateCollection::const_iterator i = pfc->begin();i!=pfc->end();++i) {
00814 sumet_+=i->pt();
00815
00816 if (vertices_->size()>0 && vertices_->at(0).isValid()&& !vertices_->at(0).isFake()) {
00817
00818 if( (i->charge() !=0 && i->trackRef().isNonnull() && vertices_->size()>0&& i->trackRef()->dz(vertices_->at(0).position())<dzPV_)||(abs(i->pdgId())==13)) {
00819 METXCh+=i->px();
00820 METYCh+=i->py();
00821 }
00822
00823 else if( i->charge() !=0 && i->trackRef().isNonnull() && i->trackRef()->dz(vertices_->at(0).position())>dzPV_) {
00824 METXNeut-=i->px();
00825 METYNeut-=i->py();
00826 }
00827
00828 else if( !(i->charge() !=0 && i->trackRef().isNonnull())) {
00829 METXNeut+=i->px();
00830 METYNeut+=i->py();
00831 }
00832 }
00833 else {
00834 METXCh+=i->px();
00835 METYCh+=i->py();
00836 }
00837 METX_ = (METXCh+METXNeut);
00838 METY_ = (METYCh+METYNeut);
00839 }
00840
00841 }
00842
00843
00844
00845
00846 void PFMuonAlgo::postClean(reco::PFCandidateCollection* cands) {
00847 using namespace std;
00848 using namespace reco;
00849 if (!postCleaning_)
00850 return;
00851
00852
00853
00854 if(pfCosmicsMuonCleanedCandidates_.get() )
00855 pfCosmicsMuonCleanedCandidates_->clear();
00856 else
00857 pfCosmicsMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00858
00859 if(pfCleanedTrackerAndGlobalMuonCandidates_.get() )
00860 pfCleanedTrackerAndGlobalMuonCandidates_->clear();
00861 else
00862 pfCleanedTrackerAndGlobalMuonCandidates_.reset( new reco::PFCandidateCollection );
00863
00864 if( pfFakeMuonCleanedCandidates_.get() )
00865 pfFakeMuonCleanedCandidates_->clear();
00866 else
00867 pfFakeMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00868
00869
00870 if( pfPunchThroughMuonCleanedCandidates_.get() )
00871 pfPunchThroughMuonCleanedCandidates_->clear();
00872 else
00873 pfPunchThroughMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00874
00875 if( pfPunchThroughHadronCleanedCandidates_.get() )
00876 pfPunchThroughHadronCleanedCandidates_->clear();
00877 else
00878 pfPunchThroughHadronCleanedCandidates_.reset( new reco::PFCandidateCollection );
00879
00880
00881
00882 pfPunchThroughHadronCleanedCandidates_->clear();
00883
00884 maskedIndices_.clear();
00885
00886
00887
00888 estimateEventQuantities(cands);
00889
00890
00891 std::vector<int> muons;
00892 std::vector<int> cosmics;
00893
00894 for(unsigned int i=0;i<cands->size();++i)
00895 if ( cands->at(i).particleId() == reco::PFCandidate::mu )
00896 muons.push_back(i);
00897
00898
00899
00900 IndexPtComparator comparator(cands);
00901 std::sort(muons.begin(),muons.end(),comparator);
00902
00903
00904
00905 double METXCosmics=0;
00906 double METYCosmics=0;
00907 double SUMETCosmics=0.0;
00908
00909 for(unsigned int i=0;i<muons.size();++i) {
00910 const PFCandidate& pfc = cands->at(muons[i]);
00911 double origin=0.0;
00912 if(vertices_->size()>0&& vertices_->at(0).isValid() && ! vertices_->at(0).isFake())
00913 origin = pfc.muonRef()->muonBestTrack()->dxy(vertices_->at(0).position());
00914
00915 if( origin> cosmicRejDistance_) {
00916 cosmics.push_back(muons[i]);
00917 METXCosmics +=pfc.px();
00918 METYCosmics +=pfc.py();
00919 SUMETCosmics +=pfc.pt();
00920 }
00921 }
00922 double MET2Cosmics = METXCosmics*METXCosmics+METYCosmics*METYCosmics;
00923
00924 if ( SUMETCosmics > (sumet_-sumetPU_)/eventFactorCosmics_ && MET2Cosmics < METX_*METX_+ METY_*METY_)
00925 for(unsigned int i=0;i<cosmics.size();++i)
00926 pfCosmicsMuonCleanedCandidates_->push_back(cands->at(muons[i]));
00927
00928
00929
00930 for(unsigned int i=0;i<muons.size();++i) {
00931
00932 if( cleanMismeasured(cands->at(muons[i]),muons[i]))
00933 continue;
00934 cleanPunchThroughAndFakes(cands->at(muons[i]),cands,muons[i]);
00935
00936 }
00937
00938
00939
00940
00941 removeDeadCandidates(cands,maskedIndices_);
00942
00943
00944
00945
00946 }
00947
00948 void PFMuonAlgo::addMissingMuons(edm::Handle<reco::MuonCollection> muons, reco::PFCandidateCollection* cands) {
00949 if(!postCleaning_)
00950 return;
00951
00952
00953 if( pfAddedMuonCandidates_.get() )
00954 pfAddedMuonCandidates_->clear();
00955 else
00956 pfAddedMuonCandidates_.reset( new reco::PFCandidateCollection );
00957
00958
00959
00960 for ( unsigned imu = 0; imu < muons->size(); ++imu ) {
00961 reco::MuonRef muonRef( muons, imu );
00962 bool used = false;
00963 bool hadron = false;
00964 for(unsigned i=0; i<cands->size(); i++) {
00965 const PFCandidate& pfc = cands->at(i);
00966 if ( !pfc.trackRef().isNonnull() ) continue;
00967 if ( pfc.trackRef().isNonnull() && pfc.trackRef() == muonRef->track() )
00968 hadron = true;
00969 if ( !pfc.muonRef().isNonnull() ) continue;
00970
00971 if ( pfc.muonRef()->innerTrack() == muonRef->innerTrack())
00972 used = true;
00973 else {
00974
00975
00976 if ( pfc.muonRef()->isStandAloneMuon() && muonRef->isStandAloneMuon() ) {
00977 double dEta = pfc.muonRef()->standAloneMuon()->eta() - muonRef->standAloneMuon()->eta();
00978 double dPhi = pfc.muonRef()->standAloneMuon()->phi() - muonRef->standAloneMuon()->phi();
00979 double dR = sqrt(dEta*dEta + dPhi*dPhi);
00980 if ( dR < 0.005 ) {
00981 used = true;
00982 }
00983 }
00984 }
00985
00986 if ( used ) break;
00987 }
00988
00989 if ( used ||hadron||(!muonRef.isNonnull()) ) continue;
00990
00991
00992 TrackMETComparator comparator(METX_,METY_);
00993
00994
00995 std::vector<reco::Muon::MuonTrackTypePair> tracks = goodMuonTracks(muonRef,true);
00996
00997 if(tracks.size()>0) {
00998
00999
01000 std::vector<reco::Muon::MuonTrackTypePair> tracksThatChangeMET = tracksPointingAtMET(tracks);
01001
01002 if (tracksThatChangeMET.size()>0) {
01003 reco::Muon::MuonTrackTypePair bestTrackType = *std::min_element(tracksThatChangeMET.begin(),tracksThatChangeMET.end(),comparator);
01004
01005
01006 if((vertices_->size()==0) ||bestTrackType.first->dz(vertices_->at(0).position())<cosmicRejDistance_){
01007
01008
01009 int charge = bestTrackType.first->charge()>0 ? 1 : -1;
01010 math::XYZTLorentzVector momentum(bestTrackType.first->px(),
01011 bestTrackType.first->py(),
01012 bestTrackType.first->pz(),
01013 sqrt(bestTrackType.first->p()*bestTrackType.first->p()+0.1057*0.1057));
01014
01015 cands->push_back( PFCandidate( charge,
01016 momentum,
01017 reco::PFCandidate::mu ) );
01018
01019 changeTrack(cands->back(),bestTrackType);
01020
01021 if (muonRef->track().isNonnull() )
01022 cands->back().setTrackRef( muonRef->track() );
01023
01024 cands->back().setMuonRef(muonRef);
01025
01026
01027 pfAddedMuonCandidates_->push_back(cands->back());
01028
01029 }
01030 }
01031 }
01032 }
01033 }
01034
01035 std::pair<double,double>
01036 PFMuonAlgo::getMinMaxMET2(const reco::PFCandidate&pfc) {
01037 std::vector<reco::Muon::MuonTrackTypePair> tracks = goodMuonTracks((pfc.muonRef()),true);
01038
01039 double METXNO = METX_-pfc.px();
01040 double METYNO = METY_-pfc.py();
01041 std::vector<double> met2;
01042 for (unsigned int i=0;i<tracks.size();++i) {
01043 met2.push_back(pow(METXNO+tracks.at(i).first->px(),2)+pow(METYNO+tracks.at(i).first->py(),2));
01044 }
01045
01046
01047
01048
01049 if(tracks.size()>1)
01050 return std::make_pair(*std::min_element(met2.begin(),met2.end()),*std::max_element(met2.begin(),met2.end()));
01051 else
01052 return std::make_pair(0,0);
01053 }
01054
01055
01056 bool PFMuonAlgo::cleanMismeasured(reco::PFCandidate& pfc,unsigned int i ){
01057 using namespace std;
01058 using namespace reco;
01059 bool cleaned=false;
01060
01061
01062 double METNOX = METX_ - pfc.px();
01063 double METNOY = METY_ - pfc.py();
01064 double SUMETNO = sumet_ -pfc.pt();
01065
01066 TrackMETComparator comparator(METNOX,METNOY);
01067
01068 if (pfc.pt()<minPostCleaningPt_)
01069 return false;
01070 std::vector<reco::Muon::MuonTrackTypePair> tracks = goodMuonTracks(pfc.muonRef(),false);
01071
01072
01073
01074
01075 if(tracks.size()>1) {
01076
01077 std::vector<reco::Muon::MuonTrackTypePair> tracksThatChangeMET = tracksWithBetterMET(tracks,pfc);
01078
01079 if (tracksThatChangeMET.size()>0) {
01080 reco::Muon::MuonTrackTypePair bestTrackType = *std::min_element(tracksThatChangeMET.begin(),tracksThatChangeMET.end(),comparator);
01081 changeTrack(pfc,bestTrackType);
01082
01083 pfCleanedTrackerAndGlobalMuonCandidates_->push_back(pfc);
01084
01085 METX_ = METNOX+pfc.px();
01086 METY_ = METNOY+pfc.py();
01087 sumet_=SUMETNO+pfc.pt();
01088
01089 }
01090 }
01091
01092
01093 if (!(pfc.muonRef()->isGlobalMuon() && pfc.muonRef()->isTrackerMuon())) {
01094
01095 double MET2 = METX_*METX_+METY_*METY_;
01096 double newMET2 = METNOX*METNOX+METNOY*METNOY;
01097 double METSig = sqrt(MET2)/sqrt(sumet_-sumetPU_);
01098 if( METSig>metSigForRejection_)
01099 if((newMET2 < MET2/metFactorRejection_) &&
01100 ((SUMETNO-sumetPU_)/(sumet_-sumetPU_)<eventFractionRejection_)) {
01101 pfFakeMuonCleanedCandidates_->push_back(pfc);
01102 maskedIndices_.push_back(i);
01103 METX_ = METNOX;
01104 METY_ = METNOY;
01105 sumet_=SUMETNO;
01106 cleaned=true;
01107 }
01108
01109 }
01110 return cleaned;
01111
01112 }
01113
01114 std::vector<reco::Muon::MuonTrackTypePair>
01115 PFMuonAlgo::tracksWithBetterMET(const std::vector<reco::Muon::MuonTrackTypePair>& tracks ,const reco::PFCandidate& pfc) {
01116 std::vector<reco::Muon::MuonTrackTypePair> outputTracks;
01117
01118 double METNOX = METX_ - pfc.px();
01119 double METNOY = METY_ - pfc.py();
01120 double SUMETNO = sumet_ -pfc.pt();
01121 double MET2 = METX_*METX_+METY_*METY_;
01122 double newMET2=0.0;
01123 double newSUMET=0.0;
01124 double METSIG = sqrt(MET2)/sqrt(sumet_-sumetPU_);
01125
01126
01127 if(METSIG>metSigForCleaning_)
01128 for( unsigned int i=0;i<tracks.size();++i) {
01129
01130 newSUMET = SUMETNO+tracks.at(i).first->pt()-sumetPU_;
01131 newMET2 = pow(METNOX+tracks.at(i).first->px(),2)+pow(METNOY+tracks.at(i).first->py(),2);
01132
01133 if(newSUMET/(sumet_-sumetPU_)>eventFractionCleaning_ && newMET2<MET2/metFactorCleaning_)
01134 outputTracks.push_back(tracks.at(i));
01135 }
01136
01137
01138 return outputTracks;
01139 }
01140
01141
01142 std::vector<reco::Muon::MuonTrackTypePair>
01143 PFMuonAlgo::tracksPointingAtMET(const std::vector<reco::Muon::MuonTrackTypePair>& tracks) {
01144 std::vector<reco::Muon::MuonTrackTypePair> outputTracks;
01145
01146
01147 double newMET2=0.0;
01148
01149 for( unsigned int i=0;i<tracks.size();++i) {
01150
01151 newMET2 = pow(METX_+tracks.at(i).first->px(),2)+pow(METY_+tracks.at(i).first->py(),2);
01152
01153 if(newMET2<(METX_*METX_+METY_*METY_)/metFactorCleaning_)
01154 outputTracks.push_back(tracks.at(i));
01155 }
01156
01157
01158 return outputTracks;
01159 }
01160
01161
01162
01163 void PFMuonAlgo::setInputsForCleaning(const reco::VertexCollection* vertices) {
01164 vertices_ = vertices;
01165 }
01166
01167 bool PFMuonAlgo::cleanPunchThroughAndFakes(reco::PFCandidate&pfc,reco::PFCandidateCollection* cands,unsigned int imu ){
01168 using namespace reco;
01169
01170 bool cleaned=false;
01171
01172 if (pfc.pt()<minPostCleaningPt_)
01173 return false;
01174
01175
01176 double METXNO = METX_-pfc.pt();
01177 double METYNO = METY_-pfc.pt();
01178 double MET2NO = METXNO*METXNO+METYNO*METYNO;
01179 double MET2 = METX_*METX_+METY_*METY_;
01180 bool fake1=false;
01181
01182 std::pair<double,double> met2 = getMinMaxMET2(pfc);
01183
01184
01185 if(pfc.muonRef()->standAloneMuon().isNonnull())
01186 fake1 =fabs ( pfc.eta() ) > 2.15 &&
01187 met2.first<met2.second/2 &&
01188 MET2NO < MET2/metFactorHighEta_ &&
01189 pfc.muonRef()->standAloneMuon()->pt() < pfc.pt()/ptFactorHighEta_;
01190
01191 double factor = std::max(2.,2000./(sumet_-pfc.pt()-sumetPU_));
01192 bool fake2 = ( pfc.pt()/(sumet_-sumetPU_) < 0.25 && MET2NO < MET2/metFactorFake_ && met2.first<met2.second/factor );
01193
01194 bool punchthrough =pfc.p() > minPunchThroughMomentum_ &&
01195 pfc.rawHcalEnergy() > minPunchThroughEnergy_ &&
01196 pfc.rawEcalEnergy()+pfc.rawHcalEnergy() > pfc.p()/punchThroughFactor_ &&
01197 !isIsolatedMuon(pfc.muonRef()) && MET2NO < MET2/punchThroughMETFactor_;
01198
01199
01200 if(fake1 || fake2||punchthrough) {
01201
01202 const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
01203 if ( eleInBlocks.size() ) {
01204 PFBlockRef blockRefMuon = eleInBlocks[0].first;
01205 unsigned indexMuon = eleInBlocks[0].second;
01206 for ( unsigned iele = 1; iele < eleInBlocks.size(); ++iele ) {
01207 indexMuon = eleInBlocks[iele].second;
01208 break;
01209 }
01210
01211
01212 double iHad = 1E9;
01213 bool hadron = false;
01214 for ( unsigned i = imu+1; i < cands->size(); ++i ) {
01215 const PFCandidate& pfcn = cands->at(i);
01216 const PFCandidate::ElementsInBlocks& ele = pfcn.elementsInBlocks();
01217 if ( !ele.size() ) {
01218 continue;
01219 }
01220 PFBlockRef blockRefHadron = ele[0].first;
01221 unsigned indexHadron = ele[0].second;
01222
01223 if ( blockRefHadron.key() != blockRefMuon.key() ) break;
01224
01225 if ( indexHadron == indexMuon &&
01226 pfcn.particleId() == reco::PFCandidate::h0 ) {
01227 iHad = i;
01228 hadron = true;
01229 }
01230 if ( hadron ) break;
01231 }
01232
01233 if ( hadron ) {
01234
01235 double rescaleFactor = cands->at(iHad).p()/cands->at(imu).p();
01236 METX_ -= cands->at(imu).px() + cands->at(iHad).px();
01237 METY_ -= cands->at(imu).py() + cands->at(iHad).py();
01238 sumet_ -=cands->at(imu).pt();
01239 cands->at(imu).rescaleMomentum(rescaleFactor);
01240 maskedIndices_.push_back(iHad);
01241 pfPunchThroughHadronCleanedCandidates_->push_back(cands->at(iHad));
01242 cands->at(imu).setParticleType(reco::PFCandidate::h);
01243 pfPunchThroughMuonCleanedCandidates_->push_back(cands->at(imu));
01244 METX_ += cands->at(imu).px();
01245 METY_ += cands->at(imu).py();
01246 sumet_ += cands->at(imu).pt();
01247
01248 } else if ( fake1 || fake2 ) {
01249 METX_ -= cands->at(imu).px();
01250 METY_ -= cands->at(imu).py();
01251 sumet_ -= cands->at(imu).pt();
01252 maskedIndices_.push_back(imu);
01253 pfFakeMuonCleanedCandidates_->push_back(cands->at(imu));
01254 cleaned=true;
01255 }
01256 }
01257 }
01258 return cleaned;
01259 }
01260
01261
01262 void PFMuonAlgo::removeDeadCandidates(reco::PFCandidateCollection* obj, const std::vector<unsigned int>& indices)
01263 {
01264 size_t N = indices.size();
01265 size_t collSize = obj->size();
01266
01267 for (size_t i = 0 ; i < N ; ++i)
01268 obj->at(indices.at(i)) = obj->at(collSize-i-1);
01269
01270 obj->resize(collSize - indices.size());
01271 }