8#include <tracking/trackFindingCDC/legendre/quadtree/AxialHitQuadTreeProcessor.h>
10#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
11#include <tracking/trackingUtilities/geometry/VectorUtil.h>
16#include <Math/Vector2D.h>
23using namespace TrackFindingCDC;
24using namespace TrackingUtilities;
27 bool sameSign(
double n1,
double n2,
double n3,
double n4)
29 return ((n1 > 0 && n2 > 0 && n3 > 0 && n4 > 0) || (n1 < 0 && n2 < 0 && n3 < 0 && n4 < 0));
32 using YSpan = AxialHitQuadTreeProcessor::YSpan;
33 YSpan splitCurvSpan(
const YSpan& curvSpan,
int nodeLevel,
int lastLevel,
int j)
35 const float meanCurv = curvSpan[0] + (curvSpan[1] - curvSpan[0]) / 2.0;
36 const std::array<float, 3> binBounds{curvSpan[0], meanCurv, curvSpan[1]};
37 const float binWidth = binBounds[j + 1] - binBounds[j];
39 const bool standardBinning = (nodeLevel <= lastLevel - 7) or (std::fabs(meanCurv) <= 0.005);
40 if (standardBinning) {
42 float curv1 = binBounds[j];
43 float curv2 = binBounds[j + 1];
46 return {curv1, curv2};
52 if (nodeLevel < lastLevel - 5) {
54 float curv1 = binBounds[j] - binWidth / 4.;
55 float curv2 = binBounds[j + 1] + binWidth / 4.;
56 return {curv1, curv2};
59 float curv1 = binBounds[j] - binWidth / 8.;
60 float curv2 = binBounds[j + 1] + binWidth / 8.;
61 return {curv1, curv2};
69 std::vector<YSpan> spans{{curvSpan}};
71 std::vector<YSpan> nextSpans;
72 for (
int level = 1; level <= lastLevel; ++level) {
74 for (
const YSpan& span : spans) {
75 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 0));
76 nextSpans.push_back(splitCurvSpan(span, level, lastLevel, 1));
78 spans.swap(nextSpans);
81 std::vector<float> bounds;
82 for (
const YSpan& span : spans) {
83 bounds.push_back(span[0]);
84 bounds.push_back(span[1]);
87 assert(bounds.size() == std::pow(2, lastLevel));
94 static const int nBins = std::pow(2, maxLevel);
96 return trigonometricLookUpTable;
112 const YSpan& curvSpan,
115, m_localOrigin(localOrigin)
116, m_cosSinLookupTable(cosSinLookupTable)
119 m_twoSidedPhaseSpace =
false;
125 if (node->
getLevel() <= 6)
return false;
128 const double nodeResolution = fabs(node->
getYMin() - node->
getYMax());
132 if (resolution >= nodeResolution)
return true;
140 const int nodeLevel = node->
getLevel();
142 const float meanCurv = std::fabs(node->
getYMax() + node->
getYMin()) / 2;
146 bool standardBinning = (nodeLevel <= lastLevel - 7) or (meanCurv <= 0.005);
148 if (standardBinning) {
155 return XYSpans({theta1, theta2}, {r1, r2});
161 if (nodeLevel < lastLevel - 5) {
166 long extension = pow(2, lastLevel - nodeLevel - 2);
169 if (theta1 < 0) theta1 = 0;
176 return XYSpans({theta1, theta2}, {r1, r2});
182 long extension = pow(2, lastLevel - nodeLevel - 3);
185 if (theta1 < 0) theta1 = 0;
192 return XYSpans({theta1, theta2}, {r1, r2});
204 const double& l = wireHit->getRefDriftLength();
205 const ROOT::Math::XYVector& pos2D = wireHit->getRefPos2D() -
m_localOrigin;
206 double r2 = pos2D.Mag2() - l * l;
208 using Quadlet = std::array<std::array<float, 2>, 2>;
213 float rMin = node->
getYMin() * r2 / 2;
214 float rMax = node->
getYMax() * r2 / 2;
217 long thetaMin = node->
getXMin();
218 long thetaMax = node->
getXMax();
223 float rHitMin = thetaVecMin.Dot(pos2D);
224 float rHitMax = thetaVecMax.Dot(pos2D);
227 float rHitMinRight = rHitMin - l;
228 float rHitMaxRight = rHitMax - l;
230 float rHitMinLeft = rHitMin + l;
231 float rHitMaxLeft = rHitMax + l;
234 distRight[0][0] = rMin - rHitMinRight;
235 distRight[0][1] = rMin - rHitMaxRight;
236 distRight[1][0] = rMax - rHitMinRight;
237 distRight[1][1] = rMax - rHitMaxRight;
239 distLeft[0][0] = rMin - rHitMinLeft;
240 distLeft[0][1] = rMin - rHitMaxLeft;
241 distLeft[1][0] = rMax - rHitMinLeft;
242 distLeft[1][1] = rMax - rHitMaxLeft;
246 if (not sameSign(distRight[0][0], distRight[0][1], distRight[1][0], distRight[1][1])) {
251 if (not sameSign(distLeft[0][0], distLeft[0][1], distLeft[1][0], distLeft[1][1])) {
256 float rHitMinExtr = VectorUtil::Cross(thetaVecMin, pos2D);
257 float rHitMaxExtr = VectorUtil::Cross(thetaVecMax, pos2D);
258 if (rHitMinExtr * rHitMaxExtr < 0.)
return checkExtremum(node, wireHit);
266 const ROOT::Math::XYVector& pos2D = wireHit->getRefPos2D() -
m_localOrigin;
268 long thetaMin = node->
getXMin();
269 long thetaMax = node->
getXMax();
274 float rMinD = VectorUtil::Cross(thetaVecMin, pos2D);
275 float rMaxD = VectorUtil::Cross(thetaVecMax, pos2D);
278 if ((rMinD > 0) && (rMaxD * rMinD >= 0))
return true;
279 if ((rMaxD * rMinD < 0))
return true;
285 const double& l = wireHit->getRefDriftLength();
286 const ROOT::Math::XYVector& pos2D = wireHit->getRefPos2D() -
m_localOrigin;
287 double r2 = pos2D.Mag2() - l * l;
290 long thetaMin = node->
getXMin();
291 long thetaMax = node->
getXMax();
296 if (not VectorUtil::isBetween(pos2D, thetaVecMin, thetaVecMax))
return false;
299 double r = pos2D.R();
300 float rRight = r - l;
304 float rMin = node->
getYMin() * r2 / 2;
305 float rMax = node->
getYMax() * r2 / 2;
307 bool crossesRight = (rMin - rRight) * (rMax - rRight) < 0;
308 bool crossesLeft = (rMin - rLeft) * (rMax - rLeft) < 0;
309 return crossesRight or crossesLeft;
314 static int nevent(0);
316 TCanvas* canv =
new TCanvas(
"canv",
"legendre transform", 0, 0, 1200, 600);
318 TGraph* dummyGraph =
new TGraph();
319 dummyGraph->SetPoint(1, -M_PI, 0);
320 dummyGraph->SetPoint(2, M_PI, 0);
321 dummyGraph->Draw(
"AP");
322 dummyGraph->GetXaxis()->SetTitle(
"#theta");
323 dummyGraph->GetYaxis()->SetTitle(
"#rho");
324 dummyGraph->GetXaxis()->SetRangeUser(-M_PI, M_PI);
325 dummyGraph->GetYaxis()->SetRangeUser(-0.02, 0.15);
328 const double& l = wireHit->getRefDriftLength();
329 const ROOT::Math::XYVector& pos2D = wireHit->getRefPos2D() -
m_localOrigin;
330 double x = pos2D.x();
331 double y = pos2D.y();
332 double r2 = pos2D.Mag2() - l * l;
334 TF1* concaveHitLegendre =
new TF1(
"concaveHitLegendre",
"2*([0]/[3])*cos(x) + 2*([1]/[3])*sin(x) + 2*([2]/[3])", -M_PI, M_PI);
335 TF1* convexHitLegendre =
new TF1(
"convexHitLegendre",
"2*([0]/[3])*cos(x) + 2*([1]/[3])*sin(x) - 2*([2]/[3])", -M_PI, M_PI);
336 concaveHitLegendre->SetLineWidth(1);
337 convexHitLegendre->SetLineWidth(1);
338 concaveHitLegendre->SetLineColor(color);
339 convexHitLegendre->SetLineColor(color);
341 concaveHitLegendre->SetParameters(x, y, l, r2);
342 convexHitLegendre->SetParameters(x, y, l, r2);
343 concaveHitLegendre->Draw(
"CSAME");
344 convexHitLegendre->Draw(
"CSAME");
348 canv->Print(Form(
"legendreHits_%i.png", nevent));
356 std::vector<const CDCWireHit*> hits;
358 const CDCWireHit* wireHit = item->getPointer();
359 hits.push_back(wireHit);
XYSpans createChild(QuadTree *node, int i, int j) const final
Return the new ranges.
ROOT::Math::XYVector m_localOrigin
Local origin on which the phase space coordinates are centered.
const double c_curlCurv
The curvature above which the trajectory is considered a curler.
const TrackingUtilities::LookupTable< ROOT::Math::XYVector > * m_cosSinLookupTable
Pinned lookup table for precomputed cosine and sine values.
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.
bool checkDerivative(QuadTree *node, const TrackingUtilities::CDCWireHit *wireHit) const
Check derivative of the sinogram.
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.
void drawNode(QuadTree *node) const
Draw QuadTree node.
static const TrackingUtilities::LookupTable< ROOT::Math::XYVector > & getCosSinLookupTable()
Get the standard lookup table containing equally spaces unit vectors (cos, sin)
static std::vector< float > createCurvBound(YSpan curvSpan, int lastLevel)
Constructs an array with the curvature bounds as generated by the default bin divisions.
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.
bool sameSign(double expected, double actual)
Predicate checking that two values have the same sign.
Abstract base class for different kinds of events.