Belle II Software development
StereoHitTrackQuadTreeMatcher.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/collectors/matchers/StereoHitTrackQuadTreeMatcher.h>
9
10#include <tracking/trackFindingCDC/hough/z0_tanLambda/HitZ0TanLambdaLegendre.h>
11#include <tracking/trackFindingCDC/hough/quadratic/HitQuadraticLegendre.h>
12#include <tracking/trackFindingCDC/hough/hyperbolic/HitHyperHough.h>
13
14#include <tracking/trackingUtilities/eventdata/tracks/CDCTrack.h>
15
16#include <tracking/trackingUtilities/eventdata/hits/CDCRLWireHit.h>
17#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
18#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
19
20#include <tracking/trackingUtilities/ca/AutomatonCell.h>
21
22#include <framework/core/ModuleParamList.templateDetails.h>
23
24#include <tracking/trackingUtilities/utilities/StringManipulation.h>
25
26#include <Math/Vector3D.h>
27
28#include <utility>
29
30using namespace Belle2;
31using namespace CDC;
32using namespace TrackFindingCDC;
33using namespace TrackingUtilities;
34
35template <class AQuadTree>
37 const std::string& prefix)
39 Super::exposeParameters(moduleParamList, prefix);
40
41 moduleParamList->addParameter(prefixed(prefix, "level"), m_param_quadTreeLevel,
42 "The number of levels for the quad tree search.",
44
45 moduleParamList->addParameter(prefixed(prefix, "minimumNumberOfHits"), m_param_minimumNumberOfHits,
46 "The minimum number of hits in a quad tree bin to be called as result.",
48
49 moduleParamList->addParameter(prefixed(prefix, "writeDebugInformation"), m_param_writeDebugInformation,
50 "Set to true to output debug information.",
52
53 moduleParamList->addParameter(prefixed(prefix, "checkForB2BTracks"),
55 "Set to false to skip the check for back-2-back tracks "
56 "(good for cosmics).",
58
59 moduleParamList->addParameter(prefixed(prefix, "checkForInWireBoundsFactor"),
61 "Used to scale the CDC before checking "
62 "whether hits are in the CDC z bounds.",
64}
65
66
67template <class AQuadTree>
75
76
77template <class AQuadTree>
84
85template <class AQuadTree>
86void StereoHitTrackQuadTreeMatcher<AQuadTree>::match(CDCTrack& track, const std::vector<CDCRLWireHit>& rlWireHits,
87 std::vector<Super::WeightedRelationItem>& relationsForCollector)
88{
89 // TODO: Extract this into smaller steps
90 // TODO: Split the filtering from the rest.
91 // This means this method would output WeightedRelations based on the quad tree decision and a second filter step
92 // can be applied on these weighted relations
93
94 // Reconstruct the hits to the track
95 const CDCTrajectory2D& trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
96 const bool isCurler = trajectory2D.isCurler();
97
98 using CDCRecoHitWithRLPointer = std::pair<CDCRecoHit3D, const CDCRLWireHit*>;
99 std::vector<CDCRecoHitWithRLPointer> recoHits;
100 recoHits.reserve(rlWireHits.size() + track.size());
101
102 /*
103 * Use the given trajectory to reconstruct the 2d hits in the vector in z direction
104 * to match the trajectory perfectly. Then add the newly created reconstructed 3D hit to the given list.
105 */
106 for (const CDCRLWireHit& rlWireHit : rlWireHits) {
107 if (rlWireHit.getWireHit().getAutomatonCell().hasTakenFlag()) continue;
108
109 const CDCWire& wire = rlWireHit.getWire();
110 const WireLine& wireLine = wire.getWireLine();
111 double signedDriftLength = rlWireHit.getSignedRefDriftLength();
112 // Equivalent to trajectory2D.reconstructBoth3D(wireLine, signedDriftLength), but the z bounds check,
113 // which only depends on the z solution, is done before the costly calculation of the xy position.
114 for (const double recoZ : trajectory2D.reconstructBothZ(wireLine, signedDriftLength)) {
115 // Skip hits out of CDC
116 if (not wire.isInCellZBounds(ROOT::Math::XYZVector(0.0, 0.0, recoZ), m_param_checkForInWireBoundsFactor)) {
117 continue;
118 }
119 const ROOT::Math::XYZVector recoWirePos3D = wireLine.sagPos3DAtZ(recoZ);
120 const auto& closest = trajectory2D.getClosest(VectorUtil::getXYVector(recoWirePos3D));
121 const ROOT::Math::XYZVector recoPos3D(closest.X(), closest.Y(), recoWirePos3D.z());
122
123 // If the track is a curler, shift all perpS values to positive ones.
124 // Else do not use this hit if m_param_checkForB2BTracks is enabled.
125 double perpS = trajectory2D.calcArcLength2D(VectorUtil::getXYVector(recoPos3D));
126 if (perpS < 0) {
127 if (isCurler) {
128 perpS += trajectory2D.getArcLength2DPeriod();
129 } else if (m_param_checkForB2BTracks) {
130 continue;
131 }
132 }
133 recoHits.emplace_back(CDCRecoHit3D(rlWireHit, recoPos3D, perpS), &rlWireHit);
134 }
135 }
136
137 // Also add already found stereo hits of the track
138 for (const CDCRecoHit3D& recoHit : track) {
139 if (not recoHit.isAxial()) {
140 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
141 const CDCRLWireHit& rlWireHit = recoHit.getRLWireHit();
142 recoHits.emplace_back(recoHit, &rlWireHit);
143 }
144 }
145
146 // Do the tree finding
147 m_quadTreeInstance.seed(recoHits);
148
151 }
152
153 const auto& foundStereoHitsWithNode = m_quadTreeInstance.findSingleBest(m_param_minimumNumberOfHits);
154 m_quadTreeInstance.fell();
155
156 if (foundStereoHitsWithNode.size() != 1) {
157 return;
158 }
159
160 // There is the possibility that we have added one cdc hits twice (as left and right one). We search for those cases here:
161 auto foundStereoHits = foundStereoHitsWithNode[0].second;
162 const auto& node = foundStereoHitsWithNode[0].first;
163
165 std::vector<CDCRecoHit3D> allHits;
166 std::vector<CDCRecoHit3D> foundHits;
167 // Turn vector of pairs into vector of first items
168 for (const CDCRecoHitWithRLPointer& recoHitWithRL : recoHits) {
169 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
170 allHits.push_back(recoHit3D);
171 }
172 for (const CDCRecoHitWithRLPointer& recoHitWithRL : foundStereoHits) {
173 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
174 foundHits.push_back(recoHit3D);
175 }
176 m_quadTreeInstance.drawDebugPlot(allHits, foundHits, node);
177 }
178
179 // Remove all assigned hits, which where already found before (and do not need to be added again)
180 const auto& isAssignedHit = [](const CDCRecoHitWithRLPointer & recoHitWithRLPointer) {
181 const CDCRecoHit3D& recoHit3D = recoHitWithRLPointer.first;
182 const auto& automatonCell = recoHit3D.getWireHit().getAutomatonCell();
183 return automatonCell.hasAssignedFlag();
184 };
185
186 foundStereoHits.erase(std::remove_if(foundStereoHits.begin(),
187 foundStereoHits.end(),
188 isAssignedHit),
189 foundStereoHits.end());
190
191 // Sort the found stereo hits by same CDCHit and smaller distance to the node
192 auto sortByHitAndNodeCenterDistance = [node](const CDCRecoHitWithRLPointer & lhs,
193 const CDCRecoHitWithRLPointer & rhs) {
194
195
196 const CDCRecoHit3D& rhsRecoHit = rhs.first;
197 const CDCRecoHit3D& lhsRecoHit = lhs.first;
198
199 const CDCWireHit& rhsWireHit = rhsRecoHit.getWireHit();
200 const CDCWireHit& lhsWireHit = lhsRecoHit.getWireHit();
201
202 if (lhsWireHit < rhsWireHit) {
203 return true;
204 } else if (rhsWireHit < lhsWireHit) {
205 return false;
206 } else {
207 return AQuadTree::DecisionAlgorithm::BoxAlgorithm::compareDistances(node, lhsRecoHit, rhsRecoHit); //returns true if lhs < rhs
208 }
209 };
210
211 const auto& sameHitComparer = [](const CDCRecoHitWithRLPointer & lhs,
212 const CDCRecoHitWithRLPointer & rhs) {
213 const CDCRecoHit3D& rhsRecoHit = rhs.first;
214 const CDCRecoHit3D& lhsRecoHit = lhs.first;
215
216 return lhsRecoHit.getWireHit() == rhsRecoHit.getWireHit();
217 };
218
219 std::sort(foundStereoHits.begin(),
220 foundStereoHits.end(),
221 sortByHitAndNodeCenterDistance);
222
223 // If the same hit is added as right and left hypothesis, do only use the one with the smaller distance to the node.
224 foundStereoHits.erase(std::unique(foundStereoHits.begin(),
225 foundStereoHits.end(),
226 sameHitComparer),
227 foundStereoHits.end());
228
229 // Add the found stereo hits to the relation vector. In the moment, all hits get the same weight (may change later).
230 for (const CDCRecoHitWithRLPointer& recoHitWithRLPointer : foundStereoHits) {
231 const CDCRLWireHit* rlWireHit = recoHitWithRLPointer.second;
232 relationsForCollector.emplace_back(&track, foundStereoHits.size(), rlWireHit);
233 }
234}
235
236template <class AQuadTree>
238{
239 std::string outputFileName = "quadTreeContent_call_" + std::to_string(m_numberOfPassedDebugCalls) + ".root";
240 m_quadTreeInstance.writeDebugInfoToFile(outputFileName);
241
243}
244
Class representing a sense wire in the central drift chamber.
Definition CDCWire.h:50
bool isInCellZBounds(const ROOT::Math::XYZVector &pos3D, const double factor=1) const
Checks whether the position is in the z bounds of the drift cell (scaled by the factor) surrounding t...
Definition CDCWire.h:287
const WireLine & getWireLine() const
Getter for the wire line representation of the wire.
Definition CDCWire.h:180
A three dimensional limited line represented by its closest approach to the z-axes (reference positio...
Definition WireLine.h:33
ROOT::Math::XYZVector sagPos3DAtZ(const double z) const
Gives the three dimensional position with wire sag effect of the line at the given z value.
Definition WireLine.h:61
The Module parameter list class.
A matcher algorithm for using a stereo quad tree for matching rl tagged wire hits to tracks.
void initialize() override
Initialize the filter and the quad tree.
void terminate() override
Terminate the filter and the quad tree.
unsigned int m_numberOfPassedDebugCalls
Store the number of passed calls to the debug function.
void match(TrackingUtilities::CDCTrack &track, const std::vector< TrackingUtilities::CDCRLWireHit > &rlWireHits, std::vector< Super::WeightedRelationItem > &relationsForCollector) override
Create a QuadTree and fill with each unused stereo hit (to be exact: twice for each stereo hit - righ...
void writeDebugInformation()
Use the writeDebugInformation function of the quad tree to write the tree into a root file with a asc...
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) override
Expose the parameters to the module.
bool hasAssignedFlag() const
Gets the current state of the already assigned marker flag.
Class representing an oriented hit wire including a hypotheses whether the causing track passes left ...
Class representing a three dimensional reconstructed hit.
const CDCWireHit & getWireHit() const
Getter for the wire hit.
Class representing a sequence of three dimensional reconstructed hits.
Definition CDCTrack.h:37
Particle trajectory as it is seen in xy projection represented as a circle.
ROOT::Math::XYVector getClosest(const ROOT::Math::XYVector &point) const
Calculates the closest approach on the trajectory to the given point.
double calcArcLength2D(const ROOT::Math::XYVector &point) const
Calculate the travel distance from the start position of the trajectory.
bool isCurler(double factor=1) const
Checks if the trajectory leaves the outer radius of the CDC times the given tolerance factor.
double getArcLength2DPeriod() const
Getter for the arc length for one round trip around the trajectory.
std::array< double, 2 > reconstructBothZ(const CDC::WireLine &wireLine, double distance=0.0, double z=0) const
Gives the two z positions where the given drift circle on the wire line touches the trajectory.
Class representing a hit wire in the central drift chamber.
Definition CDCWireHit.h:56
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
Definition CDCWireHit.h:287
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
Abstract base class for different kinds of events.