Belle II Software prerelease-11-00-00e
AxialHitQuadTreeProcessor.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <tracking/trackFindingCDC/legendre/quadtree/AxialHitQuadTreeProcessor.h>
9
10#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
11
12#include <array>
13#include <vector>
14
15#include <TF1.h>
16#include <TCanvas.h>
17#include <TGraph.h>
18#include <TAxis.h>
19
20using namespace Belle2;
21using namespace TrackFindingCDC;
22using namespace TrackingUtilities;
23
24namespace {
25 bool sameSign(double n1, double n2, double n3, double n4)
26 {
27 return ((n1 > 0 && n2 > 0 && n3 > 0 && n4 > 0) || (n1 < 0 && n2 < 0 && n3 < 0 && n4 < 0));
28 }
29
30 using YSpan = AxialHitQuadTreeProcessor::YSpan;
31 YSpan splitCurvSpan(const YSpan& curvSpan, int nodeLevel, int lastLevel, int j)
32 {
33 const float meanCurv = curvSpan[0] + (curvSpan[1] - curvSpan[0]) / 2.0;
34 const std::array<float, 3> binBounds{curvSpan[0], meanCurv, curvSpan[1]};
35 const float binWidth = binBounds[j + 1] - binBounds[j];
36
37 const bool standardBinning = (nodeLevel <= lastLevel - 7) or (std::fabs(meanCurv) <= 0.005);
38 if (standardBinning) {
39 // B2INFO("Case 1* " << meanCurv << " " << (meanCurv <= 0.005));
40 float curv1 = binBounds[j];
41 float curv2 = binBounds[j + 1];
42
43 // Standard bin division
44 return {curv1, curv2};
45 }
46
47 // Non-standard binning
48 // For level 6 to 7 only expand 1 / 4, for higher levels expand 1 / 8.
49 // (assuming last level == 12)
50 if (nodeLevel < lastLevel - 5) {
51 // B2INFO("Case 2*");
52 float curv1 = binBounds[j] - binWidth / 4.;
53 float curv2 = binBounds[j + 1] + binWidth / 4.;
54 return {curv1, curv2};
55 } else {
56 // B2INFO("Case 3*");
57 float curv1 = binBounds[j] - binWidth / 8.;
58 float curv2 = binBounds[j + 1] + binWidth / 8.;
59 return {curv1, curv2};
60 }
61 }
62
63}
64
65std::vector<float> AxialHitQuadTreeProcessor::createCurvBound(YSpan curvSpan, int lastLevel)
66{
67 std::vector<YSpan> spans{{curvSpan}};
68
69 std::vector<YSpan> nextSpans;
70 for (int level = 1; level <= lastLevel; ++level) {
71 nextSpans.clear();
72 for (const YSpan& span : spans) {
73 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 0));
74 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 1));
75 }
76 spans.swap(nextSpans);
77 }
78
79 std::vector<float> bounds;
80 for (const YSpan& span : spans) {
81 bounds.push_back(span[0]);
82 bounds.push_back(span[1]);
83 }
84
85 assert(bounds.size() == std::pow(2, lastLevel));
86 return bounds;
87}
88
90{
91 static const int maxLevel = PrecisionUtil::getLookupGridLevel();
92 static const int nBins = std::pow(2, maxLevel);
93 static LookupTable<Vector2D> trigonometricLookUpTable(&Vector2D::Phi, nBins, -M_PI, M_PI);
94 return trigonometricLookUpTable;
95}
96
98 int seedLevel,
99 const XYSpans& ranges,
100 PrecisionUtil::PrecisionFunction precisionFunction)
101 : QuadTreeProcessor(lastLevel, seedLevel, ranges)
102 , m_precisionFunction(precisionFunction)
103 , m_localOrigin(0.0, 0.0)
105{
106 m_twoSidedPhaseSpace = m_quadTree->getYMin() * m_quadTree->getYMax() < 0;
107}
108
110 const YSpan& curvSpan,
111 const LookupTable<Vector2D>* cosSinLookupTable)
112 : QuadTreeProcessor(0, 0, { {0, cosSinLookupTable->getNPoints() - 1}, curvSpan})
113, m_localOrigin(localOrigin)
114, m_cosSinLookupTable(cosSinLookupTable)
115{
116 // Never use two sided mode in off origin extension
117 m_twoSidedPhaseSpace = false;
118}
119
120
122{
123 if (node->getLevel() <= 6) return false;
124 if (node->getLevel() >= getLastLevel()) return true;
125
126 const double nodeResolution = fabs(node->getYMin() - node->getYMax());
127 const double meanCurv = (node->getYMax() + node->getYMin()) / 2;
128
129 const double resolution = m_precisionFunction(meanCurv);
130 if (resolution >= nodeResolution) return true;
131
132 return false;
133}
134
137{
138 const int nodeLevel = node->getLevel();
139 const int lastLevel = getLastLevel();
140 const float meanCurv = std::fabs(node->getYMax() + node->getYMin()) / 2;
141
142 // Expand bins for all nodes 7 levels before the last level (for lastLevel = 12 starting at 6)
143 // but only in a curvature region higher than 0.005. Lower than that use always standard.
144 bool standardBinning = (nodeLevel <= lastLevel - 7) or (meanCurv <= 0.005);
145
146 if (standardBinning) {
147 float r1 = node->getYLowerBound(j);
148 float r2 = node->getYUpperBound(j);
149 long theta1 = node->getXLowerBound(i);
150 long theta2 = node->getXUpperBound(i);
151
152 // Standard bin division
153 return XYSpans({theta1, theta2}, {r1, r2});
154 }
155
156 // Non-standard binning
157 // For level 6 to 7 only expand 1 / 4, for higher levels expand 1 / 8.
158 // (assuming last level == 12)
159 if (nodeLevel < lastLevel - 5) {
160 float r1 = node->getYLowerBound(j) - node->getYBinWidth(j) / 4.;
161 float r2 = node->getYUpperBound(j) + node->getYBinWidth(j) / 4.;
162
163 // long extension = pow(2, lastLevel - nodeLevel) / 4; is same as:
164 long extension = pow(2, lastLevel - nodeLevel - 2);
165
166 long theta1 = node->getXLowerBound(i) - extension;
167 if (theta1 < 0) theta1 = 0;
168
169 long theta2 = node->getXUpperBound(i) + extension;
170 if (theta2 >= m_cosSinLookupTable->getNPoints()) {
171 theta2 = m_cosSinLookupTable->getNPoints() - 1;
172 }
173
174 return XYSpans({theta1, theta2}, {r1, r2});
175 } else {
176 float r1 = node->getYLowerBound(j) - node->getYBinWidth(j) / 8.;
177 float r2 = node->getYUpperBound(j) + node->getYBinWidth(j) / 8.;
178
179 // long extension = pow(2, lastLevel - nodeLevel) / 8; is same as
180 long extension = pow(2, lastLevel - nodeLevel - 3);
181
182 long theta1 = node->getXLowerBound(i) - extension;
183 if (theta1 < 0) theta1 = 0;
184
185 long theta2 = node->getXUpperBound(i) + extension;
186 if (theta2 >= m_cosSinLookupTable->getNPoints()) {
187 theta2 = m_cosSinLookupTable->getNPoints() - 1;
188 }
189
190 return XYSpans({theta1, theta2}, {r1, r2});
191 }
192}
193
195{
196 // Check whether the hit lies in the forward direction
197 if (node->getLevel() <= 4 and m_twoSidedPhaseSpace and node->getYMin() > -c_curlCurv and
198 node->getYMax() < c_curlCurv) {
199 if (not checkDerivative(node, wireHit)) return false;
200 }
201
202 const double& driftLength = wireHit->getRefDriftLength();
203 const Vector2D& pos2D = wireHit->getRefPos2D() - m_localOrigin;
204 double r2 = pos2D.normSquared() - driftLength * driftLength;
205
206 using Quadlet = std::array<std::array<float, 2>, 2>;
207 Quadlet distRight{};
208 Quadlet distLeft{};
209
210 // get top and bottom borders of the node
211 float rMin = node->getYMin() * r2 / 2;
212 float rMax = node->getYMax() * r2 / 2;
213
214 // get left and right borders of the node
215 long thetaMin = node->getXMin();
216 long thetaMax = node->getXMax();
217
218 const Vector2D& thetaVecMin = m_cosSinLookupTable->at(thetaMin);
219 const Vector2D& thetaVecMax = m_cosSinLookupTable->at(thetaMax);
220
221 float rHitMin = thetaVecMin.dot(pos2D);
222 float rHitMax = thetaVecMax.dot(pos2D);
223
224 // compute Legendre curves at the left and right borders of the node
225 float rHitMinRight = rHitMin - driftLength;
226 float rHitMaxRight = rHitMax - driftLength;
227
228 float rHitMinLeft = rHitMin + driftLength;
229 float rHitMaxLeft = rHitMax + driftLength;
230
231 // Compute distance from the Legendre curves to bottom and top borders of the node
232 distRight[0][0] = rMin - rHitMinRight;
233 distRight[0][1] = rMin - rHitMaxRight;
234 distRight[1][0] = rMax - rHitMinRight;
235 distRight[1][1] = rMax - rHitMaxRight;
236
237 distLeft[0][0] = rMin - rHitMinLeft;
238 distLeft[0][1] = rMin - rHitMaxLeft;
239 distLeft[1][0] = rMax - rHitMinLeft;
240 distLeft[1][1] = rMax - rHitMaxLeft;
241
242 // Compare distance signs from Legendre curves to the node
243 // Check right
244 if (not sameSign(distRight[0][0], distRight[0][1], distRight[1][0], distRight[1][1])) {
245 return true;
246 }
247
248 // Check left
249 if (not sameSign(distLeft[0][0], distLeft[0][1], distLeft[1][0], distLeft[1][1])) {
250 return true;
251 }
252
253 // Check the extremum
254 float rHitMinExtr = thetaVecMin.cross(pos2D);
255 float rHitMaxExtr = thetaVecMax.cross(pos2D);
256 if (rHitMinExtr * rHitMaxExtr < 0.) return checkExtremum(node, wireHit);
257
258 // Not contained
259 return false;
260}
261
262void AxialHitQuadTreeProcessor::insertItemsInNodes(const std::vector<QuadTree*>& nodes,
263 const std::vector<Item*>& items)
264{
265 const size_t nNodes = nodes.size();
266 if (nNodes == 0 or items.empty()) return;
267
268 // Collect the geometry of the nodes and group them by their theta span.
269 // The nodes handed here are either the four children of one node or the nodes of the seed
270 // level, which both cover only a handful of distinct theta spans.
271 m_thetaSpanCaches.clear();
272 m_nodeCaches.resize(nNodes);
273
274 for (size_t iNode = 0; iNode < nNodes; ++iNode) {
275 QuadTree* node = nodes[iNode];
276 NodeCache& nodeCache = m_nodeCaches[iNode];
277 nodeCache.yMin = node->getYMin();
278 nodeCache.yMax = node->getYMax();
279 nodeCache.needsDerivativeCheck = node->getLevel() <= 4 and m_twoSidedPhaseSpace and
280 nodeCache.yMin > -c_curlCurv and nodeCache.yMax < c_curlCurv;
281
282 const long xMin = node->getXMin();
283 const long xMax = node->getXMax();
284
285 size_t iThetaSpan = 0;
286 for (; iThetaSpan < m_thetaSpanCaches.size(); ++iThetaSpan) {
287 if (m_thetaSpanCaches[iThetaSpan].xMin == xMin and m_thetaSpanCaches[iThetaSpan].xMax == xMax) break;
288 }
289 if (iThetaSpan == m_thetaSpanCaches.size()) {
290 ThetaSpanCache thetaSpanCache;
291 thetaSpanCache.xMin = xMin;
292 thetaSpanCache.xMax = xMax;
293 thetaSpanCache.thetaVecMin = &m_cosSinLookupTable->at(xMin);
294 thetaSpanCache.thetaVecMax = &m_cosSinLookupTable->at(xMax);
295 m_thetaSpanCaches.push_back(thetaSpanCache);
296 }
297 nodeCache.iThetaSpan = iThetaSpan;
298 }
299
300 const size_t nThetaSpans = m_thetaSpanCaches.size();
301
302 for (Item* item : items) {
303 if (item->isUsed()) continue;
304
305 const CDCWireHit* wireHit = item->getPointer();
306
307 // Quantities that only depend on the hit
308 const double driftLength = wireHit->getRefDriftLength();
309 const Vector2D pos2D = wireHit->getRefPos2D() - m_localOrigin;
310 const double r2 = pos2D.normSquared() - driftLength * driftLength;
311
312 // Quantities that only depend on the hit and the theta span of a node
313 for (size_t iThetaSpan = 0; iThetaSpan < nThetaSpans; ++iThetaSpan) {
314 ThetaSpanCache& thetaSpanCache = m_thetaSpanCaches[iThetaSpan];
315 const Vector2D& thetaVecMin = *thetaSpanCache.thetaVecMin;
316 const Vector2D& thetaVecMax = *thetaSpanCache.thetaVecMax;
317
318 const float rHitMin = thetaVecMin.dot(pos2D);
319 const float rHitMax = thetaVecMax.dot(pos2D);
320
321 thetaSpanCache.rHitMinRight = rHitMin - driftLength;
322 thetaSpanCache.rHitMaxRight = rHitMax - driftLength;
323 thetaSpanCache.rHitMinLeft = rHitMin + driftLength;
324 thetaSpanCache.rHitMaxLeft = rHitMax + driftLength;
325
326 const float rHitMinExtr = thetaVecMin.cross(pos2D);
327 const float rHitMaxExtr = thetaVecMax.cross(pos2D);
328 thetaSpanCache.rHitMinExtr = rHitMinExtr;
329 thetaSpanCache.rHitMaxExtr = rHitMaxExtr;
330
331 // Same decision as checkDerivative()
332 thetaSpanCache.derivativeOk = ((rHitMinExtr > 0) and (rHitMaxExtr * rHitMinExtr >= 0)) or
333 (rHitMaxExtr * rHitMinExtr < 0);
334
335 thetaSpanCache.hasExtremum = rHitMinExtr * rHitMaxExtr < 0.;
336 if (thetaSpanCache.hasExtremum) {
337 thetaSpanCache.extremumIsBetween = pos2D.isBetween(thetaVecMin, thetaVecMax);
338 }
339 }
340
341 // Legendre curves at the extremum - only needed if some theta span contains the extremum
342 bool extremumComputed = false;
343 float rRight = 0;
344 float rLeft = 0;
345
346 for (size_t iNode = 0; iNode < nNodes; ++iNode) {
347 const NodeCache& nodeCache = m_nodeCaches[iNode];
348 const ThetaSpanCache& thetaSpanCache = m_thetaSpanCaches[nodeCache.iThetaSpan];
349
350 // Check whether the hit lies in the forward direction
351 if (nodeCache.needsDerivativeCheck and not thetaSpanCache.derivativeOk) continue;
352
353 // get top and bottom borders of the node
354 const float rMin = nodeCache.yMin * r2 / 2;
355 const float rMax = nodeCache.yMax * r2 / 2;
356
357 // Compare distance signs from the Legendre curves to the node
358 // Check right
359 if (not sameSign(rMin - thetaSpanCache.rHitMinRight,
360 rMin - thetaSpanCache.rHitMaxRight,
361 rMax - thetaSpanCache.rHitMinRight,
362 rMax - thetaSpanCache.rHitMaxRight)) {
363 nodes[iNode]->insertItem(item);
364 continue;
365 }
366
367 // Check left
368 if (not sameSign(rMin - thetaSpanCache.rHitMinLeft,
369 rMin - thetaSpanCache.rHitMaxLeft,
370 rMax - thetaSpanCache.rHitMinLeft,
371 rMax - thetaSpanCache.rHitMaxLeft)) {
372 nodes[iNode]->insertItem(item);
373 continue;
374 }
375
376 // Check the extremum
377 if (not thetaSpanCache.hasExtremum) continue;
378 if (not thetaSpanCache.extremumIsBetween) continue;
379
380 if (not extremumComputed) {
381 const double r = pos2D.norm();
382 rRight = r - driftLength;
383 rLeft = r + driftLength;
384 extremumComputed = true;
385 }
386
387 const bool crossesRight = (rMin - rRight) * (rMax - rRight) < 0;
388 const bool crossesLeft = (rMin - rLeft) * (rMax - rLeft) < 0;
389 if (crossesRight or crossesLeft) {
390 nodes[iNode]->insertItem(item);
391 }
392 }
393 }
394}
395
397{
398 const Vector2D& pos2D = wireHit->getRefPos2D() - m_localOrigin;
399
400 long thetaMin = node->getXMin();
401 long thetaMax = node->getXMax();
402
403 const Vector2D& thetaVecMin = m_cosSinLookupTable->at(thetaMin);
404 const Vector2D& thetaVecMax = m_cosSinLookupTable->at(thetaMax);
405
406 float rMinD = thetaVecMin.cross(pos2D);
407 float rMaxD = thetaVecMax.cross(pos2D);
408
409 // Does not really make sense...
410 if ((rMinD > 0) && (rMaxD * rMinD >= 0)) return true;
411 if ((rMaxD * rMinD < 0)) return true;
412 return false;
413}
414
416{
417 const double& driftLength = wireHit->getRefDriftLength();
418 const Vector2D& pos2D = wireHit->getRefPos2D() - m_localOrigin;
419 double r2 = pos2D.normSquared() - driftLength * driftLength;
420
421 // get left and right borders of the node
422 long thetaMin = node->getXMin();
423 long thetaMax = node->getXMax();
424
425 const Vector2D& thetaVecMin = m_cosSinLookupTable->at(thetaMin);
426 const Vector2D& thetaVecMax = m_cosSinLookupTable->at(thetaMax);
427
428 if (not pos2D.isBetween(thetaVecMin, thetaVecMax)) return false;
429
430 // compute Legendre curves at the position
431 double r = pos2D.norm();
432 float rRight = r - driftLength;
433 float rLeft = r + driftLength;
434
435 // get top and bottom borders of the node
436 float rMin = node->getYMin() * r2 / 2;
437 float rMax = node->getYMax() * r2 / 2;
438
439 bool crossesRight = (rMin - rRight) * (rMax - rRight) < 0;
440 bool crossesLeft = (rMin - rLeft) * (rMax - rLeft) < 0;
441 return crossesRight or crossesLeft;
442}
443
444void AxialHitQuadTreeProcessor::drawHits(std::vector<const CDCWireHit*> hits, unsigned int color) const
445{
446 static int nevent(0);
447
448 TCanvas* canv = new TCanvas("canv", "legendre transform", 0, 0, 1200, 600);
449 canv->cd(1);
450 TGraph* dummyGraph = new TGraph();
451 dummyGraph->SetPoint(1, -M_PI, 0);
452 dummyGraph->SetPoint(2, M_PI, 0);
453 dummyGraph->Draw("AP");
454 dummyGraph->GetXaxis()->SetTitle("#theta");
455 dummyGraph->GetYaxis()->SetTitle("#rho");
456 dummyGraph->GetXaxis()->SetRangeUser(-M_PI, M_PI);
457 dummyGraph->GetYaxis()->SetRangeUser(-0.02, 0.15);
458
459 for (const CDCWireHit* wireHit : hits) {
460 const double& driftLength = wireHit->getRefDriftLength();
461 const Vector2D& pos2D = wireHit->getRefPos2D() - m_localOrigin;
462 double x = pos2D.x();
463 double y = pos2D.y();
464 double r2 = pos2D.normSquared() - driftLength * driftLength;
465
466 TF1* concaveHitLegendre = new TF1("concaveHitLegendre", "2*([0]/[3])*cos(x) + 2*([1]/[3])*sin(x) + 2*([2]/[3])", -M_PI, M_PI);
467 TF1* convexHitLegendre = new TF1("convexHitLegendre", "2*([0]/[3])*cos(x) + 2*([1]/[3])*sin(x) - 2*([2]/[3])", -M_PI, M_PI);
468 concaveHitLegendre->SetLineWidth(1);
469 convexHitLegendre->SetLineWidth(1);
470 concaveHitLegendre->SetLineColor(color);
471 convexHitLegendre->SetLineColor(color);
472
473 concaveHitLegendre->SetParameters(x, y, driftLength, r2);
474 convexHitLegendre->SetParameters(x, y, driftLength, r2);
475 concaveHitLegendre->Draw("CSAME");
476 convexHitLegendre->Draw("CSAME");
477 }
478// canv->Print(Form("legendreHits_%i.root", nevent));
479// canv->Print(Form("legendreHits_%i.eps", nevent));
480 canv->Print(Form("legendreHits_%i.png", nevent));
481 delete canv;
482
483 nevent++;
484}
485
487{
488 std::vector<const CDCWireHit*> hits;
489 for (Item* item : node->getItems()) {
490 const CDCWireHit* wireHit = item->getPointer();
491 hits.push_back(wireHit);
492 }
493 drawHits(hits);
494}
void insertItemsInNodes(const std::vector< QuadTree * > &nodes, const std::vector< Item * > &items) final
Insert the hits into the given nodes sharing the parts of the containment check that do not depend on...
std::vector< ThetaSpanCache > m_thetaSpanCaches
Reusable buffer with the per theta span quantities - one entry per distinct theta span.
XYSpans createChild(QuadTree *node, int i, int j) const final
Return the new ranges.
const double c_curlCurv
The curvature above which the trajectory is considered a curler.
bool m_twoSidedPhaseSpace
Indicator whether the two sided phases space insertion check should be used This option should automa...
void drawHits(std::vector< const TrackingUtilities::CDCWireHit * > hits, unsigned int color=46) const
Draw QuadTree node.
TrackingUtilities::Vector2D m_localOrigin
Local origin on which the phase space coordinates are centered.
bool checkDerivative(QuadTree *node, const TrackingUtilities::CDCWireHit *wireHit) const
Check derivative of the Legendre curve.
bool isLeaf(QuadTree *node) const final
lastLevel depends on curvature of the track candidate
bool isInNode(QuadTree *node, const TrackingUtilities::CDCWireHit *wireHit) const final
Check whether hit belongs to the quadtree node:
bool checkExtremum(QuadTree *node, const TrackingUtilities::CDCWireHit *wireHit) const
Checks whether extreme point is located within QuadTree node's ranges.
AxialHitQuadTreeProcessor(int lastLevel, int seedLevel, const XYSpans &ranges, PrecisionUtil::PrecisionFunction precisionFunction)
Constructor.
PrecisionUtil::PrecisionFunction m_precisionFunction
Lambda which holds resolution function for the quadtree.
static const TrackingUtilities::LookupTable< TrackingUtilities::Vector2D > & getCosSinLookupTable()
Get the standard lookup table containing equally spaces unit vectors (cos, sin)
std::vector< NodeCache > m_nodeCaches
Reusable buffer with the per node quantities - one entry per node.
void drawNode(QuadTree *node) const
Draw QuadTree node.
static std::vector< float > createCurvBound(YSpan curvSpan, int lastLevel)
Constructs an array with the curvature bounds as generated by the default bin divisions.
const TrackingUtilities::LookupTable< TrackingUtilities::Vector2D > * m_cosSinLookupTable
Pinned lookup table for precomputed cosine and sine values.
static constexpr int getLookupGridLevel()
Returns desired deepness of the trigonometrical lookup table. Used as template parameter for the Trig...
std::function< double(double)> PrecisionFunction
Function type which is used for resolution calculations (resolution=f(curvature)) Takes a curvature v...
std::vector< AItem * > & getItems()
Get items from node.
AY getYBinWidth(int iBin)
Getter for the width of the iBin bin in "r" direction.
AX getXMax() const
Get maximal "Theta" value of the node.
AY getYMax() const
Get maximal "r" value of the node.
AY getYMin() const
Get minimal "r" value of the node.
int getLevel() const
Returns level of the node in tree (i.e., how much ancestors the node has)
AX getXLowerBound(int iBin) const
Get lower "Theta" value of given bin.
AY getYUpperBound(int iBin) const
Get upper "r" value of given bin.
AY getYLowerBound(int iBin) const
Get lower "r" value of given bin.
AX getXMin() const
Get minimal "Theta" value of the node.
AX getXUpperBound(int iBin) const
Get upper "Theta" value of given bin.
QuadTreeProcessor(int lastLevel, int seedLevel, const XYSpans &xySpans, bool debugOutput=false)
Class representing a hit wire in the central drift chamber.
Definition CDCWireHit.h:58
Class which holds precomputed values of a function.
Definition LookupTable.h:50
int getNPoints() const
Return the number of finite sampling points in this lookup table.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition Vector2D.h:36
double dot(const Vector2D &rhs) const
Calculates the two dimensional dot product.
Definition Vector2D.h:174
double cross(const Vector2D &rhs) const
Calculated the two dimensional cross product.
Definition Vector2D.h:185
double x() const
Getter for the x coordinate.
Definition Vector2D.h:622
bool isBetween(const Vector2D &lower, const Vector2D &upper) const
Checks if this vector is between two other vectors Between means here that when rotating the lower ve...
Definition Vector2D.h:552
double normSquared() const
Calculates .
Definition Vector2D.h:191
double y() const
Getter for the y coordinate.
Definition Vector2D.h:637
double norm() const
Calculates the length of the vector.
Definition Vector2D.h:202
static Vector2D Phi(const double phi)
Constructs a unit vector with azimuth angle equal to phi.
Definition Vector2D.h:78
bool sameSign(double expected, double actual)
Predicate checking that two values have the same sign.
Abstract base class for different kinds of events.
Geometry of a node that is needed in the containment check.
int iThetaSpan
Index of the theta span of the node in the theta span cache.
bool needsDerivativeCheck
Indicator that the forward direction of the hit has to be checked for this node.
Quantities entering the node containment check that only depend on the hit and on the theta span of a...
bool extremumIsBetween
Indicator that the extremum is a candidate for the containment check.
const TrackingUtilities::Vector2D * thetaVecMax
Unit vector (cos, sin) at the upper theta bound.
float rHitMaxRight
Legendre curve of the right passage hypothesis at the upper theta bound.
long xMin
Lower theta bound of the nodes in this group as an index into the lookup table.
float rHitMaxExtr
Derivative of the Legendre curve at the upper theta bound.
float rHitMinExtr
Derivative of the Legendre curve at the lower theta bound.
bool hasExtremum
Indicator that the extremum of the Legendre curve lies within this theta span.
long xMax
Upper theta bound of the nodes in this group as an index into the lookup table.
float rHitMinRight
Legendre curve of the right passage hypothesis at the lower theta bound.
bool derivativeOk
Result of the derivative check for this theta span.
const TrackingUtilities::Vector2D * thetaVecMin
Unit vector (cos, sin) at the lower theta bound.
float rHitMaxLeft
Legendre curve of the left passage hypothesis at the upper theta bound.
float rHitMinLeft
Legendre curve of the left passage hypothesis at the lower theta bound.