543 {
545 statistics = FloatingSegmentStatistics{};
546 if (validationSegments != nullptr) validationSegments->clear();
547
548 using Projections =
549 std::array<std::array<std::vector<const Coincidence*>, 3>, 2>;
550 std::map<GroupKey, Projections>
grouped;
551 for (const Coincidence& coincidence : coincidences) {
552 if (stationBit(coincidence.station) == 0U) continue;
553 const std::size_t projection = coincidence.isStrip ? 1U : 0
U;
554 grouped[coincidence.key][projection][stationIndex(coincidence.station)]
555 .emplace_back(&coincidence);
556 }
557
558 std::set<CandidateKey> candidateKeys;
559 for (const auto& [groupKey, projections] : grouped) {
560 const std::vector<ProjectionSegment> wireSegments =
561 buildProjectionSegments(projections[0],
false,
m_config, statistics);
562 const std::vector<ProjectionSegment> stripSegments =
563 buildProjectionSegments(projections[1],
true,
m_config, statistics);
564 statistics.nWireSegments += wireSegments.size();
565 statistics.nStripSegments += stripSegments.size();
566 if (validationSegments != nullptr) {
567 appendValidationSegments(groupKey, wireSegments, *validationSegments);
568 appendValidationSegments(groupKey, stripSegments, *validationSegments);
569 }
570
571 std::vector<CandidatePair> pairs;
572 pairs.reserve(wireSegments.size() * stripSegments.size());
573 for (const ProjectionSegment& wire : wireSegments) {
574 if (
m_config.maxCandidateDThetaAbs >= 0.F &&
575 std::abs(wire.residual) >
m_config.maxCandidateDThetaAbs) {
576 statistics.nRejectedPairs += stripSegments.size();
577 continue;
578 }
579 for (
const ProjectionSegment&
strip : stripSegments) {
580 if (
m_config.maxCandidateDPhiAbs >= 0.F &&
582 ++statistics.nRejectedPairs;
583 continue;
584 }
587 if (!position) {
588 ++statistics.nRejectedPairs;
589 continue;
590 }
591 const std::uint8_t positionMask = static_cast<std::uint8_t>(
592 wire.stationMask &
strip.stationMask);
593 const std::uint8_t combinedMask = static_cast<std::uint8_t>(
594 wire.stationMask |
strip.stationMask);
595 if (std::popcount(static_cast<unsigned int>(combinedMask)) < 2) {
596 ++statistics.nRejectedPairs;
597 continue;
598 }
599 pairs.emplace_back(
600 CandidatePair{&wire, &
strip,
position, positionMask, combinedMask});
601 }
602 }
603
604 pruneLocalCandidateBins(pairs,
m_config, statistics);
605 suppressLocalPositionDuplicates(pairs,
m_config, statistics);
606 retainCandidateWorkingSet(pairs,
607 m_config.maxSegmentCombinationsPerGroup,
608 statistics);
609
610 for (const CandidatePair& pair : pairs) {
611 const CandidateKey
keyValue = candidateKey(groupKey, pair);
612 if (!candidateKeys.insert(keyValue).second) {
613 ++statistics.nDuplicateCandidates;
614 continue;
615 }
616
617 const ProjectionSegment& wire = *pair.wire;
618 const ProjectionSegment&
strip = *pair.strip;
619 TgcSLCandidate candidate;
620 candidate.subdetectorId = groupKey.subDetectorId;
621 candidate.sectorId = groupKey.triggerSector;
622 candidate.readoutSector = pair.position.wire->detectorSector;
623 candidate.bcTag = groupKey.bcTag;
624 candidate.eta = pair.position.wire->eta;
625 candidate.phi = pair.position.strip->phi;
626 candidate.deltaTheta = wire.outputResidual;
627 candidate.deltaPhi =
strip.outputResidual;
628 candidate.wireStationMask = wire.stationMask;
629 candidate.stripStationMask =
strip.stationMask;
630 candidate.positionStationMask = pair.positionStationMask;
631 candidate.stationMask = candidate.positionStationMask;
632 candidate.m1WireQuality = quality(wire, Station::M1);
633 candidate.m2WireQuality = quality(wire, Station::M2);
634 candidate.m3WireQuality = quality(wire, Station::M3);
635 candidate.m1StripQuality = quality(
strip, Station::M1);
636 candidate.m2StripQuality = quality(
strip, Station::M2);
637 candidate.m3StripQuality = quality(
strip, Station::M3);
638 candidate.pivotWireChannel = pair.position.wire->channel;
639 candidate.pivotStripChannel = pair.position.strip->channel;
640
641 if ((candidate.positionStationMask & 0x1U) != 0U) {
642 candidate.m1Eta = wire.points[0]->eta;
643 candidate.m1Phi =
strip.points[0]->phi;
644 candidate.m1StationEta = wire.points[0]->stationEta;
645 candidate.m1StationPhi = wire.points[0]->stationPhi;
646 }
647 if ((candidate.positionStationMask & 0x2U) != 0U) {
648 candidate.m2Eta = wire.points[1]->eta;
649 candidate.m2Phi =
strip.points[1]->phi;
650 candidate.m2StationEta = wire.points[1]->stationEta;
651 candidate.m2StationPhi = wire.points[1]->stationPhi;
652 }
653 if ((candidate.positionStationMask & 0x4U) != 0U) {
654 candidate.m3Eta = wire.points[2]->eta;
655 candidate.m3Phi =
strip.points[2]->phi;
656 candidate.m3StationEta = wire.points[2]->stationEta;
657 candidate.m3StationPhi = wire.points[2]->stationPhi;
658 }
659 candidate.wireQuality = wire.summedQuality;
660 candidate.selectorPriority = static_cast<std::uint8_t>(
661 2U * std::popcount(
662 static_cast<unsigned int>(pair.combinedStationMask)) +
663 wire.summedQuality +
strip.summedQuality);
665 countPositionMask(candidate.positionStationMask, statistics);
666 }
667 }
668 return StatusCode::SUCCESS;
669}
const Amg::Vector3D & position() const
Method to retrieve the position of the Intersection.