CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GEMEfficiencyAnalyzer.cc
Go to the documentation of this file.
2 
12 
14  : GEMOfflineDQMBase(pset),
15  gemToken1_(esConsumes<edm::Transition::BeginRun>()),
18  trasientTrackToken_(
19  esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))) {
20  name_ = pset.getUntrackedParameter<std::string>("name");
21  folder_ = pset.getUntrackedParameter<std::string>("folder");
22 
23  rechit_token_ = consumes<GEMRecHitCollection>(pset.getParameter<edm::InputTag>("recHitTag"));
24  muon_token_ = consumes<edm::View<reco::Muon> >(pset.getParameter<edm::InputTag>("muonTag"));
25 
26  is_cosmics_ = pset.getUntrackedParameter<bool>("isCosmics");
27  use_global_muon_ = pset.getUntrackedParameter<bool>("useGlobalMuon");
28  use_skip_layer_ = pset.getParameter<bool>("useSkipLayer");
29  use_only_me11_ = pset.getParameter<bool>("useOnlyME11");
30  residual_rphi_cut_ = static_cast<float>(pset.getParameter<double>("residualRPhiCut"));
31  use_prop_r_error_cut_ = pset.getParameter<bool>("usePropRErrorCut");
32  prop_r_error_cut_ = pset.getParameter<double>("propRErrorCut");
33  use_prop_phi_error_cut_ = pset.getParameter<bool>("usePropPhiErrorCut");
34  prop_phi_error_cut_ = pset.getParameter<double>("propPhiErrorCut");
35  pt_bins_ = pset.getUntrackedParameter<std::vector<double> >("ptBins");
36  eta_nbins_ = pset.getUntrackedParameter<int>("etaNbins");
37  eta_low_ = pset.getUntrackedParameter<double>("etaLow");
38  eta_up_ = pset.getUntrackedParameter<double>("etaUp");
39  monitor_ge11_ = pset.getUntrackedParameter<bool>("monitorGE11");
40  monitor_ge21_ = pset.getUntrackedParameter<bool>("monitorGE21");
41  monitor_ge0_ = pset.getUntrackedParameter<bool>("monitorGE0");
42 
43  const edm::ParameterSet muon_service_parameter = pset.getParameter<edm::ParameterSet>("ServiceParameters");
44  muon_service_ = new MuonServiceProxy(muon_service_parameter, consumesCollector());
45 
47  pt_clamp_max_ = pt_bins_.back() - eps;
48  eta_clamp_max_ = eta_up_ - eps;
49 
50  // TODO pt, eta, quality check for muons
51 }
52 
54 
56  // beam scenario
57  {
59  desc.addUntracked<std::string>("name", "GlobalMuon");
60  desc.addUntracked<std::string>("folder", "GEM/Efficiency/type0");
61  desc.add<edm::InputTag>("recHitTag", edm::InputTag("gemRecHits"));
62  desc.add<edm::InputTag>("muonTag", edm::InputTag("muons"));
63  desc.addUntracked<bool>("isCosmics", false);
64  desc.addUntracked<bool>("useGlobalMuon", true);
65  desc.add<bool>("useSkipLayer", true);
66  desc.add<bool>("useOnlyME11", false);
67  desc.add<double>("residualRPhiCut", 2.0); // TODO need to be tuned
68  desc.add<bool>("usePropRErrorCut", false);
69  desc.add<double>("propRErrorCut", 1.0);
70  desc.add<bool>("usePropPhiErrorCut", false);
71  desc.add<double>("propPhiErrorCut", 0.01);
72  desc.addUntracked<std::vector<double> >("ptBins", {20., 30., 40., 50., 60., 70., 80., 90., 100., 120.});
73  desc.addUntracked<int>("etaNbins", 9);
74  desc.addUntracked<double>("etaLow", 1.4);
75  desc.addUntracked<double>("etaUp", 2.3);
76  desc.addUntracked<bool>("monitorGE11", true);
77  desc.addUntracked<bool>("monitorGE21", false);
78  desc.addUntracked<bool>("monitorGE0", false);
79  {
81  psd0.setAllowAnything();
82  desc.add<edm::ParameterSetDescription>("ServiceParameters", psd0);
83  }
84  descriptions.add("gemEfficiencyAnalyzerDefault", desc);
85  } // beam scenario
86 }
87 
89  edm::Run const& run,
90  edm::EventSetup const& isetup) {
92  gem = isetup.getHandle(gemToken1_);
93 
94  if (not gem.isValid()) {
95  edm::LogError(kLogCategory_) << "GEMGeometry is invalid" << std::endl;
96  return;
97  }
98 
99  bookEfficiencyMomentum(ibooker, gem);
100  bookEfficiencyChamber(ibooker, gem);
101  bookEfficiencyEtaPartition(ibooker, gem);
102  bookEfficiencyDetector(ibooker, gem);
103  bookResolution(ibooker, gem);
104  bookMisc(ibooker, gem);
105 }
106 
108  const std::string name = me->getName() + "_matched";
109  TH1F* hist = dynamic_cast<TH1F*>(me->getTH1F()->Clone(name.c_str()));
110  return ibooker.book1D(name, hist);
111 }
112 
114  const std::string name = me->getName() + "_matched";
115  TH2F* hist = dynamic_cast<TH2F*>(me->getTH2F()->Clone(name.c_str()));
116  return ibooker.book2D(name, hist);
117 }
118 
120  // TODO Efficiency/Source
121  ibooker.setCurrentFolder(folder_ + "/Efficiency");
122 
123  const TString pt_x_title = "Muon p_{T} [GeV]";
124  const int pt_nbinsx = pt_bins_.size() - 1;
125 
126  const std::string eta_x_title = "Muon |#eta|";
127  const std::string phi_x_title = "Muon #phi [rad]";
128 
129  for (const GEMStation* station : gem->stations()) {
130  const int region_id = station->region();
131  const int station_id = station->station();
132 
133  if (skipGEMStation(station_id)) {
134  continue;
135  }
136 
137  const GEMDetId key = getReStKey(region_id, station_id);
138  const TString name_suffix = GEMUtils::getSuffixName(region_id, station_id);
139  const TString title_suffix = GEMUtils::getSuffixTitle(region_id, station_id);
140 
141  const TString title = name_.c_str() + title_suffix;
142 
143  TH1F* h_muon_pt = new TH1F("muon_pt" + name_suffix, title, pt_nbinsx, &pt_bins_[0]);
144  h_muon_pt->SetXTitle(pt_x_title);
145  me_muon_pt_[key] = ibooker.book1D(h_muon_pt->GetName(), h_muon_pt);
147 
148  me_muon_eta_[key] = ibooker.book1D("muon_eta" + name_suffix, title, eta_nbins_, eta_low_, eta_up_);
149  me_muon_eta_[key]->setXTitle(eta_x_title);
151 
152  me_muon_phi_[key] = ibooker.book1D("muon_phi" + name_suffix, title, 36, -M_PI, M_PI);
153  me_muon_phi_[key]->setAxisTitle(phi_x_title);
155  } // station
156 }
157 
159  // TODO Efficiency/Source
160  ibooker.setCurrentFolder(folder_ + "/Efficiency");
161 
162  for (const GEMStation* station : gem->stations()) {
163  const int region_id = station->region();
164  const int station_id = station->station();
165 
166  if (skipGEMStation(station_id)) {
167  continue;
168  }
169 
170  const std::vector<const GEMSuperChamber*> superchambers = station->superChambers();
171  if (not checkRefs(superchambers)) {
172  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMSuperChamber ptrs" << std::endl;
173  return;
174  }
175 
176  const int num_chambers = superchambers.size();
177  for (const GEMChamber* chamber : superchambers[0]->chambers()) {
178  const int layer_id = chamber->id().layer();
179 
180  const TString name_suffix = GEMUtils::getSuffixName(region_id, station_id, layer_id);
181  const TString title_suffix = GEMUtils::getSuffixTitle(region_id, station_id, layer_id);
182  const GEMDetId key = getReStLaKey(chamber->id());
183 
184  me_chamber_[key] =
185  ibooker.book1D("chamber" + name_suffix, name_.c_str() + title_suffix, num_chambers, 0.5, num_chambers + 0.5);
186  me_chamber_[key]->setAxisTitle("Chamber");
187  me_chamber_[key]->getTH1F()->SetNdivisions(-num_chambers, "Y");
188  for (int binx = 1; binx <= num_chambers; binx++) {
189  me_chamber_[key]->setBinLabel(binx, std::to_string(binx));
190  }
191 
192  me_chamber_matched_[key] = bookNumerator1D(ibooker, me_chamber_[key]);
193  } // layer
194  } // station
195 }
196 
198  const edm::ESHandle<GEMGeometry>& gem) {
199  // TODO Efficiency/Source
200  ibooker.setCurrentFolder(folder_ + "/Efficiency");
201 
202  for (const GEMStation* station : gem->stations()) {
203  const int region_id = station->region();
204  const int station_id = station->station();
205 
206  if (skipGEMStation(station_id)) {
207  continue;
208  }
209 
210  const std::vector<const GEMSuperChamber*> superchambers = station->superChambers();
211  if (not checkRefs(superchambers)) {
212  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMSuperChamber ptrs" << std::endl;
213  return;
214  }
215 
216  for (const GEMChamber* chamber : superchambers[0]->chambers()) {
217  const int layer_id = chamber->id().layer();
218  const int num_ieta = chamber->nEtaPartitions();
219 
220  const TString name_suffix = GEMUtils::getSuffixName(region_id, station_id, layer_id);
221  const TString title_suffix = GEMUtils::getSuffixTitle(region_id, station_id, layer_id);
222  const GEMDetId key = getReStLaKey(chamber->id());
223 
224  me_ieta_[key] = ibooker.book1D("ieta" + name_suffix, name_.c_str() + title_suffix, num_ieta, 0.5, num_ieta + 0.5);
225  me_ieta_[key]->setAxisTitle("i#eta");
226  me_ieta_[key]->getTH1F()->SetNdivisions(-num_ieta, "Y");
227  for (int binx = 1; binx <= num_ieta; binx++) {
228  me_ieta_[key]->setBinLabel(binx, std::to_string(binx));
229  }
230 
231  me_ieta_matched_[key] = bookNumerator1D(ibooker, me_ieta_[key]);
232  } // layer
233  } // station
234 }
235 
237  // TODO Efficiency/Source
238  ibooker.setCurrentFolder(folder_ + "/Efficiency");
239 
240  for (const GEMStation* station : gem->stations()) {
241  const int region_id = station->region();
242  const int station_id = station->station();
243 
244  if (skipGEMStation(station_id)) {
245  continue;
246  }
247 
248  const std::vector<const GEMSuperChamber*> superchambers = station->superChambers();
249  if (not checkRefs(superchambers)) {
250  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMSuperChamber ptrs" << std::endl;
251  return;
252  }
253 
254  const int num_ch = superchambers.size();
255 
256  for (const GEMChamber* chamber : superchambers[0]->chambers()) {
257  const int layer_id = chamber->id().layer();
258  const int num_ieta = chamber->nEtaPartitions();
259 
260  const TString name_suffix = GEMUtils::getSuffixName(region_id, station_id, layer_id);
261  const TString title_suffix = GEMUtils::getSuffixTitle(region_id, station_id, layer_id);
262  const GEMDetId key = getReStLaKey(chamber->id());
263 
264  me_detector_[key] = ibooker.book2D("detector" + name_suffix,
265  name_.c_str() + title_suffix,
266  num_ch,
267  0.5,
268  num_ch + 0.5,
269  num_ieta,
270  0.5,
271  num_ieta + 0.5);
272  setDetLabelsEta(me_detector_[key], station);
273 
274  me_detector_matched_[key] = bookNumerator2D(ibooker, me_detector_[key]);
275  } // layer
276  } // station
277 }
278 
280  ibooker.setCurrentFolder(folder_ + "/Resolution");
281  for (const GEMStation* station : gem->stations()) {
282  const int region_id = station->region();
283  const int station_id = station->station();
284 
285  if (skipGEMStation(station_id)) {
286  continue;
287  }
288 
289  const std::vector<const GEMSuperChamber*> superchambers = station->superChambers();
290  if (not checkRefs(superchambers)) {
291  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMSuperChamber ptrs" << std::endl;
292  return;
293  }
294 
295  const std::vector<const GEMChamber*> chambers = superchambers[0]->chambers();
296  if (not checkRefs(chambers)) {
297  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMChamber ptrs" << std::endl;
298  return;
299  }
300 
301  for (const GEMEtaPartition* eta_partition : chambers[0]->etaPartitions()) {
302  const int ieta = eta_partition->id().roll();
303 
304  const GEMDetId key = getReStEtKey(eta_partition->id());
305  // TODO
306  const TString name_suffix = TString::Format("_GE%+.2d_R%d", region_id * (station_id * 10 + 1), ieta);
307  const TString title =
308  name_.c_str() + TString::Format(" : GE%+.2d Roll %d", region_id * (station_id * 10 + 1), ieta);
309 
311  ibooker.book1D("residual_rphi" + name_suffix, title, 50, -residual_rphi_cut_, residual_rphi_cut_);
312  me_residual_rphi_[key]->setAxisTitle("Residual in R#phi [cm]");
313 
314  me_residual_y_[key] = ibooker.book1D("residual_y" + name_suffix, title, 60, -12.0, 12.0);
315  me_residual_y_[key]->setAxisTitle("Residual in Local Y [cm]");
316 
317  me_pull_y_[key] = ibooker.book1D("pull_y" + name_suffix, title, 60, -3.0, 3.0);
318  me_pull_y_[key]->setAxisTitle("Pull in Local Y");
319  } // ieta
320  } // station
321 }
322 
324  ibooker.setCurrentFolder(folder_ + "/Misc");
325  // FIXME the range shoule be dependent on the scenario
326  me_prop_r_err_ = ibooker.book1D("prop_r_err", ";Propagation Global R Error [cm];Entries", 20, 0.0, 20.0);
327  me_prop_phi_err_ = ibooker.book1D("prop_phi_err", "Propagation Global Phi Error [rad];Entries", 20, 0.0, M_PI);
328  me_all_abs_residual_rphi_ = ibooker.book1D("all_abs_residual_rphi", ";Residual in R#phi [cm];Entries", 20, 0.0, 20.0);
329 
330  for (const GEMStation* station : gem->stations()) {
331  const int region_id = station->region();
332  const int station_id = station->station();
333 
334  if (skipGEMStation(station_id)) {
335  continue;
336  }
337 
338  const std::vector<const GEMSuperChamber*> superchambers = station->superChambers();
339  if (not checkRefs(superchambers)) {
340  edm::LogError(kLogCategory_) << "failed to get a valid vector of GEMSuperChamber ptrs" << std::endl;
341  return;
342  }
343  // ignore layer ids
344  const int num_ch = superchambers.size();
345 
346  const GEMDetId key = getReStKey(region_id, station_id);
347  const TString name_suffix = GEMUtils::getSuffixName(region_id, station_id);
348  const TString title_suffix = GEMUtils::getSuffixTitle(region_id, station_id);
349  me_prop_chamber_[key] = ibooker.book1D("prop_chamber" + name_suffix, title_suffix, num_ch, 0.5, num_ch + 0.5);
350  me_prop_chamber_[key]->setAxisTitle("Destination Chamber Id", 1);
351  me_prop_chamber_[key]->setAxisTitle("Entries", 2);
352  } // station
353 }
354 
356  edm::Handle<GEMRecHitCollection> rechit_collection;
357  event.getByToken(rechit_token_, rechit_collection);
358  if (not rechit_collection.isValid()) {
359  edm::LogError(kLogCategory_) << "GEMRecHitCollection is invalid" << std::endl;
360  return;
361  }
362 
364  event.getByToken(muon_token_, muon_view);
365  if (not muon_view.isValid()) {
366  edm::LogError(kLogCategory_) << "View<Muon> is invalid" << std::endl;
367  return;
368  }
369 
371  gem = setup.getHandle(gemToken2_);
372 
373  if (not gem.isValid()) {
374  edm::LogError(kLogCategory_) << "GEMGeometry is invalid" << std::endl;
375  return;
376  }
377 
378  edm::ESHandle<GlobalTrackingGeometry> global_tracking_geometry;
379 
380  global_tracking_geometry = setup.getHandle(globalGeomToken_);
381 
382  if (not global_tracking_geometry.isValid()) {
383  edm::LogError(kLogCategory_) << "GlobalTrackingGeometry is invalid" << std::endl;
384  return;
385  }
386 
387  edm::ESHandle<TransientTrackBuilder> transient_track_builder;
388  transient_track_builder = setup.getHandle(trasientTrackToken_);
389 
390  if (not transient_track_builder.isValid()) {
391  edm::LogError(kLogCategory_) << "TransientTrackRecord is invalid" << std::endl;
392  return;
393  }
394 
395  muon_service_->update(setup);
396  edm::ESHandle<Propagator> propagator = muon_service_->propagator("SteppingHelixPropagatorAny");
397  if (not propagator.isValid()) {
398  edm::LogError(kLogCategory_) << "Propagator is invalid" << std::endl;
399  return;
400  }
401 
402  if (rechit_collection->size() < 1) {
403  edm::LogInfo(kLogCategory_) << "empty rechit collection" << std::endl;
404  return;
405  }
406 
407  if (muon_view->empty()) {
408  edm::LogInfo(kLogCategory_) << "empty muon collection" << std::endl;
409  return;
410  }
411 
412  const std::vector<GEMLayerData> layer_vector = buildGEMLayers(gem);
413 
414  for (const reco::Muon& muon : *muon_view) {
415  const reco::Track* track = getTrack(muon);
416  if (track == nullptr) {
417  edm::LogError(kLogCategory_) << "failed to get a muon track" << std::endl;
418  continue;
419  }
420 
421  const reco::TransientTrack transient_track = transient_track_builder->build(track);
422  if (not transient_track.isValid()) {
423  edm::LogError(kLogCategory_) << "failed to build TransientTrack" << std::endl;
424  continue;
425  }
426 
427  for (const GEMLayerData& layer : layer_vector) {
428  if (use_skip_layer_ and skipLayer(track, layer)) {
429  edm::LogInfo(kLogCategory_) << "skip GEM Layer" << std::endl;
430  continue;
431  }
432 
433  const auto [start_state, start_id] = getStartingState(transient_track, layer, global_tracking_geometry);
434 
435  if (not start_state.isValid()) {
436  edm::LogInfo(kLogCategory_) << "failed to get a starting state" << std::endl;
437  continue;
438  }
439 
440  if (use_only_me11_ and (not isME11(start_id))) {
441  edm::LogInfo(kLogCategory_) << "skip a starting state because it is not ME11" << std::endl;
442  continue;
443  }
444 
445  // the trajectory state on the destination surface
446  const TrajectoryStateOnSurface dest_state = propagator->propagate(start_state, *(layer.disk));
447  if (not dest_state.isValid()) {
448  edm::LogInfo(kLogCategory_) << "failed to propagate a muon" << std::endl;
449  continue;
450  }
451 
452  const GlobalPoint dest_global_pos = dest_state.globalPosition();
453 
454  if (not checkBounds(dest_global_pos, (*layer.disk))) {
455  edm::LogInfo(kLogCategory_) << "failed to pass checkBounds" << std::endl;
456  continue;
457  }
458 
459  const GEMEtaPartition* eta_partition = findEtaPartition(dest_global_pos, layer.chambers);
460  if (eta_partition == nullptr) {
461  edm::LogInfo(kLogCategory_) << "failed to find an eta partition" << std::endl;
462  continue;
463  }
464 
465  const BoundPlane surface = eta_partition->surface();
466 
467  const LocalPoint dest_local_pos = eta_partition->toLocal(dest_global_pos);
468  const LocalError dest_local_err = dest_state.localError().positionError();
469  const GlobalError dest_global_err = ErrorFrameTransformer().transform(dest_local_err, surface);
470 
471  const double dest_global_r_err = std::sqrt(dest_global_err.rerr(dest_global_pos));
472  const double dest_global_phi_err = std::sqrt(dest_global_err.phierr(dest_global_pos));
473 
474  const GEMDetId gem_id = eta_partition->id();
475  const GEMDetId rs_key = getReStKey(gem_id);
476  const GEMDetId rsl_key = getReStLaKey(gem_id);
477  const GEMDetId rse_key = getReStEtKey(gem_id);
478 
479  const int chamber_id = gem_id.chamber();
480  const int ieta = gem_id.ieta();
481 
482  // FIXME clever way to clamp values?
483  me_prop_r_err_->Fill(std::min(dest_global_r_err, 19.999));
484  me_prop_phi_err_->Fill(std::min(dest_global_r_err, M_PI - 0.0001));
485  me_prop_chamber_[rs_key]->Fill(gem_id.chamber());
486 
487  if (use_prop_r_error_cut_ and (dest_global_r_err > prop_r_error_cut_)) {
488  edm::LogInfo(kLogCategory_) << "failed to pass a propagation global R error cut" << std::endl;
489  continue;
490  }
491 
492  if (use_prop_phi_error_cut_ and (dest_global_phi_err > prop_phi_error_cut_)) {
493  edm::LogInfo(kLogCategory_) << "failed to pass a propagation global phi error cut" << std::endl;
494  continue;
495  }
496 
497  const double muon_pt = std::min(muon.pt(), pt_clamp_max_);
498  const double muon_eta = std::clamp(std::fabs(muon.eta()), eta_low_, eta_clamp_max_);
499 
500  fillME(me_muon_pt_, rs_key, muon_pt);
501  fillME(me_muon_eta_, rs_key, muon_eta);
502  fillME(me_muon_phi_, rs_key, muon.phi());
503 
504  fillME(me_chamber_, rsl_key, chamber_id);
505  fillME(me_ieta_, rsl_key, ieta);
506  fillME(me_detector_, rsl_key, chamber_id, ieta);
507 
508  const auto [hit, residual_rphi] = findClosetHit(dest_global_pos, rechit_collection->get(gem_id), eta_partition);
509 
510  if (hit == nullptr) {
511  edm::LogInfo(kLogCategory_) << "failed to find a hit" << std::endl;
512  continue;
513  }
514 
515  me_all_abs_residual_rphi_->Fill(std::min(std::abs(residual_rphi), 19.999f));
516  if (std::abs(residual_rphi) > residual_rphi_cut_) {
517  edm::LogInfo(kLogCategory_) << "failed to pass the residual rphi cut" << std::endl;
518  continue;
519  }
520 
521  fillME(me_muon_pt_matched_, rs_key, muon_pt);
522  fillME(me_muon_eta_matched_, rs_key, muon_eta);
523  fillME(me_muon_phi_matched_, rs_key, muon.phi());
524 
525  fillME(me_chamber_matched_, rsl_key, gem_id.chamber());
526  fillME(me_ieta_matched_, rsl_key, gem_id.ieta());
527  fillME(me_detector_matched_, rsl_key, gem_id.chamber(), ieta);
528 
529  const LocalPoint hit_local_pos = hit->localPosition();
530  const LocalError hit_local_err = hit->localPositionError();
531 
532  const float residual_y = dest_local_pos.y() - hit_local_pos.y();
533  const float pull_y = residual_y / std::sqrt(dest_local_err.yy() + hit_local_err.yy());
534 
535  fillME(me_residual_rphi_, rse_key, residual_rphi);
536  fillME(me_residual_y_, rse_key, residual_y);
537  fillME(me_pull_y_, rse_key, pull_y);
538  } // layer
539  } // Muon
540 }
541 
543  bool skip = false;
544 
545  if (station == 1) {
546  if (not monitor_ge11_) {
547  LogDebug(kLogCategory_) << "skip GE11 because monitorGE11 is " << std::boolalpha << monitor_ge11_;
548  skip = true;
549  }
550 
551  } else if (station == 2) {
552  if (not monitor_ge21_) {
553  LogDebug(kLogCategory_) << "skip GE21 because monitorGE21 is " << std::boolalpha << monitor_ge21_;
554  skip = true;
555  }
556 
557  } else if (station == 0) {
558  if (not monitor_ge0_) {
559  LogDebug(kLogCategory_) << "skip GE0 because monitorGE0 is " << std::boolalpha << monitor_ge0_;
560  skip = true;
561  }
562 
563  } else {
564  edm::LogError(kLogCategory_) << "got an unexpected GEM station " << station << ". skip this station.";
565  skip = true;
566  }
567 
568  return skip;
569 }
570 
571 std::vector<GEMEfficiencyAnalyzer::GEMLayerData> GEMEfficiencyAnalyzer::buildGEMLayers(
572  const edm::ESHandle<GEMGeometry>& gem) {
573  std::vector<GEMLayerData> layer_vector;
574 
575  for (const GEMStation* station : gem->stations()) {
576  const int region_id = station->region();
577  const int station_id = station->station();
578  const bool is_ge11 = station_id == 1;
579 
580  if (skipGEMStation(station_id)) {
581  continue;
582  }
583 
584  // (layer_id, is_odd) - chambers
585  std::map<std::pair<int, bool>, std::vector<const GEMChamber*> > chambers_per_layer;
586 
587  for (const GEMSuperChamber* super_chamber : station->superChambers()) {
588  // For GE0 and GE21, 'is_odd' is always set to 'false'
589  const bool is_odd = is_ge11 ? super_chamber->id().chamber() % 2 == 1 : false;
590 
591  for (const GEMChamber* chamber : super_chamber->chambers()) {
592  const int layer_id = chamber->id().layer();
593  const std::pair<int, bool> key{layer_id, is_odd};
594 
595  if (chambers_per_layer.find(key) == chambers_per_layer.end())
596  chambers_per_layer.insert({key, std::vector<const GEMChamber*>()});
597 
598  chambers_per_layer.at(key).push_back(chamber);
599  } // GEMChamber
600  } // GEMSuperChamber
601 
602  for (auto [key, chamber_vector] : chambers_per_layer) {
603  const int layer_id = key.first;
604 
605  // chambers should have same R and Z spans.
606  auto [rmin, rmax] = chamber_vector[0]->surface().rSpan();
607  auto [zmin, zmax] = chamber_vector[0]->surface().zSpan();
608 
609  // layer position and rotation
610  const float layer_z = chamber_vector[0]->position().z();
611  Surface::PositionType position{0.f, 0.f, layer_z};
613 
614  zmin -= layer_z;
615  zmax -= layer_z;
616 
617  // the bounds from min and max R and Z in the local coordinates.
618  SimpleDiskBounds* bounds = new SimpleDiskBounds(rmin, rmax, zmin, zmax);
619  const Disk::DiskPointer layer = Disk::build(position, rotation, bounds);
620 
621  layer_vector.emplace_back(layer, chamber_vector, region_id, station_id, layer_id);
622  } // layer
623  } // GEMStation
624 
625  return layer_vector;
626 }
627 
629  const reco::Track* track = nullptr;
630 
631  if (is_cosmics_) {
632  if (muon.outerTrack().isNonnull())
633  track = muon.outerTrack().get();
634 
635  } else {
636  // beams, i.e. pp or heavy ions
637  if (use_global_muon_ and muon.globalTrack().isNonnull())
638  track = muon.globalTrack().get();
639 
640  else if ((not use_global_muon_) and muon.outerTrack().isNonnull())
641  track = muon.outerTrack().get();
642  }
643 
644  return track;
645 }
646 
647 std::pair<TrajectoryStateOnSurface, DetId> GEMEfficiencyAnalyzer::getStartingState(
648  const reco::TransientTrack& transient_track,
649  const GEMLayerData& layer,
651  TrajectoryStateOnSurface starting_state;
652  DetId starting_id;
653 
654  if (use_global_muon_) {
655  std::tie(starting_state, starting_id) = findStartingState(transient_track, layer, geometry);
656 
657  } else {
658  // if outer track
659  const reco::Track& track = transient_track.track();
660  const bool is_insideout = isInsideOut(track);
661 
662  const DetId inner_id{(is_insideout ? track.outerDetId() : track.innerDetId())};
663  if (MuonHitHelper::isGEM(inner_id.rawId())) {
664  std::tie(starting_state, starting_id) = findStartingState(transient_track, layer, geometry);
665 
666  } else {
667  starting_id = inner_id;
668  if (is_insideout)
669  starting_state = transient_track.outermostMeasurementState();
670  else
671  starting_state = transient_track.innermostMeasurementState();
672  }
673  }
674 
675  return std::make_pair(starting_state, starting_id);
676 }
677 
678 std::pair<TrajectoryStateOnSurface, DetId> GEMEfficiencyAnalyzer::findStartingState(
679  const reco::TransientTrack& transient_track,
680  const GEMLayerData& layer,
681  const edm::ESHandle<GlobalTrackingGeometry>& geometry) {
682  GlobalPoint starting_point;
683  DetId starting_id;
684  float min_distance = 1e12;
685  bool found = false;
686 
687  // TODO optimize this loop because hits should be ordered..
688  for (auto rechit = transient_track.recHitsBegin(); rechit != transient_track.recHitsEnd(); rechit++) {
689  const DetId det_id = (*rechit)->geographicalId();
690 
691  if (MuonHitHelper::isGEM(det_id.rawId())) {
692  continue;
693  }
694 
695  const GeomDet* det = geometry->idToDet(det_id);
696  const GlobalPoint global_position = det->toGlobal((*rechit)->localPosition());
697  const float distance = std::abs(layer.disk->localZclamped(global_position));
698  if (distance < min_distance) {
699  found = true;
700  min_distance = distance;
701  starting_point = global_position;
702  starting_id = det_id;
703  }
704  }
705 
706  TrajectoryStateOnSurface starting_state;
707  if (found) {
708  starting_state = transient_track.stateOnSurface(starting_point);
709  }
710  return std::make_pair(starting_state, starting_id);
711 }
712 
714  if (not MuonHitHelper::isCSC(det_id))
715  return false;
716  const CSCDetId csc_id{det_id};
717  return (csc_id.station() == 1) or ((csc_id.ring() == 1) or (csc_id.ring() == 4));
718 }
719 
721  const bool is_same_region = track->eta() * layer.region > 0;
722 
723  bool skip = false;
724  if (is_cosmics_) {
725  float p2_in = track->innerMomentum().mag2();
726  float p2_out = track->outerMomentum().mag2();
727  if (isInsideOut(*track))
728  std::swap(p2_in, p2_out);
729  const bool is_outgoing = p2_in > p2_out;
730 
731  skip = (is_outgoing xor is_same_region);
732 
733  } else {
734  // beam scenario
735  skip = not is_same_region;
736  }
737 
738  return skip;
739 }
740 
741 bool GEMEfficiencyAnalyzer::checkBounds(const GlobalPoint& global_point, const Plane& plane) {
742  const LocalPoint local_point = plane.toLocal(global_point);
743  const LocalPoint local_point_2d(local_point.x(), local_point.y(), 0.0f);
744  return plane.bounds().inside(local_point_2d);
745 }
746 
748  const std::vector<const GEMChamber*>& chamber_vector) {
749  const GEMEtaPartition* bound = nullptr;
750  for (const GEMChamber* chamber : chamber_vector) {
751  if (not checkBounds(global_point, chamber->surface()))
752  continue;
753 
754  for (const GEMEtaPartition* eta_partition : chamber->etaPartitions()) {
755  if (checkBounds(global_point, eta_partition->surface())) {
756  bound = eta_partition;
757  break;
758  }
759  } // GEMEtaPartition
760  } // GEMChamber
761 
762  return bound;
763 }
764 
765 std::pair<const GEMRecHit*, float> GEMEfficiencyAnalyzer::findClosetHit(const GlobalPoint& dest_global_pos,
767  const GEMEtaPartition* eta_partition) {
768  const StripTopology& topology = eta_partition->specificTopology();
769  const LocalPoint dest_local_pos = eta_partition->toLocal(dest_global_pos);
770  const float dest_local_x = dest_local_pos.x();
771  const float dest_local_y = dest_local_pos.y();
772 
773  const GEMRecHit* closest_hit = nullptr;
774  float min_residual_rphi = 1e6;
775 
776  for (auto hit = range.first; hit != range.second; ++hit) {
777  const LocalPoint hit_local_pos = hit->localPosition();
778  const float hit_local_phi = topology.stripAngle(eta_partition->strip(hit_local_pos));
779 
780  const float residual_x = dest_local_x - hit_local_pos.x();
781  const float residual_y = dest_local_y - hit_local_pos.y();
782  const float residual_rphi = std::cos(hit_local_phi) * residual_x + std::sin(hit_local_phi) * residual_y;
783 
784  if (std::abs(residual_rphi) < std::abs(min_residual_rphi)) {
785  min_residual_rphi = residual_rphi;
786  closest_hit = &(*hit);
787  }
788  }
789 
790  return std::make_pair(closest_hit, min_residual_rphi);
791 }
T getUntrackedParameter(std::string const &, T const &) const
tuple propagator
static GlobalError transform(const LocalError &le, const Surface &surf)
bool isInsideOut(const reco::Track &)
std::pair< const_iterator, const_iterator > range
iterator range
Definition: RangeMap.h:50
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > trasientTrackToken_
GEMDetId getReStLaKey(const GEMDetId &)
static bool isCSC(unsigned int detId)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
bool skipLayer(const reco::Track *, const GEMLayerData &)
TString getSuffixName(Int_t region_id)
virtual float stripAngle(float strip) const =0
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::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
virtual bool inside(const Local3DPoint &) const =0
Determine if the point is inside the bounds.
bool isValid() const
Make the ReferenceCountingProxy method to check validity public.
void setAllowAnything()
allow any parameter label/value pairs
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:49
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
T y() const
Definition: PV3DBase.h:60
GlobalPoint globalPosition() const
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:58
const std::string & getName() const
get name of ME
std::string to_string(const V &value)
Definition: OMSAccess.h:71
const Bounds & bounds() const
Definition: Surface.h:87
std::vector< GEMLayerData > buildGEMLayers(const edm::ESHandle< GEMGeometry > &)
Log< level::Error, false > LogError
TString getSuffixTitle(Int_t region_id)
const std::string kLogCategory_
void bookEfficiencyChamber(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
void setDetLabelsEta(MonitorElement *, const GEMStation *)
LocalError positionError() const
void bookEfficiencyDetector(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
Definition: Plane.h:16
constexpr int ieta() const
Definition: GEMDetId.h:199
GEMDetId id() const
TrajectoryStateOnSurface innermostMeasurementState() const
const edm::ESGetToken< GlobalTrackingGeometry, GlobalTrackingGeometryRecord > globalGeomToken_
constexpr std::array< uint8_t, layerIndexSize > layer
const uint16_t range(const Frame &aFrame)
T phierr(const GlobalPoint &aPoint) const
void Fill(long long x)
void bookResolution(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
bool checkBounds(const GlobalPoint &, const Plane &)
bool checkRefs(const std::vector< T * > &)
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:652
static DiskPointer build(Args &&...args)
Definition: BoundDisk.h:38
MonitorElement * me_prop_r_err_
float yy() const
Definition: LocalError.h:24
std::pair< TrajectoryStateOnSurface, DetId > getStartingState(const reco::TransientTrack &, const GEMLayerData &, const edm::ESHandle< GlobalTrackingGeometry > &)
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T sqrt(T t)
Definition: SSEVec.h:19
LocalPoint toLocal(const GlobalPoint &gp) const
void bookEfficiencyEtaPartition(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
edm::ESHandle< Propagator > propagator(std::string propagatorName) const
get the propagator
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
MonitorElement * me_all_abs_residual_rphi_
std::pair< const GEMRecHit *, float > findClosetHit(const GlobalPoint &, const GEMRecHitCollection::range &, const GEMEtaPartition *)
unsigned int outerDetId() const
DetId of the detector on which surface the outermost state is located.
Definition: Track.h:79
tuple key
prepare the HTCondor submission files and eventually submit them
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Transition
Definition: Transition.h:12
const StripTopology & specificTopology() const
void analyze(const edm::Event &event, const edm::EventSetup &eventSetup) override
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
std::pair< TrajectoryStateOnSurface, DetId > findStartingState(const reco::TransientTrack &, const GEMLayerData &, const edm::ESHandle< GlobalTrackingGeometry > &)
const LocalTrajectoryError & localError() const
TrajectoryStateOnSurface outermostMeasurementState() const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool isValid() const
Definition: HandleBase.h:70
GEMEfficiencyAnalyzer(const edm::ParameterSet &)
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:48
trackingRecHit_iterator recHitsEnd() const
last iterator to RecHits
GEMDetId getReStEtKey(const GEMDetId &)
#define M_PI
void fillME(MEMap &me_map, const GEMDetId &key, const float x)
const edm::ESGetToken< GEMGeometry, MuonGeometryRecord > gemToken1_
__shared__ Hist hist
Log< level::Info, false > LogInfo
const GEMEtaPartition * findEtaPartition(const GlobalPoint &, const std::vector< const GEMChamber * > &)
Definition: DetId.h:17
const math::XYZVector & outerMomentum() const
momentum vector at the outermost hit position
Definition: Track.h:65
const Track & track() const
static void fillDescriptions(edm::ConfigurationDescriptions &)
void bookEfficiencyMomentum(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
float strip(const LocalPoint &lp) const
void bookMisc(DQMStore::IBooker &, const edm::ESHandle< GEMGeometry > &)
constexpr int chamber() const
Definition: GEMDetId.h:183
T rerr(const GlobalPoint &aPoint) const
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
void add(std::string const &label, ParameterSetDescription const &psetDescription)
edm::EDGetTokenT< GEMRecHitCollection > rechit_token_
static bool isGEM(unsigned int detId)
Definition: MuonHitHelper.cc:7
edm::EDGetTokenT< edm::View< reco::Muon > > muon_token_
bool isME11(const DetId &)
MonitorElement * me_prop_phi_err_
TrajectoryStateOnSurface stateOnSurface(const GlobalPoint &point) const
const math::XYZVector & innerMomentum() const
momentum vector at the innermost hit position
Definition: Track.h:59
static int position[264][3]
Definition: ReadPGInfo.cc:289
GEMDetId getReStKey(const int, const int)
const edm::ESGetToken< GEMGeometry, MuonGeometryRecord > gemToken2_
MonitorElement * bookNumerator2D(DQMStore::IBooker &, MonitorElement *)
void update(const edm::EventSetup &setup, bool duringEvent=true)
update the services each event
const reco::Track * getTrack(const reco::Muon &)
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:151
MonitorElement * bookNumerator1D(DQMStore::IBooker &, MonitorElement *)
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
bool isValid() const
Definition: ESHandle.h:44
std::vector< double > pt_bins_
T x() const
Definition: PV3DBase.h:59
unsigned int innerDetId() const
DetId of the detector on which surface the innermost state is located.
Definition: Track.h:82
ESGetTokenH3DDVariant esConsumes(std::string const &Reccord, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
trackingRecHit_iterator recHitsBegin() const
first iterator to RecHits
MuonServiceProxy * muon_service_
Definition: Run.h:45
#define LogDebug(id)
virtual TrackRef globalTrack() const
reference to Track reconstructed in both tracked and muon detector
Definition: Muon.h:51
virtual void setAxisTitle(const std::string &title, int axis=1)
set x-, y- or z-axis title (axis=1, 2, 3 respectively)