Belle II Software  release-08-01-10
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 
19 using namespace Belle2;
20 using 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 
34 void 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 
125 void 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 
205 void 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 
271 void 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 
349 void 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 cirlce 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 handeling of orientation relat...
Definition: Vector2D.h:35
A three dimensional vector.
Definition: Vector3D.h:33
Abstract base class for different kinds of events.