ATLAS Offline Software
MuonLayerHough.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <TH1.h>
8 #include <TString.h> // for Form
9 #include <memory.h>
10 
11 #include <bitset>
12 #include <cmath>
13 #include <cstdlib>
14 #include <iostream>
15 
17 #include "GaudiKernel/MsgStream.h"
18 #include "GaudiKernel/SystemOfUnits.h"
19 namespace {
20  // Avoid floating point exceptions arising from cases of x = 0 or x = PI
21  // by extending the inverse tan function towards a large number
22  // Avoid FPEs occuring in clang 10 , e.g.,
23  // FPEAuditor 2 1 WARNING FPE OVERFLOW in [Execute] of [MuGirlStauAlg] on event 257948896 0 0
24  // by large number
26  float cot(const float x) {
27  const float arg = M_PI_2 - x;
28  // Tan becomes singular at -pi/2 and pi/2
29  if (std::abs(arg - M_PI_2) <= FLT_EPSILON || std::abs(arg + M_PI_2) <= FLT_EPSILON) return 1.e8;
30  return std::tan(arg);
31  }
32 } // namespace
33 namespace MuonHough {
34 
36  m_descriptor(descriptor) {
37  // calculate the number of bins
38  m_nbins = (m_descriptor.yMaxRange - m_descriptor.yMinRange) / m_descriptor.yBinSize; // the same for all the cycles
40  m_invbinsize = 1. / m_binsize; // binsize in the floating plane
41 
42  // setup the histograms; determines the number of theta slices
43  m_histos.reserve(m_descriptor.nthetaSamples); // it contains all the theta layers
44  for (unsigned int i = 0; i < m_descriptor.nthetaSamples; ++i) m_histos.emplace_back(new unsigned int[m_nbins]);
45  reset();
46  }
47 
49  for (unsigned int i = 0; i < m_histos.size(); ++i) memset(m_histos[i].get(), 0, sizeof(unsigned int) * m_nbins);
50  max = 0;
51  maxhist = -1;
52  maxbin = -1;
53  }
54 
55  void MuonLayerHough::fill(float x, float y, float weight) {
56  int cycles = m_histos.size();
57  for (int ci = 0; ci < cycles; ++ci) {
58  float dtheta = m_descriptor.thetaStep;
59  float dthetaOffset = 2 * m_descriptor.thetaStep * (ci - (cycles - 1) / 2.);
60  float theta = std::atan2(x, y);
61  float zref = (m_descriptor.referencePosition - x) * cot(theta - dthetaOffset) + y;
62  float z0 = (m_descriptor.referencePosition - x) * cot(theta - dthetaOffset + dtheta) + y;
63  float z1 = (m_descriptor.referencePosition - x) * cot(theta - dthetaOffset - dtheta) + y;
64 
65  float zmin = z0 < z1 ? z0 : z1;
66  float zmax = z0 < z1 ? z1 : z0;
67  int bincenter = (zref - m_descriptor.yMinRange) * m_invbinsize;
68 
69  int binmin = (zmin - m_descriptor.yMinRange) * m_invbinsize;
70  int binmax = (zmax - m_descriptor.yMinRange) * m_invbinsize;
71  if (binmin - bincenter < -3) binmin = bincenter - 3;
72  if (binmin == bincenter) binmin -= 1;
73  if (binmax == bincenter) binmax += 1;
74  if (binmin >= m_nbins) continue;
75  if (binmax - bincenter > 3) binmax = bincenter + 3;
76  if (binmax < 0) continue;
77 
78  if (binmin < 0) binmin = 0;
79  if (binmax >= m_nbins) binmax = m_nbins - 1;
80  if (m_debug)
81  std::cout << " filling " << x << " y " << binmin << " " << binmax << " w " << weight << " center " << bincenter << " range "
83  << std::endl;
84  for (int n = binmin; n <= binmax; ++n) {
85  unsigned int& val = m_histos[ci][n];
86  int w = 1000 * weight;
87  if (w < 0 && (int)val < -w)
88  val = 0;
89  else
90  val += weight;
91  if (val > max) {
92  max = val;
93  maxhist = ci;
94  maxbin = n;
95  }
96  }
97  }
98  }
99 
100  void MuonLayerHough::fillLayer(const HitVec& hits, bool subtract) {
101  if (hits.empty()) return;
102 
103  // outer loop over cycles
104  int cycles = m_histos.size();
105  for (int ci = 0; ci < cycles; ++ci) {
106  // float dtheta = m_descriptor.thetaStep;
107  // float dthetaOffset = 2*m_descriptor.thetaStep*(ci-(cycles-1)/2.);
108 
109  int prevlayer = -1;
110  int prevbinmin = 10000;
111  int prevbinmax = -1;
112  // inner loop over hits
113  HitVec::const_iterator it = hits.begin();
114  HitVec::const_iterator it_end = hits.end();
115  for (; it != it_end; ++it) {
116  float x = (*it)->x;
117  float y1 = (*it)->ymin;
118  float y2 = (*it)->ymax;
119  std::pair<int, int> minMax = range((*it)->x, (*it)->ymin, (*it)->ymax, ci);
120  int binmin = std::max(minMax.first,0);
121  int binmax = std::min(minMax.second, m_nbins - 1);
122  if (binmin >= m_nbins || binmax < 0) continue;
123 
124  if (m_debug) {
125  std::cout << " filling hit " << x << " refpos " << m_descriptor.referencePosition << " ymin " << y1 << " ymax " << y2
126  << " layer " << (*it)->layer << " binmin " << binmin << " max " << binmax;
127  if ((*it)->debugInfo()) {
128  const HitDebugInfo* db1 = (*it)->debugInfo();
129  std::cout << " sec " << db1->sector << " r " <<Muon::MuonStationIndex::regionName(db1->region) << " type "
130  << db1->type << " lay " << Muon::MuonStationIndex::layerName(db1->layer)
131  << " slay " << db1->sublayer << std::endl;
132  } else
133  std::cout << std::endl;
134  }
135  // first hit within range
136  if (prevbinmax == -1) {
137  if (m_debug) std::cout << " first range " << binmin << " " << binmax << std::endl;
138  prevbinmin = binmin;
139  prevbinmax = binmax;
140  prevlayer = (*it)->layer;
141  continue;
142  }
143 
144  if (binmin < prevbinmin && prevlayer == (*it)->layer) {
145  std::cout << "Error hits are out of order: min " << binmin << " max " << binmax << " lay " << (*it)->layer << std::endl;
146  }
147  // if the max value of the previous hit is smaller than the current minvalue fill the histogram of the previous hit
148  // do the same when reached last hit
149  if (prevbinmax < binmin || prevlayer != (*it)->layer) {
150  if (m_debug)
151  std::cout << " filling range " << prevbinmin << " " << prevbinmax << " new min " << binmin << " " << binmax
152  << " weight " << (*it)->w << std::endl;
153  for (int n = prevbinmin; n <= prevbinmax; ++n) {
154  unsigned int& val = m_histos[ci][n];
155  int w = 1000 * (*it)->w;
156  if (subtract) w *= -1;
157  if (w < 0 && (int)val < -w)
158  val = 0;
159  else
160  val += w;
161  if (val > max) {
162  max = val;
163  maxhist = ci;
164  maxbin = n;
165  }
166  }
167  prevbinmin = binmin;
168  prevbinmax = binmax;
169  prevlayer = (*it)->layer;
170 
171  } else {
172  // update the maximum value of the window
173  if (m_debug)
174  std::cout << " updating range " << prevbinmin << " " << prevbinmax << " hit " << binmin << " " << binmax
175  << " new " << prevbinmin << " " << binmax << std::endl;
176  prevbinmax = binmax;
177  }
178  }
179  if (prevbinmax != -1) {
180  if (m_debug)
181  std::cout << " filling last range " << prevbinmin << " " << prevbinmax << " weight " << hits.back()->w << std::endl;
182  for (int n = prevbinmin; n <= prevbinmax; ++n) {
183  unsigned int& val = m_histos[ci][n];
184  int w = 1000 * hits.back()->w;
185  if (subtract) w *= -1;
186  if (w < 0 && (int)val < -w)
187  val = 0;
188  else
189  val += w;
190  if (val > max) {
191  max = val;
192  maxhist = ci;
193  maxbin = n;
194  }
195  }
196  }
197  }
198  }
199 
200  void MuonLayerHough::fillLayer2(const HitVec& hits, bool subtract) {
201  if (hits.empty()) return;
202 
203  std::vector<int> layerCounts(m_nbins, 0);
204  int sign = subtract ? -1000 : 1000;
205  // outer loop over cycles
206  int cycles = m_histos.size();
207  for (int ci = 0; ci < cycles; ++ci) {
208  // keep track of the previous layer
209  int prevlayer = hits.front()->layer;
210 
211  // inner loop over hits
212  HitVec::const_iterator it = hits.begin();
213  HitVec::const_iterator it_end = hits.end();
214  for (; it != it_end; ++it) {
215  // if we get to the next layer process the current one and fill the Hough space
216  if (prevlayer != (*it)->layer) {
217  for (int i = 0; i < m_nbins; ++i) {
218  if (subtract && -layerCounts[i] >= static_cast<int>(m_histos[ci][i]))
219  m_histos[ci][i] = 0;
220  else
221  m_histos[ci][i] += layerCounts[i];
222  layerCounts[i] = 0; // reset bin
223  }
224  prevlayer = (*it)->layer;
225  }
226 
227  // get bin range
228  std::pair<int, int> minMax = range((*it)->x, (*it)->ymin, (*it)->ymax, ci);
229  int binmin = minMax.first;
230  int binmax = minMax.second;
231 
232  // check wether we are within the Hough space
233  if (binmin >= m_nbins) continue;
234  if (binmax < 0) continue;
235 
236  // adjust boundaries if needed
237  if (binmin < 0) binmin = 0;
238  if (binmax >= m_nbins) binmax = m_nbins - 1;
239 
240  // output hit for debug purposes
241  if (m_debug) {
242  std::cout << " cycle(theta layers) " << ci << " filling hit " << (*it)->x << " refpos "
243  << m_descriptor.referencePosition << " ymin " << (*it)->ymin << " ymax " << (*it)->ymax << " layer "
244  << (*it)->layer << " weight " << (*it)->w << " binmin " << binmin << " max " << binmax;
245  std::cout << " zmin " << binmin * m_binsize + m_descriptor.yMinRange << " zmax "
246  << binmax * m_binsize + m_descriptor.yMinRange;
247  if ((*it)->debugInfo()) {
248  const HitDebugInfo* db1 = (*it)->debugInfo();
249  std::cout << " sec " << db1->sector << " r " << Muon::MuonStationIndex::regionName(db1->region)
250  << " type " << db1->type << " lay " << Muon::MuonStationIndex::layerName(db1->layer)
251  << " bc " << db1->barcode << std::endl;
252  } else
253  std::cout << std::endl;
254  }
255  int weight = sign * (*it)->w; // set the hit weight
256  // set bits to true
257  for (; binmin <= binmax; ++binmin) layerCounts[binmin] = weight;
258  } // end of loopin gover hits
259  // if the last set of hits was not filled, fill them now; just for the last layer
260  for (int i = 0; i < m_nbins; ++i) {
261  if (subtract && -layerCounts[i] >= static_cast<int>(m_histos[ci][i]))
262  m_histos[ci][i] = 0;
263  else
264  m_histos[ci][i] += layerCounts[i];
265  // if( m_debug && layerCounts[i] != 0 ) std::cout << " filling layer " << prevlayer << " bin " << i << " val " <<
266  // layerCounts[i] << " tot " << m_histos[ci][i] << std::endl;
267  layerCounts[i] = 0; // reset bin
268  }
269  }
270  }
271 
272  std::vector<TH1*> MuonLayerHough::rootHistos(const std::string& prefix, const float* rmi, const float* rma) const {
273  std::vector<TH1*> hists;
274  hists.reserve(m_histos.size());
275 
276  float rmin = rmi ? *rmi : m_descriptor.yMinRange;
277  float rmax = rma ? *rma : m_descriptor.yMaxRange;
278 
279  int cycles = m_histos.size();
280  for (int ci = 0; ci < cycles; ++ci) {
281  TString hname = prefix + "_hist";
282  hname += ci;
283  TH1F* h = new TH1F(hname, hname, m_nbins, rmin, rmax); // register the new histograms here
284  for (int n = 0; n < m_nbins; ++n) h->SetBinContent(n + 1, m_histos[ci][n] * 0.001);
285  hists.push_back(h);
286  }
287  return hists;
288  }
289 
291  const float preMaxCut = selector.getMinCutValue(); // in this case it is likely to be 1.9
292  maximum.max = 0;
293  maximum.pos = 0;
294  maximum.theta = 0;
295  maximum.refpos = 0;
296  maximum.refregion = DetRegIdx::DetectorRegionUnknown;
297  maximum.refchIndex = ChIdx::ChUnknown;
298  maximum.binpos = -1;
299  maximum.binposmin = -1;
300  maximum.binposmax = -1;
301  maximum.binsize = -1;
302  maximum.bintheta = -1;
303  maximum.triggerConfirmed = 0;
304  maximum.hits.clear();
305  maximum.hough = this;
306 
307  if (preMaxCut < 0) return false; // this is where there is no cut
308 
309  float tmax = 0;
310  int posb = -1;
311  int thetab = -1;
312  int imaxval = preMaxCut * 1000;
313  const int cycles = m_histos.size();
314  // loop over histograms and find maximum
315  for (int ci = 0; ci < cycles; ++ci) {
316  const float scale =
317  1. - 0.01 * std::abs(ci - cycles / 2.0); // small deweighting of non pointing bins; weighting more on the central part
318  for (int n = 0; n < m_nbins; ++n) {
319  const int val = m_histos[ci][n];
320  if (val < imaxval) continue;
321 
322  if (scale * val > tmax) {
323  tmax = scale * val;
324  posb = n;
325  thetab = ci;
326  }
327  }
328  }
329  if (posb == -1) return false; // didn't find a max
330 
331  const float candidatePos = m_descriptor.yMinRange + m_binsize * posb;
332  if (tmax < selector.getCutValue(candidatePos)) return false;
333 
334  maximum.max = tmax * 0.001;
335  maximum.pos = candidatePos;
336  maximum.theta =
337  -m_descriptor.thetaStep * (thetab - (m_histos.size() - 1) * 0.5) + std::atan2(m_descriptor.referencePosition, maximum.pos);
339  maximum.refregion = m_descriptor.region;
340  maximum.refchIndex = m_descriptor.chIndex;
341  maximum.binpos = posb;
342  maximum.binposmin = posb;
343  maximum.binposmax = posb;
344  maximum.binsize = m_binsize;
345  maximum.bintheta = thetab;
346 
347  // determin width of maximum; now to be 70% of the original height
348  unsigned int imax = m_histos[thetab][posb];
349  unsigned int sidemax = 0.7 * imax;
350  // loop down, catch case the maximum is in the first bin
351  for (int n = posb != 0 ? posb - 1 : posb; n >= 0; --n) {
352  if (m_histos[thetab][n] > sidemax) {
353  maximum.binposmin = n;
354  } else {
355  break;
356  }
357  }
358  for (int n = posb + 1; n < m_nbins; ++n) {
359  if (m_histos[thetab][n] > sidemax) {
360  maximum.binposmax = n;
361  } else {
362  break;
363  }
364  }
365  return true;
366  }
367 
369  if (maximum.bintheta == -1 || maximum.binposmax == -1 || maximum.binposmin == -1) return;
370  // loop over hits and find those that are compatible with the maximum
371  HitVec::const_iterator it = hits.begin();
372  HitVec::const_iterator it_end = hits.end();
373  for (; it != it_end; ++it) {
374  // calculate the bins associated with the hit and check whether any of they are part of the maximum
375  std::pair<int, int> minMax = range((*it)->x, (*it)->ymin, (*it)->ymax, maximum.bintheta);
376  if (m_debug) {
377  std::cout << " associating hit: x " << (*it)->x << " ymin " << (*it)->ymin << " ymax " << (*it)->ymax << " layer "
378  << (*it)->layer << " range " << minMax.first << " " << minMax.second << " max range " << maximum.binposmin
379  << " " << maximum.binposmax << " prd " << (*it)->prd << " tgc " << (*it)->tgc;
380  if ((*it)->debugInfo()) std::cout << " trigC " << (*it)->debugInfo()->trigConfirm;
381  std::cout << std::endl;
382  }
383  if (minMax.first > maximum.binposmax) continue; // minimum bin large than the maximum, drop
384  if (minMax.second < maximum.binposmin) continue; // maximum bin smaller than the minimum, drop
385  // keep everything else
386  maximum.hits.push_back(*it);
387  if ((*it)->debugInfo() && (*it)->debugInfo()->trigConfirm > 0) ++maximum.triggerConfirmed;
388  }
389  }
390 
391  std::pair<float, float> MuonLayerHough::maximum(float x, float y, int& posbin, int& thetabin) const {
392  unsigned int max = 0;
393  thetabin = -1;
394  posbin = -1;
395 
396  int cycles = m_histos.size();
397  for (int ci = 0; ci < cycles; ++ci) {
398  int relbin = ci - (cycles - 1) / 2;
399  float dtheta = m_descriptor.thetaStep;
400  float dthetaOffset = 2 * m_descriptor.thetaStep * (relbin); // if bintheta = cycles, this is the same as dtheta * (cycles + 1 )
401  float theta = std::atan2(x, y);
402  float z0 = (m_descriptor.referencePosition - x) * cot(theta - dthetaOffset + dtheta) +
403  y; // move the angle by a step, recalculate the new y value
404  float z1 = (m_descriptor.referencePosition - x) * cot(theta - dthetaOffset - dtheta) + y;
405 
406  float zmin = z0 < z1 ? z0 : z1;
407  float zmax = z0 < z1 ? z1 : z0;
408  int binmin = (zmin - m_descriptor.yMinRange) / m_binsize - 1;
409  int binmax = (zmax - m_descriptor.yMinRange) / m_binsize + 1;
410  if (binmin >= m_nbins) continue;
411  if (binmax < 0) continue;
412 
413  if (binmin < 0) binmin = 0;
414  if (binmax >= m_nbins) binmax = m_nbins - 1;
415  for (int n = binmin; n < binmax; ++n) {
416  if (max < m_histos[ci][n]) {
417  max = m_histos[ci][n];
418  posbin = n;
419  thetabin = ci;
420  }
421  }
422  }
423  float dthetaOffset = 2 * m_descriptor.thetaStep * (thetabin - (cycles - 1) / 2.);
424  return std::make_pair(0.001 * max, -dthetaOffset);
425  }
426 
427  float MuonLayerHough::layerConfirmation(float x, float y, float range) const {
428  unsigned int max = 0;
429  if (x == 0) return 0;
430 
431  float yloc = m_descriptor.referencePosition * y / x;
432  int bincenter = (yloc - m_descriptor.yMinRange) / m_binsize;
433  int scanRange = range / m_binsize;
434  int binmin = bincenter - scanRange;
435  int binmax = bincenter + scanRange;
436  if (binmin >= m_nbins) return 0;
437  if (binmax < 0) return 0;
438 
439  int maxbin = -1;
440  if (binmin < 0) binmin = 0;
441  if (binmax >= m_nbins) binmax = m_nbins - 1;
442  int cyclesmin = 0;
443  int cycles = m_histos.size();
444  if (cycles > 3) {
445  int c0 = cycles / 2;
446  cyclesmin = c0 - 1;
447  cycles = c0 + 1;
448  }
449  for (int n = binmin; n < binmax; ++n) {
450  for (int ci = cyclesmin; ci < cycles; ++ci) {
451  if (max < m_histos[ci][n]) {
452  max = m_histos[ci][n];
453  maxbin = n;
454  }
455  }
456  }
457  if (range == 900) std::cout << " layerConfirmation " << max << " bin " << maxbin << " entry " << bincenter << std::endl;
458  return 0.001 * max;
459  }
460 
461  std::pair<float, float> MuonLayerHough::layerConfirmation(unsigned int thetaBin, float x, float y, float range) const {
462  unsigned int max = 0;
463  if (x == 0) return std::make_pair(0., 0.);
464  if (thetaBin >= m_histos.size()) return std::make_pair(0., 0.);
465  float yloc = m_descriptor.referencePosition * y / x;
466  int bincenter = (yloc - m_descriptor.yMinRange) / m_binsize;
467  int scanRange = range / m_binsize;
468  int binmin = bincenter - scanRange;
469  int binmax = bincenter + scanRange;
470  if (binmin >= m_nbins) return std::make_pair(0., 0.);
471  if (binmax < 0) return std::make_pair(0., 0.);
472 
473  int maxbin = -1;
474  if (binmin < 0) binmin = 0;
475  if (binmax >= m_nbins) binmax = m_nbins - 1;
476  for (int n = binmin; n < binmax; ++n) {
477  if (max < m_histos[thetaBin][n]) {
478  max = m_histos[thetaBin][n];
479  maxbin = n;
480  }
481  }
482  std::cout << " layerConfirmation " << max << " bin " << maxbin << " entry " << bincenter << " val " << yval(max) << std::endl;
483  return std::make_pair(0.001 * max, yval(maxbin));
484  }
485 
486  std::pair<int, int> MuonLayerHough::range(const float x, const float y1, const float y2, const int bintheta) const {
487  int cycles = m_histos.size();
489  float dtheta = m_descriptor.thetaStep;
490  if (dtheta <= 0)
491  throw std::runtime_error(
492  Form("File: %s, Line: %d\nMuonLayerHough::range() - dtheta is not positive (%.4f)", __FILE__, __LINE__, dtheta));
493  float dthetaOffset = 2 * dtheta * (bintheta - (cycles - 1) / 2.);
494 
495  float theta1 = std::atan2(x, y1) - dthetaOffset;
496  float z01 = dx * cot(theta1 + dtheta) + y1;
497  float z11 = dx * cot(theta1 - dtheta) + y1;
498  float zmin1 = std::min(z01, z11);
499  float zmax1 = std::max(z01, z11);
500 
501  float theta2 = std::atan2(x, y2) - dthetaOffset;
502  float z02 = dx * cot(theta2 + dtheta) + y2;
503  float z12 = dx * cot(theta2 - dtheta) + y2;
504  float zmin2 = std::min(z02, z12);
505  float zmax2 = std::max(z02, z12);
506 
507  const float zmin = std::min(zmin1, zmin2);
508  const float zmax = std::max(zmax1, zmax2);
509 
512  constexpr float cavern_size = 100.*Gaudi::Units::meter;
513  const float flt_lower_bin = std::max(-cavern_size, (zmin - m_descriptor.yMinRange) * m_invbinsize);
514  const float flt_upper_bin = std::min(cavern_size, (zmax - m_descriptor.yMinRange) * m_invbinsize);
515  const int lower_bin = std::floor(flt_lower_bin);
516  const int upper_bin = std::floor(flt_upper_bin);
517 
518  return std::make_pair(lower_bin, upper_bin); // convert the output to bins
519  }
520 
521  float extrapolate(const MuonLayerHough::Maximum& ref, const MuonLayerHough::Maximum& ex, bool doparabolic) {
522  // z is always the precision plane. r is the reference plane, simple and robust
523  double ref_z = ref.getGlobalZ();
524  double ref_r = ref.getGlobalR();
525  double ex_z = ex.getGlobalZ();
526  double ex_r = ex.getGlobalR();
527  float theta_ref = ref.getGlobalTheta();
528  if (!doparabolic || ref_z == 0 || theta_ref == 0) { // do linear extrapolation
529  if (!ex.isEndcap()) { // if extrapolate to barell
530  return ex_z - ex_r / ref_r * ref_z;
531  } else { // if extrapolate to endcap
532  return ex_r - ex_z * ref_r / ref_z;
533  }
534  } else { // do parabolic
535  float expected = 0;
536  float extrapolated_diff = 9999;
537  const float tan_theta_ref = std::tan(theta_ref);
538  const float invtan_theta_ref = 1. / tan_theta_ref;
539  float r_start = static_cast<int>(ref.hough->m_descriptor.chIndex) % 2 > 0
540  ? 4900.
541  : 5200.; // start of barrel B field; values could be further optimized; 5500.:6500.
542  float z_start = 8500.; // start of endcap B field; used to be 6500; should start at 8500
543  float z_end = 12500.; // end of endcap B field; used to be 12000; should end at 12500
544  float r_SL = ref_r + (ex_z - ref_z) * tan_theta_ref;
545  float z_SL = ref_z + (ex_r - ref_r) * invtan_theta_ref;
546  // start extrapolation
547  if (!ref.isEndcap()) { // this is starting with barrel chamber; BEE is 6
548  float rgeo = ref_r * ref_r - r_start * r_start;
549  float rhoInv = (invtan_theta_ref * ref_r - ref_z) / rgeo;
550  if (!ex.isEndcap()) { // this ends with barrel chamber; BEE is 6
551  expected = ref_z + (ex_r - ref_r) * invtan_theta_ref + (ex_r - ref_r) * (ex_r - ref_r) * rhoInv;
552  extrapolated_diff = ex_z - expected;
553  } // end with barrel to barrel extrapolation
554  else { // this is a barrel to endcap extrapolation, mostly in the transition region
555  // recalculate z start
556  z_start = ref_z + (r_start - ref_r) * invtan_theta_ref + (r_start - ref_r) * (r_start - ref_r) * rhoInv;
557  float zgeo = ref_z * ref_z - z_start * z_start;
558  float rho = (tan_theta_ref * ref_z - ref_r) / zgeo;
559  expected = ref_r + (ex_z - ref_z) * tan_theta_ref + (ex_z - ref_z) * (ex_z - ref_z) * rho;
560  extrapolated_diff = ex_r - expected;
561  }
562  } else { // this starts with endcap chamber;
563  // swap the starting position if on the other side
564  if (tan_theta_ref < 0) {
565  z_start = -z_start;
566  z_end = -z_end;
567  }
568  if (ex.isEndcap()) { // extrapolate to endcap
569  if (std::abs(ref_z) < std::abs(z_end)) { // extrapolate from EI or EE, have to use linear
570  expected = r_SL;
571  } else { // from EM or EO or EE
572  if (std::abs(ex_z) > std::abs(z_start)) { // extrapolate to EM or EO
573  // extrapolate to outer layer, just using theta of the middle measurement; only works if the theta measurement
574  // is correct can extrapolate with either the outside theta or middle theta; outside theta is better; farther
575  // away from the B field
576  expected = r_SL;
577  } else { // to EI
578  float r_end = ref_r + (z_end - ref_z) * tan_theta_ref;
579  float zgeo = z_start * z_start - z_end * z_end;
580  float rhoInv = (r_end - z_end * tan_theta_ref) / zgeo;
581  float tantheta = tan_theta_ref - 2 * (z_end - z_start) * rhoInv;
582  expected = ex_z * tantheta + (ex_z - z_start) * (ex_z - z_start) * rhoInv;
583  }
584  }
585  extrapolated_diff = ex_r - expected;
586  } else { // exrapolate to barrel; again verly likely to be in transition region, complicated B field; just use linear
587  expected = z_SL;
588  extrapolated_diff = ex_z - expected;
589  }
590  }
591  return extrapolated_diff;
592  } // end of parabolic extrapolation
593  }
594 } // namespace MuonHough
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
MuonHough::HitVec
std::vector< std::shared_ptr< MuonHough::Hit > > HitVec
Definition: MuonLayerHough.h:21
MuonHough::MuonLayerHough::yval
float yval(int posBin) const
access to y coordinate of a given bin
Definition: MuonLayerHough.h:204
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
MuonHough::MuonLayerHough::m_binsize
float m_binsize
Definition: MuonLayerHough.h:176
dqt_zlumi_pandas.hname
string hname
Definition: dqt_zlumi_pandas.py:279
PixelAthClusterMonAlgCfg.zmin
zmin
Definition: PixelAthClusterMonAlgCfg.py:169
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonHough::MuonLayerHough::layerConfirmation
float layerConfirmation(const Hit &hit, float range=1000.) const
calculate the highest value of the hough transform within the specified range for the given hit
Definition: MuonLayerHough.h:206
MuonHough::MuonLayerHough::max
unsigned int max
Definition: MuonLayerHough.h:182
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonHough::MuonLayerHough::m_descriptor
RegionDescriptor m_descriptor
Definition: MuonLayerHough.h:187
MuonHough::MuonLayerHough::m_nbins
int m_nbins
inverse binsize
Definition: MuonLayerHough.h:180
MuonHough::HitDebugInfo
struct containing additional debug information on the hits that is not needed for the actual alg but ...
Definition: MuonSpectrometer/MuonReconstruction/MuonRecUtils/MuonLayerHough/MuonLayerHough/Hit.h:26
MuonHough::MuonLayerHough::m_debug
bool m_debug
Definition: MuonLayerHough.h:185
MuonHough::RegionDescriptor::yMinRange
float yMinRange
Definition: MuonLayerHough.h:49
skel.it
it
Definition: skel.GENtoEVGEN.py:396
MuonHough::RegionDescriptor::thetaStep
float thetaStep
Definition: MuonLayerHough.h:52
MuonHough::RegionDescriptor::nthetaSamples
unsigned int nthetaSamples
Definition: MuonLayerHough.h:53
MuonHough::MuonLayerHoughSelector
Definition: MuonLayerHoughSelector.h:12
MuonHough::RegionDescriptor::yMaxRange
float yMaxRange
Definition: MuonLayerHough.h:50
MuonHough::RegionDescriptor::referencePosition
float referencePosition
Definition: MuonLayerHough.h:48
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
MuonHough::RegionDescriptor
struct containing all information to build a Hough transform for a given chamber index
Definition: MuonLayerHough.h:25
MuonHough::MuonLayerHough::Maximum::getGlobalR
float getGlobalR() const
Definition: MuonLayerHough.h:93
x
#define x
MuonHough::MuonLayerHough::maxhist
int maxhist
Definition: MuonLayerHough.h:183
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:189
MuonLayerHough.h
bsCompare.db1
int db1
Definition: bsCompare.py:40
hotSpotInTAG.c0
c0
Definition: hotSpotInTAG.py:192
MuonHough::RegionDescriptor::region
DetRegIdx region
Definition: MuonLayerHough.h:46
MuonHough::MuonLayerHough::Maximum
struct representing the maximum in the hough space
Definition: MuonLayerHough.h:64
Muon::MuonStationIndex::regionName
static const std::string & regionName(DetectorRegionIndex index)
convert DetectorRegionIndex into a string
Definition: MuonStationIndex.cxx:176
python.SystemOfUnits.meter
int meter
Definition: SystemOfUnits.py:61
MuonHough::MuonLayerHough::fill
void fill(const Hit &hit)
fill the hough space with a single position
Definition: MuonLayerHough.h:208
MuonHough::MuonLayerHough::range
std::pair< int, int > range(const float x, const float y1, const float y2, const int bintheta) const
calculates the first and last bin the hit should be filled in for a given theta bin
Definition: MuonLayerHough.cxx:486
lumiFormat.i
int i
Definition: lumiFormat.py:85
MuonHough::MuonLayerHough::maximum
std::pair< float, float > maximum(float x, float y, int &posbin, int &thetabin) const
returns a pair with the position and angle corresponing to the input x,y values
Definition: MuonLayerHough.cxx:391
beamspotman.n
n
Definition: beamspotman.py:731
MuonHough::MuonLayerHough::findMaximum
bool findMaximum(Maximum &maximum, const MuonLayerHoughSelector &selector) const
find the highest maximum that is above maxval
Definition: MuonLayerHough.cxx:290
makeTRTBarrelCans.y2
tuple y2
Definition: makeTRTBarrelCans.py:18
MuonHough
Definition: MuonLayerHoughTool.h:41
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:169
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
MuonHough::z_end
constexpr double z_end
z value whereafter no magnetic field / curvature
Definition: MuonHoughMathUtils.h:28
MakeTH3DFromTH2Ds.hists
hists
Definition: MakeTH3DFromTH2Ds.py:72
MuonHough::MuonLayerHough::Maximum::getGlobalZ
float getGlobalZ() const
Definition: MuonLayerHough.h:97
Muon::MuonStationIndex::layerName
static const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
Definition: MuonStationIndex.cxx:192
MuonHough::MuonLayerHough::associateHitsToMaximum
void associateHitsToMaximum(Maximum &maximum, const HitVec &hits) const
associates the list of input hits to the provided maximum
Definition: MuonLayerHough.cxx:368
MuonHough::MuonLayerHough::m_invbinsize
float m_invbinsize
binsize
Definition: MuonLayerHough.h:177
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
TRT::Track::z0
@ z0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:63
MuonHough::MuonLayerHough::MuonLayerHough
MuonLayerHough(const RegionDescriptor &descriptor)
constructor
Definition: MuonLayerHough.cxx:35
imax
int imax(int i, int j)
Definition: TileLaserTimingTool.cxx:33
create_dcsc_inputs_sqlite.arg
list arg
Definition: create_dcsc_inputs_sqlite.py:48
MuonHough::MuonLayerHough::maxbin
int maxbin
Definition: MuonLayerHough.h:184
MuonHough::RegionDescriptor::yBinSize
float yBinSize
Definition: MuonLayerHough.h:51
MuonHough::MuonLayerHough::reset
void reset()
reset the transform
Definition: MuonLayerHough.cxx:48
MuonHough::MuonLayerHough::fillLayer
void fillLayer(const HitVec &hits, bool substract=false)
fill the hough space with a vector of hits using the layer mode
Definition: MuonLayerHough.cxx:100
python.selector.AtlRunQuerySelectorLhcOlc.selector
selector
Definition: AtlRunQuerySelectorLhcOlc.py:611
y
#define y
h
ref
const boost::regex ref(r_ef)
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
MuonHough::MuonLayerHough::m_histos
std::vector< std::unique_ptr< unsigned int[]> > m_histos
Definition: MuonLayerHough.h:186
MuonHough::MuonLayerHough::rootHistos
std::vector< TH1 * > rootHistos(const std::string &prefix, const float *rmin=0, const float *rmax=0) const
returns a vector with all the histograms of the hough as TH1*
Definition: MuonLayerHough.cxx:272
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
MuonHough::MuonLayerHough::fillLayer2
void fillLayer2(const HitVec &hits, bool subtract=false)
Definition: MuonLayerHough.cxx:200
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
MuonHough::extrapolate
float extrapolate(const MuonLayerHough::Maximum &ref, const MuonLayerHough::Maximum &ex, bool doparabolic=false)
Definition: MuonLayerHough.cxx:521
python.TrigEgammaMonitorHelper.TH1F
def TH1F(name, title, nxbins, bins_par2, bins_par3=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:24
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
MuonHough::RegionDescriptor::chIndex
ChIdx chIndex
Definition: MuonLayerHough.h:47
MuonHough::MuonLayerHough::Maximum::isEndcap
bool isEndcap() const
Definition: MuonLayerHough.h:85
fitman.rho
rho
Definition: fitman.py:532