8#include <tracking/trackFindingCDC/legendre/quadtree/AxialHitQuadTreeProcessor.h>
10#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
21using namespace TrackFindingCDC;
22using namespace TrackingUtilities;
25 bool sameSign(
double n1,
double n2,
double n3,
double n4)
27 return ((n1 > 0 && n2 > 0 && n3 > 0 && n4 > 0) || (n1 < 0 && n2 < 0 && n3 < 0 && n4 < 0));
30 using YSpan = AxialHitQuadTreeProcessor::YSpan;
31 YSpan splitCurvSpan(
const YSpan& curvSpan,
int nodeLevel,
int lastLevel,
int j)
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];
37 const bool standardBinning = (nodeLevel <= lastLevel - 7) or (std::fabs(meanCurv) <= 0.005);
38 if (standardBinning) {
40 float curv1 = binBounds[j];
41 float curv2 = binBounds[j + 1];
44 return {curv1, curv2};
50 if (nodeLevel < lastLevel - 5) {
52 float curv1 = binBounds[j] - binWidth / 4.;
53 float curv2 = binBounds[j + 1] + binWidth / 4.;
54 return {curv1, curv2};
57 float curv1 = binBounds[j] - binWidth / 8.;
58 float curv2 = binBounds[j + 1] + binWidth / 8.;
59 return {curv1, curv2};
67 std::vector<YSpan> spans{{curvSpan}};
69 std::vector<YSpan> nextSpans;
70 for (
int level = 1; level <= lastLevel; ++level) {
72 for (
const YSpan& span : spans) {
73 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 0));
74 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 1));
76 spans.swap(nextSpans);
79 std::vector<float> bounds;
80 for (
const YSpan& span : spans) {
81 bounds.push_back(span[0]);
82 bounds.push_back(span[1]);
85 assert(bounds.size() == std::pow(2, lastLevel));
92 static const int nBins = std::pow(2, maxLevel);
94 return trigonometricLookUpTable;
110 const YSpan& curvSpan,
113, m_localOrigin(localOrigin)
114, m_cosSinLookupTable(cosSinLookupTable)
117 m_twoSidedPhaseSpace =
false;
123 if (node->
getLevel() <= 6)
return false;
126 const double nodeResolution = fabs(node->
getYMin() - node->
getYMax());
130 if (resolution >= nodeResolution)
return true;
138 const int nodeLevel = node->
getLevel();
140 const float meanCurv = std::fabs(node->
getYMax() + node->
getYMin()) / 2;
144 bool standardBinning = (nodeLevel <= lastLevel - 7) or (meanCurv <= 0.005);
146 if (standardBinning) {
153 return XYSpans({theta1, theta2}, {r1, r2});
159 if (nodeLevel < lastLevel - 5) {
164 long extension = pow(2, lastLevel - nodeLevel - 2);
167 if (theta1 < 0) theta1 = 0;
174 return XYSpans({theta1, theta2}, {r1, r2});
180 long extension = pow(2, lastLevel - nodeLevel - 3);
183 if (theta1 < 0) theta1 = 0;
190 return XYSpans({theta1, theta2}, {r1, r2});
202 const double& driftLength = wireHit->getRefDriftLength();
204 double r2 = pos2D.
normSquared() - driftLength * driftLength;
206 using Quadlet = std::array<std::array<float, 2>, 2>;
211 float rMin = node->
getYMin() * r2 / 2;
212 float rMax = node->
getYMax() * r2 / 2;
215 long thetaMin = node->
getXMin();
216 long thetaMax = node->
getXMax();
221 float rHitMin = thetaVecMin.
dot(pos2D);
222 float rHitMax = thetaVecMax.
dot(pos2D);
225 float rHitMinRight = rHitMin - driftLength;
226 float rHitMaxRight = rHitMax - driftLength;
228 float rHitMinLeft = rHitMin + driftLength;
229 float rHitMaxLeft = rHitMax + driftLength;
232 distRight[0][0] = rMin - rHitMinRight;
233 distRight[0][1] = rMin - rHitMaxRight;
234 distRight[1][0] = rMax - rHitMinRight;
235 distRight[1][1] = rMax - rHitMaxRight;
237 distLeft[0][0] = rMin - rHitMinLeft;
238 distLeft[0][1] = rMin - rHitMaxLeft;
239 distLeft[1][0] = rMax - rHitMinLeft;
240 distLeft[1][1] = rMax - rHitMaxLeft;
244 if (not sameSign(distRight[0][0], distRight[0][1], distRight[1][0], distRight[1][1])) {
249 if (not sameSign(distLeft[0][0], distLeft[0][1], distLeft[1][0], distLeft[1][1])) {
254 float rHitMinExtr = thetaVecMin.
cross(pos2D);
255 float rHitMaxExtr = thetaVecMax.
cross(pos2D);
256 if (rHitMinExtr * rHitMaxExtr < 0.)
return checkExtremum(node, wireHit);
263 const std::vector<Item*>& items)
265 const size_t nNodes = nodes.size();
266 if (nNodes == 0 or items.empty())
return;
274 for (
size_t iNode = 0; iNode < nNodes; ++iNode) {
282 const long xMin = node->
getXMin();
283 const long xMax = node->
getXMax();
285 size_t iThetaSpan = 0;
291 thetaSpanCache.
xMin = xMin;
292 thetaSpanCache.
xMax = xMax;
302 for (
Item* item : items) {
303 if (item->isUsed())
continue;
305 const CDCWireHit* wireHit = item->getPointer();
308 const double driftLength = wireHit->getRefDriftLength();
310 const double r2 = pos2D.
normSquared() - driftLength * driftLength;
313 for (
size_t iThetaSpan = 0; iThetaSpan < nThetaSpans; ++iThetaSpan) {
318 const float rHitMin = thetaVecMin.
dot(pos2D);
319 const float rHitMax = thetaVecMax.
dot(pos2D);
323 thetaSpanCache.
rHitMinLeft = rHitMin + driftLength;
324 thetaSpanCache.
rHitMaxLeft = rHitMax + driftLength;
326 const float rHitMinExtr = thetaVecMin.
cross(pos2D);
327 const float rHitMaxExtr = thetaVecMax.
cross(pos2D);
332 thetaSpanCache.
derivativeOk = ((rHitMinExtr > 0) and (rHitMaxExtr * rHitMinExtr >= 0)) or
333 (rHitMaxExtr * rHitMinExtr < 0);
335 thetaSpanCache.
hasExtremum = rHitMinExtr * rHitMaxExtr < 0.;
342 bool extremumComputed =
false;
346 for (
size_t iNode = 0; iNode < nNodes; ++iNode) {
354 const float rMin = nodeCache.
yMin * r2 / 2;
355 const float rMax = nodeCache.
yMax * r2 / 2;
363 nodes[iNode]->insertItem(item);
368 if (not sameSign(rMin - thetaSpanCache.
rHitMinLeft,
372 nodes[iNode]->insertItem(item);
380 if (not extremumComputed) {
381 const double r = pos2D.
norm();
382 rRight = r - driftLength;
383 rLeft = r + driftLength;
384 extremumComputed =
true;
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);
400 long thetaMin = node->
getXMin();
401 long thetaMax = node->
getXMax();
406 float rMinD = thetaVecMin.
cross(pos2D);
407 float rMaxD = thetaVecMax.
cross(pos2D);
410 if ((rMinD > 0) && (rMaxD * rMinD >= 0))
return true;
411 if ((rMaxD * rMinD < 0))
return true;
417 const double& driftLength = wireHit->getRefDriftLength();
419 double r2 = pos2D.
normSquared() - driftLength * driftLength;
422 long thetaMin = node->
getXMin();
423 long thetaMax = node->
getXMax();
428 if (not pos2D.
isBetween(thetaVecMin, thetaVecMax))
return false;
431 double r = pos2D.
norm();
432 float rRight = r - driftLength;
433 float rLeft = r + driftLength;
436 float rMin = node->
getYMin() * r2 / 2;
437 float rMax = node->
getYMax() * r2 / 2;
439 bool crossesRight = (rMin - rRight) * (rMax - rRight) < 0;
440 bool crossesLeft = (rMin - rLeft) * (rMax - rLeft) < 0;
441 return crossesRight or crossesLeft;
446 static int nevent(0);
448 TCanvas* canv =
new TCanvas(
"canv",
"legendre transform", 0, 0, 1200, 600);
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);
460 const double& driftLength = wireHit->getRefDriftLength();
462 double x = pos2D.
x();
463 double y = pos2D.
y();
464 double r2 = pos2D.
normSquared() - driftLength * driftLength;
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);
473 concaveHitLegendre->SetParameters(x, y, driftLength, r2);
474 convexHitLegendre->SetParameters(x, y, driftLength, r2);
475 concaveHitLegendre->Draw(
"CSAME");
476 convexHitLegendre->Draw(
"CSAME");
480 canv->Print(Form(
"legendreHits_%i.png", nevent));
488 std::vector<const CDCWireHit*> hits;
490 const CDCWireHit* wireHit = item->getPointer();
491 hits.push_back(wireHit);
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.
QuadTreeNode< long, float, Item > QuadTree
std::pair< XSpan, YSpan > XYSpans
QuadTreeProcessor(int lastLevel, int seedLevel, const XYSpans &xySpans, bool debugOutput=false)
typename QuadTree::YSpan YSpan
QuadTreeItem< const TrackingUtilities::CDCWireHit > Item
std::unique_ptr< QuadTree > m_quadTree
Class representing a hit wire in the central drift chamber.
Class which holds precomputed values of a function.
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...
double dot(const Vector2D &rhs) const
Calculates the two dimensional dot product.
double cross(const Vector2D &rhs) const
Calculated the two dimensional cross product.
double x() const
Getter for the x coordinate.
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...
double normSquared() const
Calculates .
double y() const
Getter for the y coordinate.
double norm() const
Calculates the length of the vector.
static Vector2D Phi(const double phi)
Constructs a unit vector with azimuth angle equal to phi.
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.
float yMax
Upper curvature bound of the node.
float yMin
Lower curvature bound of the 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.