Main algorithm.
102{
103 using InTracks = std::array<const CDCTrack*, 2>;
104
105
106 std::map<const CDCWireHit*, InTracks> inTracksByWireHit;
107 for (const CDCTrack& track : inputTracks) {
108 for (const CDCRecoHit3D& recoHit3D : track) {
109 const CDCWireHit& wireHit = recoHit3D.getWireHit();
110 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {nullptr, nullptr};
111 inTracksByWireHit[&wireHit][0] = &track;
112
115 }
116 }
117
118 for (const CDCTrack& track : secondInputTracks) {
119 for (const CDCRecoHit3D& recoHit3D : track) {
120 const CDCWireHit& wireHit = recoHit3D.getWireHit();
121 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {nullptr, nullptr};
122 inTracksByWireHit[&wireHit][1] = &track;
123
126 }
127 }
128
129
130 std::vector<std::pair<std::pair<int, size_t>, const CDCTrack*> > rankedTracks;
131 for (const CDCTrack& track : inputTracks) {
132 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
133 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(), Id() > 0);
134 rankedTracks.push_back({{nSL, track.size()}, &track});
135 }
136 for (const CDCTrack& track : secondInputTracks) {
137 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
138 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(), Id() > 0);
139 rankedTracks.push_back({{nSL, track.size()}, &track});
140 }
141 std::sort(rankedTracks.begin(), rankedTracks.end(), GreaterOf<First>());
142
143
144 std::deque<CDCSegment3D> segments;
145
146
147 std::vector<WeightedRelation<const CDCSegment3D>> segmentRelations;
148
149
150 std::map<const CDCSegment3D*, InTracks> inTracksBySegment;
151
152
153 for (const std::pair<std::pair<int, size_t>, const CDCTrack*>& rankedTrack : rankedTracks) {
154
155 const CDCTrack* track = rankedTrack.second;
156 std::vector<std::pair<InTracks, CDCSegment3D> > segmentsInTrack;
157
158
159 CDCSegment3D* currentSegment = nullptr;
161 InTracks lastTracksForHit{{nullptr, nullptr}};
162 for (const CDCRecoHit3D& recoHit3D : *track) {
163 ISuperLayer iSuperLayer = recoHit3D.getISuperLayer();
164 std::array<const CDCTrack*, 2> tracksForWireHit = inTracksByWireHit[&recoHit3D.getWireHit()];
165 if (not currentSegment or iSuperLayer != lastISuperLayer or tracksForWireHit != lastTracksForHit) {
166
167 segmentsInTrack.push_back({tracksForWireHit, CDCSegment3D()});
168 currentSegment = &segmentsInTrack.back().second;
169 currentSegment->setTrajectory3D(track->getStartTrajectory3D());
170 }
171 currentSegment->push_back(recoHit3D);
172 lastISuperLayer = iSuperLayer;
173 lastTracksForHit = tracksForWireHit;
174 }
175
176
177 auto absorbsSegment = [](std::pair<InTracks, CDCSegment3D>& segment1,
178 std::pair<InTracks, CDCSegment3D>& segment2) {
179
180 if (segment1.second.getISuperLayer() != segment2.second.getISuperLayer()) return false;
181 if (segment1.second.size() < 3) {
182 segment1.first = segment2.first;
183 }
184
185 if (segment1.second.size() < 3 or segment2.second.size() < 3 or
186 segment1.first == segment2.first) {
187 segment1.second.insert(segment1.second.end(),
188 segment2.second.begin(),
189 segment2.second.end());
190 return true;
191 }
192 return false;
193 };
194 auto itSegmentToDrop = std::unique(segmentsInTrack.begin(), segmentsInTrack.end(), absorbsSegment);
195 segmentsInTrack.erase(itSegmentToDrop, segmentsInTrack.end());
196
197 size_t nHits = 0;
198 for (std::pair<InTracks, CDCSegment3D>& segment : segmentsInTrack) {
199 nHits += segment.second.size();
200 }
201 B2ASSERT("Expected the number of hits to be the same", nHits == track->size());
202
203
204 const CDCSegment3D* lastSegment = nullptr;
205 for (std::pair<InTracks, CDCSegment3D>& segmentInTrack : segmentsInTrack) {
206 const InTracks& inTracks = segmentInTrack.first;
207 const CDCSegment3D& segment = segmentInTrack.second;
208 segment->setCellWeight(segment.size());
209 segments.push_back(std::move(segment));
210 inTracksBySegment[&segments.back()] = inTracks;
211 if (lastSegment != nullptr) {
212 segmentRelations.push_back({lastSegment, 0, &segments.back()});
213 }
214 lastSegment = &segments.back();
215 }
216 }
217
218
219 std::sort(segmentRelations.begin(), segmentRelations.end());
220
221
223 std::vector<std::pair<const CDCSegment3D*, const CDCSegment3D*>> segmentContainmentRelation;
224 for (auto itSegment1 = segments.begin(); itSegment1 != segments.end(); ++itSegment1) {
225 const CDCSegment3D& segment1 = *itSegment1;
226 std::vector<CDCRLWireHit> rlWireHits1 = getRLWireHitSegment(segment1);
228 InTracks inTracks1 = inTracksBySegment[&segment1];
229 for (auto itSegment2 = itSegment1 + 1; itSegment2 != segments.end(); ++itSegment2) {
230 const CDCSegment3D& segment2 = *itSegment2;
231
232
233 if (&segment1 == &segment2) continue;
234
236 if (iSL1 != iSL2) continue;
237
238 InTracks inTracks2 = inTracksBySegment[&segment2];
239 if (inTracks1 != inTracks2) continue;
240
241
242 std::vector<CDCRLWireHit> rlWireHits2 = getRLWireHitSegment(segment2);
243 std::vector<std::pair<std::pair<int, int>, CDCRLWireHit>> commonRLWireHits =
244 getCommonRLWireHits(rlWireHits1, rlWireHits2);
245
246
247
248 bool contains = commonRLWireHits.size() > 2 and
249 commonRLWireHits.size() > rlWireHits1.size() * 0.8 and
250 commonRLWireHits.size() > rlWireHits2.size() * 0.8;
251 if (not contains) continue;
252
253
254 double n = commonRLWireHits.size();
255 double prod11 = 0;
256 double prod12 = 0;
257 double prod22 = 0;
258 double sum1 = 0;
259 double sum2 = 0;
260 for (const auto& commonRLWireHit : commonRLWireHits) {
261 const std::pair<int, int>& indices = commonRLWireHit.first;
262 prod11 += indices.first * indices.first;
263 prod12 += indices.first * indices.second;
264 prod22 += indices.second * indices.second;
265
266 sum1 += indices.first;
267 sum2 += indices.second;
268 }
269 double var1 = (prod11 - sum1 * sum1 / n);
270 double var2 = (prod22 - sum2 * sum2 / n);
271 double cov12 = (prod12 - sum1 * sum2 / n);
272 double cor = cov12 / std::sqrt(var1 * var2);
273 if (not(cor > 0.75)) continue;
274
275 segmentContainmentRelation.push_back({&segment1, &segment2});
276 }
277 }
278
279
280 std::vector<WeightedRelation<const CDCSegment3D>> additionalSegmentRelations;
281 for (std::pair<const CDCSegment3D*, const CDCSegment3D*>& rel : segmentContainmentRelation) {
282 for (WeightedRelation<const CDCSegment3D> rel1 :
283 asRange(std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.first))) {
284 additionalSegmentRelations.push_back({rel.second, 0, rel1.getTo()});
285 }
286
287 for (WeightedRelation<const CDCSegment3D> rel2 : asRange(
288 std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.second))) {
289 additionalSegmentRelations.push_back({rel.first, 0, rel2.getFrom()});
290 }
291 }
292 segmentRelations.insert(segmentRelations.end(),
293 additionalSegmentRelations.begin(),
294 additionalSegmentRelations.end());
295 std::sort(segmentRelations.begin(), segmentRelations.end());
296 }
297
298
299
300 std::vector<const CDCSegment3D*> segmentPtrs = as_pointers<const CDCSegment3D>(segments);
301
302
303 std::vector<Path<const CDCSegment3D>> segmentPaths;
305
306
307 outputTracks.clear();
308 for (const std::vector<const CDCSegment3D*>& segmentPath : segmentPaths) {
309
310 if (segmentPath.size() < 2) continue;
311 outputTracks.push_back(condense(segmentPath));
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334}
bool m_param_identifyCommonSegments
Parameter : Activate the identification of common segments.
TrackingUtilities::MultipassCellularPathFinder< const TrackingUtilities::CDCSegment3D > m_cellularPathFinder
Instance of the cellular automaton path finder.
void unsetMaskedFlag()
Resets the masked flag to false.
void unsetTemporaryFlags()
Resets the assigned, start and cycle marker flag.
CDC::ISuperLayer getISuperLayer() const
Returns the common super layer id of all stored tracking hits.
signed short ISuperLayer
The type of the layer and superlayer ids.