ATLAS Offline Software
QratCscClusterFitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "QratCscClusterFitter.h"
6 
7 #include <iomanip>
8 #include <sstream>
9 
18 #include "CxxUtils/trapping_fp.h"
19 
21 using Muon::CscPrepData;
24 
27 using Results = std::vector<Result>;
28 
31 
32 namespace {
33  std::string splane(CscPlane plane) {
34  switch (plane) {
35  case CSS_ETA: return "CSS eta";
36  case CSL_ETA: return "CSL eta";
37  case CSS_PHI: return "CSS phi";
38  case CSL_PHI: return "CSL phi";
39  case UNKNOWN_PLANE: return "no such plane";
40  }
41  return "no such plane";
42  }
43 
44  CscPlane findPlane(int station, bool measphi) {
45  if (station == 1) {
46  if (measphi)
47  return CSS_PHI;
48  else
49  return CSS_ETA;
50  } else if (station == 2) {
51  if (measphi)
52  return CSL_PHI;
53  else
54  return CSL_ETA;
55  }
56  return UNKNOWN_PLANE;
57  }
58 } // namespace
59 
60 //******************************************************************************
61 
62 int qrat_correction(CscPlane plane, double qrat, double& cor, double& dcordqrat) {
63  std::vector<double> pfac;
64  if (plane == CSS_ETA) {
65  if (qrat < 0.095) return 1;
66  if (qrat > 1.01) return 1;
67  if (qrat < 0.15) {
68  pfac.push_back(-5.483);
69  pfac.push_back(130.6);
70  pfac.push_back(-1296.);
71  pfac.push_back(5994.);
72  pfac.push_back(-10580.);
73  } else if (qrat < 0.30) {
74  pfac.push_back(-0.9225);
75  pfac.push_back(5.569);
76  pfac.push_back(2.908);
77  pfac.push_back(-66.19);
78  pfac.push_back(108.5);
79  } else {
80  pfac.push_back(-0.4246);
81  pfac.push_back(2.619);
82  pfac.push_back(-3.642);
83  pfac.push_back(2.837);
84  pfac.push_back(-0.8916);
85  }
86  } else if (plane == CSL_ETA) {
87  if (qrat < 0.105) return 1;
88  if (qrat > 1.01) return 1;
89  if (qrat < 0.25) {
90  pfac.push_back(-2.823);
91  pfac.push_back(42.71);
92  pfac.push_back(-279.1);
93  pfac.push_back(879.2);
94  pfac.push_back(-1062.);
95  } else {
96  pfac.push_back(-0.5409);
97  pfac.push_back(3.110);
98  pfac.push_back(-4.630);
99  pfac.push_back(3.800);
100  pfac.push_back(-1.241);
101  }
102  } else {
103  return 3;
104  }
105  cor = 0.0;
106  dcordqrat = 0.0;
107  double term = 1.0;
108  for (unsigned int ipow = 0; ipow < pfac.size(); ++ipow) {
109  dcordqrat += ipow * pfac[ipow] * term;
110  if (ipow) term *= qrat;
111  cor += pfac[ipow] * term;
112  }
113  return 0;
114 }
115 
116 //******************************************************************************
117 
118 // Calculate QRAT correction by interpolation.
119 // Input array runs from 0.0 to 1.0.
120 // Output is shifted by 0.5.
121 // The value in each bin corresponds to upper edge of the bin.
122 // qrmin = min value of the qrat distribution
123 // corvals = array of corrections
124 // qrat = input value of qrat
125 // cor = output correction
126 // dcordqrat = derivative of cor w.r.t. qrat
127 
128 int qrat_interpolation(double qrmin, const std::vector<double>& corvals, double qrat, double& cor, double& dcordqrat) {
129  int nbin = corvals.size();
130  if (!nbin) return 1;
131  // Treat any QRAT below the minimum as if it were at the minumum.
132  if (qrat < qrmin) qrat = qrmin;
133  // Find the bin holding dqrat.
134  double dqrat = 1.0 / nbin;
135  int bin = int(qrat / dqrat);
136  // Extract the value for this bin (x1) and the preceding (x0)
137  // and the following (x2).
138  double x1 = corvals[bin];
139  if (x1 == 0.0) return 2;
140  double x0 = bin == 0 ? 0.0 : corvals[bin - 1];
141  double x2 = bin == nbin - 1 ? 1.0 : corvals[bin + 1];
142  // Assign the qrat values for these bins. If this is the first
143  // bin with data, then use the input qrmin.
144  double qrat0 = dqrat * bin;
145  double qrat1 = qrat0 + dqrat;
146 
147  if (x0 == 0.0) {
148  if (qrmin > qrat0 && qrmin < qrat1) { qrat0 = qrmin; }
149  }
150  // Calculate correction and derivative.
151  // Use quadratic interpolation with the high edge of this bin,
152  // the preceding and the following. For the last bin, use linear
153  // interpolation.
154  if (bin == nbin - 1) {
155  double a = x0;
156  double b = (x1 - x0) / dqrat;
157  cor = a + b * (qrat - qrat0);
158  dcordqrat = b;
159  } else {
160  double d0 = qrat1 - qrat0;
161  double d = dqrat;
162  double w = 1.0 / (d0 * d * d + d0 * d0 * d);
163  double a = x1;
164  double b = w * d * d * (x1 - x0) + w * d0 * d0 * (x2 - x1);
165  double c = w * d0 * (x2 - x1) - w * d * (x1 - x0);
166  cor = a + b * (qrat - qrat1) + c * (qrat - qrat1) * (qrat - qrat1);
167  dcordqrat = b + 2.0 * c * (qrat - qrat1);
168  }
169  if (cor < 0.0) cor = 0.0;
170  // Shift correction to center of bin.
171  cor -= 0.50;
172  return 0;
173 }
174 
175 //****************************************************************************
176 
194 int qrat_atanh(const double a, const double b, double c, const double x0, double qrat, double& cor, double& dcordqrat) {
195  if (qrat <= 0) return 1; // avoid trouble in error calculation
196  // minimum qrat value (at pos=-1) or use pos = -0.5?
197  double qrmin = a + b * tanh(c * (-1 - x0));
198 
199  // Treat any QRAT below the minimum as if it were at the minumum.
200  if (qrat < qrmin) qrat = qrmin;
201  double z = (qrat - a) / b;
202  cor = atanh(z) / c + x0;
203  dcordqrat = 1.0 / (1.0 - z * z) / b / c;
204 
205  return 0;
206 }
207 
208 //****************************************************************************
209 
210 QratCscClusterFitter::QratCscClusterFitter(const std::string& type, const std::string& aname, const IInterface* parent) :
212  declareInterface<ICscClusterFitter>(this);
213  m_max_width.push_back(5); // CSS eta
214  m_max_width.push_back(5); // CSL eta
215  m_max_width.push_back(3); // CSS phi
216  m_max_width.push_back(2); // CSL phi
217  declareProperty("max_width", m_max_width); // Maximum width (strips) for unspoiled clusters
218  declareProperty("position_option_eta", m_posopt_eta = "ATANH");
219  declareProperty("position_option_phi", m_posopt_phi = "NONE");
220  declareProperty("error_option_eta", m_erropt_eta = "CHARGE");
221  declareProperty("error_option_phi", m_erropt_phi = "NONE");
222  declareProperty("error_eta", m_error_eta = 0.050); // in mm this is for fixed error
223  declareProperty("error_phi", m_error_phi = 0.140); // in mm this is for fixed error
224 
225  declareProperty("precisionErrorScaler", m_precisionErrorScaler = 1.0); // in mm this is for fixed error
226 
227  declareProperty("qrat_maxdiff", m_qrat_maxdiff = 0.15); // in strips
228  declareProperty("qrat_maxsig", m_qrat_maxsig = 6.0); // in strips
229  declareProperty("error_tantheta", m_error_tantheta = 0.57); // in mm
230  declareProperty("xtan_css_eta_offset", m_xtan_css_eta_offset = 0.0015); // in mm
231  declareProperty("xtan_css_eta_slope", m_xtan_css_eta_slope = 0.000137); // in mm
232  declareProperty("xtan_csl_eta_offset", m_xtan_csl_eta_offset = -0.0045); // in mm
233  declareProperty("xtan_csl_eta_slope", m_xtan_csl_eta_slope = 0.000131); // in mm
234  declareProperty("qratmin_css_eta", m_qratmin_css_eta = 0.0940459);
235  declareProperty("qratmin_csl_eta", m_qratmin_csl_eta = 0.108975);
236  declareProperty("qratcor_css_eta", m_qratcor_css_eta); // in strips
237  declareProperty("qratcor_csl_eta", m_qratcor_csl_eta); // in strips
238 
239  declareProperty("atanh_a_css_eta", m_atanh_a_css_eta = 1.5);
240  declareProperty("atanh_b_css_eta", m_atanh_b_css_eta = 1.411);
241  declareProperty("atanh_c_css_eta", m_atanh_c_css_eta = 2.329);
242  declareProperty("atanh_x0_css_eta", m_atanh_x0_css_eta = 0.6601);
243  declareProperty("atanh_a_csl_eta", m_atanh_a_csl_eta = 1.516);
244  declareProperty("atanh_b_csl_eta", m_atanh_b_csl_eta = 1.427);
245  declareProperty("atanh_c_csl_eta", m_atanh_c_csl_eta = 2.35);
246  declareProperty("atanh_x0_csl_eta", m_atanh_x0_csl_eta = 0.6615);
247 
248  declareProperty("dposmin", m_dposmin = 0.082);
249 }
250 
251 //**********************************************************************
252 
254  ATH_MSG_VERBOSE("Initalizing " << name());
255 
256  // retrieve MuonDetectorManager from the conditions store
258 
259  ATH_CHECK(m_idHelperSvc.retrieve());
260 
261  if (m_alignmentTool.retrieve().isFailure()) {
262  ATH_MSG_WARNING(name() << ": unable to retrieve cluster fitter " << m_alignmentTool);
263  } else {
264  ATH_MSG_DEBUG(name() << ": retrieved " << m_alignmentTool);
265  }
266 
267  ATH_MSG_DEBUG("Properties for " << name() << ":");
268  ATH_MSG_DEBUG(" Eta position option: " << m_posopt_eta);
269  ATH_MSG_DEBUG(" Phi position option: " << m_posopt_phi);
270  ATH_MSG_DEBUG(" Eta error option: " << m_erropt_eta);
271  ATH_MSG_DEBUG(" Phi error option: " << m_erropt_phi);
272  ATH_MSG_DEBUG(" Eta assigned error: " << m_error_eta);
273  ATH_MSG_DEBUG(" Phi assigned error: " << m_error_phi);
274  ATH_MSG_DEBUG(" Max strip pos diff: " << m_qrat_maxdiff);
275  ATH_MSG_DEBUG(" Max strip pos sig: " << m_qrat_maxsig);
276  ATH_MSG_DEBUG(" Non-normal error coeff: " << m_error_tantheta);
277  ATH_MSG_DEBUG(" CSS eta pos-slope offset: " << m_xtan_css_eta_offset);
278  ATH_MSG_DEBUG(" CSS eta pos-slope slope: " << m_xtan_css_eta_slope);
279  ATH_MSG_DEBUG(" CSL eta pos-slope offset: " << m_xtan_csl_eta_offset);
280  ATH_MSG_DEBUG(" CSL eta pos-slope slope: " << m_xtan_csl_eta_slope);
281  ATH_MSG_DEBUG(" CSS eta table offset: " << m_qratmin_css_eta);
282  ATH_MSG_DEBUG(" CSL eta table offset: " << m_qratmin_csl_eta);
283  ATH_MSG_DEBUG(" CSS eta table size: " << m_qratcor_css_eta.size());
284  ATH_MSG_DEBUG(" CSL eta table size: " << m_qratcor_csl_eta.size());
285 
286  ATH_MSG_DEBUG("atanh_a_css_eta: " << m_atanh_a_css_eta);
287  ATH_MSG_DEBUG("atanh_b_css_eta: " << m_atanh_b_css_eta);
288  ATH_MSG_DEBUG("atanh_c_css_eta: " << m_atanh_c_css_eta);
289  ATH_MSG_DEBUG("atanh_x0_css_eta: " << m_atanh_x0_css_eta);
290  ATH_MSG_DEBUG("atanh_a_csl_eta: " << m_atanh_a_csl_eta);
291  ATH_MSG_DEBUG("atanh_b_csl_eta: " << m_atanh_b_csl_eta);
292  ATH_MSG_DEBUG("atanh_c_csl_eta: " << m_atanh_c_csl_eta);
293  ATH_MSG_DEBUG("atanh_x0_csl_eta: " << m_atanh_x0_csl_eta);
294 
295  ATH_MSG_DEBUG("Minimum pos error: " << m_dposmin);
296 
297  return StatusCode::SUCCESS;
298 }
299 
300 //**********************************************************************
301 
303  auto init = [&]() {
304  DataNames dnames;
305  bool dofixed = false;
306  bool docharge = false;
307  if (m_posopt_phi == "POLYNOMIAL" || m_posopt_phi == "TABLE" || m_posopt_phi == "ATANH") {
308  if (m_erropt_phi == "FIXED") dofixed = true;
309  if (m_erropt_phi == "CHARGE") docharge = true;
310  }
311  if (m_posopt_eta == "POLYNOMIAL" || m_posopt_eta == "TABLE" || m_posopt_eta == "ATANH") {
312  if (m_erropt_eta == "FIXED") dofixed = true;
313  if (m_erropt_eta == "CHARGE") docharge = true;
314  }
315  if (dofixed || docharge) {
316  dnames.emplace_back("scor1");
317  dnames.emplace_back("scor2");
318  dnames.emplace_back("scor");
319  }
320  if (docharge) {
321  dnames.emplace_back("dscor1");
322  dnames.emplace_back("dscor2");
323  dnames.emplace_back("dscor");
324  dnames.emplace_back("scordiff");
325  dnames.emplace_back("dscordiff");
326  }
327  return dnames;
328  };
329  static const DataNames dnames = init();
330  return dnames;
331 }
332 
333 //**********************************************************************
334 
335 Results QratCscClusterFitter::fit(const StripFitList& sfits, double tantheta) const {
336  ATH_MSG_VERBOSE("QRAT fit with tool " << name());
337 
339 
340  // Check input has at least three strips.
341  unsigned int nstrip = sfits.size();
342  if (nstrip < 3) {
343  ATH_MSG_VERBOSE(" Input has fewer than three strips.");
344  if (nstrip == 2) {
345  Muon::CscTimeStatus tstatus = (sfits[0].charge > sfits[1].charge) ? sfits[0].timeStatus : sfits[1].timeStatus;
346  results.emplace_back(1, Muon::CscStatusNarrow, tstatus);
347  } else if (nstrip == 1) {
348  Muon::CscTimeStatus tstatus = sfits[0].timeStatus;
349  results.emplace_back(1, Muon::CscStatusNarrow, tstatus);
350  }
351  return results;
352  }
353 
354  // Fetch the number of strips and check the input arrays.
355  for (unsigned int istrip = 0; istrip < nstrip; ++istrip) {
356  if (sfits[istrip].strip == nullptr) {
357  ATH_MSG_WARNING("Strip pointer is null.");
358  results.emplace_back(2);
359  return results;
360  }
361  }
362 
363  // Use the first strip to extract the layer parameters.
364  const CscStripPrepData* pstrip = sfits[0].strip;
365  Identifier idStrip0 = pstrip->identify();
366 
367  // retrieve MuonDetectorManager from the conditions store
369  const MuonGM::MuonDetectorManager* MuonDetMgr = DetectorManagerHandle.cptr();
370  if (MuonDetMgr == nullptr) {
371  ATH_MSG_ERROR("Null pointer to the MuonDetectorManager conditions object");
372  return results;
373  }
374  const CscReadoutElement* pro = MuonDetMgr->getCscReadoutElement(idStrip0);
375 
376  bool measphi = m_idHelperSvc->cscIdHelper().CscIdHelper::measuresPhi(idStrip0);
377  double pitch = pro->cathodeReadoutPitch(0, measphi);
378  unsigned int maxstrip = pro->maxNumberOfStrips(measphi);
379  unsigned int strip0 = m_idHelperSvc->cscIdHelper().strip(idStrip0) - 1;
380  int station = m_idHelperSvc->cscIdHelper().stationName(idStrip0) - 49; // 1=CSS, 2=CSL
381 
382  CscPlane plane = findPlane(station, measphi);
383  if (plane == UNKNOWN_PLANE) {
384  ATH_MSG_WARNING("Invalid CSC plane: station=" << station << "; measphi=" << measphi);
385  results.emplace_back(3);
386  return results;
387  }
388 
389  // Display input strips.
390  ATH_MSG_VERBOSE("QRAT fittter input has " << nstrip << " strips");
391  for (unsigned int istrip = 0; istrip < nstrip; ++istrip) {
392  Identifier id = sfits[istrip].strip->identify();
393  ATH_MSG_VERBOSE(" " << station << " : " << measphi << " " << m_idHelperSvc->cscIdHelper().wireLayer(id) << " " << istrip << " "
394  << m_idHelperSvc->cscIdHelper().strip(id) << " " << sfits[istrip].charge);
395  }
396 
397  // Find the peak strip and check the shape.
398  unsigned int istrip_peak = 0; // strip number within cluster
399  // Loop over strips excluding the edges.
400  for (unsigned int istrip = 1; istrip < nstrip - 1; ++istrip) {
401  // Tell clang to optimize assuming that FP operations may trap.
403  StripFit sfit = sfits[istrip];
404  float qthis = sfit.charge;
405  float qlast = sfits[istrip - 1].charge;
406  float qnext = sfits[istrip + 1].charge;
407  // Peak if the adjacent strips have less charge.
408  bool ispeak = qthis > qlast && qthis > qnext;
409  // Special case: next strip has the same charge.
410  // Require the previous strip has less charge and the next following
411  // strip be absent or have less charge.
412  if (!ispeak) {
413  if (qthis == qnext) { ispeak = (qthis > qlast) && (istrip + 2 == nstrip || sfits[istrip + 2].charge < qthis); }
414  }
415  // Special case: first and second strips have the same charge.
416  // Require the third strip has less charge.
417  if (!ispeak) {
418  if (istrip == 1) {
419  if (qthis == qlast) {
420  ispeak = qthis > qnext; // bug found 10/13/07
421  }
422  }
423  }
424  // Record if peak.
425  if (ispeak) {
426  if (istrip_peak) { // Error if multiple peaks are found.
427  results.emplace_back(6, Muon::CscStatusMultiPeak); // Time status should be defined in SimpleClusterFit...
428  return results;
429  }
430  istrip_peak = istrip;
431  }
432  }
433  ATH_MSG_VERBOSE(" Peak is at " << istrip_peak << "th strip in cluster");
434 
435  // Check we are not on the edge.
436  if (strip0 <= 0 || strip0 + nstrip > maxstrip) {
437  results.emplace_back(4, Muon::CscStatusEdge, sfits[istrip_peak].timeStatus);
438  return results;
439  }
440 
441  // MS: remove this check since width is amplitude dependent.
442  // use saturation check instead
443  /**************************************
444  if ( nstrip > m_max_width[plane] ) {
445  // if ( nstrip_threshold > m_max_width[plane] ) {
446  results.push_back(Result(5, Muon::CscStatusWide, sfits[istrip_peak].timeStatus));
447  return results;
448  }
449  ***************************************/
450 
451  // Cluster is spoiled if peak is not at the center.
452  bool is_even = 2 * (nstrip / 2) == nstrip;
453  bool atcenter = istrip_peak == nstrip / 2 || (is_even && istrip_peak + 1 == nstrip / 2);
454  if (!atcenter) {
455  results.emplace_back(7, Muon::CscStatusSkewed, sfits[istrip_peak].timeStatus);
456  return results;
457  }
458 
459  if (sfits[istrip_peak].stripStatus == Muon::CscStrStatSaturated || sfits[istrip_peak - 1].stripStatus == Muon::CscStrStatSaturated ||
460  sfits[istrip_peak + 1].stripStatus == Muon::CscStrStatSaturated) {
461  results.emplace_back(15, Muon::CscStatusSaturated, sfits[istrip_peak].timeStatus);
462  return results;
463  }
464 
465  // left/peak/right strip should have good time information....
466  if (sfits[istrip_peak].stripStatus != Muon::CscStrStatSuccess
467  // || sfits[istrip_peak-1].stripStatus != Muon::CscStrStatSuccess
468  // || sfits[istrip_peak+1].stripStatus != Muon::CscStrStatSuccess ) {
469  ) {
470  results.emplace_back(14, Muon::CscStatusStripFitFailed, sfits[istrip_peak].timeStatus);
471  return results;
472  } else if (sfits[istrip_peak - 1].stripStatus == Muon::CscStrStatHot || sfits[istrip_peak - 1].stripStatus == Muon::CscStrStatDead ||
473  sfits[istrip_peak + 1].stripStatus == Muon::CscStrStatHot || sfits[istrip_peak + 1].stripStatus == Muon::CscStrStatDead) {
474  results.emplace_back(14, Muon::CscStatusStripFitFailed, sfits[istrip_peak].timeStatus);
475  return results;
476  }
477 
479  // Set initial strip position.
480  double savg = istrip_peak;
481 
482  // Calculate QRAT correction to strip position.
483  std::string posopt = m_posopt_eta;
484  std::string erropt = m_erropt_eta;
485  double dpos = 0.0;
486  if (measphi) {
487  posopt = m_posopt_phi;
488  erropt = m_erropt_phi;
489  }
490  double q1 = sfits[istrip_peak - 1].charge;
491  double q0 = sfits[istrip_peak].charge;
492  double q2 = sfits[istrip_peak + 1].charge;
493  double qrat1 = q1 / q0;
494  double qrat2 = q2 / q0;
495  double dq1 = sfits[istrip_peak - 1].dcharge;
496  double dq0 = sfits[istrip_peak].dcharge;
497  double dq2 = sfits[istrip_peak + 1].dcharge;
498 
499  ATH_MSG_VERBOSE(" QRAT charge ratios: " << qrat1 << " " << qrat2);
500  double scor1 = 0.; // left side correction.
501  double dscordqrat1 = 0.;
502  double scor2 = 0; // right side correction.
503  double dscordqrat2 = 0.;
504  int stat1 = 0;
505  int stat2 = 0;
506  if (posopt == "POLYNOMIAL") {
507  stat1 = qrat_correction(plane, qrat1, scor1, dscordqrat1);
508  stat2 = qrat_correction(plane, qrat2, scor2, dscordqrat2);
509  } else if (posopt == "TABLE") {
510  double qrmin = 0.0;
511  const std::vector<double>* pcor = nullptr;
512  if (plane == CSS_ETA) {
513  qrmin = m_qratmin_css_eta;
514  pcor = &m_qratcor_css_eta;
515  } else if (plane == CSL_ETA) {
516  qrmin = m_qratmin_csl_eta;
517  pcor = &m_qratcor_csl_eta;
518  } else {
519  ATH_MSG_WARNING(" Invalid QRAT plane: " << splane(plane));
520  results.emplace_back(8);
521  return results;
522  }
523  if (pcor) {
524  stat1 = qrat_interpolation(qrmin, *pcor, qrat1, scor1, dscordqrat1);
525  stat2 = qrat_interpolation(qrmin, *pcor, qrat2, scor2, dscordqrat2);
526  } else {
527  stat1 = 99;
528  }
529  } else if (posopt == "ATANH") { // MS: atanh parametrization
530  double a, b, c, x0; // parameters
531  if (plane == CSS_ETA) {
535  x0 = m_atanh_x0_css_eta;
536  } else if (plane == CSL_ETA) {
540  x0 = m_atanh_x0_csl_eta;
541  } else {
542  ATH_MSG_WARNING(" Invalid QRAT plane: " << splane(plane));
543  results.emplace_back(8);
544  return results;
545  }
546  stat1 = qrat_atanh(a, b, c, x0, qrat1, scor1, dscordqrat1);
547  stat2 = qrat_atanh(a, b, c, x0, qrat2, scor2, dscordqrat2);
548 
549  } else {
550  ATH_MSG_WARNING(" Invalid position option: " << posopt);
551  results.emplace_back(9);
552  return results;
553  }
554  if (stat1 || stat2) {
555  ATH_MSG_VERBOSE(" QRAT correction failed: SPOILED");
556  results.emplace_back(10);
557  return results;
558  }
559  ATH_MSG_VERBOSE(" QRAT strip corrs: " << scor1 << " " << scor2);
560  ATH_MSG_VERBOSE(" QRAT derivatives: " << dscordqrat1 << " " << dscordqrat2);
561 
562  // Compare left and right.
563  // Flip sign of the left side correction.
564  scor1 = -scor1;
565  dscordqrat1 = -dscordqrat1;
566  double scor = 0.0;
567  DataMap dmap;
568  // Calculation weighting corrections by their derivatives, i.e. assuming the
569  // two charge ratios have the same error.
570  if (erropt == "FIXED") {
571  double w1 = 1 / (dscordqrat1 * dscordqrat1);
572  double w2 = 1 / (dscordqrat2 * dscordqrat2);
573  scor = (w1 * scor1 + w2 * scor2) / (w1 + w2);
574  double scor_diff = std::abs(scor2 - scor1);
575  ATH_MSG_VERBOSE(" Combined corr: " << scor);
576  dpos = measphi ? m_error_phi : m_error_eta;
577  // Fill data map.
578  dmap["scor1"] = scor1;
579  dmap["scor2"] = scor2;
580  dmap["scor"] = scor;
581  // Exit if measurements are inconsistent.
582  if (scor_diff > m_qrat_maxdiff) {
583  ATH_MSG_VERBOSE(" SPOILED (scor_diff=" << scor_diff << ")");
584  results.emplace_back(11, Muon::CscStatusQratInconsistent);
585  return results;
586  }
587  // Calculation using the (independent) errors in the three charges.
588  } else if (erropt == "CHARGE") {
589  // Calculate intermediate variables.
590  double x1 = dscordqrat1 * qrat1;
591  double x2 = dscordqrat2 * qrat2;
592  double dqq0 = dq0 / q0;
593  double dqq1 = dq1 / q1;
594  double dqq2 = dq2 / q2;
595  double rnum = (-x1 * x1 * dqq1 * dqq1 + x2 * x2 * dqq2 * dqq2 + (x2 * x2 - x1 * x1) * dqq0 * dqq0);
596  double rden = (x1 * x1 * dqq1 * dqq1 + x2 * x2 * dqq2 * dqq2 + (x2 - x1) * (x2 - x1) * dqq0 * dqq0);
597  double rfac = rnum / rden;
598  // Calculate the significance of the difference between the measurements.
599  double dscor_diff = sqrt(rden);
600  double scor_diff = scor2 - scor1;
601  double scor_sig = std::abs(scor_diff) / dscor_diff;
602  // Calculate the weighted average of the corrections.
603  double w1 = 0.5 * (1.0 + rfac);
604  double w2 = 0.5 * (1.0 - rfac);
605  scor = w1 * scor1 + w2 * scor2;
606  // Calculate the error in this average.
607  double ddscor1 = w1 * x1 * dqq1;
608  double ddscor2 = w2 * x2 * dqq2;
609  double ddscor0 = (w1 * x1 + w2 * x2) * dqq0;
610  double dscor = sqrt(ddscor1 * ddscor1 + ddscor2 * ddscor2 + ddscor0 * ddscor0);
611  dpos = pitch * dscor;
612  // add minimum error (in mm) in quadrature:
613  dpos = sqrt(dpos * dpos + m_dposmin * m_dposmin);
614  // Fill data map.
615  double dscor1 = std::abs(x1) * sqrt(dqq1 * dqq1 + dqq0 * dqq0);
616  double dscor2 = std::abs(x2) * sqrt(dqq2 * dqq2 + dqq0 * dqq0);
617  dmap["scor1"] = scor1;
618  dmap["dscor1"] = dscor1;
619  dmap["scor2"] = scor2;
620  dmap["dscor2"] = dscor2;
621  dmap["scordiff"] = scor_diff;
622  dmap["dscordiff"] = dscor_diff;
623  dmap["scor"] = scor;
624  dmap["dscor"] = dscor;
625  // Debugging.
626  ATH_MSG_VERBOSE("QRAT CHARGE calculation");
627  ATH_MSG_VERBOSE(" q1, q0, q2: " << q1 << " " << q0 << " " << q2);
628  ATH_MSG_VERBOSE(" dq1, dq0, dq2: " << dq1 << " " << dq0 << " " << dq2);
629  ATH_MSG_VERBOSE(" dscordqrat1, x1: " << dscordqrat1 << " " << x1);
630  ATH_MSG_VERBOSE(" dscordqrat2, x2: " << dscordqrat2 << " " << x2);
631  ATH_MSG_VERBOSE(" scor1 = " << scor1 << " +/- " << dscor1);
632  ATH_MSG_VERBOSE(" scor2 = " << scor2 << " +/- " << dscor2);
633  ATH_MSG_VERBOSE(" scor = " << scor << " +/- " << dscor);
634  ATH_MSG_VERBOSE(" scordiff = " << scor_diff << " +/- " << dscor_diff);
635  ATH_MSG_VERBOSE(" scor_sig = " << scor_sig);
636 
637  // Exit if measurements are inconsistent.
638  if (scor_sig > m_qrat_maxsig) {
639  ATH_MSG_VERBOSE(" SPOILED (scor_sig=" << scor_sig << ")");
640  results.emplace_back(12, Muon::CscStatusQratInconsistent, sfits[istrip_peak].timeStatus);
641  return results;
642  }
643  } else {
644  ATH_MSG_WARNING(" Invalid error option: " << erropt);
645  results.emplace_back(13, Muon::CscStatusUndefined, sfits[istrip_peak].timeStatus);
646  return results;
647  }
648 
649  // Correct strip position.
650  savg += scor + strip0;
651  ATH_MSG_VERBOSE(" QRAT corr " << splane(plane) << " nstrip=" << nstrip << " savg=" << savg << " qrat1=" << qrat1
652  << " qrat2=" << qrat2 << " scor1=" << scor1 << " scor2=" << scor2);
653 
654  // Error due to incident angle.
655  double dpostht = m_error_tantheta * std::abs(tantheta);
656 
657  // Scale error on dpos
658  dpos = dpos * m_precisionErrorScaler;
659 
660  // Set return values.
662  res.strip = istrip_peak;
663  res.position = pitch * (savg + 0.5 - 0.5 * maxstrip);
664 
665  // internal alignment ...
666  Identifier id = sfits[res.strip].strip->identify();
667  double offset = m_alignmentTool->getAlignmentOffset(id);
668  res.position -= offset;
669 
670  res.dposition = sqrt(dpos * dpos + dpostht * dpostht);
671 
672  res.fstrip = 0;
673  res.lstrip = nstrip - 1;
674  res.time = sfits[istrip_peak].time;
675  res.time_beforeT0Corr = sfits[istrip_peak].time_beforeT0Corr;
676  res.time_beforeBPCorr = sfits[istrip_peak].time_beforeBPCorr;
677  res.timeStatus = sfits[istrip_peak].timeStatus;
678 
679  res.qleft = q1;
680  res.qpeak = q0;
681  res.qright = q2;
682 
683  // res.diff = dmap["scordiff"];
684  // res.sig = dmap["scordiff"]/dmap["dscordiff"];
685 
686  // cluster charge should be qsum over three strip... 3/21/2011
687  res.charge = res.qleft + res.qpeak + res.qright;
688  res.charge_beforeBPCorr =
689  sfits[istrip_peak].charge_beforeBPCorr + sfits[istrip_peak - 1].charge_beforeBPCorr + sfits[istrip_peak + 1].charge_beforeBPCorr;
690 
691  res.dataMap = dmap;
692 
693  ATH_MSG_VERBOSE(" Position :: pos=" << res.position << " dpos:dtht=" << dpos << ":" << dpostht << " ==>" << res.dposition
694  << " at tanth=" << tantheta);
695 
696  results.push_back(res);
697  return results;
698 }
699 // int QratCscClusterFitter::
700 // fit(const StripList&, const StripFitList& sfits,
701 // double& pos, double& dpos, Muon::CscClusterStatus& clustatus,
702 // unsigned int& /*istrip*/, double& /*charge*/, double& /*time*/, DataMap* /*pdmap*/) const { return 0;}
703 //**********************************************************************
704 
705 double QratCscClusterFitter::getCorrectedError(const CscPrepData* pclu, double slope) const {
706  // Cluster position.
707  Trk::ParamDefs icor = Trk::loc1;
708  Trk::ParamDefs ierr = Trk::loc1;
709  double pos = pclu->localPosition()[icor];
710  double dpos = Amg::error(pclu->localCovariance(), ierr);
711 
712  Identifier idStrip0 = pclu->identify();
713  int station = m_idHelperSvc->cscIdHelper().stationName(idStrip0) - 49; // 1=CSS, 2=CSL
714  // Calculate the angle of incidence.
715  double tantht = 0.0;
716  if (station == 1) {
718  } else {
720  }
721  // Correct the error using this angle.
722  double old_dpostht = m_error_tantheta * std::abs(tantht);
723 
724  double new_dpostht = m_error_tantheta * std::abs(slope);
725 
726  double newError = sqrt(dpos * dpos - old_dpostht * old_dpostht + new_dpostht * new_dpostht);
727 
728  ATH_MSG_VERBOSE(" Position :: pos=" << pos << " dpos:newdpos=" << dpos << " : " << newError << " " << old_dpostht << " "
729  << new_dpostht);
730 
731  if (slope < -990) { newError = sqrt(dpos * dpos + old_dpostht * old_dpostht); }
732 
733  return newError;
734 }
735 
736 //**********************************************************************
737 
739  Results results = fit(sfits, 0.0);
740  Results new_results;
741  for (unsigned int iresult = 0; iresult < results.size(); ++iresult) {
742  Result res = results[iresult];
743  if (res.fitStatus) {
744  new_results.push_back(res);
745  continue;
746  }
747  // Fetch the chamber type.
748  const CscStripPrepData* pstrip = sfits[0].strip;
749  Identifier idStrip0 = pstrip->identify();
750  int station = m_idHelperSvc->cscIdHelper().stationName(idStrip0) - 49; // 1=CSS, 2=CSL
751  // Calculate the angle of incidence.
752  double tantht = 0.0;
753  double pos = res.position;
754  if (station == 1) {
756  } else {
758  }
759  // Correct the error using this angle.
760  double dpostht = m_error_tantheta * std::abs(tantht);
761  double dpos = res.dposition;
762 
763  res.dposition = sqrt(dpos * dpos + dpostht * dpostht);
764 
765  // Return the updated result.
766  new_results.push_back(res);
767  }
768 
769  return new_results;
770 }
CSS_ETA
@ CSS_ETA
Definition: QratCscClusterFitter.cxx:30
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
CXXUTILS_TRAPPING_FP
#define CXXUTILS_TRAPPING_FP
Definition: trapping_fp.h:24
QratCscClusterFitter::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: QratCscClusterFitter.h:82
QratCscClusterFitter::initialize
StatusCode initialize()
Definition: QratCscClusterFitter.cxx:253
QratCscClusterFitter::m_qratcor_css_eta
std::vector< double > m_qratcor_css_eta
Definition: QratCscClusterFitter.h:60
SiliconTech::strip
@ strip
CSL_ETA
@ CSL_ETA
Definition: QratCscClusterFitter.cxx:30
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ICscClusterFitter::Results
std::vector< Result > Results
Definition: ICscClusterFitter.h:101
Muon::CscStrStatSaturated
@ CscStrStatSaturated
Definition: CscStripStatus.h:33
QratCscClusterFitter::m_xtan_css_eta_offset
double m_xtan_css_eta_offset
Definition: QratCscClusterFitter.h:54
CSS
@ CSS
Definition: QratCscClusterFitter.cxx:29
hist_file_dump.d
d
Definition: hist_file_dump.py:142
QratCscClusterFitter::m_qratmin_css_eta
double m_qratmin_css_eta
Definition: QratCscClusterFitter.h:58
QratCscClusterFitter.h
Trk::ParamDefs
ParamDefs
Definition: ParamDefs.h:32
QratCscClusterFitter::m_dposmin
double m_dposmin
Definition: QratCscClusterFitter.h:72
EventPrimitivesHelpers.h
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:217
Trk::PrepRawData::localCovariance
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
QratCscClusterFitter::m_posopt_phi
std::string m_posopt_phi
Definition: QratCscClusterFitter.h:45
CSS_PHI
@ CSS_PHI
Definition: QratCscClusterFitter.cxx:30
ICscStripFitter::Result::charge
double charge
Definition: ICscStripFitter.h:31
bin
Definition: BinsDiffFromStripMedian.h:43
QratCscClusterFitter::m_atanh_c_css_eta
double m_atanh_c_css_eta
Definition: QratCscClusterFitter.h:65
CscStripPrepData.h
DataNames
ICscClusterFitter::DataNames DataNames
Definition: CscSplitClusterFitter.cxx:20
QratCscClusterFitter::m_error_phi
double m_error_phi
Definition: QratCscClusterFitter.h:49
QratCscClusterFitter::dataNames
const DataNames & dataNames() const
Definition: QratCscClusterFitter.cxx:302
CSL_PHI
@ CSL_PHI
Definition: QratCscClusterFitter.cxx:30
qrat_interpolation
int qrat_interpolation(double qrmin, const std::vector< double > &corvals, double qrat, double &cor, double &dcordqrat)
Definition: QratCscClusterFitter.cxx:128
MuonGM::CscReadoutElement
Definition: CscReadoutElement.h:56
QratCscClusterFitter::m_qrat_maxsig
double m_qrat_maxsig
Definition: QratCscClusterFitter.h:52
QratCscClusterFitter::m_xtan_csl_eta_offset
double m_xtan_csl_eta_offset
Definition: QratCscClusterFitter.h:56
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
QratCscClusterFitter::m_xtan_css_eta_slope
double m_xtan_css_eta_slope
Definition: QratCscClusterFitter.h:55
QratCscClusterFitter::m_atanh_c_csl_eta
double m_atanh_c_csl_eta
Definition: QratCscClusterFitter.h:69
ParamDefs.h
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
QratCscClusterFitter::m_alignmentTool
ToolHandle< ICscAlignmentTool > m_alignmentTool
Definition: QratCscClusterFitter.h:88
QratCscClusterFitter::m_atanh_a_csl_eta
double m_atanh_a_csl_eta
Definition: QratCscClusterFitter.h:67
QratCscClusterFitter::QratCscClusterFitter
QratCscClusterFitter(const std::string &, const std::string &, const IInterface *)
Definition: QratCscClusterFitter.cxx:210
python.Dumpers.aname
string aname
Definition: Dumpers.py:5543
QratCscClusterFitter::m_atanh_b_css_eta
double m_atanh_b_css_eta
Definition: QratCscClusterFitter.h:64
Muon::CscStripPrepData
Class representing the raw data of one CSC strip (for clusters look at Muon::CscPrepData).
Definition: CscStripPrepData.h:40
QratCscClusterFitter::m_precisionErrorScaler
double m_precisionErrorScaler
Definition: QratCscClusterFitter.h:50
Muon::CscStrStatHot
@ CscStrStatHot
Definition: CscStripStatus.h:29
Muon::CscStrStatDead
@ CscStrStatDead
Definition: CscStripStatus.h:31
Muon::CscStatusSaturated
@ CscStatusSaturated
Definition: CscClusterStatus.h:56
MuonGM::CscReadoutElement::maxNumberOfStrips
int maxNumberOfStrips(int measuresPhi) const
Definition: CscReadoutElement.cxx:162
CaloSwCorrections.rfac
def rfac(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:182
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ICscClusterFitter::Result
Definition: ICscClusterFitter.h:52
CscPrepData.h
z
#define z
Muon::CscStatusStripFitFailed
@ CscStatusStripFitFailed
Definition: CscClusterStatus.h:53
MuonGM::MuonDetectorManager::getCscReadoutElement
const CscReadoutElement * getCscReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:227
qrat_correction
int qrat_correction(CscPlane plane, double qrat, double &cor, double &dcordqrat)
Definition: QratCscClusterFitter.cxx:62
Muon::CscPrepData
Class representing clusters from the CSC.
Definition: CscPrepData.h:39
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Definition: AthCommonDataStore.h:145
Muon::CscStatusQratInconsistent
@ CscStatusQratInconsistent
Positions from Qrat_left and Qrat_right is not consistent.
Definition: CscClusterStatus.h:49
ICscClusterFitter::DataNames
std::vector< std::string > DataNames
Definition: ICscClusterFitter.h:46
QratCscClusterFitter::m_error_eta
double m_error_eta
Definition: QratCscClusterFitter.h:48
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:11
CscReadoutElement.h
TRT::Track::d0
@ d0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:62
Result
ICscClusterFitter::Result Result
Definition: QratCscClusterFitter.cxx:26
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Muon::CscStrStatSuccess
@ CscStrStatSuccess
Definition: CscStripStatus.h:25
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
add-xsec-uncert-quadrature-N.results
dictionary results
Definition: add-xsec-uncert-quadrature-N.py:39
ICscStripFitter::Result
Definition: ICscStripFitter.h:25
Muon::CscStatusSkewed
@ CscStatusSkewed
Skewed, e.g.
Definition: CscClusterStatus.h:46
QratCscClusterFitter::m_erropt_eta
std::string m_erropt_eta
Definition: QratCscClusterFitter.h:46
Muon::CscStatusUndefined
@ CscStatusUndefined
Undefined, should not happen, most likely indicates a problem.
Definition: CscClusterStatus.h:94
CscClusterStatus.h
CSL
@ CSL
Definition: QratCscClusterFitter.cxx:29
ICscClusterFitter::DataMap
std::map< std::string, double > DataMap
Definition: ICscClusterFitter.h:47
trapping_fp.h
Tell the compiler to optimize assuming that FP may trap.
Trk::PrepRawData::identify
Identifier identify() const
return the identifier
EventPrimitives.h
Muon::CscStatusNarrow
@ CscStatusNarrow
Too narrow.
Definition: CscClusterStatus.h:40
Muon::CscStatusUnspoiled
@ CscStatusUnspoiled
Clean cluster with precision fit.
Definition: CscClusterStatus.h:26
Result
Definition: fbtTestBasics.cxx:50
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
Amg::error
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Definition: EventPrimitivesHelpers.h:40
Trk::PrepRawData::localPosition
const Amg::Vector2D & localPosition() const
return the local position reference
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:82
QratCscClusterFitter::m_max_width
std::vector< unsigned int > m_max_width
Definition: QratCscClusterFitter.h:43
charge
double charge(const T &p)
Definition: AtlasPID.h:986
qrat_atanh
int qrat_atanh(const double a, const double b, double c, const double x0, double qrat, double &cor, double &dcordqrat)
Calculate QRAT correction from inverse hyperbolic tangent based on a fit to the plot of pos x vs char...
Definition: QratCscClusterFitter.cxx:194
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Results
std::vector< Result > Results
Definition: CscSplitClusterFitter.cxx:22
Muon::CscStatusMultiPeak
@ CscStatusMultiPeak
More than one peak in cluster.
Definition: CscClusterStatus.h:37
python.PyKernel.init
def init(v_theApp, v_rootStream=None)
Definition: PyKernel.py:45
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
QratCscClusterFitter::m_DetectorManagerKey
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_DetectorManagerKey
retrieve MuonDetectorManager from the conditions store
Definition: QratCscClusterFitter.h:75
QratCscClusterFitter::m_atanh_b_csl_eta
double m_atanh_b_csl_eta
Definition: QratCscClusterFitter.h:68
a
TList * a
Definition: liststreamerinfos.cxx:10
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
MuonGM::MuonDetectorManager
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonDetectorManager.h:51
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
QratCscClusterFitter::m_error_tantheta
double m_error_tantheta
Definition: QratCscClusterFitter.h:53
CscStation
CscStation
Definition: ParabolaCscClusterFitter.h:25
QratCscClusterFitter::fit
Results fit(const StripFitList &sfits) const
Definition: QratCscClusterFitter.cxx:738
QratCscClusterFitter::m_erropt_phi
std::string m_erropt_phi
Definition: QratCscClusterFitter.h:47
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
QratCscClusterFitter::getCorrectedError
double getCorrectedError(const Muon::CscPrepData *pclu, double slope) const
Definition: QratCscClusterFitter.cxx:705
QratCscClusterFitter::m_xtan_csl_eta_slope
double m_xtan_csl_eta_slope
Definition: QratCscClusterFitter.h:57
LocalDirection.h
ICscClusterFitter::StripFitList
std::vector< StripFit > StripFitList
Definition: ICscClusterFitter.h:40
Muon::CscClusterStatus
CscClusterStatus
Enum to represent the cluster status - see the specific enum values for more details.
Definition: CscClusterStatus.h:23
AthAlgTool
Definition: AthAlgTool.h:26
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:198
UNKNOWN_PLANE
@ UNKNOWN_PLANE
Definition: QratCscClusterFitter.cxx:30
QratCscClusterFitter::m_atanh_x0_css_eta
double m_atanh_x0_css_eta
Definition: QratCscClusterFitter.h:66
Trk::loc1
@ loc1
Definition: ParamDefs.h:34
UNKNOWN_STATION
@ UNKNOWN_STATION
Definition: QratCscClusterFitter.cxx:29
CscPlane
CscPlane
Definition: ParabolaCscClusterFitter.h:26
QratCscClusterFitter::m_qrat_maxdiff
double m_qrat_maxdiff
Definition: QratCscClusterFitter.h:51
python.compressB64.c
def c
Definition: compressB64.py:93
QratCscClusterFitter::m_atanh_x0_csl_eta
double m_atanh_x0_csl_eta
Definition: QratCscClusterFitter.h:70
QratCscClusterFitter::m_posopt_eta
std::string m_posopt_eta
Definition: QratCscClusterFitter.h:44
Muon::CscStatusEdge
@ CscStatusEdge
Cluster reaches the edge of plane.
Definition: CscClusterStatus.h:34
QratCscClusterFitter::m_qratmin_csl_eta
double m_qratmin_csl_eta
Definition: QratCscClusterFitter.h:59
QratCscClusterFitter::m_atanh_a_css_eta
double m_atanh_a_css_eta
Definition: QratCscClusterFitter.h:63
QratCscClusterFitter::m_qratcor_csl_eta
std::vector< double > m_qratcor_csl_eta
Definition: QratCscClusterFitter.h:61
Muon::CscTimeStatus
CscTimeStatus
Enum to represent the cluster time measurement status - see the specific enum values for more details...
Definition: CscTimeStatus.h:24
Identifier
Definition: IdentifierFieldParser.cxx:14
MuonGM::CscReadoutElement::cathodeReadoutPitch
double cathodeReadoutPitch(int chLayer, int measuresPhi) const
Definition: CscReadoutElement.cxx:147