Belle II Software development
TrackQualityTools.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/processing/TrackQualityTools.h>
9#include <tracking/trackFindingCDC/eventdata/tracks/CDCTrack.h>
10#include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
11#include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory3D.h>
12#include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
13
14#include <tracking/trackFindingCDC/topology/CDCWire.h>
15#include <tracking/trackFindingCDC/utilities/ReversedRange.h>
16
17#include <Math/VectorUtil.h>
18
19using namespace Belle2;
20using namespace TrackFindingCDC;
21
22
24{
25 for (const CDCRecoHit3D& recoHit : track) {
26 if (recoHit.getStereoKind() == EStereoKind::c_Axial) {
27 break;
28 } else {
29 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
30 }
31 }
32}
33
34void TrackQualityTools::splitSecondHalfOfTrack(CDCTrack& track, std::vector<CDCTrack>& tracks)
35{
36 const CDCTrajectory3D& trajectory3D = track.getStartTrajectory3D();
37 const CDCTrajectory2D& trajectory2D = trajectory3D.getTrajectory2D();
38 const double radius = trajectory2D.getLocalCircle()->absRadius();
39 const Vector2D& apogee = trajectory2D.getGlobalCircle().apogee();
40 double arcLength2DOfApogee = trajectory2D.calcArcLength2D(apogee);
41 if (arcLength2DOfApogee < 0) {
42 arcLength2DOfApogee += 2 * TMath::Pi() * radius;
43 }
44
45 CDCTrack splittedCDCTrack;
46 splittedCDCTrack.setStartTrajectory3D(trajectory3D);
47
48 for (CDCRecoHit3D& recoHit : track) {
49 double currentArcLength2D = recoHit.getArcLength2D();
50 if (currentArcLength2D < 0) B2INFO("Below 0");
51 if (currentArcLength2D > arcLength2DOfApogee) {
52 splittedCDCTrack.push_back(recoHit);
53 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
54 }
55 }
56
57 if (splittedCDCTrack.size() > 0) {
58 tracks.push_back(splittedCDCTrack);
59 }
60}
61
63{
64 if (track.empty()) return;
65
66 CDCTrajectory3D trajectory3D = track.getStartTrajectory3D();
67
68 // We reset the trajectory here to start (later) at the newStartPosition of the first hit
69 const Vector3D startPosition(0, 0, 0);
70 trajectory3D.setLocalOrigin(startPosition);
71 trajectory3D.setFlightTime(0);
72
73 CDCTrajectory2D trajectory2D = trajectory3D.getTrajectory2D();
74
75 // Check if we have to reverse the trajectory. This is done by counting the number of hits
76 // with positive and with negative arc length
77 unsigned int numberOfPositiveHits = 0;
78 for (const CDCRecoHit3D& recoHit : track) {
79 const double currentArcLength = trajectory2D.calcArcLength2D(recoHit.getRecoPos2D());
80 if (currentArcLength > 0) {
81 numberOfPositiveHits++;
82 }
83 }
84 const bool reverseTrajectory = 2 * numberOfPositiveHits < track.size();
85
86 if (reverseTrajectory) {
87 trajectory3D.reverse();
88 trajectory2D.reverse();
89 }
90
91 double arcLength2DPeriod = trajectory2D.getArcLength2DPeriod();
92 for (CDCRecoHit3D& recoHit : track) {
93 Vector2D recoPos2D = recoHit.getRLWireHit().reconstruct3D(trajectory2D).xy();
94 double arcLength2D = trajectory2D.calcArcLength2D(recoPos2D);
95
96 if (arcLength2D < 0) {
97 arcLength2D += arcLength2DPeriod;
98 }
99 recoHit.setArcLength2D(arcLength2D);
100 recoHit.getWireHit().getAutomatonCell().unsetAssignedFlag();
101 recoHit.getWireHit().getAutomatonCell().setTakenFlag();
102 }
103
104 // We can now sort by arc length
105 track.sortByArcLength2D();
106
107 // Set the position to the first hit and let the hits start at arc length of 0
108 Vector3D frontPosition = track.front().getRLWireHit().reconstruct3D(trajectory2D);
109 double arcLengthOffset = trajectory3D.setLocalOrigin(frontPosition);
110 track.setStartTrajectory3D(trajectory3D);
111 for (CDCRecoHit3D& recoHit : track) {
112 recoHit.shiftArcLength2D(-arcLengthOffset);
113 }
114
115 // Set the back trajectory to start at the last hit position (and shift if necessary)
116 Vector3D backPosition = track.back().getRLWireHit().reconstruct3D(trajectory2D);
117 double backArcLength2D = trajectory3D.setLocalOrigin(backPosition);
118 if (backArcLength2D < 0) {
119 trajectory3D.shiftPeriod(1);
120 }
121 track.setEndTrajectory3D(trajectory3D);
122
123}
124
125void TrackQualityTools::removeHitsAfterCDCWall(CDCTrack& track, double outerCylindricalRFactor)
126{
127 const CDCTrajectory2D& trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
128 const double radius = trajectory2D.getLocalCircle()->absRadius();
129
130 // Curler are allowed to have hits on both arms
131 if (trajectory2D.isCurler(outerCylindricalRFactor)) {
132 return;
133 }
134
135 const Vector2D& outerExitWithFactor = trajectory2D.getOuterExit(outerCylindricalRFactor);
136
137 double arcLength2DOfExitWithFactor = trajectory2D.calcArcLength2D(outerExitWithFactor);
138 if (arcLength2DOfExitWithFactor < 0) {
139 arcLength2DOfExitWithFactor += 2 * TMath::Pi() * radius;
140 }
141 bool removeAfterThis = false;
142
143 for (const CDCRecoHit3D& recoHit : track) {
144 if (removeAfterThis) {
145 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
146 continue;
147 }
148
149 double currentArcLength2D = recoHit.getArcLength2D();
150 if (currentArcLength2D < 0) {
151 currentArcLength2D += 2 * TMath::Pi() * radius;
152 }
153
154 if (currentArcLength2D > arcLength2DOfExitWithFactor) {
155 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
156 removeAfterThis = true;
157 }
158 }
159}
160
162{
163 ILayer lastLayer = -1;
164 Vector2D lastWirePosition;
165
166 std::vector<std::vector<const CDCRecoHit3D*>> trackletList;
167 trackletList.reserve(3);
168
169 std::vector<const CDCRecoHit3D*>* currentTracklet = nullptr;
170
171 for (const CDCRecoHit3D& recoHit : track) {
172 if (currentTracklet == nullptr) {
173 trackletList.emplace_back();
174 currentTracklet = &(trackletList.back());
175 }
176
177 const ILayer currentLayer = recoHit.getWire().getICLayer();
178 const Vector2D& currentPosition = recoHit.getRecoPos2D();
179 if (lastLayer != -1) {
180 const ILayer delta = currentLayer - lastLayer;
181 const double distance = (currentPosition - lastWirePosition).norm();
182 if (abs(delta) > 4 or distance > 50) {
183 trackletList.emplace_back();
184 currentTracklet = &(trackletList.back());
185 }
186 }
187
188 lastWirePosition = currentPosition;
189 lastLayer = currentLayer;
190
191 currentTracklet->push_back(&recoHit);
192 }
193
194 if (trackletList.size() > 1) {
195 for (const std::vector<const CDCRecoHit3D*>& tracklet : trackletList) {
196 if (tracklet.size() < 5) {
197 for (const CDCRecoHit3D* recoHit : tracklet) {
198 recoHit->getWireHit().getAutomatonCell().setAssignedFlag();
199 }
200 }
201 }
202 }
203}
204
205void TrackQualityTools::removeHitsAfterLayerBreak(CDCTrack& track, double m_maximumArcLength2DDistance)
206{
207 const CDCTrajectory3D& trajectory3D = track.getStartTrajectory3D();
208 const CDCTrajectory2D& trajectory2D = trajectory3D.getTrajectory2D();
209 const double radius = trajectory2D.getLocalCircle()->absRadius();
210
211 if (std::isnan(radius)) {
212 return;
213 }
214
215 std::vector<std::vector<const CDCRecoHit3D*>> trackletList;
216
217 double lastArcLength2D = NAN;
218
219 std::vector<const CDCRecoHit3D*>* currentTracklet = nullptr;
220
221 for (const CDCRecoHit3D& recoHit : track) {
222 if (currentTracklet == nullptr) {
223 trackletList.emplace_back();
224 currentTracklet = &(trackletList.back());
225 }
226
227 const double currentArcLength2D = recoHit.getArcLength2D();
228 if (not std::isnan(lastArcLength2D)) {
229 const double delta = (currentArcLength2D - lastArcLength2D);
230 if (std::fabs(delta) > m_maximumArcLength2DDistance) {
231 trackletList.emplace_back();
232 currentTracklet = &(trackletList.back());
233 }
234 }
235
236 lastArcLength2D = currentArcLength2D;
237
238 currentTracklet->push_back(&recoHit);
239 }
240
241 if (trackletList.size() > 1) {
242 // Throw away the ends if they are too small
243 while (trackletList.size() > 0) {
244 if (trackletList.back().size() > 4) {
245 break;
246 }
247
248 for (const CDCRecoHit3D* recoHit : trackletList.back()) {
249 recoHit->getWireHit().getAutomatonCell().setAssignedFlag();
250 }
251
252 trackletList.pop_back();
253 }
254
255 std::reverse(trackletList.begin(), trackletList.end());
256
257 while (trackletList.size() > 0) {
258 if (trackletList.back().size() > 4) {
259 break;
260 }
261
262 for (const CDCRecoHit3D* recoHit : trackletList.back()) {
263 recoHit->getWireHit().getAutomatonCell().setAssignedFlag();
264 }
265
266 trackletList.pop_back();
267 }
268 }
269}
270
271void TrackQualityTools::removeHitsIfSmall(CDCTrack& track, unsigned int minimalHits)
272{
273 const bool deleteTrack = track.size() < minimalHits;
274
275 if (deleteTrack) {
276 for (const CDCRecoHit3D& recoHit : track) {
277 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
278 }
279 }
280}
281
283{
284 double lastAngle = NAN;
285 bool removeAfterThis = false;
286
287 for (const CDCRecoHit3D& recoHit : reversedRange(track)) {
288 if (removeAfterThis) {
289 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
290 continue;
291 }
292
293 const double currentAngle = recoHit.getRecoPos2D().phi();
294 if (not std::isnan(lastAngle)) {
295 const double delta = currentAngle - lastAngle;
296 const double normalizedDelta =
297 std::min(
298 ROOT::Math::VectorUtil::Phi_0_2pi(delta),
299 ROOT::Math::VectorUtil::Phi_0_2pi(-delta));
300 if (fabs(normalizedDelta) > maximalAngle) {
301 removeAfterThis = true;
302 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
303 }
304 }
305
306 lastAngle = currentAngle;
307 }
308}
309
310
312{
313 ISuperLayer lastLayer = -1;
314 bool deleteTrack = true;
315
316 for (const CDCRecoHit3D& recoHit : track) {
317 const ISuperLayer currentLayer = recoHit.getISuperLayer();
318 if (lastLayer != -1 and lastLayer != currentLayer) {
319 deleteTrack = false;
320 break;
321 }
322
323 lastLayer = currentLayer;
324 }
325
326 if (deleteTrack) {
327 for (const CDCRecoHit3D& recoHit : track) {
328 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
329 }
330 }
331}
332
334{
335 const CDCTrajectory3D& trajectory3D = track.getStartTrajectory3D();
336 const CDCTrajectory2D& trajectory2D = trajectory3D.getTrajectory2D();
337
338 // Curler are allowed to have negative arc lengths
339 if (trajectory2D.isCurler()) {
340 return;
341 }
342 for (const CDCRecoHit3D& recoHit : track) {
343 if (trajectory2D.calcArcLength2D(recoHit.getRecoPos2D()) < 0) {
344 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
345 }
346 }
347}
348
349void TrackQualityTools::removeArcLength2DHoles(CDCTrack& track, double m_maximumArcLength2DDistance)
350{
351 const CDCTrajectory3D& trajectory3D = track.getStartTrajectory3D();
352 const CDCTrajectory2D& trajectory2D = trajectory3D.getTrajectory2D();
353 const double radius = trajectory2D.getLocalCircle()->absRadius();
354
355 if (std::isnan(radius)) {
356 return;
357 }
358
359 double lastArcLength2D = NAN;
360 bool removeAfterThis = false;
361
362 for (const CDCRecoHit3D& recoHit : track) {
363 if (removeAfterThis) {
364 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
365 continue;
366 }
367
368 const double currentArcLength2D = recoHit.getArcLength2D();
369 if (not std::isnan(lastArcLength2D)) {
370 const double delta = (currentArcLength2D - lastArcLength2D) / radius;
371 if (fabs(delta) > m_maximumArcLength2DDistance) {
372 removeAfterThis = true;
373 recoHit.getWireHit().getAutomatonCell().setAssignedFlag();
374 continue;
375 }
376 }
377
378 lastArcLength2D = currentArcLength2D;
379 }
380}
void setAssignedFlag(bool setTo=true)
Sets the already assigned marker flag to the given value. Default value true.
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
Class representing a sequence of three dimensional reconstructed hits.
Definition: CDCTrack.h:41
void setStartTrajectory3D(const CDCTrajectory3D &startTrajectory3D)
Setter for the two dimensional trajectory.
Definition: CDCTrack.h:98
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
Definition: CDCTrack.h:125
Particle trajectory as it is seen in xy projection represented as a circle.
PerigeeCircle getGlobalCircle() const
Getter for the circle in global coordinates.
Vector2D getOuterExit(double factor=1) const
Calculates the point where the trajectory meets the outer wall of the CDC.
void reverse()
Reverses the trajectory in place.
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.
const UncertainPerigeeCircle & getLocalCircle() const
Getter for the circle in local coordinates.
Particle full three dimensional trajectory.
void reverse()
Reverses the trajectory in place.
CDCTrajectory2D getTrajectory2D() const
Getter for the two dimensional trajectory.
double shiftPeriod(int nPeriods)
Adjusts the z0 to the one that lies n periods forward.
double setLocalOrigin(const Vector3D &localOrigin)
Setter for the origin of the local coordinate system.
void setFlightTime(double flightTime)
Setter for the time when the particle reached the support point position.
Vector2D apogee() const
Getter for the apogee of the circle. If it was a line both components will be infinity.
double absRadius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
static void removeArcLength2DHoles(CDCTrack &track, double m_maximumArcLength2DDistance=10)
Remove all hits that come after a large hole in the two dimensional arc length.
static void moveToNextAxialLayer(CDCTrack &track)
Delete hits of the first superlayer if it is a stereo one (fitting does not work very well when start...
static void removeHitsIfOnlyOneSuperLayer(CDCTrack &track)
Remove the whole track if it only consists of one superlayer.
static void normalizeHitsAndResetTrajectory(CDCTrack &track)
Update all hits to have a positive perpS, a taken flag and no background flag Also set the trajectory...
static void removeHitsInTheBeginningIfAngleLarge(CDCTrack &track, double maximalAngle=0.7)
If the angle between two following hits is larger than maximalAngle, delete all hits before (!...
static void removeHitsAfterCDCWall(CDCTrack &track, double outerCylindricalRFactor=1.1)
Remove all hits which can not belong to the track, as the particle can not exit and enter the CDC aga...
static void removeHitsIfSmall(CDCTrack &track, unsigned int minimalHits=7)
Delete a track fully of the number of hits is below minimalHits.
static void removeHitsOnTheWrongSide(CDCTrack &track)
Remove all hits that are on the wrong side of the detector (so to say: "beyond the IP").
static void splitSecondHalfOfTrack(CDCTrack &track, std::vector< CDCTrack > &tracks)
Trasan did output curlers in split two halves - this method can be used to mimic this.
static void removeHitsAfterLayerBreak(CDCTrack &track, double m_maximumArcLength2DDistance=10)
Delete all hits after a large layer break.
static void removeHitsAfterLayerBreak2(CDCTrack &track)
Delete all hits after a large layer break.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition: Vector2D.h:32
A three dimensional vector.
Definition: Vector3D.h:33
Abstract base class for different kinds of events.