00001 #include "DataFormats/MuonReco/interface/MuonSelectors.h"
00002 #include "DataFormats/TrackReco/interface/Track.h"
00003
00004 unsigned int muon::RequiredStationMask( const reco::Muon& muon,
00005 double maxChamberDist,
00006 double maxChamberDistPull,
00007 reco::Muon::ArbitrationType arbitrationType )
00008 {
00009 unsigned int theMask = 0;
00010
00011 for(int stationIdx = 1; stationIdx < 5; ++stationIdx)
00012 for(int detectorIdx = 1; detectorIdx < 3; ++detectorIdx)
00013 if(muon.trackDist(stationIdx,detectorIdx,arbitrationType) < maxChamberDist &&
00014 muon.trackDist(stationIdx,detectorIdx,arbitrationType)/muon.trackDistErr(stationIdx,detectorIdx,arbitrationType) < maxChamberDistPull)
00015 theMask += 1<<((stationIdx-1)+4*(detectorIdx-1));
00016
00017 return theMask;
00018 }
00019
00020
00021 float muon::caloCompatibility(const reco::Muon& muon) {
00022 return muon.caloCompatibility();
00023 }
00024
00025
00026 float muon::segmentCompatibility(const reco::Muon& muon) {
00027 bool use_weight_regain_at_chamber_boundary = true;
00028 bool use_match_dist_penalty = true;
00029
00030 int nr_of_stations_crossed = 0;
00031 int nr_of_stations_with_segment = 0;
00032 std::vector<int> stations_w_track(8);
00033 std::vector<int> station_has_segmentmatch(8);
00034 std::vector<int> station_was_crossed(8);
00035 std::vector<float> stations_w_track_at_boundary(8);
00036 std::vector<float> station_weight(8);
00037 int position_in_stations = 0;
00038 float full_weight = 0.;
00039
00040 for(int i = 1; i<=8; ++i) {
00041
00042
00043
00044 if(i<=4) {
00045 if( muon.trackDist(i,1) < 999999 ) {
00046 ++nr_of_stations_crossed;
00047 station_was_crossed[i-1] = 1;
00048 if(muon.trackDist(i,1) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i,1);
00049 else stations_w_track_at_boundary[i-1] = 0.;
00050 }
00051 if( muon.segmentX(i,1) < 999999 ) {
00052 ++nr_of_stations_with_segment;
00053 station_has_segmentmatch[i-1] = 1;
00054 }
00055 }
00056 else {
00057 if( muon.trackDist(i-4,2) < 999999 ) {
00058 ++nr_of_stations_crossed;
00059 station_was_crossed[i-1] = 1;
00060 if(muon.trackDist(i-4,2) > -10. ) stations_w_track_at_boundary[i-1] = muon.trackDist(i-4,2);
00061 else stations_w_track_at_boundary[i-1] = 0.;
00062 }
00063 if( muon.segmentX(i-4,2) < 999999 ) {
00064 ++nr_of_stations_with_segment;
00065 station_has_segmentmatch[i-1] = 1;
00066 }
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 }
00077
00078
00079
00080
00081
00082
00083
00084 const float attenuate_weight_regain = 0.5;
00085
00086 for(int i = 1; i<=8; ++i) {
00087
00088
00089
00090
00091
00092 if( station_was_crossed[i-1] > 0 ) {
00093
00094
00095
00096
00097
00098 ++position_in_stations;
00099
00100 switch ( nr_of_stations_crossed ) {
00101 case 1 :
00102 station_weight[i-1] = 1.;
00103 break;
00104 case 2 :
00105 if ( position_in_stations == 1 ) station_weight[i-1] = 0.33;
00106 else station_weight[i-1] = 0.67;
00107 break;
00108 case 3 :
00109 if ( position_in_stations == 1 ) station_weight[i-1] = 0.23;
00110 else if( position_in_stations == 2 ) station_weight[i-1] = 0.33;
00111 else station_weight[i-1] = 0.44;
00112 break;
00113 case 4 :
00114 if ( position_in_stations == 1 ) station_weight[i-1] = 0.10;
00115 else if( position_in_stations == 2 ) station_weight[i-1] = 0.20;
00116 else if( position_in_stations == 3 ) station_weight[i-1] = 0.30;
00117 else station_weight[i-1] = 0.40;
00118 break;
00119
00120 default :
00121
00122
00123
00124 station_weight[i-1] = 1./nr_of_stations_crossed;
00125 }
00126
00127 if( use_weight_regain_at_chamber_boundary ) {
00128 if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] != 0. ) {
00129
00130
00131
00132 station_weight[i-1] = station_weight[i-1]*attenuate_weight_regain*0.5*(TMath::Erf(stations_w_track_at_boundary[i-1]/6.)+1.);
00133 }
00134 else if(station_has_segmentmatch[i-1] <= 0 && stations_w_track_at_boundary[i-1] == 0.) {
00135
00136 station_weight[i-1] = 0.;
00137 }
00138 }
00139 else {
00140 if(station_has_segmentmatch[i-1] <= 0) station_weight[i-1] = 0.;
00141 }
00142
00143 if( station_has_segmentmatch[i-1] > 0 && 42 == 42 ) {
00144 if(i<=4) {
00145 if( muon.dY(i,1) < 999999 && muon.dX(i,1) < 999999) {
00146 if(
00147 TMath::Sqrt(TMath::Power(muon.pullX(i,1),2.)+TMath::Power(muon.pullY(i,1),2.))> 1. ) {
00148
00149 if(use_match_dist_penalty) {
00150
00151 if(TMath::Sqrt(TMath::Power(muon.dX(i,1),2.)+TMath::Power(muon.dY(i,1),2.)) < 3. && TMath::Sqrt(TMath::Power(muon.pullX(i,1),2.)+TMath::Power(muon.pullY(i,1),2.)) > 3. ) {
00152 station_weight[i-1] *= 1./TMath::Power(
00153 TMath::Max((double)TMath::Sqrt(TMath::Power(muon.dX(i,1),2.)+TMath::Power(muon.dY(i,1),2.)),(double)1.),.25);
00154 }
00155 else {
00156 station_weight[i-1] *= 1./TMath::Power(
00157 TMath::Sqrt(TMath::Power(muon.pullX(i,1),2.)+TMath::Power(muon.pullY(i,1),2.)),.25);
00158 }
00159 }
00160 }
00161 }
00162 else if (muon.dY(i,1) >= 999999) {
00163 if( muon.pullX(i,1) > 1. ) {
00164
00165 if(use_match_dist_penalty) {
00166
00167 if( muon.dX(i,1) < 3. && muon.pullX(i,1) > 3. ) {
00168 station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dX(i,1),(double)1.),.25);
00169 }
00170 else {
00171 station_weight[i-1] *= 1./TMath::Power(muon.pullX(i,1),.25);
00172 }
00173 }
00174 }
00175 }
00176 else {
00177 if( muon.pullY(i,1) > 1. ) {
00178
00179 if(use_match_dist_penalty) {
00180
00181 if( muon.dY(i,1) < 3. && muon.pullY(i,1) > 3. ) {
00182 station_weight[i-1] *= 1./TMath::Power(TMath::Max((double)muon.dY(i,1),(double)1.),.25);
00183 }
00184 else {
00185 station_weight[i-1] *= 1./TMath::Power(muon.pullY(i,1),.25);
00186 }
00187 }
00188 }
00189 }
00190 }
00191 else {
00192 if(
00193 TMath::Sqrt(TMath::Power(muon.pullX(i-4,2),2.)+TMath::Power(muon.pullY(i-4,2),2.)) > 1. ) {
00194
00195 if(use_match_dist_penalty) {
00196
00197 if(TMath::Sqrt(TMath::Power(muon.dX(i-4,2),2.)+TMath::Power(muon.dY(i-4,2),2.)) < 3. && TMath::Sqrt(TMath::Power(muon.pullX(i-4,2),2.)+TMath::Power(muon.pullY(i-4,2),2.)) > 3. ) {
00198 station_weight[i-1] *= 1./TMath::Power(
00199 TMath::Max((double)TMath::Sqrt(TMath::Power(muon.dX(i-4,2),2.)+TMath::Power(muon.dY(i-4,2),2.)),(double)1.),.25);
00200 }
00201 else {
00202 station_weight[i-1] *= 1./TMath::Power(
00203 TMath::Sqrt(TMath::Power(muon.pullX(i-4,2),2.)+TMath::Power(muon.pullY(i-4,2),2.)),.25);
00204 }
00205 }
00206 }
00207 }
00208 }
00209
00210
00211
00212
00213
00214 }
00215 else {
00216 station_weight[i-1] = 0.;
00217 }
00218
00219
00220 full_weight += station_weight[i-1];
00221 }
00222
00223
00224
00225
00226 if( nr_of_stations_crossed == 0 ) {
00227
00228 full_weight = 0.5;
00229 }
00230
00231
00232
00233
00234
00235 return full_weight;
00236
00237 }
00238
00239 bool muon::isGoodMuon( const reco::Muon& muon,
00240 AlgorithmType type,
00241 double minCompatibility ) {
00242 if (!muon.isMatchesValid()) return false;
00243 bool goodMuon = false;
00244
00245 switch( type ) {
00246 case TM2DCompatibility:
00247
00248 if( ( (0.8*caloCompatibility( muon ))+(1.2*segmentCompatibility( muon )) ) > minCompatibility ) goodMuon = true;
00249 else goodMuon = false;
00250 return goodMuon;
00251 break;
00252 default :
00253
00254 goodMuon = false;
00255 return goodMuon;
00256 break;
00257 }
00258 }
00259
00260 bool muon::isGoodMuon( const reco::Muon& muon,
00261 AlgorithmType type,
00262 int minNumberOfMatches,
00263 double maxAbsDx,
00264 double maxAbsPullX,
00265 double maxAbsDy,
00266 double maxAbsPullY,
00267 double maxChamberDist,
00268 double maxChamberDistPull,
00269 reco::Muon::ArbitrationType arbitrationType )
00270 {
00271 if (!muon.isMatchesValid()) return false;
00272 bool goodMuon = false;
00273
00274 if (type == TMLastStation) {
00275
00276
00277 if(minNumberOfMatches == 0) return true;
00278
00279 unsigned int theStationMask = muon.stationMask(arbitrationType);
00280 unsigned int theRequiredStationMask = RequiredStationMask(muon, maxChamberDist, maxChamberDistPull, arbitrationType);
00281
00282
00283 int numSegs = 0;
00284 int numRequiredStations = 0;
00285 for(int it = 0; it < 8; ++it) {
00286 if(theStationMask & 1<<it) ++numSegs;
00287 if(theRequiredStationMask & 1<<it) ++numRequiredStations;
00288 }
00289
00290
00291
00292
00293 if (fabs(muon.eta()) < 1.2) {
00294 if(minNumberOfMatches > numRequiredStations)
00295 minNumberOfMatches = numRequiredStations;
00296 if(minNumberOfMatches < 1)
00297 minNumberOfMatches = 1;
00298 }
00299
00300 if(numSegs >= minNumberOfMatches) goodMuon = 1;
00301
00302
00303
00304
00305
00306 int lastSegBit = 0;
00307 if(theRequiredStationMask) {
00308 for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
00309 if(theRequiredStationMask & 1<<stationIdx)
00310 if(theStationMask & 1<<stationIdx) {
00311 lastSegBit = stationIdx;
00312 goodMuon &= 1;
00313 break;
00314 } else {
00315 goodMuon = false;
00316 break;
00317 }
00318 } else {
00319 for(int stationIdx = 7; stationIdx >= 0; --stationIdx)
00320 if(theStationMask & 1<<stationIdx) {
00321 lastSegBit = stationIdx;
00322 break;
00323 }
00324 }
00325
00326 if(!goodMuon) return false;
00327
00328
00329 int station = 0, detector = 0;
00330 station = lastSegBit < 4 ? lastSegBit+1 : lastSegBit-3;
00331 detector = lastSegBit < 4 ? 1 : 2;
00332
00333
00334 if(fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
00335 fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx)
00336 return false;
00337
00338
00339 if (maxAbsDy < 999999) {
00340
00341
00342 if (detector == 2) {
00343 if(fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
00344 fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy)
00345 return false;
00346 } else {
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 for (int stationIdx = station; stationIdx > 0; --stationIdx) {
00363 if(! (theStationMask & 1<<(stationIdx-1)))
00364 continue;
00365
00366 if(muon.dY(stationIdx,1,arbitrationType) > 999998)
00367 continue;
00368
00369 if(fabs(muon.pullY(stationIdx,1,arbitrationType,1)) > maxAbsPullY &&
00370 fabs(muon.dY(stationIdx,1,arbitrationType)) > maxAbsDy) {
00371 return false;
00372 }
00373
00374
00375 return true;
00376 }
00377 }
00378 }
00379
00380 return goodMuon;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 if (type == TMOneStation) {
00394 unsigned int theStationMask = muon.stationMask(arbitrationType);
00395
00396
00397 if (! theStationMask) return false;
00398
00399 int station = 0, detector = 0;
00400
00401
00402
00403
00404 bool existsGoodDTSegX = false;
00405 bool existsDTSegY = false;
00406
00407
00408
00409 for(int stationIdx = 0; stationIdx <= 7; ++stationIdx)
00410 if(theStationMask & 1<<stationIdx) {
00411 station = stationIdx < 4 ? stationIdx+1 : stationIdx-3;
00412 detector = stationIdx < 4 ? 1 : 2;
00413
00414 if(fabs(muon.pullX(station,detector,arbitrationType,1)) > maxAbsPullX &&
00415 fabs(muon.dX(station,detector,arbitrationType)) > maxAbsDx)
00416 continue;
00417 else if (detector == 1)
00418 existsGoodDTSegX = true;
00419
00420
00421 if (maxAbsDy < 999999) {
00422 if (detector == 2) {
00423 if(fabs(muon.pullY(station,2,arbitrationType,1)) > maxAbsPullY &&
00424 fabs(muon.dY(station,2,arbitrationType)) > maxAbsDy)
00425 continue;
00426 } else {
00427
00428 if(muon.dY(station,1,arbitrationType) > 999998)
00429 continue;
00430 else
00431 existsDTSegY = true;
00432
00433 if(fabs(muon.pullY(station,1,arbitrationType,1)) > maxAbsPullY &&
00434 fabs(muon.dY(station,1,arbitrationType)) > maxAbsDy) {
00435 continue;
00436 }
00437 }
00438 }
00439
00440
00441 return true;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451 if (maxAbsDy < 999999) {
00452 if (existsDTSegY)
00453 return false;
00454 else if (existsGoodDTSegX)
00455 return true;
00456 } else
00457 return false;
00458 }
00459
00460 return goodMuon;
00461 }
00462
00463 bool muon::isGoodMuon( const reco::Muon& muon, reco::Muon::SelectionType type )
00464 {
00465 switch (type)
00466 {
00467 case reco::Muon::All:
00468 return true;
00469 break;
00470 case reco::Muon::AllGlobalMuons:
00471 return muon.isGlobalMuon();
00472 break;
00473 case reco::Muon::AllTrackerMuons:
00474 return muon.isTrackerMuon();
00475 break;
00476 case reco::Muon::AllStandAloneMuons:
00477 return muon.isStandAloneMuon();
00478 break;
00479 case reco::Muon::TrackerMuonArbitrated:
00480 return muon.isTrackerMuon() && muon.numberOfMatches(reco::Muon::SegmentAndTrackArbitration)>0;
00481 break;
00482 case reco::Muon::AllArbitrated:
00483 return ! muon.isTrackerMuon() || muon.numberOfMatches(reco::Muon::SegmentAndTrackArbitration)>0;
00484 break;
00485 case reco::Muon::GlobalMuonPromptTight:
00486 return muon.isGlobalMuon() && muon.globalTrack()->normalizedChi2()<10.;
00487 break;
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 case reco::Muon::TMLastStationLoose:
00499 return isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,reco::Muon::SegmentAndTrackArbitration);
00500 break;
00501 case reco::Muon::TMLastStationTight:
00502 return isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,reco::Muon::SegmentAndTrackArbitration);
00503 break;
00504 case reco::Muon::TMOneStationLoose:
00505 return isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,reco::Muon::SegmentAndTrackArbitration);
00506 break;
00507 case reco::Muon::TMOneStationTight:
00508 return isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,reco::Muon::SegmentAndTrackArbitration);
00509 break;
00510 case reco::Muon::TMLastStationOptimizedLowPtLoose:
00511 if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
00512 return isGoodMuon(muon,TMOneStation,1,3,3,1E9,1E9,1E9,1E9,reco::Muon::SegmentAndTrackArbitration);
00513 else
00514 return isGoodMuon(muon,TMLastStation,2,3,3,1E9,1E9,-3,-3,reco::Muon::SegmentAndTrackArbitration);
00515 break;
00516 case reco::Muon::TMLastStationOptimizedLowPtTight:
00517 if (muon.pt() < 8. && fabs(muon.eta()) < 1.2)
00518 return isGoodMuon(muon,TMOneStation,1,3,3,3,3,1E9,1E9,reco::Muon::SegmentAndTrackArbitration);
00519 else
00520 return isGoodMuon(muon,TMLastStation,2,3,3,3,3,-3,-3,reco::Muon::SegmentAndTrackArbitration);
00521 break;
00522
00523 case reco::Muon::TM2DCompatibilityLoose:
00524 return isGoodMuon(muon,TM2DCompatibility,0.7);
00525 break;
00526
00527 case reco::Muon::TM2DCompatibilityTight:
00528 return isGoodMuon(muon,TM2DCompatibility,1.0);
00529 break;
00530 default:
00531 return false;
00532 }
00533 }