CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MuonSelectors.cc
Go to the documentation of this file.
5 
6 namespace muon {
8 {
9  static SelectionTypeStringToEnum selectionTypeStringToEnumMap[] = {
10  { "All", All },
11  { "AllGlobalMuons", AllGlobalMuons },
12  { "AllStandAloneMuons", AllStandAloneMuons },
13  { "AllTrackerMuons", AllTrackerMuons },
14  { "TrackerMuonArbitrated", TrackerMuonArbitrated },
15  { "AllArbitrated", AllArbitrated },
16  { "GlobalMuonPromptTight", GlobalMuonPromptTight },
17  { "TMLastStationLoose", TMLastStationLoose },
18  { "TMLastStationTight", TMLastStationTight },
19  { "TM2DCompatibilityLoose", TM2DCompatibilityLoose },
20  { "TM2DCompatibilityTight", TM2DCompatibilityTight },
21  { "TMOneStationLoose", TMOneStationLoose },
22  { "TMOneStationTight", TMOneStationTight },
23  { "TMLastStationOptimizedLowPtLoose", TMLastStationOptimizedLowPtLoose },
24  { "TMLastStationOptimizedLowPtTight", TMLastStationOptimizedLowPtTight },
25  { "GMTkChiCompatibility", GMTkChiCompatibility },
26  { "GMStaChiCompatibility", GMStaChiCompatibility},
27  { "GMTkKinkTight", GMTkKinkTight},
28  { "TMLastStationAngLoose", TMLastStationAngLoose },
29  { "TMLastStationAngTight", TMLastStationAngTight },
30  { "TMOneStationAngLoose", TMOneStationAngLoose },
31  { "TMOneStationAngTight", TMOneStationAngTight },
32  { "TMLastStationOptimizedBarrelLowPtLoose", TMLastStationOptimizedBarrelLowPtLoose },
33  { "TMLastStationOptimizedBarrelLowPtTight", TMLastStationOptimizedBarrelLowPtTight },
34  { 0, (SelectionType)-1 }
35  };
36 
38  bool found = false;
39  for(int i = 0; selectionTypeStringToEnumMap[i].label && (! found); ++i)
40  if (! strcmp(label.c_str(), selectionTypeStringToEnumMap[i].label)) {
41  found = true;
42  value = selectionTypeStringToEnumMap[i].value;
43  }
44 
45  // in case of unrecognized selection type
46  if (! found) throw cms::Exception("MuonSelectorError") << label << " is not a recognized SelectionType";
47  return value;
48 }
49 }
50 
52  double maxChamberDist,
53  double maxChamberDistPull,
54  reco::Muon::ArbitrationType arbitrationType )
55 {
56  unsigned int theMask = 0;
57 
58  for(int stationIdx = 1; stationIdx < 5; ++stationIdx)
59  for(int detectorIdx = 1; detectorIdx < 3; ++detectorIdx)
60  if(muon.trackDist(stationIdx,detectorIdx,arbitrationType) < maxChamberDist &&
61  muon.trackDist(stationIdx,detectorIdx,arbitrationType)/muon.trackDistErr(stationIdx,detectorIdx,arbitrationType) < maxChamberDistPull)
62  theMask += 1<<((stationIdx-1)+4*(detectorIdx-1));
63 
64  return theMask;
65 }
66 
67 // ------------ method to calculate the calo compatibility for a track with matched muon info ------------
69  return muon.caloCompatibility();
70 }
71 
72 // ------------ method to calculate the segment compatibility for a track with matched muon info ------------
74  bool use_weight_regain_at_chamber_boundary = true;
75  bool use_match_dist_penalty = true;
76 
77  int nr_of_stations_crossed = 0;
78  int nr_of_stations_with_segment = 0;
79  std::vector<int> stations_w_track(8);
80  std::vector<int> station_has_segmentmatch(8);
81  std::vector<int> station_was_crossed(8);
82  std::vector<float> stations_w_track_at_boundary(8);
83  std::vector<float> station_weight(8);
84  int position_in_stations = 0;
85  float full_weight = 0.;
86 
87  for(int i = 1; i<=8; ++i) {
88  // ********************************************************;
89  // *** fill local info for this muon (do some counting) ***;
90  // ************** begin ***********************************;
91  if(i<=4) { // this is the section for the DTs
92  if( muon.trackDist(i,1,arbitrationType) < 999999 ) { //current "raw" info that a track is close to a chamber
93  ++nr_of_stations_crossed;
94  station_was_crossed[i-1] = 1;
95  if(muon.trackDist(i,1,arbitrationType) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i,1,arbitrationType);
96  else stations_w_track_at_boundary[i-1] = 0.;
97  }
98  if( muon.segmentX(i,1,arbitrationType) < 999999 ) { //current "raw" info that a segment is matched to the current track
99  ++nr_of_stations_with_segment;
100  station_has_segmentmatch[i-1] = 1;
101  }
102  }
103  else { // this is the section for the CSCs
104  if( muon.trackDist(i-4,2,arbitrationType) < 999999 ) { //current "raw" info that a track is close to a chamber
105  ++nr_of_stations_crossed;
106  station_was_crossed[i-1] = 1;
107  if(muon.trackDist(i-4,2,arbitrationType) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i-4,2,arbitrationType);
108  else stations_w_track_at_boundary[i-1] = 0.;
109  }
110  if( muon.segmentX(i-4,2,arbitrationType) < 999999 ) { //current "raw" info that a segment is matched to the current track
111  ++nr_of_stations_with_segment;
112  station_has_segmentmatch[i-1] = 1;
113  }
114  }
115  // rough estimation of chamber border efficiency (should be parametrized better, this is just a quick guess):
116  // TF1 * merf = new TF1("merf","-0.5*(TMath::Erf(x/6.)-1)",-100,100);
117  // use above value to "unpunish" missing segment if close to border, i.e. rather than not adding any weight, add
118  // the one from the function. Only for dist ~> -10 cm, else full punish!.
119 
120  // ********************************************************;
121  // *** fill local info for this muon (do some counting) ***;
122  // ************** end *************************************;
123  }
124 
125  // ********************************************************;
126  // *** calculate weights for each station *****************;
127  // ************** begin ***********************************;
128  // const float slope = 0.5;
129  // const float attenuate_weight_regain = 1.;
130  // if attenuate_weight_regain < 1., additional punishment if track is close to boundary and no segment
131  const float attenuate_weight_regain = 0.5;
132 
133  for(int i = 1; i<=8; ++i) { // loop over all possible stations
134 
135  // first set all weights if a station has been crossed
136  // later penalize if a station did not have a matching segment
137 
138  //old logic if(station_has_segmentmatch[i-1] > 0 ) { // the track has an associated segment at the current station
139  if( station_was_crossed[i-1] > 0 ) { // the track crossed this chamber (or was nearby)
140  // - Apply a weight depending on the "depth" of the muon passage.
141  // - The station_weight is later reduced for stations with badly matched segments.
142  // - Even if there is no segment but the track passes close to a chamber boundary, the
143  // weight is set non zero and can go up to 0.5 of the full weight if the track is quite
144  // far from any station.
145  ++position_in_stations;
146 
147  switch ( nr_of_stations_crossed ) { // define different weights depending on how many stations were crossed
148  case 1 :
149  station_weight[i-1] = 1.;
150  break;
151  case 2 :
152  if ( position_in_stations == 1 ) station_weight[i-1] = 0.33;
153  else station_weight[i-1] = 0.67;
154  break;
155  case 3 :
156  if ( position_in_stations == 1 ) station_weight[i-1] = 0.23;
157  else if( position_in_stations == 2 ) station_weight[i-1] = 0.33;
158  else station_weight[i-1] = 0.44;
159  break;
160  case 4 :
161  if ( position_in_stations == 1 ) station_weight[i-1] = 0.10;
162  else if( position_in_stations == 2 ) station_weight[i-1] = 0.20;
163  else if( position_in_stations == 3 ) station_weight[i-1] = 0.30;
164  else station_weight[i-1] = 0.40;
165  break;
166 
167  default :
168 // LogTrace("MuonIdentification")<<" // Message: A muon candidate track has more than 4 stations with matching segments.";
169 // LogTrace("MuonIdentification")<<" // Did not expect this - please let me know: ibloch@fnal.gov";
170  // for all other cases
171  station_weight[i-1] = 1./nr_of_stations_crossed;
172  }
173 
174  if( use_weight_regain_at_chamber_boundary ) { // reconstitute some weight if there is no match but the segment is close to a boundary:
175  if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] != 0. ) {
176  // if segment is not present but track in inefficient region, do not count as "missing match" but add some reduced weight.
177  // original "match weight" is currently reduced by at least attenuate_weight_regain, variing with an error function down to 0 if the track is
178  // inside the chamber.
179  station_weight[i-1] = station_weight[i-1]*attenuate_weight_regain*0.5*(TMath::Erf(stations_w_track_at_boundary[i-1]/6.)+1.); // remark: the additional scale of 0.5 normalizes Err to run from 0 to 1 in y
180  }
181  else if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] == 0.) { // no segment match and track well inside chamber
182  // full penalization
183  station_weight[i-1] = 0.;
184  }
185  }
186  else { // always fully penalize tracks with no matching segment, whether the segment is close to the boundary or not.
187  if(station_has_segmentmatch[i-1] <= 0) station_weight[i-1] = 0.;
188  }
189 
190  if( station_has_segmentmatch[i-1] > 0 && 42 == 42 ) { // if track has matching segment, but the matching is not high quality, penalize
191  if(i<=4) { // we are in the DTs
192  if( muon.dY(i,1,arbitrationType) < 999999 && muon.dX(i,1,arbitrationType) < 999999) { // have both X and Y match
193  if(
194  TMath::Sqrt(TMath::Power(muon.pullX(i,1,arbitrationType),2.)+TMath::Power(muon.pullY(i,1,arbitrationType),2.))> 1. ) {
195  // reduce weight
196  if(use_match_dist_penalty) {
197  // only use pull if 3 sigma is not smaller than 3 cm
198  if(TMath::Sqrt(TMath::Power(muon.dX(i,1,arbitrationType),2.)+TMath::Power(muon.dY(i,1,arbitrationType),2.)) < 3. && TMath::Sqrt(TMath::Power(muon.pullX(i,1,arbitrationType),2.)+TMath::Power(muon.pullY(i,1,arbitrationType),2.)) > 3. ) {
199  station_weight[i-1] *= 1./TMath::Power(
200  TMath::Max((double)TMath::Sqrt(TMath::Power(muon.dX(i,1,arbitrationType),2.)+TMath::Power(muon.dY(i,1,arbitrationType),2.)),(double)1.),.25);
201  }
202  else {
203  station_weight[i-1] *= 1./TMath::Power(
204  TMath::Sqrt(TMath::Power(muon.pullX(i,1,arbitrationType),2.)+TMath::Power(muon.pullY(i,1,arbitrationType),2.)),.25);
205  }
206  }
207  }
208  }
209  else if (muon.dY(i,1,arbitrationType) >= 999999) { // has no match in Y
210  if( muon.pullX(i,1,arbitrationType) > 1. ) { // has a match in X. Pull larger that 1 to avoid increasing the weight (just penalize, don't anti-penalize)
211  // reduce weight
212  if(use_match_dist_penalty) {
213  // only use pull if 3 sigma is not smaller than 3 cm
214  if( muon.dX(i,1,arbitrationType) < 3. && muon.pullX(i,1,arbitrationType) > 3. ) {
215  station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dX(i,1,arbitrationType),(double)1.),.25);
216  }
217  else {
218  station_weight[i-1] *= 1./TMath::Power(muon.pullX(i,1,arbitrationType),.25);
219  }
220  }
221  }
222  }
223  else { // has no match in X
224  if( muon.pullY(i,1,arbitrationType) > 1. ) { // has a match in Y. Pull larger that 1 to avoid increasing the weight (just penalize, don't anti-penalize)
225  // reduce weight
226  if(use_match_dist_penalty) {
227  // only use pull if 3 sigma is not smaller than 3 cm
228  if( muon.dY(i,1,arbitrationType) < 3. && muon.pullY(i,1,arbitrationType) > 3. ) {
229  station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dY(i,1,arbitrationType),(double)1.),.25);
230  }
231  else {
232  station_weight[i-1] *= 1./TMath::Power(muon.pullY(i,1,arbitrationType),.25);
233  }
234  }
235  }
236  }
237  }
238  else { // We are in the CSCs
239  if(
240  TMath::Sqrt(TMath::Power(muon.pullX(i-4,2,arbitrationType),2.)+TMath::Power(muon.pullY(i-4,2,arbitrationType),2.)) > 1. ) {
241  // reduce weight
242  if(use_match_dist_penalty) {
243  // only use pull if 3 sigma is not smaller than 3 cm
244  if(TMath::Sqrt(TMath::Power(muon.dX(i-4,2,arbitrationType),2.)+TMath::Power(muon.dY(i-4,2,arbitrationType),2.)) < 3. && TMath::Sqrt(TMath::Power(muon.pullX(i-4,2,arbitrationType),2.)+TMath::Power(muon.pullY(i-4,2,arbitrationType),2.)) > 3. ) {
245  station_weight[i-1] *= 1./TMath::Power(
246  TMath::Max((double)TMath::Sqrt(TMath::Power(muon.dX(i-4,2,arbitrationType),2.)+TMath::Power(muon.dY(i-4,2,arbitrationType),2.)),(double)1.),.25);
247  }
248  else {
249  station_weight[i-1] *= 1./TMath::Power(
250  TMath::Sqrt(TMath::Power(muon.pullX(i-4,2,arbitrationType),2.)+TMath::Power(muon.pullY(i-4,2,arbitrationType),2.)),.25);
251  }
252  }
253  }
254  }
255  }
256 
257  // Thoughts:
258  // - should penalize if the segment has only x OR y info
259  // - should also use the segment direction, as it now works!
260 
261  }
262  else { // track did not pass a chamber in this station - just reset weight
263  station_weight[i-1] = 0.;
264  }
265 
266  //increment final weight for muon:
267  full_weight += station_weight[i-1];
268  }
269 
270  // if we don't expect any matches, we set the compatibility to
271  // 0.5 as the track is as compatible with a muon as it is with
272  // background - we should maybe rather set it to -0.5!
273  if( nr_of_stations_crossed == 0 ) {
274  // full_weight = attenuate_weight_regain*0.5;
275  full_weight = 0.5;
276  }
277 
278  // ********************************************************;
279  // *** calculate weights for each station *****************;
280  // ************** end *************************************;
281 
282  return full_weight;
283 
284 }
285 
288  double minCompatibility,
289  reco::Muon::ArbitrationType arbitrationType ) {
290  if (!muon.isMatchesValid()) return false;
291  bool goodMuon = false;
292 
293  switch( type ) {
294  case TM2DCompatibility:
295  // Simplistic first cut in the 2D segment- vs calo-compatibility plane. Will have to be refined!
296  if( ( (0.8*caloCompatibility( muon ))+(1.2*segmentCompatibility( muon, arbitrationType )) ) > minCompatibility ) goodMuon = true;
297  else goodMuon = false;
298  return goodMuon;
299  break;
300  default :
301  // LogTrace("MuonIdentification")<<" // Invalid Algorithm Type called!";
302  goodMuon = false;
303  return goodMuon;
304  break;
305  }
306 }
307 
310  int minNumberOfMatches,
311  double maxAbsDx,
312  double maxAbsPullX,
313  double maxAbsDy,
314  double maxAbsPullY,
315  double maxChamberDist,
316  double maxChamberDistPull,
317  reco::Muon::ArbitrationType arbitrationType,
318  bool syncMinNMatchesNRequiredStationsInBarrelOnly,
319  bool applyAlsoAngularCuts)
320 {
321  if (!muon.isMatchesValid()) return false;
322  bool goodMuon = false;
323 
324  if (type == TMLastStation) {
325  // To satisfy my own paranoia, if the user specifies that the
326  // minimum number of matches is zero, then return true.
327  if(minNumberOfMatches == 0) return true;
328 
329  unsigned int theStationMask = muon.stationMask(arbitrationType);
330  unsigned int theRequiredStationMask = RequiredStationMask(muon, maxChamberDist, maxChamberDistPull, arbitrationType);
331 
332  // Require that there be at least a minimum number of segments
333  int numSegs = 0;
334  int numRequiredStations = 0;
335  for(int it = 0; it < 8; ++it) {
336  if(theStationMask & 1<<it) ++numSegs;
337  if(theRequiredStationMask & 1<<it) ++numRequiredStations;
338  }
339 
340  // Make sure the minimum number of matches is not greater than
341  // the number of required stations but still greater than zero
342  if (syncMinNMatchesNRequiredStationsInBarrelOnly) {
343  // Note that we only do this in the barrel region!
344  if (fabs(muon.eta()) < 1.2) {
345  if(minNumberOfMatches > numRequiredStations)
346  minNumberOfMatches = numRequiredStations;
347  if(minNumberOfMatches < 1) //SK: this only happens for negative values
348  minNumberOfMatches = 1;
349  }
350  } else {
351  if(minNumberOfMatches > numRequiredStations)
352  minNumberOfMatches = numRequiredStations;
353  if(minNumberOfMatches < 1) //SK: this only happens for negative values
354  minNumberOfMatches = 1;
355  }
356 
357  if(numSegs >= minNumberOfMatches) goodMuon = 1;
358 
359  // Require that last required station have segment
360  // If there are zero required stations keep track
361  // of the last station with a segment so that we may
362  // apply the quality cuts below to it instead
363  int lastSegBit = 0;
364  if(theRequiredStationMask) {
365  for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
366  if(theRequiredStationMask & 1<<stationIdx){
367  if(theStationMask & 1<<stationIdx) {
368  lastSegBit = stationIdx;
369  goodMuon &= 1;
370  break;
371  } else {
372  goodMuon = false;
373  break;
374  }
375  }
376  } else {
377  for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
378  if(theStationMask & 1<<stationIdx) {
379  lastSegBit = stationIdx;
380  break;
381  }
382  }
383 
384  if(!goodMuon) return false;
385 
386  // Impose pull cuts on last segment
387  int station = 0, detector = 0;
388  station = lastSegBit < 4 ? lastSegBit+1 : lastSegBit-3;
389  detector = lastSegBit < 4 ? 1 : 2;
390 
391  // Check x information
392  if(fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
393  fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx)
394  return false;
395 
396  if(applyAlsoAngularCuts && fabs(muon.pullDxDz(station,detector,arbitrationType,1)) > maxAbsPullX)
397  return false;
398 
399  // Is this a tight algorithm, i.e. do we bother to check y information?
400  if (maxAbsDy < 999999) { // really if maxAbsDy < 1E9 as currently defined
401 
402  // Check y information
403  if (detector == 2) { // CSC
404  if(fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
405  fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy)
406  return false;
407 
408  if(applyAlsoAngularCuts && fabs(muon.pullDyDz(station,2,arbitrationType,1)) > maxAbsPullY)
409  return false;
410  } else {
411  //
412  // In DT, if this is a "Tight" algorithm and the last segment is
413  // missing y information (always the case in station 4!!!), impose
414  // respective cuts on the next station in the stationMask that has
415  // a segment with y information. If there are no segments with y
416  // information then there is nothing to penalize. Should we
417  // penalize in Tight for having zero segments with y information?
418  // That is the fundamental question. Of course I am being uber
419  // paranoid; if this is a good muon then there will probably be at
420  // least one segment with y information but not always. Suppose
421  // somehow a muon only creates segments in station 4, then we
422  // definitely do not want to require that there be at least one
423  // segment with y information because we will lose it completely.
424  //
425 
426  for (int stationIdx = station; stationIdx > 0; --stationIdx) {
427  if(! (theStationMask & 1<<(stationIdx-1))) // don't bother if the station is not in the stationMask
428  continue;
429 
430  if(muon.dY(stationIdx,1,arbitrationType) > 999998) // no y-information
431  continue;
432 
433  if(fabs(muon.pullY(stationIdx,1,arbitrationType,1)) > maxAbsPullY &&
434  fabs(muon.dY(stationIdx,1,arbitrationType)) > maxAbsDy) {
435  return false;
436  }
437 
438  if(applyAlsoAngularCuts && fabs(muon.pullDyDz(stationIdx,1,arbitrationType,1)) > maxAbsPullY)
439  return false;
440 
441  // If we get this far then great this is a good muon
442  return true;
443  }
444  }
445  }
446 
447  return goodMuon;
448  } // TMLastStation
449 
450  // TMOneStation requires only that there be one "good" segment, regardless
451  // of the required stations. We do not penalize if there are absolutely zero
452  // segments with y information in the Tight algorithm. Maybe I'm being
453  // paranoid but so be it. If it's really a good muon then we will probably
454  // find at least one segment with both x and y information but you never
455  // know, and I don't want to deal with a potential inefficiency in the DT
456  // like we did with the original TMLastStation. Incidentally, not penalizing
457  // for total lack of y information in the Tight algorithm is what is done in
458  // the new TMLastStation
459  //
460  if (type == TMOneStation) {
461  unsigned int theStationMask = muon.stationMask(arbitrationType);
462 
463  // Of course there must be at least one segment
464  if (! theStationMask) return false;
465 
466  int station = 0, detector = 0;
467  // Keep track of whether or not there is a DT segment with y information.
468  // In the end, if it turns out there are absolutely zero DT segments with
469  // y information, require only that there was a segment with good x info.
470  // This of course only applies to the Tight algorithms.
471  bool existsGoodDTSegX = false;
472  bool existsDTSegY = false;
473 
474  // Impose cuts on the segments in the station mask until we find a good one
475  // Might as well start with the lowest bit to speed things up.
476  for(int stationIdx = 0; stationIdx <= 7; ++stationIdx)
477  if(theStationMask & 1<<stationIdx) {
478  station = stationIdx < 4 ? stationIdx+1 : stationIdx-3;
479  detector = stationIdx < 4 ? 1 : 2;
480 
481  if((fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
482  fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx) ||
483  (applyAlsoAngularCuts && fabs(muon.pullDxDz(station,detector,arbitrationType,1)) > maxAbsPullX))
484  continue;
485  else if (detector == 1)
486  existsGoodDTSegX = true;
487 
488  // Is this a tight algorithm? If yes, use y information
489  if (maxAbsDy < 999999) {
490  if (detector == 2) { // CSC
491  if((fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
492  fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy) ||
493  (applyAlsoAngularCuts && fabs(muon.pullDyDz(station,2,arbitrationType,1)) > maxAbsPullY))
494  continue;
495  } else {
496 
497  if(muon.dY(station,1,arbitrationType) > 999998) // no y-information
498  continue;
499  else
500  existsDTSegY = true;
501 
502  if((fabs(muon.pullY(station,1,arbitrationType,1)) > maxAbsPullY &&
503  fabs(muon.dY(station,1,arbitrationType)) > maxAbsDy) ||
504  (applyAlsoAngularCuts && fabs(muon.pullDyDz(station,1,arbitrationType,1)) > maxAbsPullY)) {
505  continue;
506  }
507  }
508  }
509 
510  // If we get this far then great this is a good muon
511  return true;
512  }
513 
514  // If we get this far then for sure there are no "good" CSC segments. For
515  // DT, check if there were any segments with y information. If there
516  // were none, but there was a segment with good x, then we're happy. If
517  // there WERE segments with y information, then they must have been shit
518  // since we are here so fail it. Of course, if this is a Loose algorithm
519  // then fail immediately since if we had good x we would already have
520  // returned true
521  if (maxAbsDy < 999999) {
522  if (existsDTSegY)
523  return false;
524  else if (existsGoodDTSegX)
525  return true;
526  } else
527  return false;
528  } // TMOneStation
529 
530  return goodMuon;
531 }
532 
534  reco::Muon::ArbitrationType arbitrationType)
535 {
536  switch (type)
537  {
538  case muon::All:
539  return true;
540  break;
542  return muon.isGlobalMuon();
543  break;
545  return muon.isTrackerMuon();
546  break;
548  return muon.isStandAloneMuon();
549  break;
551  return muon.isTrackerMuon() && muon.numberOfMatches(arbitrationType)>0;
552  break;
553  case muon::AllArbitrated:
554  return ! muon.isTrackerMuon() || muon.numberOfMatches(arbitrationType)>0;
555  break;
557  return muon.isGlobalMuon() && muon.globalTrack()->normalizedChi2()<10. && muon.globalTrack()->hitPattern().numberOfValidMuonHits() >0;
558  break;
559  // For "Loose" algorithms we choose maximum y quantity cuts of 1E9 instead of
560  // 9999 as before. We do this because the muon methods return 999999 (note
561  // there are six 9's) when the requested information is not available. For
562  // example, if a muon fails to traverse the z measuring superlayer in a station
563  // in the DT, then all methods involving segmentY in this station return
564  // 999999 to demonstrate that the information is missing. In order to not
565  // penalize muons for missing y information in Loose algorithms where we do
566  // not care at all about y information, we raise these limits. In the
567  // TMLastStation and TMOneStation algorithms we actually use this huge number
568  // to determine whether to consider y information at all.
570  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,true,false);
571  break;
573  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,true,false);
574  break;
576  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
577  break;
579  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
580  break;
582  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
583  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
584  else
585  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,false,false);
586  break;
588  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
589  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
590  else
591  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,false,false);
592  break;
593  //compatibility loose
595  return muon.isTrackerMuon() && isGoodMuon(muon,TM2DCompatibility,0.7,arbitrationType);
596  break;
597  //compatibility tight
599  return muon.isTrackerMuon() && isGoodMuon(muon,TM2DCompatibility,1.0,arbitrationType);
600  break;
602  return muon.isGlobalMuon() && muon.isQualityValid() && fabs(muon.combinedQuality().trkRelChi2 - muon.innerTrack()->normalizedChi2()) < 2.0;
603  break;
605  return muon.isGlobalMuon() && muon.isQualityValid() && fabs(muon.combinedQuality().staRelChi2 - muon.outerTrack()->normalizedChi2()) < 2.0;
606  break;
607  case muon::GMTkKinkTight:
608  return muon.isGlobalMuon() && muon.isQualityValid() && muon.combinedQuality().trkKink < 100.0;
609  break;
611  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,false,true);
612  break;
614  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,false,true);
615  break;
617  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,true);
618  break;
620  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,true);
621  break;
623  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
624  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
625  else
626  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,true,false);
627  break;
629  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
630  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
631  else
632  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,true,false);
633  break;
634  default:
635  return false;
636  }
637 }
638 
639 bool muon::overlap( const reco::Muon& muon1, const reco::Muon& muon2,
640  double pullX, double pullY, bool checkAdjacentChambers)
641 {
642  unsigned int nMatches1 = muon1.numberOfMatches(reco::Muon::SegmentAndTrackArbitration);
643  unsigned int nMatches2 = muon2.numberOfMatches(reco::Muon::SegmentAndTrackArbitration);
644  unsigned int betterMuon = ( muon1.pt() > muon2.pt() ? 1 : 2 );
645  for ( std::vector<reco::MuonChamberMatch>::const_iterator chamber1 = muon1.matches().begin();
646  chamber1 != muon1.matches().end(); ++chamber1 )
647  for ( std::vector<reco::MuonChamberMatch>::const_iterator chamber2 = muon2.matches().begin();
648  chamber2 != muon2.matches().end(); ++chamber2 )
649  {
650 
651  // if ( (chamber1->segmentMatches.empty() || chamber2->segmentMatches.empty()) ) continue;
652 
653  // handle case where both muons have information about the same chamber
654  // here we know how close they are
655  if ( chamber1->id == chamber2->id ){
656  // found the same chamber
657  if ( fabs(chamber1->x-chamber2->x) <
658  pullX * sqrt(chamber1->xErr*chamber1->xErr+chamber2->xErr*chamber2->xErr) )
659  {
660  if ( betterMuon == 1 )
661  nMatches2--;
662  else
663  nMatches1--;
664  if ( nMatches1==0 || nMatches2==0 ) return true;
665  continue;
666  }
667  if ( fabs(chamber1->y-chamber2->y) <
668  pullY * sqrt(chamber1->yErr*chamber1->yErr+chamber2->yErr*chamber2->yErr) )
669  {
670  if ( betterMuon == 1 )
671  nMatches2--;
672  else
673  nMatches1--;
674  if ( nMatches1==0 || nMatches2==0 ) return true;
675  }
676  } else {
677  if ( ! checkAdjacentChambers ) continue;
678  // check if tracks are pointing into overlaping region of the CSC detector
679  if ( chamber1->id.subdetId() != MuonSubdetId::CSC ||
680  chamber2->id.subdetId() != MuonSubdetId::CSC ) continue;
681  CSCDetId id1(chamber1->id);
682  CSCDetId id2(chamber2->id);
683  if ( id1.endcap() != id2.endcap() ) continue;
684  if ( id1.station() != id2.station() ) continue;
685  if ( id1.ring() != id2.ring() ) continue;
686  if ( abs(id1.chamber() - id2.chamber())>1 ) continue;
687  // FIXME: we don't handle 18->1; 36->1 transitions since
688  // I don't know how to check for sure how many chambers
689  // are there. Probably need to hard code some checks.
690 
691  // Now we have to make sure that both tracks are close to an edge
692  // FIXME: ignored Y coordinate for now
693  if ( fabs(chamber1->edgeX) > chamber1->xErr*pullX ) continue;
694  if ( fabs(chamber2->edgeX) > chamber2->xErr*pullX ) continue;
695  if ( chamber1->x * chamber2->x < 0 ) { // check if the same edge
696  if ( betterMuon == 1 )
697  nMatches2--;
698  else
699  nMatches1--;
700  if ( nMatches1==0 || nMatches2==0 ) return true;
701  }
702  }
703  }
704  return false;
705 }
int chamber() const
Definition: CSCDetId.h:70
type
Definition: HCALResponse.h:22
int i
Definition: DBlmapReader.cc:9
const std::string & label
Definition: MVAComputer.cc:186
AlgorithmType
Definition: MuonSelectors.h:61
float trackDistErr(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:691
virtual TrackRef innerTrack() const
Definition: Muon.h:38
bool isTrackerMuon() const
Definition: Muon.h:149
#define abs(x)
Definition: mlp_lapack.h:159
bool isGlobalMuon() const
Definition: Muon.h:148
float trkKink
value of the kink algorithm applied to the inner track stub
Definition: MuonQuality.h:11
bool isMatchesValid() const
Definition: Muon.h:89
float dY(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:328
bool isStandAloneMuon() const
Definition: Muon.h:150
float trkRelChi2
chi2 value for the inner track stub with respect to the global track
Definition: MuonQuality.h:15
virtual double eta() const
momentum pseudorapidity
float caloCompatibility(const reco::Muon &muon)
SelectionType
Selector type.
Definition: MuonSelectors.h:16
bool overlap(const reco::Muon &muon1, const reco::Muon &muon2, double pullX=1.0, double pullY=1.0, bool checkAdjacentChambers=false)
int endcap() const
Definition: CSCDetId.h:95
static const int CSC
Definition: MuonSubdetId.h:15
ArbitrationType
define arbitration schemes
Definition: Muon.h:115
T sqrt(T t)
Definition: SSEVec.h:28
MuonQuality combinedQuality() const
get energy deposition information
Definition: Muon.h:72
float pullDxDz(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
Definition: Muon.cc:375
float segmentCompatibility(const reco::Muon &muon, reco::Muon::ArbitrationType arbitrationType=reco::Muon::SegmentAndTrackArbitration)
bool isQualityValid() const
Definition: Muon.h:70
unsigned int stationMask(ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:97
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:41
float pullY(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
Definition: Muon.cc:364
float segmentX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:396
bool isGoodMuon(const reco::Muon &muon, SelectionType type, reco::Muon::ArbitrationType arbitrationType=reco::Muon::SegmentAndTrackArbitration)
main GoodMuon wrapper call
int numberOfMatches(ArbitrationType type=SegmentAndTrackArbitration) const
get number of chambers with matched segments
Definition: Muon.cc:40
int ring() const
Definition: CSCDetId.h:77
float staRelChi2
chi2 value for the outer track stub with respect to the global track
Definition: MuonQuality.h:17
SelectionType selectionTypeFromString(const std::string &label)
Definition: MuonSelectors.cc:7
virtual double pt() const
transverse momentum
a lightweight &quot;map&quot; for selection type string label and enum value
Definition: MuonSelectors.h:51
unsigned int RequiredStationMask(const reco::Muon &muon, double maxChamberDist, double maxChamberDistPull, reco::Muon::ArbitrationType arbitrationType)
std::vector< MuonChamberMatch > & matches()
get muon matching information
Definition: Muon.h:91
float trackDist(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:674
float dX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
Definition: Muon.cc:320
int station() const
Definition: CSCDetId.h:88
float caloCompatibility() const
Definition: Muon.h:101
float pullDyDz(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
Definition: Muon.cc:385
virtual TrackRef globalTrack() const
reference to Track reconstructed in both tracked and muon detector
Definition: Muon.h:44
float pullX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
Definition: Muon.cc:354