492 const EventContext& ctx,
493 const std::vector<const xAOD::SpacePointContainer*>& spacePointCollections,
494 const Eigen::Vector3f& beamSpotPos,
float bFieldInZ,
498 gridCfg.bFieldInZ = bFieldInZ;
500 GridType grid(gridCfg,
logger().cloneWithSuffix(
"Grid"));
502 std::size_t totalSpacePoints = 0;
504 totalSpacePoints += spacePoints->size();
507 std::vector<const xAOD::SpacePoint*> selectedXAODSpacePoints;
508 std::vector<float> selectedSpacePointsR;
509 selectedXAODSpacePoints.reserve(totalSpacePoints);
510 selectedSpacePointsR.reserve(totalSpacePoints);
513 std::vector<float> selectedSpacePointsPhi;
514 std::vector<float> selectedSpacePointsAsinD0OverR;
515 const float dPhiCutD0 =
518 selectedSpacePointsPhi.reserve(totalSpacePoints);
519 selectedSpacePointsAsinD0OverR.reserve(totalSpacePoints);
524 float x =
static_cast<float>(
sp->x() - beamSpotPos[0]);
525 float y =
static_cast<float>(
sp->y() - beamSpotPos[1]);
526 float z =
static_cast<float>(
sp->z());
527 float r = std::hypot(
x,
y);
528 float phi = std::atan2(
y,
x);
536 selectedXAODSpacePoints.push_back(
sp);
537 selectedSpacePointsR.push_back(
r);
539 selectedSpacePointsPhi.push_back(
phi);
540 selectedSpacePointsAsinD0OverR.push_back(
541 std::asin(std::min(1.f, dPhiCutD0 / std::max(
r, 1.f))));
546 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
548 grid.at(i), [&](Acts::SpacePointIndex
a, Acts::SpacePointIndex b) {
549 return selectedSpacePointsR[a] < selectedSpacePointsR[b];
553 Acts::SpacePointContainer selectedSpacePoints;
554 selectedSpacePoints.createColumns(
555 Acts::SpacePointColumns::CopiedFromIndex |
556 Acts::SpacePointColumns::PackedXY | Acts::SpacePointColumns::PackedZR |
557 Acts::SpacePointColumns::VarianceZ | Acts::SpacePointColumns::VarianceR);
559 selectedSpacePoints.createColumns(
560 Acts::SpacePointColumns::StripCalibrationDetails);
562 selectedSpacePoints.reserve(grid.numberOfSpacePoints());
563 std::vector<Acts::SpacePointIndexRange> gridSpacePointRanges;
564 gridSpacePointRanges.reserve(grid.numberOfBins());
565 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
566 std::uint32_t begin = selectedSpacePoints.size();
567 for (
const Acts::SpacePointIndex spIndex : grid.at(i)) {
570 auto newSp = selectedSpacePoints.createSpacePoint();
571 newSp.copiedFromIndex() = spIndex;
573 std::array<float, 2>{
static_cast<float>(
sp->x() - beamSpotPos[0]),
574 static_cast<float>(
sp->y() - beamSpotPos[1])};
575 newSp.zr() = std::array<float, 2>{
static_cast<float>(
sp->z()),
576 selectedSpacePointsR[spIndex]};
577 newSp.varianceZ() =
static_cast<float>(
sp->varianceZ());
578 newSp.varianceR() =
static_cast<float>(
sp->varianceR());
581 const Eigen::Vector3f innerStripHalfVector =
582 sp->bottomHalfStripLength() *
sp->bottomStripDirection();
583 const Eigen::Vector3f outerStripCenter =
sp->topStripCenter();
584 const Eigen::Vector3f outerStripHalfVector =
585 sp->topHalfStripLength() *
sp->topStripDirection();
586 const Eigen::Vector3f stripSeparation =
sp->stripCenterDistance();
588 newSp.outerStripCalibrationDetails().outerCenter = std::array<float, 3>{
589 outerStripCenter.x() - beamSpotPos[0],
590 outerStripCenter.y() - beamSpotPos[1], outerStripCenter.z()};
591 newSp.outerStripCalibrationDetails().innerToOuterSeparation =
592 std::array<float, 3>{stripSeparation.x(), stripSeparation.y(),
593 stripSeparation.z()};
594 newSp.outerStripCalibrationDetails().outerHalfVector =
595 std::array<float, 3>{outerStripHalfVector.x(),
596 outerStripHalfVector.y(),
597 outerStripHalfVector.z()};
598 newSp.outerStripCalibrationDetails().innerHalfVector =
599 std::array<float, 3>{innerStripHalfVector.x(),
600 innerStripHalfVector.y(),
601 innerStripHalfVector.z()};
604 std::uint32_t end = selectedSpacePoints.size();
605 gridSpacePointRanges.emplace_back(begin, end);
609 selectedSpacePointsR = {};
611 ACTS_VERBOSE(
"Number of space points after selection "
612 << selectedSpacePoints.size() <<
" out of " << totalSpacePoints);
616 const Acts::Range1D<float> rRange = [&]() -> Acts::Range1D<float> {
617 float minRange = std::numeric_limits<float>::max();
618 float maxRange = std::numeric_limits<float>::lowest();
619 for (
const Acts::SpacePointIndexRange& range : gridSpacePointRanges) {
620 if (range.first == range.second) {
623 auto first = selectedSpacePoints[range.first];
624 auto last = selectedSpacePoints[range.second - 1];
625 minRange = std::min(first.zr()[1], minRange);
626 maxRange = std::max(last.zr()[1], maxRange);
628 return {minRange, maxRange};
637 auto doubletSelection =
638 [
this, &selectedSpacePointsPhi, &selectedSpacePointsAsinD0OverR](
639 const Acts::ConstSpacePointProxy& middle,
640 const Acts::ConstSpacePointProxy& other,
float cotTheta,
641 bool isBottomCandidate) {
643 selectedSpacePointsAsinD0OverR, middle,
644 other, cotTheta, isBottomCandidate);
647 bottomDoubletFinderCfg.experimentCuts.connect(doubletSelection);
648 topDoubletFinderCfg.experimentCuts.connect(doubletSelection);
655 for(
const auto* vtx: *inputHoughVtx)
667 auto bottomDoubletFinder =
668 Acts::DoubletSeedFinder::create(Acts::DoubletSeedFinder::DerivedConfig(
669 bottomDoubletFinderCfg, bFieldInZ));
670 auto topDoubletFinder = Acts::DoubletSeedFinder::create(
671 Acts::DoubletSeedFinder::DerivedConfig(topDoubletFinderCfg, bFieldInZ));
672 auto tripletFinder = Acts::TripletSeedFinder::create(
676 const Acts::Range1D<float> rMiddleSpRange(
680 Acts::BroadTripletSeedFilter::State filterState;
681 Acts::BroadTripletSeedFilter::Cache filterCache;
682 Acts::TripletSeeder::Cache cache;
684 Acts::BroadTripletSeedFilter filter(
m_filterCfg, filterState, filterCache,
687 std::vector<Acts::SpacePointContainer::ConstRange> bottomSpRanges;
688 std::optional<Acts::SpacePointContainer::ConstRange> middleSpRange;
689 std::vector<Acts::SpacePointContainer::ConstRange> topSpRanges;
691 Acts::SeedContainer tmpSeedContainer;
693 for (
const auto [bottom, middle, top] : grid.binnedGroup()) {
694 ACTS_VERBOSE(
"Process middle bin " << middle);
695 if (middle >= gridSpacePointRanges.size()) {
696 ATH_MSG_ERROR(
"Grid Binned Group returned an unreasonable middle bin");
697 return StatusCode::FAILURE;
700 bottomSpRanges.clear();
703 std::ranges::transform(
704 bottom, std::back_inserter(bottomSpRanges),
705 [&](std::size_t b) -> Acts::SpacePointContainer::ConstRange {
706 return selectedSpacePoints.range(gridSpacePointRanges[b]).asConst();
709 selectedSpacePoints.range(gridSpacePointRanges[middle]).asConst();
710 std::ranges::transform(
711 top, std::back_inserter(topSpRanges),
712 [&](std::size_t t) -> Acts::SpacePointContainer::ConstRange {
713 return selectedSpacePoints.range(gridSpacePointRanges[t]).asConst();
718 auto firstMiddleSp = middleSpRange->front();
719 auto radiusRangeForMiddle =
722 ACTS_VERBOSE(
"Validity range (radius) for the middle space point is ["
723 << radiusRangeForMiddle.first <<
", "
724 << radiusRangeForMiddle.second <<
"]");
727 cache, *bottomDoubletFinder, *topDoubletFinder, *tripletFinder, filter,
728 selectedSpacePoints, bottomSpRanges, *middleSpRange, topSpRanges,
729 radiusRangeForMiddle, tmpSeedContainer);
735 auto selectionFunction =
736 [&filterState](
const Acts::MutableSeedProxy& seed) ->
bool {
737 float seedQuality = seed.quality();
738 float bottomQuality =
739 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[0]);
740 float middleQuality =
741 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[1]);
743 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[2]);
745 return bottomQuality <= seedQuality || middleQuality <= seedQuality ||
746 topQuality <= seedQuality;
749 seedContainer.
reserve(seedContainer.
size() + tmpSeedContainer.size());
752 for (Acts::MutableSeedProxy seed : tmpSeedContainer) {
758 Acts::ConstSeedProxy(seed), [&](
const Acts::SpacePointIndex spIndex) {
759 const Acts::SpacePointIndex originalIndex =
760 selectedSpacePoints.at(spIndex).copiedFromIndex();
761 return selectedXAODSpacePoints[originalIndex];
765 return StatusCode::SUCCESS;