472 const EventContext& ctx,
473 const std::vector<const xAOD::SpacePointContainer*>& spacePointCollections,
474 const Eigen::Vector3f& beamSpotPos,
float bFieldInZ,
479 gridCfg.bFieldInZ = bFieldInZ;
481 Acts::CylindricalSpacePointGrid grid(gridCfg,
482 logger().cloneWithSuffix(
"Grid"));
484 std::size_t totalSpacePoints = 0;
486 totalSpacePoints += spacePoints->size();
489 std::vector<const xAOD::SpacePoint*> selectedXAODSpacePoints;
490 std::vector<float> selectedSpacePointsR;
491 selectedXAODSpacePoints.reserve(totalSpacePoints);
492 selectedSpacePointsR.reserve(totalSpacePoints);
495 std::vector<float> selectedSpacePointsPhi;
496 std::vector<float> selectedSpacePointsAsinD0OverR;
497 const float dPhiCutD0 =
500 selectedSpacePointsPhi.reserve(totalSpacePoints);
501 selectedSpacePointsAsinD0OverR.reserve(totalSpacePoints);
506 float x =
static_cast<float>(
sp->x() - beamSpotPos[0]);
507 float y =
static_cast<float>(
sp->y() - beamSpotPos[1]);
508 float z =
static_cast<float>(
sp->z());
509 float r = std::hypot(
x,
y);
510 float phi = std::atan2(
y,
x);
516 grid.insert(selectedXAODSpacePoints.size(),
phi,
z,
r);
517 selectedXAODSpacePoints.push_back(
sp);
518 selectedSpacePointsR.push_back(
r);
520 selectedSpacePointsPhi.push_back(
phi);
521 selectedSpacePointsAsinD0OverR.push_back(
522 std::asin(std::min(1.f, dPhiCutD0 / std::max(
r, 1.f))));
527 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
529 grid.at(i), [&](Acts::SpacePointIndex
a, Acts::SpacePointIndex b) {
530 return selectedSpacePointsR[a] < selectedSpacePointsR[b];
534 Acts::SpacePointContainer selectedSpacePoints;
535 selectedSpacePoints.createColumns(
536 Acts::SpacePointColumns::CopiedFromIndex |
537 Acts::SpacePointColumns::PackedXY | Acts::SpacePointColumns::PackedZR |
538 Acts::SpacePointColumns::VarianceZ | Acts::SpacePointColumns::VarianceR);
540 selectedSpacePoints.createColumns(
541 Acts::SpacePointColumns::StripCalibrationDetails);
543 selectedSpacePoints.reserve(grid.numberOfSpacePoints());
544 std::vector<Acts::SpacePointIndexRange> gridSpacePointRanges;
545 gridSpacePointRanges.reserve(grid.numberOfBins());
546 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
547 std::uint32_t begin = selectedSpacePoints.size();
548 for (
const Acts::SpacePointIndex spIndex : grid.at(i)) {
551 auto newSp = selectedSpacePoints.createSpacePoint();
552 newSp.copiedFromIndex() = spIndex;
554 std::array<float, 2>{
static_cast<float>(
sp->x() - beamSpotPos[0]),
555 static_cast<float>(
sp->y() - beamSpotPos[1])};
556 newSp.zr() = std::array<float, 2>{
static_cast<float>(
sp->z()),
557 selectedSpacePointsR[spIndex]};
558 newSp.varianceZ() =
static_cast<float>(
sp->varianceZ());
559 newSp.varianceR() =
static_cast<float>(
sp->varianceR());
562 const Eigen::Vector3f innerStripHalfVector =
563 sp->bottomHalfStripLength() *
sp->bottomStripDirection();
564 const Eigen::Vector3f outerStripCenter =
sp->topStripCenter();
565 const Eigen::Vector3f outerStripHalfVector =
566 sp->topHalfStripLength() *
sp->topStripDirection();
567 const Eigen::Vector3f stripSeparation =
sp->stripCenterDistance();
569 newSp.outerStripCalibrationDetails().outerCenter = std::array<float, 3>{
570 outerStripCenter.x(), outerStripCenter.y(), outerStripCenter.z()};
571 newSp.outerStripCalibrationDetails().innerToOuterSeparation =
572 std::array<float, 3>{stripSeparation.x(), stripSeparation.y(),
573 stripSeparation.z()};
574 newSp.outerStripCalibrationDetails().outerHalfVector =
575 std::array<float, 3>{outerStripHalfVector.x(),
576 outerStripHalfVector.y(),
577 outerStripHalfVector.z()};
578 newSp.outerStripCalibrationDetails().innerHalfVector =
579 std::array<float, 3>{innerStripHalfVector.x(),
580 innerStripHalfVector.y(),
581 innerStripHalfVector.z()};
584 std::uint32_t end = selectedSpacePoints.size();
585 gridSpacePointRanges.emplace_back(begin, end);
589 selectedSpacePointsR = {};
591 ACTS_VERBOSE(
"Number of space points after selection "
592 << selectedSpacePoints.size() <<
" out of " << totalSpacePoints);
596 const Acts::Range1D<float> rRange = [&]() -> Acts::Range1D<float> {
597 float minRange = std::numeric_limits<float>::max();
598 float maxRange = std::numeric_limits<float>::lowest();
599 for (
const Acts::SpacePointIndexRange& range : gridSpacePointRanges) {
600 if (range.first == range.second) {
603 auto first = selectedSpacePoints[range.first];
604 auto last = selectedSpacePoints[range.second - 1];
605 minRange = std::min(first.zr()[1], minRange);
606 maxRange = std::max(last.zr()[1], maxRange);
608 return {minRange, maxRange};
617 auto doubletSelection =
618 [
this, &selectedSpacePointsPhi, &selectedSpacePointsAsinD0OverR](
619 const Acts::ConstSpacePointProxy& middle,
620 const Acts::ConstSpacePointProxy& other,
float cotTheta,
621 bool isBottomCandidate) {
623 selectedSpacePointsAsinD0OverR, middle,
624 other, cotTheta, isBottomCandidate);
627 bottomDoubletFinderCfg.experimentCuts.connect(doubletSelection);
628 topDoubletFinderCfg.experimentCuts.connect(doubletSelection);
635 for(
const auto* vtx: *inputHoughVtx)
647 auto bottomDoubletFinder =
648 Acts::DoubletSeedFinder::create(Acts::DoubletSeedFinder::DerivedConfig(
649 bottomDoubletFinderCfg, bFieldInZ));
650 auto topDoubletFinder = Acts::DoubletSeedFinder::create(
651 Acts::DoubletSeedFinder::DerivedConfig(topDoubletFinderCfg, bFieldInZ));
652 auto tripletFinder = Acts::TripletSeedFinder::create(
656 const Acts::Range1D<float> rMiddleSpRange(
660 Acts::BroadTripletSeedFilter::State filterState;
661 Acts::BroadTripletSeedFilter::Cache filterCache;
662 Acts::TripletSeeder::Cache cache;
664 Acts::BroadTripletSeedFilter filter(
m_filterCfg, filterState, filterCache,
667 std::vector<Acts::SpacePointContainer::ConstRange> bottomSpRanges;
668 std::optional<Acts::SpacePointContainer::ConstRange> middleSpRange;
669 std::vector<Acts::SpacePointContainer::ConstRange> topSpRanges;
671 Acts::SeedContainer tmpSeedContainer;
673 for (
const auto [bottom, middle,
top] : grid.binnedGroup()) {
674 ACTS_VERBOSE(
"Process middle bin " << middle);
675 if (middle >= gridSpacePointRanges.size()) {
676 ATH_MSG_ERROR(
"Grid Binned Group returned an unreasonable middle bin");
677 return StatusCode::FAILURE;
680 bottomSpRanges.clear();
683 std::ranges::transform(
684 bottom, std::back_inserter(bottomSpRanges),
685 [&](std::size_t b) -> Acts::SpacePointContainer::ConstRange {
686 return selectedSpacePoints.range(gridSpacePointRanges[b]).asConst();
689 selectedSpacePoints.range(gridSpacePointRanges[middle]).asConst();
690 std::ranges::transform(
691 top, std::back_inserter(topSpRanges),
692 [&](std::size_t t) -> Acts::SpacePointContainer::ConstRange {
693 return selectedSpacePoints.range(gridSpacePointRanges[t]).asConst();
698 auto firstMiddleSp = middleSpRange->front();
699 auto radiusRangeForMiddle =
702 ACTS_VERBOSE(
"Validity range (radius) for the middle space point is ["
703 << radiusRangeForMiddle.first <<
", "
704 << radiusRangeForMiddle.second <<
"]");
707 cache, *bottomDoubletFinder, *topDoubletFinder, *tripletFinder, filter,
708 selectedSpacePoints, bottomSpRanges, *middleSpRange, topSpRanges,
709 radiusRangeForMiddle, tmpSeedContainer);
715 auto selectionFunction =
716 [&filterState](
const Acts::MutableSeedProxy& seed) ->
bool {
717 float seedQuality = seed.quality();
718 float bottomQuality =
719 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[0]);
720 float middleQuality =
721 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[1]);
723 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[2]);
725 return bottomQuality <= seedQuality || middleQuality <= seedQuality ||
726 topQuality <= seedQuality;
729 seedContainer.
reserve(seedContainer.
size() + tmpSeedContainer.size());
732 for (Acts::MutableSeedProxy seed : tmpSeedContainer) {
738 Acts::ConstSeedProxy(seed), [&](
const Acts::SpacePointIndex spIndex) {
739 const Acts::SpacePointIndex originalIndex =
740 selectedSpacePoints.at(spIndex).copiedFromIndex();
741 return selectedXAODSpacePoints[originalIndex];
745 return StatusCode::SUCCESS;