Belle II Software prerelease-11-00-00e
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/trackingUtilities/eventdata/tracks/CDCTrack.h>
15#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
16#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
17
18#include <tracking/trackingUtilities/numerics/WeightComperator.h>
19
20#include <tracking/trackingUtilities/utilities/StringManipulation.h>
21
22#include <framework/core/ModuleParamList.templateDetails.h>
23
24using namespace Belle2;
25using namespace TrackFindingCDC;
26using namespace TrackingUtilities;
27
29{
30 return "Merges axial tracks found in the Legendre search";
31}
32
33void AxialTrackMerger::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
34{
35 moduleParamList->addParameter(prefixed(prefix, "minFitProb"),
37 "Minimal fit probability of the common fit "
38 "of two tracks to be eligible for merging",
40
41 moduleParamList->addParameter(prefixed(prefix, "removeHitsAfterSuperLayerBreak"),
43 "Remove the hits of the tracks after a super layer break "
44 "before merging the tracks",
46}
47
48void AxialTrackMerger::apply(std::vector<CDCTrack>& axialTracks,
49 const std::vector<const CDCWireHit*>& allAxialWireHits)
50{
51 // Check quality of the track basing on holes on the trajectory;
52 // if holes exist then track is split
53 for (CDCTrack& track : axialTracks) {
54 if (track.size() < 5) continue;
57 }
59 }
60
61 // Update tracks before storing to DataStore
62 for (CDCTrack& track : axialTracks) {
64 }
65
66 // Remove bad tracks
69
70 // Perform tracks merging
71 this->doTracksMerging(axialTracks, allAxialWireHits);
72
73 // Remove the consumed, now empty tracks.
75}
76
77void AxialTrackMerger::doTracksMerging(std::vector<CDCTrack>& axialTracks,
78 const std::vector<const CDCWireHit*>& allAxialWireHits)
79{
80 // Search for best matches - cannot use range for here :(.
81 for (auto itTrack = axialTracks.begin(); itTrack != axialTracks.end(); ++itTrack) {
82 CDCTrack& track = *itTrack;
83 auto followingTracks = asRange(std::next(itTrack), axialTracks.end());
84
85 WithWeight<MayBePtr<CDCTrack> > bestTrack = calculateBestTrackToMerge(track, followingTracks);
86 double fitProb = bestTrack.getWeight();
87
88 if (bestTrack != nullptr and fitProb > m_param_minFitProb) {
89 mergeTracks(track, *bestTrack, allAxialWireHits);
90 }
91 }
92
94}
95
97template <class ACDCTracks>
99{
100 std::vector<WithWeight<CDCTrack*>> weightedTracks;
101 for (CDCTrack& track2 : tracks) {
102 if (&track == &track2) continue;
103 if (track2.size() < 3) continue;
104
105 double fitProb = doTracksFitTogether(track, track2);
106 if (std::isnan(fitProb)) continue;
107
108 weightedTracks.emplace_back(&track2, fitProb);
109 }
110
111 auto bestMatch = std::max_element(weightedTracks.begin(), weightedTracks.end(), LessWeight());
112 if (bestMatch == weightedTracks.end()) return {nullptr, 0};
113 else return *bestMatch;
114}
115
117{
118 // First check whether most of the hits from the tracks lie in the backward direction
119 // even if though track is not curling -> tracks should not be merged
120 const CDCTrajectory3D& trajectory3D1 = track1.getStartTrajectory3D();
121 const CDCTrajectory3D& trajectory3D2 = track2.getStartTrajectory3D();
122
123 int fbVote12 = 0;
124 int fbVote21 = 0;
125
126 for (const CDCRecoHit3D& recoHit3D : track1) {
127 EForwardBackward fbInfo = trajectory3D2.getFlightDirection3DAtSupport().xy().isForwardOrBackwardOf(recoHit3D.getRecoPos2D());
128 if (not isValid(fbInfo)) continue;
129 fbVote12 += fbInfo;
130 }
131
132 for (const CDCRecoHit3D& recoHit3D : track2) {
133 EForwardBackward fbInfo = trajectory3D1.getFlightDirection3DAtSupport().xy().isForwardOrBackwardOf(recoHit3D.getRecoPos2D());
134 if (not isValid(fbInfo)) continue;
135 fbVote21 += fbInfo;
136 }
137
138 if (not trajectory3D1.isCurler() and fbVote12 < 0) return NAN;
139 if (not trajectory3D2.isCurler() and fbVote21 < 0) return NAN;
140
141 // Build common hit list by copying the wire hits into one large list
142 // We use the wire hits here as we do not want them to bring
143 // their "old" reconstructed position when fitting.
144 std::vector<const CDCWireHit*> combinedWireHits;
145 combinedWireHits.reserve(track1.size() + track2.size());
146 for (const CDCRecoHit3D& hit : track1) {
147 combinedWireHits.push_back(&(hit.getWireHit()));
148 }
149 for (const CDCRecoHit3D& hit : track2) {
150 combinedWireHits.push_back(&(hit.getWireHit()));
151 }
152
153 // Sorting is done via pointer addresses (!!).
154 // This is not very stable and also not very meaningful (in terms of ordering in the track),
155 // but it does the job for unique.
156 // (the ordering is still outwards though since the wire hits are ordered like that in continuous memory)
157 std::sort(combinedWireHits.begin(), combinedWireHits.end());
158 erase_unique(combinedWireHits);
159
160 // Calculate track parameters
161 CDCTrajectory2D commonTrajectory2D;
163
164 // Approach the best fit
165 commonTrajectory2D = fitter.fit(combinedWireHits);
166 removeStrangeHits(5, combinedWireHits, commonTrajectory2D);
167 commonTrajectory2D = fitter.fit(combinedWireHits);
168 removeStrangeHits(3, combinedWireHits, commonTrajectory2D);
169 commonTrajectory2D = fitter.fit(combinedWireHits);
170 removeStrangeHits(1, combinedWireHits, commonTrajectory2D);
171 commonTrajectory2D = fitter.fit(combinedWireHits);
172 removeStrangeHits(1, combinedWireHits, commonTrajectory2D);
173 commonTrajectory2D = fitter.fit(combinedWireHits);
174
175 // Dismiss this possibility if the hit list size after all the removing of hits is even smaller
176 // than the two lists before or if the list is too small
177 if (combinedWireHits.size() <= std::max(track1.size(), track2.size())
178 or combinedWireHits.size() < 15) {
179 return NAN;
180 }
181
182 return commonTrajectory2D.getPValue();
183}
184
186 std::vector<const CDCWireHit*>& wireHits,
187 CDCTrajectory2D& trajectory2D)
188{
189 auto farFromTrajectory = [&trajectory2D, &factor](const CDCWireHit * wireHit) {
190 Vector2D pos2D = wireHit->getRefPos2D();
191 double driftLength = wireHit->getRefDriftLength();
192 double dist = std::fabs(trajectory2D.getDist2D(pos2D)) - driftLength;
193 return std::fabs(dist) > driftLength * factor;
194 };
195 erase_remove_if(wireHits, farFromTrajectory);
196}
197
199 CDCTrack& track2,
200 const std::vector<const CDCWireHit*>& allAxialWireHits)
201{
202 if (&track1 == &track2) return;
203
204 CDCTrajectory2D trajectory2D = track1.getStartTrajectory3D().getTrajectory2D();
205 for (const CDCRecoHit3D& orgRecoHit3D : track2) {
206 CDCRecoHit3D recoHit3D = CDCRecoHit3D::reconstruct(orgRecoHit3D.getRLWireHit(), trajectory2D);
207 track1.push_back(std::move(recoHit3D));
208 }
209 track2.clear();
210
212
214
216
217 for (CDCRecoHit3D& recoHit3D : track2) {
218 recoHit3D.setRecoPos3D({recoHit3D.getRefPos2D(), 0});
219 recoHit3D.setRLInfo(ERightLeft::c_Unknown);
220 }
221
223 bool success = AxialTrackUtil::postprocessTrack(track2, allAxialWireHits);
224 if (not success) {
225 for (const CDCRecoHit3D& recoHit3D : track2) {
226 recoHit3D.getWireHit()->setTakenFlag(false);
227 }
228 track2.clear();
229 }
230}
The Module parameter list class.
void apply(std::vector< TrackingUtilities::CDCTrack > &axialTracks, const std::vector< const TrackingUtilities::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 TrackingUtilities::CDCWireHit * > &wireHits, TrackingUtilities::CDCTrajectory2D &trajectory)
Remove all hits that are further than factor * driftlength away from the trajectory.
void doTracksMerging(std::vector< TrackingUtilities::CDCTrack > &axialTracks, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits)
The track finding often finds two curling tracks, originating from the same particle.
bool m_param_removeHitsAfterSuperLayerBreak
Parameter : Remove the hits of the tracks after a super layer break before merging.
std::string getDescription() final
Short description of the findlet.
static void mergeTracks(TrackingUtilities::CDCTrack &track1, TrackingUtilities::CDCTrack &track2, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits)
Function to merge two track candidates.
static double doTracksFitTogether(TrackingUtilities::CDCTrack &track1, TrackingUtilities::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.
static TrackingUtilities::WithWeight< TrackingUtilities::MayBePtr< TrackingUtilities::CDCTrack > > calculateBestTrackToMerge(TrackingUtilities::CDCTrack &track, ACDCTracks &tracks)
Searches for the best candidate to merge this track to.
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.
static CDCRecoHit3D reconstruct(const CDCRecoHit2D &recoHit2D, const CDCTrajectory2D &trajectory2D)
Reconstructs the three dimensional hit from the two dimensional and the two dimensional trajectory.
Class representing a sequence of three dimensional reconstructed hits.
Definition CDCTrack.h:39
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:58
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition Vector2D.h:36
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:520
const Vector2D & xy() const
Getter for the xy projected vector ( reference ! )
Definition Vector3D.h:509
A mixin class to attach a weight to an object.
Definition WithWeight.h:24
Weight getWeight() const
Getter for the weight.
Definition WithWeight.h:56
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
Abstract base class for different kinds of events.
static void normalizeTrack(TrackingUtilities::CDCTrack &track)
Refit and resort the track. Unmask all hits.
static void deleteShortTracks(std::vector< TrackingUtilities::CDCTrack > &axialTracks, double minimal_size=5)
Remove tracks that are shorter than the given number of hits.
static void deleteTracksWithLowFitProbability(std::vector< TrackingUtilities::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 ...
static void removeHitsAfterSuperLayerBreak(TrackingUtilities::CDCTrack &track)
Searches for a break in the super layer chain and remove all hits that come after that.
static std::vector< TrackingUtilities::CDCRecoHit3D > splitBack2BackTrack(TrackingUtilities::CDCTrack &track)
Tries to split back-to-back tracks into two different tracks.
static bool postprocessTrack(TrackingUtilities::CDCTrack &track, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits)
Perform all track postprocessing - return whether the track is considered good after the postprocessi...