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