12#include "Acts/Utilities/VectorHelpers.hpp"
13#include "Acts/Utilities/Helpers.hpp"
30 if(tubeNum1 == tubeNum2) {
33 return std::abs(tubeNum1-tubeNum2) < 2;
35 double inDegrees(
double angle) {
36 return angle / Gaudi::Units::deg;
39 using PatternHitVisualInfoVec = std::vector<PatternHitVisualInfo>;
44 void resetVisualToOverlap(PatternHitVisualInfoVec* visualInfo) {
45 if (!visualInfo)
return;
46 const auto [
first, last] = std::ranges::remove_if(*visualInfo, [](
const PatternHitVisualInfo& v){
47 return v.status == PatternHitVisualInfo::PatternStatus::eSuccessful;});
49 visualInfo->erase(first,last);
65 auto visualInfo {
m_cfg.visionTool ? std::make_unique<PatternHitVisualInfoVec>() :
nullptr};
76 for (
const auto& [spc, bucketVec] : pat.bucketsPerContainer) {
77 if (outBuckets.find(spc) == outBuckets.end()) {
78 throw std::runtime_error(
"The space point container associated to the pattern is not present in the output bucket map.");
81 auto& outBucketVec = outBuckets[spc];
82 if (std::ranges::find(outBucketVec, bucket) == outBucketVec.end()) {
83 outBucketVec.push_back(bucket);
90 m_cfg.visionTool->plotPatternBuckets(Gaudi::Hive::currentContext(),
"GlobPatternFinder", std::move(*visualInfo));
102 for (
const auto seedingLayer :
m_cfg.layerSeedings) {
105 for (
const auto& [seedCoords, seed] : orderedSpacepoints) {
109 if (seedLayer != seedingLayer || (seedHit->
isStraw() && !
m_cfg.seedFromMdt)) {
113 auto nExistingPatterns {std::ranges::count_if(
patterns, [&seed, &seedCoords,
this](
const PatternState& pattern){
114 if (std::abs(pattern.theta - seedCoords[thetaIdx]) >
m_cfg.thetaSearchWindow ||
115 pattern.sectorCoord !=
static_cast<int>(seedCoords[sectorIdx])) {
118 return pattern.isInPattern(seed);
120 if (nExistingPatterns >=
m_cfg.maxSeedAttempts) {
121 ATH_MSG_DEBUG(
"The seed hit "<<*seedHit<<
"\n coordinates "<<seedCoords<<
" has already been used to build "<<nExistingPatterns<<
" patterns, which is above the maximum number of attempts allowed to build a pattern from hits already used in existing patterns. Do not use it as seed for a new pattern.");
125 SearchTree_t::range_t selectRange{};
127 selectRange[sectorIdx].shrink(seedCoords[sectorIdx] - 0.1, seedCoords[sectorIdx] + 0.1);
129 const double thetaWindow {(seedLayer == LayerIndex::Inner || seedLayer == LayerIndex::Outer)
130 ?
m_cfg.thetaSearchWindow : 0.5*
m_cfg.thetaSearchWindow};
131 selectRange[thetaIdx].shrink(seedCoords[thetaIdx] - thetaWindow, seedCoords[thetaIdx] + thetaWindow);
133 auto candidateHits = orderedSpacepoints.rangeSearchWithKey(selectRange);
134 if (candidateHits.size() <
m_cfg.minBendingTriggerHits +
m_cfg.minBendingPrecisionHits) {
135 ATH_MSG_VERBOSE(
"Found "<<candidateHits.size()<<
" candidate hits for seed hit "<<*seedHit<<
", coordinates "<<seedCoords
136 <<
". This is below the minimum number of hits required to build a pattern. Do not create a pattern.");
140 if (std::ranges::find_if(candidateHits, [
this, seedLayer](
const auto& c){
141 return m_cfg.idHelperSvc->layerIndex(c.second.hit->identify()) != seedLayer;
142 }) == candidateHits.end()) {
143 ATH_MSG_VERBOSE(
"All candidate hits for seed hit "<<*seedHit<<
", coordinates "<<seedCoords
144 <<
" are in the same layer. We need hits in at least two layers to build a pattern. Do not create a pattern.");
148 std::ranges::sort(candidateHits, [
this](
const auto& c1,
const auto& c2){
158 const auto seedItr {std::ranges::find_if(candidateHits,
159 [&seed](
const auto& c){
return c.second == seed; })};
160 assert(seedItr != candidateHits.end());
162 std::vector<PatternState> activePatterns{};
163 activePatterns.emplace_back(seed,
static_cast<int>(seedCoords[sectorIdx]), seedCoords[thetaIdx]);
165 activePatterns.back().visualInfo = std::make_unique<PatternHitVisualInfo>(seedHit, seedCoords[thetaIdx] - thetaWindow, seedCoords[thetaIdx] + thetaWindow);
172 auto processNewHit = [&](
const TreeNode& testPair){
174 ATH_MSG_VERBOSE(
"** Check compatibility of hit "<<*test.hit<<
", coordinates "<<testPair.first <<
". We start from " << activePatterns.size() <<
" active patterns.");
175 extendPatterns(activePatterns, test, seed, *prevCandidate, visualInfo);
176 prevCandidate = &test;
179 auto ensureOnePattern = [&activePatterns, &visualInfo,
this]() {
180 if (activePatterns.size() > 1) {
181 ATH_MSG_VERBOSE(
"Found "<<activePatterns.size()<<
" patterns during the search. Remove overlaps.");
182 activePatterns =
resolveOverlaps(std::move(activePatterns), visualInfo);
183 resetVisualToOverlap(visualInfo);
184 assert(activePatterns.size() == 1);
187 activePatterns.back().nInsertedHits = 0;
189 ATH_MSG_VERBOSE(
"Search between " << candidateHits.size() <<
" candidates for compatible hits to "<<*seedHit<<
", coordinates: "<<seedCoords);
190 for (
auto it = std::next(seedItr); it != candidateHits.end(); ++it) {
194 activePatterns.back().nInsertedHits = 0;
196 for (
auto it = std::reverse_iterator(seedItr); it != candidateHits.rend(); ++it) {
200 PatternState newPattern {std::move(activePatterns.back())};
209 patterns.push_back(std::move(newPattern));
221 nextPatterns.reserve(activePatterns.size()* 2);
223 const unsigned refMissedLayerHits {std::ranges::min_element(activePatterns,
224 [](
const auto&
a,
const auto& b) {
return a.nMissedLayerHits < b.nMissedLayerHits; }
225 )->nMissedLayerHits};
229 if (pattern.nMissedLayerHits >=
m_cfg.maxMissedLayerHits && (!nextPatterns.empty() || pattern.nMissedLayerHits > refMissedLayerHits)) {
230 ATH_MSG_VERBOSE(
"Pattern " << pattern <<
" has already missed " << pattern.nMissedLayerHits <<
" hits in different layers, which is above the maximum allowed. Do not try to extend it with new hits.");
237 switch (compResult.
result) {
241 ATH_MSG_VERBOSE(
"Hit is compatible, add it to the pattern. Updated pattern: " << pattern);
246 auto isNew = std::ranges::find_if(nextPatterns, [&test](
const PatternState& p) {
247 const HitPayload& lastHit {p.getNthLastHit(1u)};
248 return lastHit == test;
249 }) == nextPatterns.end();
251 ATH_MSG_VERBOSE(
"Hit is compatible & in the same layer of the last added hit. The branched pattern is already in the list of next patterns. Do not add it again.");
256 const HitPayload& lastPatHit {pattern.getNthLastHit(1u)};
258 ATH_MSG_VERBOSE(
"Hit is compatible & in the same layer of the last added hit. Branch the pattern, new pattern: " << newPattern);
260 if (pattern.visualInfo) {
261 pattern.visualInfo->replacedHits.push_back(test.hit);
262 newPattern.
visualInfo->replacedHits.push_back(lastPatHit.
hit);
265 nextPatterns.push_back(std::move(newPattern));
270 if (pattern.visualInfo) {
271 pattern.visualInfo->discardedHits.push_back(test.hit);
274 pattern.nMissedLayerHits++;
279 nextPatterns.push_back(std::move(pattern));
288 if (test.hit->measuresPhi() && pattern.nPhiHits &&
290 ATH_MSG_VERBOSE(
"The pattern with phi = "<<inDegrees(pattern.phi)<<
" is not compatible with the test hit with phi "<<inDegrees(test.phi));
297 auto checkResidualInWindow = [&](
const HitPayload& lastPatHit,
298 const bool isUnique) {
300 const bool useSeed2Beamspot {lastPatHit.
hit == seed.hit ||
301 std::abs( lastPatHit.
Z - seed.Z) <=
m_cfg.minZDiff4Line ||
302 std::abs( lastPatHit.
R - seed.R) <=
m_cfg.minRDiff4Line};
303 const double lineSlope {
computeLineSlope(lastPatHit, seed, useSeed2Beamspot, beamSpot)};
305 const double acceptanceWindow {
computeAcceptanceWindow(test, seed, lastPatHit, lineSlope, useSeed2Beamspot, beamSpot)};
306 ATH_MSG_VERBOSE(
"Check residual in window... Residual: " << testResidual <<
", Acceptance Window: " << acceptanceWindow);
307 if (pattern.visualInfo) {
308 pattern.visualInfo->hitLineInfo[test.hit] = std::make_pair(lineSlope, acceptanceWindow);
310 if (testResidual < acceptanceWindow) {
317 const HitPayload& lastPatHit {pattern.getNthLastHit(1u)};
325 if (test == lastPatHit) {
326 ATH_MSG_VERBOSE(
"The test hit is the same as the last inserted hit. Do not add it to the pattern.");
330 if (areConsecutiveMdt(*test.hit, *lastPatHit.
hit)) {
331 ATH_MSG_VERBOSE(
"The test hit is in the same layer of the last inserted one. They are consecutive MDT hits, so they are compatible.");
335 if (pattern.nInsertedHits == 0) {
336 ATH_MSG_VERBOSE(
"The test hit is in the same layer of the seed. They are not consecutive MDT hits, so they are not compatible.");
343 while (n < pattern.nInsertedHits) {
344 const HitPayload& nthHit {pattern.getNthLastHit(n)};
346 return checkResidualInWindow(nthHit,
false);
351 return checkResidualInWindow(pattern.getNthLastHit(n),
false);
355 return checkResidualInWindow(lastPatHit,
true);
360 const bool useSeed2Beamspot,
363 const double deltaR {(useSeed2Beamspot ? beamSpot.perp() - seed.R : lastPatHit.
R - seed.R) };
364 const double deltaZ {(useSeed2Beamspot ? beamSpot.z() - seed.Z : lastPatHit.
Z - seed.Z)};
365 ATH_MSG_VERBOSE(
"Computing line seed-to-lastPatHit... deltaR = " << lastPatHit.
R - seed.R <<
", deltaZ = " << lastPatHit.
Z - seed.Z
366 <<
", we use" << (useSeed2Beamspot ?
" beamSpot" :
" lastPatHit") <<
" giving " << std::format(
"deltaR_slope: {}, deltaZ_slope: {}",
deltaR, deltaZ)
367 <<
". The line slope is: " <<
deltaR / deltaZ);
373 const double lineSlope)
const {
374 const double signedResidual { testHit.
R - seed.R - lineSlope * (testHit.
Z - seed.Z)};
375 ATH_MSG_VERBOSE(
"Computing residual... slope: " << lineSlope <<
", deltaR_residual: " << (testHit.
R - seed.R) <<
", deltaZ_residual: " << (testHit.
Z - seed.Z) <<
", signed residual: " << signedResidual);
376 return std::abs(signedResidual);
382 const double lineSlope,
383 const bool useSeed2Beamspot,
388 const double geometricalFactor {1.+ Acts::square(lineSlope)};
390 const double& refZ {useSeed2Beamspot ? beamSpot.z() : lastPatHit.
Z};
392 const double alpha {(testHit.
Z-seed.Z) / (refZ - seed.Z)};
393 const double propagationFactor {1. - alpha + Acts::square(alpha)};
394 ATH_MSG_VERBOSE(
"Computing the acceptance window... Geometrical Factor: " << std::sqrt(geometricalFactor) <<
" alpha: " << alpha
395 <<
", Propagation Factor: " << std::sqrt(propagationFactor) <<
", Computed Window: " <<
m_cfg.baseRWindow * std::sqrt(geometricalFactor * propagationFactor));
396 return m_cfg.baseRWindow * std::sqrt(2*geometricalFactor * propagationFactor);
403 outputPatterns.reserve(toResolve.size());
406 const bool overlapInSector {
a.sectorCoord == b.sectorCoord ||
407 (std::abs(
a.sectorCoord - b.sectorCoord) == 1 && std::abs(
a.phi - b.phi) <=
m_cfg.phiTolerance)};
408 return overlapInSector && std::abs(
a.theta - b.theta) <=
m_cfg.thetaSearchWindow;
412 if (
a.nBendingTriggerHits != b.nBendingTriggerHits) {
413 return a.nBendingTriggerHits > b.nBendingTriggerHits;
415 if (
a.nPrecisionHits != b.nPrecisionHits) {
416 return a.nPrecisionHits > b.nPrecisionHits;
418 return a.meanNormResidual2 < b.meanNormResidual2;
420 for (
auto it = toResolve.begin(); it != toResolve.end(); ++it) {
426 for (
auto jt = std::next(it); jt != toResolve.end(); ++jt) {
427 if (jt->isOverlap || !areOverlapping(*it, *jt)) {
430 if (isBetter(*it, *jt)) {
431 jt->isOverlap =
true;
433 it->isOverlap =
true;
437 if (!it->isOverlap) {
438 outputPatterns.push_back( std::move(*it));
444 ATH_MSG_VERBOSE(
"Patterns surviving overlap removal: "<< outputPatterns.size());
445 return outputPatterns;
452 for (
const auto& [spc, bucketVec] : pattern.bucketsPerContainer) {
454 const Amg::Transform3D& localToGlobal {bucket->msSector()->localToGlobalTransform(gctx)};
455 const Amg::Vector3D locY {localToGlobal.linear() * Amg::Vector3D::UnitY()};
456 for (
const auto& hit : *bucket) {
458 if (hit->measuresEta()){
462 const Amg::Vector3D globalPos {localToGlobal * hit->localPosition()};
463 const double globPhi {globalPos.phi()};
468 const double sigmaEta {std::sqrt(hit->covariance()[covIdxEta])};
469 double thetaMin {(globalPos - sigmaEta * locY).
theta()};
470 double thetaMax {(globalPos + sigmaEta * locY).
theta()};
471 if (thetaMax < thetaMin) {
474 if (pattern.theta > thetaMax || pattern.theta < thetaMin) {
475 ATH_MSG_VERBOSE(
"The pattern with theta = "<<inDegrees(pattern.theta)<<
" is not compatible with the test hit theta strip: ["<<inDegrees(thetaMin)<<
", "<<inDegrees(thetaMax)<<
"]");
479 pattern.addHit(
HitPayload{hit.get(),
m_cfg.idHelperSvc->stationIndex(hit->identify()), globPhi}, 0., 0.);
483 pattern.finalizePatternPhi();
491 if (pattern.nPhiHits) {
493 ATH_MSG_VERBOSE(
"The pattern with phi = "<<inDegrees(pattern.phi)<<
" is not compatible with the test hit with phi "<<inDegrees(testPhi));
497 const bool isCompatible {pattern.sector1 == pattern.sector2 ? sectorMap.
insideSector(pattern.sector1, testPhi) :
500 ATH_MSG_VERBOSE(
"The test hit with phi = "<<inDegrees(testPhi)<<
" is not inside the pattern sectors: "<<pattern.sector1<<
" and "<<pattern.sector2);
509 auto& out = hitPerStation[station];
510 out.reserve(hits.size());
511 std::ranges::transform(hits, std::back_inserter(out), [](
const HitPayload&
h){
return h.hit;});
514 pattern.setTheta(cache.
theta);
515 pattern.setPhi(cache.
phi);
517 pattern.setSector(cache.
sector1);
518 pattern.setSecondarySector(cache.
sector2);
522 pattern.setNPhiHits(cache.
nPhiHits);
531 std::transform(cache.begin(), cache.end(), std::back_inserter(
patterns), [
this](
const PatternState& cacheEntry) {
532 GlobalPattern pattern {convertToPattern(cacheEntry)};
542 SearchTree_t::vector_t rawData{};
545 size_t totalHits = 0;
548 totalHits += bucket->size();
552 rawData.reserve(3 * totalHits);
555 ATH_MSG_VERBOSE(
"Adding to the search tree "<<spc->size()<<
" space point buckets");
558 const Amg::Transform3D& localToGlobal {bucket->msSector()->localToGlobalTransform(gctx)};
559 const int sector = bucket->msSector()->sector();
561 for (
const auto& hit : *bucket) {
563 if (!hit->measuresEta() || (!
m_cfg.useMdtHits && hit->isStraw())) {
566 const Amg::Vector3D globalPos {localToGlobal * hit->localPosition()};
567 const double globalTheta {globalPos.theta()};
568 const HitPayload newHit {hit.get(), bucket, spc,
m_cfg.idHelperSvc->stationIndex(hit->identify()),
569 m_spSorter.sectorLayerNum(*hit),globalPos.perp(), globalPos.z(), globalPos.phi()};
573 for (
const auto proj : {SectorProjector::leftOverlap, SectorProjector::center, SectorProjector::rightOverlap}) {
576 if (hit->measuresPhi() && proj != SectorProjector::center &&
582 std::array<double, 2> coords{};
590 <<
"\nwith global position "<<
Amg::toString(globalPos) <<
" and coordinates "<<coords<<
" to the search tree");
591 rawData.emplace_back(std::move(coords), newHit);
596 ATH_MSG_VERBOSE(
"Create a new tree with "<<rawData.size()<<
" entries. ");
604 auto getLayerOrdering = [](
const bool isLayer1Lower) {
623 if (layer1 == layer2) {
625 if (layer1 == LayerIndex::Middle) {
627 return getLayerOrdering(st1 == StIndex::BM);
628 }
else if (layer1 == LayerIndex::Inner) {
630 return getLayerOrdering(hit1.
R < hit2.
R);
632 throw std::runtime_error(
"Unexpected to have two pattern-compatible hits one in BO and the other in EO.");
635 if (layer1 == LayerIndex::Inner || layer2 == LayerIndex::Inner) {
637 return getLayerOrdering(layer1 == LayerIndex::Inner);
639 if (layer1 == LayerIndex::Outer || layer2 == LayerIndex::Outer) {
641 return getLayerOrdering(layer2 == LayerIndex::Outer);
643 if (layer1 == LayerIndex::BarrelExtended || layer2 == LayerIndex::BarrelExtended) {
645 return getLayerOrdering(layer1 == LayerIndex::BarrelExtended);
648 if (layer1 == LayerIndex::Extended) {
649 return getLayerOrdering(st2 == StIndex::EM);
651 return getLayerOrdering(st1 == StIndex::BM);
656 const double seedTheta)
664 const double residual,
665 const double acceptWindow) {
684 if (acceptWindow > 1e-3) {
693 const double newResidual,
694 const double newAcceptWindow) {
696 throw std::runtime_error(std::format(
"Trying to overwrite a hit in station {} with another one from station {}",
stName(oldHit.
station),
stName(newHit.
station)));
703 std::stringstream
ss {
"Trying to overwrite a hit with incompatible type\n"};
706 throw std::runtime_error(
ss.str());
711 throw std::runtime_error(
"Trying to remove a hit from a station that is not in the pattern cache");
714 auto& hitsInThisStation = it->second;
715 auto toRemove = std::ranges::find(hitsInThisStation, oldHit);
716 if (toRemove == hitsInThisStation.end()) {
717 throw std::runtime_error(
"Trying to remove a hit that is not in the pattern cache station hits");
739 for (
const auto& hit : hits) {
742 if (std::ranges::find(bucketVec, hit.bucket) == bucketVec.end()){
743 bucketVec.push_back(hit.bucket);
746 theta += atan2(hit.R, hit.Z);
760 double deltaPhiAcc {0.};
761 std::optional<double> centralPhi {};
763 for (
const auto& hit : hits) {
764 if (!hit.hit->measuresPhi()) {
768 centralPhi = hit.phi;
784 if (
auto it =std::ranges::find_if(*visualInfo, [&pattern](
const auto& v){
785 return v.patternCopy && *v.patternCopy == pattern; }); it != visualInfo->end()) {
790 auto& bucketVec {visualInfo->back().parentBuckets};
792 bucketVec.insert(bucketVec.end(), buckets.begin(), buckets.end());
794 visualInfo->back().patternCopy = std::make_unique<GlobalPattern>(std::move(pattern));
795 visualInfo->back().status = status;
803 std::size_t remaining {n};
806 const size_t nHits {hits.size()};
807 if (remaining <=
nHits) {
808 return hits.at(
nHits - remaining);
818 std::ranges::find(seedStationIt->second, hit) != seedStationIt->second.end();
837 return hit == other.hit;
840 ostr<<
"Pattern state, Expanded Sector: "<<
sectorCoord<<
", Theta: "<<
theta <<
", Phi: "<<
phi;
843 ostr<<
", Hit per station: \n";
846 for (
const auto& hit : hits) {
847 ostr<<
" "<<*hit.hit<<
", R: "<<hit.R<<
", Phi:"<<hit.phi<<
"\n";
Scalar theta() const
theta method
#define ATH_MSG_VERBOSE(x)
static const uint32_t nHits
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
Header file for AthHistogramAlgorithm.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
bool barrel() const
Returns whether the sector is placed in the barrel.
std::vector< const SpacePointContainer * > SpacePointContainerVec
Abrivation for a vector of space-point containers.
LayerOrdering checkLayerOrdering(const HitPayload &hit1, const HitPayload &hit2) const
Method to check the logical layer ordering of two hits.
std::pair< SearchTree_t::coordinate_t, HitPayload > TreeNode
Type alias for a tree node, formed by a hit payload and its indexing coordinates.
@ eRejectHit
Test failed, discard the hit.
@ eBranchPattern
Test successfull with multiple pattern hits in the same logical measurement layer,...
@ eAddHit
Test successfull, add the hit to the pattern.
LineCompatibilityResult checkLineCompatibility(const HitPayload &seed, const HitPayload &test, const PatternState &pattern) const
Method to check the line compatibility of a test hit with a given pattern.
PatternStateVec resolveOverlaps(PatternStateVec &&toResolve, PatternHitVisualInfoVec *visualInfo=nullptr) const
Method to remove overlapping patterns.
std::vector< PatternHitVisualInfo > PatternHitVisualInfoVec
Abrivation for a vector of visual information objects.
SearchTree_t constructTree(const ActsTrk::GeometryContext &gctx, const SpacePointContainerVec &spacepoints) const
Method to construct the search tree by filling it up with spacepoints from the given containers.
void addVisualInfo(const PatternState &candidate, PatternHitVisualInfo::PatternStatus status, PatternHitVisualInfoVec *visualInfo) const
Helper function to add visual information of a given pattern (which is usually going to be destroyed)...
void extendPatterns(PatternStateVec &activePatterns, const HitPayload &test, const HitPayload &seed, const HitPayload &prevCandidate, PatternHitVisualInfoVec *visualInfo=nullptr) const
Function testing pattern compatibility of a set of active patterns (patterns produced from the same s...
Config m_cfg
Global Pattern Recognition configuration.
bool isPhiCompatible(const double testPhi, const PatternState &pattern) const
Method to check the phi compatibility of a test hit with a given pattern.
std::vector< GlobalPattern > PatternVec
Abrivation for a vector of global patterns.
double computeAcceptanceWindow(const HitPayload &testHit, const HitPayload &seed, const HitPayload &lastPatHit, const double lineSlope, const bool useSeed2Beamspot, const Amg::Vector3D &beamSpot) const
Method to compute the acceptance window in global R for a given pattern line and test hit.
Muon::MuonStationIndex::StIndex StIndex
Type alias for the station index.
LayerOrdering
Enum to express the logical measurement layer ordering given two hits.
double computeLineSlope(const HitPayload &lastPatHit, const HitPayload &seed, const bool useSeed2Beamspot, const Amg::Vector3D &beamSpot) const
Helper method to compute the line slope between the seed and the last hit in a given pattern in the R...
void addPhiOnlyHits(const ActsTrk::GeometryContext &gctx, PatternStateVec &patterns) const
Method to add phi-only measurements to existing PatternStates.
GlobalPatternFinder(const std::string &name, Config &&config)
Standard constructor.
std::vector< PatternState > PatternStateVec
PatternVec findPatterns(const ActsTrk::GeometryContext &gctx, const SpacePointContainerVec &spacepoints, BucketPerContainer &outBuckets) const
Main methods steering the pattern finding.
SeedCoords
Abrivation of the seed coordinates.
@ eSector
Expanded sector coordinate of the associated spectrometer sector
SpacePointPerLayerSorter m_spSorter
Spacepoint sorter per logical measurement layer.
GlobalPattern convertToPattern(const PatternState &candidate) const
Method to convert a PatternState into a GlobalPattern object.
std::unordered_map< const SpacePointContainer *, std::vector< const SpacePointBucket * > > BucketPerContainer
Abrivation for a collection of space-point buckets grouped by their corresponding input container.
PatternStateVec findPatternsInEta(const SearchTree_t &orderedSpacepoints, PatternHitVisualInfoVec *visualInfo=nullptr) const
Method steering the building of patterns in eta.
double computeResidual(const HitPayload &testHit, const HitPayload &seed, const double lineSlope) const
Method to compute the residual in globalR given the pattern line and test hit.
Acts::KDTree< 2, HitPayload, double, std::array, 5 > SearchTree_t
Definition of the search tree class.
Muon::MuonStationIndex::LayerIndex LayerIndex
Type alias for the station layer index.
Data class to represent an eta maximum in hough space.
std::unordered_map< StIndex, std::vector< HitType > > HitCollection
Helper class to group muon sgements that may belong to a muon trajectory.
static std::string to_string(const SectorProjector proj)
Print the sector projector.
static int ringSector(const int sector)
Ensure that the parsed sector number is following the MS sector schema 0 is mapped to 16 and 17 is ma...
static int ringOverlap(const int sector)
Maps the sector 33 -> 0 to close the extended MS symmetry ring.
SectorProjector
Enumeration to select the sector projection.
: The muon space point bucket represents a collection of points that will bre processed together in t...
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
bool measuresPhi() const
: Does the space point contain a phi measurement
bool isStraw() const
Returns whether the measurement is a Mdt.
bool measuresEta() const
: Does the space point contain an eta measurement
const Amg::Vector3D & localPosition() const
xAOD::UncalibMeasType type() const
const xAOD::UncalibratedMeasurement * primaryMeasurement() const
const MuonGMR4::SpectrometerSector * msSector() const
double sectorOverlapPhi(int sector1, int sector2) const
returns the phi position of the overlap between the two sectors (which have to be neighboring) in rad...
bool insideSector(int sector, double phi) const
checks whether the phi position is consistent with sector
std::vector< std::string > patterns
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
T wrapToPi(T phi)
Wrap angle in radians to [-pi, pi].
T deltaPhi(T phiA, T phiB)
Return difference phiA - phiB in range [-pi, pi].
double deltaR(double eta1, double eta2, double phi1, double phi2)
MsTrackSeeder::SectorProjector SectorProjector
bool isPrecisionHit(const SpacePoint &hit)
Returns whether the uncalibrated spacepoint is a precision hit (Mdt, micromegas, stgc strips)
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
const std::string & stName(StIndex index)
convert StIndex into a string
LayerIndex toLayerIndex(ChIndex index)
convert ChIndex into LayerIndex
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
MdtDriftCircle_v1 MdtDriftCircle
Helper for azimuthal angle calculations.
Hit information stored during pattern building.
HitPayload(const SpacePoint *hit, const SpacePointBucket *bucket, const SpacePointContainer *container, StIndex station, unsigned layerNum, double R, double Z, double phi)
Full constructor for eta hits.
const SpacePoint * hit
Pointer to the underlying hit.
const SpacePointBucket * bucket
Pointer to the parent bucket.
const SpacePointContainer * container
Pointer to the parent container.
StIndex station
Station index.
unsigned layerNum
Logical layer number in the sector frame.
bool operator==(const HitPayload &other) const
Equal operator: it compares the underlying hit.
: Small struct to encapsulate the checkLineCompatibility result
CompatibilityResult result
Pattern state object storing pattern information during construction.
Acts::CloneablePtr< PatternHitVisualInfo > visualInfo
Pointer to Visual Information for pattern visualization.
double lastResidual
Residual & acceptance window of the last inserted hit (needed when replacing a hit)
void addHit(const HitPayload &hit, const double residual, const double acceptWindow)
Add a hit to the pattern and update the internal state.
BucketPerContainer bucketsPerContainer
Map of spacepoint buckets per spacepoint container associated to the pattern.
double meanNormResidual2
Mean over eta hits of the square of their residual divided by acceptance window.
unsigned nMissedLayerHits
Number of missed candidate hits in different measurement layers during pattern building.
bool isInPattern(const HitPayload &hit) const
Check wheter a hit is present in the pattern.
int sectorCoord
expanded sector coordinate & the two corresponding physical sectors
double theta
Average theta & average phi of the pattern.
std::vector< StIndex > stations
Pattern hit stations to save the filling order.
void print(std::ostream &ostr) const
Print the pattern candidate and stream operator.
unsigned nInsertedHits
Number of inserted hits during one of the two search stages (from seed outward and from seed inward)
void finalizePatternEta()
Finalize the pattern building in eta and update its state.
bool operator==(const PatternState &other) const
Equal operator, it checks the hit-per-station map.
unsigned nBendingTriggerHits
void finalizePatternPhi()
Finalize the pattern building in phi and update its state.
unsigned nPrecisionHits
Counts of precision measurements / non-precision in bending direction / phi measurements.
std::unordered_map< StIndex, std::vector< HitPayload > > hitsPerStation
Map collection of hits per station.
PatternState(const HitPayload &seed, const int sectorCoord, const double seedTheta)
Constructor taking the seed information.
const HitPayload & getNthLastHit(const std::size_t n) const
Get the nth last inserted hit.
void overWriteHit(const HitPayload &oldHit, const HitPayload &newHit, const double newResidual, const double newAcceptWindow)
Overwrite a hit in the pattern and update the internal state.