CMS 3D CMS Logo

GEMEfficiencyAnalyzer.cc
Go to the documentation of this file.
2 
12 
15  kGEMGeometryTokenBeginRun_(esConsumes<edm::Transition::BeginRun>()),
16  kTransientTrackBuilderToken_(
17  esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))),
18  kGEMRecHitCollectionToken_(consumes<GEMRecHitCollection>(ps.getUntrackedParameter<edm::InputTag>("recHitTag"))),
19  kMuonViewToken_(consumes<edm::View<reco::Muon> >(ps.getUntrackedParameter<edm::InputTag>("muonTag"))),
20  kMuonTrackTypeName_(ps.getUntrackedParameter<std::string>("muonTrackType")),
21  kMuonTrackType_(getMuonTrackType(kMuonTrackTypeName_)),
22  kMuonName_(TString(ps.getUntrackedParameter<std::string>("muonName"))),
23  kFolder_(ps.getUntrackedParameter<std::string>("folder")),
24  kScenario_(getScenarioOption(ps.getUntrackedParameter<std::string>("scenario"))),
25  kStartingStateType_(getStartingStateType(ps.getUntrackedParameter<std::string>("startingStateType"))),
26  kMuonSubdetForGEM_({
27  ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE0"),
28  ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE11"),
29  ps.getUntrackedParameter<std::vector<int> >("muonSubdetForGE21"),
30  }),
31  kCSCForGEM_({
32  ps.getUntrackedParameter<std::vector<int> >("cscForGE0"),
33  ps.getUntrackedParameter<std::vector<int> >("cscForGE11"),
34  ps.getUntrackedParameter<std::vector<int> >("cscForGE21"),
35  }),
36  kMuonSegmentMatchDRCut_(static_cast<float>(ps.getUntrackedParameter<double>("muonSegmentMatchDRCut"))),
37  kMuonPtMinCuts_({
38  ps.getUntrackedParameter<double>("muonPtMinCutGE0"),
39  ps.getUntrackedParameter<double>("muonPtMinCutGE11"),
40  ps.getUntrackedParameter<double>("muonPtMinCutGE21"),
41  }),
42  kMuonEtaMinCuts_({
43  ps.getUntrackedParameter<double>("muonEtaMinCutGE0"),
44  ps.getUntrackedParameter<double>("muonEtaMinCutGE11"),
45  ps.getUntrackedParameter<double>("muonEtaMinCutGE21"),
46  }),
47  kMuonEtaMaxCuts_({
48  ps.getUntrackedParameter<double>("muonEtaMaxCutGE0"),
49  ps.getUntrackedParameter<double>("muonEtaMaxCutGE11"),
50  ps.getUntrackedParameter<double>("muonEtaMaxCutGE21"),
51  }),
52  kPropagationErrorRCut_(static_cast<float>(ps.getUntrackedParameter<double>("propagationErrorRCut"))),
53  kPropagationErrorPhiCut_(static_cast<float>(ps.getUntrackedParameter<double>("propagationErrorPhiCut"))),
54  kBoundsErrorScale_(static_cast<float>(ps.getUntrackedParameter<double>("boundsErrorScale"))),
55  kMatchingMetric_(getMatchingMetric(ps.getUntrackedParameter<std::string>("matchingMetric"))),
56  kMatchingCut_(static_cast<float>(ps.getUntrackedParameter<double>("matchingCut"))),
57  kMuonPtBins_(ps.getUntrackedParameter<std::vector<double> >("muonPtBins")),
58  kMuonEtaNbins_({
59  ps.getUntrackedParameter<int>("muonEtaNbinsGE0"),
60  ps.getUntrackedParameter<int>("muonEtaNbinsGE11"),
61  ps.getUntrackedParameter<int>("muonEtaNbinsGE21"),
62  }),
63  kMuonEtaLow_({
64  ps.getUntrackedParameter<double>("muonEtaLowGE0"),
65  ps.getUntrackedParameter<double>("muonEtaLowGE11"),
66  ps.getUntrackedParameter<double>("muonEtaLowGE21"),
67  }),
68  kMuonEtaUp_({
69  ps.getUntrackedParameter<double>("muonEtaUpGE0"),
70  ps.getUntrackedParameter<double>("muonEtaUpGE11"),
71  ps.getUntrackedParameter<double>("muonEtaUpGE21"),
72  }),
73  kModeDev_(ps.getUntrackedParameter<bool>("modeDev")) {
74  muon_service_ =
75  std::make_unique<MuonServiceProxy>(ps.getParameter<edm::ParameterSet>("ServiceParameters"), consumesCollector());
76 }
77 
79 
82  // GEMDQMEfficiencySourceBase
83  desc.addUntracked<edm::InputTag>("ohStatusTag", edm::InputTag("muonGEMDigis", "OHStatus"));
84  desc.addUntracked<edm::InputTag>("vfatStatusTag", edm::InputTag("muonGEMDigis", "VFATStatus"));
85  desc.addUntracked<bool>("monitorGE11", true);
86  desc.addUntracked<bool>("monitorGE21", false);
87  desc.addUntracked<bool>("monitorGE0", false);
88  desc.addUntracked<bool>("maskChamberWithError", false);
89  desc.addUntracked<std::string>("logCategory", "GEMEfficiencyAnalyzer");
90 
91  // GEMEfficiencyAnalyzer
92  desc.addUntracked<edm::InputTag>("recHitTag", edm::InputTag("gemRecHits"));
93  desc.addUntracked<edm::InputTag>("muonTag", edm::InputTag("muons"));
94  desc.addUntracked<bool>("modeDev", false);
95  desc.addUntracked<std::string>("muonTrackType", "OuterTrack");
96  desc.addUntracked<std::string>("muonName", "STA Muon");
97  desc.addUntracked<std::string>("folder", "GEM/Efficiency/muonSTA");
98  desc.addUntracked<std::string>("scenario", "pp");
99  //
100  desc.addUntracked<std::string>("startingStateType", "OutermostMeasurementState");
101  desc.addUntracked<double>("muonSegmentMatchDRCut", 5.0f); // for cosmics, in cm, TODO tune
102  // muon pt cut
103  desc.addUntracked<double>("muonPtMinCutGE0", 20.0f);
104  desc.addUntracked<double>("muonPtMinCutGE11", 20.0f);
105  desc.addUntracked<double>("muonPtMinCutGE21", 20.0f);
106  // muon abs eta cut for GE11
107  desc.addUntracked<double>("muonEtaMinCutGE11", 1.5);
108  desc.addUntracked<double>("muonEtaMaxCutGE11", 2.2);
109  // muon abs eta cut for GE21
110  desc.addUntracked<double>("muonEtaMinCutGE21", 1.5);
111  desc.addUntracked<double>("muonEtaMaxCutGE21", 2.5);
112  // muon abs eta cut for GE0
113  desc.addUntracked<double>("muonEtaMinCutGE0", 2.0);
114  desc.addUntracked<double>("muonEtaMaxCutGE0", 3.0);
115  // propagation error cuts
116  desc.addUntracked<double>("propagationErrorRCut", 0.5); // cm
117  desc.addUntracked<double>("propagationErrorPhiCut", 0.2); // degree
118  //
119  desc.addUntracked<double>("boundsErrorScale", -2.0); // TODO tune
120  // matching
121  desc.addUntracked<std::string>("matchingMetric", "DeltaPhi");
122  desc.addUntracked<double>("matchingCut", 0.2); // DeltaPhi for pp, in degree TODO tune
123  // for MinotorElement
124  const std::vector<double> default_pt_bins{
125  0, 5, 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110.}; // actually edges
126  desc.addUntracked<std::vector<double> >("muonPtBins", default_pt_bins);
127  // GE11
128  desc.addUntracked<int>("muonEtaNbinsGE11", 9); // bin width = 0.1
129  desc.addUntracked<double>("muonEtaLowGE11", 1.4);
130  desc.addUntracked<double>("muonEtaUpGE11", 2.3);
131  // GE21
132  desc.addUntracked<int>("muonEtaNbinsGE21", 12); // bin width = 0.1
133  desc.addUntracked<double>("muonEtaLowGE21", 1.4);
134  desc.addUntracked<double>("muonEtaUpGE21", 2.6);
135  // GE0
136  desc.addUntracked<int>("muonEtaNbinsGE0", 12); // bin width = 0.1
137  desc.addUntracked<double>("muonEtaLowGE0", 1.9);
138  desc.addUntracked<double>("muonEtaUpGE0", 3.1);
139 
140  // MuonSubdetId's are listed in DataFormats/MuonDetId/interface/MuonSubdetId.h
141  desc.addUntracked<std::vector<int> >("muonSubdetForGE0", {}); // allow all muon subdetectors. TODO optimzie.
142  desc.addUntracked<std::vector<int> >("muonSubdetForGE11", {});
143  desc.addUntracked<std::vector<int> >("muonSubdetForGE21", {});
144  // INFO when muonTrackType is "CombinedTrack" or "OuterTrack"
145  // https://github.com/cms-sw/cmssw/blob/CMSSW_12_4_0_pre3/DataFormats/MuonDetId/interface/CSCDetId.h#L187-L193
146  // assumed to be the same area.
147  desc.addUntracked<std::vector<int> >("cscForGE11", {1, 2}); // ME1a, ME1b
148  desc.addUntracked<std::vector<int> >("cscForGE21", {}); // all CSCSegments allowed
149  desc.addUntracked<std::vector<int> >("cscForGE0", {}); // all CSCSegments allowed
150 
151  // ServiceParameters for MuonServiceProxy
152  // This will be initialized in the cfi file
153  edm::ParameterSetDescription service_parameters;
154  service_parameters.setAllowAnything();
155  desc.add<edm::ParameterSetDescription>("ServiceParameters", service_parameters);
156 
157  descriptions.add("gemEfficiencyAnalyzerDefault", desc);
158 }
159 
160 // convert a string to enum
163 
164  if (name == "DeltaPhi") {
166 
167  } else if (name == "RdPhi") {
169 
170  } else {
171  edm::LogError(kLogCategory_) << "received an unexpected MatchingMetric: " << name
172  << " -> MatchingMetric::kDeltaPhi will be used instead.";
174  }
175 
176  return method;
177 }
178 
179 // convert a string to enum
182 
183  if (name == "InnermostMeasurementState") {
185 
186  } else if (name == "OutermostMeasurementState") {
188 
189  } else if (name == "StateOnSurfaceWithCSCSegment") {
191 
192  } else if (name == "AlignmentStyle") {
194 
195  } else {
196  edm::LogError(kLogCategory_) << "received an unexpected StartingStateType: " << name
197  << " -> StartingStateType::kOutermostMeasurementState will be used instead.";
199  }
200 
201  return type;
202 }
203 
204 // convert a string to enum
206  reco::Muon::MuonTrackType muon_track_type;
207 
208  // DO NOT ALLOW TYPO
209  if (name == "InnerTrack") {
210  muon_track_type = reco::Muon::MuonTrackType::InnerTrack;
211 
212  } else if (name == "OuterTrack") {
213  muon_track_type = reco::Muon::MuonTrackType::OuterTrack;
214 
215  } else if (name == "CombinedTrack") {
216  muon_track_type = reco::Muon::MuonTrackType::CombinedTrack;
217 
218  } else {
219  edm::LogError(kLogCategory_) << "received an unexpected reco::Muon::MuonTrackType: " << name
220  << " --> OuterTrack will be used instead.";
221 
222  muon_track_type = reco::Muon::MuonTrackType::OuterTrack;
223  }
224 
225  return muon_track_type;
226 }
227 
230  if (name == "pp") {
232 
233  } else if (name == "cosmics") {
235 
236  } else if (name == "HeavyIons") {
238 
239  edm::LogInfo(kLogCategory_) << "The scenario is set to \"HeavyIons\""
240  << " but there is no strategy dedicated to"
241  << "\"HeavyIons\" scenario. The strategy for "
242  << "the \"pp\" scenario will be used insteqad.";
243 
244  } else {
246 
247  edm::LogError(kLogCategory_) << "received an unexpected ScenarioOption: " << name
248  << ". Choose from (\"pp\", \"cosmics\", \"HeavyIons\")"
249  << " --> pp will be used instead.";
250  }
251 
252  return scenario;
253 }
254 
256  ibooker.setCurrentFolder(kFolder_);
257 
258  const GEMGeometry* gem = nullptr;
259  if (auto handle = setup.getHandle(kGEMGeometryTokenBeginRun_)) {
260  gem = handle.product();
261  } else {
262  edm::LogError(kLogCategory_ + "|bookHistograms") << "failed to get GEMGeometry";
263  return;
264  }
265 
266  for (const GEMStation* station : gem->stations()) {
267  const int region_id = station->region();
268  const int station_id = station->station();
269 
270  if (skipGEMStation(station_id)) {
271  continue;
272  }
273 
275  // Region-Station
277  { // shadowing to reuse short variable names
278  const GEMDetId key = getReStKey(region_id, station_id);
279  const TString suffix = GEMUtils::getSuffixName(region_id, station_id);
280  const TString title = kMuonName_ + GEMUtils::getSuffixTitle(region_id, station_id);
281 
282  // sources for eff. vs muon pt
283  TH1F* h_muon_pt = new TH1F("muon_pt" + suffix, title, kMuonPtBins_.size() - 1, &kMuonPtBins_[0]);
284  me_muon_pt_[key] = ibooker.book1D(h_muon_pt->GetName(), h_muon_pt);
285  me_muon_pt_[key]->setAxisTitle("Muon p_{T} [GeV]", 1);
287 
288  // sources for eff. vs muon eta
289  me_muon_eta_[key] = ibooker.book1D("muon_eta" + suffix,
290  title,
291  kMuonEtaNbins_.at(station_id),
292  kMuonEtaLow_.at(station_id),
293  kMuonEtaUp_.at(station_id));
294  me_muon_eta_[key]->setAxisTitle("Muon |#eta|", 1);
296 
297  // sources for eff. vs muon phi
298  me_muon_phi_[key] = ibooker.book1D("muon_phi" + suffix, title, 36, -180, 180);
299  me_muon_phi_[key]->setAxisTitle("Muon #phi [deg]");
301 
302  if (kModeDev_) {
303  // without cuts except the fiducial cut
304  TH1F* h_muon_pt_all = new TH1F("muon_pt_all" + suffix, title, kMuonPtBins_.size() - 1, &kMuonPtBins_[0]);
305  me_muon_pt_all_[key] = ibooker.book1D(h_muon_pt_all->GetName(), h_muon_pt_all);
306  me_muon_pt_all_[key]->setAxisTitle("Muon p_{T} [GeV]", 1);
308 
309  me_muon_eta_all_[key] = ibooker.book1D("muon_eta_all" + suffix,
310  title,
311  kMuonEtaNbins_.at(station_id),
312  kMuonEtaLow_.at(station_id),
313  kMuonEtaUp_.at(station_id));
314  me_muon_eta_all_[key]->setAxisTitle("Muon |#eta|", 1);
316 
317  me_muon_charge_[key] = ibooker.book1D("muon_charge" + suffix, title, 3, -1.5, 1.5);
318  me_muon_charge_[key]->setAxisTitle("Muon charge", 1);
320  }
321  } // shadowing
322 
324  // Region - Station - Layer
326  const std::vector<const GEMSuperChamber*> superchamber_vec = station->superChambers();
327  if (not checkRefs(superchamber_vec)) {
328  edm::LogError(kLogCategory_) << "got an invalid ptr from GEMStation::superChambers";
329  return;
330  }
331 
332  const std::vector<const GEMChamber*> chamber_vec = superchamber_vec.front()->chambers();
333  if (not checkRefs(chamber_vec)) {
334  edm::LogError(kLogCategory_) << "got an invalid ptr from GEMSuperChamber::chambers";
335  return;
336  }
337 
338  // we actually loop over layers
339  for (const GEMChamber* chamber : chamber_vec) {
340  const int layer_id = chamber->id().layer();
341 
342  { // shadowing
343  const GEMDetId key = getReStLaKey(chamber->id());
344  const TString suffix = GEMUtils::getSuffixName(region_id, station_id, layer_id);
345  const TString title = kMuonName_ + GEMUtils::getSuffixTitle(region_id, station_id, layer_id);
346 
347  me_chamber_ieta_[key] = bookChamberEtaPartition(ibooker, "chamber_ieta" + suffix, title, station);
349 
350  if (kModeDev_) {
351  me_prop_path_length_[key] = ibooker.book1D("prop_path_length" + suffix, title, 50, 0.0, 5.0);
352  me_prop_path_length_[key]->setAxisTitle("Propagation path length [cm]", 1);
354 
355  // prop. r error in the global coordinates
356  me_prop_err_r_[key] = ibooker.book1D("prop_err_r" + suffix, title, 60, 0.0, 3.0);
357  me_prop_err_r_[key]->setAxisTitle("Propagation global #sigma_{R} [cm]", 1);
359 
360  // prop. r error in the global coordinates
361  me_prop_err_phi_[key] = ibooker.book1D("prop_err_phi" + suffix, title, 50, 0.0, 1.0);
362  me_prop_err_phi_[key]->setAxisTitle("Propagation's global #sigma_{#phi} [deg]", 1);
364 
365  // cutflow
366  me_cutflow_[key] = ibooker.book1D("cutflow" + suffix, title, 5, 0.5, 5.5);
367  me_cutflow_[key]->setBinLabel(1, "All");
368  me_cutflow_[key]->setBinLabel(2, Form("#sigma_{R} < %.3f cm", kPropagationErrorRCut_));
369  me_cutflow_[key]->setBinLabel(3, Form("#sigma_{phi} < %.3f deg", kPropagationErrorPhiCut_));
370  me_cutflow_[key]->setBinLabel(4, Form("p_{T} > %.1f GeV", kMuonPtMinCuts_.at(station_id)));
371  me_cutflow_[key]->setBinLabel(
372  5, Form("%.2f < |#eta| < %.2f", kMuonEtaMinCuts_.at(station_id), kMuonEtaMaxCuts_.at(station_id)));
373 
375  }
376  } // shadowing
377  } // GEMChamber
378 
380  // Region - Station - iEta
382  const std::vector<const GEMEtaPartition*> eta_partition_vec = chamber_vec.front()->etaPartitions();
383  if (not checkRefs(eta_partition_vec)) {
384  edm::LogError(kLogCategory_) << "got an invalid ptr from GEMChamber::etaPartitions";
385  continue;
386  }
387 
388  for (const GEMEtaPartition* eta_partition : eta_partition_vec) {
389  const int ieta = eta_partition->id().ieta();
390 
391  { // shadowing
392  const GEMDetId key = getReStEtKey(eta_partition->id());
393  const TString gem_label = TString::Format("GE%d1-%c-E%d", station_id, (region_id > 0 ? 'P' : 'M'), ieta);
394  const TString suffix = "_" + gem_label;
395  const TString title = kMuonName_ + " " + gem_label;
396 
397  // FIXME
398  const float dphi_up = (kMatchingMetric_ == MatchingMetric::kDeltaPhi) ? kMatchingCut_
400  : 0.2;
401  me_residual_phi_[key] = ibooker.book1D("residual_phi" + suffix, title, 41, -dphi_up, dphi_up);
402  me_residual_phi_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
403 
404  if (kModeDev_) {
405  // matching metric
406  std::string matching_metric_x_title;
408  matching_metric_x_title = "#Delta#phi [deg]";
409 
411  matching_metric_x_title = "R#Delta#phi [cm]";
412 
413  } else {
414  matching_metric_x_title = "UNKNOWN METRIC";
415  }
416 
417  // matching metrics without any cuts
419  ibooker.book1D("matching_metric_all" + suffix, title, 101, -3 * kMatchingCut_, 3 * kMatchingCut_);
420  me_matching_metric_all_[key]->setAxisTitle(matching_metric_x_title, 1);
421 
422  // matching metrics after cuts
424  ibooker.book1D("matching_metric" + suffix, title, 101, -kMatchingCut_, kMatchingCut_);
425  me_matching_metric_[key]->setAxisTitle(matching_metric_x_title, 1);
426 
427  // residuals in the global phi for muons (q < 0)
429  ibooker.book1D("residual_phi_muon" + suffix, title + " (#mu, q < 0)", 50, -0.5, 0.5);
430  me_residual_phi_muon_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
431  me_residual_phi_muon_[key]->setAxisTitle("Number of muons", 2);
432 
433  // residuals in the global phi for anti-muons (q > 0)
435  ibooker.book1D("residual_phi_antimuon" + suffix, title + " (#tilde{#mu}, q > 0)", 50, -0.5, 0.5);
436  me_residual_phi_antimuon_[key]->setAxisTitle("Residual in global #phi [deg]", 1);
437  me_residual_phi_antimuon_[key]->setAxisTitle("Number of anti-muons", 2);
438 
439  // residuals in the local x
440  me_residual_x_[key] = ibooker.book1D("residual_x" + suffix, title, 60, -1.5, 1.5);
441  me_residual_x_[key]->setAxisTitle("Residual in local X [cm]", 1);
442 
443  // residuals in the local y
444  me_residual_y_[key] = ibooker.book1D("residual_y" + suffix, title, 48, -12.0, 12.0);
445  me_residual_y_[key]->setAxisTitle("Residual in local Y [cm]", 1);
446 
447  // the strip difference
448  me_residual_strip_[key] = ibooker.book1D("residual_strip" + suffix, title, 21, -10.0, 10.0);
449  me_residual_strip_[key]->setAxisTitle("propagation strip - hit strip", 1);
450  }
451  } // shadowing
452  } // GEMEtaPartition
453  } // GEMStataion
454 }
455 
456 // In the `cosmics` scenario, TODO doc
458  return track.innerPosition().mag2() > track.outerPosition().mag2();
459 }
460 
461 //
463  std::map<GEMDetId, std::vector<const GEMChamber*> > chambers_per_layer;
464 
465  for (const GEMStation* station : gem->stations()) {
466  const int region_id = station->region();
467  const int station_id = station->station();
468  const bool is_ge11 = station_id == 1;
469 
470  if (skipGEMStation(station_id)) {
471  continue;
472  }
473 
474  for (const GEMSuperChamber* superchamber : station->superChambers()) {
475  // GE11: chamber == 0 for even chambers, chamber == 1 for odd chambers
476  // GE21 and GE0: chamber == 0 for all chambers
477  const int chamber_id = is_ge11 ? superchamber->id().chamber() % 2 : 0;
478 
479  for (const GEMChamber* chamber : superchamber->chambers()) {
480  const int layer_id = chamber->id().layer();
481 
482  const GEMDetId key{region_id, 1, station_id, layer_id, chamber_id, 0};
483 
484  if (chambers_per_layer.find(key) == chambers_per_layer.end()) {
485  chambers_per_layer.insert({key, std::vector<const GEMChamber*>()});
486  }
487  chambers_per_layer.at(key).push_back(chamber);
488  } // GEMChamber => iterate over layer ids
489  } // GEMSuperChamber => iterate over chamber ids
490  } // GEMStation
491 
492  gem_layers_.reserve(chambers_per_layer.size());
493  for (auto [gem_id, chambers] : chambers_per_layer) {
494  // layer position and rotation
495  const float z_origin = chambers.front()->position().z();
496  Surface::PositionType position{0.f, 0.f, z_origin};
498 
499  // eta partitions should have same R and Z spans.
500  // XXX is it true?
501  auto [r_min, r_max] = chambers.front()->surface().rSpan();
502  auto [z_min, z_max] = chambers.front()->surface().zSpan();
503 
504  z_min -= z_origin;
505  z_max -= z_origin;
506 
507  // the bounds from min and max R and Z in the local coordinates.
508  SimpleDiskBounds* bounds = new SimpleDiskBounds(r_min, r_max, z_min, z_max);
510 
511  gem_layers_.emplace_back(layer, chambers, gem_id);
512 
513  LogDebug(kLogCategory_) << gem_id
514  << Form(" ==> (z_origin, z_min, z_max) = (%.2f, %.2f, %.2f)", z_origin, z_min, z_max);
515  } // ring
516 }
517 
518 // TODO doc
519 // See https://twiki.cern.ch/twiki/pub/CMS/GEMPPDOfflineDQM/check-muon-direction.pdf
521  const bool is_same_region = track->eta() * layer.id.region() > 0;
522 
523  bool skip = false;
525  float p2_in = track->innerMomentum().mag2();
526  float p2_out = track->outerMomentum().mag2();
527  if (isInsideOut(*track))
528  std::swap(p2_in, p2_out);
529  const bool is_outgoing = p2_in > p2_out;
530 
531  skip = (is_outgoing xor is_same_region);
532 
533  } else {
534  // beam scenario
535  skip = not is_same_region;
536  }
537 
538  return skip;
539 }
540 
542  const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
543  bool found = false;
545  DetId det_id;
546 
547  switch (kStartingStateType_) {
549  std::tie(found, state, det_id) = getOutermostMeasurementState(transient_track);
550  break;
551  }
553  std::tie(found, state, det_id) = getInnermostMeasurementState(transient_track);
554  break;
555  }
557  std::tie(found, state, det_id) = buildStateOnSurfaceWithCSCSegment(muon, transient_track, gem_layer);
558  break;
559  }
561  std::tie(found, state, det_id) = buildStartingStateAlignmentStyle(muon, transient_track, gem_layer);
562  break;
563  }
564  default: {
565  edm::LogError(kLogCategory_) << "got an unexpected StartingStateType";
566  break;
567  }
568  }
569 
570  found &= state.isValid();
571 
572  if (found and (det_id.det() == DetId::Detector::Muon)) {
573  found &= isMuonSubdetAllowed(det_id, gem_layer.id.station());
574  }
575 
576  if (found) {
577  if (MuonHitHelper::isGEM(det_id)) {
578  const GEMDetId start_id{det_id};
579 
580  const bool are_same_region = gem_layer.id.region() == start_id.region();
581  const bool are_same_station = gem_layer.id.station() == start_id.station();
582  const bool are_same_layer = gem_layer.id.layer() == start_id.layer();
583  if (are_same_region and are_same_station and are_same_layer) {
585  << "The starting detector of the muon propagation is same with the destination. Skip this propagation.";
586  found = false;
587  }
588  } // isGEM
589  } // found
590 
591  return std::make_tuple(found, state, det_id);
592 }
593 
594 // Use the innermost measurement state as an initial state for the muon propagation.
595 // NOTE If the analyzer uses global or standalone muons and GEM hits are used in the
596 // muon reconstruction, the result should be biased.
597 // In 12_4_0_pre3, GEM hits are used in the pp scenario, but not in the cosmics scenario.
598 // https://github.com/cms-sw/cmssw/blob/CMSSW_12_4_0_pre3/RecoMuon/StandAloneMuonProducer/python/standAloneMuons_cfi.py#L111-L127
599 // https://github.com/cms-sw/cmssw/blob/CMSSW_12_4_0_pre3/RecoMuon/CosmicMuonProducer/python/cosmicMuons_cfi.py
601  const reco::TransientTrack& transient_track) {
603  DetId det_id;
604 
605  const reco::Track& track = transient_track.track();
606  // get real innermost state
607  if (isInsideOut(track)) {
608  state = transient_track.outermostMeasurementState();
609  det_id = track.outerDetId();
610 
611  } else {
612  state = transient_track.innermostMeasurementState();
613  det_id = track.innerDetId();
614  }
615 
616  return std::make_tuple(true, state, det_id);
617 }
618 
619 // Use the outermost measurement state as an initial state for the muon propagation.
621  const reco::TransientTrack& transient_track) {
622  const reco::Track& track = transient_track.track();
623 
625  DetId det_id;
626 
627  // get real innermost state
628  if (isInsideOut(track)) {
629  state = transient_track.innermostMeasurementState();
630  det_id = track.innerDetId();
631 
632  } else {
633  state = transient_track.outermostMeasurementState();
634  det_id = track.outerDetId();
635  }
636 
637  return std::make_tuple(true, state, det_id);
638 }
639 
640 // Find the nearest CSC segment to the given GEM layer and then use a trajectory
641 // state on the surface with the segment as an initial state.
642 // XXX This method results in the residual phi distribution with two peaks
643 // because the muon and antimuon make different peaks.
645  const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
646  bool found = false;
648  DetId det_id;
649 
650  if (const CSCSegment* csc_segment = findCSCSegment(muon, transient_track, gem_layer)) {
651  const GeomDet* det = muon_service_->trackingGeometry()->idToDet(csc_segment->cscDetId());
652  const GlobalPoint global_position = det->toGlobal(csc_segment->localPosition());
653 
654  found = true;
655  state = transient_track.stateOnSurface(global_position);
656  det_id = csc_segment->geographicalId();
657  }
658 
659  return std::make_tuple(found, state, det_id);
660 }
661 
662 // Find an ME11 segment and the build an initial state using the location and
663 // direction of the ME11 segment. If the muon has an inner track, the outerP of
664 // the inner track is used as the momentum magnitude. If not, the momentum
665 // magnitude is set to 1 GeV.
666 // https://github.com/gem-sw/alignment/blob/713e8fa/GEMCSCBendingAnalyzer/MuonAnalyser/plugins/analyser.cc#L435-L446
668  const reco::Muon& muon, const reco::TransientTrack& transient_track, const GEMLayer& gem_layer) {
669  bool found = false;
671  DetId det_id;
672 
673  if (const CSCSegment* csc_segment = findCSCSegment(muon, transient_track, gem_layer)) {
674  found = true;
675  det_id = csc_segment->geographicalId();
676 
677  // position
678  const LocalPoint position = csc_segment->localPosition();
679  // momentum
680  const reco::TrackRef inner_track = muon.innerTrack();
681  const float momentum_magnitude = inner_track.isNonnull() ? inner_track.get()->outerP() : 1.0f;
682  const LocalVector momentum = momentum_magnitude * csc_segment->localDirection();
683 
684  // trajectory parameter
685  const LocalTrajectoryParameters trajectory_parameters{position, momentum, muon.charge()};
686 
687  // trajectory error
688  const LocalTrajectoryError trajectory_error =
689  asSMatrix<5>(csc_segment->parametersError().similarityT(csc_segment->projectionMatrix()));
690 
691  // surface
692  const Plane& surface = muon_service_->trackingGeometry()->idToDet(det_id)->surface();
693 
694  state =
695  TrajectoryStateOnSurface{trajectory_parameters, trajectory_error, surface, &*muon_service_->magneticField()};
696  }
697 
698  return std::make_tuple(found, state, det_id);
699 }
700 
701 //
702 // for beam scenario
704  const GEMLayer& gem_layer) {
705  const CSCSegment* best_csc_segment = nullptr;
706  double min_z_distance = std::numeric_limits<double>::infinity(); // in cm
707 
708  for (trackingRecHit_iterator tracking_rechit_iter = transient_track.recHitsBegin();
709  tracking_rechit_iter != transient_track.recHitsEnd();
710  tracking_rechit_iter++) {
711  const TrackingRecHit* tracking_rechit = *tracking_rechit_iter;
712  if (not tracking_rechit->isValid()) {
713  LogDebug(kLogCategory_) << "got an invalid trackingRecHit_iterator from transient_track. skip it.";
714  continue;
715  }
716 
717  const DetId det_id = tracking_rechit->geographicalId();
718  if (not MuonHitHelper::isCSC(det_id)) {
719  continue;
720  }
721 
722  if (tracking_rechit->dimension() != kCSCSegmentDimension_) {
723  continue;
724  }
725 
726  const CSCDetId csc_id{det_id};
727  if (not isCSCAllowed(csc_id, gem_layer.id.station())) {
728  continue;
729  }
730 
731  if (auto csc_segment = dynamic_cast<const CSCSegment*>(tracking_rechit)) {
732  const GeomDet* det = muon_service_->trackingGeometry()->idToDet(csc_id);
733  if (det == nullptr) {
734  edm::LogError(kLogCategory_) << "GlobalTrackingGeometry::idToDet returns nullptr; CSCDetId=" << csc_id;
735  continue;
736  }
737  const GlobalPoint global_position = det->toGlobal(csc_segment->localPosition());
738  const float z_distance = std::abs(gem_layer.disk->localZclamped(global_position));
739 
740  if (z_distance < min_z_distance) {
741  best_csc_segment = csc_segment;
742  min_z_distance = z_distance;
743  }
744 
745  } else {
747  << "failed to perform the conversion from `const TrackingRechit*` to `const CSCSegment*`";
748  }
749  } // trackingRecHit_iterator
750 
751  return best_csc_segment;
752 }
753 
755  const CSCSegment* best_csc_segment = nullptr;
756 
757  for (const reco::MuonChamberMatch& chamber_match : muon.matches()) {
758  if (not MuonHitHelper::isCSC(chamber_match.id)) {
759  continue;
760  }
761 
762  const CSCDetId csc_id{chamber_match.id};
763  if (not isCSCAllowed(csc_id, gem_layer.id.station())) {
764  continue;
765  }
766 
767  const float x_track = chamber_match.x;
768  const float y_track = chamber_match.y;
769 
770  for (const reco::MuonSegmentMatch& segment_match : chamber_match.segmentMatches) {
771  if (not segment_match.isMask(reco::MuonSegmentMatch::BestInStationByDR)) {
772  continue;
773  }
774 
775  const float dr = std::hypot(x_track - segment_match.x, y_track - segment_match.y);
776  std::cout << kLogCategory_ << ": dr=" << dr << std::endl;
777 
778  if (dr > kMuonSegmentMatchDRCut_) {
779  LogDebug(kLogCategory_) << "too large dR(muon, segment)";
780  break;
781  }
782 
783  if (segment_match.cscSegmentRef.isNonnull()) {
784  best_csc_segment = segment_match.cscSegmentRef.get();
785  }
786  } // MuonSegmentMatch
787  } // MuonChamberMatch
788 
789  return best_csc_segment;
790 }
791 
792 // just thin wrapper
794  const reco::TransientTrack& transient_track,
795  const GEMLayer& gem_layer) {
797  return findCSCSegmentCosmics(muon, gem_layer);
798  } else {
799  // pp or HI
800  return findCSCSegmentBeam(transient_track, gem_layer);
801  }
802 }
803 
804 bool GEMEfficiencyAnalyzer::isMuonSubdetAllowed(const DetId& det_id, const int gem_station) {
805  if ((gem_station < 0) or (gem_station > 2)) {
806  edm::LogError(kLogCategory_) << "got unexpected gem station " << gem_station;
807  return false;
808  }
809 
810  if (det_id.det() != DetId::Detector::Muon) {
811  edm::LogError(kLogCategory_) << Form(
812  "(Detector, Subdetector) = (%d, %d)", static_cast<int>(det_id.det()), det_id.subdetId());
813  return false;
814  }
815 
816  const std::vector<int> allowed = kMuonSubdetForGEM_.at(gem_station);
817  return allowed.empty() or (std::find(allowed.begin(), allowed.end(), det_id.subdetId()) != allowed.end());
818 }
819 
820 // Returns a bool value indicating whether or not the CSC detector can be used
821 // as a start detector for a given GEM station.
822 // See https://github.com/cms-sw/cmssw/blob/CMSSW_12_4_0_pre3/DataFormats/MuonDetId/interface/CSCDetId.h#L187-L193
823 // This method is used when using `buildStateOnSurfaceWithCSCSegment` or
824 // `buildStartingStateAlignmentStyle`
825 bool GEMEfficiencyAnalyzer::isCSCAllowed(const CSCDetId& csc_id, const int gem_station) {
826  if ((gem_station < 0) or (gem_station > 2)) {
827  edm::LogError(kLogCategory_) << "got unexpected gem station " << gem_station;
828  return false;
829  }
830 
831  // unsigned short to int
832  const int csc_chamber_type = static_cast<int>(csc_id.iChamberType());
833 
834  const std::vector<int> allowed = kCSCForGEM_.at(gem_station);
835  return allowed.empty() or (std::find(allowed.begin(), allowed.end(), csc_chamber_type) != allowed.end());
836 }
837 
838 bool GEMEfficiencyAnalyzer::checkBounds(const Plane& plane, const GlobalPoint& global_point) {
839  const LocalPoint local_point = plane.toLocal(global_point);
840  const LocalPoint local_point_2d(local_point.x(), local_point.y(), 0.0f);
841  return plane.bounds().inside(local_point_2d);
842 }
843 
844 // TODO comment on the scale
845 // https://github.com/cms-sw/cmssw/blob/CMSSW_12_0_0_pre3/DataFormats/GeometrySurface/src/SimpleDiskBounds.cc#L20-L35
847  const GlobalPoint& global_point,
848  const GlobalError& global_error,
849  const float scale) {
850  const LocalPoint local_point = plane.toLocal(global_point);
851  const LocalError local_error = ErrorFrameTransformer::transform(global_error, plane);
852 
853  const LocalPoint local_point_2d{local_point.x(), local_point.y(), 0.0f};
854  return plane.bounds().inside(local_point_2d, local_error, scale);
855 }
856 
858  const GlobalError& global_error,
859  const std::vector<const GEMChamber*>& chamber_vector) {
860  const GEMEtaPartition* bound = nullptr;
861  for (const GEMChamber* chamber : chamber_vector) {
862  if (not checkBounds(chamber->surface(), global_point, global_error, kBoundsErrorScale_)) {
863  continue;
864  }
865 
866  for (const GEMEtaPartition* eta_partition : chamber->etaPartitions()) {
867  if (checkBounds(eta_partition->surface(), global_point, global_error, kBoundsErrorScale_)) {
868  bound = eta_partition;
869  break;
870  }
871  } // GEMEtaPartition
872  } // GEMChamber
873 
874  return bound;
875 }
876 
877 // Borrowed from https://github.com/gem-sw/alignment/blob/713e8fa/GEMCSCBendingAnalyzer/MuonAnalyser/plugins/analyser.cc#L321-L327
879  const LocalPoint& hit_local_pos,
880  const GEMEtaPartition* eta_partition) {
881  const StripTopology& topology = eta_partition->specificTopology();
882  const LocalPoint prop_local_pos = eta_partition->toLocal(prop_global_pos);
883 
884  const float dx = prop_local_pos.x() - hit_local_pos.x();
885  const float dy = prop_local_pos.y() - hit_local_pos.y();
886  const float hit_strip = eta_partition->strip(hit_local_pos);
887  const float hit_phi = topology.stripAngle(hit_strip);
888  const float rdphi = std::cos(hit_phi) * dx - std::sin(hit_phi) * dy;
889  return rdphi;
890 }
891 
892 // Returns a global delta phi between a propagated muon and a reconstructed hit.
894  const LocalPoint& hit_local_pos,
895  const GEMEtaPartition* eta_partition) {
896  const GlobalPoint hit_global_pos = eta_partition->toGlobal(hit_local_pos);
897  const float dphi = Geom::convertRadToDeg(prop_global_pos.phi() - hit_global_pos.phi());
898  return dphi;
899 }
900 
901 // a thin wrapper to hide a messy conditional statement
903  const LocalPoint& hit_local_pos,
904  const GEMEtaPartition* eta_partition) {
905  float metric;
906  switch (kMatchingMetric_) {
908  metric = computeDeltaPhi(prop_global_pos, hit_local_pos, eta_partition);
909  break;
910  }
911  case MatchingMetric::kRdPhi: {
912  metric = computeRdPhi(prop_global_pos, hit_local_pos, eta_partition);
913  break;
914  }
915  default: {
916  edm::LogError(kLogCategory_) << "unknown MatchingMetric."; // TODO
918  }
919  }
920 
921  return metric;
922 }
923 
924 // This method finds the closest hit to a propagated muon in the eta partition
925 // with that propagated muon. Adjacent eta partitions are excluded from the area
926 // of interst to avoid ambiguity in defining the detection efficiency of each
927 // eta partition.
928 std::pair<const GEMRecHit*, float> GEMEfficiencyAnalyzer::findClosestHit(const GlobalPoint& prop_global_pos,
929  const GEMRecHitCollection::range& rechit_range,
930  const GEMEtaPartition* eta_partition) {
931  const GEMRecHit* closest_hit = nullptr;
932  float min_metric = std::numeric_limits<float>::infinity();
933 
934  for (auto hit = rechit_range.first; hit != rechit_range.second; ++hit) {
935  const LocalPoint hit_local_pos = hit->localPosition();
936 
937  const float metric = computeMatchingMetric(prop_global_pos, hit_local_pos, eta_partition);
938 
939  if (std::abs(metric) < std::abs(min_metric)) {
940  min_metric = metric;
941  closest_hit = &(*hit);
942  }
943  }
944 
945  return std::make_pair(closest_hit, min_metric);
946 }
947 
949  const GEMGeometry* gem = nullptr;
950  if (auto handle = setup.getHandle(kGEMGeometryTokenBeginRun_)) {
951  gem = handle.product();
952  } else {
953  edm::LogError(kLogCategory_ + "|dqmBeginRun") << "failed to get GEMGeometry";
954  return;
955  }
956 
958 }
959 
962  // get data from Event
964  const GEMRecHitCollection* rechit_collection = nullptr;
965  if (auto handle = event.getHandle(kGEMRecHitCollectionToken_)) {
966  rechit_collection = handle.product();
967  } else {
968  edm::LogError(kLogCategory_) << "failed to get GEMRecHitCollection";
969  return;
970  }
971 
972  const edm::View<reco::Muon>* muon_view = nullptr;
973  if (auto handle = event.getHandle(kMuonViewToken_)) {
974  muon_view = handle.product();
975  } else {
976  edm::LogError(kLogCategory_) << "failed to get View<Muon>";
977  return;
978  }
979 
980  const GEMOHStatusCollection* oh_status_collection = nullptr;
981  const GEMVFATStatusCollection* vfat_status_collection = nullptr;
983  if (auto handle = event.getHandle(kGEMOHStatusCollectionToken_)) {
984  oh_status_collection = handle.product();
985  } else {
986  edm::LogError(kLogCategory_) << "failed to get OHVFATStatusCollection";
987  return;
988  }
989 
990  if (auto handle = event.getHandle(kGEMVFATStatusCollectionToken_)) {
991  vfat_status_collection = handle.product();
992  } else {
993  edm::LogError(kLogCategory_) << "failed to get GEMVFATStatusCollection";
994  return;
995  }
996  }
997 
999  // get data from EventSetup
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 
1010  // get more data from EventSetup using MuonServiceProxy
1012  muon_service_->update(setup);
1013 
1014  // TODO StraightLinePropagator if B < epsilon else SteppingHelixPropagatorAny
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 
1024  // Main loop
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_) {
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  // the trajectory state on the destination surface
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 
1089  //
1091  const GEMDetId rs_key = getReStKey(gem_id); // region-station
1092  const GEMDetId rsl_key = getReStLaKey(gem_id); // region-station-layer
1093  const GEMDetId rse_key = getReStEtKey(gem_id); // region-station-ieta
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  // cuts
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 
1124  // Fill denominators
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  } // dev mode
1154 
1156  // Find a closet hit
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 
1176  // Fill numerators
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 
1210  // Fill resolutions
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  } // kModeDev_
1238  } // passed_all_cuts
1239  } // destination
1240  } // Muon
1241 } // analyze
static DiskPointer build(Args &&... args)
Definition: BoundDisk.h:38
const Track & track() const
static GlobalError transform(const LocalError &le, const Surface &surf)
virtual int dimension() const =0
constexpr int station() const
Definition: GEMDetId.h:179
bool isInsideOut(const reco::Track &)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
StartingState buildStartingStateAlignmentStyle(const reco::Muon &, const reco::TransientTrack &, const GEMLayer &)
MPlex< T, D1, D2, N > hypot(const MPlex< T, D1, D2, N > &a, const MPlex< T, D1, D2, N > &b)
Definition: Matriplex.h:436
std::pair< const_iterator, const_iterator > range
iterator range
Definition: RangeMap.h:50
constexpr int region() const
Definition: GEMDetId.h:171
static bool isCSC(unsigned int detId)
TString getSuffixName(Int_t region_id)
CSCSegmentRef cscSegmentRef
const std::vector< double > kMuonEtaLow_
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
std::tuple< bool, TrajectoryStateOnSurface, DetId > StartingState
virtual bool inside(const Local3DPoint &) const =0
Determine if the point is inside the bounds.
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:58
void setAllowAnything()
allow any parameter label/value pairs
MonitorElement * bookChamberEtaPartition(DQMStore::IBooker &, const TString &, const TString &, const GEMStation *)
std::unique_ptr< MuonServiceProxy > muon_service_
trackingRecHit_iterator recHitsEnd() const
last iterator to RecHits
const std::vector< double > kMuonPtBins_
const std::vector< double > kMuonPtMinCuts_
MonitorElement * bookNumerator2D(DQMStore::IBooker &, MonitorElement *)
void buildGEMLayers(const GEMGeometry *)
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
constexpr NumType convertRadToDeg(NumType radians)
Definition: angle_units.h:21
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
bool checkBounds(const Plane &, const GlobalPoint &)
float strip(const LocalPoint &lp) const
void fillMEWithinLimits(MonitorElement *, const double)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
float computeRdPhi(const GlobalPoint &, const LocalPoint &, const GEMEtaPartition *)
bool maskChamberWithError(const GEMDetId &chamber_id, const GEMOHStatusCollection *, const GEMVFATStatusCollection *)
trackingRecHit_iterator recHitsBegin() const
first iterator to RecHits
Log< level::Error, false > LogError
TString getSuffixTitle(Int_t region_id)
constexpr int layer() const
Definition: GEMDetId.h:190
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
unsigned short iChamberType() const
Definition: CSCDetId.h:96
LocalPoint toLocal(const GlobalPoint &gp) const
const edm::EDGetTokenT< GEMVFATStatusCollection > kGEMVFATStatusCollectionToken_
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
const edm::EDGetTokenT< GEMRecHitCollection > kGEMRecHitCollectionToken_
const edm::EDGetTokenT< edm::View< reco::Muon > > kMuonViewToken_
static const unsigned int BestInStationByDR
Definition: Plane.h:16
scenario
Definition: constants.h:219
constexpr int chamber() const
Definition: GEMDetId.h:183
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
T phierr(const GlobalPoint &aPoint) const
const MatchingMetric kMatchingMetric_
StartingStateType getStartingStateType(const std::string)
const CSCSegment * findCSCSegmentBeam(const reco::TransientTrack &, const GEMLayer &)
void fillME(MEMap &, const GEMDetId &, const double)
const reco::Muon::MuonTrackType kMuonTrackType_
reco::Muon::MuonTrackType getMuonTrackType(const std::string)
const std::vector< std::vector< int > > kCSCForGEM_
GEMDetId id() const
T getUntrackedParameter(std::string const &, T const &) const
reco::TransientTrack build(const reco::Track *p) const
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
StartingState getOutermostMeasurementState(const reco::TransientTrack &)
const std::vector< std::vector< int > > kMuonSubdetForGEM_
Definition: Muon.py:1
const std::vector< double > kMuonEtaMaxCuts_
bool isValid() const
TrajectoryStateOnSurface outermostMeasurementState() const
MonitorElement * bookNumerator1D(DQMStore::IBooker &, MonitorElement *)
T sqrt(T t)
Definition: SSEVec.h:19
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
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
const edm::ESGetToken< GEMGeometry, MuonGeometryRecord > kGEMGeometryTokenBeginRun_
ScenarioOption getScenarioOption(const std::string)
const std::vector< double > kMuonEtaUp_
const double infinity
bool isMask(unsigned int flag=Arbitrated) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Transition
Definition: Transition.h:12
void analyze(const edm::Event &event, const edm::EventSetup &eventSetup) override
key
prepare the HTCondor submission files and eventually submit them
const GEMEtaPartition * findEtaPartition(const GlobalPoint &, const GlobalError &, const std::vector< const GEMChamber *> &)
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
TrajectoryStateOnSurface innermostMeasurementState() const
const CSCSegment * findCSCSegment(const reco::Muon &, const reco::TransientTrack &, const GEMLayer &)
StartingState buildStartingState(const reco::Muon &, const reco::TransientTrack &, const GEMLayer &)
GEMDetId getReStKey(const int, const int)
GEMEfficiencyAnalyzer(const edm::ParameterSet &)
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:49
const std::vector< int > kMuonEtaNbins_
constexpr int ieta() const
Definition: GEMDetId.h:199
Log< level::Info, false > LogInfo
const edm::EDGetTokenT< GEMOHStatusCollection > kGEMOHStatusCollectionToken_
Definition: DetId.h:17
StartingState getInnermostMeasurementState(const reco::TransientTrack &)
const std::string kMuonTrackTypeName_
bool checkRefs(const std::vector< T *> &)
DetId geographicalId() const
std::vector< GEMLayer > gem_layers_
static void fillDescriptions(edm::ConfigurationDescriptions &)
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > kTransientTrackBuilderToken_
void dqmBeginRun(edm::Run const &, edm::EventSetup const &) override
const ScenarioOption kScenario_
float computeDeltaPhi(const GlobalPoint &, const LocalPoint &, const GEMEtaPartition *)
bool isCSCAllowed(const CSCDetId &, const int)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TrajectoryStateOnSurface stateOnSurface(const GlobalPoint &point) const
static bool isGEM(unsigned int detId)
Definition: MuonHitHelper.cc:7
const StripTopology & specificTopology() const
float computeMatchingMetric(const GlobalPoint &, const LocalPoint &, const GEMEtaPartition *)
fixed size matrix
HLT enums.
StartingState buildStateOnSurfaceWithCSCSegment(const reco::Muon &, const reco::TransientTrack &, const GEMLayer &)
static int position[264][3]
Definition: ReadPGInfo.cc:289
T rerr(const GlobalPoint &aPoint) const
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
constexpr GEMDetId chamberId() const
Definition: GEMDetId.h:204
bool checkPropagationDirection(const reco::Track *, const GEMLayer &)
MuonTrackType
map for Global Muon refitters
Definition: Muon.h:36
const std::vector< double > kMuonEtaMinCuts_
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
bool isValid() const
Make the ReferenceCountingProxy method to check validity public.
GEMDetId getReStLaKey(const GEMDetId &)
MatchingMetric getMatchingMetric(const std::string)
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
static char chambers[264][20]
Definition: ReadPGInfo.cc:243
GEMDetId getReStEtKey(const GEMDetId &)
const StartingStateType kStartingStateType_
Definition: event.py:1
Definition: Run.h:45
#define LogDebug(id)
std::pair< const GEMRecHit *, float > findClosestHit(const GlobalPoint &, const GEMRecHitCollection::range &, const GEMEtaPartition *)
const Bounds & bounds() const
Definition: Surface.h:87
bool isMuonSubdetAllowed(const DetId &, const int)
const CSCSegment * findCSCSegmentCosmics(const reco::Muon &, const GEMLayer &)
A container for a generic type of digis indexed by some index, implemented with a map<IndexType...