CMS 3D CMS Logo

MuonCocktails.cc
Go to the documentation of this file.
1 #include "TMath.h"
4 
5 //
6 // Return the TeV-optimized refit track (aka the cocktail or Tune P) or
7 // the tracker track if either the optimized pT or tracker pT is below the pT threshold
8 //
10  const reco::TrackRef& trackerTrack,
11  const reco::TrackRef& tpfmsTrack,
12  const reco::TrackRef& pickyTrack,
13  const reco::TrackRef& dytTrack,
14  const double ptThreshold,
15  const double tune1,
16  const double tune2,
17  double dptcut) {
18  const unsigned int nAlgo = 5;
19 
20  // Array for convenience below.
21  const reco::Muon::MuonTrackTypePair refit[nAlgo] = {make_pair(trackerTrack, reco::Muon::InnerTrack),
22  make_pair(combinedTrack, reco::Muon::CombinedTrack),
23  make_pair(tpfmsTrack, reco::Muon::TPFMS),
24  make_pair(pickyTrack, reco::Muon::Picky),
25  make_pair(dytTrack, reco::Muon::DYT)};
26 
27  // Calculate the log(tail probabilities). If there's a problem,
28  // signify this with prob == 0. The current problems recognized are:
29  // the track being not available, whether the (re)fit failed or it's
30  // just not in the event, or if the (re)fit ended up with no valid
31  // hits.
32  double prob[nAlgo] = {0., 0., 0., 0., 0.};
33  bool valid[nAlgo] = {false, false, false, false, false};
34 
35  double dptmin = 1.;
36 
37  if (dptcut > 0) {
38  for (unsigned int i = 0; i < nAlgo; ++i)
39  if (refit[i].first.isNonnull())
40  if (refit[i].first->ptError() / refit[i].first->pt() < dptmin)
41  dptmin = refit[i].first->ptError() / refit[i].first->pt();
42 
43  if (dptmin > dptcut)
44  dptcut = dptmin + 0.15;
45  }
46 
47  for (unsigned int i = 0; i < nAlgo; ++i)
48  if (refit[i].first.isNonnull()) {
49  valid[i] = true;
50  if (refit[i].first->numberOfValidHits() &&
51  (refit[i].first->ptError() / refit[i].first->pt() < dptcut || dptcut < 0))
52  prob[i] = muon::trackProbability(refit[i].first);
53  }
54 
55  // Start with picky.
56  int chosen = 3;
57 
58  // If there's a problem with picky, make the default one of the
59  // other tracks. Try TPFMS first, then global, then tracker-only.
60  if (prob[3] == 0.) {
61  // split so that passing dptcut<0 recreates EXACTLY the old tuneP behavior
62  if (dptcut > 0) {
63  if (prob[4] > 0.)
64  chosen = 4;
65  else if (prob[0] > 0.)
66  chosen = 0;
67  else if (prob[2] > 0.)
68  chosen = 2;
69  else if (prob[1] > 0.)
70  chosen = 1;
71  } else {
72  if (prob[2] > 0.)
73  chosen = 2;
74  else if (prob[1] > 0.)
75  chosen = 1;
76  else if (prob[0] > 0.)
77  chosen = 0;
78  }
79  }
80 
81  // Now the algorithm: switch from picky to dyt if the difference is lower than a tuned value. Then
82  // switch from picky to tracker-only if the
83  // difference, log(tail prob(picky)) - log(tail prob(tracker-only))
84  // is greater than a tuned value. Then compare the
85  // so-picked track to TPFMS in the same manner using another tuned
86  // value.
87  if (prob[4] > 0. && prob[3] > 0.) {
88  if (refit[3].first->pt() > 0 && refit[4].first->pt() > 0 &&
89  (refit[4].first->ptError() / refit[4].first->pt() - refit[3].first->ptError() / refit[3].first->pt()) <= 0)
90  chosen = 4; // dyt
91  }
92 
93  if (prob[0] > 0. && prob[chosen] > 0. && (prob[chosen] - prob[0]) > tune1)
94  chosen = 0;
95  if (prob[2] > 0. && (prob[chosen] - prob[2]) > tune2)
96  chosen = 2;
97 
98  // Sanity checks
99  if (chosen == 4 && !valid[4])
100  chosen = 3;
101  if (chosen == 3 && !valid[3])
102  chosen = 2;
103  if (chosen == 2 && !valid[2])
104  chosen = 1;
105  if (chosen == 1 && !valid[1])
106  chosen = 0;
107 
108  // Done. If pT of the chosen track (or pT of the tracker track) is below the threshold value, return the tracker track.
109  if (valid[chosen] && refit[chosen].first->pt() < ptThreshold && prob[0] > 0.)
110  return make_pair(trackerTrack, reco::Muon::InnerTrack);
111  if (trackerTrack->pt() < ptThreshold && prob[0] > 0.)
112  return make_pair(trackerTrack, reco::Muon::InnerTrack);
113 
114  // Return the chosen track (which can be the global track in
115  // very rare cases).
116  return refit[chosen];
117 }
118 
119 //
120 // calculate the tail probability (-ln(P)) of a fit
121 //
123  int nDOF = (int)track->ndof();
124  if (nDOF > 0 && track->chi2() > 0) {
125  return -log(TMath::Prob(track->chi2(), nDOF));
126  } else {
127  return 0.0;
128  }
129 }
130 
132  reco::TrackToTrackMap::const_iterator it = map.find(combinedTrack);
133  return it == map.end() ? reco::TrackRef() : it->val;
134 }
135 
136 //
137 // Get the sigma-switch decision (tracker-only versus global).
138 //
140  const reco::TrackRef& trackerTrack,
141  const double nSigma,
142  const double ptThreshold) {
143  // If either the global or tracker-only fits have pT below threshold
144  // (default 200 GeV), return the tracker-only fit.
145  if (combinedTrack->pt() < ptThreshold || trackerTrack->pt() < ptThreshold)
146  return make_pair(trackerTrack, reco::Muon::InnerTrack);
147 
148  // If both are above the pT threshold, compare the difference in
149  // q/p: if less than two sigma of the tracker-only track, switch to
150  // global. Otherwise, use tracker-only.
151  const double delta = fabs(trackerTrack->qoverp() - combinedTrack->qoverp());
152  const double threshold = nSigma * trackerTrack->qoverpError();
153  return delta > threshold ? make_pair(trackerTrack, reco::Muon::InnerTrack)
154  : make_pair(combinedTrack, reco::Muon::CombinedTrack);
155 }
156 
157 //
158 // Get the TMR decision (tracker-only versus TPFMS).
159 //
161  const reco::TrackRef& fmsTrack,
162  const double tune) {
163  double probTK = 0;
164  double probFMS = 0;
165 
166  if (trackerTrack.isNonnull() && trackerTrack->numberOfValidHits())
167  probTK = muon::trackProbability(trackerTrack);
168  if (fmsTrack.isNonnull() && fmsTrack->numberOfValidHits())
169  probFMS = muon::trackProbability(fmsTrack);
170 
171  bool TKok = probTK > 0;
172  bool FMSok = probFMS > 0;
173 
174  if (TKok && FMSok) {
175  if (probFMS - probTK > tune)
176  return make_pair(trackerTrack, reco::Muon::InnerTrack);
177  else
178  return make_pair(fmsTrack, reco::Muon::TPFMS);
179  } else if (FMSok)
180  return make_pair(fmsTrack, reco::Muon::TPFMS);
181  else if (TKok)
182  return make_pair(trackerTrack, reco::Muon::InnerTrack);
183  else
184  return make_pair(reco::TrackRef(), reco::Muon::None);
185 }
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:232
reco::Muon::MuonTrackTypePair sigmaSwitch(const reco::TrackRef &combinedTrack, const reco::TrackRef &trackerTrack, const double nSigma=2., const double ptThreshold=200.)
reco::Muon::MuonTrackTypePair tevOptimized(const reco::TrackRef &combinedTrack, const reco::TrackRef &trackerTrack, const reco::TrackRef &tpfmsTrack, const reco::TrackRef &pickyTrack, const reco::TrackRef &dytTrack, const double ptThreshold=200., const double tune1=17., const double tune2=40., const double dptcut=0.25)
Definition: MuonCocktails.cc:9
reco::Muon::MuonTrackTypePair TMR(const reco::TrackRef &trackerTrack, const reco::TrackRef &fmsTrack, const double tune=4.)
edm::Ref< TrackCollection > TrackRef
persistent reference to a Track
Definition: TrackFwd.h:20
reco::TrackRef getTevRefitTrack(const reco::TrackRef &combinedTrack, const reco::TrackToTrackMap &map)
double trackProbability(const reco::TrackRef track)
std::pair< TrackRef, Muon::MuonTrackType > MuonTrackTypePair
Definition: Muon.h:38