File indexing completed on 2024-09-11 04:32:30
0001 #include "DQM/GEM/plugins/GEMEfficiencyAnalyzer.h"
0002
0003 #include "FWCore/Framework/interface/ConsumesCollector.h"
0004 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
0005 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0006 #include "DataFormats/GeometryCommonDetAlgo/interface/ErrorFrameTransformer.h"
0007 #include "DataFormats/GeometrySurface/interface/SimpleDiskBounds.h"
0008 #include "DataFormats/Math/interface/deltaPhi.h"
0009 #include "Geometry/CommonTopologies/interface/StripTopology.h"
0010 #include "Validation/MuonHits/interface/MuonHitHelper.h"
0011 #include "Validation/MuonGEMHits/interface/GEMValidationUtils.h"
0012
0013 GEMEfficiencyAnalyzer::GEMEfficiencyAnalyzer(const edm::ParameterSet& ps)
0014 : GEMDQMEfficiencySourceBase(ps),
0015 kGEMGeometryTokenBeginRun_(esConsumes<edm::Transition::BeginRun>()),
0016 kTransientTrackBuilderToken_(
0017 esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))),
0018 kGEMRecHitCollectionToken_(consumes<GEMRecHitCollection>(ps.getUntrackedParameter<edm::InputTag>("recHitTag"))),
0019 kMuonViewToken_(consumes<edm::View<reco::Muon> >(ps.getUntrackedParameter<edm::InputTag>("muonTag"))),
0020 kMuonTrackTypeName_(ps.getUntrackedParameter<std::string>("muonTrackType")),
0021 kMuonTrackType_(getMuonTrackType(kMuonTrackTypeName_)),
0022 kMuonName_(TString(ps.getUntrackedParameter<std::string>("muonName"))),
0023 kFolder_(ps.getUntrackedParameter<std::string>("folder")),
0024 kScenario_(getScenarioOption(ps.getUntrackedParameter<std::string>("scenario"))),
0025 kStartingStateType_(getStartingStateType(ps.getUntrackedParameter<std::string>("startingStateType"))),
0026 kMuonSubdetForGEM_({
0027 ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE0"),
0028 ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE11"),
0029 ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE21"),
0030 }),
0031 kCSCForGEM_({
0032 ps.getUntrackedParameter<std::vector<int> >("cscForGE0"),
0033 ps.getUntrackedParameter<std::vector<int> >("cscForGE11"),
0034 ps.getUntrackedParameter<std::vector<int> >("cscForGE21"),
0035 }),
0036 kMuonSegmentMatchDRCut_(static_cast<float>(ps.getUntrackedParameter<double>("muonSegmentMatchDRCut"))),
0037 kMuonPtMinCuts_({
0038 ps.getUntrackedParameter<double>("muonPtMinCutGE0"),
0039 ps.getUntrackedParameter<double>("muonPtMinCutGE11"),
0040 ps.getUntrackedParameter<double>("muonPtMinCutGE21"),
0041 }),
0042 kMuonEtaMinCuts_({
0043 ps.getUntrackedParameter<double>("muonEtaMinCutGE0"),
0044 ps.getUntrackedParameter<double>("muonEtaMinCutGE11"),
0045 ps.getUntrackedParameter<double>("muonEtaMinCutGE21"),
0046 }),
0047 kMuonEtaMaxCuts_({
0048 ps.getUntrackedParameter<double>("muonEtaMaxCutGE0"),
0049 ps.getUntrackedParameter<double>("muonEtaMaxCutGE11"),
0050 ps.getUntrackedParameter<double>("muonEtaMaxCutGE21"),
0051 }),
0052 kPropagationErrorRCut_(static_cast<float>(ps.getUntrackedParameter<double>("propagationErrorRCut"))),
0053 kPropagationErrorPhiCut_(static_cast<float>(ps.getUntrackedParameter<double>("propagationErrorPhiCut"))),
0054 kBoundsErrorScale_(static_cast<float>(ps.getUntrackedParameter<double>("boundsErrorScale"))),
0055 kMatchingMetric_(getMatchingMetric(ps.getUntrackedParameter<std::string>("matchingMetric"))),
0056 kMatchingCut_(static_cast<float>(ps.getUntrackedParameter<double>("matchingCut"))),
0057 kMuonPtBins_(ps.getUntrackedParameter<std::vector<double> >("muonPtBins")),
0058 kMuonEtaNbins_({
0059 ps.getUntrackedParameter<int>("muonEtaNbinsGE0"),
0060 ps.getUntrackedParameter<int>("muonEtaNbinsGE11"),
0061 ps.getUntrackedParameter<int>("muonEtaNbinsGE21"),
0062 }),
0063 kMuonEtaLow_({
0064 ps.getUntrackedParameter<double>("muonEtaLowGE0"),
0065 ps.getUntrackedParameter<double>("muonEtaLowGE11"),
0066 ps.getUntrackedParameter<double>("muonEtaLowGE21"),
0067 }),
0068 kMuonEtaUp_({
0069 ps.getUntrackedParameter<double>("muonEtaUpGE0"),
0070 ps.getUntrackedParameter<double>("muonEtaUpGE11"),
0071 ps.getUntrackedParameter<double>("muonEtaUpGE21"),
0072 }),
0073 kModeDev_(ps.getUntrackedParameter<bool>("modeDev")) {
0074 muon_service_ =
0075 std::make_unique<MuonServiceProxy>(ps.getParameter<edm::ParameterSet>("ServiceParameters"), consumesCollector());
0076 }
0077
0078 GEMEfficiencyAnalyzer::~GEMEfficiencyAnalyzer() {}
0079
0080 void GEMEfficiencyAnalyzer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0081 edm::ParameterSetDescription desc;
0082
0083 desc.addUntracked<edm::InputTag>("ohStatusTag", edm::InputTag("muonGEMDigis", "OHStatus"));
0084 desc.addUntracked<edm::InputTag>("vfatStatusTag", edm::InputTag("muonGEMDigis", "VFATStatus"));
0085 desc.addUntracked<bool>("monitorGE11", true);
0086 desc.addUntracked<bool>("monitorGE21", false);
0087 desc.addUntracked<bool>("monitorGE0", false);
0088 desc.addUntracked<bool>("maskChamberWithError", false);
0089 desc.addUntracked<std::string>("logCategory", "GEMEfficiencyAnalyzer");
0090
0091
0092 desc.addUntracked<edm::InputTag>("recHitTag", edm::InputTag("gemRecHits"));
0093 desc.addUntracked<edm::InputTag>("muonTag", edm::InputTag("muons"));
0094 desc.addUntracked<bool>("modeDev", false);
0095 desc.addUntracked<std::string>("muonTrackType", "OuterTrack");
0096 desc.addUntracked<std::string>("muonName", "STA Muon");
0097 desc.addUntracked<std::string>("folder", "GEM/Efficiency/muonSTA");
0098 desc.addUntracked<std::string>("scenario", "pp");
0099
0100 desc.addUntracked<std::string>("startingStateType", "OutermostMeasurementState");
0101 desc.addUntracked<double>("muonSegmentMatchDRCut", 5.0f);
0102
0103 desc.addUntracked<double>("muonPtMinCutGE0", 20.0f);
0104 desc.addUntracked<double>("muonPtMinCutGE11", 20.0f);
0105 desc.addUntracked<double>("muonPtMinCutGE21", 20.0f);
0106
0107 desc.addUntracked<double>("muonEtaMinCutGE11", 1.5);
0108 desc.addUntracked<double>("muonEtaMaxCutGE11", 2.2);
0109
0110 desc.addUntracked<double>("muonEtaMinCutGE21", 1.5);
0111 desc.addUntracked<double>("muonEtaMaxCutGE21", 2.5);
0112
0113 desc.addUntracked<double>("muonEtaMinCutGE0", 2.0);
0114 desc.addUntracked<double>("muonEtaMaxCutGE0", 3.0);
0115
0116 desc.addUntracked<double>("propagationErrorRCut", 0.5);
0117 desc.addUntracked<double>("propagationErrorPhiCut", 0.2);
0118
0119 desc.addUntracked<double>("boundsErrorScale", -2.0);
0120
0121 desc.addUntracked<std::string>("matchingMetric", "DeltaPhi");
0122 desc.addUntracked<double>("matchingCut", 0.2);
0123
0124 const std::vector<double> default_pt_bins{
0125 0, 5, 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110.};
0126 desc.addUntracked<std::vector<double> >("muonPtBins", default_pt_bins);
0127
0128 desc.addUntracked<int>("muonEtaNbinsGE11", 9);
0129 desc.addUntracked<double>("muonEtaLowGE11", 1.4);
0130 desc.addUntracked<double>("muonEtaUpGE11", 2.3);
0131
0132 desc.addUntracked<int>("muonEtaNbinsGE21", 12);
0133 desc.addUntracked<double>("muonEtaLowGE21", 1.4);
0134 desc.addUntracked<double>("muonEtaUpGE21", 2.6);
0135
0136 desc.addUntracked<int>("muonEtaNbinsGE0", 12);
0137 desc.addUntracked<double>("muonEtaLowGE0", 1.9);
0138 desc.addUntracked<double>("muonEtaUpGE0", 3.1);
0139
0140
0141 desc.addUntracked<std::vector<int> >("muonSubdetForGE0", {});
0142 desc.addUntracked<std::vector<int> >("muonSubdetForGE11", {});
0143 desc.addUntracked<std::vector<int> >("muonSubdetForGE21", {});
0144
0145
0146
0147 desc.addUntracked<std::vector<int> >("cscForGE11", {1, 2});
0148 desc.addUntracked<std::vector<int> >("cscForGE21", {});
0149 desc.addUntracked<std::vector<int> >("cscForGE0", {});
0150
0151
0152
0153 edm::ParameterSetDescription service_parameters;
0154 service_parameters.setAllowAnything();
0155 desc.add<edm::ParameterSetDescription>("ServiceParameters", service_parameters);
0156
0157 descriptions.add("gemEfficiencyAnalyzerDefault", desc);
0158 }
0159
0160
0161 GEMEfficiencyAnalyzer::MatchingMetric GEMEfficiencyAnalyzer::getMatchingMetric(const std::string name) {
0162 MatchingMetric method;
0163
0164 if (name == "DeltaPhi") {
0165 method = MatchingMetric::kDeltaPhi;
0166
0167 } else if (name == "RdPhi") {
0168 method = MatchingMetric::kRdPhi;
0169
0170 } else {
0171 edm::LogError(kLogCategory_) << "received an unexpected MatchingMetric: " << name
0172 << " -> MatchingMetric::kDeltaPhi will be used instead.";
0173 method = MatchingMetric::kDeltaPhi;
0174 }
0175
0176 return method;
0177 }
0178
0179
0180 GEMEfficiencyAnalyzer::StartingStateType GEMEfficiencyAnalyzer::getStartingStateType(const std::string name) {
0181 StartingStateType type;
0182
0183 if (name == "InnermostMeasurementState") {
0184 type = StartingStateType::kInnermostMeasurementState;
0185
0186 } else if (name == "OutermostMeasurementState") {
0187 type = StartingStateType::kOutermostMeasurementState;
0188
0189 } else if (name == "StateOnSurfaceWithCSCSegment") {
0190 type = StartingStateType::kStateOnSurfaceWithCSCSegment;
0191
0192 } else if (name == "AlignmentStyle") {
0193 type = StartingStateType::kAlignmentStyle;
0194
0195 } else {
0196 edm::LogError(kLogCategory_) << "received an unexpected StartingStateType: " << name
0197 << " -> StartingStateType::kOutermostMeasurementState will be used instead.";
0198 type = StartingStateType::kOutermostMeasurementState;
0199 }
0200
0201 return type;
0202 }
0203
0204
0205 reco::Muon::MuonTrackType GEMEfficiencyAnalyzer::getMuonTrackType(const std::string name) {
0206 reco::Muon::MuonTrackType muon_track_type;
0207
0208
0209 if (name == "InnerTrack") {
0210 muon_track_type = reco::Muon::MuonTrackType::InnerTrack;
0211
0212 } else if (name == "OuterTrack") {
0213 muon_track_type = reco::Muon::MuonTrackType::OuterTrack;
0214
0215 } else if (name == "CombinedTrack") {
0216 muon_track_type = reco::Muon::MuonTrackType::CombinedTrack;
0217
0218 } else {
0219 edm::LogError(kLogCategory_) << "received an unexpected reco::Muon::MuonTrackType: " << name
0220 << " --> OuterTrack will be used instead.";
0221
0222 muon_track_type = reco::Muon::MuonTrackType::OuterTrack;
0223 }
0224
0225 return muon_track_type;
0226 }
0227
0228 GEMEfficiencyAnalyzer::ScenarioOption GEMEfficiencyAnalyzer::getScenarioOption(const std::string name) {
0229 ScenarioOption scenario;
0230 if (name == "pp") {
0231 scenario = ScenarioOption::kPP;
0232
0233 } else if (name == "cosmics") {
0234 scenario = ScenarioOption::kCosmics;
0235
0236 } else if (name == "HeavyIons") {
0237 scenario = ScenarioOption::kHeavyIons;
0238
0239 edm::LogInfo(kLogCategory_) << "The scenario is set to \"HeavyIons\""
0240 << " but there is no strategy dedicated to"
0241 << "\"HeavyIons\" scenario. The strategy for "
0242 << "the \"pp\" scenario will be used insteqad.";
0243
0244 } else {
0245 scenario = ScenarioOption::kPP;
0246
0247 edm::LogError(kLogCategory_) << "received an unexpected ScenarioOption: " << name
0248 << ". Choose from (\"pp\", \"cosmics\", \"HeavyIons\")"
0249 << " --> pp will be used instead.";
0250 }
0251
0252 return scenario;
0253 }
0254
0255 void GEMEfficiencyAnalyzer::bookHistograms(DQMStore::IBooker& ibooker, edm::Run const&, edm::EventSetup const& setup) {
0256 ibooker.setCurrentFolder(kFolder_);
0257
0258 const GEMGeometry* gem = nullptr;
0259 if (auto handle = setup.getHandle(kGEMGeometryTokenBeginRun_)) {
0260 gem = handle.product();
0261 } else {
0262 edm::LogError(kLogCategory_ + "|bookHistograms") << "failed to get GEMGeometry";
0263 return;
0264 }
0265
0266 for (const GEMStation* station : gem->stations()) {
0267 const int region_id = station->region();
0268 const int station_id = station->station();
0269
0270 if (skipGEMStation(station_id)) {
0271 continue;
0272 }
0273
0274
0275
0276
0277 {
0278 const GEMDetId key = getReStKey(region_id, station_id);
0279 const TString suffix = GEMUtils::getSuffixName(region_id, station_id);
0280 const TString title = kMuonName_ + GEMUtils::getSuffixTitle(region_id, station_id);
0281
0282
0283 TH1F* h_muon_pt = new TH1F("muon_pt" + suffix, title, kMuonPtBins_.size() - 1, &kMuonPtBins_[0]);
0284 me_muon_pt_[key] = ibooker.book1D(h_muon_pt->GetName(), h_muon_pt);
0285 me_muon_pt_[key]->setAxisTitle("Muon p_{T} [GeV]", 1);
0286 me_muon_pt_matched_[key] = bookNumerator1D(ibooker, me_muon_pt_[key]);
0287
0288
0289 me_muon_eta_[key] = ibooker.book1D("muon_eta" + suffix,
0290 title,
0291 kMuonEtaNbins_.at(station_id),
0292 kMuonEtaLow_.at(station_id),
0293 kMuonEtaUp_.at(station_id));
0294 me_muon_eta_[key]->setAxisTitle("Muon |#eta|", 1);
0295 me_muon_eta_matched_[key] = bookNumerator1D(ibooker, me_muon_eta_[key]);
0296
0297
0298 me_muon_phi_[key] = ibooker.book1D("muon_phi" + suffix, title, 36, -180, 180);
0299 me_muon_phi_[key]->setAxisTitle("Muon #phi [deg]");
0300 me_muon_phi_matched_[key] = bookNumerator1D(ibooker, me_muon_phi_[key]);
0301
0302 if (kModeDev_) {
0303
0304 TH1F* h_muon_pt_all = new TH1F("muon_pt_all" + suffix, title, kMuonPtBins_.size() - 1, &kMuonPtBins_[0]);
0305 me_muon_pt_all_[key] = ibooker.book1D(h_muon_pt_all->GetName(), h_muon_pt_all);
0306 me_muon_pt_all_[key]->setAxisTitle("Muon p_{T} [GeV]", 1);
0307 me_muon_pt_all_matched_[key] = bookNumerator1D(ibooker, me_muon_pt_all_[key]);
0308
0309 me_muon_eta_all_[key] = ibooker.book1D("muon_eta_all" + suffix,
0310 title,
0311 kMuonEtaNbins_.at(station_id),
0312 kMuonEtaLow_.at(station_id),
0313 kMuonEtaUp_.at(station_id));
0314 me_muon_eta_all_[key]->setAxisTitle("Muon |#eta|", 1);
0315 me_muon_eta_all_matched_[key] = bookNumerator1D(ibooker, me_muon_eta_all_[key]);
0316
0317 me_muon_charge_[key] = ibooker.book1D("muon_charge" + suffix, title, 3, -1.5, 1.5);
0318 me_muon_charge_[key]->setAxisTitle("Muon charge", 1);
0319 me_muon_charge_matched_[key] = bookNumerator1D(ibooker, me_muon_charge_[key]);
0320 }
0321 }
0322
0323
0324
0325
0326 const std::vector<const GEMSuperChamber*> superchamber_vec = station->superChambers();
0327 if (not checkRefs(superchamber_vec)) {
0328 edm::LogError(kLogCategory_) << "got an invalid ptr from GEMStation::superChambers";
0329 return;
0330 }
0331
0332 const std::vector<const GEMChamber*> chamber_vec = superchamber_vec.front()->chambers();
0333 if (not checkRefs(chamber_vec)) {
0334 edm::LogError(kLogCategory_) << "got an invalid ptr from GEMSuperChamber::chambers";
0335 return;
0336 }
0337
0338
0339 for (const GEMChamber* chamber : chamber_vec) {
0340 const int layer_id = chamber->id().layer();
0341
0342 {
0343 const GEMDetId key = getReStLaKey(chamber->id());
0344 const TString suffix = GEMUtils::getSuffixName(region_id, station_id, layer_id);
0345 const TString title = kMuonName_ + GEMUtils::getSuffixTitle(region_id, station_id, layer_id);
0346
0347 me_chamber_ieta_[key] = bookChamberEtaPartition(ibooker, "chamber_ieta" + suffix, title, station);
0348 me_chamber_ieta_matched_[key] = bookNumerator2D(ibooker, me_chamber_ieta_[key]);
0349
0350 if (kModeDev_) {
0351 me_prop_path_length_[key] = ibooker.book1D("prop_path_length" + suffix, title, 50, 0.0, 5.0);
0352 me_prop_path_length_[key]->setAxisTitle("Propagation path length [cm]", 1);
0353 me_prop_path_length_matched_[key] = bookNumerator1D(ibooker, me_prop_path_length_[key]);
0354
0355
0356 me_prop_err_r_[key] = ibooker.book1D("prop_err_r" + suffix, title, 60, 0.0, 3.0);
0357 me_prop_err_r_[key]->setAxisTitle("Propagation global #sigma_{R} [cm]", 1);
0358 me_prop_err_r_matched_[key] = bookNumerator1D(ibooker, me_prop_err_r_[key]);
0359
0360
0361 me_prop_err_phi_[key] = ibooker.book1D("prop_err_phi" + suffix, title, 50, 0.0, 1.0);
0362 me_prop_err_phi_[key]->setAxisTitle("Propagation's global #sigma_{#phi} [deg]", 1);
0363 me_prop_err_phi_matched_[key] = bookNumerator1D(ibooker, me_prop_err_phi_[key]);
0364
0365
0366 me_cutflow_[key] = ibooker.book1D("cutflow" + suffix, title, 5, 0.5, 5.5);
0367 me_cutflow_[key]->setBinLabel(1, "All");
0368 me_cutflow_[key]->setBinLabel(2, Form("#sigma_{R} < %.3f cm", kPropagationErrorRCut_));
0369 me_cutflow_[key]->setBinLabel(3, Form("#sigma_{phi} < %.3f deg", kPropagationErrorPhiCut_));
0370 me_cutflow_[key]->setBinLabel(4, Form("p_{T} > %.1f GeV", kMuonPtMinCuts_.at(station_id)));
0371 me_cutflow_[key]->setBinLabel(
0372 5, Form("%.2f < |#eta| < %.2f", kMuonEtaMinCuts_.at(station_id), kMuonEtaMaxCuts_.at(station_id)));
0373
0374 me_cutflow_matched_[key] = bookNumerator1D(ibooker, me_cutflow_.at(key));
0375 }
0376 }
0377 }
0378
0379
0380
0381
0382 const std::vector<const GEMEtaPartition*> eta_partition_vec = chamber_vec.front()->etaPartitions();
0383 if (not checkRefs(eta_partition_vec)) {
0384 edm::LogError(kLogCategory_) << "got an invalid ptr from GEMChamber::etaPartitions";
0385 continue;
0386 }
0387
0388 for (const GEMEtaPartition* eta_partition : eta_partition_vec) {
0389 const int ieta = eta_partition->id().ieta();
0390
0391 {
0392 const GEMDetId key = getReStEtKey(eta_partition->id());
0393 const TString gem_label = TString::Format("GE%d1-%c-E%d", station_id, (region_id > 0 ? 'P' : 'M'), ieta);
0394 const TString suffix = "_" + gem_label;
0395 const TString title = kMuonName_ + " " + gem_label;
0396
0397
0398 const float dphi_up = (kMatchingMetric_ == MatchingMetric::kDeltaPhi) ? kMatchingCut_
0399 : (kScenario_ == ScenarioOption::kCosmics) ? 1.0
0400 : 0.2;
0401 me_residual_phi_[key] = ibooker.book1D("residual_phi" + suffix, title, 41, -dphi_up, dphi_up);
0402 me_residual_phi_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
0403
0404 if (kModeDev_) {
0405
0406 std::string matching_metric_x_title;
0407 if (kMatchingMetric_ == MatchingMetric::kDeltaPhi) {
0408 matching_metric_x_title = "#Delta#phi [deg]";
0409
0410 } else if (kMatchingMetric_ == MatchingMetric::kRdPhi) {
0411 matching_metric_x_title = "R#Delta#phi [cm]";
0412
0413 } else {
0414 matching_metric_x_title = "UNKNOWN METRIC";
0415 }
0416
0417
0418 me_matching_metric_all_[key] =
0419 ibooker.book1D("matching_metric_all" + suffix, title, 101, -3 * kMatchingCut_, 3 * kMatchingCut_);
0420 me_matching_metric_all_[key]->setAxisTitle(matching_metric_x_title, 1);
0421
0422
0423 me_matching_metric_[key] =
0424 ibooker.book1D("matching_metric" + suffix, title, 101, -kMatchingCut_, kMatchingCut_);
0425 me_matching_metric_[key]->setAxisTitle(matching_metric_x_title, 1);
0426
0427
0428 me_residual_phi_muon_[key] =
0429 ibooker.book1D("residual_phi_muon" + suffix, title + " (#mu, q < 0)", 50, -0.5, 0.5);
0430 me_residual_phi_muon_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
0431 me_residual_phi_muon_[key]->setAxisTitle("Number of muons", 2);
0432
0433
0434 me_residual_phi_antimuon_[key] =
0435 ibooker.book1D("residual_phi_antimuon" + suffix, title + " (#tilde{#mu}, q > 0)", 50, -0.5, 0.5);
0436 me_residual_phi_antimuon_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
0437 me_residual_phi_antimuon_[key]->setAxisTitle("Number of anti-muons", 2);
0438
0439
0440 me_residual_x_[key] = ibooker.book1D("residual_x" + suffix, title, 60, -1.5, 1.5);
0441 me_residual_x_[key]->setAxisTitle("Residual in local X [cm]", 1);
0442
0443
0444 me_residual_y_[key] = ibooker.book1D("residual_y" + suffix, title, 48, -12.0, 12.0);
0445 me_residual_y_[key]->setAxisTitle("Residual in local Y [cm]", 1);
0446
0447
0448 me_residual_strip_[key] = ibooker.book1D("residual_strip" + suffix, title, 21, -10.0, 10.0);
0449 me_residual_strip_[key]->setAxisTitle("propagation strip - hit strip", 1);
0450 }
0451 }
0452 }
0453 }
0454 }
0455
0456
0457 bool GEMEfficiencyAnalyzer::isInsideOut(const reco::Track& track) {
0458 return track.innerPosition().mag2() > track.outerPosition().mag2();
0459 }
0460
0461
0462 void GEMEfficiencyAnalyzer::buildGEMLayers(const GEMGeometry* gem) {
0463 std::map<GEMDetId, std::vector<const GEMChamber*> > chambers_per_layer;
0464
0465 for (const GEMStation* station : gem->stations()) {
0466 const int region_id = station->region();
0467 const int station_id = station->station();
0468 const bool is_ge11 = station_id == 1;
0469
0470 if (skipGEMStation(station_id)) {
0471 continue;
0472 }
0473
0474 for (const GEMSuperChamber* superchamber : station->superChambers()) {
0475
0476
0477 const int chamber_id = is_ge11 ? superchamber->id().chamber() % 2 : 0;
0478
0479 for (const GEMChamber* chamber : superchamber->chambers()) {
0480 const int layer_id = chamber->id().layer();
0481
0482 const GEMDetId key{region_id, 1, station_id, layer_id, chamber_id, 0};
0483
0484 if (chambers_per_layer.find(key) == chambers_per_layer.end()) {
0485 chambers_per_layer.insert({key, std::vector<const GEMChamber*>()});
0486 }
0487 chambers_per_layer.at(key).push_back(chamber);
0488 }
0489 }
0490 }
0491
0492 gem_layers_.reserve(chambers_per_layer.size());
0493 for (auto [gem_id, chambers] : chambers_per_layer) {
0494
0495 const float z_origin = chambers.front()->position().z();
0496 Surface::PositionType position{0.f, 0.f, z_origin};
0497 Surface::RotationType rotation;
0498
0499
0500
0501 auto [r_min, r_max] = chambers.front()->surface().rSpan();
0502 auto [z_min, z_max] = chambers.front()->surface().zSpan();
0503
0504 z_min -= z_origin;
0505 z_max -= z_origin;
0506
0507
0508 SimpleDiskBounds* bounds = new SimpleDiskBounds(r_min, r_max, z_min, z_max);
0509 const Disk::DiskPointer layer = Disk::build(position, rotation, bounds);
0510
0511 gem_layers_.emplace_back(layer, chambers, gem_id);
0512
0513 LogDebug(kLogCategory_) << gem_id
0514 << Form(" ==> (z_origin, z_min, z_max) = (%.2f, %.2f, %.2f)", z_origin, z_min, z_max);
0515 }
0516 }
0517
0518
0519
0520 bool GEMEfficiencyAnalyzer::checkPropagationDirection(const reco::Track* track, const GEMLayer& layer) {
0521 const bool is_same_region = track->eta() * layer.id.region() > 0;
0522
0523 bool skip = false;
0524 if (kScenario_ == ScenarioOption::kCosmics) {
0525 float p2_in = track->innerMomentum().mag2();
0526 float p2_out = track->outerMomentum().mag2();
0527 if (isInsideOut(*track))
0528 std::swap(p2_in, p2_out);
0529 const bool is_outgoing = p2_in > p2_out;
0530
0531 skip = (is_outgoing xor is_same_region);
0532
0533 } else {
0534
0535 skip = not is_same_region;
0536 }
0537
0538 return skip;
0539 }
0540
0541 GEMEfficiencyAnalyzer::StartingState GEMEfficiencyAnalyzer::buildStartingState(
0542 const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
0543 bool found = false;
0544 TrajectoryStateOnSurface state;
0545 DetId det_id;
0546
0547 switch (kStartingStateType_) {
0548 case StartingStateType::kOutermostMeasurementState: {
0549 std::tie(found, state, det_id) = getOutermostMeasurementState(transient_track);
0550 break;
0551 }
0552 case StartingStateType::kInnermostMeasurementState: {
0553 std::tie(found, state, det_id) = getInnermostMeasurementState(transient_track);
0554 break;
0555 }
0556 case StartingStateType::kStateOnSurfaceWithCSCSegment: {
0557 std::tie(found, state, det_id) = buildStateOnSurfaceWithCSCSegment(muon, transient_track, gem_layer);
0558 break;
0559 }
0560 case StartingStateType::kAlignmentStyle: {
0561 std::tie(found, state, det_id) = buildStartingStateAlignmentStyle(muon, transient_track, gem_layer);
0562 break;
0563 }
0564 default: {
0565 edm::LogError(kLogCategory_) << "got an unexpected StartingStateType";
0566 break;
0567 }
0568 }
0569
0570 found &= state.isValid();
0571
0572 if (found and (det_id.det() == DetId::Detector::Muon)) {
0573 found &= isMuonSubdetAllowed(det_id, gem_layer.id.station());
0574 }
0575
0576 if (found) {
0577 if (MuonHitHelper::isGEM(det_id)) {
0578 const GEMDetId start_id{det_id};
0579
0580 const bool are_same_region = gem_layer.id.region() == start_id.region();
0581 const bool are_same_station = gem_layer.id.station() == start_id.station();
0582 const bool are_same_layer = gem_layer.id.layer() == start_id.layer();
0583 if (are_same_region and are_same_station and are_same_layer) {
0584 LogDebug(kLogCategory_)
0585 << "The starting detector of the muon propagation is same with the destination. Skip this propagation.";
0586 found = false;
0587 }
0588 }
0589 }
0590
0591 return std::make_tuple(found, state, det_id);
0592 }
0593
0594
0595
0596
0597
0598
0599
0600 GEMEfficiencyAnalyzer::StartingState GEMEfficiencyAnalyzer::getInnermostMeasurementState(
0601 const reco::TransientTrack& transient_track) {
0602 TrajectoryStateOnSurface state;
0603 DetId det_id;
0604
0605 const reco::Track& track = transient_track.track();
0606
0607 if (isInsideOut(track)) {
0608 state = transient_track.outermostMeasurementState();
0609 det_id = track.outerDetId();
0610
0611 } else {
0612 state = transient_track.innermostMeasurementState();
0613 det_id = track.innerDetId();
0614 }
0615
0616 return std::make_tuple(true, state, det_id);
0617 }
0618
0619
0620 GEMEfficiencyAnalyzer::StartingState GEMEfficiencyAnalyzer::getOutermostMeasurementState(
0621 const reco::TransientTrack& transient_track) {
0622 const reco::Track& track = transient_track.track();
0623
0624 TrajectoryStateOnSurface state;
0625 DetId det_id;
0626
0627
0628 if (isInsideOut(track)) {
0629 state = transient_track.innermostMeasurementState();
0630 det_id = track.innerDetId();
0631
0632 } else {
0633 state = transient_track.outermostMeasurementState();
0634 det_id = track.outerDetId();
0635 }
0636
0637 return std::make_tuple(true, state, det_id);
0638 }
0639
0640
0641
0642
0643
0644 GEMEfficiencyAnalyzer::StartingState GEMEfficiencyAnalyzer::buildStateOnSurfaceWithCSCSegment(
0645 const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
0646 bool found = false;
0647 TrajectoryStateOnSurface state;
0648 DetId det_id;
0649
0650 if (const CSCSegment* csc_segment = findCSCSegment(muon, transient_track, gem_layer)) {
0651 const GeomDet* det = muon_service_->trackingGeometry()->idToDet(csc_segment->cscDetId());
0652 const GlobalPoint global_position = det->toGlobal(csc_segment->localPosition());
0653
0654 found = true;
0655 state = transient_track.stateOnSurface(global_position);
0656 det_id = csc_segment->geographicalId();
0657 }
0658
0659 return std::make_tuple(found, state, det_id);
0660 }
0661
0662
0663
0664
0665
0666
0667 GEMEfficiencyAnalyzer::StartingState GEMEfficiencyAnalyzer::buildStartingStateAlignmentStyle(
0668 const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
0669 bool found = false;
0670 TrajectoryStateOnSurface state;
0671 DetId det_id;
0672
0673 if (const CSCSegment* csc_segment = findCSCSegment(muon, transient_track, gem_layer)) {
0674 found = true;
0675 det_id = csc_segment->geographicalId();
0676
0677
0678 const LocalPoint position = csc_segment->localPosition();
0679
0680 const reco::TrackRef inner_track = muon.innerTrack();
0681 const float momentum_magnitude = inner_track.isNonnull() ? inner_track.get()->outerP() : 1.0f;
0682 const LocalVector momentum = momentum_magnitude * csc_segment->localDirection();
0683
0684
0685 const LocalTrajectoryParameters trajectory_parameters{position, momentum, muon.charge()};
0686
0687
0688 const LocalTrajectoryError trajectory_error =
0689 asSMatrix<5>(csc_segment->parametersError().similarityT(csc_segment->projectionMatrix()));
0690
0691
0692 const Plane& surface = muon_service_->trackingGeometry()->idToDet(det_id)->surface();
0693
0694 state =
0695 TrajectoryStateOnSurface{trajectory_parameters, trajectory_error, surface, &*muon_service_->magneticField()};
0696 }
0697
0698 return std::make_tuple(found, state, det_id);
0699 }
0700
0701
0702
0703 const CSCSegment* GEMEfficiencyAnalyzer::findCSCSegmentBeam(const reco::TransientTrack& transient_track,
0704 const GEMLayer& gem_layer) {
0705 const CSCSegment* best_csc_segment = nullptr;
0706 double min_z_distance = std::numeric_limits<double>::infinity();
0707
0708 for (trackingRecHit_iterator tracking_rechit_iter = transient_track.recHitsBegin();
0709 tracking_rechit_iter != transient_track.recHitsEnd();
0710 tracking_rechit_iter++) {
0711 const TrackingRecHit* tracking_rechit = *tracking_rechit_iter;
0712 if (not tracking_rechit->isValid()) {
0713 LogDebug(kLogCategory_) << "got an invalid trackingRecHit_iterator from transient_track. skip it.";
0714 continue;
0715 }
0716
0717 const DetId det_id = tracking_rechit->geographicalId();
0718 if (not MuonHitHelper::isCSC(det_id)) {
0719 continue;
0720 }
0721
0722 if (tracking_rechit->dimension() != kCSCSegmentDimension_) {
0723 continue;
0724 }
0725
0726 const CSCDetId csc_id{det_id};
0727 if (not isCSCAllowed(csc_id, gem_layer.id.station())) {
0728 continue;
0729 }
0730
0731 if (auto csc_segment = dynamic_cast<const CSCSegment*>(tracking_rechit)) {
0732 const GeomDet* det = muon_service_->trackingGeometry()->idToDet(csc_id);
0733 if (det == nullptr) {
0734 edm::LogError(kLogCategory_) << "GlobalTrackingGeometry::idToDet returns nullptr; CSCDetId=" << csc_id;
0735 continue;
0736 }
0737 const GlobalPoint global_position = det->toGlobal(csc_segment->localPosition());
0738 const float z_distance = std::abs(gem_layer.disk->localZclamped(global_position));
0739
0740 if (z_distance < min_z_distance) {
0741 best_csc_segment = csc_segment;
0742 min_z_distance = z_distance;
0743 }
0744
0745 } else {
0746 edm::LogError(kLogCategory_)
0747 << "failed to perform the conversion from `const TrackingRechit*` to `const CSCSegment*`";
0748 }
0749 }
0750
0751 return best_csc_segment;
0752 }
0753
0754 const CSCSegment* GEMEfficiencyAnalyzer::findCSCSegmentCosmics(const reco::Muon& muon, const GEMLayer& gem_layer) {
0755 const CSCSegment* best_csc_segment = nullptr;
0756
0757 for (const reco::MuonChamberMatch& chamber_match : muon.matches()) {
0758 if (not MuonHitHelper::isCSC(chamber_match.id)) {
0759 continue;
0760 }
0761
0762 const CSCDetId csc_id{chamber_match.id};
0763 if (not isCSCAllowed(csc_id, gem_layer.id.station())) {
0764 continue;
0765 }
0766
0767 const float x_track = chamber_match.x;
0768 const float y_track = chamber_match.y;
0769
0770 for (const reco::MuonSegmentMatch& segment_match : chamber_match.segmentMatches) {
0771 if (not segment_match.isMask(reco::MuonSegmentMatch::BestInStationByDR)) {
0772 continue;
0773 }
0774
0775 const float dr = std::hypot(x_track - segment_match.x, y_track - segment_match.y);
0776 std::cout << kLogCategory_ << ": dr=" << dr << std::endl;
0777
0778 if (dr > kMuonSegmentMatchDRCut_) {
0779 LogDebug(kLogCategory_) << "too large dR(muon, segment)";
0780 break;
0781 }
0782
0783 if (segment_match.cscSegmentRef.isNonnull()) {
0784 best_csc_segment = segment_match.cscSegmentRef.get();
0785 }
0786 }
0787 }
0788
0789 return best_csc_segment;
0790 }
0791
0792
0793 const CSCSegment* GEMEfficiencyAnalyzer::findCSCSegment(const reco::Muon& muon,
0794 const reco::TransientTrack& transient_track,
0795 const GEMLayer& gem_layer) {
0796 if (kScenario_ == ScenarioOption::kCosmics) {
0797 return findCSCSegmentCosmics(muon, gem_layer);
0798 } else {
0799
0800 return findCSCSegmentBeam(transient_track, gem_layer);
0801 }
0802 }
0803
0804 bool GEMEfficiencyAnalyzer::isMuonSubdetAllowed(const DetId& det_id, const int gem_station) {
0805 if ((gem_station < 0) or (gem_station > 2)) {
0806 edm::LogError(kLogCategory_) << "got unexpected gem station " << gem_station;
0807 return false;
0808 }
0809
0810 if (det_id.det() != DetId::Detector::Muon) {
0811 edm::LogError(kLogCategory_) << Form(
0812 "(Detector, Subdetector) = (%d, %d)", static_cast<int>(det_id.det()), det_id.subdetId());
0813 return false;
0814 }
0815
0816 const std::vector<int> allowed = kMuonSubdetForGEM_.at(gem_station);
0817 return allowed.empty() or (std::find(allowed.begin(), allowed.end(), det_id.subdetId()) != allowed.end());
0818 }
0819
0820
0821
0822
0823
0824
0825 bool GEMEfficiencyAnalyzer::isCSCAllowed(const CSCDetId& csc_id, const int gem_station) {
0826 if ((gem_station < 0) or (gem_station > 2)) {
0827 edm::LogError(kLogCategory_) << "got unexpected gem station " << gem_station;
0828 return false;
0829 }
0830
0831
0832 const int csc_chamber_type = static_cast<int>(csc_id.iChamberType());
0833
0834 const std::vector<int> allowed = kCSCForGEM_.at(gem_station);
0835 return allowed.empty() or (std::find(allowed.begin(), allowed.end(), csc_chamber_type) != allowed.end());
0836 }
0837
0838 bool GEMEfficiencyAnalyzer::checkBounds(const Plane& plane, const GlobalPoint& global_point) {
0839 const LocalPoint local_point = plane.toLocal(global_point);
0840 const LocalPoint local_point_2d(local_point.x(), local_point.y(), 0.0f);
0841 return plane.bounds().inside(local_point_2d);
0842 }
0843
0844
0845
0846 bool GEMEfficiencyAnalyzer::checkBounds(const Plane& plane,
0847 const GlobalPoint& global_point,
0848 const GlobalError& global_error,
0849 const float scale) {
0850 const LocalPoint local_point = plane.toLocal(global_point);
0851 const LocalError local_error = ErrorFrameTransformer::transform(global_error, plane);
0852
0853 const LocalPoint local_point_2d{local_point.x(), local_point.y(), 0.0f};
0854 return plane.bounds().inside(local_point_2d, local_error, scale);
0855 }
0856
0857 const GEMEtaPartition* GEMEfficiencyAnalyzer::findEtaPartition(const GlobalPoint& global_point,
0858 const GlobalError& global_error,
0859 const std::vector<const GEMChamber*>& chamber_vector) {
0860 const GEMEtaPartition* bound = nullptr;
0861 for (const GEMChamber* chamber : chamber_vector) {
0862 if (not checkBounds(chamber->surface(), global_point, global_error, kBoundsErrorScale_)) {
0863 continue;
0864 }
0865
0866 for (const GEMEtaPartition* eta_partition : chamber->etaPartitions()) {
0867 if (checkBounds(eta_partition->surface(), global_point, global_error, kBoundsErrorScale_)) {
0868 bound = eta_partition;
0869 break;
0870 }
0871 }
0872 }
0873
0874 return bound;
0875 }
0876
0877
0878 float GEMEfficiencyAnalyzer::computeRdPhi(const GlobalPoint& prop_global_pos,
0879 const LocalPoint& hit_local_pos,
0880 const GEMEtaPartition* eta_partition) {
0881 const StripTopology& topology = eta_partition->specificTopology();
0882 const LocalPoint prop_local_pos = eta_partition->toLocal(prop_global_pos);
0883
0884 const float dx = prop_local_pos.x() - hit_local_pos.x();
0885 const float dy = prop_local_pos.y() - hit_local_pos.y();
0886 const float hit_strip = eta_partition->strip(hit_local_pos);
0887 const float hit_phi = topology.stripAngle(hit_strip);
0888 const float rdphi = std::cos(hit_phi) * dx - std::sin(hit_phi) * dy;
0889 return rdphi;
0890 }
0891
0892
0893 float GEMEfficiencyAnalyzer::computeDeltaPhi(const GlobalPoint& prop_global_pos,
0894 const LocalPoint& hit_local_pos,
0895 const GEMEtaPartition* eta_partition) {
0896 const GlobalPoint hit_global_pos = eta_partition->toGlobal(hit_local_pos);
0897 const float dphi = Geom::convertRadToDeg(prop_global_pos.phi() - hit_global_pos.phi());
0898 return dphi;
0899 }
0900
0901
0902 float GEMEfficiencyAnalyzer::computeMatchingMetric(const GlobalPoint& prop_global_pos,
0903 const LocalPoint& hit_local_pos,
0904 const GEMEtaPartition* eta_partition) {
0905 float metric;
0906 switch (kMatchingMetric_) {
0907 case MatchingMetric::kDeltaPhi: {
0908 metric = computeDeltaPhi(prop_global_pos, hit_local_pos, eta_partition);
0909 break;
0910 }
0911 case MatchingMetric::kRdPhi: {
0912 metric = computeRdPhi(prop_global_pos, hit_local_pos, eta_partition);
0913 break;
0914 }
0915 default: {
0916 edm::LogError(kLogCategory_) << "unknown MatchingMetric.";
0917 metric = std::numeric_limits<float>::infinity();
0918 }
0919 }
0920
0921 return metric;
0922 }
0923
0924
0925
0926
0927
0928 std::pair<const GEMRecHit*, float> GEMEfficiencyAnalyzer::findClosestHit(const GlobalPoint& prop_global_pos,
0929 const GEMRecHitCollection::range& rechit_range,
0930 const GEMEtaPartition* eta_partition) {
0931 const GEMRecHit* closest_hit = nullptr;
0932 float min_metric = std::numeric_limits<float>::infinity();
0933
0934 for (auto hit = rechit_range.first; hit != rechit_range.second; ++hit) {
0935 const LocalPoint hit_local_pos = hit->localPosition();
0936
0937 const float metric = computeMatchingMetric(prop_global_pos, hit_local_pos, eta_partition);
0938
0939 if (std::abs(metric) < std::abs(min_metric)) {
0940 min_metric = metric;
0941 closest_hit = &(*hit);
0942 }
0943 }
0944
0945 return std::make_pair(closest_hit, min_metric);
0946 }
0947
0948 void GEMEfficiencyAnalyzer::dqmBeginRun(edm::Run const&, edm::EventSetup const& setup) {
0949 const GEMGeometry* gem = nullptr;
0950 if (auto handle = setup.getHandle(kGEMGeometryTokenBeginRun_)) {
0951 gem = handle.product();
0952 } else {
0953 edm::LogError(kLogCategory_ + "|dqmBeginRun") << "failed to get GEMGeometry";
0954 return;
0955 }
0956
0957 buildGEMLayers(gem);
0958 }
0959
0960 void GEMEfficiencyAnalyzer::analyze(const edm::Event& event, const edm::EventSetup& setup) {
0961
0962
0963
0964 const GEMRecHitCollection* rechit_collection = nullptr;
0965 if (auto handle = event.getHandle(kGEMRecHitCollectionToken_)) {
0966 rechit_collection = handle.product();
0967 } else {
0968 edm::LogError(kLogCategory_) << "failed to get GEMRecHitCollection";
0969 return;
0970 }
0971
0972 const edm::View<reco::Muon>* muon_view = nullptr;
0973 if (auto handle = event.getHandle(kMuonViewToken_)) {
0974 muon_view = handle.product();
0975 } else {
0976 edm::LogError(kLogCategory_) << "failed to get View<Muon>";
0977 return;
0978 }
0979
0980 const GEMOHStatusCollection* oh_status_collection = nullptr;
0981 const GEMVFATStatusCollection* vfat_status_collection = nullptr;
0982 if (kMaskChamberWithError_) {
0983 if (auto handle = event.getHandle(kGEMOHStatusCollectionToken_)) {
0984 oh_status_collection = handle.product();
0985 } else {
0986 edm::LogError(kLogCategory_) << "failed to get OHVFATStatusCollection";
0987 return;
0988 }
0989
0990 if (auto handle = event.getHandle(kGEMVFATStatusCollectionToken_)) {
0991 vfat_status_collection = handle.product();
0992 } else {
0993 edm::LogError(kLogCategory_) << "failed to get GEMVFATStatusCollection";
0994 return;
0995 }
0996 }
0997
0998
0999
1000
1001 const TransientTrackBuilder* transient_track_builder = nullptr;
1002 if (auto handle = setup.getHandle(kTransientTrackBuilderToken_)) {
1003 transient_track_builder = handle.product();
1004 } else {
1005 edm::LogError(kLogCategory_) << "failed to get TransientTrackBuilder";
1006 return;
1007 }
1008
1009
1010
1011
1012 muon_service_->update(setup);
1013
1014
1015 const Propagator* propagator = nullptr;
1016 if (auto handle = muon_service_->propagator("SteppingHelixPropagatorAny")) {
1017 propagator = handle.product();
1018 } else {
1019 edm::LogError(kLogCategory_) << "failed to get Propagator";
1020 return;
1021 }
1022
1023
1024
1025
1026
1027 for (const reco::Muon& muon : *muon_view) {
1028 const reco::Track* track = muon.muonTrack(kMuonTrackType_).get();
1029 if (track == nullptr) {
1030 LogDebug(kLogCategory_) << "failed to get a " << kMuonTrackTypeName_;
1031 continue;
1032 }
1033
1034 const reco::TransientTrack transient_track = transient_track_builder->build(track);
1035 if (not transient_track.isValid()) {
1036 edm::LogError(kLogCategory_) << "failed to build TransientTrack";
1037 continue;
1038 }
1039
1040 for (const GEMLayer& layer : gem_layers_) {
1041 if (checkPropagationDirection(track, layer)) {
1042 LogDebug(kLogCategory_) << "bad flight path. skip this propagation.";
1043 continue;
1044 }
1045
1046 const auto [found_start_state, start_state, start_id] = buildStartingState(muon, transient_track, layer);
1047 if (not found_start_state) {
1048 LogDebug(kLogCategory_) << "propagation starting state not found";
1049 continue;
1050 }
1051
1052
1053 const auto [propagated_state, prop_path_length] = propagator->propagateWithPath(start_state, *(layer.disk));
1054 if (not propagated_state.isValid()) {
1055 LogDebug(kLogCategory_) << "failed to propagate a muon from "
1056 << Form("(Detector, Subdetector) = (%d, %d)",
1057 static_cast<int>(start_id.det()),
1058 start_id.subdetId())
1059 << " to " << layer.id << ". The path length is " << prop_path_length;
1060 continue;
1061 }
1062
1063 const GlobalPoint prop_global_pos = propagated_state.globalPosition();
1064 const GlobalError& prop_global_err =
1065 ErrorFrameTransformer::transform(propagated_state.localError().positionError(), *layer.disk);
1066
1067 if (not checkBounds(*layer.disk, prop_global_pos, prop_global_err, kBoundsErrorScale_)) {
1068 LogDebug(kLogCategory_) << "failed to pass checkBounds";
1069 continue;
1070 }
1071
1072 const GEMEtaPartition* eta_partition = findEtaPartition(prop_global_pos, prop_global_err, layer.chambers);
1073 if (eta_partition == nullptr) {
1074 LogDebug(kLogCategory_) << "failed to find an eta partition";
1075 continue;
1076 }
1077
1078 const GEMDetId gem_id = eta_partition->id();
1079
1080 if (kMaskChamberWithError_) {
1081 const bool has_error = maskChamberWithError(gem_id.chamberId(), oh_status_collection, vfat_status_collection);
1082 if (has_error) {
1083 LogDebug(kLogCategory_) << gem_id.chamberId() << " has an erorr. Skip this propagation.";
1084 continue;
1085 }
1086 }
1087
1088
1089
1090
1091 const GEMDetId rs_key = getReStKey(gem_id);
1092 const GEMDetId rsl_key = getReStLaKey(gem_id);
1093 const GEMDetId rse_key = getReStEtKey(gem_id);
1094
1095 const int station_id = gem_id.station();
1096 const int chamber_id = gem_id.chamber();
1097 const int ieta = gem_id.ieta();
1098
1099 const double muon_pt = muon.pt();
1100 const double muon_eta = std::fabs(muon.eta());
1101 const double muon_phi = Geom::convertRadToDeg(muon.phi());
1102
1103 const double prop_global_err_r = std::sqrt(prop_global_err.rerr(prop_global_pos));
1104 const double prop_global_err_phi = Geom::convertRadToDeg(std::sqrt(prop_global_err.phierr(prop_global_pos)));
1105
1106
1107 const bool passed_prop_err_r_cut = (prop_global_err_r < kPropagationErrorRCut_);
1108 const bool passed_prop_err_phi_cut = (prop_global_err_phi < kPropagationErrorPhiCut_);
1109 const bool passed_pt_cut = muon_pt > kMuonPtMinCuts_.at(station_id);
1110 const bool passed_eta_cut =
1111 (muon_eta > kMuonEtaMinCuts_.at(station_id)) and (muon_eta < kMuonEtaMaxCuts_.at(station_id));
1112
1113 const bool passed_prop_err_cuts = passed_prop_err_r_cut and passed_prop_err_phi_cut;
1114 const bool passed_all_cuts = passed_prop_err_cuts and passed_pt_cut and passed_eta_cut;
1115
1116 const int cutflow_last = not kModeDev_ ? 0
1117 : not passed_prop_err_r_cut ? 1
1118 : not passed_prop_err_phi_cut ? 2
1119 : not passed_pt_cut ? 3
1120 : not passed_eta_cut ? 4
1121 : 5;
1122
1123
1124
1125
1126 if (passed_eta_cut and passed_prop_err_cuts) {
1127 fillMEWithinLimits(me_muon_pt_, rs_key, muon_pt);
1128 }
1129
1130 if (passed_pt_cut and passed_prop_err_cuts) {
1131 fillMEWithinLimits(me_muon_eta_, rs_key, muon_eta);
1132 }
1133
1134 if (passed_all_cuts) {
1135 fillME(me_chamber_ieta_, rsl_key, chamber_id, ieta);
1136 fillME(me_muon_phi_, rs_key, muon_phi);
1137 }
1138
1139 if (kModeDev_) {
1140 fillMEWithinLimits(me_prop_path_length_, rsl_key, prop_path_length);
1141 fillMEWithinLimits(me_prop_err_r_, rsl_key, prop_global_err_r);
1142 fillMEWithinLimits(me_prop_err_phi_, rsl_key, prop_global_err_phi);
1143
1144 fillMEWithinLimits(me_muon_pt_all_, rs_key, muon_pt);
1145 fillMEWithinLimits(me_muon_eta_all_, rs_key, muon_eta);
1146
1147 fillME(me_muon_charge_, rs_key, muon.charge());
1148
1149 for (int bin = 1; bin <= cutflow_last; bin++) {
1150 fillME(me_cutflow_, rsl_key, bin);
1151 }
1152
1153 }
1154
1155
1156
1157
1158 const auto [hit, matching_metric] =
1159 findClosestHit(prop_global_pos, rechit_collection->get(gem_id), eta_partition);
1160
1161 if (hit == nullptr) {
1162 LogDebug(kLogCategory_) << "hit not found";
1163 continue;
1164 }
1165
1166 if (kModeDev_) {
1167 fillMEWithinLimits(me_matching_metric_all_, rse_key, matching_metric);
1168 }
1169
1170 if (std::abs(matching_metric) > kMatchingCut_) {
1171 LogDebug(kLogCategory_) << "failed to pass the residual rphi cut";
1172 continue;
1173 }
1174
1175
1176
1177
1178 if (passed_eta_cut and passed_prop_err_cuts) {
1179 fillMEWithinLimits(me_muon_pt_matched_, rs_key, muon_pt);
1180 }
1181
1182 if (passed_pt_cut and passed_prop_err_cuts) {
1183 fillMEWithinLimits(me_muon_eta_matched_, rs_key, muon_eta);
1184 }
1185
1186 if (passed_all_cuts) {
1187 fillME(me_chamber_ieta_matched_, rsl_key, chamber_id, ieta);
1188 fillME(me_muon_phi_matched_, rs_key, muon_phi);
1189 }
1190
1191 if (kModeDev_) {
1192 fillMEWithinLimits(me_prop_path_length_matched_, rsl_key, prop_path_length);
1193
1194 fillMEWithinLimits(me_prop_err_r_matched_, rsl_key, prop_global_err_r);
1195 fillMEWithinLimits(me_prop_err_phi_matched_, rsl_key, prop_global_err_phi);
1196
1197 fillMEWithinLimits(me_muon_pt_all_matched_, rs_key, muon_pt);
1198 fillMEWithinLimits(me_muon_eta_all_matched_, rs_key, muon_eta);
1199
1200 fillME(me_muon_charge_matched_, rs_key, muon.charge());
1201
1202 if (passed_all_cuts) {
1203 for (int bin = 1; bin <= cutflow_last; bin++) {
1204 fillME(me_cutflow_matched_, rsl_key, bin);
1205 }
1206 }
1207 }
1208
1209
1210
1211
1212 if (passed_all_cuts) {
1213 const LocalPoint hit_local_pos = hit->localPosition();
1214 const GlobalPoint& hit_global_pos = eta_partition->toGlobal(hit_local_pos);
1215 const float residual_phi = Geom::convertRadToDeg(prop_global_pos.phi() - hit_global_pos.phi());
1216
1217 fillMEWithinLimits(me_residual_phi_, rse_key, residual_phi);
1218
1219 if (kModeDev_) {
1220 const LocalPoint prop_local_pos = eta_partition->toLocal(prop_global_pos);
1221 const StripTopology& topology = eta_partition->specificTopology();
1222
1223 const float residual_x = prop_local_pos.x() - hit_local_pos.x();
1224 const float residual_y = prop_local_pos.y() - hit_local_pos.y();
1225 const float residual_strip = topology.strip(prop_local_pos) - topology.strip(hit_local_pos);
1226
1227 fillMEWithinLimits(me_matching_metric_, rse_key, matching_metric);
1228 fillMEWithinLimits(me_residual_x_, rse_key, residual_x);
1229 fillMEWithinLimits(me_residual_y_, rse_key, residual_y);
1230 fillMEWithinLimits(me_residual_strip_, rse_key, residual_strip);
1231
1232 if (muon.charge() < 0) {
1233 fillMEWithinLimits(me_residual_phi_muon_, rse_key, residual_phi);
1234 } else {
1235 fillMEWithinLimits(me_residual_phi_antimuon_, rse_key, residual_phi);
1236 }
1237 }
1238 }
1239 }
1240 }
1241 }