Belle II Software  release-08-01-10
AxialTrackMerger.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/findlets/minimal/AxialTrackMerger.h>
9 
10 #include <tracking/trackFindingCDC/processing/AxialTrackUtil.h>
11 
12 #include <tracking/trackFindingCDC/fitting/CDCKarimakiFitter.h>
13 
14 #include <tracking/trackFindingCDC/eventdata/tracks/CDCTrack.h>
15 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
16 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
17 
18 #include <tracking/trackFindingCDC/numerics/WeightComperator.h>
19 
20 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
21 
22 #include <framework/core/ModuleParamList.templateDetails.h>
23 
24 using namespace Belle2;
25 using namespace TrackFindingCDC;
26 
28 {
29  return "Merges axial tracks found in the legendre search";
30 }
31 
32 void AxialTrackMerger::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
33 {
34  moduleParamList->addParameter(prefixed(prefix, "minFitProb"),
36  "Minimal fit probability of the common fit "
37  "of two tracks to be eligible for merging",
39 }
40 
41 void AxialTrackMerger::apply(std::vector<CDCTrack>& axialTracks,
42  const std::vector<const CDCWireHit*>& allAxialWireHits)
43 {
44  // Check quality of the track basing on holes on the trajectory;
45  // if holes exist then track is splitted
46  for (CDCTrack& track : axialTracks) {
47  if (track.size() < 5) continue;
50  }
51 
52  // Update tracks before storing to DataStore
53  for (CDCTrack& track : axialTracks) {
55  }
56 
57  // Remove bad tracks
60 
61  // Perform tracks merging
62  this->doTracksMerging(axialTracks, allAxialWireHits);
63 
64  // Remove the consumed, now empty tracks.
65  AxialTrackUtil::deleteShortTracks(axialTracks, 0);
66 }
67 
68 void AxialTrackMerger::doTracksMerging(std::vector<CDCTrack>& axialTracks,
69  const std::vector<const CDCWireHit*>& allAxialWireHits)
70 {
71  // Search for best matches - cannot use range for here :(.
72  for (auto itTrack = axialTracks.begin(); itTrack != axialTracks.end(); ++itTrack) {
73  CDCTrack& track = *itTrack;
74  auto followingTracks = asRange(std::next(itTrack), axialTracks.end());
75 
76  WithWeight<MayBePtr<CDCTrack> > bestTrack = calculateBestTrackToMerge(track, followingTracks);
77  double fitProb = bestTrack.getWeight();
78 
79  if (bestTrack != nullptr and fitProb > m_param_minFitProb) {
80  mergeTracks(track, *bestTrack, allAxialWireHits);
81  }
82  }
83 
85 }
86 
88 template <class ACDCTracks>
90 {
91  std::vector<WithWeight<CDCTrack*>> weightedTracks;
92  for (CDCTrack& track2 : tracks) {
93  if (&track == &track2) continue;
94  if (track2.size() < 3) continue;
95 
96  double fitProb = doTracksFitTogether(track, track2);
97  if (std::isnan(fitProb)) continue;
98 
99  weightedTracks.emplace_back(&track2, fitProb);
100  }
101 
102  auto bestMatch = std::max_element(weightedTracks.begin(), weightedTracks.end(), LessWeight());
103  if (bestMatch == weightedTracks.end()) return {nullptr, 0};
104  else return *bestMatch;
105 }
106 
108 {
109  // First check whether most of the hits from the tracks lie in the backward direction
110  // even if though track is not curling -> tracks should not be merged
111  const CDCTrajectory3D& trajectory3D1 = track1.getStartTrajectory3D();
112  const CDCTrajectory3D& trajectory3D2 = track2.getStartTrajectory3D();
113 
114  const Vector2D& phi0Vec1 = trajectory3D1.getFlightDirection3DAtSupport().xy();
115  const Vector2D& phi0Vec2 = trajectory3D2.getFlightDirection3DAtSupport().xy();
116 
117  int fbVote12 = 0;
118  int fbVote21 = 0;
119 
120  for (const CDCRecoHit3D& recoHit3D : track1) {
121  EForwardBackward fbInfo = phi0Vec2.isForwardOrBackwardOf(recoHit3D.getRecoPos2D());
122  if (not isValid(fbInfo)) continue;
123  fbVote12 += fbInfo;
124  }
125 
126  for (const CDCRecoHit3D& recoHit3D : track2) {
127  EForwardBackward fbInfo = phi0Vec1.isForwardOrBackwardOf(recoHit3D.getRecoPos2D());
128  if (not isValid(fbInfo)) continue;
129  fbVote21 += fbInfo;
130  }
131 
132  if (not trajectory3D1.isCurler() and fbVote12 < 0) return NAN;
133  if (not trajectory3D2.isCurler() and fbVote21 < 0) return NAN;
134 
135  // Build common hit list by copying the wire hits into one large list
136  // We use the wire hits here as we do not want them to bring
137  // their "old" reconstructed position when fitting.
138  std::vector<const CDCWireHit*> combinedWireHits;
139  combinedWireHits.reserve(track1.size() + track2.size());
140  for (const CDCRecoHit3D& hit : track1) {
141  combinedWireHits.push_back(&(hit.getWireHit()));
142  }
143  for (const CDCRecoHit3D& hit : track2) {
144  combinedWireHits.push_back(&(hit.getWireHit()));
145  }
146 
147  // Sorting is done via pointer addresses (!!).
148  // This is not very stable and also not very meaningful (in terms of ordering in the track),
149  // but it does the job for unique.
150  // (the ordering is still outwards though since the wire hits are ordered like that in continuous memory)
151  std::sort(combinedWireHits.begin(), combinedWireHits.end());
152  erase_unique(combinedWireHits);
153 
154  // Calculate track parameters
155  CDCTrajectory2D commonTrajectory2D;
157 
158  // Approach the best fit
159  commonTrajectory2D = fitter.fit(combinedWireHits);
160  removeStrangeHits(5, combinedWireHits, commonTrajectory2D);
161  commonTrajectory2D = fitter.fit(combinedWireHits);
162  removeStrangeHits(3, combinedWireHits, commonTrajectory2D);
163  commonTrajectory2D = fitter.fit(combinedWireHits);
164  removeStrangeHits(1, combinedWireHits, commonTrajectory2D);
165  commonTrajectory2D = fitter.fit(combinedWireHits);
166  removeStrangeHits(1, combinedWireHits, commonTrajectory2D);
167  commonTrajectory2D = fitter.fit(combinedWireHits);
168 
169  // Dismiss this possibility if the hit list size after all the removing of hits is even smaller
170  // than the two lists before or if the list is too small
171  if (combinedWireHits.size() <= std::max(track1.size(), track2.size())
172  or combinedWireHits.size() < 15) {
173  return NAN;
174  }
175 
176  return commonTrajectory2D.getPValue();
177 }
178 
180  std::vector<const CDCWireHit*>& wireHits,
181  CDCTrajectory2D& trajectory2D)
182 {
183  auto farFromTrajectory = [&trajectory2D, &factor](const CDCWireHit * wireHit) {
184  Vector2D pos2D = wireHit->getRefPos2D();
185  double driftLength = wireHit->getRefDriftLength();
186  double dist = std::fabs(trajectory2D.getDist2D(pos2D)) - driftLength;
187  return std::fabs(dist) > driftLength * factor;
188  };
189  erase_remove_if(wireHits, farFromTrajectory);
190 }
191 
193  CDCTrack& track2,
194  const std::vector<const CDCWireHit*>& allAxialWireHits)
195 {
196  if (&track1 == &track2) return;
197 
198  CDCTrajectory2D trajectory2D = track1.getStartTrajectory3D().getTrajectory2D();
199  for (const CDCRecoHit3D& orgRecoHit3D : track2) {
200  CDCRecoHit3D recoHit3D = CDCRecoHit3D::reconstruct(orgRecoHit3D.getRLWireHit(), trajectory2D);
201  track1.push_back(std::move(recoHit3D));
202  }
203  track2.clear();
204 
206 
208 
210 
211  for (CDCRecoHit3D& recoHit3D : track2) {
212  recoHit3D.setRecoPos3D({recoHit3D.getRefPos2D(), 0});
213  recoHit3D.setRLInfo(ERightLeft::c_Unknown);
214  }
215 
217  bool success = AxialTrackUtil::postprocessTrack(track2, allAxialWireHits);
218  if (not success) {
219  for (const CDCRecoHit3D& recoHit3D : track2) {
220  recoHit3D.getWireHit()->setTakenFlag(false);
221  }
222  track2.clear();
223  }
224 }
The Module parameter list class.
static WithWeight< MayBePtr< CDCTrack > > calculateBestTrackToMerge(CDCTrack &track, ACDCTracks &tracks)
Searches for the best candidate to merge this track to.
void apply(std::vector< CDCTrack > &axialTracks, const std::vector< const CDCWireHit * > &axialWireHits) final
Merge tracks together. Allows for axial hits to be added as it may see fit.
static void removeStrangeHits(double factor, std::vector< const CDCWireHit * > &wireHits, CDCTrajectory2D &trajectory)
Remove all hits that are further than factor * driftlength away from the trajectory.
static void mergeTracks(CDCTrack &track1, CDCTrack &track2, const std::vector< const CDCWireHit * > &allAxialWireHits)
Function to merge two track candidates.
std::string getDescription() final
Short description of the findlet.
static double doTracksFitTogether(CDCTrack &track1, CDCTrack &track2)
Fits the hit content of both tracks in a common fit repeated with an annealing schedule removing far ...
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) final
Expose the parameters to a module.
void doTracksMerging(std::vector< CDCTrack > &axialTracks, const std::vector< const CDCWireHit * > &allAxialWireHits)
The track finding often finds two curling tracks, originating from the same particle.
double m_param_minFitProb
Parameter : Minimal fit probability of the common fit of two tracks to be eligible for merging.
Class implementing the fitter using Karimakis method.
static const CDCKarimakiFitter & getNoDriftVarianceFitter()
Static getter for a general fitter that does not use the drift length variances.
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
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
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 getPValue() const
Getter for p-value.
double getDist2D(const Vector2D &point) const
Calculates the distance from the point to the trajectory as seen from the xy projection.
Particle full three dimensional trajectory.
bool isCurler(double factor=1) const
Checks if the trajectory leaves the outer radius of the CDC times the given tolerance factor.
Vector3D getFlightDirection3DAtSupport() const
Get the unit momentum at the start point of the trajectory.
Class representing a hit wire in the central drift chamber.
Definition: CDCWireHit.h:55
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
EForwardBackward isForwardOrBackwardOf(const Vector2D &rhs) const
Indicates if the given vector is more coaligned or reverse if you looked in the direction of this vec...
Definition: Vector2D.h:505
const Vector2D & xy() const
Getter for the xy projected vector ( reference ! )
Definition: Vector3D.h:508
A mixin class to attach a weight to an object.
Definition: WithWeight.h:24
Weight getWeight() const
Getter for the weight.
Definition: WithWeight.h:58
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
EForwardBackward
Enumeration to represent the distinct possibilities of the right left passage information.
Abstract base class for different kinds of events.
static void deleteShortTracks(std::vector< CDCTrack > &axialTracks, double minimal_size=5)
Remove tracks that are shorter than the given number of hits.
static void normalizeTrack(CDCTrack &track)
Refit and resort the track. Unmask all hits.
static void removeHitsAfterSuperLayerBreak(CDCTrack &track)
Searches for a break in the super layer chain and remove all hits that come after that.
static bool postprocessTrack(CDCTrack &track, const std::vector< const CDCWireHit * > &allAxialWireHits)
Perform all track postprocessing - return whether the track is considered good after the postprocessi...
static std::vector< CDCRecoHit3D > splitBack2BackTrack(CDCTrack &track)
Tries to split back-to-back tracks into two different tracks.
static void deleteTracksWithLowFitProbability(std::vector< CDCTrack > &axialTracks, double minimal_probability_for_good_fit=0.4)
Check an (improper) p-values of the tracks. If they are below the given value, delete the track from ...
Functor factory turning a binary functor and two functors into a new functor which executes the binar...
Definition: Functional.h:127