From 56bc6eb374ea3272c4a92c5c64d228a2f2475ef8 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Mon, 10 Feb 2025 13:15:19 +0100 Subject: [PATCH 1/5] Pointer based truth matching --- .../src/MuonRecoChainTester.cxx | 32 ++++++++----------- .../src/MuonRecoChainTester.h | 5 ++- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx index 941d12bbba4b..63acb94498ae 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx @@ -10,6 +10,7 @@ #include "MuonPRDTest/ParticleVariables.h" #include "FourMomUtils/xAODP4Helpers.h" #include "AthContainers/ConstDataVector.h" +#include "xAODTruth/xAODTruthHelpers.h" #include "StoreGate/ReadHandle.h" using namespace MuonVal; @@ -17,20 +18,7 @@ using namespace MuonPRDTest; namespace { - template <class RefPartType, class SearchPartType> - const SearchPartType* findClosestParticle(const RefPartType* reference, - const DataVector<SearchPartType>& candidateContainer) { - const SearchPartType* best{nullptr}; - for (const SearchPartType* candidate : candidateContainer) { - if (!best || xAOD::P4Helpers::deltaR2(reference, candidate) < - xAOD::P4Helpers::deltaR2(reference, best)) { - best = candidate; - } - } - return best; - } - static const SG::Decorator<int> acc_truthMatched{"truthMatched"}; - + static const SG::Decorator<int> acc_truthMatched{"truthMatched"}; } namespace MuonValR4{ StatusCode MuonRecoChainTester::initialize() { @@ -68,6 +56,11 @@ namespace MuonValR4{ m_tree.addBranch(m_TrksHoughR4); if (m_isMC) { + m_trkTruthLinks.emplace_back(m_legacyTrackKey, "truthParticleLink"); + m_trkTruthLinks.emplace_back(m_TrackKeyHoughR4, "truthParticleLink"); + m_trkTruthLinks.emplace_back(m_TrackKeyR4, "truthParticleLink"); + + m_truthTrks = std::make_shared<IParticleFourMomBranch>(m_tree, "TruthMuons"); m_truthTrks->addVariable<int>("legacyMatched"); m_truthTrks->addVariable<int>("houghMatched"); @@ -75,6 +68,7 @@ namespace MuonValR4{ m_tree.addBranch(m_truthTrks); } + ATH_CHECK(m_trkTruthLinks.initialize()); ATH_CHECK(m_tree.init(this)); return StatusCode::SUCCESS; } @@ -82,14 +76,14 @@ namespace MuonValR4{ const xAOD::TrackParticleContainer& tracks, const SG::Decorator<int>& decRecoMatch, const std::shared_ptr<MuonVal::IParticleFourMomBranch>& trkBranch) const { - constexpr double matchDR = 0.2; - decRecoMatch(*truth) = -1; - const xAOD::TrackParticle* closest = findClosestParticle(truth, tracks); - - if (!closest || xAOD::P4Helpers::deltaR(truth, closest) > matchDR) { + const auto match_itr = std::find_if(tracks.begin(), tracks.end(),[truth](const xAOD::TrackParticle* track){ + return truth == xAOD::TruthHelpers::getTruthParticle(*track); + }); + if (match_itr == tracks.end()) { return; } + const xAOD::TrackParticle* closest{*match_itr}; // Decorate the truth particle index to the reco particle acc_truthMatched(*closest) = static_cast<int>(m_truthTrks->size()); trkBranch->push_back(closest); diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h index 3b876a0be24a..be8332b39eb6 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h @@ -13,6 +13,7 @@ #include "MuonTesterTree/MuonTesterTreeDict.h" #include "StoreGate/ReadHandleKey.h" +#include "StoreGate/ReadDecorHandleKeyArray.h" namespace MuonValR4{ @@ -86,7 +87,9 @@ namespace MuonValR4{ SG::ReadHandleKey<xAOD::TrackParticleContainer> m_TrackKeyR4{this, "TrackKeyR4", "MuonSpectrometerTrackParticlesR4"}; /** @brief Key to the truth particle collection */ - SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthKey{this, "TruthKey", "TruthParticles"}; + SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthKey{this, "TruthKey", "MuonTruthParticles"}; + /** @brief Decoration dependency to the MS truth track links */ + SG::ReadDecorHandleKeyArray<xAOD::TrackParticleContainer> m_trkTruthLinks{this, "TruthTrackLinks", {}}; /** @brief Key to the space point container */ SG::ReadHandleKey<MuonR4::SpacePointContainer> m_spacePointKey{this, "SpacePointContainer", "MuonSpacePoints"}; -- GitLab From 91506072fed110c782a5da00866a0c194f30c7c3 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Sun, 16 Feb 2025 12:07:21 +0100 Subject: [PATCH 2/5] Add Linker branches --- .../src/MuonRecoChainTester.cxx | 69 +++------------ .../src/MuonRecoChainTester.h | 11 --- .../MuonTesterTree/IParticleFourMomBranch.h | 1 + .../MuonTesterTree/LinkerBranch.h | 83 ++++++++++++++++++ .../MuonTesterTree/MuonTesterTreeDict.h | 8 +- .../Root/IParticleFourMomBranch.cxx | 11 ++- .../MuonTesterTree/Root/LinkerBranch.cxx | 84 +++++++++++++++++++ 7 files changed, 195 insertions(+), 72 deletions(-) create mode 100644 MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/LinkerBranch.h create mode 100644 MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx index 63acb94498ae..015371b380b8 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx @@ -4,7 +4,7 @@ // Framework includes #include "MuonRecoChainTester.h" -#include "MuonTesterTree/EventInfoBranch.h" +#include "MuonTesterTree/MuonTesterTreeDict.h" #include "MuonTesterTree/TrackChi2Branch.h" #include "MuonPRDTest/SegmentVariables.h" #include "MuonPRDTest/ParticleVariables.h" @@ -41,15 +41,12 @@ namespace MuonValR4{ m_legacyTrks = std::make_shared<IParticleFourMomBranch>(m_tree, "LegacyMSTrks"); m_legacyTrks->addVariable(std::make_shared<TrackChi2Branch>(*m_legacyTrks)); - m_legacyTrks->addVariable<int>("truthMatched"); m_TrksHoughR4 = std::make_shared<IParticleFourMomBranch>(m_tree, "HoughMSTrks"); m_TrksHoughR4->addVariable(std::make_shared<TrackChi2Branch>(*m_TrksHoughR4)); - m_TrksHoughR4->addVariable<int>("truthMatched"); m_TrksSegmentR4 = std::make_shared<IParticleFourMomBranch>(m_tree, "MSTrksR4"); m_TrksSegmentR4->addVariable(std::make_shared<TrackChi2Branch>(*m_TrksSegmentR4)); - m_TrksSegmentR4->addVariable<int>("truthMatched"); m_tree.addBranch(m_legacyTrks); m_tree.addBranch(m_TrksSegmentR4); @@ -60,36 +57,20 @@ namespace MuonValR4{ m_trkTruthLinks.emplace_back(m_TrackKeyHoughR4, "truthParticleLink"); m_trkTruthLinks.emplace_back(m_TrackKeyR4, "truthParticleLink"); - m_truthTrks = std::make_shared<IParticleFourMomBranch>(m_tree, "TruthMuons"); - m_truthTrks->addVariable<int>("legacyMatched"); - m_truthTrks->addVariable<int>("houghMatched"); - m_truthTrks->addVariable<int>("r4Matched"); - + /// m_legacyTrks->addVariable(std::make_shared<LinkerBranch>(*m_legacyTrks, m_truthTrks, [](const xAOD::IParticle* trk){ + /// return xAOD::TruthHelpers::getTruthParticle(*trk); + /// }, "truthMatched")); + /// m_TrksHoughR4->addBranch(std::make_shared<LinkerBranch>(*m_TrksHoughR4, m_truthTrks, [](const xAOD::IParticle* trk){ + /// return xAOD::TruthHelpers::getTruthParticle(*trk); + /// }, "truthMatched")); + m_tree.addBranch(m_truthTrks); } ATH_CHECK(m_trkTruthLinks.initialize()); ATH_CHECK(m_tree.init(this)); return StatusCode::SUCCESS; } - void MuonRecoChainTester::matchTrackToTruth(const xAOD::TruthParticle* truth, - const xAOD::TrackParticleContainer& tracks, - const SG::Decorator<int>& decRecoMatch, - const std::shared_ptr<MuonVal::IParticleFourMomBranch>& trkBranch) const { - decRecoMatch(*truth) = -1; - const auto match_itr = std::find_if(tracks.begin(), tracks.end(),[truth](const xAOD::TrackParticle* track){ - return truth == xAOD::TruthHelpers::getTruthParticle(*track); - }); - if (match_itr == tracks.end()) { - return; - } - const xAOD::TrackParticle* closest{*match_itr}; - // Decorate the truth particle index to the reco particle - acc_truthMatched(*closest) = static_cast<int>(m_truthTrks->size()); - trkBranch->push_back(closest); - /// Decorate the reco particle index to the truth particle - decRecoMatch(*truth) = trkBranch->find(closest); - } void MuonRecoChainTester::fillBucketsPerStation(const MuonR4::SpacePointContainer& spContainer, const StIdx station, MuonVal::ScalarBranch<uint16_t>& outBranch) const{ @@ -101,11 +82,6 @@ namespace MuonValR4{ StatusCode MuonRecoChainTester::execute() { - const SG::Decorator<int> acc_legacyMatched{"legacyMatched"}; - const SG::Decorator<int> acc_houghMatched{"houghMatched"}; - const SG::Decorator<int> acc_r4Matched{"r4Matched"}; - - const EventContext& ctx{Gaudi::Hive::currentContext()}; SG::ReadHandle legacyTrks{m_legacyTrackKey, ctx}; ATH_CHECK(legacyTrks.isPresent()); @@ -115,15 +91,15 @@ namespace MuonValR4{ ATH_CHECK(trksR4.isPresent()); for (const xAOD::TrackParticle* trk : *legacyTrks) { - acc_truthMatched(*trk) = -1; + m_legacyTrks->push_back(trk); } for (const xAOD::TrackParticle* trk : *trksR4) { - acc_truthMatched(*trk) = -1; + m_TrksSegmentR4->push_back(trk); } for (const xAOD::TrackParticle* trk : *trksFromHoughR4) { - acc_truthMatched(*trk) = -1; - } - + m_TrksHoughR4->push_back(trk); + } + ConstDataVector<xAOD::TruthParticleContainer> truthParts{SG::VIEW_ELEMENTS}; if (!m_truthKey.empty()) { SG::ReadHandle readHandle{m_truthKey, ctx}; @@ -135,27 +111,8 @@ namespace MuonValR4{ } } for (const xAOD::TruthParticle* truth : truthParts) { - matchTrackToTruth(truth, *legacyTrks, acc_legacyMatched, m_legacyTrks); - matchTrackToTruth(truth, *trksFromHoughR4, acc_houghMatched, m_TrksHoughR4); - matchTrackToTruth(truth, *trksR4, acc_r4Matched, m_TrksSegmentR4); - if (truth->eta() > 2. && acc_legacyMatched(*truth) != -1 - && acc_r4Matched(*truth) == -1 ) { - ATH_MSG_VERBOSE("In event "<<ctx.eventID()<<" the new chain is inefficient. eta: " - <<truth->eta()<<", pT: "<<truth->pt() - <<" legacy: "<<acc_legacyMatched(*truth)<<", r4-hough: "<< - acc_houghMatched(*truth)<<", r4 seg: "<<acc_r4Matched(*truth)); - } m_truthTrks->push_back(truth); } - for (const xAOD::TrackParticle* trk : *legacyTrks) { - m_legacyTrks->push_back(trk); - } - for (const xAOD::TrackParticle* trk : *trksR4) { - m_TrksSegmentR4->push_back(trk); - } - for (const xAOD::TrackParticle* trk : *trksFromHoughR4) { - m_TrksHoughR4->push_back(trk); - } /** Fill the bucket summary counts */ SG::ReadHandle spContainer{m_spacePointKey, ctx}; ATH_CHECK(spContainer.isPresent()); diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h index be8332b39eb6..e486b9678fff 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.h @@ -27,17 +27,6 @@ namespace MuonValR4{ virtual StatusCode finalize() override; private: - /** @brief Finds the closest track to the truth particle in terms of dR - * @param truthPart: Pointer to the reference truth particle - * @param tracks: MS-track collection where the closest track shall be searched - * @param decRecoMatch: Decorator to decorate the track particle index in the output tree - * to the truth particle - * @param trkBranch: Track branch collection to save the track particle */ - void matchTrackToTruth(const xAOD::TruthParticle* truthPart, - const xAOD::TrackParticleContainer& tracks, - const SG::Decorator<int>& decRecoMatch, - const std::shared_ptr<MuonVal::IParticleFourMomBranch>& trkBranch) const; - using StIdx = Muon::MuonStationIndex::StIndex; /** @brief Counts how many buckets are in a particular station * @param spContainer: Space point collection diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h index a37f47181c86..02ffd43d67f5 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h @@ -126,6 +126,7 @@ namespace MuonVal { MuonTesterTree& m_parent; std::string m_name; bool m_init{false}; + bool m_filled{true}; VectorBranch<float> m_pt{m_parent.tree(), m_name +"_pt"}; VectorBranch<float> m_eta{m_parent.tree(), m_name + "_eta"}; VectorBranch<float> m_phi{m_parent.tree(), m_name + "_phi"}; diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/LinkerBranch.h b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/LinkerBranch.h new file mode 100644 index 000000000000..ed24d10aa490 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/LinkerBranch.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef MUONTESTER_LINKERBRANCH_H +#define MUONTESTER_LINKERBRANCH_H + +#include <MuonTesterTree/VectorBranch.h> +#include <MuonTesterTree/IParticleFourMomBranch.h> + +namespace MuonVal{ + /** @brief The linker branch is a helper class to establish linking indices + * between dumped particle collections. Once the primary particle is + * added to the collection, the linker branch calls the linker function + * to find the related particle and to add it into it's forseen collection. + * The position where the related particle is saved in the tree, is then + * saved by the linker branch */ + class LinkerBranch : public VectorBranch<unsigned short>, + virtual public IParticleDecorationBranch { + public: + /** @brief Abreviation of the pointer to the particle branch. */ + using ParticleBranch_ptr = std::shared_ptr<IParticleFourMomBranch>; + + /** @brief Typedef of the linker function. The function takes as argument the primary + * particle of interest and shall then return the particle to associate with */ + using Linker_t = std::function<const xAOD::IParticle*(const xAOD::IParticle*)>; + + /** @brief Standard constructor fo the LinkerBranch + * @param parent: Particle branch collection where the linker branch is appended to. + * The primary particle of interest is provided by this collection. + * @param linkColl: Particle branch collection where the linked particle shall be appended + * @param linker: Function to find the linked particle from the primary particle + * @param altName: by default the name is <primaryColl>_linked<Secondary>. + * Parse an alternative name */ + LinkerBranch(IParticleFourMomBranch& parent, + ParticleBranch_ptr linkColl, + Linker_t linker, + const std::string& altName = ""); + /** @brief Use the push back methods of the parent class */ + using VectorBranch<unsigned short>::push_back; + /** @brief Interface methods to handle the particle */ + void push_back(const xAOD::IParticle* p) override; + void push_back(const xAOD::IParticle& p) override; + void operator+=(const xAOD::IParticle* p) override; + void operator+=(const xAOD::IParticle& p) override; + + private: + std::weak_ptr<IParticleFourMomBranch> m_linkColl; + Linker_t m_linkerFunc; + }; + + class BilateralLinkerBranch: public VectorBranch<unsigned short>, + virtual public IParticleDecorationBranch { + public: + using Linker_t = LinkerBranch::Linker_t; + using ParticleBranch_ptr = LinkerBranch::ParticleBranch_ptr; + /** @brief Use the push back methods of the parent class */ + using VectorBranch<unsigned short>::push_back; + /** @brief Interface methods to handle the particle */ + void push_back(const xAOD::IParticle* p) override; + void push_back(const xAOD::IParticle& p) override; + void operator+=(const xAOD::IParticle* p) override; + void operator+=(const xAOD::IParticle& p) override; + + bool fill(const EventContext& ctx) override; + + static bool connectCollections(ParticleBranch_ptr primColl, + ParticleBranch_ptr secondColl, + Linker_t fromPrimToSec, + const std::string& altPrimName ="", + const std::string& altSecName = ""); + private: + BilateralLinkerBranch(IParticleFourMomBranch& bilatColl, + ParticleBranch_ptr primColl, + Linker_t linker, + const std::string& altName); + const IParticleFourMomBranch& m_parent; + std::weak_ptr<IParticleFourMomBranch> m_linkColl; + Linker_t m_linkerFunc; + + + }; +} +#endif \ No newline at end of file diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/MuonTesterTreeDict.h b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/MuonTesterTreeDict.h index 3bbc9b94f656..89d36b143da5 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/MuonTesterTreeDict.h +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/MuonTesterTreeDict.h @@ -1,25 +1,27 @@ /* -Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration */ #ifndef MUONTESTER_MUONTESTERTREEDICT_H #define MUONTESTER_MUONTESTERTREEDICT_H - #include <MuonTesterTree/ArrayBranch.h> #include <MuonTesterTree/AuxElementBranch.h> #include <MuonTesterTree/CoordTransformBranch.h> #include <MuonTesterTree/EventHashBranch.h> +#include <MuonTesterTree/EventIDBranch.h> #include <MuonTesterTree/EventInfoBranch.h> #include <MuonTesterTree/FourVectorBranch.h> #include <MuonTesterTree/IMuonTesterBranch.h> #include <MuonTesterTree/IParticleFourMomBranch.h> #include <MuonTesterTree/IdentifierBranch.h> +#include <MuonTesterTree/LinkerBranch.h> #include <MuonTesterTree/MatrixBranch.h> #include <MuonTesterTree/MuonTesterBranch.h> #include <MuonTesterTree/MuonTesterTree.h> -#include <MuonTesterTree/MuonTesterTreeDict.h> #include <MuonTesterTree/ScalarBranch.h> #include <MuonTesterTree/SetBranch.h> #include <MuonTesterTree/ThreeVectorBranch.h> +#include <MuonTesterTree/TrackChi2Branch.h> #include <MuonTesterTree/TwoVectorBranch.h> #include <MuonTesterTree/VectorBranch.h> #endif + diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx index 8c1d214a4b83..1a1ebbdcd318 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx @@ -33,6 +33,10 @@ namespace MuonVal{ void IParticleFourMomBranch::operator+=(const xAOD::IParticle& p) {push_back(p); } void IParticleFourMomBranch::push_back(const xAOD::IParticle& p) { push_back(&p); } void IParticleFourMomBranch::push_back(const xAOD::IParticle* p) { + if (m_filled) { + m_cached_particles.clear(); + m_filled = false; + } /// Avoid that the particle is added twice to the tree if (!p || find(p) < size()) return; @@ -63,7 +67,10 @@ namespace MuonVal{ return find([p](const xAOD::IParticle* cached) { return p == cached; }); } size_t IParticleFourMomBranch::find(std::function<bool(const xAOD::IParticle*)> func) const { - size_t j = 0; + if (m_filled) { + return dummyIdx; + } + size_t j{0}; for (const xAOD::IParticle* p : m_cached_particles) { if (func(p)) { return j; @@ -82,7 +89,7 @@ namespace MuonVal{ } } m_init = true; - m_cached_particles.clear(); + m_filled = true; return true; } bool IParticleFourMomBranch::initialized() const { diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx new file mode 100644 index 000000000000..5ae790bb64a8 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx @@ -0,0 +1,84 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ +#include <MuonTesterTree/LinkerBranch.h> +#include <format> +namespace MuonVal{ + LinkerBranch::LinkerBranch(IParticleFourMomBranch& parent, + ParticleBranch_ptr linkColl, + Linker_t linker, + const std::string& altName): + VectorBranch<unsigned short>{parent.tree(), + std::format("{:}_{:}Link", parent.name(), altName.empty() ? linkColl->name() : altName)}, + m_linkColl{linkColl}, + m_linkerFunc{linker} {} + + void LinkerBranch::operator+=(const xAOD::IParticle* p) { + push_back(p); + } + void LinkerBranch::operator+=(const xAOD::IParticle& p) { + push_back(p); + } + void LinkerBranch::push_back(const xAOD::IParticle& p) { + push_back(&p); + } + void LinkerBranch::push_back(const xAOD::IParticle* p) { + const xAOD::IParticle* related = m_linkerFunc(p); + if (related) { + ParticleBranch_ptr linkColl = m_linkColl.lock(); + linkColl->push_back(related); + VectorBranch<unsigned short>::push_back(linkColl->find(related)); + } else { + VectorBranch<unsigned short>::push_back(-1); + } + } + + + bool BilateralLinkerBranch::connectCollections(ParticleBranch_ptr primColl, + ParticleBranch_ptr secondColl, + Linker_t fromPrimToSec, + const std::string& altPrimName, + const std::string& altSecName) { + return primColl->addVariable(std::make_unique<LinkerBranch>(*primColl, secondColl, fromPrimToSec, altPrimName)) && + secondColl->addVariable(std::unique_ptr<IParticleDecorationBranch>{new BilateralLinkerBranch(*secondColl, primColl, fromPrimToSec, altSecName)}); + } + + BilateralLinkerBranch::BilateralLinkerBranch(IParticleFourMomBranch& parent, + ParticleBranch_ptr primColl, + Linker_t linker, + const std::string& altName): + VectorBranch<unsigned short>{parent.tree(), + std::format("{:}_{:}Link", parent.name(), altName.empty() ? primColl->name() : altName)}, + m_parent{parent}, + m_linkColl{primColl}, + m_linkerFunc{linker} { + setDefault(-1); + } + + void BilateralLinkerBranch::push_back(const xAOD::IParticle* /* p*/) { + } + void BilateralLinkerBranch::push_back(const xAOD::IParticle& p) { + push_back(&p); + } + void BilateralLinkerBranch::operator+=(const xAOD::IParticle* p){ + push_back(p); + } + void BilateralLinkerBranch::operator+=(const xAOD::IParticle& p){ + push_back(p); + } + bool BilateralLinkerBranch::fill(const EventContext& ctx) { + if (m_parent.size()) { + /** Allocate the memory */ + get(m_parent.size() -1); + ParticleBranch_ptr linkColl = m_linkColl.lock(); + const std::vector<const xAOD::IParticle*>& linkeMe = linkColl->getCached(); + for (std::size_t primToSec = 0 ; primToSec < linkeMe.size(); ++primToSec) { + const size_t linkIdx = m_parent.find(m_linkerFunc(linkeMe[primToSec])); + if (linkIdx < size()) { + get(linkIdx) = primToSec; + } + } + } + return VectorBranch<unsigned short>::fill(ctx); + } +} \ No newline at end of file -- GitLab From e8657bbf73a59b5afbb10a5d4e38c503ac9a805d Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Mon, 17 Feb 2025 08:40:05 +0100 Subject: [PATCH 3/5] Establish back & forth linkin between truth & reco tracks --- .../python/MuonRecoChainTesterConfig.py | 2 +- .../python/PatternTestConfig.py | 6 +++- .../src/MuonRecoChainTester.cxx | 28 +++++++++---------- .../MuonTesterTree/IParticleFourMomBranch.h | 4 +-- .../Root/IParticleFourMomBranch.cxx | 24 +++++++++++----- .../MuonTesterTree/Root/LinkerBranch.cxx | 2 ++ 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/MuonRecoChainTesterConfig.py b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/MuonRecoChainTesterConfig.py index 96c0bcb08b00..ca14bb3b2ffd 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/MuonRecoChainTesterConfig.py +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/MuonRecoChainTesterConfig.py @@ -7,7 +7,7 @@ if __name__=="__main__": parser.set_defaults(nEvents = -1) parser.set_defaults(noMM=True) parser.set_defaults(noSTGC=True) - parser.set_defaults(outRootFile="HoughTransformTester.root") + parser.set_defaults(outRootFile="RecoChainTester.root") # parser.set_defaults(condTag="CONDBR2-BLKPA-2023-03") parser.set_defaults(inputFile=[ "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/MuonGeomRTT/R3SimHits.pool.root" diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py index 518187675b9f..206c1416cea3 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py @@ -165,6 +165,8 @@ def TrackTruthMatchCfg(flags): track_cols = ["MuonTracksR4", "MuonTracksFromHoughR4", "MuonSpectrometerTracks"] track_colstp = ["MuonSpectrometerTrackParticlesR4", "MuonSpectrometerTrackParticlesFromHoughR4", "MuonSpectrometerTrackParticles"] + from MCTruthClassifier.MCTruthClassifierConfig import MCTruthClassifierCfg + for trk in track_cols: result.merge(MuonDetailedTrackTruthMakerCfg(flags, name=f"MuonDetailedTruthTrkMaker{trk}", TrackCollectionNames=[trk])) @@ -176,6 +178,8 @@ def TrackTruthMatchCfg(flags): result.merge(TrackTruthSelectorCfg(flags, tracks=track_cols[i])) result.merge(TrackParticleTruthAlgCfg(flags, tracks=track_cols[i], - TrackParticleName=track_colstp[i])) + TrackParticleName=track_colstp[i], + MCTruthClassifier = result.popToolsAndMerge(MCTruthClassifierCfg(flags, + xAODTruthParticleContainerName="MuonTruthParticles")))) return result diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx index 015371b380b8..0ce3abfde49a 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx @@ -58,13 +58,13 @@ namespace MuonValR4{ m_trkTruthLinks.emplace_back(m_TrackKeyR4, "truthParticleLink"); m_truthTrks = std::make_shared<IParticleFourMomBranch>(m_tree, "TruthMuons"); - /// m_legacyTrks->addVariable(std::make_shared<LinkerBranch>(*m_legacyTrks, m_truthTrks, [](const xAOD::IParticle* trk){ - /// return xAOD::TruthHelpers::getTruthParticle(*trk); - /// }, "truthMatched")); - /// m_TrksHoughR4->addBranch(std::make_shared<LinkerBranch>(*m_TrksHoughR4, m_truthTrks, [](const xAOD::IParticle* trk){ - /// return xAOD::TruthHelpers::getTruthParticle(*trk); - /// }, "truthMatched")); - + BilateralLinkerBranch::connectCollections(m_legacyTrks, m_truthTrks, [](const xAOD::IParticle* trk){ + return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "LegacyMS"); + BilateralLinkerBranch::connectCollections(m_TrksHoughR4, m_truthTrks, [](const xAOD::IParticle* trk){ + return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "HoughR4"); + BilateralLinkerBranch::connectCollections(m_TrksSegmentR4, m_truthTrks, [](const xAOD::IParticle* trk){ + return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "SegmentR4"); + m_tree.addBranch(m_truthTrks); } ATH_CHECK(m_trkTruthLinks.initialize()); @@ -90,28 +90,26 @@ namespace MuonValR4{ SG::ReadHandle trksR4{m_TrackKeyR4, ctx}; ATH_CHECK(trksR4.isPresent()); + ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_legacyTrackKey.fullKey()); for (const xAOD::TrackParticle* trk : *legacyTrks) { m_legacyTrks->push_back(trk); } + ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_TrackKeyR4.fullKey()); for (const xAOD::TrackParticle* trk : *trksR4) { m_TrksSegmentR4->push_back(trk); } + ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_TrackKeyHoughR4.fullKey()); for (const xAOD::TrackParticle* trk : *trksFromHoughR4) { m_TrksHoughR4->push_back(trk); } - ConstDataVector<xAOD::TruthParticleContainer> truthParts{SG::VIEW_ELEMENTS}; if (!m_truthKey.empty()) { SG::ReadHandle readHandle{m_truthKey, ctx}; ATH_CHECK(readHandle.isPresent()); + ATH_MSG_ALWAYS("Fill truth from "<<m_truthKey.fullKey()); for (const xAOD::TruthParticle* truth : *readHandle) { - if (!truth->isMuon()) continue; - if (truth->status() != 1) continue; - truthParts.push_back(truth); - } - } - for (const xAOD::TruthParticle* truth : truthParts) { - m_truthTrks->push_back(truth); + m_truthTrks->push_back(truth); + } } /** Fill the bucket summary counts */ SG::ReadHandle spContainer{m_spacePointKey, ctx}; diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h index 02ffd43d67f5..0676588b7f2c 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/MuonTesterTree/IParticleFourMomBranch.h @@ -124,9 +124,9 @@ namespace MuonVal { private: MuonTesterTree& m_parent; - std::string m_name; + std::string m_name{}; bool m_init{false}; - bool m_filled{true}; + bool m_updated{false}; VectorBranch<float> m_pt{m_parent.tree(), m_name +"_pt"}; VectorBranch<float> m_eta{m_parent.tree(), m_name + "_eta"}; VectorBranch<float> m_phi{m_parent.tree(), m_name + "_phi"}; diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx index 1a1ebbdcd318..db7f634fbca7 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx @@ -25,7 +25,7 @@ namespace MuonVal{ return m_cached_particles; } - size_t IParticleFourMomBranch::size() const { return m_pt.size(); } + size_t IParticleFourMomBranch::size() const { return m_updated ? m_cached_particles.size() : 0; } std::string IParticleFourMomBranch::name() const { return m_name; } const TTree* IParticleFourMomBranch::tree() const { return m_pt.tree(); } TTree* IParticleFourMomBranch::tree() { return m_pt.tree(); } @@ -33,13 +33,16 @@ namespace MuonVal{ void IParticleFourMomBranch::operator+=(const xAOD::IParticle& p) {push_back(p); } void IParticleFourMomBranch::push_back(const xAOD::IParticle& p) { push_back(&p); } void IParticleFourMomBranch::push_back(const xAOD::IParticle* p) { - if (m_filled) { + if (!m_updated) { m_cached_particles.clear(); - m_filled = false; + m_updated = true; } /// Avoid that the particle is added twice to the tree - if (!p || find(p) < size()) + if (!p || find(p) < size()){ + if (p) ATH_MSG_ALWAYS("Rejected particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<". Size: "<<size()); return; + } + m_cached_particles.push_back(p); m_pt.push_back(p->pt() * MeVtoGeV); m_eta.push_back(p->eta()); @@ -51,6 +54,8 @@ namespace MuonVal{ } else if (p->type() == xAOD::Type::ObjectType::TrackParticle){ q = static_cast<const xAOD::TrackParticle*>(p)->charge(); } + ATH_MSG_ALWAYS("New particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<", q: "<<q<<". Size: "<<size()); + m_q.push_back(q); for (const auto& var : m_variables) { var->push_back(p); @@ -64,10 +69,12 @@ namespace MuonVal{ if (!p) { return dummyIdx; } - return find([p](const xAOD::IParticle* cached) { return p == cached; }); + return find([p](const xAOD::IParticle* cached) { + return p == cached; + }); } size_t IParticleFourMomBranch::find(std::function<bool(const xAOD::IParticle*)> func) const { - if (m_filled) { + if (!m_updated) { return dummyIdx; } size_t j{0}; @@ -80,6 +87,9 @@ namespace MuonVal{ return dummyIdx; } bool IParticleFourMomBranch::fill(const EventContext& ctx) { + if (!m_updated) { + m_cached_particles.clear(); + } if (!m_pt.fill(ctx) || !m_eta.fill(ctx) || !m_phi.fill(ctx) || !m_e.fill(ctx) || !m_q.fill(ctx)){ return false; } @@ -89,7 +99,7 @@ namespace MuonVal{ } } m_init = true; - m_filled = true; + m_updated = false; return true; } bool IParticleFourMomBranch::initialized() const { diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx index 5ae790bb64a8..5da56869f459 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx @@ -67,6 +67,8 @@ namespace MuonVal{ push_back(p); } bool BilateralLinkerBranch::fill(const EventContext& ctx) { + ATH_MSG_ALWAYS("Fill "<<name()<<", size: "<<m_parent.size()<<", "<<m_parent.name() + <<", cached: "<<m_parent.getCached().size()); if (m_parent.size()) { /** Allocate the memory */ get(m_parent.size() -1); -- GitLab From ac7d0bc79bdcd0fa4960ddd621a54465f53d9667 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Mon, 17 Feb 2025 09:16:09 +0100 Subject: [PATCH 4/5] Put in verbose messages --- .../MuonPatternRecognitionTest/python/PatternTestConfig.py | 5 +---- .../MuonTesterTree/Root/IParticleFourMomBranch.cxx | 4 ++-- .../MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py index 206c1416cea3..6a7f04aac976 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py @@ -165,7 +165,6 @@ def TrackTruthMatchCfg(flags): track_cols = ["MuonTracksR4", "MuonTracksFromHoughR4", "MuonSpectrometerTracks"] track_colstp = ["MuonSpectrometerTrackParticlesR4", "MuonSpectrometerTrackParticlesFromHoughR4", "MuonSpectrometerTrackParticles"] - from MCTruthClassifier.MCTruthClassifierConfig import MCTruthClassifierCfg for trk in track_cols: result.merge(MuonDetailedTrackTruthMakerCfg(flags, name=f"MuonDetailedTruthTrkMaker{trk}", @@ -178,8 +177,6 @@ def TrackTruthMatchCfg(flags): result.merge(TrackTruthSelectorCfg(flags, tracks=track_cols[i])) result.merge(TrackParticleTruthAlgCfg(flags, tracks=track_cols[i], - TrackParticleName=track_colstp[i], - MCTruthClassifier = result.popToolsAndMerge(MCTruthClassifierCfg(flags, - xAODTruthParticleContainerName="MuonTruthParticles")))) + TrackParticleName=track_colstp[i])) return result diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx index db7f634fbca7..1b52ca847cdf 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/IParticleFourMomBranch.cxx @@ -39,7 +39,7 @@ namespace MuonVal{ } /// Avoid that the particle is added twice to the tree if (!p || find(p) < size()){ - if (p) ATH_MSG_ALWAYS("Rejected particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<". Size: "<<size()); + if (p) ATH_MSG_VERBOSE("Rejected particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<". Size: "<<size()); return; } @@ -54,7 +54,7 @@ namespace MuonVal{ } else if (p->type() == xAOD::Type::ObjectType::TrackParticle){ q = static_cast<const xAOD::TrackParticle*>(p)->charge(); } - ATH_MSG_ALWAYS("New particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<", q: "<<q<<". Size: "<<size()); + ATH_MSG_VERBOSE("New particle ("<<p<<") "<<p->pt()<<", "<<p->eta()<<", "<<p->phi()<<", q: "<<q<<". Size: "<<size()); m_q.push_back(q); for (const auto& var : m_variables) { diff --git a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx index 5da56869f459..66d36426ecb6 100644 --- a/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx +++ b/MuonSpectrometer/MuonValidation/MuonTesterTree/Root/LinkerBranch.cxx @@ -67,8 +67,7 @@ namespace MuonVal{ push_back(p); } bool BilateralLinkerBranch::fill(const EventContext& ctx) { - ATH_MSG_ALWAYS("Fill "<<name()<<", size: "<<m_parent.size()<<", "<<m_parent.name() - <<", cached: "<<m_parent.getCached().size()); + ATH_MSG_VERBOSE("Fill "<<name()<<", size: "<<m_parent.size()<<", "<<m_parent.name()); if (m_parent.size()) { /** Allocate the memory */ get(m_parent.size() -1); -- GitLab From 541015f66d76240fe0464fdd0763c35eaa8f06f5 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Mon, 17 Feb 2025 09:20:46 +0100 Subject: [PATCH 5/5] Another always message --- .../src/MuonRecoChainTester.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx index 0ce3abfde49a..9da44743c5a7 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/src/MuonRecoChainTester.cxx @@ -61,9 +61,9 @@ namespace MuonValR4{ BilateralLinkerBranch::connectCollections(m_legacyTrks, m_truthTrks, [](const xAOD::IParticle* trk){ return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "LegacyMS"); BilateralLinkerBranch::connectCollections(m_TrksHoughR4, m_truthTrks, [](const xAOD::IParticle* trk){ - return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "HoughR4"); + return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "HoughMS"); BilateralLinkerBranch::connectCollections(m_TrksSegmentR4, m_truthTrks, [](const xAOD::IParticle* trk){ - return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "SegmentR4"); + return xAOD::TruthHelpers::getTruthParticle(*trk); }, "truth", "MSTrksR4"); m_tree.addBranch(m_truthTrks); } @@ -90,15 +90,15 @@ namespace MuonValR4{ SG::ReadHandle trksR4{m_TrackKeyR4, ctx}; ATH_CHECK(trksR4.isPresent()); - ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_legacyTrackKey.fullKey()); + ATH_MSG_DEBUG("Fill reconstructed tracks from "<<m_legacyTrackKey.fullKey()); for (const xAOD::TrackParticle* trk : *legacyTrks) { m_legacyTrks->push_back(trk); } - ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_TrackKeyR4.fullKey()); + ATH_MSG_DEBUG("Fill reconstructed tracks from "<<m_TrackKeyR4.fullKey()); for (const xAOD::TrackParticle* trk : *trksR4) { m_TrksSegmentR4->push_back(trk); } - ATH_MSG_ALWAYS("Fill reconstructed tracks from "<<m_TrackKeyHoughR4.fullKey()); + ATH_MSG_DEBUG("Fill reconstructed tracks from "<<m_TrackKeyHoughR4.fullKey()); for (const xAOD::TrackParticle* trk : *trksFromHoughR4) { m_TrksHoughR4->push_back(trk); } @@ -106,7 +106,7 @@ namespace MuonValR4{ if (!m_truthKey.empty()) { SG::ReadHandle readHandle{m_truthKey, ctx}; ATH_CHECK(readHandle.isPresent()); - ATH_MSG_ALWAYS("Fill truth from "<<m_truthKey.fullKey()); + ATH_MSG_DEBUG("Fill truth from "<<m_truthKey.fullKey()); for (const xAOD::TruthParticle* truth : *readHandle) { m_truthTrks->push_back(truth); } -- GitLab