Belle II Software  release-08-01-10
CDCTrack.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/eventdata/tracks/CDCTrack.h>
9 
10 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentTriple.h>
11 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentPair.h>
12 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment3D.h>
13 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment2D.h>
14 
15 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit3D.h>
16 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit2D.h>
17 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
18 
19 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory3D.h>
20 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
21 
22 #include <tracking/trackFindingCDC/topology/ISuperLayer.h>
23 
24 #include <tracking/trackFindingCDC/geometry/PerigeeCircle.h>
25 #include <tracking/trackFindingCDC/geometry/UncertainPerigeeCircle.h>
26 #include <tracking/trackFindingCDC/geometry/Vector3D.h>
27 
28 #include <tracking/trackFindingCDC/ca/AutomatonCell.h>
29 
30 #include <tracking/trackFindingCDC/numerics/FloatComparing.h>
31 
32 #include <tracking/trackFindingCDC/utilities/MayBePtr.h>
33 
34 #include <framework/logging/Logger.h>
35 
36 #include <algorithm>
37 #include <utility>
38 #include <cmath>
39 
40 namespace Belle2 {
45  namespace TrackFindingCDC {
46  class CDCRLWireHit;
47  }
49 }
50 
51 using namespace Belle2;
52 using namespace TrackFindingCDC;
53 
54 namespace {
56  void appendReconstructed(const CDCSegment2D* segment,
57  const CDCTrajectory3D& trajectory3D,
58  double perpSOffset,
59  CDCTrack& track)
60  {
61  B2ASSERT("Did not expect segment == nullptr", segment);
62 
63  for (const CDCRecoHit2D& recohit2D : *segment) {
64  track.push_back(CDCRecoHit3D::reconstruct(recohit2D,
65  trajectory3D));
66  track.back().shiftArcLength2D(perpSOffset);
67  }
68  }
69 
70 
83  double appendReconstructedAverage(const CDCSegment2D* segment,
84  const CDCTrajectory3D& trajectory3D,
85  double perpSOffset,
86  const CDCTrajectory3D& parallelTrajectory3D,
87  CDCTrack& track)
88  {
89  B2ASSERT("Did not expect segment == nullptr", segment);
90 
91  const CDCRecoHit2D& firstRecoHit2D = segment->front();
92 
93  CDCRecoHit3D firstRecoHit3D =
94  CDCRecoHit3D::reconstruct(firstRecoHit2D, trajectory3D);
95 
96  double firstPerpS = firstRecoHit3D.getArcLength2D();
97 
98  CDCRecoHit3D parallelFirstRecoHit3D =
99  CDCRecoHit3D::reconstruct(firstRecoHit2D, parallelTrajectory3D);
100 
101  double parallelFirstPerpS = parallelFirstRecoHit3D.getArcLength2D();
102 
103  double parallelPerpSOffSet = firstPerpS + perpSOffset - parallelFirstPerpS;
104 
105  for (const CDCRecoHit2D& recoHit2D : *segment) {
106 
107  CDCRecoHit3D recoHit3D =
108  CDCRecoHit3D::reconstruct(recoHit2D, trajectory3D);
109 
110  recoHit3D.shiftArcLength2D(perpSOffset);
111 
112 
113  CDCRecoHit3D parallelRecoHit3D =
114  CDCRecoHit3D::reconstruct(recoHit2D, parallelTrajectory3D);
115 
116  parallelRecoHit3D.shiftArcLength2D(parallelPerpSOffSet);
117 
118  track.push_back(CDCRecoHit3D::average(recoHit3D, parallelRecoHit3D));
119 
120  }
121 
122  const CDCRecoHit2D& lastRecoHit2D = segment->back() ;
123 
124  CDCRecoHit3D parallelLastRecoHit3D =
125  CDCRecoHit3D::reconstruct(lastRecoHit2D, parallelTrajectory3D);
126 
127  double newPrepSOffset = track.back().getArcLength2D() - parallelLastRecoHit3D.getArcLength2D();
128 
129  return newPrepSOffset;
130  }
131 }
132 
133 CDCTrack::CDCTrack(const std::vector<CDCRecoHit3D>& recoHits3D)
134  : std::vector<CDCRecoHit3D>(recoHits3D)
135 {
136 }
137 
139  m_startTrajectory3D(segment.getTrajectory2D()),
140  m_endTrajectory3D(segment.getTrajectory2D())
141 {
142  if (segment.empty()) return;
143 
144  // Adjust the start point
145  const CDCRecoHit2D& startRecoHit2D = segment.front();
146  const CDCRecoHit2D& endRecoHit2D = segment.back();
147 
148  Vector3D startPos3D(startRecoHit2D.getRecoPos2D(), 0.0);
149  Vector3D endPos3D(endRecoHit2D.getRecoPos2D(), 0.0);
150 
153 
154  for (const CDCRecoHit2D& recoHit2D : segment) {
155  const CDCRLWireHit& rlWireHit = recoHit2D.getRLWireHit();
156  Vector3D recoPos3D(recoHit2D.getRecoPos2D(), 0.0);
157  double perpS = m_startTrajectory3D.calcArcLength2D(recoPos3D);
158  push_back(CDCRecoHit3D(rlWireHit, recoPos3D, perpS));
159  }
160 
161  // TODO: Maybe enhance the estimation of the z coordinate with the superlayer slopes.
162 }
163 
164 CDCTrack CDCTrack::condense(const Path<const CDCTrack>& trackPath)
165 {
166  if (trackPath.empty()) {
167  return CDCTrack();
168  } else if (trackPath.size() == 1) {
169  return CDCTrack(*(trackPath[0]));
170  } else {
171  CDCTrack result;
172  for (const CDCTrack* track : trackPath) {
173  for (const CDCRecoHit3D& recoHit3D : *track) {
174  result.push_back(recoHit3D);
176  }
177  }
178 
179  CDCTrajectory3D startTrajectory3D = trackPath.front()->getStartTrajectory3D();
180  CDCTrajectory3D endTrajectory3D = trackPath.back()->getStartTrajectory3D();
181 
182  double resetPerpSOffset =
183  startTrajectory3D.setLocalOrigin(result.front().getRecoPos3D());
184  result.setStartTrajectory3D(startTrajectory3D);
185 
186  endTrajectory3D.setLocalOrigin(result.back().getRecoPos3D());
187  result.setEndTrajectory3D(endTrajectory3D);
188 
189  for (CDCRecoHit3D& recoHit3D : result) {
190  recoHit3D.shiftArcLength2D(-resetPerpSOffset);
191  }
192 
193  return result;
194  }
195 }
196 
197 CDCTrack CDCTrack::condense(const Path<const CDCSegmentTriple>& segmentTriplePath)
198 {
199  CDCTrack track;
200  // B2DEBUG(200,"Lenght of segmentTripleTrack is " << segmentTripleTrack.size() );
201  if (segmentTriplePath.empty()) return track;
202 
203  Path<const CDCSegmentTriple>::const_iterator itSegmentTriple = segmentTriplePath.begin();
204  const CDCSegmentTriple* firstSegmentTriple = *itSegmentTriple++;
205 
206  // Set the start fits of the track to the ones of the first segment
207  CDCTrajectory3D startTrajectory3D = firstSegmentTriple->getTrajectory3D();
208 
209 
210  double perpSOffset = 0.0;
211  appendReconstructed(firstSegmentTriple->getStartSegment(),
212  firstSegmentTriple->getTrajectory3D(),
213  perpSOffset,
214  track);
215 
216  appendReconstructed(firstSegmentTriple->getMiddleSegment(),
217  firstSegmentTriple->getTrajectory3D(),
218  perpSOffset, track);
219 
220  while (itSegmentTriple != segmentTriplePath.end()) {
221 
222  const CDCSegmentTriple* secondSegmentTriple = *itSegmentTriple++;
223  B2ASSERT("Two segement triples do not overlap in their axial segments",
224  firstSegmentTriple->getEndSegment() == secondSegmentTriple->getStartSegment());
225 
226  perpSOffset = appendReconstructedAverage(firstSegmentTriple->getEndSegment(),
227  firstSegmentTriple->getTrajectory3D(),
228  perpSOffset,
229  secondSegmentTriple->getTrajectory3D(),
230  track);
231 
232  appendReconstructed(secondSegmentTriple->getMiddleSegment(),
233  secondSegmentTriple->getTrajectory3D(),
234  perpSOffset, track);
235 
236  firstSegmentTriple = secondSegmentTriple;
237 
238  }
239 
240  const CDCSegmentTriple* lastSegmentTriple = firstSegmentTriple;
241 
242  appendReconstructed(lastSegmentTriple->getEndSegment(),
243  lastSegmentTriple->getTrajectory3D(),
244  perpSOffset, track);
245 
246  // Set the end fits of the track to the ones of the last segment
247  CDCTrajectory3D endTrajectory3D = lastSegmentTriple->getTrajectory3D();
248 
249  // Set the reference point on the trajectories to the last reconstructed hit
250  double resetPerpSOffset = startTrajectory3D.setLocalOrigin(track.front().getRecoPos3D());
251  track.setStartTrajectory3D(startTrajectory3D);
252 
253  endTrajectory3D.setLocalOrigin(track.back().getRecoPos3D());
254  track.setEndTrajectory3D(endTrajectory3D);
255 
256  for (CDCRecoHit3D& recoHit3D : track) {
257  recoHit3D.shiftArcLength2D(-resetPerpSOffset);
258  }
259 
260  return track;
261 }
262 
263 CDCTrack CDCTrack::condense(const Path<const CDCSegmentPair>& segmentPairPath)
264 {
265  CDCTrack track;
266 
267  //B2DEBUG(200,"Lenght of segmentTripleTrack is " << segmentTripleTrack.size() );
268  if (segmentPairPath.empty()) return track;
269 
270  Path<const CDCSegmentPair>::const_iterator itSegmentPair = segmentPairPath.begin();
271  const CDCSegmentPair* firstSegmentPair = *itSegmentPair++;
272 
273 
274  // Keep the fit of the first segment pair to set it as the fit at the start of the track
275  CDCTrajectory3D startTrajectory3D = firstSegmentPair->getTrajectory3D();
276 
277  double perpSOffset = 0.0;
278  appendReconstructed(firstSegmentPair->getFromSegment(),
279  firstSegmentPair->getTrajectory3D(),
280  perpSOffset, track);
281 
282  while (itSegmentPair != segmentPairPath.end()) {
283 
284  const CDCSegmentPair* secondSegmentPair = *itSegmentPair++;
285 
286  B2ASSERT("Two segement pairs do not overlap in their segments",
287  firstSegmentPair->getToSegment() == secondSegmentPair->getFromSegment());
288 
289  perpSOffset = appendReconstructedAverage(firstSegmentPair->getToSegment(),
290  firstSegmentPair->getTrajectory3D(),
291  perpSOffset,
292  secondSegmentPair->getTrajectory3D(),
293  track);
294 
295  firstSegmentPair = secondSegmentPair;
296  }
297 
298  const CDCSegmentPair* lastSegmentPair = firstSegmentPair;
299  appendReconstructed(lastSegmentPair->getToSegment(),
300  lastSegmentPair->getTrajectory3D(),
301  perpSOffset, track);
302 
303  // Keep the fit of the last segment pair to set it as the fit at the end of the track
304  CDCTrajectory3D endTrajectory3D = lastSegmentPair->getTrajectory3D();
305 
306  // Move the reference point of the start fit to the first observered position
307  double resetPerpSOffset = startTrajectory3D.setLocalOrigin(track.front().getRecoPos3D());
308  track.setStartTrajectory3D(startTrajectory3D);
309 
310  // Move the reference point of the end fit to the last observered position
311  endTrajectory3D.setLocalOrigin(track.back().getRecoPos3D());
312  track.setEndTrajectory3D(endTrajectory3D);
313 
314  for (CDCRecoHit3D& recoHit3D : track) {
315  recoHit3D.shiftArcLength2D(-resetPerpSOffset);
316  }
317 
318  return track;
319 }
320 
321 std::vector<CDCSegment3D> CDCTrack::splitIntoSegments() const
322 {
323  vector<CDCSegment3D> result;
324  ISuperLayer lastISuperLayer = -1;
325  for (const CDCRecoHit3D& recoHit3D : *this) {
326  ISuperLayer iSuperLayer = recoHit3D.getISuperLayer();
327  if (result.empty() or lastISuperLayer != iSuperLayer) {
328  result.emplace_back();
329  }
330  result.back().push_back(recoHit3D);
331  lastISuperLayer = iSuperLayer;
332  }
333  return result;
334 }
335 
337 {
338  if (empty()) return;
339 
340  // Exchange the forward and backward trajectory and reverse them
344 
345  const CDCRecoHit3D& lastRecoHit3D = back();
346  double lastPerpS = lastRecoHit3D.getArcLength2D();
347  double newLastPerpS = m_startTrajectory3D.calcArcLength2D(lastRecoHit3D.getRecoPos3D());
348 
349  // Reverse the left right passage hypotheses and reverse the measured travel distance
350  for (CDCRecoHit3D& recoHit3D : *this) {
351  recoHit3D.reverse();
352  double perpS = recoHit3D.getArcLength2D();
353  recoHit3D.setArcLength2D(newLastPerpS + lastPerpS - perpS);
354  }
355 
356  // Reverse the arrangement of hits.
357  std::reverse(begin(), end());
358 }
359 
361 {
362  CDCTrack reversedTrack(*this);
363  reversedTrack.reverse();
364  return reversedTrack;
365 }
366 
367 MayBePtr<const CDCRecoHit3D> CDCTrack::find(const CDCWireHit& wireHit) const
368 {
369  auto hasWireHit = [&wireHit](const CDCRecoHit3D & recoHit3D) {
370  return recoHit3D.hasWireHit(wireHit);
371  };
372  auto itRecoHit3D = std::find_if(this->begin(), this->end(), hasWireHit);
373  return itRecoHit3D == this->end() ? nullptr : &*itRecoHit3D;
374 }
375 
377 {
379  for (const CDCRecoHit3D& recoHit3D : *this) {
380  const CDCWireHit& wireHit = recoHit3D.getWireHit();
381  wireHit.getAutomatonCell().unsetMaskedFlag();
382  }
383 }
384 
386 {
388  for (const CDCRecoHit3D& recoHit3D : *this) {
389  const CDCWireHit& wireHit = recoHit3D.getWireHit();
390  wireHit.getAutomatonCell().setMaskedFlag();
391  }
392 }
393 
395 {
396  for (const CDCRecoHit3D& recoHit3D : *this) {
397  const CDCWireHit& wireHit = recoHit3D.getWireHit();
398  if (wireHit.getAutomatonCell().hasMaskedFlag()) {
400  return;
401  }
402  }
403 }
404 
405 void CDCTrack::forwardTakenFlag(bool takenFlag) const
406 {
407  for (const CDCRecoHit3D& recoHit3D : *this) {
408  recoHit3D.getWireHit().getAutomatonCell().setTakenFlag(takenFlag);
409  }
410 }
411 
413 {
414  std::stable_sort(begin(),
415  end(),
416  [](const CDCRecoHit3D & recoHit, const CDCRecoHit3D & otherRecoHit) {
417  double arcLength = recoHit.getArcLength2D();
418  double otherArcLength = otherRecoHit.getArcLength2D();
419  return lessFloatHighNaN(arcLength, otherArcLength);
420  });
421 }
422 
423 void CDCTrack::shiftToPositiveArcLengths2D(bool doForAllTracks)
424 {
425  const CDCTrajectory2D& startTrajectory2D = getStartTrajectory3D().getTrajectory2D();
426  if (doForAllTracks or startTrajectory2D.isCurler(1.1)) {
427  const double shiftValue = startTrajectory2D.getLocalCircle()->arcLengthPeriod();
428  if (std::isfinite(shiftValue)) {
429  for (CDCRecoHit3D& recoHit : *this) {
430  if (recoHit.getArcLength2D() < 0) {
431  recoHit.shiftArcLength2D(shiftValue);
432  }
433  }
434  }
435  }
436 }
void setTakenFlag(bool setTo=true)
Sets the taken flag to the given value. Default value true.
void setMaskedFlag(bool setTo=true)
Sets the masked flag to the given value. Default value true.
void unsetMaskedFlag()
Resets the masked flag to false.
bool hasMaskedFlag() const
Gets the current state of the masked marker flag.
Class representing an oriented hit wire including a hypotheses whether the causing track passes left ...
Definition: CDCRLWireHit.h:41
Class representing a two dimensional reconstructed hit in the central drift chamber.
Definition: CDCRecoHit2D.h:47
Vector2D getRecoPos2D() const
Getter for the position in the reference plane.
Definition: CDCRecoHit2D.h:238
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
static CDCRecoHit3D average(const CDCRecoHit3D &first, const CDCRecoHit3D &second)
Constructs the average of two reconstructed hit positions.
ISuperLayer getISuperLayer() const
Getter for the superlayer id.
Definition: CDCRecoHit3D.h:220
void shiftArcLength2D(double arcLength2DOffSet)
Adjust the travel distance by the given value.
Definition: CDCRecoHit3D.h:364
void reverse()
Turns the orientation in place.
static CDCRecoHit3D reconstruct(const CDCRecoHit2D &recoHit2D, const CDCTrajectory2D &trajectory2D)
Reconstructs the three dimensional hit from the two dimensional and the two dimensional trajectory.
Definition: CDCRecoHit3D.cc:56
double getArcLength2D() const
Getter for the travel distance in the xy projection.
Definition: CDCRecoHit3D.h:370
bool hasWireHit(const CDCWireHit &wireHit) const
Checks if the reconstructed hit is assoziated with the give wire hit.
Definition: CDCRecoHit3D.h:244
void setArcLength2D(const double arcLength2D)
Setter for the travel distance in the xy projection.
Definition: CDCRecoHit3D.h:376
const Vector3D & getRecoPos3D() const
Getter for the 3d position of the hit.
Definition: CDCRecoHit3D.h:285
const CDCWireHit & getWireHit() const
Getter for the wire hit.
Definition: CDCRecoHit3D.h:238
A reconstructed sequence of two dimensional hits in one super layer.
Definition: CDCSegment2D.h:39
Class representing a pair of one reconstructed axial segement and one stereo segment in adjacent supe...
const CDCSegment2D * getFromSegment() const
Getter for the from segment.
CDCTrajectory3D & getTrajectory3D() const
Getter for the three dimensional trajectory.
const CDCSegment2D * getToSegment() const
Getter for the to segment.
Class representing a triple of reconstructed segements in adjacent superlayer.
const CDCAxialSegment2D * getStartSegment() const
Getter for the start axial segment.
const CDCTrajectory3D & getTrajectory3D() const
Getter for the three dimensional helix trajectory.
const CDCAxialSegment2D * getEndSegment() const
Getter for the end axial segment.
const CDCStereoSegment2D * getMiddleSegment() const
Getter for the middle stereo segment.
Class representing a sequence of three dimensional reconstructed hits.
Definition: CDCTrack.h:41
std::vector< CDCSegment3D > splitIntoSegments() const
Splits the track into segments.
Definition: CDCTrack.cc:321
CDCTrack reversed() const
Return a reversed copy of the track.
Definition: CDCTrack.cc:360
void reverse()
Reverse the track inplace.
Definition: CDCTrack.cc:336
void forwardTakenFlag(bool takenFlag=true) const
Set the taken flag of all hits belonging to this track to the given value (default true),...
Definition: CDCTrack.cc:405
void sortByArcLength2D()
Sort the recoHits according to their perpS information.
Definition: CDCTrack.cc:412
void shiftToPositiveArcLengths2D(bool doForAllTracks=false)
Set all arcLengths to have positive values by shifting them by pi*radius if they are negative.
Definition: CDCTrack.cc:423
void setAndForwardMaskedFlag() const
Set the masked flag of the automaton cell of this segment and forward the masked flag to all containe...
Definition: CDCTrack.cc:385
CDCTrajectory3D m_startTrajectory3D
Memory for the three dimensional trajectory at the start of the track.
Definition: CDCTrack.h:204
void unsetAndForwardMaskedFlag() const
Unset the masked flag of the automaton cell of this segment and of all contained wire hits.
Definition: CDCTrack.cc:376
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
Definition: CDCTrack.h:125
MayBePtr< const CDCRecoHit3D > find(const CDCWireHit &wireHit) const
Finds the first CDCRecoHit3D that is based on the given wire hit - nullptr if none.
Definition: CDCTrack.cc:367
static CDCTrack condense(const Path< const CDCTrack > &trackPath)
Concats several tracks from a path.
Definition: CDCTrack.cc:164
CDCTrajectory3D m_endTrajectory3D
Memory for the three dimensional trajectory at the end of the track.
Definition: CDCTrack.h:207
void receiveMaskedFlag() const
Check all contained wire hits if one has the masked flag.
Definition: CDCTrack.cc:394
CDCTrack()=default
Default constructor for ROOT compatibility.
const CDCTrajectory3D & getStartTrajectory3D() const
Getter for the two dimensional trajectory.
Definition: CDCTrack.h:112
Particle trajectory as it is seen in xy projection represented as a circle.
bool isCurler(double factor=1) const
Checks if the trajectory leaves the outer radius of the CDC times the given tolerance factor.
const UncertainPerigeeCircle & getLocalCircle() const
Getter for the cirlce in local coordinates.
Particle full three dimensional trajectory.
double calcArcLength2D(const Vector3D &point) const
Calculate the travel distance from the start position of the trajectory.
void reverse()
Reverses the trajectory in place.
CDCTrajectory2D getTrajectory2D() const
Getter for the two dimensional trajectory.
double setLocalOrigin(const Vector3D &localOrigin)
Setter for the origin of the local coordinate system.
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
double arcLengthPeriod() const
Getter for the arc length for a full round of the circle.
A three dimensional vector.
Definition: Vector3D.h:33
Abstract base class for different kinds of events.