98 const std::vector<CDCTrack>& secondInputTracks,
99 std::vector<CDCTrack>& outputTracks)
101 using InTracks = std::array<const CDCTrack*, 2>;
104 std::map<const CDCWireHit*, InTracks> inTracksByWireHit;
105 for (
const CDCTrack& track : inputTracks) {
107 const CDCWireHit& wireHit = recoHit3D.getWireHit();
108 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {
nullptr,
nullptr};
109 inTracksByWireHit[&wireHit][0] = &track;
116 for (
const CDCTrack& track : secondInputTracks) {
118 const CDCWireHit& wireHit = recoHit3D.getWireHit();
119 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {
nullptr,
nullptr};
120 inTracksByWireHit[&wireHit][1] = &track;
128 std::vector<std::pair<std::pair<int, size_t>,
const CDCTrack*> > rankedTracks;
129 for (
const CDCTrack& track : inputTracks) {
130 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
131 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(),
Id() > 0);
132 rankedTracks.push_back({{nSL, track.size()}, &track});
134 for (
const CDCTrack& track : secondInputTracks) {
135 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
136 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(),
Id() > 0);
137 rankedTracks.push_back({{nSL, track.size()}, &track});
139 std::sort(rankedTracks.begin(), rankedTracks.end(), GreaterOf<First>());
142 std::deque<CDCSegment3D> segments;
145 std::vector<WeightedRelation<const CDCSegment3D>> segmentRelations;
148 std::map<const CDCSegment3D*, InTracks> inTracksBySegment;
151 for (
const std::pair<std::pair<int, size_t>,
const CDCTrack*>& rankedTrack : rankedTracks) {
153 const CDCTrack* track = rankedTrack.second;
154 std::vector<std::pair<InTracks, CDCSegment3D> > segmentsInTrack;
158 ISuperLayer lastISuperLayer = -1;
159 InTracks lastTracksForHit{{
nullptr,
nullptr}};
161 ISuperLayer iSuperLayer = recoHit3D.getISuperLayer();
162 std::array<const CDCTrack*, 2> tracksForWireHit = inTracksByWireHit[&recoHit3D.getWireHit()];
163 if (not currentSegment or iSuperLayer != lastISuperLayer or tracksForWireHit != lastTracksForHit) {
165 segmentsInTrack.push_back({tracksForWireHit,
CDCSegment3D()});
166 currentSegment = &segmentsInTrack.back().second;
167 currentSegment->setTrajectory3D(track->getStartTrajectory3D());
169 currentSegment->push_back(recoHit3D);
170 lastISuperLayer = iSuperLayer;
171 lastTracksForHit = tracksForWireHit;
175 auto absorbsSegment = [](std::pair<InTracks, CDCSegment3D>& segment1,
176 std::pair<InTracks, CDCSegment3D>& segment2) {
178 if (segment1.second.getISuperLayer() != segment2.second.getISuperLayer())
return false;
179 if (segment1.second.size() < 3) {
180 segment1.first = segment2.first;
183 if (segment1.second.size() < 3 or segment2.second.size() < 3 or
184 segment1.first == segment2.first) {
185 segment1.second.insert(segment1.second.end(),
186 segment2.second.begin(),
187 segment2.second.end());
192 auto itSegmentToDrop = std::unique(segmentsInTrack.begin(), segmentsInTrack.end(), absorbsSegment);
193 segmentsInTrack.erase(itSegmentToDrop, segmentsInTrack.end());
196 for (std::pair<InTracks, CDCSegment3D>& segment : segmentsInTrack) {
197 nHits += segment.second.size();
199 B2ASSERT(
"Expected the number of hits to be the same", nHits == track->size());
203 for (std::pair<InTracks, CDCSegment3D>& segmentInTrack : segmentsInTrack) {
204 const InTracks& inTracks = segmentInTrack.first;
206 segment->setCellWeight(segment.size());
207 segments.push_back(std::move(segment));
208 inTracksBySegment[&segments.back()] = inTracks;
209 if (lastSegment !=
nullptr) {
210 segmentRelations.push_back({lastSegment, 0, &segments.back()});
212 lastSegment = &segments.back();
217 std::sort(segmentRelations.begin(), segmentRelations.end());
221 std::vector<std::pair<const CDCSegment3D*, const CDCSegment3D*>> segmentContainmentRelation;
222 for (
auto itSegment1 = segments.begin(); itSegment1 != segments.end(); ++itSegment1) {
224 std::vector<CDCRLWireHit> rlWireHits1 = getRLWireHitSegment(segment1);
226 InTracks inTracks1 = inTracksBySegment[&segment1];
227 for (
auto itSegment2 = itSegment1 + 1; itSegment2 != segments.end(); ++itSegment2) {
231 if (&segment1 == &segment2)
continue;
234 if (iSL1 != iSL2)
continue;
236 InTracks inTracks2 = inTracksBySegment[&segment2];
237 if (inTracks1 != inTracks2)
continue;
240 std::vector<CDCRLWireHit> rlWireHits2 = getRLWireHitSegment(segment2);
241 std::vector<std::pair<std::pair<int, int>,
CDCRLWireHit>> commonRLWireHits =
242 getCommonRLWireHits(rlWireHits1, rlWireHits2);
246 bool contains = commonRLWireHits.size() > 2 and
247 commonRLWireHits.size() > rlWireHits1.size() * 0.8 and
248 commonRLWireHits.size() > rlWireHits2.size() * 0.8;
249 if (not contains)
continue;
252 double n = commonRLWireHits.size();
258 for (
const auto& commonRLWireHit : commonRLWireHits) {
259 const std::pair<int, int>& indices = commonRLWireHit.first;
260 prod11 += indices.first * indices.first;
261 prod12 += indices.first * indices.second;
262 prod22 += indices.second * indices.second;
264 sum1 += indices.first;
265 sum2 += indices.second;
267 double var1 = (prod11 - sum1 * sum1 / n);
268 double var2 = (prod22 - sum2 * sum2 / n);
269 double cov12 = (prod12 - sum1 * sum2 / n);
270 double cor = cov12 / std::sqrt(var1 * var2);
271 if (not(cor > 0.75))
continue;
273 segmentContainmentRelation.push_back({&segment1, &segment2});
278 std::vector<WeightedRelation<const CDCSegment3D>> additionalSegmentRelations;
279 for (std::pair<const CDCSegment3D*, const CDCSegment3D*>& rel : segmentContainmentRelation) {
281 asRange(std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.first))) {
282 additionalSegmentRelations.push_back({rel.second, 0, rel1.getTo()});
286 std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.second))) {
287 additionalSegmentRelations.push_back({rel.first, 0, rel2.getFrom()});
290 segmentRelations.insert(segmentRelations.end(),
291 additionalSegmentRelations.begin(),
292 additionalSegmentRelations.end());
293 std::sort(segmentRelations.begin(), segmentRelations.end());
298 std::vector<const CDCSegment3D*> segmentPtrs = as_pointers<const CDCSegment3D>(segments);
301 std::vector<TrackFindingCDC::Path<const CDCSegment3D>> segmentPaths;
305 outputTracks.clear();
306 for (
const std::vector<const CDCSegment3D*>& segmentPath : segmentPaths) {
308 if (segmentPath.size() < 2)
continue;
309 outputTracks.push_back(condense(segmentPath));