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/trackFindingCDC/eventdata/tracks/CDCTrack.h>
15
16#include <tracking/trackFindingCDC/eventdata/hits/CDCRLWireHit.h>
17#include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
18#include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
19
20#include <tracking/trackFindingCDC/ca/AutomatonCell.h>
21
22#include <framework/core/ModuleParamList.templateDetails.h>
23
24#include <tracking/trackFindingCDC/utilities/StringManipulation.h>
25
26#include <utility>
27
28using namespace Belle2;
29using namespace TrackFindingCDC;
30
31template <class AQuadTree>
33 const std::string& prefix)
34{
35 Super::exposeParameters(moduleParamList, prefix);
36
37 moduleParamList->addParameter(prefixed(prefix, "level"), m_param_quadTreeLevel,
38 "The number of levels for the quad tree search.",
39 m_param_quadTreeLevel);
40
41 moduleParamList->addParameter(prefixed(prefix, "minimumNumberOfHits"), m_param_minimumNumberOfHits,
42 "The minimum number of hits in a quad tree bin to be called as result.",
43 m_param_minimumNumberOfHits);
44
45 moduleParamList->addParameter(prefixed(prefix, "writeDebugInformation"), m_param_writeDebugInformation,
46 "Set to true to output debug information.",
47 m_param_writeDebugInformation);
48
49 moduleParamList->addParameter(prefixed(prefix, "checkForB2BTracks"),
50 m_param_checkForB2BTracks,
51 "Set to false to skip the check for back-2-back tracks "
52 "(good for cosmics).",
53 m_param_checkForB2BTracks);
54
55 moduleParamList->addParameter(prefixed(prefix, "checkForInWireBoundsFactor"),
56 m_param_checkForInWireBoundsFactor,
57 "Used to scale the CDC before checking "
58 "whether hits are in the CDC z bounds.",
59 m_param_checkForInWireBoundsFactor);
60}
61
62
63template <class AQuadTree>
65{
66 Super::initialize();
67
68 m_quadTreeInstance.setMaxLevel(m_param_quadTreeLevel);
69 m_quadTreeInstance.initialize();
70}
71
72
73template <class AQuadTree>
75{
76 Super::terminate();
77
78 m_quadTreeInstance.raze();
79}
80
81template <class AQuadTree>
82void StereoHitTrackQuadTreeMatcher<AQuadTree>::match(CDCTrack& track, const std::vector<CDCRLWireHit>& rlWireHits,
83 std::vector<Super::WeightedRelationItem>& relationsForCollector)
84{
85 // TODO: Extract this into smaller steps
86 // TODO: Split the filtering from the rest.
87 // This means this method would output WeightedRelations based on the quad tree decision and a second filter step
88 // can be applied on these weighted relations
89
90 // Reconstruct the hits to the track
91 const CDCTrajectory2D& trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
92 const bool isCurler = trajectory2D.isCurler();
93
94 using CDCRecoHitWithRLPointer = std::pair<CDCRecoHit3D, const CDCRLWireHit*>;
95 std::vector<CDCRecoHitWithRLPointer> recoHits;
96 recoHits.reserve(rlWireHits.size() + track.size());
97
98 /*
99 * Use the given trajectory to reconstruct the 2d hits in the vector in z direction
100 * to match the trajectory perfectly. Then add the newly created reconstructed 3D hit to the given list.
101 */
102 for (const CDCRLWireHit& rlWireHit : rlWireHits) {
103 if (rlWireHit.getWireHit().getAutomatonCell().hasTakenFlag()) continue;
104
105 const CDCWire& wire = rlWireHit.getWire();
106 const WireLine& wireLine = wire.getWireLine();
107 double signedDriftLength = rlWireHit.getSignedRefDriftLength();
108 for (const Vector3D& recoPos3D : trajectory2D.reconstructBoth3D(wireLine, signedDriftLength)) {
109 // Skip hits out of CDC
110 if (not wire.isInCellZBounds(recoPos3D, m_param_checkForInWireBoundsFactor)) {
111 continue;
112 }
113
114 // If the track is a curler, shift all perpS values to positive ones.
115 // Else do not use this hit if m_param_checkForB2BTracks is enabled.
116 double perpS = trajectory2D.calcArcLength2D(recoPos3D.xy());
117 if (perpS < 0) {
118 if (isCurler) {
119 perpS += trajectory2D.getArcLength2DPeriod();
120 } else if (m_param_checkForB2BTracks) {
121 continue;
122 }
123 }
124 recoHits.emplace_back(CDCRecoHit3D(rlWireHit, recoPos3D, perpS), &rlWireHit);
125 }
126 }
127
128 // Also add already found stereo hits of the track
129 for (const CDCRecoHit3D& recoHit : track) {
130 if (not recoHit.isAxial()) {
131 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
132 const CDCRLWireHit& rlWireHit = recoHit.getRLWireHit();
133 recoHits.emplace_back(recoHit, &rlWireHit);
134 }
135 }
136
137 // Do the tree finding
138 m_quadTreeInstance.seed(recoHits);
139
140 if (m_param_writeDebugInformation) {
141 writeDebugInformation();
142 }
143
144 const auto& foundStereoHitsWithNode = m_quadTreeInstance.findSingleBest(m_param_minimumNumberOfHits);
145 m_quadTreeInstance.fell();
146
147 if (foundStereoHitsWithNode.size() != 1) {
148 return;
149 }
150
151 // There is the possibility that we have added one cdc hits twice (as left and right one). We search for those cases here:
152 auto foundStereoHits = foundStereoHitsWithNode[0].second;
153 const auto& node = foundStereoHitsWithNode[0].first;
154
155 if (m_param_writeDebugInformation) {
156 std::vector<CDCRecoHit3D> allHits;
157 std::vector<CDCRecoHit3D> foundHits;
158 // Turn vector of pairs into vector of first items
159 for (const CDCRecoHitWithRLPointer& recoHitWithRL : recoHits) {
160 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
161 allHits.push_back(recoHit3D);
162 }
163 for (const CDCRecoHitWithRLPointer& recoHitWithRL : foundStereoHits) {
164 const CDCRecoHit3D& recoHit3D = recoHitWithRL.first;
165 foundHits.push_back(recoHit3D);
166 }
167 m_quadTreeInstance.drawDebugPlot(allHits, foundHits, node);
168 }
169
170 // Remove all assigned hits, which where already found before (and do not need to be added again)
171 const auto& isAssignedHit = [](const CDCRecoHitWithRLPointer & recoHitWithRLPointer) {
172 const CDCRecoHit3D& recoHit3D = recoHitWithRLPointer.first;
173 const auto& automatonCell = recoHit3D.getWireHit().getAutomatonCell();
174 return automatonCell.hasAssignedFlag();
175 };
176
177 foundStereoHits.erase(std::remove_if(foundStereoHits.begin(),
178 foundStereoHits.end(),
179 isAssignedHit),
180 foundStereoHits.end());
181
182 // Sort the found stereo hits by same CDCHit and smaller distance to the node
183 auto sortByHitAndNodeCenterDistance = [node](const CDCRecoHitWithRLPointer & lhs,
184 const CDCRecoHitWithRLPointer & rhs) {
185
186
187 const CDCRecoHit3D& rhsRecoHit = rhs.first;
188 const CDCRecoHit3D& lhsRecoHit = lhs.first;
189
190 const CDCWireHit& rhsWireHit = rhsRecoHit.getWireHit();
191 const CDCWireHit& lhsWireHit = lhsRecoHit.getWireHit();
192
193 if (lhsWireHit < rhsWireHit) {
194 return true;
195 } else if (rhsWireHit < lhsWireHit) {
196 return false;
197 } else {
198 return AQuadTree::DecisionAlgorithm::BoxAlgorithm::compareDistances(node, lhsRecoHit, rhsRecoHit); //returns true if lhs < rhs
199 }
200 };
201
202 const auto& sameHitComparer = [](const CDCRecoHitWithRLPointer & lhs,
203 const CDCRecoHitWithRLPointer & rhs) {
204 const CDCRecoHit3D& rhsRecoHit = rhs.first;
205 const CDCRecoHit3D& lhsRecoHit = lhs.first;
206
207 return lhsRecoHit.getWireHit() == rhsRecoHit.getWireHit();
208 };
209
210 std::sort(foundStereoHits.begin(),
211 foundStereoHits.end(),
212 sortByHitAndNodeCenterDistance);
213
214 // If the same hit is added as right and left hypothesis, do only use the one with the smaller distance to the node.
215 foundStereoHits.erase(std::unique(foundStereoHits.begin(),
216 foundStereoHits.end(),
217 sameHitComparer),
218 foundStereoHits.end());
219
220 // Add the found stereo hits to the relation vector. In the moment, all hits get the same weight (may change later).
221 for (const CDCRecoHitWithRLPointer& recoHitWithRLPointer : foundStereoHits) {
222 const CDCRLWireHit* rlWireHit = recoHitWithRLPointer.second;
223 relationsForCollector.emplace_back(&track, foundStereoHits.size(), rlWireHit);
224 }
225}
226
227template <class AQuadTree>
229{
230 std::string outputFileName = "quadTreeContent_call_" + std::to_string(m_numberOfPassedDebugCalls) + ".root";
231 m_quadTreeInstance.writeDebugInfoToFile(outputFileName);
232
233 m_numberOfPassedDebugCalls++;
234}
235
The Module parameter list class.
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 ...
Definition: CDCRLWireHit.h:41
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
const CDCWireHit & getWireHit() const
Getter for the wire hit.
Definition: CDCRecoHit3D.h:238
Class representing a sequence of three dimensional reconstructed hits.
Definition: CDCTrack.h:41
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.
std::array< Vector3D, 2 > reconstructBoth3D(const WireLine &wireLine, double distance=0.0, double z=0) const
Gives the two three dimensional points where the drift circle touches the wire line.
double getArcLength2DPeriod() const
Getter for the arc length for one round trip around the trajectory.
Class representing a hit wire in the central drift chamber.
Definition: CDCWireHit.h:55
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
Definition: CDCWireHit.h:286
Class representing a sense wire in the central drift chamber.
Definition: CDCWire.h:58
bool isInCellZBounds(const Vector3D &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:295
const WireLine & getWireLine() const
Getter for the wire line representation of the wire.
Definition: CDCWire.h:188
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.
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.
void match(CDCTrack &track, const std::vector< 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...
A three dimensional vector.
Definition: Vector3D.h:33
A three dimensional limited line represented by its closest approach to the z-axes (reference positio...
Definition: WireLine.h:31
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.