417 const std::vector<float>& spPhi,
const std::vector<float>& spAsinD0OverR,
418 const Acts::ConstSpacePointProxy& middle,
419 const Acts::ConstSpacePointProxy& other,
float cotTheta,
420 bool isBottomCandidate)
const {
429 const float rM = middle.zr()[1];
430 const float rO = other.zr()[1];
431 const float rInner = std::min(rM, rO);
432 const float rOuter = std::max(rM, rO);
439 const auto iM = middle.copiedFromIndex();
440 const auto iO = other.copiedFromIndex();
441 float dPhi = spPhi[iO] - spPhi[iM];
442 const float swing = std::abs(spAsinD0OverR[iO] - spAsinD0OverR[iM]);
443 if (dPhi > std::numbers::pi_v<float>) {
444 dPhi -= 2.f * std::numbers::pi_v<float>;
445 }
else if (dPhi < -std::numbers::pi_v<float>) {
446 dPhi += 2.f * std::numbers::pi_v<float>;
452 if (std::abs(dPhi) > bound) {
459 const auto& xyM = middle.xy();
460 const auto& zrM = middle.zr();
461 const auto& xyO = other.xy();
462 const auto& zrO = other.zr();
463 const std::array<float, 3> chord{xyO[0] - xyM[0], xyO[1] - xyM[1],
465 std::array<float, 3> calibrated{};
466 for (
const Acts::ConstSpacePointProxy*
sp : {&middle, &other}) {
467 const Acts::OuterStripSpacePointCalibrationDetailsDerived derived =
468 Acts::detail::deriveOuterStripSpacePointCalibrationDetails(
469 sp->outerStripCalibrationDetails());
470 if (!Acts::detail::calibrateOuterStripSpacePoint(
471 chord, derived, calibrated,
487 if (std::abs(middle.zr()[0]) > 1500 and middle.zr()[1] > 100 and
488 middle.zr()[1] < 150) {
497 static constexpr float cotThetaEta120 = 1.5095;
498 static constexpr float cotThetaEta360 = 18.2855;
500 float absCotTheta = std::abs(cotTheta);
501 if (isBottomCandidate && other.zr()[1] <
m_expCutrMin &&
502 absCotTheta > cotThetaEta120 && absCotTheta < cotThetaEta360) {
533 const EventContext& ctx,
534 const std::vector<const xAOD::SpacePointContainer*>& spacePointCollections,
535 const Eigen::Vector3f& beamSpotPos,
float bFieldInZ,
539 gridCfg.bFieldInZ = bFieldInZ;
541 GridType grid(gridCfg,
logger().cloneWithSuffix(
"Grid"));
543 std::size_t totalSpacePoints = 0;
545 totalSpacePoints += spacePoints->size();
548 std::vector<const xAOD::SpacePoint*> selectedXAODSpacePoints;
549 std::vector<float> selectedSpacePointsR;
550 selectedXAODSpacePoints.reserve(totalSpacePoints);
551 selectedSpacePointsR.reserve(totalSpacePoints);
554 std::vector<float> selectedSpacePointsPhi;
555 std::vector<float> selectedSpacePointsAsinD0OverR;
556 const float dPhiCutD0 =
559 selectedSpacePointsPhi.reserve(totalSpacePoints);
560 selectedSpacePointsAsinD0OverR.reserve(totalSpacePoints);
565 float x =
static_cast<float>(
sp->x() - beamSpotPos[0]);
566 float y =
static_cast<float>(
sp->y() - beamSpotPos[1]);
567 float z =
static_cast<float>(
sp->z());
568 float r = std::hypot(
x,
y);
569 float phi = std::atan2(
y,
x);
577 selectedXAODSpacePoints.push_back(
sp);
578 selectedSpacePointsR.push_back(
r);
580 selectedSpacePointsPhi.push_back(
phi);
581 selectedSpacePointsAsinD0OverR.push_back(
582 std::asin(std::min(1.f, dPhiCutD0 / std::max(
r, 1.f))));
587 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
589 grid.at(i), [&](Acts::SpacePointIndex
a, Acts::SpacePointIndex b) {
590 return selectedSpacePointsR[a] < selectedSpacePointsR[b];
594 Acts::SpacePointContainer selectedSpacePoints;
595 selectedSpacePoints.createColumns(
596 Acts::SpacePointColumns::CopiedFromIndex |
597 Acts::SpacePointColumns::PackedXY | Acts::SpacePointColumns::PackedZR |
598 Acts::SpacePointColumns::VarianceZ | Acts::SpacePointColumns::VarianceR);
600 selectedSpacePoints.createColumns(
601 Acts::SpacePointColumns::StripCalibrationDetails);
603 selectedSpacePoints.reserve(grid.numberOfSpacePoints());
604 std::vector<Acts::SpacePointIndexRange> gridSpacePointRanges;
605 gridSpacePointRanges.reserve(grid.numberOfBins());
606 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
607 std::uint32_t begin = selectedSpacePoints.size();
608 for (
const Acts::SpacePointIndex spIndex : grid.at(i)) {
611 auto newSp = selectedSpacePoints.createSpacePoint();
612 newSp.copiedFromIndex() = spIndex;
614 std::array<float, 2>{
static_cast<float>(
sp->x() - beamSpotPos[0]),
615 static_cast<float>(
sp->y() - beamSpotPos[1])};
616 newSp.zr() = std::array<float, 2>{
static_cast<float>(
sp->z()),
617 selectedSpacePointsR[spIndex]};
624 const Eigen::Vector3f innerStripHalfVector =
625 sp->bottomHalfStripLength() *
sp->bottomStripDirection();
626 const Eigen::Vector3f outerStripCenter =
sp->topStripCenter();
627 const Eigen::Vector3f outerStripHalfVector =
628 sp->topHalfStripLength() *
sp->topStripDirection();
629 const Eigen::Vector3f stripSeparation =
sp->stripCenterDistance();
631 newSp.outerStripCalibrationDetails().outerCenter = std::array<float, 3>{
632 outerStripCenter.x() - beamSpotPos[0],
633 outerStripCenter.y() - beamSpotPos[1], outerStripCenter.z()};
634 newSp.outerStripCalibrationDetails().innerToOuterSeparation =
635 std::array<float, 3>{stripSeparation.x(), stripSeparation.y(),
636 stripSeparation.z()};
637 newSp.outerStripCalibrationDetails().outerHalfVector =
638 std::array<float, 3>{outerStripHalfVector.x(),
639 outerStripHalfVector.y(),
640 outerStripHalfVector.z()};
641 newSp.outerStripCalibrationDetails().innerHalfVector =
642 std::array<float, 3>{innerStripHalfVector.x(),
643 innerStripHalfVector.y(),
644 innerStripHalfVector.z()};
647 std::uint32_t end = selectedSpacePoints.size();
648 gridSpacePointRanges.emplace_back(begin, end);
652 selectedSpacePointsR = {};
654 ACTS_VERBOSE(
"Number of space points after selection "
655 << selectedSpacePoints.size() <<
" out of " << totalSpacePoints);
659 const Acts::Range1D<float> rRange = [&]() -> Acts::Range1D<float> {
660 float minRange = std::numeric_limits<float>::max();
661 float maxRange = std::numeric_limits<float>::lowest();
662 for (
const Acts::SpacePointIndexRange& range : gridSpacePointRanges) {
663 if (range.first == range.second) {
666 auto first = selectedSpacePoints[range.first];
667 auto last = selectedSpacePoints[range.second - 1];
668 minRange = std::min(first.zr()[1], minRange);
669 maxRange = std::max(last.zr()[1], maxRange);
671 return {minRange, maxRange};
680 auto doubletSelection =
681 [
this, &selectedSpacePointsPhi, &selectedSpacePointsAsinD0OverR](
682 const Acts::ConstSpacePointProxy& middle,
683 const Acts::ConstSpacePointProxy& other,
float cotTheta,
684 bool isBottomCandidate) {
686 selectedSpacePointsAsinD0OverR, middle,
687 other, cotTheta, isBottomCandidate);
691 bottomDoubletFinderCfg.experimentCuts.connect(doubletSelection);
692 topDoubletFinderCfg.experimentCuts.connect(doubletSelection);
699 for(
const auto* vtx: *inputHoughVtx)
711 auto bottomDoubletFinder =
712 Acts::DoubletSeedFinder::create(Acts::DoubletSeedFinder::DerivedConfig(
713 bottomDoubletFinderCfg, bFieldInZ));
714 auto topDoubletFinder = Acts::DoubletSeedFinder::create(
715 Acts::DoubletSeedFinder::DerivedConfig(topDoubletFinderCfg, bFieldInZ));
716 auto tripletFinder = Acts::TripletSeedFinder::create(
720 const Acts::Range1D<float> rMiddleSpRange(
724 Acts::BroadTripletSeedFilter::State filterState;
725 Acts::BroadTripletSeedFilter::Cache filterCache;
726 Acts::TripletSeeder::Cache cache;
728 Acts::BroadTripletSeedFilter filter(
m_filterCfg, filterState, filterCache,
731 std::vector<Acts::SpacePointContainer::ConstRange> bottomSpRanges;
732 std::optional<Acts::SpacePointContainer::ConstRange> middleSpRange;
733 std::vector<Acts::SpacePointContainer::ConstRange> topSpRanges;
735 Acts::SeedContainer tmpSeedContainer;
737 for (
const auto [bottom, middle, top] : grid.binnedGroup()) {
738 ACTS_VERBOSE(
"Process middle bin " << middle);
739 if (middle >= gridSpacePointRanges.size()) {
740 ATH_MSG_ERROR(
"Grid Binned Group returned an unreasonable middle bin");
741 return StatusCode::FAILURE;
744 bottomSpRanges.clear();
747 std::ranges::transform(
748 bottom, std::back_inserter(bottomSpRanges),
749 [&](std::size_t b) -> Acts::SpacePointContainer::ConstRange {
750 return selectedSpacePoints.range(gridSpacePointRanges[b]).asConst();
753 selectedSpacePoints.range(gridSpacePointRanges[middle]).asConst();
754 std::ranges::transform(
755 top, std::back_inserter(topSpRanges),
756 [&](std::size_t t) -> Acts::SpacePointContainer::ConstRange {
757 return selectedSpacePoints.range(gridSpacePointRanges[t]).asConst();
762 auto firstMiddleSp = middleSpRange->front();
763 auto radiusRangeForMiddle =
766 ACTS_VERBOSE(
"Validity range (radius) for the middle space point is ["
767 << radiusRangeForMiddle.first <<
", "
768 << radiusRangeForMiddle.second <<
"]");
771 cache, *bottomDoubletFinder, *topDoubletFinder, *tripletFinder, filter,
772 selectedSpacePoints, bottomSpRanges, *middleSpRange, topSpRanges,
773 radiusRangeForMiddle, tmpSeedContainer);
779 auto selectionFunction =
780 [&filterState](
const Acts::MutableSeedProxy& seed) ->
bool {
781 float seedQuality = seed.quality();
782 float bottomQuality =
783 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[0]);
784 float middleQuality =
785 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[1]);
787 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[2]);
789 return bottomQuality <= seedQuality || middleQuality <= seedQuality ||
790 topQuality <= seedQuality;
793 seedContainer.
reserve(seedContainer.
size() + tmpSeedContainer.size());
796 for (Acts::MutableSeedProxy seed : tmpSeedContainer) {
802 Acts::ConstSeedProxy(seed), [&](
const Acts::SpacePointIndex spIndex) {
803 const Acts::SpacePointIndex originalIndex =
804 selectedSpacePoints.at(spIndex).copiedFromIndex();
805 return selectedXAODSpacePoints[originalIndex];
809 return StatusCode::SUCCESS;