CMS 3D CMS Logo

MuonSelectors.cc
Go to the documentation of this file.
7 
8 namespace muon {
10 {
11  static const SelectionTypeStringToEnum selectionTypeStringToEnumMap[] = {
12  { "All", All },
13  { "AllGlobalMuons", AllGlobalMuons },
14  { "AllStandAloneMuons", AllStandAloneMuons },
15  { "AllTrackerMuons", AllTrackerMuons },
16  { "TrackerMuonArbitrated", TrackerMuonArbitrated },
17  { "AllArbitrated", AllArbitrated },
18  { "GlobalMuonPromptTight", GlobalMuonPromptTight },
19  { "TMLastStationLoose", TMLastStationLoose },
20  { "TMLastStationTight", TMLastStationTight },
21  { "TM2DCompatibilityLoose", TM2DCompatibilityLoose },
22  { "TM2DCompatibilityTight", TM2DCompatibilityTight },
23  { "TMOneStationLoose", TMOneStationLoose },
24  { "TMOneStationTight", TMOneStationTight },
25  { "TMLastStationOptimizedLowPtLoose", TMLastStationOptimizedLowPtLoose },
26  { "TMLastStationOptimizedLowPtTight", TMLastStationOptimizedLowPtTight },
27  { "GMTkChiCompatibility", GMTkChiCompatibility },
28  { "GMStaChiCompatibility", GMStaChiCompatibility},
29  { "GMTkKinkTight", GMTkKinkTight},
30  { "TMLastStationAngLoose", TMLastStationAngLoose },
31  { "TMLastStationAngTight", TMLastStationAngTight },
32  { "TMOneStationAngLoose", TMOneStationAngLoose },
33  { "TMOneStationAngTight", TMOneStationAngTight },
34  { "TMLastStationOptimizedBarrelLowPtLoose", TMLastStationOptimizedBarrelLowPtLoose },
35  { "TMLastStationOptimizedBarrelLowPtTight", TMLastStationOptimizedBarrelLowPtTight },
36  { "RPCMuLoose", RPCMuLoose },
37  { "AllME0Muons", AllME0Muons },
38  { "ME0MuonArbitrated", ME0MuonArbitrated },
39  { "AllGEMMuons", AllGEMMuons },
40  { "GEMMuonArbitrated", GEMMuonArbitrated },
41  { 0, (SelectionType)-1 }
42  };
43 
45  bool found = false;
46  for(int i = 0; selectionTypeStringToEnumMap[i].label && (! found); ++i)
47  if (! strcmp(label.c_str(), selectionTypeStringToEnumMap[i].label)) {
48  found = true;
49  value = selectionTypeStringToEnumMap[i].value;
50  }
51 
52  // in case of unrecognized selection type
53  if (! found) throw cms::Exception("MuonSelectorError") << label << " is not a recognized SelectionType";
54  return value;
55 }
56 }
57 
59  double maxChamberDist,
60  double maxChamberDistPull,
61  reco::Muon::ArbitrationType arbitrationType )
62 {
63  unsigned int theMask = 0;
64 
65  for(int stationIdx = 1; stationIdx < 5; ++stationIdx)
66  for(int detectorIdx = 1; detectorIdx < 3; ++detectorIdx)
67  if(muon.trackDist(stationIdx,detectorIdx,arbitrationType) < maxChamberDist &&
68  muon.trackDist(stationIdx,detectorIdx,arbitrationType)/muon.trackDistErr(stationIdx,detectorIdx,arbitrationType) < maxChamberDistPull)
69  theMask += 1<<((stationIdx-1)+4*(detectorIdx-1));
70 
71  return theMask;
72 }
73 
74 // ------------ method to calculate the calo compatibility for a track with matched muon info ------------
76  return muon.caloCompatibility();
77 }
78 
79 // ------------ method to calculate the segment compatibility for a track with matched muon info ------------
81  bool use_weight_regain_at_chamber_boundary = true;
82  bool use_match_dist_penalty = true;
83 
84  int nr_of_stations_crossed = 0;
85  int nr_of_stations_with_segment = 0;
86  std::vector<int> stations_w_track(8);
87  std::vector<int> station_has_segmentmatch(8);
88  std::vector<int> station_was_crossed(8);
89  std::vector<float> stations_w_track_at_boundary(8);
90  std::vector<float> station_weight(8);
91  int position_in_stations = 0;
92  float full_weight = 0.;
93 
94  for(int i = 1; i<=8; ++i) {
95  // ********************************************************;
96  // *** fill local info for this muon (do some counting) ***;
97  // ************** begin ***********************************;
98  if(i<=4) { // this is the section for the DTs
99  if( muon.trackDist(i,1,arbitrationType) < 999999 ) { //current "raw" info that a track is close to a chamber
100  ++nr_of_stations_crossed;
101  station_was_crossed[i-1] = 1;
102  if(muon.trackDist(i,1,arbitrationType) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i,1,arbitrationType);
103  else stations_w_track_at_boundary[i-1] = 0.;
104  }
105  if( muon.segmentX(i,1,arbitrationType) < 999999 ) { //current "raw" info that a segment is matched to the current track
106  ++nr_of_stations_with_segment;
107  station_has_segmentmatch[i-1] = 1;
108  }
109  }
110  else { // this is the section for the CSCs
111  if( muon.trackDist(i-4,2,arbitrationType) < 999999 ) { //current "raw" info that a track is close to a chamber
112  ++nr_of_stations_crossed;
113  station_was_crossed[i-1] = 1;
114  if(muon.trackDist(i-4,2,arbitrationType) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i-4,2,arbitrationType);
115  else stations_w_track_at_boundary[i-1] = 0.;
116  }
117  if( muon.segmentX(i-4,2,arbitrationType) < 999999 ) { //current "raw" info that a segment is matched to the current track
118  ++nr_of_stations_with_segment;
119  station_has_segmentmatch[i-1] = 1;
120  }
121  }
122  // rough estimation of chamber border efficiency (should be parametrized better, this is just a quick guess):
123  // TF1 * merf = new TF1("merf","-0.5*(TMath::Erf(x/6.)-1)",-100,100);
124  // use above value to "unpunish" missing segment if close to border, i.e. rather than not adding any weight, add
125  // the one from the function. Only for dist ~> -10 cm, else full punish!.
126 
127  // ********************************************************;
128  // *** fill local info for this muon (do some counting) ***;
129  // ************** end *************************************;
130  }
131 
132  // ********************************************************;
133  // *** calculate weights for each station *****************;
134  // ************** begin ***********************************;
135  // const float slope = 0.5;
136  // const float attenuate_weight_regain = 1.;
137  // if attenuate_weight_regain < 1., additional punishment if track is close to boundary and no segment
138  const float attenuate_weight_regain = 0.5;
139 
140  for(int i = 1; i<=8; ++i) { // loop over all possible stations
141 
142  // first set all weights if a station has been crossed
143  // later penalize if a station did not have a matching segment
144 
145  //old logic if(station_has_segmentmatch[i-1] > 0 ) { // the track has an associated segment at the current station
146  if( station_was_crossed[i-1] > 0 ) { // the track crossed this chamber (or was nearby)
147  // - Apply a weight depending on the "depth" of the muon passage.
148  // - The station_weight is later reduced for stations with badly matched segments.
149  // - Even if there is no segment but the track passes close to a chamber boundary, the
150  // weight is set non zero and can go up to 0.5 of the full weight if the track is quite
151  // far from any station.
152  ++position_in_stations;
153 
154  switch ( nr_of_stations_crossed ) { // define different weights depending on how many stations were crossed
155  case 1 :
156  station_weight[i-1] = 1.;
157  break;
158  case 2 :
159  if ( position_in_stations == 1 ) station_weight[i-1] = 0.33;
160  else station_weight[i-1] = 0.67;
161  break;
162  case 3 :
163  if ( position_in_stations == 1 ) station_weight[i-1] = 0.23;
164  else if( position_in_stations == 2 ) station_weight[i-1] = 0.33;
165  else station_weight[i-1] = 0.44;
166  break;
167  case 4 :
168  if ( position_in_stations == 1 ) station_weight[i-1] = 0.10;
169  else if( position_in_stations == 2 ) station_weight[i-1] = 0.20;
170  else if( position_in_stations == 3 ) station_weight[i-1] = 0.30;
171  else station_weight[i-1] = 0.40;
172  break;
173 
174  default :
175 // LogTrace("MuonIdentification")<<" // Message: A muon candidate track has more than 4 stations with matching segments.";
176 // LogTrace("MuonIdentification")<<" // Did not expect this - please let me know: ibloch@fnal.gov";
177  // for all other cases
178  station_weight[i-1] = 1./nr_of_stations_crossed;
179  }
180 
181  if( use_weight_regain_at_chamber_boundary ) { // reconstitute some weight if there is no match but the segment is close to a boundary:
182  if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] != 0. ) {
183  // if segment is not present but track in inefficient region, do not count as "missing match" but add some reduced weight.
184  // original "match weight" is currently reduced by at least attenuate_weight_regain, variing with an error function down to 0 if the track is
185  // inside the chamber.
186  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
187  }
188  else if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] == 0.) { // no segment match and track well inside chamber
189  // full penalization
190  station_weight[i-1] = 0.;
191  }
192  }
193  else { // always fully penalize tracks with no matching segment, whether the segment is close to the boundary or not.
194  if(station_has_segmentmatch[i-1] <= 0) station_weight[i-1] = 0.;
195  }
196 
197  if( station_has_segmentmatch[i-1] > 0 && 42 == 42 ) { // if track has matching segment, but the matching is not high quality, penalize
198  if(i<=4) { // we are in the DTs
199  if( muon.dY(i,1,arbitrationType) < 999999 && muon.dX(i,1,arbitrationType) < 999999) { // have both X and Y match
200  if(
201  TMath::Sqrt(TMath::Power(muon.pullX(i,1,arbitrationType),2.)+TMath::Power(muon.pullY(i,1,arbitrationType),2.))> 1. ) {
202  // reduce weight
203  if(use_match_dist_penalty) {
204  // only use pull if 3 sigma is not smaller than 3 cm
205  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. ) {
206  station_weight[i-1] *= 1./TMath::Power(
207  TMath::Max((double)TMath::Sqrt(TMath::Power(muon.dX(i,1,arbitrationType),2.)+TMath::Power(muon.dY(i,1,arbitrationType),2.)),(double)1.),.25);
208  }
209  else {
210  station_weight[i-1] *= 1./TMath::Power(
211  TMath::Sqrt(TMath::Power(muon.pullX(i,1,arbitrationType),2.)+TMath::Power(muon.pullY(i,1,arbitrationType),2.)),.25);
212  }
213  }
214  }
215  }
216  else if (muon.dY(i,1,arbitrationType) >= 999999) { // has no match in Y
217  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)
218  // reduce weight
219  if(use_match_dist_penalty) {
220  // only use pull if 3 sigma is not smaller than 3 cm
221  if( muon.dX(i,1,arbitrationType) < 3. && muon.pullX(i,1,arbitrationType) > 3. ) {
222  station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dX(i,1,arbitrationType),(double)1.),.25);
223  }
224  else {
225  station_weight[i-1] *= 1./TMath::Power(muon.pullX(i,1,arbitrationType),.25);
226  }
227  }
228  }
229  }
230  else { // has no match in X
231  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)
232  // reduce weight
233  if(use_match_dist_penalty) {
234  // only use pull if 3 sigma is not smaller than 3 cm
235  if( muon.dY(i,1,arbitrationType) < 3. && muon.pullY(i,1,arbitrationType) > 3. ) {
236  station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dY(i,1,arbitrationType),(double)1.),.25);
237  }
238  else {
239  station_weight[i-1] *= 1./TMath::Power(muon.pullY(i,1,arbitrationType),.25);
240  }
241  }
242  }
243  }
244  }
245  else { // We are in the CSCs
246  if(
247  TMath::Sqrt(TMath::Power(muon.pullX(i-4,2,arbitrationType),2.)+TMath::Power(muon.pullY(i-4,2,arbitrationType),2.)) > 1. ) {
248  // reduce weight
249  if(use_match_dist_penalty) {
250  // only use pull if 3 sigma is not smaller than 3 cm
251  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. ) {
252  station_weight[i-1] *= 1./TMath::Power(
253  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);
254  }
255  else {
256  station_weight[i-1] *= 1./TMath::Power(
257  TMath::Sqrt(TMath::Power(muon.pullX(i-4,2,arbitrationType),2.)+TMath::Power(muon.pullY(i-4,2,arbitrationType),2.)),.25);
258  }
259  }
260  }
261  }
262  }
263 
264  // Thoughts:
265  // - should penalize if the segment has only x OR y info
266  // - should also use the segment direction, as it now works!
267 
268  }
269  else { // track did not pass a chamber in this station - just reset weight
270  station_weight[i-1] = 0.;
271  }
272 
273  //increment final weight for muon:
274  full_weight += station_weight[i-1];
275  }
276 
277  // if we don't expect any matches, we set the compatibility to
278  // 0.5 as the track is as compatible with a muon as it is with
279  // background - we should maybe rather set it to -0.5!
280  if( nr_of_stations_crossed == 0 ) {
281  // full_weight = attenuate_weight_regain*0.5;
282  full_weight = 0.5;
283  }
284 
285  // ********************************************************;
286  // *** calculate weights for each station *****************;
287  // ************** end *************************************;
288 
289  return full_weight;
290 
291 }
292 
295  double minCompatibility,
296  reco::Muon::ArbitrationType arbitrationType ) {
297  if (!muon.isMatchesValid()) return false;
298  bool goodMuon = false;
299 
300  switch( type ) {
301  case TM2DCompatibility:
302  // Simplistic first cut in the 2D segment- vs calo-compatibility plane. Will have to be refined!
303  if( ( (0.8*caloCompatibility( muon ))+(1.2*segmentCompatibility( muon, arbitrationType )) ) > minCompatibility ) goodMuon = true;
304  else goodMuon = false;
305  return goodMuon;
306  break;
307  default :
308  // LogTrace("MuonIdentification")<<" // Invalid Algorithm Type called!";
309  goodMuon = false;
310  return goodMuon;
311  break;
312  }
313 }
314 
317  int minNumberOfMatches,
318  double maxAbsDx,
319  double maxAbsPullX,
320  double maxAbsDy,
321  double maxAbsPullY,
322  double maxChamberDist,
323  double maxChamberDistPull,
324  reco::Muon::ArbitrationType arbitrationType,
325  bool syncMinNMatchesNRequiredStationsInBarrelOnly,
326  bool applyAlsoAngularCuts)
327 {
328  if (!muon.isMatchesValid()) return false;
329  bool goodMuon = false;
330 
331  if (type == TMLastStation) {
332  // To satisfy my own paranoia, if the user specifies that the
333  // minimum number of matches is zero, then return true.
334  if(minNumberOfMatches == 0) return true;
335 
336  unsigned int theStationMask = muon.stationMask(arbitrationType);
337  unsigned int theRequiredStationMask = RequiredStationMask(muon, maxChamberDist, maxChamberDistPull, arbitrationType);
338 
339  // Require that there be at least a minimum number of segments
340  int numSegs = 0;
341  int numRequiredStations = 0;
342  for(int it = 0; it < 8; ++it) {
343  if(theStationMask & 1<<it) ++numSegs;
344  if(theRequiredStationMask & 1<<it) ++numRequiredStations;
345  }
346 
347  // Make sure the minimum number of matches is not greater than
348  // the number of required stations but still greater than zero
349  if (syncMinNMatchesNRequiredStationsInBarrelOnly) {
350  // Note that we only do this in the barrel region!
351  if (fabs(muon.eta()) < 1.2) {
352  if(minNumberOfMatches > numRequiredStations)
353  minNumberOfMatches = numRequiredStations;
354  if(minNumberOfMatches < 1) //SK: this only happens for negative values
355  minNumberOfMatches = 1;
356  }
357  } else {
358  if(minNumberOfMatches > numRequiredStations)
359  minNumberOfMatches = numRequiredStations;
360  if(minNumberOfMatches < 1) //SK: this only happens for negative values
361  minNumberOfMatches = 1;
362  }
363 
364  if(numSegs >= minNumberOfMatches) goodMuon = 1;
365 
366  // Require that last required station have segment
367  // If there are zero required stations keep track
368  // of the last station with a segment so that we may
369  // apply the quality cuts below to it instead
370  int lastSegBit = 0;
371  if(theRequiredStationMask) {
372  for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
373  if(theRequiredStationMask & 1<<stationIdx){
374  if(theStationMask & 1<<stationIdx) {
375  lastSegBit = stationIdx;
376  goodMuon &= 1;
377  break;
378  } else {
379  goodMuon = false;
380  break;
381  }
382  }
383  } else {
384  for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
385  if(theStationMask & 1<<stationIdx) {
386  lastSegBit = stationIdx;
387  break;
388  }
389  }
390 
391  if(!goodMuon) return false;
392 
393  // Impose pull cuts on last segment
394  int station = 0, detector = 0;
395  station = lastSegBit < 4 ? lastSegBit+1 : lastSegBit-3;
396  detector = lastSegBit < 4 ? 1 : 2;
397 
398  // Check x information
399  if(fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
400  fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx)
401  return false;
402 
403  if(applyAlsoAngularCuts && fabs(muon.pullDxDz(station,detector,arbitrationType,1)) > maxAbsPullX)
404  return false;
405 
406  // Is this a tight algorithm, i.e. do we bother to check y information?
407  if (maxAbsDy < 999999) { // really if maxAbsDy < 1E9 as currently defined
408 
409  // Check y information
410  if (detector == 2) { // CSC
411  if(fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
412  fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy)
413  return false;
414 
415  if(applyAlsoAngularCuts && fabs(muon.pullDyDz(station,2,arbitrationType,1)) > maxAbsPullY)
416  return false;
417  } else {
418  //
419  // In DT, if this is a "Tight" algorithm and the last segment is
420  // missing y information (always the case in station 4!!!), impose
421  // respective cuts on the next station in the stationMask that has
422  // a segment with y information. If there are no segments with y
423  // information then there is nothing to penalize. Should we
424  // penalize in Tight for having zero segments with y information?
425  // That is the fundamental question. Of course I am being uber
426  // paranoid; if this is a good muon then there will probably be at
427  // least one segment with y information but not always. Suppose
428  // somehow a muon only creates segments in station 4, then we
429  // definitely do not want to require that there be at least one
430  // segment with y information because we will lose it completely.
431  //
432 
433  for (int stationIdx = station; stationIdx > 0; --stationIdx) {
434  if(! (theStationMask & 1<<(stationIdx-1))) // don't bother if the station is not in the stationMask
435  continue;
436 
437  if(muon.dY(stationIdx,1,arbitrationType) > 999998) // no y-information
438  continue;
439 
440  if(fabs(muon.pullY(stationIdx,1,arbitrationType,1)) > maxAbsPullY &&
441  fabs(muon.dY(stationIdx,1,arbitrationType)) > maxAbsDy) {
442  return false;
443  }
444 
445  if(applyAlsoAngularCuts && fabs(muon.pullDyDz(stationIdx,1,arbitrationType,1)) > maxAbsPullY)
446  return false;
447 
448  // If we get this far then great this is a good muon
449  return true;
450  }
451  }
452  }
453 
454  return goodMuon;
455  } // TMLastStation
456 
457  // TMOneStation requires only that there be one "good" segment, regardless
458  // of the required stations. We do not penalize if there are absolutely zero
459  // segments with y information in the Tight algorithm. Maybe I'm being
460  // paranoid but so be it. If it's really a good muon then we will probably
461  // find at least one segment with both x and y information but you never
462  // know, and I don't want to deal with a potential inefficiency in the DT
463  // like we did with the original TMLastStation. Incidentally, not penalizing
464  // for total lack of y information in the Tight algorithm is what is done in
465  // the new TMLastStation
466  //
467  if (type == TMOneStation) {
468  unsigned int theStationMask = muon.stationMask(arbitrationType);
469 
470  // Of course there must be at least one segment
471  if (! theStationMask) return false;
472 
473  int station = 0, detector = 0;
474  // Keep track of whether or not there is a DT segment with y information.
475  // In the end, if it turns out there are absolutely zero DT segments with
476  // y information, require only that there was a segment with good x info.
477  // This of course only applies to the Tight algorithms.
478  bool existsGoodDTSegX = false;
479  bool existsDTSegY = false;
480 
481  // Impose cuts on the segments in the station mask until we find a good one
482  // Might as well start with the lowest bit to speed things up.
483  for(int stationIdx = 0; stationIdx <= 7; ++stationIdx)
484  if(theStationMask & 1<<stationIdx) {
485  station = stationIdx < 4 ? stationIdx+1 : stationIdx-3;
486  detector = stationIdx < 4 ? 1 : 2;
487 
488  if((fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
489  fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx) ||
490  (applyAlsoAngularCuts && fabs(muon.pullDxDz(station,detector,arbitrationType,1)) > maxAbsPullX))
491  continue;
492  else if (detector == 1)
493  existsGoodDTSegX = true;
494 
495  // Is this a tight algorithm? If yes, use y information
496  if (maxAbsDy < 999999) {
497  if (detector == 2) { // CSC
498  if((fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
499  fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy) ||
500  (applyAlsoAngularCuts && fabs(muon.pullDyDz(station,2,arbitrationType,1)) > maxAbsPullY))
501  continue;
502  } else {
503 
504  if(muon.dY(station,1,arbitrationType) > 999998) // no y-information
505  continue;
506  else
507  existsDTSegY = true;
508 
509  if((fabs(muon.pullY(station,1,arbitrationType,1)) > maxAbsPullY &&
510  fabs(muon.dY(station,1,arbitrationType)) > maxAbsDy) ||
511  (applyAlsoAngularCuts && fabs(muon.pullDyDz(station,1,arbitrationType,1)) > maxAbsPullY)) {
512  continue;
513  }
514  }
515  }
516 
517  // If we get this far then great this is a good muon
518  return true;
519  }
520 
521  // If we get this far then for sure there are no "good" CSC segments. For
522  // DT, check if there were any segments with y information. If there
523  // were none, but there was a segment with good x, then we're happy. If
524  // there WERE segments with y information, then they must have been shit
525  // since we are here so fail it. Of course, if this is a Loose algorithm
526  // then fail immediately since if we had good x we would already have
527  // returned true
528  if (maxAbsDy < 999999) {
529  if (existsDTSegY)
530  return false;
531  else if (existsGoodDTSegX)
532  return true;
533  } else
534  return false;
535  } // TMOneStation
536 
537  if ( type == RPCMu )
538  {
539  if ( minNumberOfMatches == 0 ) return true;
540 
541  int nMatch = 0;
542  for ( std::vector<reco::MuonChamberMatch>::const_iterator chamberMatch = muon.matches().begin();
543  chamberMatch != muon.matches().end(); ++chamberMatch )
544  {
545  if ( chamberMatch->detector() != 3 ) continue;
546 
547  const double trkX = chamberMatch->x;
548  const double errX = chamberMatch->xErr;
549 
550  for ( std::vector<reco::MuonRPCHitMatch>::const_iterator rpcMatch = chamberMatch->rpcMatches.begin();
551  rpcMatch != chamberMatch->rpcMatches.end(); ++rpcMatch )
552  {
553  const double rpcX = rpcMatch->x;
554 
555  const double dX = fabs(rpcX-trkX);
556  if ( dX < maxAbsDx or dX/errX < maxAbsPullX )
557  {
558  ++nMatch;
559  break;
560  }
561  }
562  }
563 
564  if ( nMatch >= minNumberOfMatches ) return true;
565  else return false;
566  } // RPCMu
567 
568  if ( type == ME0Mu )
569  {
570  if ( minNumberOfMatches == 0 ) return true;
571 
572  int nMatch = 0;
573  for ( const auto& chamberMatch : muon.matches() )
574  {
575  if ( chamberMatch.detector() != MuonSubdetId::ME0 ) continue;
576 
577  const double trkX = chamberMatch.x;
578  const double errX = chamberMatch.xErr;
579  const double trkY = chamberMatch.y;
580  const double errY = chamberMatch.yErr;
581 
582  for ( const auto& segment : chamberMatch.me0Matches )
583  {
584 
585  const double me0X = segment.x;
586  const double me0ErrX = segment.xErr;
587  const double me0Y = segment.y;
588  const double me0ErrY = segment.yErr;
589 
590  const double dX = fabs(me0X - trkX);
591  const double dY = fabs(me0Y - trkY);
592  const double pullX = dX/std::sqrt(errX + me0ErrX);
593  const double pullY = dY/std::sqrt(errY + me0ErrY);
594 
595  if ( (dX < maxAbsDx or pullX < maxAbsPullX) and (dY < maxAbsDy or pullY < maxAbsPullY) )
596  {
597  ++nMatch;
598  break;
599  }
600  }
601  }
602 
603  return ( nMatch >= minNumberOfMatches );
604  } // ME0Mu
605 
606  if ( type == GEMMu )
607  {
608  if ( minNumberOfMatches == 0 ) return true;
609 
610  int nMatch = 0;
611  for ( const auto& chamberMatch : muon.matches() )
612  {
613  if ( chamberMatch.detector() != MuonSubdetId::GEM ) continue;
614 
615  const double trkX = chamberMatch.x;
616  const double errX = chamberMatch.xErr;
617  const double trkY = chamberMatch.y;
618  const double errY = chamberMatch.yErr;
619 
620  for ( const auto& segment : chamberMatch.gemMatches )
621  {
622 
623  const double gemX = segment.x;
624  const double gemErrX = segment.xErr;
625  const double gemY = segment.y;
626  const double gemErrY = segment.yErr;
627 
628  const double dX = fabs(gemX - trkX);
629  const double dY = fabs(gemY - trkY);
630  const double pullX = dX/std::sqrt(errX + gemErrX);
631  const double pullY = dY/std::sqrt(errY + gemErrY);
632 
633  if ( (dX < maxAbsDx or pullX < maxAbsPullX) and (dY < maxAbsDy or pullY < maxAbsPullY) )
634  {
635  ++nMatch;
636  break;
637  }
638  }
639  }
640 
641  return ( nMatch >= minNumberOfMatches );
642  } // GEMMu
643 
644  return goodMuon;
645 }
646 
648  reco::Muon::ArbitrationType arbitrationType)
649 {
650  switch (type)
651  {
652  case muon::All:
653  return true;
654  break;
656  return muon.isGlobalMuon();
657  break;
659  return muon.isTrackerMuon();
660  break;
662  return muon.isStandAloneMuon();
663  break;
665  return muon.isTrackerMuon() && muon.numberOfMatches(arbitrationType)>0;
666  break;
667  case muon::AllArbitrated:
668  return ! muon.isTrackerMuon() || muon.numberOfMatches(arbitrationType)>0;
669  break;
671  return muon.isGlobalMuon() && muon.globalTrack()->normalizedChi2()<10. && muon.globalTrack()->hitPattern().numberOfValidMuonHits() >0;
672  break;
673  // For "Loose" algorithms we choose maximum y quantity cuts of 1E9 instead of
674  // 9999 as before. We do this because the muon methods return 999999 (note
675  // there are six 9's) when the requested information is not available. For
676  // example, if a muon fails to traverse the z measuring superlayer in a station
677  // in the DT, then all methods involving segmentY in this station return
678  // 999999 to demonstrate that the information is missing. In order to not
679  // penalize muons for missing y information in Loose algorithms where we do
680  // not care at all about y information, we raise these limits. In the
681  // TMLastStation and TMOneStation algorithms we actually use this huge number
682  // to determine whether to consider y information at all.
684  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,true,false);
685  break;
687  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,true,false);
688  break;
690  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
691  break;
693  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
694  break;
696  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
697  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
698  else
699  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,false,false);
700  break;
702  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
703  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
704  else
705  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,false,false);
706  break;
707  //compatibility loose
709  return muon.isTrackerMuon() && isGoodMuon(muon,TM2DCompatibility,0.7,arbitrationType);
710  break;
711  //compatibility tight
713  return muon.isTrackerMuon() && isGoodMuon(muon,TM2DCompatibility,1.0,arbitrationType);
714  break;
716  return muon.isGlobalMuon() && muon.isQualityValid() && fabs(muon.combinedQuality().trkRelChi2 - muon.innerTrack()->normalizedChi2()) < 2.0;
717  break;
719  return muon.isGlobalMuon() && muon.isQualityValid() && fabs(muon.combinedQuality().staRelChi2 - muon.outerTrack()->normalizedChi2()) < 2.0;
720  break;
721  case muon::GMTkKinkTight:
722  return muon.isGlobalMuon() && muon.isQualityValid() && muon.combinedQuality().trkKink < 100.0;
723  break;
725  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,false,true);
726  break;
728  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,false,true);
729  break;
731  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,true);
732  break;
734  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,true);
735  break;
737  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
738  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,arbitrationType,false,false);
739  else
740  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,arbitrationType,true,false);
741  break;
743  if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
744  return muon.isTrackerMuon() && isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,arbitrationType,false,false);
745  else
746  return muon.isTrackerMuon() && isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,arbitrationType,true,false);
747  break;
748  case muon::RPCMuLoose:
749  return muon.isRPCMuon() && isGoodMuon(muon, RPCMu, 2, 20, 4, 1e9, 1e9, 1e9, 1e9, arbitrationType, false, false);
750  break;
751  case muon::AllME0Muons:
752  return muon.isME0Muon();
753  break;
755  return muon.isME0Muon() && isGoodMuon(muon, ME0Mu, 1, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, arbitrationType, false, false);
756  break;
757  case muon::AllGEMMuons:
758  return muon.isGEMMuon();
759  break;
761  return muon.isGEMMuon() && isGoodMuon(muon, GEMMu, 1, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, arbitrationType, false, false);
762  break;
763  default:
764  return false;
765  }
766 }
767 
768 bool muon::overlap( const reco::Muon& muon1, const reco::Muon& muon2,
769  double pullX, double pullY, bool checkAdjacentChambers)
770 {
771  unsigned int nMatches1 = muon1.numberOfMatches(reco::Muon::SegmentAndTrackArbitration);
772  unsigned int nMatches2 = muon2.numberOfMatches(reco::Muon::SegmentAndTrackArbitration);
773  unsigned int betterMuon = ( muon1.pt() > muon2.pt() ? 1 : 2 );
774  for ( std::vector<reco::MuonChamberMatch>::const_iterator chamber1 = muon1.matches().begin();
775  chamber1 != muon1.matches().end(); ++chamber1 )
776  for ( std::vector<reco::MuonChamberMatch>::const_iterator chamber2 = muon2.matches().begin();
777  chamber2 != muon2.matches().end(); ++chamber2 )
778  {
779 
780  // if ( (chamber1->segmentMatches.empty() || chamber2->segmentMatches.empty()) ) continue;
781 
782  // handle case where both muons have information about the same chamber
783  // here we know how close they are
784  if ( chamber1->id == chamber2->id ){
785  // found the same chamber
786  if ( fabs(chamber1->x-chamber2->x) <
787  pullX * sqrt(chamber1->xErr*chamber1->xErr+chamber2->xErr*chamber2->xErr) )
788  {
789  if ( betterMuon == 1 )
790  nMatches2--;
791  else
792  nMatches1--;
793  if ( nMatches1==0 || nMatches2==0 ) return true;
794  continue;
795  }
796  if ( fabs(chamber1->y-chamber2->y) <
797  pullY * sqrt(chamber1->yErr*chamber1->yErr+chamber2->yErr*chamber2->yErr) )
798  {
799  if ( betterMuon == 1 )
800  nMatches2--;
801  else
802  nMatches1--;
803  if ( nMatches1==0 || nMatches2==0 ) return true;
804  }
805  } else {
806  if ( ! checkAdjacentChambers ) continue;
807  // check if tracks are pointing into overlaping region of the CSC detector
808  if ( chamber1->id.subdetId() != MuonSubdetId::CSC ||
809  chamber2->id.subdetId() != MuonSubdetId::CSC ) continue;
810  CSCDetId id1(chamber1->id);
811  CSCDetId id2(chamber2->id);
812  if ( id1.endcap() != id2.endcap() ) continue;
813  if ( id1.station() != id2.station() ) continue;
814  if ( id1.ring() != id2.ring() ) continue;
815  if ( abs(id1.chamber() - id2.chamber())>1 ) continue;
816  // FIXME: we don't handle 18->1; 36->1 transitions since
817  // I don't know how to check for sure how many chambers
818  // are there. Probably need to hard code some checks.
819 
820  // Now we have to make sure that both tracks are close to an edge
821  // FIXME: ignored Y coordinate for now
822  if ( fabs(chamber1->edgeX) > chamber1->xErr*pullX ) continue;
823  if ( fabs(chamber2->edgeX) > chamber2->xErr*pullX ) continue;
824  if ( chamber1->x * chamber2->x < 0 ) { // check if the same edge
825  if ( betterMuon == 1 )
826  nMatches2--;
827  else
828  nMatches1--;
829  if ( nMatches1==0 || nMatches2==0 ) return true;
830  }
831  }
832  }
833  return false;
834 }
835 
836 
838 
839  if(!muon.isPFMuon() || !muon.isGlobalMuon() ) return false;
840 
841  bool muID = isGoodMuon(muon,GlobalMuonPromptTight) && (muon.numberOfMatchedStations() > 1);
842 
843 
844  bool hits = muon.innerTrack()->hitPattern().trackerLayersWithMeasurement() > 5 &&
845  muon.innerTrack()->hitPattern().numberOfValidPixelHits() > 0;
846 
847 
848  bool ip = fabs(muon.muonBestTrack()->dxy(vtx.position())) < 0.2 && fabs(muon.muonBestTrack()->dz(vtx.position())) < 0.5;
849 
850  return muID && hits && ip;
851 }
852 
853 
855  return muon.isPFMuon() && ( muon.isGlobalMuon() || muon.isTrackerMuon());
856 }
857 
858 
860  if( !( isLooseMuon(muon) && muon.innerTrack()->validFraction() > 0.8 )) return false;
861 
862  bool goodGlb = muon.isGlobalMuon() &&
863  muon.globalTrack()->normalizedChi2() < 3. &&
864  muon.combinedQuality().chi2LocalPosition < 12. &&
865  muon.combinedQuality().trkKink < 20.;
866 
867  return (segmentCompatibility(muon) > (goodGlb ? 0.303 : 0.451));
868 }
869 
870 
872 
873  bool muID = muon::isGoodMuon(muon, TMOneStationTight);
874 
875  if(!muID) return false;
876 
877  bool layers = muon.innerTrack()->hitPattern().trackerLayersWithMeasurement() > 5 &&
878  muon.innerTrack()->hitPattern().pixelLayersWithMeasurement() > 0;
879 
880  bool ishighq = muon.innerTrack()->quality(reco::Track::highPurity);
881 
882  bool ip = fabs(muon.innerTrack()->dxy(vtx.position())) < 0.3 && fabs(muon.innerTrack()->dz(vtx.position())) < 20.;
883 
884  return layers && ip && ishighq;
885 }
886 
887 
888 
890  bool muID = muon.isGlobalMuon() && muon.globalTrack()->hitPattern().numberOfValidMuonHits() >0 && (muon.numberOfMatchedStations() > 1);
891  if(!muID) return false;
892 
893  bool hits = muon.innerTrack()->hitPattern().trackerLayersWithMeasurement() > 5 &&
894  muon.innerTrack()->hitPattern().numberOfValidPixelHits() > 0;
895 
896  bool momQuality = muon.tunePMuonBestTrack()->ptError()/muon.tunePMuonBestTrack()->pt() < 0.3;
897 
898  bool ip = fabs(muon.innerTrack()->dxy(vtx.position())) < 0.2 && fabs(muon.innerTrack()->dz(vtx.position())) < 0.5;
899 
900  return muID && hits && momQuality && ip;
901 
902 }
903 
904 int muon::sharedSegments( const reco::Muon& mu, const reco::Muon& mu2, unsigned int segmentArbitrationMask ) {
905  int ret = 0;
906 
907  // Will do with a stupid double loop, since creating and filling a map is probably _more_ inefficient for a single lookup.
908  for(std::vector<reco::MuonChamberMatch>::const_iterator chamberMatch = mu.matches().begin();
909  chamberMatch != mu.matches().end(); ++chamberMatch) {
910  if (chamberMatch->segmentMatches.empty()) continue;
911  for(std::vector<reco::MuonChamberMatch>::const_iterator chamberMatch2 = mu2.matches().begin();
912  chamberMatch2 != mu2.matches().end(); ++chamberMatch2) {
913  if (chamberMatch2->segmentMatches.empty()) continue;
914  if (chamberMatch2->id() != chamberMatch->id()) continue;
915  for(std::vector<reco::MuonSegmentMatch>::const_iterator segmentMatch = chamberMatch->segmentMatches.begin();
916  segmentMatch != chamberMatch->segmentMatches.end(); ++segmentMatch) {
917  if (!segmentMatch->isMask(segmentArbitrationMask)) continue;
918  for(std::vector<reco::MuonSegmentMatch>::const_iterator segmentMatch2 = chamberMatch2->segmentMatches.begin();
919  segmentMatch2 != chamberMatch2->segmentMatches.end(); ++segmentMatch2) {
920  if (!segmentMatch2->isMask(segmentArbitrationMask)) continue;
921  if ((segmentMatch->cscSegmentRef.isNonnull() && segmentMatch->cscSegmentRef == segmentMatch2->cscSegmentRef) ||
922  (segmentMatch-> dtSegmentRef.isNonnull() && segmentMatch-> dtSegmentRef == segmentMatch2-> dtSegmentRef) ) {
923  ++ret;
924  } // is the same
925  } // segment of mu2 in chamber
926  } // segment of mu1 in chamber
927  } // chamber of mu2
928  } // chamber of mu1
929 
930  return ret;
931 }
float chi2LocalPosition
chi2 value for the STA-TK matching of local position
Definition: MuonQuality.h:19
int chamber() const
Definition: CSCDetId.h:68
type
Definition: HCALResponse.h:21
virtual double pt() const final
transverse momentum
float segmentX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
std::vector< LayerSetAndLayers > layers(const SeedingLayerSetsHits &sets)
Definition: LayerTriplets.cc:4
AlgorithmType
Definition: MuonSelectors.h:67
virtual double eta() const final
momentum pseudorapidity
virtual TrackRef innerTrack() const
Definition: Muon.h:48
bool isTrackerMuon() const
Definition: Muon.h:226
static const int GEM
Definition: MuonSubdetId.h:15
bool isGlobalMuon() const
Definition: Muon.h:225
float trkKink
value of the kink algorithm applied to the inner track stub
Definition: MuonQuality.h:11
bool isMatchesValid() const
Definition: Muon.h:142
bool isStandAloneMuon() const
Definition: Muon.h:227
float trkRelChi2
chi2 value for the inner track stub with respect to the global track
Definition: MuonQuality.h:15
bool isMediumMuon(const reco::Muon &)
const Point & position() const
position
Definition: Vertex.h:109
bool isME0Muon() const
Definition: Muon.h:232
float caloCompatibility(const reco::Muon &muon)
bool isLooseMuon(const reco::Muon &)
SelectionType
Selector type.
Definition: MuonSelectors.h:17
bool overlap(const reco::Muon &muon1, const reco::Muon &muon2, double pullX=1.0, double pullY=1.0, bool checkAdjacentChambers=false)
bool isSoftMuon(const reco::Muon &, const reco::Vertex &)
int endcap() const
Definition: CSCDetId.h:93
bool isRPCMuon() const
Definition: Muon.h:230
static const int ME0
Definition: MuonSubdetId.h:16
float trackDistErr(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
static const int CSC
Definition: MuonSubdetId.h:13
float dY(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
virtual TrackRef muonBestTrack() const
Definition: Muon.h:63
ArbitrationType
define arbitration schemes
Definition: Muon.h:182
float pullDxDz(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
T sqrt(T t)
Definition: SSEVec.h:18
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
MuonQuality combinedQuality() const
get energy deposition information
Definition: Muon.h:121
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float segmentCompatibility(const reco::Muon &muon, reco::Muon::ArbitrationType arbitrationType=reco::Muon::SegmentAndTrackArbitration)
const int mu
Definition: Constants.h:22
Definition: value.py:1
bool isQualityValid() const
Definition: Muon.h:119
float dX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
float pullY(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:51
bool isGoodMuon(const reco::Muon &muon, SelectionType type, reco::Muon::ArbitrationType arbitrationType=reco::Muon::SegmentAndTrackArbitration)
main GoodMuon wrapper call
unsigned int stationMask(ArbitrationType type=SegmentAndTrackArbitration) const
int numberOfMatchedStations(ArbitrationType type=SegmentAndTrackArbitration) const
T Max(T a, T b)
Definition: MathUtil.h:44
int ring() const
Definition: CSCDetId.h:75
float staRelChi2
chi2 value for the outer track stub with respect to the global track
Definition: MuonQuality.h:17
int sharedSegments(const reco::Muon &muon1, const reco::Muon &muon2, unsigned int segmentArbitrationMask=reco::MuonSegmentMatch::BestInChamberByDR)
bool isHighPtMuon(const reco::Muon &, const reco::Vertex &)
SelectionType selectionTypeFromString(const std::string &label)
Definition: MuonSelectors.cc:9
bool isGEMMuon() const
Definition: Muon.h:231
a lightweight "map" for selection type string label and enum value
Definition: MuonSelectors.h:57
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:144
int numberOfMatches(ArbitrationType type=SegmentAndTrackArbitration) const
get number of chambers with matched segments
float pullDyDz(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const
float trackDist(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration) const
bool isPFMuon() const
Definition: Muon.h:229
int station() const
Definition: CSCDetId.h:86
virtual TrackRef tunePMuonBestTrack() const
Definition: Muon.h:65
bool isTightMuon(const reco::Muon &, const reco::Vertex &)
float caloCompatibility() const
Definition: Muon.h:154
virtual TrackRef globalTrack() const
reference to Track reconstructed in both tracked and muon detector
Definition: Muon.h:54
float pullX(int station, int muonSubdetId, ArbitrationType type=SegmentAndTrackArbitration, bool includeSegmentError=true) const