Belle II Software prerelease-11-00-00e
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 <utility>
27
28using namespace Belle2;
29using namespace CDC;
30using namespace TrackFindingCDC;
31using namespace TrackingUtilities;
32
33template <class AQuadTree>
35 const std::string& prefix)
36{
37 Super::exposeParameters(moduleParamList, prefix);
39 moduleParamList->addParameter(prefixed(prefix, "level"), m_param_quadTreeLevel,
40 "The number of levels for the quad tree search.",
42
43 moduleParamList->addParameter(prefixed(prefix, "minimumNumberOfHits"), m_param_minimumNumberOfHits,
44 "The minimum number of hits in a quad tree bin to be called as result.",
46
47 moduleParamList->addParameter(prefixed(prefix, "writeDebugInformation"), m_param_writeDebugInformation,
48 "Set to true to output debug information.",
51 moduleParamList->addParameter(prefixed(prefix, "checkForB2BTracks"),
53 "Set to false to skip the check for back-2-back tracks "
54 "(good for cosmics).",
56
57 moduleParamList->addParameter(prefixed(prefix, "checkForInWireBoundsFactor"),
59 "Used to scale the CDC before checking "
60 "whether hits are in the CDC z bounds.",
62}
63
64
65template <class AQuadTree>
73
74
75template <class AQuadTree>
82
83template <class AQuadTree>
84void StereoHitTrackQuadTreeMatcher<AQuadTree>::match(CDCTrack& track, const std::vector<CDCRLWireHit>& rlWireHits,
85 std::vector<Super::WeightedRelationItem>& relationsForCollector)
86{
87 // TODO: Extract this into smaller steps
88 // TODO: Split the filtering from the rest.
89 // This means this method would output WeightedRelations based on the quad tree decision and a second filter step
90 // can be applied on these weighted relations
91
92 // Reconstruct the hits to the track
93 const CDCTrajectory2D& trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
94 const bool isCurler = trajectory2D.isCurler();
95
96 using CDCRecoHitWithRLPointer = std::pair<CDCRecoHit3D, const CDCRLWireHit*>;
97 std::vector<CDCRecoHitWithRLPointer> recoHits;
98 recoHits.reserve(rlWireHits.size() + track.size());
99
100 /*
101 * Use the given trajectory to reconstruct the 2d hits in the vector in z direction
102 * to match the trajectory perfectly. Then add the newly created reconstructed 3D hit to the given list.
103 */
104 for (const CDCRLWireHit& rlWireHit : rlWireHits) {
105 if (rlWireHit.getWireHit().getAutomatonCell().hasTakenFlag()) continue;
106
107 const CDCWire& wire = rlWireHit.getWire();
108 const WireLine& wireLine = wire.getWireLine();
109 double signedDriftLength = rlWireHit.getSignedRefDriftLength();
110 // Equivalent to trajectory2D.reconstructBoth3D(wireLine, signedDriftLength), but the z bounds check,
111 // which only depends on the z solution, is done before the costly calculation of the xy position.
112 for (const double recoZ : trajectory2D.reconstructBothZ(wireLine, signedDriftLength)) {
113 // Skip hits out of CDC
114 if (not wire.isInCellZBounds(Vector3D(0.0, 0.0, recoZ), m_param_checkForInWireBoundsFactor)) {
115 continue;
116 }
117 const Vector3D recoWirePos3D = wireLine.sagPos3DAtZ(recoZ);
118 const Vector3D recoPos3D(trajectory2D.getClosest(recoWirePos3D.xy()), recoWirePos3D.z());
119
120 // If the track is a curler, shift all perpS values to positive ones.
121 // Else do not use this hit if m_param_checkForB2BTracks is enabled.
122 double perpS = trajectory2D.calcArcLength2D(recoPos3D.xy());
123 if (perpS < 0) {
124 if (isCurler) {
125 perpS += trajectory2D.getArcLength2DPeriod();
126 } else if (m_param_checkForB2BTracks) {
127 continue;
128 }
129 }
130 recoHits.emplace_back(CDCRecoHit3D(rlWireHit, recoPos3D, perpS), &rlWireHit);
131 }
132 }
133
134 // Also add already found stereo hits of the track
135 for (const CDCRecoHit3D& recoHit : track) {
136 if (not recoHit.isAxial()) {
137 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
138 const CDCRLWireHit& rlWireHit = recoHit.getRLWireHit();
139 recoHits.emplace_back(recoHit, &rlWireHit);
140 }
141 }
142
143 // Do the tree finding
144 m_quadTreeInstance.seed(recoHits);
145
148 }
149
150 const auto& foundStereoHitsWithNode = m_quadTreeInstance.findSingleBest(m_param_minimumNumberOfHits);
151 m_quadTreeInstance.fell();
152
153 if (foundStereoHitsWithNode.size() != 1) {
154 return;
155 }
156
157 // There is the possibility that we have added one cdc hits twice (as left and right one). We search for those cases here:
158 auto foundStereoHits = foundStereoHitsWithNode[0].second;
159 const auto& node = foundStereoHitsWithNode[0].first;
160
162 std::vector<CDCRecoHit3D> allHits;
163 std::vector<CDCRecoHit3D> foundHits;
164 // Turn vector of pairs into vector of first items
165 for (const CDCRecoHitWithRLPointer& recoHitWithRL : recoHits) {
166 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
167 allHits.push_back(recoHit3D);
168 }
169 for (const CDCRecoHitWithRLPointer& recoHitWithRL : foundStereoHits) {
170 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
171 foundHits.push_back(recoHit3D);
172 }
173 m_quadTreeInstance.drawDebugPlot(allHits, foundHits, node);
174 }
175
176 // Remove all assigned hits, which where already found before (and do not need to be added again)
177 const auto& isAssignedHit = [](const CDCRecoHitWithRLPointer & recoHitWithRLPointer) {
178 const CDCRecoHit3D& recoHit3D = recoHitWithRLPointer.first;
179 const auto& automatonCell = recoHit3D.getWireHit().getAutomatonCell();
180 return automatonCell.hasAssignedFlag();
181 };
182
183 foundStereoHits.erase(std::remove_if(foundStereoHits.begin(),
184 foundStereoHits.end(),
185 isAssignedHit),
186 foundStereoHits.end());
187
188 // Sort the found stereo hits by same CDCHit and smaller distance to the node
189 auto sortByHitAndNodeCenterDistance = [node](const CDCRecoHitWithRLPointer & lhs,
190 const CDCRecoHitWithRLPointer & rhs) {
191
192
193 const CDCRecoHit3D& rhsRecoHit = rhs.first;
194 const CDCRecoHit3D& lhsRecoHit = lhs.first;
195
196 const CDCWireHit& rhsWireHit = rhsRecoHit.getWireHit();
197 const CDCWireHit& lhsWireHit = lhsRecoHit.getWireHit();
198
199 if (lhsWireHit < rhsWireHit) {
200 return true;
201 } else if (rhsWireHit < lhsWireHit) {
202 return false;
203 } else {
204 return AQuadTree::DecisionAlgorithm::BoxAlgorithm::compareDistances(node, lhsRecoHit, rhsRecoHit); //returns true if lhs < rhs
205 }
206 };
207
208 const auto& sameHitComparer = [](const CDCRecoHitWithRLPointer & lhs,
209 const CDCRecoHitWithRLPointer & rhs) {
210 const CDCRecoHit3D& rhsRecoHit = rhs.first;
211 const CDCRecoHit3D& lhsRecoHit = lhs.first;
212
213 return lhsRecoHit.getWireHit() == rhsRecoHit.getWireHit();
214 };
215
216 std::sort(foundStereoHits.begin(),
217 foundStereoHits.end(),
218 sortByHitAndNodeCenterDistance);
219
220 // If the same hit is added as right and left hypothesis, do only use the one with the smaller distance to the node.
221 foundStereoHits.erase(std::unique(foundStereoHits.begin(),
222 foundStereoHits.end(),
223 sameHitComparer),
224 foundStereoHits.end());
225
226 // Add the found stereo hits to the relation vector. In the moment, all hits get the same weight (may change later).
227 for (const CDCRecoHitWithRLPointer& recoHitWithRLPointer : foundStereoHits) {
228 const CDCRLWireHit* rlWireHit = recoHitWithRLPointer.second;
229 relationsForCollector.emplace_back(&track, foundStereoHits.size(), rlWireHit);
230 }
231}
232
233template <class AQuadTree>
235{
236 std::string outputFileName = "quadTreeContent_call_" + std::to_string(m_numberOfPassedDebugCalls) + ".root";
237 m_quadTreeInstance.writeDebugInfoToFile(outputFileName);
238
240}
241
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:39
Particle trajectory as it is seen in xy projection represented as a circle.
double calcArcLength2D(const Vector2D &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.
Vector2D getClosest(const Vector2D &point) const
Calculates the closest approach on the trajectory to the given point.
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:58
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
Definition CDCWireHit.h:289
const Vector2D & xy() const
Getter for the xy projected vector ( reference ! )
Definition Vector3D.h:509
double z() const
Getter for the z coordinate.
Definition Vector3D.h:497
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
HepGeom::Vector3D< double > Vector3D
3D Vector
Definition Cell.h:34
Abstract base class for different kinds of events.