ATLAS Offline Software
Loading...
Searching...
No Matches
GridTripletSeedingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <cmath>
8#include <cstdint>
9#include <numbers>
10#include <span>
11#include <string_view>
12#include <vector>
13
14namespace ActsTrk {
15
17 const std::string& name,
18 const IInterface* parent)
19 : base_class(type, name, parent) {}
20
22 ATH_MSG_DEBUG("Initializing " << name() << "...");
23
24 ATH_MSG_DEBUG("Properties Summary:");
30
31 ATH_MSG_DEBUG(" * Used by space point grid config:");
32 ATH_MSG_DEBUG(" " << m_minPt);
35 ATH_MSG_DEBUG(" " << m_zMin);
36 ATH_MSG_DEBUG(" " << m_zMax);
44
45 ATH_MSG_DEBUG(" * Used by seed finder config:");
46 ATH_MSG_DEBUG(" " << m_minPt);
49 ATH_MSG_DEBUG(" " << m_zMin);
50 ATH_MSG_DEBUG(" " << m_zMax);
52 ATH_MSG_DEBUG(" " << m_rMax);
67 }
79 } else if (not m_rRangeMiddleSP.empty())
99 }
102 ATH_MSG_DEBUG(" " << m_phiMin);
103 ATH_MSG_DEBUG(" " << m_phiMax);
104 ATH_MSG_DEBUG(" " << m_rMin);
105 ATH_MSG_DEBUG(" " << m_zAlign);
106 ATH_MSG_DEBUG(" " << m_rAlign);
108
109 ATH_MSG_DEBUG(" * Used by seed filter config:");
133 }
140
141 // Make the logger && Propagate to ACTS routines
142 m_logger = makeActsAthenaLogger(this, "Acts");
143
144 // Both edge vectors define the bins of the corresponding grid axis, so n
145 // edges give n-1 bins. Guard against an empty vector before subtracting, the
146 // sizes are unsigned.
147 if (m_zBinEdges.size() < 2 || m_rBinEdges.size() < 2) {
148 ATH_MSG_ERROR("zBinEdges and rBinEdges must each contain at least two "
149 "edges, got "
150 << m_zBinEdges.size() << " and " << m_rBinEdges.size());
151 return StatusCode::FAILURE;
152 }
153 const std::size_t nZBins = m_zBinEdges.size() - 1;
154 const std::size_t nRBins = m_rBinEdges.size() - 1;
155
156 // The neighbour vectors hold one entry per bin and are indexed 0-based by
157 // Acts::GridBinFinder. An empty vector means "one neighbour on each side".
158 auto checkNeighbors = [this](std::string_view name,
159 std::span<const std::pair<int, int>> values,
160 std::size_t nBins) {
161 if (values.empty() || values.size() == nBins) {
162 return true;
163 }
164 ATH_MSG_ERROR("Inconsistent config " << name << ": got " << values.size()
165 << " entries but the grid has "
166 << nBins << " bins");
167 return false;
168 };
169
170 if (!checkNeighbors("zBinNeighborsTop", m_zBinNeighborsTop.value(), nZBins) ||
171 !checkNeighbors("zBinNeighborsBottom", m_zBinNeighborsBottom.value(),
172 nZBins) ||
173 !checkNeighbors("rBinNeighborsTop", m_rBinNeighborsTop.value(), nRBins) ||
174 !checkNeighbors("rBinNeighborsBottom", m_rBinNeighborsBottom.value(),
175 nRBins)) {
176 return StatusCode::FAILURE;
177 }
178
179 // The custom looping vectors are the Acts::BinnedGroup navigation and use
180 // the 1-based local bin numbering of the grid axis: valid entries run from 1
181 // to the number of bins. Bin 0 is the underflow bin, which never holds a
182 // space point, so listing it would silently drop an entry from the loop. A
183 // vector may list a subset of the bins in order to skip the remaining ones,
184 // but must not repeat a bin. An empty vector means all bins in their natural
185 // order.
186 auto checkLooping = [this](std::string_view name,
187 std::span<const std::size_t> bins,
188 std::size_t nBins) {
189 std::vector<bool> visited(nBins + 1, false);
190 for (std::size_t i : bins) {
191 if (i == 0 || i > nBins) {
192 ATH_MSG_ERROR("Inconsistent config "
193 << name << ": bin " << i
194 << " is out of range, the numbering is 1-based and the "
195 "grid has "
196 << nBins << " bins (valid entries are 1.." << nBins
197 << ")");
198 return false;
199 }
200 if (visited[i]) {
201 ATH_MSG_ERROR("Inconsistent config " << name << ": bin " << i
202 << " is listed more than once");
203 return false;
204 }
205 visited[i] = true;
206 }
207 return true;
208 };
209
210 if (!checkLooping("zBinsCustomLooping", m_zBinsCustomLooping.value(),
211 nZBins) ||
212 !checkLooping("rBinsCustomLooping", m_rBinsCustomLooping.value(),
213 nRBins)) {
214 return StatusCode::FAILURE;
215 }
216
217 // rRangeMiddleSP is indexed 0-based by z bin in retrieveRadiusRangeForMiddle,
218 // so it needs exactly one entry per z bin. It is only read when the variable
219 // middle range is disabled.
220 if (!m_useVariableMiddleSPRange && m_rRangeMiddleSP.size() != nZBins) {
221 ATH_MSG_ERROR("Inconsistent config rRangeMiddleSP: got "
222 << m_rRangeMiddleSP.size()
223 << " entries but the grid has " << nZBins << " z bins");
224 return StatusCode::FAILURE;
225 }
226
227 m_gridCfg.minPt = m_minPt;
228 m_gridCfg.rMin = 0;
229 m_gridCfg.rMax = m_gridRMax;
230 m_gridCfg.zMin = m_zMin;
231 m_gridCfg.zMax = m_zMax;
232 m_gridCfg.deltaRMax = m_deltaRMax;
233 m_gridCfg.cotThetaMax = m_cotThetaMax;
234 m_gridCfg.impactMax = m_impactMax;
235 m_gridCfg.phiMin = m_gridPhiMin;
236 m_gridCfg.phiMax = m_gridPhiMax;
237 m_gridCfg.phiBinDeflectionCoverage = m_phiBinDeflectionCoverage;
238 m_gridCfg.maxPhiBins = m_maxPhiBins;
239 m_gridCfg.zBinEdges = m_zBinEdges;
240 m_gridCfg.rBinEdges = m_rBinEdges;
241 m_gridCfg.bFieldInZ = 0; // will be set later
242 m_gridCfg.bottomBinFinder = Acts::GridBinFinder<3ul>(
244 m_rBinNeighborsBottom.value());
245 m_gridCfg.topBinFinder = Acts::GridBinFinder<3ul>(m_numPhiNeighbors.value(),
246 m_zBinNeighborsTop.value(),
247 m_rBinNeighborsTop.value());
248 m_gridCfg.navigation[0ul] = {};
249 m_gridCfg.navigation[1ul] = m_zBinsCustomLooping;
250 m_gridCfg.navigation[2ul] = m_rBinsCustomLooping;
251
252 m_bottomDoubletFinderCfg.spacePointsSortedByRadius = true;
253 m_bottomDoubletFinderCfg.candidateDirection = Acts::Direction::Backward();
264 m_bottomDoubletFinderCfg.helixCutTolerance = 1.;
265 m_topDoubletFinderCfg = m_bottomDoubletFinderCfg; // copy the bottom cuts
266 m_topDoubletFinderCfg.candidateDirection = Acts::Direction::Forward();
269
271 m_tripletFinderCfg.sortedByCotTheta = true;
273 m_tripletFinderCfg.sigmaScattering = m_sigmaScattering;
274 m_tripletFinderCfg.radLengthPerSeed = m_radLengthPerSeed;
276 m_tripletFinderCfg.helixCutTolerance = 1.;
277 m_tripletFinderCfg.toleranceParam = m_toleranceParam;
279 m_filterCfg.deltaInvHelixDiameter = m_deltaInvHelixDiameter;
280 m_filterCfg.deltaRMin = m_deltaRMin;
281 m_filterCfg.compatSeedWeight = m_compatSeedWeight;
282 m_filterCfg.impactWeightFactor = m_impactWeightFactor;
283 m_filterCfg.zOriginWeightFactor = m_zOriginWeightFactor;
284 m_filterCfg.maxSeedsPerSpM = m_maxSeedsPerSpM;
285 m_filterCfg.compatSeedLimit = m_compatSeedLimit;
286 m_filterCfg.seedWeightIncrement = m_seedWeightIncrement;
287 m_filterCfg.numSeedIncrement = m_numSeedIncrement;
288 m_filterCfg.seedConfirmation = m_seedConfirmationInFilter;
289 m_filterCfg.centralSeedConfirmationRange.zMinSeedConf = m_seedConfCentralZMin;
290 m_filterCfg.centralSeedConfirmationRange.zMaxSeedConf = m_seedConfCentralZMax;
291 m_filterCfg.centralSeedConfirmationRange.rMaxSeedConf = m_seedConfCentralRMax;
292 m_filterCfg.centralSeedConfirmationRange.nTopForLargeR =
294 m_filterCfg.centralSeedConfirmationRange.nTopForSmallR =
296 m_filterCfg.centralSeedConfirmationRange.seedConfMinBottomRadius =
298 m_filterCfg.centralSeedConfirmationRange.seedConfMaxZOrigin =
300 m_filterCfg.centralSeedConfirmationRange.minImpactSeedConf =
302 m_filterCfg.forwardSeedConfirmationRange.zMinSeedConf = m_seedConfForwardZMin;
303 m_filterCfg.forwardSeedConfirmationRange.zMaxSeedConf = m_seedConfForwardZMax;
304 m_filterCfg.forwardSeedConfirmationRange.rMaxSeedConf = m_seedConfForwardRMax;
305 m_filterCfg.forwardSeedConfirmationRange.nTopForLargeR =
307 m_filterCfg.forwardSeedConfirmationRange.nTopForSmallR =
309 m_filterCfg.forwardSeedConfirmationRange.seedConfMinBottomRadius =
311 m_filterCfg.forwardSeedConfirmationRange.seedConfMaxZOrigin =
313 m_filterCfg.forwardSeedConfirmationRange.minImpactSeedConf =
315 m_filterCfg.maxSeedsPerSpMConf = m_maxSeedsPerSpMConf;
316 m_filterCfg.maxQualitySeedsPerSpMConf = m_maxQualitySeedsPerSpMConf;
317 m_filterCfg.useDeltaRinsteadOfTopRadius = m_useDeltaRorTopRadius;
318 m_filterCfg.absDeltaEtaWeightFactor = m_absDeltaEtaWeightFactor;
319 m_filterCfg.absDeltaEtaMinImpact = m_absDeltaEtaMinImpact;
320
321 m_finder = Acts::TripletSeeder(logger().cloneWithSuffix("Finder"));
322
323 m_loggerFilter = logger().cloneWithSuffix("Filter");
324
325 ATH_CHECK(detStore()->retrieve(m_pixelId, "PixelID"));
326
327 return StatusCode::SUCCESS;
328}
329
331 const xAOD::SpacePoint* sp, float r) const {
332 float zabs = std::abs(sp->z());
333 float absCotTheta = zabs / r;
334
335 // checking configuration to remove pixel space points
336 Identifier identifier = m_pixelId->wafer_id(sp->elementIdList().at(0));
337 if (m_pixelId->is_barrel(identifier)) {
338 if (zabs > 200 && r < 40)
339 return false;
340
341 return true;
342 }
343
344 // Inner layers
345 // Below 1.20 - accept all
346 static constexpr float cotThetaEta120 = 1.5095;
347 if (absCotTheta < cotThetaEta120)
348 return true;
349
350 // Below 3.40 - remove if too close to beamline
351 static constexpr float cotThetaEta340 = 14.9654;
352 if (absCotTheta < cotThetaEta340 && r < m_expCutrMin)
353 return false;
354
355 // Outer layers
356 // Above 2.20
357 static constexpr float cotThetaEta220 = 4.4571;
358 if (absCotTheta > cotThetaEta220 && r > 260.)
359 return false;
360
361 // Above 2.60
362 static constexpr float cotThetaEta260 = 6.6947;
363 if (absCotTheta > cotThetaEta260 && r > 200.)
364 return false;
365
366 // Above 3.20
367 static constexpr float cotThetaEta320 = 12.2459;
368 if (absCotTheta > cotThetaEta320 && r > 140.)
369 return false;
370
371 // Above 4.00
372 static constexpr float cotThetaEta400 = 27.2899;
373 if (absCotTheta > cotThetaEta400)
374 return false;
375
376 return true;
377}
378
380 const std::vector<float>& spPhi, const std::vector<float>& spAsinD0OverR,
381 const Acts::ConstSpacePointProxy& middle,
382 const Acts::ConstSpacePointProxy& other, float cotTheta,
383 bool isBottomCandidate) const {
384 if (m_doubletDPhiCut) {
385 // per-pair azimuthal-swing bound: the hit azimuth of a track with impact
386 // parameter d0 swings between two radii by asin(d0/rInner) -
387 // asin(d0/rOuter) on top of the curvature rotation. The grid phi-bin
388 // widening only knows the full radial span; this applies the exact
389 // per-pair bound before the doublet enters the triplet stage.
390 // NB: this container only fills the packed coordinate columns, so the
391 // packed accessor zr() must be used here.
392 const float rM = middle.zr()[1];
393 const float rO = other.zr()[1];
394 const float rInner = std::min(rM, rO);
395 const float rOuter = std::max(rM, rO);
396
397 // phi(SP) and asin(d0/r) depend only on the SP (d0 is constant from the
398 // config), so they are computed once per SP in createSeeds and looked up
399 // via copiedFromIndex, avoiding two atan2 and two asin calls per
400 // candidate. asin(d0/r) is monotone in r, so the inner-minus-outer swing
401 // equals the absolute difference of the two per-SP terms.
402 const auto iM = middle.copiedFromIndex();
403 const auto iO = other.copiedFromIndex();
404 float dPhi = spPhi[iO] - spPhi[iM];
405 const float swing = std::abs(spAsinD0OverR[iO] - spAsinD0OverR[iM]);
406 if (dPhi > std::numbers::pi_v<float>) {
407 dPhi -= 2.f * std::numbers::pi_v<float>;
408 } else if (dPhi < -std::numbers::pi_v<float>) {
409 dPhi += 2.f * std::numbers::pi_v<float>;
410 }
411 const float bound = m_doubletDPhiConst +
412 m_doubletDPhiSlope * (rOuter - rInner) +
413 std::min(m_doubletDPhiCap.value(), swing);
414
415 if (std::abs(dPhi) > bound) {
416 return false;
417 }
418 }
419
420 if (!m_useExperimentCuts) {
421 return true;
422 }
423
424 // We remove some doublets that have the middle space point in some specific
425 // areas This should eventually be moved inside ACTS and allow a veto
426 // mechanism according to the user desire. As of now we cannot really do this
427 // since we define a range of validity of the middle candidate, and if we want
428 // to veto some sub-regions inside it, we need to do it here.
429 if (std::abs(middle.zr()[0]) > 1500 and middle.zr()[1] > 100 and
430 middle.zr()[1] < 150) {
431 return false;
432 }
433
434 // We remove here some seeds, in case the bottom space point radius is
435 // too small (i.e. < fastTrackingRMin)
436
437 // This operation is done only within a specific eta window
438 // Instead of eta we use the doublet cottheta
439 static constexpr float cotThetaEta120 = 1.5095;
440 static constexpr float cotThetaEta360 = 18.2855;
441
442 float absCotTheta = std::abs(cotTheta);
443 if (isBottomCandidate && other.zr()[1] < m_expCutrMin &&
444 absCotTheta > cotThetaEta120 && absCotTheta < cotThetaEta360) {
445 return false;
446 }
447
448 return true;
449}
450
452 const Acts::ConstSpacePointProxy& spM,
453 const Acts::Range1D<float>& rMiddleSpRange) const {
455 return {rMiddleSpRange.min(), rMiddleSpRange.max()};
456 }
457 if (m_rRangeMiddleSP.empty()) {
458 throw std::runtime_error(
459 "m_rRangeMiddleSP is empty, please check the configuration.");
460 }
461
462 // get zBin position of the middle SP
463 auto pVal =
464 std::lower_bound(m_zBinEdges.begin(), m_zBinEdges.end(), spM.zr()[0]);
465 int zBin = std::distance(m_zBinEdges.begin(), pVal);
466 // protects against zM at the limit of zBinEdges
467 zBin == 0 ? zBin : --zBin;
468 return {m_rRangeMiddleSP[zBin][0], m_rRangeMiddleSP[zBin][1]};
469}
470
472 const EventContext& ctx,
473 const std::vector<const xAOD::SpacePointContainer*>& spacePointCollections,
474 const Eigen::Vector3f& beamSpotPos, float bFieldInZ,
475 ActsTrk::SeedContainer& seedContainer) const {
476 (void)ctx;
477
478 auto gridCfg = m_gridCfg;
479 gridCfg.bFieldInZ = bFieldInZ;
480
481 Acts::CylindricalSpacePointGrid grid(gridCfg,
482 logger().cloneWithSuffix("Grid"));
483
484 std::size_t totalSpacePoints = 0;
485 for (const xAOD::SpacePointContainer* spacePoints : spacePointCollections) {
486 totalSpacePoints += spacePoints->size();
487 }
488
489 std::vector<const xAOD::SpacePoint*> selectedXAODSpacePoints;
490 std::vector<float> selectedSpacePointsR;
491 selectedXAODSpacePoints.reserve(totalSpacePoints);
492 selectedSpacePointsR.reserve(totalSpacePoints);
493 // Per-SP inputs for the doublet dPhi selection (see
494 // doubletSelectionFunction); only filled when the cut is enabled.
495 std::vector<float> selectedSpacePointsPhi;
496 std::vector<float> selectedSpacePointsAsinD0OverR;
497 const float dPhiCutD0 =
498 m_doubletDPhiD0Max < 0.f ? m_impactMax.value() : m_doubletDPhiD0Max.value();
499 if (m_doubletDPhiCut) {
500 selectedSpacePointsPhi.reserve(totalSpacePoints);
501 selectedSpacePointsAsinD0OverR.reserve(totalSpacePoints);
502 }
503
504 for (const xAOD::SpacePointContainer* spacePoints : spacePointCollections) {
505 for (const xAOD::SpacePoint* sp : *spacePoints) {
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);
511
513 continue;
514 }
515
516 grid.insert(selectedXAODSpacePoints.size(), phi, z, r);
517 selectedXAODSpacePoints.push_back(sp);
518 selectedSpacePointsR.push_back(r);
519 if (m_doubletDPhiCut) {
520 selectedSpacePointsPhi.push_back(phi);
521 selectedSpacePointsAsinD0OverR.push_back(
522 std::asin(std::min(1.f, dPhiCutD0 / std::max(r, 1.f))));
523 }
524 }
525 }
526
527 for (std::size_t i = 0; i < grid.numberOfBins(); ++i) {
528 std::ranges::sort(
529 grid.at(i), [&](Acts::SpacePointIndex a, Acts::SpacePointIndex b) {
530 return selectedSpacePointsR[a] < selectedSpacePointsR[b];
531 });
532 }
533
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);
542 }
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)) {
549 const xAOD::SpacePoint* sp = selectedXAODSpacePoints[spIndex];
550
551 auto newSp = selectedSpacePoints.createSpacePoint();
552 newSp.copiedFromIndex() = spIndex;
553 newSp.xy() =
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());
560
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();
568
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()};
582 }
583 }
584 std::uint32_t end = selectedSpacePoints.size();
585 gridSpacePointRanges.emplace_back(begin, end);
586 }
587
588 // clear temporary
589 selectedSpacePointsR = {};
590
591 ACTS_VERBOSE("Number of space points after selection "
592 << selectedSpacePoints.size() << " out of " << totalSpacePoints);
593
594 // Compute radius range. We rely on the fact the grid is storing the proxies
595 // with a sorting in the radius
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) {
601 continue;
602 }
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);
607 }
608 return {minRange, maxRange};
609 }();
610
611 auto bottomDoubletFinderCfg = m_bottomDoubletFinderCfg;
612 auto topDoubletFinderCfg = m_topDoubletFinderCfg;
613
614 // set up the cache for the doublet selection function, which needs to know the per-SP phi and
615 // asin(d0/r) values for the middle and other SPs. The cache is filled in
616 // createSeeds, and the selection function is connected to the doublet finders below.
617 auto doubletSelection =
618 [this, &selectedSpacePointsPhi, &selectedSpacePointsAsinD0OverR](
619 const Acts::ConstSpacePointProxy& middle,
620 const Acts::ConstSpacePointProxy& other, float cotTheta,
621 bool isBottomCandidate) {
622 return doubletSelectionFunction(selectedSpacePointsPhi,
623 selectedSpacePointsAsinD0OverR, middle,
624 other, cotTheta, isBottomCandidate);
625 };
627 bottomDoubletFinderCfg.experimentCuts.connect(doubletSelection);
628 topDoubletFinderCfg.experimentCuts.connect(doubletSelection);
629 }
630
633 ATH_CHECK(inputHoughVtx.isValid());
634
635 for(const auto* vtx: *inputHoughVtx)
636 {
637 if(vtx->vertexType() == xAOD::VxType::PriVtx)
638 {
639 bottomDoubletFinderCfg.collisionRegionMin = vtx->z() - m_hvCollisionRegionTolerance;
640 bottomDoubletFinderCfg.collisionRegionMax = vtx->z() + m_hvCollisionRegionTolerance;
641 break;
642 }
643 }
644 // in case HoughVtx is not found and inputHoughVtx is empty, keep the original collision region
645 }
646
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(
653 Acts::TripletSeedFinder::DerivedConfig(m_tripletFinderCfg, bFieldInZ));
654
655 // variable middle SP radial region of interest
656 const Acts::Range1D<float> rMiddleSpRange(
657 std::floor(rRange.min() / 2) * 2 + m_deltaRMiddleMinSPRange,
658 std::floor(rRange.max() / 2) * 2 - m_deltaRMiddleMaxSPRange);
659
660 Acts::BroadTripletSeedFilter::State filterState;
661 Acts::BroadTripletSeedFilter::Cache filterCache;
662 Acts::TripletSeeder::Cache cache;
663
664 Acts::BroadTripletSeedFilter filter(m_filterCfg, filterState, filterCache,
666
667 std::vector<Acts::SpacePointContainer::ConstRange> bottomSpRanges;
668 std::optional<Acts::SpacePointContainer::ConstRange> middleSpRange;
669 std::vector<Acts::SpacePointContainer::ConstRange> topSpRanges;
670
671 Acts::SeedContainer tmpSeedContainer;
672
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;
678 }
679
680 bottomSpRanges.clear();
681 topSpRanges.clear();
682
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();
687 });
688 middleSpRange =
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();
694 });
695
696 // we compute this here since all middle space point candidates belong to
697 // the same z-bin
698 auto firstMiddleSp = middleSpRange->front();
699 auto radiusRangeForMiddle =
700 retrieveRadiusRangeForMiddle(firstMiddleSp, rMiddleSpRange);
701
702 ACTS_VERBOSE("Validity range (radius) for the middle space point is ["
703 << radiusRangeForMiddle.first << ", "
704 << radiusRangeForMiddle.second << "]");
705
706 m_finder->createSeedsFromGroups(
707 cache, *bottomDoubletFinder, *topDoubletFinder, *tripletFinder, filter,
708 selectedSpacePoints, bottomSpRanges, *middleSpRange, topSpRanges,
709 radiusRangeForMiddle, tmpSeedContainer);
710 }
711
712 // Selection function - temporary implementation
713 // need change from ACTS for final implementation
714 // To be used only on PPP
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]);
722 float topQuality =
723 filterState.bestSeedQualityMap.at(seed.spacePointIndices()[2]);
724
725 return bottomQuality <= seedQuality || middleQuality <= seedQuality ||
726 topQuality <= seedQuality;
727 };
728
729 seedContainer.reserve(seedContainer.size() + tmpSeedContainer.size());
730
731 // Select and convert the seeds
732 for (Acts::MutableSeedProxy seed : tmpSeedContainer) {
733 if (m_seedQualitySelection && !selectionFunction(seed)) {
734 continue;
735 }
736
737 seedContainer.push_back(
738 Acts::ConstSeedProxy(seed), [&](const Acts::SpacePointIndex spIndex) {
739 const Acts::SpacePointIndex originalIndex =
740 selectedSpacePoints.at(spIndex).copiedFromIndex();
741 return selectedXAODSpacePoints[originalIndex];
742 });
743 }
744
745 return StatusCode::SUCCESS;
746}
747
748} // namespace ActsTrk
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
static Double_t sp
static Double_t a
static const std::vector< std::string > bins
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
@ top
#define y
#define x
#define z
bool spacePointSelectionFunction(const xAOD::SpacePoint *sp, float r) const
Acts::TripletSeedFinder::Config m_tripletFinderCfg
Gaudi::Property< bool > m_useDeltaRorTopRadius
Gaudi::Property< bool > m_seedQualitySelection
Gaudi::Property< float > m_seedConfForwardMinImpact
Acts::DoubletSeedFinder::Config m_bottomDoubletFinderCfg
Gaudi::Property< std::vector< std::pair< int, int > > > m_rBinNeighborsTop
Gaudi::Property< float > m_impactWeightFactor
Acts::DoubletSeedFinder::Config m_topDoubletFinderCfg
Gaudi::Property< float > m_collisionRegionMax
Gaudi::Property< float > m_seedConfCentralMinBottomRadius
std::optional< Acts::TripletSeeder > m_finder
Gaudi::Property< int > m_phiBinDeflectionCoverage
Gaudi::Property< float > m_zOriginWeightFactor
Gaudi::Property< std::size_t > m_maxSeedsPerSpMConf
Gaudi::Property< float > m_maxPtScattering
Gaudi::Property< bool > m_useVariableMiddleSPRange
Gaudi::Property< float > m_toleranceParam
Gaudi::Property< float > m_maxStripDeltaCotTheta
StatusCode createSeeds(const EventContext &ctx, const std::vector< const xAOD::SpacePointContainer * > &spacePointCollections, const Eigen::Vector3f &beamSpotPos, float bFieldInZ, ActsTrk::SeedContainer &seedContainer) const override
Gaudi::Property< float > m_deltaRMaxBottomSP
Gaudi::Property< float > m_seedConfForwardMinBottomRadius
Gaudi::Property< float > m_compatSeedWeight
Gaudi::Property< std::vector< std::vector< double > > > m_rRangeMiddleSP
Gaudi::Property< float > m_deltaRMinTopSP
Gaudi::Property< float > m_seedConfForwardZMin
Gaudi::Property< float > m_doubletDPhiSlope
Acts::BroadTripletSeedFilter::Config m_filterCfg
Gaudi::Property< std::vector< std::pair< int, int > > > m_rBinNeighborsBottom
Gaudi::Property< bool > m_useDetailedDoubleMeasurementInfo
Gaudi::Property< std::vector< std::pair< int, int > > > m_zBinNeighborsBottom
Gaudi::Property< float > m_gridPhiMin
std::pair< float, float > retrieveRadiusRangeForMiddle(const Acts::ConstSpacePointProxy &spM, const Acts::Range1D< float > &rMiddleSpRange) const
Gaudi::Property< bool > m_interactionPointCut
Gaudi::Property< size_t > m_seedConfCentralNTopSmallR
Gaudi::Property< std::vector< float > > m_rBinEdges
Gaudi::Property< float > m_seedConfForwardRMax
Gaudi::Property< float > m_doubletDPhiCap
Gaudi::Property< float > m_deltaRMiddleMaxSPRange
GridTripletSeedingTool(const std::string &type, const std::string &name, const IInterface *parent)
Gaudi::Property< bool > m_useHVCollisionRegion
Acts::CylindricalSpacePointGrid::Config m_gridCfg
Gaudi::Property< std::vector< std::pair< int, int > > > m_zBinNeighborsTop
Gaudi::Property< float > m_deltaInvHelixDiameter
Gaudi::Property< float > m_collisionRegionMin
Gaudi::Property< float > m_seedConfCentralMaxZOrigin
Gaudi::Property< float > m_seedConfCentralMinImpact
Gaudi::Property< std::size_t > m_maxQualitySeedsPerSpMConf
Gaudi::Property< float > m_gridPhiMax
Gaudi::Property< std::vector< float > > m_zBinEdges
Gaudi::Property< bool > m_seedConfirmation
Gaudi::Property< float > m_seedConfForwardMaxZOrigin
Gaudi::Property< float > m_hvCollisionRegionTolerance
Gaudi::Property< float > m_doubletDPhiD0Max
Gaudi::Property< float > m_seedWeightIncrement
Gaudi::Property< float > m_radLengthPerSeed
Gaudi::Property< float > m_absDeltaEtaMinImpact
Gaudi::Property< float > m_absDeltaEtaWeightFactor
Gaudi::Property< float > m_cotThetaMax
Gaudi::Property< float > m_deltaRMinBottomSP
Gaudi::Property< size_t > m_seedConfCentralNTopLargeR
virtual StatusCode initialize() override
Gaudi::Property< float > m_deltaRMiddleMinSPRange
Gaudi::Property< float > m_seedConfForwardZMax
Gaudi::Property< bool > m_seedConfirmationInFilter
Gaudi::Property< std::vector< std::size_t > > m_rBinsCustomLooping
const Acts::Logger & logger() const
Private access to the logger.
Gaudi::Property< float > m_seedConfCentralRMax
std::unique_ptr< const Acts::Logger > m_logger
logging instance
Gaudi::Property< float > m_sigmaScattering
std::unique_ptr< const Acts::Logger > m_loggerFilter
Gaudi::Property< std::vector< size_t > > m_zBinsCustomLooping
Gaudi::Property< float > m_seedConfCentralZMax
bool doubletSelectionFunction(const std::vector< float > &spPhi, const std::vector< float > &spAsinD0OverR, const Acts::ConstSpacePointProxy &middle, const Acts::ConstSpacePointProxy &other, float cotTheta, bool isBottomCandidate) const
doublet selection which caches per SP phi and asin(d0/r) values for the middle and other SPs
Gaudi::Property< float > m_deltaRMaxTopSP
Gaudi::Property< std::size_t > m_compatSeedLimit
Gaudi::Property< size_t > m_seedConfForwardNTopSmallR
SG::ReadHandleKey< xAOD::VertexContainer > m_inputHoughVtxKey
Gaudi::Property< float > m_seedConfCentralZMin
Gaudi::Property< bool > m_useExperimentCuts
Gaudi::Property< float > m_numSeedIncrement
Gaudi::Property< float > m_doubletDPhiConst
Gaudi::Property< size_t > m_seedConfForwardNTopLargeR
virtual bool isValid() override final
Can the handle be successfully dereferenced?
int r
Definition globals.cxx:22
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
@ PriVtx
Primary vertex.
SpacePointContainer_v1 SpacePointContainer
Define the version of the space point container.
Seed push_back(SpacePointRange spacePoints, float quality, float vertexZ)
void reserve(std::size_t size, float averageSpacePoints=3) noexcept
std::size_t size() const noexcept