ATLAS Offline Software
Loading...
Searching...
No Matches
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"
19namespace {
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
33namespace 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
39 m_binsize = (m_descriptor.yMaxRange - m_descriptor.yMinRange) / m_nbins;
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 "
82 << (zmin - m_descriptor.yMinRange) * m_invbinsize << " " << (zmax - m_descriptor.yMinRange) * m_invbinsize
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->uniqueID << 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);
338 maximum.refpos = m_descriptor.referencePosition;
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();
488 float dx = m_descriptor.referencePosition - x;
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
const boost::regex ref(r_ef)
Scalar theta() const
theta method
int sign(int a)
int imax(int i, int j)
#define y
#define x
Header file for AthHistogramAlgorithm.
struct containing additional debug information on the hits that is not needed for the actual alg but ...
singleton-like access to IMessageSvc via open function and helper
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
float extrapolate(const MuonLayerHough::Maximum &ref, const MuonLayerHough::Maximum &ex, bool doparabolic=false)
constexpr double z_end
z value whereafter no magnetic field / curvature
std::vector< std::shared_ptr< MuonHough::Hit > > HitVec
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
const std::string & regionName(DetectorRegionIndex index)
convert DetectorRegionIndex into a string
struct representing the maximum in the hough space
void reset()
reset the transform
void associateHitsToMaximum(Maximum &maximum, const HitVec &hits) const
associates the list of input hits to the provided maximum
RegionDescriptor m_descriptor
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
std::vector< std::unique_ptr< unsigned int[]> > m_histos
int m_nbins
inverse binsize
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*
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
float yval(int posBin) const
access to y coordinate of a given bin
void fillLayer2(const HitVec &hits, bool subtract=false)
bool findMaximum(Maximum &maximum, const MuonLayerHoughSelector &selector) const
find the highest maximum that is above maxval
MuonLayerHough(const RegionDescriptor &descriptor)
constructor
void fill(const Hit &hit)
fill the hough space with a single position
void fillLayer(const HitVec &hits, bool substract=false)
fill the hough space with a vector of hits using the layer mode
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
struct containing all information to build a Hough transform for a given chamber index