27#include <unordered_map>
31static const SG::AuxElement::ConstAccessor<int> g4TrackIdAcc{
"MuonSim_G4TrkId"};
33constexpr int32_t noTruthLabel() {
return -1; }
34constexpr int32_t noTruthSource() {
return 0; }
35constexpr int32_t g4TruthSource() {
return 2; }
36constexpr int32_t truthParticleSource() {
return 3; }
37constexpr int32_t firstG4PseudoLabel() {
return 2000000; }
45bool operator<(
const G4Key&
a,
const G4Key& b) {
46 if (
a.type !=
b.type)
return a.type <
b.type;
50using G4KeyCounts_t = std::map<G4Key, unsigned int>;
51using LabelSupport_t = std::map<int32_t, unsigned int>;
53struct SegmentTruthLabel {
54 int32_t
id{noTruthLabel()};
55 int32_t source{noTruthSource()};
57 float pt{std::numeric_limits<float>::quiet_NaN()};
58 float eta{std::numeric_limits<float>::quiet_NaN()};
59 float phi{std::numeric_limits<float>::quiet_NaN()};
62 std::vector<int32_t> altIds{};
68 const auto genParticle =
link.cptr();
76 return link.id() > 0 ?
link.id() : 0;
80 G4KeyCounts_t g4Keys{};
83 if (std::abs(simHit.
pdgId()) != 13) {
87 const int hepMcId = simHitHepMcId(simHit);
89 ++g4Keys[G4Key{0, hepMcId}];
92 if (g4TrackIdAcc.isAvailable(simHit)) {
93 const int g4TrackId = g4TrackIdAcc(simHit);
95 ++g4Keys[G4Key{1, g4TrackId}];
102SegmentTruthLabel labelFromSupport(
const LabelSupport_t& support,
103 const unsigned int totalSupport,
104 const int32_t source) {
105 SegmentTruthLabel
label{};
106 if (support.empty()) {
110 std::vector<std::pair<int32_t, unsigned int>> ranked{support.begin(), support.end()};
111 std::sort(ranked.begin(), ranked.end(), [](
const auto&
a,
const auto& b) {
112 if (a.second != b.second) return a.second > b.second;
113 return a.first < b.first;
116 label.id = ranked.front().first;
119 label.weight = totalSupport > 0
120 ?
static_cast<float>(ranked.front().second) /
static_cast<float>(totalSupport)
122 label.ambiguous = ranked.size() > 1 && ranked[0].second == ranked[1].second ? 1 : 0;
123 label.altIds.reserve(ranked.size() > 0 ? ranked.size() - 1 : 0);
124 std::transform(std::next(ranked.begin()), ranked.end(), std::back_inserter(
label.altIds),
125 [](
const auto& entry) { return entry.first; });
129struct LocalSegSorter {
132 if (
a == b)
return false;
133 if (
a->chamberIndex() !=
b->chamberIndex())
134 return a->chamberIndex() <
b->chamberIndex();
135 if (
a->sector() !=
b->sector())
136 return a->sector() <
b->sector();
137 if (
a->etaIndex() !=
b->etaIndex())
138 return a->etaIndex() <
b->etaIndex();
139 using namespace MuonR4::SegmentFit;
160 m_tree.addBranch(std::make_shared<MuonVal::EventHashBranch>(
m_tree.tree()));
162 return StatusCode::SUCCESS;
167 return StatusCode::SUCCESS;
172 using SegmentsPerBucket_t =
174 std::set<const xAOD::MuonSegment*, LocalSegSorter>>;
182 std::map<const xAOD::MuonSegment*, const xAOD::TruthParticle*> directTruth{};
183 std::map<const xAOD::MuonSegment*, G4KeyCounts_t> segmentG4Keys{};
184 std::map<G4Key, unsigned int> g4SegmentMultiplicity{};
185 std::map<G4Key, LabelSupport_t> g4TruthSupport{};
186 std::map<G4Key, int32_t> g4PseudoLabels{};
187 int32_t nextG4PseudoLabel = firstG4PseudoLabel();
191 directTruth.emplace(seg, tp);
197 G4KeyCounts_t g4Keys = collectG4Keys(*seg);
198 for (
const auto& keyCount : g4Keys) {
199 ++g4SegmentMultiplicity[keyCount.first];
202 const int32_t truthIdx =
static_cast<int32_t
>(tp->index());
203 for (
const auto& [key,
count] : g4Keys) {
204 g4TruthSupport[key][truthIdx] +=
count;
207 segmentG4Keys.emplace(seg, std::move(g4Keys));
210 auto hasEnoughG4SegmentSupport = [&](
const G4Key& key) {
212 if (minSegments <= 1) {
215 const auto multItr = g4SegmentMultiplicity.find(key);
216 return multItr != g4SegmentMultiplicity.end() && multItr->second >= minSegments;
219 auto g4PseudoLabel = [&](
const G4Key& key) {
220 auto [itr, inserted] = g4PseudoLabels.try_emplace(key, nextG4PseudoLabel);
228 SegmentTruthLabel
label{};
229 const auto keyItr = segmentG4Keys.find(&segment);
230 if (keyItr == segmentG4Keys.end() || keyItr->second.empty()) {
234 const G4KeyCounts_t& g4Keys = keyItr->second;
235 LabelSupport_t propagatedSupport{};
236 unsigned int totalPropagatedSupport{0};
237 for (
const auto& [key,
count] : g4Keys) {
238 if (!hasEnoughG4SegmentSupport(key)) {
241 const auto supportItr = g4TruthSupport.find(key);
242 if (supportItr == g4TruthSupport.end()) {
245 for (
const auto& [truthIdx, truthCount] : supportItr->second) {
246 const unsigned int support = std::max(
count, truthCount);
247 propagatedSupport[truthIdx] += support;
248 totalPropagatedSupport += support;
251 if (!propagatedSupport.empty()) {
252 return labelFromSupport(propagatedSupport, totalPropagatedSupport, g4TruthSource());
255 G4KeyCounts_t eligibleG4Keys{};
256 for (
const auto& [key,
count] : g4Keys) {
257 if (hasEnoughG4SegmentSupport(key)) {
258 eligibleG4Keys[key] =
count;
261 const auto bestKey = std::max_element(eligibleG4Keys.begin(), eligibleG4Keys.end(),
262 [](
const auto&
a,
const auto& b) {
263 if (a.second != b.second) return a.second < b.second;
264 return b.first < a.first;
266 if (bestKey == eligibleG4Keys.end()) {
270 unsigned int totalKeys{0};
271 for (
const auto& [key,
count] : eligibleG4Keys) {
275 label.id = g4PseudoLabel(bestKey->first);
276 label.source = g4TruthSource();
278 label.weight = totalKeys > 0
279 ?
static_cast<float>(bestKey->second) /
static_cast<float>(totalKeys)
281 label.ambiguous = eligibleG4Keys.size() > 1 ? 1 : 0;
282 for (
const auto& keyCount : eligibleG4Keys) {
283 const G4Key& key = keyCount.first;
284 if (key.type == bestKey->first.type && key.id == bestKey->first.id) {
287 label.altIds.push_back(g4PseudoLabel(key));
298 SegmentsPerBucket_t segPerBucket{};
302 segPerBucket[detSeg->parent()->parentBucket()].insert(seg);
312 const auto it = segPerBucket.find(bucket);
313 m_bucket_segments = (it != segPerBucket.end()) ?
static_cast<uint16_t
>(it->second.size()) : 0;
317 if (it != segPerBucket.end()) {
327 const float segEta =
static_cast<float>(globDir.eta());
328 const float segPhi =
static_cast<float>(globDir.phi());
332 SegmentTruthLabel
label{};
333 const auto truthItr = directTruth.find(seg);
337 label.id =
static_cast<int32_t
>(tp->index());
338 label.source = truthParticleSource();
339 label.pdgId =
static_cast<int32_t
>(tp->
pdgId());
340 label.pt =
static_cast<float>(tp->
pt());
341 label.eta =
static_cast<float>(tp->
eta());
342 label.phi =
static_cast<float>(tp->
phi());
345 label = g4Label(*seg);
357 for (
const int32_t altId :
label.altIds) {
371 return StatusCode::FAILURE;
376 return StatusCode::SUCCESS;
381 std::vector<unsigned int> uniqueLayers;
382 uniqueLayers.reserve(bucket.size());
384 for (
const SpacePointBucket::value_type&
sp : bucket) {
385 const unsigned layNum = sorter.sectorLayerNum(*
sp);
386 if (std::find(uniqueLayers.begin(), uniqueLayers.end(), layNum) == uniqueLayers.end()) {
387 uniqueLayers.push_back(layNum);
390 return static_cast<uint16_t
>(uniqueLayers.size());
#define ATH_CHECK
Evaluate an expression and check for errors.
bool operator<(const DataVector< T > &a, const DataVector< T > &b)
Vector ordering relation.
ATLAS-specific HepMC functions.
Handle class for reading from StoreGate.
a link optimized in size for a GenParticle in a McEventCollection
MuonVal::ThreeVectorBranch m_segmentPos
MuonVal::VectorBranch< int32_t > & m_segmentTruthAltPartOffsets
ActsTrk::GeoContextReadKey_t m_geoCtxKey
MuonVal::VectorBranch< float > & m_segment_numberDoF
SG::ReadDecorHandleKeyArray< xAOD::MuonSegmentContainer > m_truthDecorKeys
Truth decoration (MC).
MuonVal::VectorBranch< float > & m_segmentTruthPhi
MuonVal::VectorBranch< float > & m_segmentTruthEta
SG::ReadHandleKeyArray< SpacePointContainer > m_spacePointKeys
Inputs.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_segmentKeys
MuonVal::VectorBranch< float > & m_segmentTruthPt
MuonVal::VectorBranch< int32_t > & m_segmentTruthSource
MuonVal::ScalarBranch< uint16_t > & m_bucket_spacePoints
StatusCode execute(const EventContext &ctx) override final
Execute method.
MuonVal::MuonTesterTree m_tree
Output tree.
MuonVal::VectorBranch< float > & m_segmentRecoEta
MuonVal::ScalarBranch< uint16_t > & m_bucket_segments
MuonVal::ScalarBranch< uint8_t > & m_bucket_chamberIdx
MuonVal::VectorBranch< int32_t > & m_segmentTruthPDGId
uint16_t countLayersInBucket(const SpacePointBucket &bucket) const
MuonVal::ScalarBranch< uint8_t > & m_bucket_sector
MuonVal::VectorBranch< float > & m_segmentRecoPhi
Gaudi::Property< bool > m_includeG4TrackTruth
Allow the dumper to label otherwise-unmatched reco segments from sim-hit G4/HepMC ids.
StatusCode finalize() override final
MuonVal::VectorBranch< int32_t > & m_segmentTruthAltParts
MuonVal::VectorBranch< uint8_t > & m_segmentHasTruth
MuonVal::VectorBranch< float > & m_segmentTruthLabelWeight
StatusCode initialize() override final
MuonVal::VectorBranch< float > & m_segment_chiSquared
MuonVal::VectorBranch< uint8_t > & m_segmentTruthAmbiguous
MuonVal::VectorBranch< int32_t > & m_segmentTruthIdx
MuonVal::ThreeVectorBranch m_segmentDir
Gaudi::Property< unsigned int > m_minG4TrackTruthSegments
Minimum number of reco segments that must share the same G4/HepMC id.
MuonVal::ScalarBranch< uint16_t > & m_bucket_layers
: The muon space point bucket represents a collection of points that will bre processed together in t...
The SpacePointPerLayerSorter sort two given space points by their layer Identifier.
float numberDoF() const
Returns the numberDoF.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
int pdgId() const
Returns the pdgID of the traversing particle.
const HepMcParticleLink & genParticleLink() const
Returns the link to the HepMC particle producing this hit.
int pdgId() const
PDG ID code.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle.
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
std::string label(const std::string &format, int i)
Eigen::Matrix< double, 3, 1 > Vector3D
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
This header ties the generic definitions in this package.
const xAOD::TruthParticle * getTruthMatchedParticle(const xAOD::MuonSegment &segment)
Returns the particle truth-matched to the segment.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
pointer & link(pointer p) const
Return a reference to the link for an element.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
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".
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
TruthParticle_v1 TruthParticle
Typedef to implementation.
MuonSegment_v1 MuonSegment
Reference the current persistent version: