CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/DataFormats/MuonReco/src/MuonCocktails.cc

Go to the documentation of this file.
00001 #include "TMath.h"
00002 #include "DataFormats/MuonReco/interface/MuonCocktails.h"
00003 #include "DataFormats/TrackReco/interface/Track.h"
00004 
00005 //
00006 // Return the TeV-optimized refit track (aka the cocktail or Tune P) or
00007 // the tracker track if either the optimized pT or tracker pT is below the pT threshold
00008 //
00009 reco::Muon::MuonTrackTypePair  muon::tevOptimized(const reco::TrackRef& combinedTrack,
00010                                                   const reco::TrackRef& trackerTrack,
00011                                                   const reco::TrackRef& tpfmsTrack,
00012                                                   const reco::TrackRef& pickyTrack,
00013                                                   const double ptThreshold,
00014                                                   const double tune1,
00015                                                   const double tune2,
00016                                                   double dptcut) {
00017 
00018   // Array for convenience below.
00019   const reco::Muon::MuonTrackTypePair refit[4] = { 
00020     make_pair(trackerTrack, reco::Muon::InnerTrack), 
00021     make_pair(combinedTrack,reco::Muon::CombinedTrack),
00022     make_pair(tpfmsTrack,   reco::Muon::TPFMS),
00023     make_pair(pickyTrack,   reco::Muon::Picky)
00024   }; 
00025   
00026   // Calculate the log(tail probabilities). If there's a problem,
00027   // signify this with prob == 0. The current problems recognized are:
00028   // the track being not available, whether the (re)fit failed or it's
00029   // just not in the event, or if the (re)fit ended up with no valid
00030   // hits.
00031   double prob[4] = {0.,0.,0.,0.};
00032   bool valid[4] = {0,0,0,0};
00033 
00034   double dptmin = 1.;
00035 
00036   if (dptcut>0) {  
00037     for (unsigned int i = 0; i < 4; ++i)
00038       if (refit[i].first.isNonnull())
00039         if (refit[i].first->ptError()/refit[i].first->pt()<dptmin) dptmin = refit[i].first->ptError()/refit[i].first->pt();
00040   
00041     if (dptmin>dptcut) dptcut = dptmin+0.15;
00042   }
00043 
00044   for (unsigned int i = 0; i < 4; ++i) 
00045     if (refit[i].first.isNonnull()){ 
00046       valid[i] = true;
00047       if (refit[i].first->numberOfValidHits() && (refit[i].first->ptError()/refit[i].first->pt()<dptcut || dptcut<0)) 
00048         prob[i] = muon::trackProbability(refit[i].first); 
00049     }
00050 
00051   
00052   // Start with picky.
00053   int chosen = 3;
00054   
00055   // If there's a problem with picky, make the default one of the
00056   // other tracks. Try TPFMS first, then global, then tracker-only.
00057   if (prob[3] == 0.) { 
00058 
00059     // split so that passing dptcut<0 recreates EXACTLY the old tuneP behavior
00060     if (dptcut>0) {
00061       if      (prob[0] > 0.) chosen = 0;
00062       else if (prob[2] > 0.) chosen = 2;
00063       else if (prob[1] > 0.) chosen = 1;
00064     } else {
00065       if      (prob[2] > 0.) chosen = 2;
00066       else if (prob[1] > 0.) chosen = 1;
00067       else if (prob[0] > 0.) chosen = 0;
00068     }
00069   } 
00070   
00071   // Now the algorithm: switch from picky to tracker-only if the
00072   // difference, log(tail prob(picky)) - log(tail prob(tracker-only))
00073   // is greater than a tuned value. Then compare the
00074   // so-picked track to TPFMS in the same manner using another tuned
00075   // value.
00076   if (prob[0] > 0. && prob[3] > 0. && (prob[3] - prob[0]) > tune1)
00077     chosen = 0;
00078   if (prob[2] > 0. && (prob[chosen] - prob[2]) > tune2)
00079     chosen = 2;
00080 
00081   // Sanity checks 
00082   if (chosen == 3 && !valid[3] ) chosen = 2;
00083   if (chosen == 2 && !valid[2] ) chosen = 1;
00084   if (chosen == 1 && !valid[1] ) chosen = 0; 
00085 
00086   // Done. If pT of the chosen track (or pT of the tracker track) is below the threshold value, return the tracker track.
00087   if (valid[chosen] && refit[chosen].first->pt() < ptThreshold && prob[0] > 0.) return make_pair(trackerTrack,reco::Muon::InnerTrack);    
00088   if (trackerTrack->pt() < ptThreshold && prob[0] > 0.) return make_pair(trackerTrack,reco::Muon::InnerTrack);  
00089   
00090   // Return the chosen track (which can be the global track in
00091   // very rare cases).
00092   return refit[chosen];
00093 }
00094 
00095 //
00096 // calculate the tail probability (-ln(P)) of a fit
00097 //
00098 double muon::trackProbability(const reco::TrackRef track) {
00099   
00100   int nDOF = (int)track->ndof();
00101   if ( nDOF > 0 && track->chi2()> 0) { 
00102     return -log(TMath::Prob(track->chi2(), nDOF));
00103   } else { 
00104     return 0.0;
00105   }
00106   
00107 }
00108 
00109 reco::TrackRef muon::getTevRefitTrack(const reco::TrackRef& combinedTrack,
00110                                                      const reco::TrackToTrackMap& map) {
00111   reco::TrackToTrackMap::const_iterator it = map.find(combinedTrack);
00112   return it == map.end() ? reco::TrackRef() : it->val;
00113 }
00114 
00115 
00116 //
00117 // Get the sigma-switch decision (tracker-only versus global).
00118 //
00119 reco::Muon::MuonTrackTypePair muon::sigmaSwitch(const reco::TrackRef& combinedTrack,
00120                                                 const reco::TrackRef& trackerTrack,
00121                                                 const double nSigma,
00122                                                 const double ptThreshold) {
00123   // If either the global or tracker-only fits have pT below threshold
00124   // (default 200 GeV), return the tracker-only fit.
00125   if (combinedTrack->pt() < ptThreshold || trackerTrack->pt() < ptThreshold)
00126     return make_pair(trackerTrack,reco::Muon::InnerTrack);
00127   
00128   // If both are above the pT threshold, compare the difference in
00129   // q/p: if less than two sigma of the tracker-only track, switch to
00130   // global. Otherwise, use tracker-only.
00131   const double delta = fabs(trackerTrack->qoverp() - combinedTrack->qoverp());
00132   const double threshold = nSigma * trackerTrack->qoverpError();
00133   return delta > threshold ? make_pair(trackerTrack,reco::Muon::InnerTrack) :  make_pair(combinedTrack,reco::Muon::CombinedTrack);
00134 }
00135 
00136 //
00137 // Get the TMR decision (tracker-only versus TPFMS).
00138 //
00139 reco::Muon::MuonTrackTypePair muon::TMR(const reco::TrackRef& trackerTrack,
00140                                         const reco::TrackRef& fmsTrack,
00141                                         const double tune) {
00142   double probTK  = 0;
00143   double probFMS = 0;
00144   
00145   if (trackerTrack.isNonnull() && trackerTrack->numberOfValidHits())  
00146     probTK = muon::trackProbability(trackerTrack);
00147   if (fmsTrack.isNonnull() && fmsTrack->numberOfValidHits())
00148     probFMS = muon::trackProbability(fmsTrack);
00149   
00150   bool TKok  = probTK > 0;
00151   bool FMSok = probFMS > 0;
00152   
00153   if (TKok && FMSok) {
00154     if (probFMS - probTK > tune)
00155       return make_pair(trackerTrack,reco::Muon::InnerTrack);
00156     else
00157       return  make_pair(fmsTrack,reco::Muon::TPFMS);
00158   }
00159   else if (FMSok)
00160     return  make_pair(fmsTrack,reco::Muon::TPFMS);
00161   else if (TKok)
00162     return make_pair(trackerTrack,reco::Muon::InnerTrack);
00163   else
00164     return make_pair(reco::TrackRef(),reco::Muon::None); 
00165 }