CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoParticleFlow/PFProducer/src/PFMuonAlgo.cc

Go to the documentation of this file.
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; //Disable by default (for HLT)
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     // No tracker muon -> Request a perfect stand-alone muon, or an even better global muon
00273     bool result = false;
00274       
00275     // Check the quality of the stand-alone muon : 
00276     // good chi**2 and large number of hits and good pt error
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       // If the stand-alone muon is good, check the global muon
00288       if ( combinedMu->normalizedChi2() > standAloneMu->normalizedChi2() ) {
00289         // If the combined muon is worse than the stand-alone, it 
00290         // means that either the corresponding tracker track was not 
00291         // reconstructed, or that the sta muon comes from a late 
00292         // pion decay (hence with a momentum smaller than the track)
00293         // Take the stand-alone muon only if its momentum is larger
00294         // than that of the track
00295         result = standAloneMu->pt() > trackerMu->pt() ;
00296      } else { 
00297         // If the combined muon is better (and good enough), take the 
00298         // global muon
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     //std::cout<<" PT ERROR > 10 % "<< trackerMu->pt() <<std::endl;
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     // Check the quality of the stand-alone muon : 
00374     // good chi**2 and large number of hits and good pt error
00375     if (  nMuonHits <=15  ||
00376           standAloneMu->normalizedChi2() > 10. || 
00377           standAloneMu->ptError()/standAloneMu->pt() > 0.20 ) {
00378       quality = false;
00379     }
00380    else { 
00381       // If the stand-alone muon is good, check the global muon
00382       if ( combinedMu->normalizedChi2() > standAloneMu->normalizedChi2() ) {
00383         // If the combined muon is worse than the stand-alone, it 
00384         // means that either the corresponding tracker track was not 
00385         // reconstructed, or that the sta muon comes from a late 
00386         // pion decay (hence with a momentum smaller than the track)
00387         // Take the stand-alone muon only if its momentum is larger
00388         // than that of the track
00389 
00390         // Note that here we even take the standAlone if it has a smaller pT, in contrast to GlobalTight
00391         if(standAloneMu->pt() > trackerMu->pt() || combinedMu->normalizedChi2()<5.) quality =  true;
00392       }
00393       else { 
00394         // If the combined muon is better (and good enough), take the 
00395         // global muon
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   // this doesn't seem to be necessary on the small samples looked at, but keep it around as insurance
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   // Isolated Muons which are missed by standard cuts are nearly always global+tracker
00439   if ( !muonRef->isGlobalMuon() ) return false;
00440 
00441   // If it's not a tracker muon, only take it if there are valid muon hits
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   // for isolation, take the smallest pt available to reject fakes
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   //const reco::TrackRef& combinedMuon = muonRef->combinedMuon();    
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     //if ( ratio > 2. && delta < 3. ) std::cout << "ALARM ! " << ratio << ", " << delta << std::endl;
00611     std::cout<<" ratio "<<ratio<<" combined mu pt "<<combinedMu->pt()<<std::endl;
00612     //bool quality3 =  ( combinedMu->pt() < 50. || ratio < 2. ) && delta <  3.;
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)//Here Loose!@
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   //Magic: TPFMS is not a really good track especially under misalignment
00662   //IT is kind of crap because if mu system is displaced it can make a change
00663   //So allow TPFMS if there is no picky or the error of tpfms is better than picky
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     //get the valid tracks(without standalone except we allow loose muons)
00705     //MIKE: Here we need to be careful. If we have a muon inside a dense 
00706     //jet environment often the track is badly measured. In this case 
00707     //we should not apply Dpt/Pt<1
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     //check what is the track used.Rerun TuneP
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     //OK Now redefine the canddiate with that track
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     //    candidate.setTrackRef( bestTrack );  
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   //SUM ET from PU
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   //SUM ET and MET
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       //If charged and from PV or muon
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       //If charged and not from PV(assume there is a neutral balancing it)
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       //Neutral
00828       else if( !(i->charge() !=0 && i->trackRef().isNonnull())) {
00829         METXNeut+=i->px();
00830         METYNeut+=i->py();
00831       }
00832     } //else if we dont have a vertex make standard PFMET
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   //Initialize vectors
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   //Estimate MET and SumET
00887 
00888   estimateEventQuantities(cands);
00889 
00890   
00891   std::vector<int> muons;
00892   std::vector<int> cosmics;
00893   //get the muons
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   //Then sort the muon indicess by decsending pt
00899 
00900   IndexPtComparator comparator(cands);
00901   std::sort(muons.begin(),muons.end(),comparator);
00902 
00903 
00904   //first kill cosmics
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   //Loop on the muons candidates and clean
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   //OK Now do the hard job ->remove the candidates that were cleaned 
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         // Check if the stand-alone muon is not a spurious copy of an existing muon 
00975         // (Protection needed for HLT)
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     //Low pt dont need to be cleaned
00994   
00995     std::vector<reco::Muon::MuonTrackTypePair> tracks  = goodMuonTracks(muonRef,true);
00996     //If there is at least 1 track choice  try to change the track 
00997     if(tracks.size()>0) {
00998 
00999     //Find tracks that change dramatically MET or Pt
01000     std::vector<reco::Muon::MuonTrackTypePair> tracksThatChangeMET = tracksPointingAtMET(tracks);
01001     //From those tracks get the one with smallest MET 
01002     if (tracksThatChangeMET.size()>0) {
01003       reco::Muon::MuonTrackTypePair bestTrackType = *std::min_element(tracksThatChangeMET.begin(),tracksThatChangeMET.end(),comparator);
01004 
01005       //Make sure it is not cosmic
01006       if((vertices_->size()==0) ||bestTrackType.first->dz(vertices_->at(0).position())<cosmicRejDistance_){
01007         
01008         //make a pfcandidate
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   //PROTECT for cases of only one track. If there is only one track it will crash .
01047   //Has never happened but could likely happen!
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   //First define the MET without this guy
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   //Low pt dont need to be cleaned
01068   if (pfc.pt()<minPostCleaningPt_)
01069     return false;
01070   std::vector<reco::Muon::MuonTrackTypePair> tracks  = goodMuonTracks(pfc.muonRef(),false);
01071   
01072 
01073 
01074   //If there is more than 1 track choice  try to change the track 
01075   if(tracks.size()>1) {
01076     //Find tracks that change dramatically MET or Pt
01077     std::vector<reco::Muon::MuonTrackTypePair> tracksThatChangeMET = tracksWithBetterMET(tracks,pfc);
01078     //From those tracks get the one with smallest MET 
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       //update eventquantities
01085       METX_ = METNOX+pfc.px();
01086       METY_ = METNOY+pfc.py();
01087       sumet_=SUMETNO+pfc.pt();
01088 
01089     }      
01090   }
01091 
01092   //Now attempt to kill it 
01093   if (!(pfc.muonRef()->isGlobalMuon() && pfc.muonRef()->isTrackerMuon())) {
01094     //define MET significance and SUM ET
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     //calculate new SUM ET and MET2
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     //calculate new SUM ET and MET2
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   //Check for Fakes at high pseudorapidity
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     // Find the block of the muon
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       // Check if the muon gave rise to a neutral hadron
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             // We are out of the block -> exit the loop
01223             if ( blockRefHadron.key() != blockRefMuon.key() ) break;
01224             // Check that this particle is a neutral hadron
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 }