ATLAS Offline Software
Loading...
Searching...
No Matches
MlMsTrackSeeder.cxx
Go to the documentation of this file.
5#include <algorithm>
6#include <unordered_map>
7#include <set>
8#include <tbb/blocked_range.h>
9#include <tbb/parallel_for.h>
10
11namespace MuonR4 {
12
13MlMsTrackSeeder::MlMsTrackSeeder(const std::string& msgName, Config&& cfg)
14 : AthMessaging{msgName + ".MlMsTrackSeeder"},
15 m_cfg{std::move(cfg)},
16 m_baselineSeeder{msgName + ".BaselineMsTrackSeeder", MsTrackSeeder::Config{m_cfg.baselineSeeder}} {}
17
18std::unique_ptr<MsTrackSeedContainer> MlMsTrackSeeder::findTrackSeeds(const EventContext& ctx,
19 const ActsTrk::GeometryContext& gctx,
20 const xAOD::MuonSegmentContainer& segments) const {
21 SG::AuxElement::ConstAccessor<std::vector<unsigned>> acc{m_cfg.candidateDecoration};
22 std::unordered_map<unsigned, std::vector<const xAOD::MuonSegment*>> groups;
23 groups.reserve(segments.size());
24
25 bool sawDecor = false;
26 for (const xAOD::MuonSegment* seg : segments) {
27 if (!seg || !acc.isAvailable(*seg)) continue;
28 sawDecor = true;
29 for (const unsigned id : acc(*seg)) groups[id].push_back(seg);
30 }
31
32 if (!sawDecor) {
33 ATH_MSG_DEBUG("MlMsTrackSeeder: no ML decoration found on any segment."
34 << (m_cfg.fallbackToBaselineIfUndecorated ? " Falling back to baseline seeder." : " Returning empty seed set."));
35 if (m_cfg.fallbackToBaselineIfUndecorated) return m_baselineSeeder.findTrackSeeds(ctx, gctx, segments);
36 return std::make_unique<MsTrackSeedContainer>();
37 }
38
39 ATH_MSG_DEBUG("MlMsTrackSeeder: " << groups.size() << " ML candidate group(s) from "
40 << segments.size() << " segment(s)");
41
42 auto out = std::make_unique<MsTrackSeedContainer>();
43
44 std::vector<unsigned> orderedIds;
45 orderedIds.reserve(groups.size());
46 for (const auto& [id, _] : groups) orderedIds.push_back(id);
47 std::sort(orderedIds.begin(), orderedIds.end());
48
49 struct CandidateResult {
50 unsigned id{0};
51 std::size_t nSegments{0};
52 std::unique_ptr<MsTrackSeedContainer> seeds{};
53 };
54
55 std::vector<CandidateResult> results(orderedIds.size());
56
57 auto runOneCandidate = [&](std::size_t idx) {
58 const unsigned id = orderedIds[idx];
59 auto& segs = groups[id];
60 std::sort(segs.begin(), segs.end());
61 segs.erase(std::unique(segs.begin(), segs.end()), segs.end());
62 results[idx].id = id;
63 results[idx].nSegments = segs.size();
64
65 if (segs.size() < m_cfg.minSegmentsPerCandidate) {
66 return;
67 }
68
70 for (const xAOD::MuonSegment* seg : segs) {
71 viewCont.push_back(seg);
72 }
73 results[idx].seeds = m_baselineSeeder.findTrackSeeds(ctx, gctx, *viewCont.asDataVector());
74 };
75
76 if (m_cfg.runCandidatesInParallel && orderedIds.size() > 1) {
77 tbb::parallel_for(tbb::blocked_range<std::size_t>(0, orderedIds.size()),
78 [&](const tbb::blocked_range<std::size_t>& range) {
79 for (std::size_t idx = range.begin(); idx != range.end(); ++idx) {
80 runOneCandidate(idx);
81 }
82 });
83 } else {
84 for (std::size_t idx = 0; idx < orderedIds.size(); ++idx) {
85 runOneCandidate(idx);
86 }
87 }
88
89 for (CandidateResult& result : results) {
90 const std::size_t nSeeds = result.seeds ? result.seeds->size() : 0;
91 ATH_MSG_DEBUG(" candidate " << result.id << ": "
92 << result.nSegments << " segment(s) -> "
93 << nSeeds << " seed(s)");
94 if (!result.seeds) continue;
95 for (MsTrackSeed& seed : *result.seeds) {
96 out->push_back(std::move(seed));
97 }
98 }
99
100 // Remove exact duplicates induced by overlapping ML candidate IDs.
101 // This is intentionally pointer-based: if two seeds contain the same segment set,
102 // they will drive the same downstream fit attempt.
103 std::set<std::vector<const xAOD::MuonSegment*>> seen;
104 MsTrackSeedContainer uniqueSeeds{};
105 for (MsTrackSeed& seed : *out) {
106 std::vector<const xAOD::MuonSegment*> key = seed.segments();
107 std::sort(key.begin(), key.end());
108 if (!seen.insert(key).second) continue;
109 uniqueSeeds.push_back(std::move(seed));
110 }
111 *out = std::move(uniqueSeeds);
112
113 ATH_MSG_DEBUG("MlMsTrackSeeder: total seeds produced = " << out->size()
114 << (out->empty() && m_cfg.fallbackToBaselineIfNoCandidates ? " — falling back to baseline seeder" : ""));
115 if (out->empty() && m_cfg.fallbackToBaselineIfNoCandidates) return m_baselineSeeder.findTrackSeeds(ctx, gctx, segments);
116 return out;
117}
118
119} // namespace MuonR4
#define ATH_MSG_DEBUG(x)
Base class for elements of a container that can have aux data.
DataVector adapter that acts like it holds const pointers.
Define macros for attributes used to control the static checker.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
DataVector adapter that acts like it holds const pointers.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const DV * asDataVector() const
Return a pointer to this object, as a const DataVector.
size_type size() const noexcept
Returns the number of elements in the collection.
MlMsTrackSeeder(const std::string &msgName, Config &&cfg)
MsTrackSeeder m_baselineSeeder
const MsTrackSeeder & baselineSeeder() const
std::unique_ptr< MsTrackSeedContainer > findTrackSeeds(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
Helper class to group muon sgements that may belong to a muon trajectory.
This header ties the generic definitions in this package.
std::vector< MsTrackSeed > MsTrackSeedContainer
Definition MsTrackSeed.h:63
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
STL namespace.
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
MuonSegment_v1 MuonSegment
Reference the current persistent version: