ATLAS Offline Software
Loading...
Searching...
No Matches
MsTrackTester.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#include "MsTrackTester.h"
5
15
18#include "ActsInterop/Logger.h"
19
20#include "Acts/Definitions/Units.hpp"
21#include "Acts/Surfaces/PlaneSurface.hpp"
22#include "Acts/Utilities/Helpers.hpp"
24
25#include <format>
26
27using namespace MuonVal;
28using namespace MuonPRDTest;
29using namespace MuonR4;
30using namespace Acts::UnitLiterals;
31
32namespace {
33 constexpr double MeVtoGeV = 1.e-3;
34 constexpr double toDeg(const double rad) {
35 return rad / 1._degree;
36 }
37 using Location = MsTrackSeed::Location;
38
39 const MuonR4::MuonTag* findTagMatchingToId(const xAOD::TrackParticle& idTrack,
41 const EventContext& ctx) {
42 const MuonR4::MuonTagContainer* muTagCont{nullptr};
43 if(!SG::get(muTagCont, key, ctx).isSuccess()){
44 THROW_EXCEPTION("Failed to retrieve "<<key.fullKey());
45 }
46 if (!muTagCont) {
47 return nullptr;
48 }
49 for (const MuonR4::MuonTag* muTag : *muTagCont) {
50 if (muTag->idTrack() == &idTrack){
51 return muTag;
52 }
53 }
54 return nullptr;
55 }
56
57 bool isOnCaloExit(const Acts::Surface& surf) {
58 return surf.geometryId().volume() == ActsTrk::detail::GeoVolIds::s_caloEnvelopeID;
59 }
60
61 bool isOnCaloExit(const Acts::BoundTrackParameters& pars) {
62 return isOnCaloExit(pars.referenceSurface());
63 }
64
65}
66
67namespace MuonValR4 {
68 std::optional<MsTrackSeed> MsTrackTester::makeSeedFromTruth(const Acts::GeometryContext& tgContext,
69 const xAOD::TruthParticle& truthMuon) const {
70 std::vector<const xAOD::MuonSegment*> matchedSegs = MuonR4::getTruthSegments(truthMuon);
71 if (matchedSegs.empty() || toLayerIndex(matchedSegs.front()->chamberIndex()) == toLayerIndex(matchedSegs.back()->chamberIndex())) {
72 return std::nullopt;
73 }
74 ExpandedSector sector{matchedSegs[0]->position().phi()};
76 MsTrackSeed barrelSeed{Location::Barrel, sector};
77 MsTrackSeed endcapSeed{Location::Endcap, sector};
78 for (const xAOD::MuonSegment* seg : matchedSegs) {
79 barrelSeed.addSegment(seg);
80 endcapSeed.addSegment(seg);
81 }
82 barrelSeed.setPosition(matchedSegs[0]->position());
83 endcapSeed.setPosition(matchedSegs[0]->position());
84 const auto [barrelLength, barrelTheta] = calcSeedLength(tgContext, barrelSeed);
85 const auto [endcapLength, endcapTheta] = calcSeedLength(tgContext, endcapSeed);
86 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Constructed new seed from truth muon wih pT:"
87 <<(truthMuon.pt()/ Gaudi::Units::GeV)<<" [GeV], eta: "<<truthMuon.eta()
88 <<", phi: "<<toDeg(truthMuon.phi())<<", q: "<<truthMuon.charge()
89 <<", matchedSeg: "<<matchedSegs.size()<< " barrel (L/theta): "<<barrelLength
90 <<"/"<<barrelTheta<<" - endcap (L/theta): "
91 <<endcapLength<<"/"<<endcapTheta<<"\n"<<barrelSeed);
92 if (barrelLength < 0 && endcapLength < 0) {
93 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Invalid seed");
94 return std::nullopt;
95 }
96 return barrelLength < 0 || std::abs(endcapLength) < barrelLength
97 ? endcapSeed : barrelSeed;
98 }
99
100 std::pair<double, double> MsTrackTester::calcSeedLength(const Acts::GeometryContext& tgContext,
101 const MuonR4::MsTrackSeed& seed) const {
102 double maxL{-1.*Gaudi::Units::km}, minL{1.*Gaudi::Units::km},
103 maxTheta{-181.}, minTheta{181};
104 for (const xAOD::MuonSegment* seg : seed.segments()) {
105 const Amg::Vector2D projPos{m_seedingTool->expressOnCylinder(tgContext, *seg, seed.location(), seed.sector())};
106 if (!m_seedingTool->withinBounds(projPos, seed.location())) {
107 continue;
108 }
109 const double projected = projPos[seed.location()==Location::Barrel];
110 const double theta = seg->direction().theta();
111 minL = std::min(minL, projected);
112 maxL = std::max(maxL, projected);
113 minTheta = std::min(minTheta, toDeg(theta));
114 maxTheta = std::max(maxTheta, toDeg(theta));
115 }
116 return std::make_pair(maxL - minL, maxTheta - minTheta);
117 }
120 ATH_CHECK(m_truthKey.initialize(m_isMC));
121
122 ATH_CHECK(m_muonKey.initialize());
123 ATH_CHECK(m_msTrkSeedKey.initialize());
124 ATH_CHECK(m_recoSegmentKey.initialize());
125
126 ATH_CHECK(m_summaryTool.retrieve());
127 ATH_CHECK(m_seedingTool.retrieve());
128
129 ATH_CHECK(m_legacyMuonKey.initialize(!m_legacyMuonKey.empty()));
130 ATH_CHECK(m_legacyTrackKey.initialize(!m_legacyMuonKey.empty()));
131 ATH_CHECK(m_legacySegmentKey.initialize(!m_legacyMuonKey.empty()));
132 ATH_CHECK(m_idTrackKey.initialize(m_isMC && m_storeID));
133 ATH_CHECK(m_idTagKey.initialize(!m_idTrackKey.empty()));
134 ATH_CHECK(m_segTagKey.initialize(!m_idTrackKey.empty()));
135
136 ATH_CHECK(m_ctxProvider.initialize());
137 ATH_CHECK(m_extrapolationTool.retrieve(EnableTool{m_storeID}));
138 ATH_CHECK(detStore()->retrieve(m_detMgr));
139 m_logger = makeActsAthenaLogger(this, name());
140
141 int evOpts{0};
142
143 m_recoSegs = std::make_unique<SegmentVariables>(m_tree, m_recoSegmentKey.key(), "Segments", msgLevel());
145 "Segments_passSeedQual",[this](const SG::AuxElement* aux){
146 const auto* seg = static_cast<const xAOD::MuonSegment*>(aux);
147 return m_segSelector->passSeedingQuality(Gaudi::Hive::currentContext(),
148 *seg); }));
150 "Segments_passTrackQual",[this](const SG::AuxElement* aux){
151 const auto* seg = static_cast<const xAOD::MuonSegment*>(aux);
152 return m_segSelector->passTrackQuality(Gaudi::Hive::currentContext(),
153 *seg);
154 }));
155
156
157 if (m_isMC) {
158 evOpts |= EventInfoBranch::isMC;
160 "Segments_truthSegLink",[this](const SG::AuxElement* aux){
161 const auto* seg = static_cast<const xAOD::MuonSegment*>(aux);
163 const unsigned linkIdx = truthS ? m_truthSegs->push_back(*truthS) : -1;
165 if (truthS) {
166 m_truthSegToRecoLink.push_back(linkIdx, m_recoSegs->push_back(*seg));
167 const xAOD::TruthParticle* truthMuon = MuonR4::getTruthMatchedParticle(*truthS);
168 if (truthMuon){
169 m_truthTrks->push_back(truthMuon);
170 m_truthMuRecoSegLinks[m_truthTrks->find(truthMuon)].push_back(m_recoSegs->push_back(*seg));
171 }
172 }
173 return linkIdx;
174 }));
175
176 m_truthSegs = std::make_unique<SegmentVariables>(m_tree, m_truthSegmentKey.key(), "TruthSegments", msgLevel());
177
179 "TruthSegments_truthLink",[this](const SG::AuxElement* aux){
180 const auto* seg = static_cast<const xAOD::MuonSegment*>(aux);
182 m_truthTrks->push_back(truthP);
183 unsigned short linkIdx = m_truthTrks->find(truthP);
184 return linkIdx;
185 }));
186 for (auto loc : {Location::Barrel, Location::Endcap}) {
188 std::format("TruthSegments_has{}Proj", loc), [loc, this](const SG::AuxElement* aux) -> unsigned short {
189
190 const auto* seg = static_cast<const xAOD::MuonSegment*>(aux);
191 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(Gaudi::Hive::currentContext());
192 ExpandedSector sector{seg->position().phi()};
193 const Amg::Vector2D projPos{m_seedingTool->expressOnCylinder(tgContext, *seg, loc, sector)};
194 return m_seedingTool->withinBounds(projPos, loc);
195 }));
196 }
197
198 m_tree.addBranch(m_truthSegs);
199
200 m_truthTrks = std::make_unique<IParticleFourMomBranch>(m_tree, "TruthMuons");
201 m_truthTrks->addVariable<int>(-1, "truthOrigin");
202 m_truthTrks->addVariable<int>(-1, "truthType");
204 m_truthTrks->addVariable(
206 std::vector<unsigned short>>>(m_tree,
207 std::format("{:}_truthSegLinks", m_truthTrks->name()), [&] (const xAOD::TruthParticle& p){
208 std::vector<unsigned short> idx{};
209 for (const xAOD::MuonSegment* truthSeg: getTruthSegments(p)){
210 idx.push_back(m_truthSegs->push_back(*truthSeg));
211 }
212 return idx;
213 }));
215 m_truthTrks->addVariable(
217 std::format("{:}_nTruthSegments", m_truthTrks->name()), [&] (const xAOD::TruthParticle& p) -> unsigned short {
218 return getTruthSegments(p).size();
219 }));
220
221 m_truthTrks->addVariable(
223 std::format("{:}_eLossInMS", m_truthTrks->name()), [] (const xAOD::TruthParticle& p) -> float {
224 std::vector<const xAOD::MuonSimHit*> allHits{};
225 for (const xAOD::MuonSegment* seg : getTruthSegments(p)){
226 auto hits = getMatchingSimHits(*seg);
227 allHits.insert(allHits.end(), hits.begin(), hits.end());
228 }
229 if (allHits.empty()) {
230 return 0.;
231 }
232 auto [min, max] = std::ranges::minmax(allHits, [](const xAOD::MuonSimHit* a, const xAOD::MuonSimHit* b){
233 return a->kineticEnergy() < b->kineticEnergy();
234 });
235 return (min->kineticEnergy() - max->kineticEnergy()) / Gaudi::Units::GeV;
236 }));
238 auto cone = std::make_shared<VectorBranch<float>>(m_tree,
239 std::format("{}_seedThetaCone", m_truthTrks->name()));
240 auto qTimesP = std::make_shared<VectorBranch<float>>(m_tree,
241 std::format("{}_qTimesP", m_truthTrks->name()));
242
243 m_tree.addBranch(cone);
244 m_tree.addBranch(qTimesP);
245 m_truthTrks->addVariable(
247 std::format("{:}_seedLength", m_truthTrks->name()), [cone, qTimesP, this] (const xAOD::TruthParticle& p) -> float {
248
249 const EventContext& ctx{Gaudi::Hive::currentContext()};
250 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
251 const Acts::MagneticFieldContext mfContext = m_ctxProvider.getMagneticFieldContext(ctx);
252 MagField::AtlasFieldCache magField{};
253 mfContext.get<const AtlasFieldCacheCondObj*>()->getInitializedCache(magField);
254 auto truthSeed = makeSeedFromTruth(tgContext, p);
255 if (!truthSeed) {
256 cone->push_back(-1);
257 qTimesP->push_back(0);
258 return -1.;
259 }
260 auto [length, theta] = calcSeedLength(tgContext, *truthSeed);
261 cone->push_back(theta);
262 qTimesP->push_back(m_seedingTool->estimateQtimesP(tgContext, *truthSeed, magField) / Gaudi::Units::GeV);
263 return length;
264 }));
265
266 m_tree.addBranch(m_truthTrks);
267 m_trkTruthLinks.emplace_back(m_truthSegmentKey, "truthParticleLink");
268 m_trkTruthLinks.emplace_back(m_truthKey, "truthSegmentLinks");
269 m_trkTruthLinks.emplace_back(m_recoSegmentKey, "truthSegmentLink");
270 m_trkTruthLinks.emplace_back(m_muonKey, "truthParticleLink");
271 }
272
273 m_tree.addBranch(m_recoSegs);
274 m_tree.addBranch(std::make_unique<EventInfoBranch>(m_tree, evOpts));
275
276 static const std::vector<std::string> trackSummaries{
277 // Inner
278 "innerSmallHits", "innerLargeHits", "innerSmallHoles", "innerLargeHoles",
279 "innerClosePrecisionHits",
280 // Middle
281 "middleSmallHits", "middleLargeHits", "middleSmallHoles",
282 "middleLargeHoles", "middleClosePrecisionHits",
283 // Outer
284 "outerSmallHits", "outerLargeHits", "outerSmallHoles", "outerLargeHoles",
285 "outerClosePrecisionHits",
286 // Extended
287 "extendedSmallHits", "extendedLargeHits", "extendedSmallHoles",
288 "extendedLargeHoles", "extendedClosePrecisionHits",
289 "innerTriggerEtaHits", "innerTriggerPhiHits",
290 "middleTriggerEtaHits", "middleTriggerPhiHits",
291 "outerTriggerEtaHits", "outerTriggerPhiHits",
292
293 "innerTriggerEtaHoles", "innerTriggerPhiHoles",
294 "middleTriggerEtaHoles", "middleTriggerPhiHoles",
295 "outerTriggerEtaHoles", "outerTriggerPhiHoles",
296 };
297 if(!m_legacyTrackKey.empty()) {
298 m_legacyTrks = std::make_unique<IParticleFourMomBranch>(m_tree, "LegacyMSTrks");
299 m_legacyTrks->addVariable(std::make_unique<TrackChi2Branch>(*m_legacyTrks));
300 if (m_isMC) {
301 BilateralLinkerBranch::connectCollections(m_legacyTrks, m_truthTrks,
302 [](const xAOD::IParticle* trk){
304 }, "truth", "LegacyMS");
305 }
306 for (const auto& summary : trackSummaries) {
307 m_legacyTrks->addVariable<uint8_t>(-1, summary);
308 }
309 m_tree.addBranch(m_legacyTrks);
310 m_legacyRecoSegs = std::make_unique<SegmentVariables>(m_tree, m_legacySegmentKey.key(), "LegacyRecoSegments", msgLevel());
311 m_tree.addBranch(m_legacyRecoSegs);
312 }
313
314 m_seedSummary = std::make_shared<TrackSummaryModule>(m_tree, "TrkSeed", m_summaryTool.get());
315 m_muonTrks = std::make_shared<IParticleFourMomBranch>(m_tree, "ActsMuons");
316 m_muonTrks->addVariable(std::make_unique<TrackChi2Branch>(*m_muonTrks));
317 m_muonTrks->addVariable<float>(4.5, "segmentDeltaEta");
318 m_muonTrks->addVariable<float>(std::numbers::pi, "segmentDeltaPhi");
319 m_muonTrks->addVariable<float>(-1., "segmentChi2OverDoF");
320
321 using TrkType = xAOD::Muon::TrackParticleType;
322 auto dumpTrack = [&](const std::string& trkName, TrkType type) {
323 auto trkColl = std::make_shared<IParticleFourMomBranch>(m_tree, trkName);
324 trkColl->addVariable(std::make_unique<TrackChi2Branch>(*trkColl));
325 if (type != TrkType::InnerDetectorTrackParticle) {
326 trkColl->addVariable(std::make_unique<TrackFitIterBranch>(*trkColl));
327 }
328 trkColl->addVariable(std::make_unique<MaterialRecorderBranch>(*trkColl));
329 trkColl->addVariable(std::make_unique<EnergyLossBranch>(*trkColl));
330
331 trkColl->addVariable<float>("d0");
332 trkColl->addVariable<float>("z0");
333 if (type != TrkType::InnerDetectorTrackParticle) {
334 for (const auto& summary : trackSummaries) {
335 trkColl->addVariable<uint8_t>(-1, summary);
336 }
337 }
339 [type](const xAOD::IParticle* muonP) -> const xAOD::IParticle* {
340 const auto* muon = dynamic_cast<const xAOD::Muon*>(muonP);
341 if (!muon) {
342 return nullptr;
343 }
344 return muon->trackParticle(type);
345 }, trkName, "muon");
346
347 return trkColl;
348 };
349
350 auto msTracks = dumpTrack("MsTrk", TrkType::MuonSpectrometerTrackParticle);
351 dumpTrack("MeTrk", TrkType::ExtrapolatedMuonSpectrometerTrackParticle);
352 m_idTracks = dumpTrack("IdTrk", TrkType::InnerDetectorTrackParticle);
353
355 {
356 auto& l0{m_tree.newVector<float>(std::format("{:}_caloExitLoc0", m_idTracks->name()))};
357 auto& l1{m_tree.newVector<float>(std::format("{:}_caloExitLoc1", m_idTracks->name()))};
358 auto& theta{m_tree.newVector<float>(std::format("{:}_caloExitTheta", m_idTracks->name()))};
359 auto& phi{m_tree.newVector<float>(std::format("{:}_caloExitPhi", m_idTracks->name()))};
360 auto& mom{m_tree.newVector<float>(std::format("{:}_caloExitMom", m_idTracks->name()))};
361
362 m_idTracks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, std::uint8_t>>(m_tree,
363 std::format("{:}_isCandidate", m_idTracks->name()),
364 [this, &l0, &l1, &theta, &phi, &mom] (const xAOD::TrackParticle& idTrack) -> std::uint8_t {
365 const MuonR4::MuonTag* tag = findBaseIdTag(idTrack, Gaudi::Hive::currentContext());
366 std::optional<Acts::BoundTrackParameters> trkPars = tag ? tag->extrapolatedParsID(Acts::hashString("@CaloExit"))
367 : std::nullopt;
368 const std::size_t idx = l0.size();
369 using namespace MuonCombinedR4;
370 l0[idx] = trkPars ? longitudinalParam(*trkPars, logger()) : 1._km;
371 l1[idx] = trkPars ? toDeg(localPolarAngle(*trkPars, logger())) : 360.;
372
373 theta[idx] = trkPars ? toDeg(trkPars->get<Acts::eBoundTheta>()) : 360.;
374 phi[idx] = trkPars ? toDeg(trkPars->get<Acts::eBoundPhi>()) : 360.;
375 mom[idx] = trkPars ? trkPars->absoluteMomentum() : -1._GeV;
376 return trkPars != std::nullopt;
377 }));
378 }
379 {
380 auto& dX0{m_tree.newMatrix<float>(std::format("{:}_segTagDx0", m_idTracks->name()))};
381 auto& dY0{m_tree.newMatrix<float>(std::format("{:}_segTagDy0", m_idTracks->name()))};
382 auto& dTheta{m_tree.newMatrix<float>(std::format("{:}_segTagDtheta", m_idTracks->name()))};
383 auto& dPhi{m_tree.newMatrix<float>(std::format("{:}_segTagDphi", m_idTracks->name()))};
384 auto& segments{m_tree.newMatrix<std::uint8_t>(std::format("{:}_segTagSegments", m_idTracks->name()))};
385 auto& goodExtp{m_tree.newMatrix<std::uint8_t>(std::format("{:}_segTagExtpGood",m_idTracks->name()))};
386 auto& taggedSeg{m_tree.newMatrix<std::uint8_t>(std::format("{:}_segTagOnTag", m_idTracks->name()))};
387 m_idTracks->addVariable(
388 std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, std::vector<float>>>(m_tree,
389 std::format("{:}_segTagScore", m_idTracks->name()),
390 [&dX0, &dY0, &dTheta, &dPhi, &segments,
391 &goodExtp, &taggedSeg,this] (const xAOD::TrackParticle& idTrack) -> std::vector<float> {
392 auto result = calcSegTagVariables(idTrack, Gaudi::Hive::currentContext());
393
394 segments.push_back(std::move(result.recoSegs));
395 dX0.push_back(std::move(result.deltaX0));
396 dY0.push_back(std::move(result.deltaY0));
397 dTheta.push_back(std::move(result.deltaTheta));
398 dPhi.push_back(std::move(result.deltaPhi));
399 goodExtp.push_back(std::move(result.goodExtp));
400 taggedSeg.push_back(std::move(result.taggedSeg));
401 return std::move(result.matchScores);
402 }));
403 }
404 if (m_isMC) {
405 BilateralLinkerBranch::connectCollections(m_idTracks, m_truthTrks,
406 [this](const xAOD::IParticle* trk) {
407 return truthTreeParticle(*trk, Gaudi::Hive::currentContext());
408 }, "truth", "IdTrack");
409
410 }
411
412 m_muonTrks->addVariable<uint16_t>("allAuthors");
413 m_muonTrks->addVariable<uint16_t>("author");
415 m_muonTrks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::Muon,
416 std::vector<unsigned short>>>(m_tree,
417 std::format("{:}_segmentLinks", m_muonTrks->name()), [&] (const xAOD::Muon& p){
418 std::vector<unsigned short> idx{};
419 for (unsigned seg = 0 ; seg < p.nMuonSegments(); ++seg) {
420 idx.push_back(m_recoSegs->push_back(*p.muonSegment(seg)));
421 }
422 return idx;
423 }));
425 msTracks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, unsigned short>>(m_tree,
426 std::format("{:}_seedLink", msTracks->name()), [&] (const xAOD::TrackParticle& p) -> unsigned short {
427 auto actsTrk = ActsTrk::getActsTrack(p);
428 if (!actsTrk) {
429 THROW_EXCEPTION("Cannot find the associated ms track from the primary track");
430 }
431 return actsTrk->component<std::size_t>("parentSeed");
432 }));
433
434 msTracks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, float>>(m_tree,
435 std::format("{:}_loc0", msTracks->name()), [&] (const xAOD::TrackParticle& p){
436 auto actsTrk = ActsTrk::getActsTrack(p);
437 if (!actsTrk) {
438 THROW_EXCEPTION("Cannot find the associated ms track from the primary track");
439 }
440 auto refPars = actsTrk->createParametersAtReference();
441 return isOnCaloExit(refPars) ? MuonCombinedR4::longitudinalParam(refPars, logger())
442 : refPars.get<Acts::eBoundLoc0>();
443 }));
444 msTracks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, float>>(m_tree,
445 std::format("{:}_loc1", msTracks->name()), [&] (const xAOD::TrackParticle& p){
446 auto actsTrk = ActsTrk::getActsTrack(p);
447 if (!actsTrk) {
448 THROW_EXCEPTION("Cannot find the associated ms track from the primary track");
449 }
450 auto refPars = actsTrk->createParametersAtReference();
451 return isOnCaloExit(refPars) ? toDeg(MuonCombinedR4::localPolarAngle(refPars, logger()))
452 : refPars.get<Acts::eBoundLoc0>();
453 }));
454 msTracks->addVariable(std::make_unique<GenericPartDecorBranch<xAOD::TrackParticle, std::uint8_t>>(m_tree,
455 std::format("{:}_isOnCaloExit", msTracks->name()), [&] (const xAOD::TrackParticle& p){
456 auto actsTrk = ActsTrk::getActsTrack(p);
457 if (!actsTrk) {
458 THROW_EXCEPTION("Cannot find the associated ms track from the primary track");
459 }
460 return isOnCaloExit(actsTrk->referenceSurface());
461 }));
462 if (m_isMC) {
463 BilateralLinkerBranch::connectCollections(m_muonTrks, m_truthTrks,
464 [](const xAOD::IParticle* trk) -> const xAOD::TruthParticle* {
466 }, "truth", "ActsMuon");
467 }
468
469 for (const auto& summary : trackSummaries) {
470 m_muonTrks->addVariable<uint8_t>(summary);
471 }
472 m_tree.addBranch(m_muonTrks);
473
474 m_tree.addBranch(m_seedSummary);
475
476 ATH_CHECK(m_trkTruthLinks.initialize());
477 ATH_CHECK(m_tree.init(this));
478 return StatusCode::SUCCESS;
479 }
480
482 const EventContext& ctx) const {
484 if (!truthTrk || !m_truthTrks) {
485 return nullptr;
486 }
487 for (const xAOD::IParticle* thisPart : m_truthTrks->getCached(ctx)) {
488 if (thisPart == truthTrk || truthTrk == xAOD::TruthHelpers::getTruthParticle(*thisPart)) {
489 return dynamic_cast<const xAOD::TruthParticle*>(thisPart);
490 }
491 }
492 return nullptr;
493 }
494
496 const EventContext& ctx) const {
497 return findTagMatchingToId(idTrack, m_idTagKey, ctx);
498 }
500 const EventContext& ctx) const {
501 return findTagMatchingToId(idTrack, m_segTagKey, ctx);
502 }
503
504 std::vector<const xAOD::MuonSegment*>
506 const EventContext& ctx) const {
507 std::vector<const xAOD::MuonSegment*> compatibleSegs{};
508 if (const xAOD::TruthParticle* truthPart = truthTreeParticle(idTrack, ctx); truthPart != nullptr) {
509 std::vector<const xAOD::MuonSegment*> truthSegs = getTruthSegments(*truthPart);
510 const xAOD::MuonSegmentContainer* recoSegs{nullptr};
511 SG::get(recoSegs, m_recoSegmentKey, ctx).ignore();
512 std::copy_if(recoSegs->begin(), recoSegs->end(), std::back_inserter(compatibleSegs),
513 [&truthSegs](const xAOD::MuonSegment* recoSeg){
514 return Acts::rangeContainsValue(truthSegs, getMatchedTruthSegment(*recoSeg));
515 });
516 if (!compatibleSegs.empty()) {
517 return compatibleSegs;
518 }
519 }
520
521 const xAOD::MuonContainer* muons{nullptr};
522 SG::get(muons,m_muonKey, ctx).ignore();
523 for (const xAOD::Muon* muon : *muons) {
524 if (muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle) == &idTrack) {
525 for (std::size_t s = 0; s < muon->nMuonSegments() ; ++s) {
526 compatibleSegs.push_back(muon->muonSegment(s));
527 }
528 break;
529 }
530 }
531 return compatibleSegs;
532 }
533
535 return m_detMgr->getSectorEnvelope(segment.chamberIndex(), segment.sector(), segment.etaIndex());
536 }
537
540 const EventContext& ctx) {
541
542 SegmentTagVariables result{};
544 const std::vector<const xAOD::MuonSegment*> compatibleSegs = getAssociatedSegments(idTrack, ctx);
545 if (compatibleSegs.empty()) {
546 return result;
547 }
549 const ActsTrk::CaloExtension* caloExt = ActsTrk::getCaloExtension(idTrack);
550 if (!caloExt) {
551 return result;
552 }
553 std::optional<Acts::BoundTrackParameters> startPars = caloExt->lastParameters();
554 if (!startPars) {
555 return result;
556 }
557
558 const MuonR4::MuonTag* muTag = findMuTagIMO(idTrack, ctx);
559
560 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
561
562 auto nextParameters = [&](const xAOD::MuonSegment& segment) {
564 const MuonGMR4::SpectrometerSector* msSector = getEnvelope(segment);
565 const Acts::Surface& target{msSector->surface()};
566 if (target.geometryId() == startPars->referenceSurface().geometryId()) {
567 return true;
568 }
569 if (muTag) {
570 auto surfPars = muTag->extrapolatedParsID(Acts::toUnderlying(segment.chamberIndex()));
571 if (surfPars) {
572 startPars = surfPars;
573 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Recycle cached parameters from muTag\n"
574 <<(*startPars));
575 return true;
576 }
577 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Extrapolation to "<<printID(segment)<<" failed somehow");
578 }
579
580 auto extpPars = m_extrapolationTool->propagate(ctx, *startPars, target);
581 if (!extpPars.ok()) {
582 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Extrapolation keeps failing");
583 return false;
584 }
585 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Updated parameters to \n"<<(*extpPars));
586 startPars = *extpPars;
587 return true;
588 };
589
590 const xAOD::MuonSegment* bestSeg{nullptr};
591 float bestMatchScore{std::numeric_limits<float>::max()};
592 Acts::BoundVector bestPars{Acts::BoundVector::Zero()};
593
594 auto dumpBestSeg = [&]() {
595 if (!bestSeg) {
596 return;
597 }
598 result.recoSegs.push_back(m_recoSegs->push_back(*bestSeg));
599 result.matchScores.push_back(bestMatchScore);
600 result.deltaPhi.push_back(toDeg(bestPars[Acts::eBoundPhi]));
601 result.deltaTheta.push_back(toDeg(bestPars[Acts::eBoundTheta]));
602 result.deltaY0.push_back(bestPars[Acts::eBoundLoc1]);
603 result.deltaX0.push_back(bestPars[Acts::eBoundLoc0]);
604 result.goodExtp.push_back(1);
605 result.taggedSeg.push_back(muTag && Acts::rangeContainsValue(muTag->segments(), bestSeg));
606 bestSeg = nullptr;
607 bestMatchScore = std::numeric_limits<float>::max();
608 bestPars = Acts::BoundVector::Zero();
609 };
610
611 for (auto segItr = compatibleSegs.begin(); segItr != compatibleSegs.end(); ) {
612 const xAOD::MuonSegment* testMe{*segItr};
614 if (!nextParameters(*testMe)) {
615 result.recoSegs.push_back(m_recoSegs->push_back(*testMe));
616 result.matchScores.push_back(-1.f);
617 result.deltaX0.push_back(1._m);
618 result.deltaY0.push_back(1._m);
619 result.deltaTheta.push_back(180.);
620 result.deltaPhi.push_back(180.);
621 result.goodExtp.push_back(0);
622 result.taggedSeg.push_back(0);
623 segItr = std::find_if(std::next(segItr),compatibleSegs.end(), [&](const xAOD::MuonSegment* assocSeg){
624 return getEnvelope(*testMe) != getEnvelope(*assocSeg);
625 });
626 } else {
627 ++segItr;
628 }
630 if (bestSeg && getEnvelope(*testMe) != getEnvelope(*bestSeg)) {
631 dumpBestSeg();
632 }
633 const Acts::BoundTrackParameters segmentPars{MuonR4::SegmentFit::boundSegmentPars(tgContext, *m_detMgr, *testMe)};
634 Acts::BoundVector dPars = segmentPars.parameters() - startPars->parameters();
636 if (!testMe->nPhiLayers()) {
637 dPars[Acts::eBoundPhi] = dPars[Acts::eBoundLoc0] = 0.;
638 } else {
639 dPars[Acts::eBoundPhi] = P4Helpers::deltaPhi(dPars[Acts::eBoundPhi], 0.);
640 }
641
642 dPars[Acts::eBoundQOverP] = dPars[Acts::eBoundTime] = 0.;
643 Acts::BoundMatrix covariance{Acts::BoundMatrix::Identity()};
644 covariance(Acts::eBoundLoc0, Acts::eBoundLoc0) = Acts::square(m_toleranceX0.value());
645 covariance(Acts::eBoundLoc1, Acts::eBoundLoc1) = Acts::square(m_toleranceY0.value());
646 covariance(Acts::eBoundTheta, Acts::eBoundTheta) = Acts::square(m_toleranceTheta.value());
647 covariance(Acts::eBoundPhi, Acts::eBoundPhi) = Acts::square(m_tolerancePhi.value());
648 if (startPars->covariance()) {
649 covariance += (*startPars->covariance());
650 }
651 if (segmentPars.covariance()) {
652 covariance += (*segmentPars.covariance());
653 }
654 const float chi2 = dPars.dot(covariance.inverse()*dPars);
655 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Difference: "<<Acts::toString(dPars)
656 <<", covariance: \n"<<Acts::toString(covariance)<<",\nchi2: "<<chi2);
657 if (chi2 < bestMatchScore) {
658 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Best parameters on surface thus far");
659 bestMatchScore = chi2;
660 bestSeg = testMe;
661 bestPars = std::move(dPars);
662 }
663 }
664 dumpBestSeg();
665 return result;
666 }
667
668
669 StatusCode MsTrackTester::dumpLegacyTracks(const EventContext& ctx) {
670
671 //This for now is to be able to retrieve the matching between the legacy segments and tracks ...
672 const xAOD::MuonContainer* legacyMuons{nullptr};
673 ATH_CHECK(SG::get(legacyMuons, m_legacyMuonKey, ctx));
674
675 if (!legacyMuons) {
676 return StatusCode::SUCCESS;
677 }
678
679 for (const xAOD::Muon* muon : *legacyMuons) {
680 ATH_MSG_VERBOSE("iMuon " << muon->index() << " pT: "<<(muon->pt() *MeVtoGeV)<<" [GeV], eta: "
681 <<muon->eta() <<", phi: "<<toDeg(muon->phi())<<", q: "<<muon->charge()
682 <<", nSegments: "<<muon->nMuonSegments());
683 const xAOD::TrackParticle* track = muon->trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle);
684 if (!track) {
685 continue;
686 }
687 m_summaryTool->copySummary(m_summaryTool->makeSummary(ctx, *track->track()), *track);
688 m_legacyTrks->push_back(track);
689 auto trkIdx = m_legacyTrks->find(track);
690 for (size_t s = 0; s < muon->nMuonSegments(); ++s) {
691 const xAOD::MuonSegment* segment = muon->muonSegment(s);
692 auto segIdx = m_legacyRecoSegs->push_back(*segment);
693 ATH_MSG_VERBOSE(std::format( "Legacy muon-segment link: segment {:} @{:}, eta: {:.2f}, phi {:.2f}",
694 printID(*segment), Amg::toString(segment->position()),
695 segment->direction().eta(), toDeg(segment->direction().phi())));
696 m_legacySegToTrkLinks[segIdx] = trkIdx;
697 }
698 }
699
700 //Dump also legacy segments
701 const xAOD::MuonSegmentContainer* legacyRecoSegs{nullptr};
702 ATH_CHECK(SG::get(legacyRecoSegs, m_legacySegmentKey, ctx));
703
704 if (legacyRecoSegs->size()) {
705 m_legacySegToTrkLinks[legacyRecoSegs->size()-1];
706 for (const xAOD::MuonSegment* seg : *legacyRecoSegs) {
707 //Store all segments
708 m_legacyRecoSegs->push_back(*seg);
709 }
710 }
711
712 const xAOD::TrackParticleContainer* legacyTrks{nullptr};
713 ATH_CHECK(SG::get(legacyTrks, m_legacyTrackKey, ctx));
714
715 for (const xAOD::TrackParticle* track : *legacyTrks) {
716 m_summaryTool->copySummary(m_summaryTool->makeSummary(ctx, *track->track()), *track);
717 m_legacyTrks->push_back(track);
718 }
719
720 return StatusCode::SUCCESS;
721 }
722 StatusCode MsTrackTester::dumpTruthContent(const EventContext& ctx) {
723 if (!m_isMC) {
724 return StatusCode::SUCCESS;
725 }
726 const xAOD::MuonSegmentContainer* truthSegs{nullptr};
727 ATH_CHECK(SG::get(truthSegs, m_truthSegmentKey, ctx));
728
729
730 for (const xAOD::MuonSegment* seg : *truthSegs) {
731 ATH_MSG_VERBOSE("Dump truth segment "<<printID(*seg)<<" @"<<
732 Amg::toString(seg->position())<<", eta: "<<seg->direction().eta()
733 <<", phi: "<<toDeg(seg->direction().phi()));
734 m_truthSegs->push_back(*seg);
735 }
736 if (truthSegs->size()) {
737 m_truthSegToRecoLink[truthSegs->size()-1];
738 }
739
740
741 const xAOD::TruthParticleContainer* truthMuons{nullptr};
742 ATH_CHECK(SG::get(truthMuons, m_truthKey, ctx));
743 const std::size_t nT = truthMuons->size() - 1;
744 if (!truthMuons->empty()) {
749 }
750 for (const xAOD::TruthParticle* truth : *truthMuons) {
751 ATH_MSG_DEBUG("Truth muon: pT: "<<(truth->pt() *MeVtoGeV)
752 <<", eta: "<<truth->eta()<<", phi: "<<toDeg(truth->phi())<<", q: "<<truth->charge()
753 <<", uuid: "<<HepMC::uniqueID(truth));
754 m_truthTrks->push_back(*truth);
755 }
756
757 return StatusCode::SUCCESS;
758 }
759 StatusCode MsTrackTester::dumpRecoContent(const EventContext& ctx) {
760 const xAOD::MuonContainer* muons{nullptr};
761 ATH_CHECK(SG::get(muons, m_muonKey, ctx));
763 const xAOD::MuonSegmentContainer* recoSegments{nullptr};
764 ATH_CHECK(SG::get(recoSegments, m_recoSegmentKey, ctx));
765
766 const MuonR4::MsTrackSeedContainer* trkSeeds{nullptr};
767 ATH_CHECK(SG::get(trkSeeds, m_msTrkSeedKey, ctx));
768
769 const xAOD::TrackParticleContainer* idTracks{nullptr};
770 ATH_CHECK(SG::get(idTracks, m_idTrackKey, ctx));
771
772 const MuonR4::MuonTagContainer* idTags{nullptr};
773 ATH_CHECK(SG::get(idTags, m_idTagKey, ctx));
774
775 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
776 const Acts::MagneticFieldContext mfContext = m_ctxProvider.getMagneticFieldContext(ctx);
777
778 MagField::AtlasFieldCache magField{};
779 mfContext.get<const AtlasFieldCacheCondObj*>()->getInitializedCache(magField);
780
781 std::unordered_map<const xAOD::TruthParticle*,
782 std::vector<unsigned>> truthToSeedMatchCounter{};
783
784 if (!trkSeeds->empty()) {
785 m_seedTruthLink[trkSeeds->size() -1];
786 }
787
788 for (const MuonR4::MsTrackSeed& seed : *trkSeeds) {
789 unsigned int seedIdx = m_seedPos.size();
790 m_seedPos += seed.position();
791 m_seedType+= Acts::toUnderlying(seed.location());
792 m_seedSector += seed.sector().sector();
793 m_seedSummary->push_back(ctx, seed);
794
795 auto startPars = m_seedingTool->estimateStartParameters(ctx, seed);
796 if (startPars.ok()) {
797 m_seedDir += (*startPars).direction();
798 } else {
799 m_seedDir += Amg::Vector3D::UnitZ();
800 }
801 // m_seedDir
802 ATH_MSG_VERBOSE(" Dump new seed: "<<seed);
803 for (const xAOD::MuonSegment* seg : seed.segments()){
804 m_seedRecoSegMatch[seedIdx].push_back(m_recoSegs->push_back(*seg));
805 if (const xAOD::MuonSegment* truthSeg = MuonR4::getMatchedTruthSegment(*seg);
806 truthSeg != nullptr) {
807 std::vector<unsigned>& matchCounter = truthToSeedMatchCounter[MuonR4::getTruthMatchedParticle(*truthSeg)];
808 if (seedIdx >= matchCounter.size()) {
809 matchCounter.resize(seedIdx +1);
810 }
811 ++matchCounter[seedIdx];
812 }
813 }
814 const auto[seedLength, theta] = calcSeedLength(tgContext, seed);
815 m_seedLength+= seedLength;
817 m_seedQP += m_seedingTool->estimateQtimesP(tgContext, seed, magField) / Gaudi::Units::GeV;
818 m_seedGood += startPars.ok();
819 }
821 for (auto& [truthMuon, matches] : truthToSeedMatchCounter) {
822 const unsigned tIndex = m_truthTrks->find(truthMuon);
823 if (tIndex >= m_truthTrks->size()) {
824 continue;
825 }
827 while (std::count_if(matches.begin(), matches.end(),
828 [](const unsigned nMatched){
829 return nMatched > 0;
830 })) {
831 auto bestMatch = std::ranges::max_element(matches);
832 const std::size_t seedIdx = std::distance(matches.begin(), bestMatch);
833 m_truthMuToSeedIdx[tIndex].push_back(seedIdx);
834
835 m_seedTruthLink[seedIdx] = tIndex;
836 m_truthMuToSeedCounter[tIndex].push_back(*bestMatch);
837 (*bestMatch) = 0;
838 }
839 }
840
841 for (const xAOD::Muon* muon : *muons) {
842 m_muonTrks->push_back(muon);
843 }
844
845 for (const xAOD::MuonSegment* seg : *recoSegments) {
846 m_recoSegs->push_back(*seg);
847 }
848
850 if (idTracks) {
851 m_nIdTracks = idTracks->size();
852 for (const xAOD::TrackParticle* idTrk : *idTracks) {
853 if (m_truthTrks->find([idTrk](const xAOD::IParticle* p){
854 return xAOD::TruthHelpers::getTruthParticle(*idTrk) ==
855 xAOD::TruthHelpers::getTruthParticle(*p);
856 }) < m_truthTrks->size()) {
857 m_idTracks->push_back(idTrk);
858 }
859 }
860 }
861 if (idTags) {
862 m_nIdTags = idTags->size();
863 for (const MuonR4::MuonTag* idTag : *idTags) {
865 if (idTag->extrapolatedParsID(Acts::hashString("@CaloExit"))){
866 m_idTracks->push_back(idTag->idTrack());
867 }
868 }
869 }
870 return StatusCode::SUCCESS;
871 }
872 StatusCode MsTrackTester::execute(const EventContext& ctx) {
876
877 ATH_CHECK(m_tree.fill(ctx));
878 return StatusCode::SUCCESS;
879 }
881 ATH_CHECK(m_tree.write());
882 return StatusCode::SUCCESS;
883 }
884}
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
double length(const pvec &v)
static Double_t a
Handle class for reading from StoreGate.
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Definition Logger.cxx:64
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
The CaloExtension holds the ID extrapolation states through the calorimeter and the associated CaloCl...
std::optional< Acts::BoundTrackParameters > lastParameters() const
Returns the outermost parameters known to the extension.
const ServiceHandle< StoreGateSvc > & detStore() const
StatusCode addVariable(const std::string &name, T *&ptr, std::string_view docstring="")
Add a variable to the tuple.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
const Acts::PlaneSurface & surface() const
Returns the associated surface.
void addSegment(const xAOD::MuonSegment *seg)
Append a segment to the seed.
Location
Enum defining whether the seed is made in the endcap / barrel.
Definition MsTrackSeed.h:25
void setPosition(Amg::Vector3D &&pos)
set the seed's position
Baseline EDM object to gather all relevant information about a reconstructed muon candidate which can...
Definition MuonTag.h:25
std::optional< Acts::BoundTrackParameters > extrapolatedParsID(const Acts::HashedString &parName) const
Returns the cached extrapolated ID track parameters.
Definition MuonTag.cxx:76
const std::vector< const xAOD::MuonSegment * > & segments() const
Returns the segments associated with the tag.
Definition MuonTag.cxx:12
ToolHandle< MuonR4::ITrackSeedingDiagnosticsTool > m_seedingTool
The track seeding tool to construct the seed candidates and to estimate the initial parameters.
const MuonGMR4::MuonDetectorManager * m_detMgr
The detector manager to fetch the segment surfaces.
MuonVal::ScalarBranch< std::uint16_t > & m_nIdTags
The number of selected ID tracks in the event.
ToolHandle< MuonR4::ITrackSummaryTool > m_summaryTool
Hit summary tool.
StatusCode dumpLegacyTracks(const EventContext &ctx)
Dumps the legacy containers to the TTree.
SegmentKey_t m_legacySegmentKey
Legacy segment container.
const MuonR4::MuonTag * findBaseIdTag(const xAOD::TrackParticle &idTrack, const EventContext &ctx) const
Searches the Id track in the basline collection of all ID tracks selected for the combined muon recon...
const MuonGMR4::SpectrometerSector * getEnvelope(const xAOD::MuonSegment &segment) const
MuonTagKey_t m_idTagKey
The collection of all ID tracks that are selected for combined reconstruction.
TrackKey_t m_idTrackKey
The collection of ID tracks associated with the truth particle.
MuonVal::VectorBranch< unsigned short > & m_legacySegToTrkLinks
Link of the legacy track to the legacy segment.
ParticleBranchPtr_t m_truthTrks
MuonVal::VectorBranch< int > & m_seedSector
Sector of the seed, even center, odd overlap regions, for details see:
MuonVal::VectorBranch< float > & m_seedThetaCone
Maximum angular difference between the segments part of the seed.
ParticleBranchPtr_t m_legacyTrks
Output branches of the legacy MS tracks.
SegmentBranchPtr_t m_truthSegs
SegmentBranchPtr_t m_legacyRecoSegs
MuonVal::ScalarBranch< std::uint16_t > & m_nIdTracks
The number of ID tracks in the event.
MuonVal::MatrixBranch< unsigned short > & m_truthMuRecoSegLinks
Links from the truth muon to the segments.
std::unique_ptr< const Acts::Logger > m_logger
Instance to the Acts logger.
MuonVal::MatrixBranch< unsigned short > & m_truthMuToSeedIdx
Links to all MsTrkSeeds that could be matched to the truthMuon, i.e.
TrackKey_t m_legacyTrackKey
Legacy track reconstruction chain.
std::pair< double, double > calcSeedLength(const Acts::GeometryContext &tgContext, const MuonR4::MsTrackSeed &seed) const
Calculate the length of the seed and the theta deflection angle The length is defined as the spread o...
StatusCode execute(const EventContext &ctx) override final
Execute method.
SegmentTagVariables calcSegTagVariables(const xAOD::TrackParticle &idTrack, const EventContext &ctx)
MuonTagKey_t m_segTagKey
The collection of the original segment tags.
MuonVal::VectorBranch< char > & m_seedType
Is the seed in the encap or in the barrel chambers.
StatusCode dumpRecoContent(const EventContext &ctx)
Dump the reconstructed information.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthKey
Key to the truth particle collection.
Gaudi::Property< double > m_toleranceTheta
Extra tolerance applied on the bending direction when calculating the matching score.
Gaudi::Property< bool > m_isMC
Toggle whether the job runs on MC or not.
ParticleBranchPtr_t m_muonTrks
Stored muon information from the Acts muon reco chain.
MuonVal::MatrixBranch< unsigned short > & m_truthSegToRecoLink
Link of the truth segments to the matchin reco segments.
Gaudi::Property< double > m_toleranceX0
Extra tolerance applied on the non-bending intercept when calculating the matching score.
SegmentBranchPtr_t m_recoSegs
StatusCode dumpTruthContent(const EventContext &ctx)
Dump truth information.
SG::ReadHandleKey< MuonR4::MsTrackSeedContainer > m_msTrkSeedKey
Temporary container write handle to push the seeds to store gate for later efficiency analysis.
Gaudi::Property< bool > m_storeID
Toggle whether to process ID tracks or not.
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
Track extrapolation tool.
const xAOD::TruthParticle * truthTreeParticle(const xAOD::IParticle &part, const EventContext &ctx) const
Returns the matched truth particle that is dumped in the tree.
const MuonR4::MuonTag * findMuTagIMO(const xAOD::TrackParticle &idTrack, const EventContext &ctx) const
ParticleBranchPtr_t m_idTracks
Stored ID track information.
StatusCode initialize() override final
MuonVal::MatrixBranch< unsigned short > & m_seedRecoSegMatch
Link of the track seed to the building segment.
MuonVal::VectorBranch< float > & m_seedQP
Estimated momentum times charge from the track seed.
MuonVal::MatrixBranch< unsigned short > & m_truthMuToSeedCounter
Number of matched segments in the seed.
MuonVal::ThreeVectorBranch m_seedPos
Simple seed information.
Gaudi::Property< double > m_tolerancePhi
Extra tolerance applied on the bending direction when calculating the matching score.
MuonKey_t m_legacyMuonKey
Legacy muons.
MuonVal::VectorBranch< float > & m_seedLength
Maximum separation between the segments on the reference plane.
MuonVal::UnitThreeVectorBranch m_seedDir
Seed direction vector.
ToolHandle< MuonR4::ISegmentSelectionTool > m_segSelector
Selection tool to quantify the segment candidate quality.
SegmentKey_t m_recoSegmentKey
Primary segment container.
MuonVal::MuonTesterTree m_tree
The output tree object.
std::vector< const xAOD::MuonSegment * > getAssociatedSegments(const xAOD::TrackParticle &idTrack, const EventContext &ctx) const
Returns the collection of reconstructed segments that can be associated to the id track If the track ...
ActsTrk::ContextUtility m_ctxProvider
Context provider for geometry, magnetic field and calibration contexts.
SegmentKey_t m_truthSegmentKey
Segment from the truth hits.
MuonVal::VectorBranch< char > & m_seedGood
Does the seeding tool construct valid parameters from the seed.
std::optional< MuonR4::MsTrackSeed > makeSeedFromTruth(const Acts::GeometryContext &tgContext, const xAOD::TruthParticle &truthMuon) const
Construct MS track seed from the truth associated segments.
StatusCode finalize() override final
std::shared_ptr< TrackSummaryModule > m_seedSummary
Hit summary on the track seed.
Gaudi::Property< double > m_toleranceY0
Extra tolerance applied on the bending intercept when calculating the matching score.
MuonVal::VectorBranch< unsigned short > & m_seedTruthLink
Link to the truth muon.
MuonKey_t m_muonKey
Dependency on the R4 muon container.
static bool connectCollections(ParticleBranch_ptr primColl, ParticleBranch_ptr secondColl, Linker_t fromPrimToSec, const std::string &altPrimName="", const std::string &altSecName="")
@ isMC
Flag determining whether the branch is simulation.
Generic branch object where the information is evaluated by a std::function instead reading it from t...
Property holding a SG store/key/clid from which a ReadHandle is made.
Class providing the definition of the 4-vector interface.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
::Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
int etaIndex() const
Returns the eta index, which corresponds to stationEta in the offline identifiers (and the ).
std::uint8_t nPhiLayers() const
Returns the number of trigger phi hits.
double chi2(TH1 *h0, TH1 *h1)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
static Root::TMsgLogger logger("iLumiCalc")
constexpr std::size_t s_caloEnvelopeID
Volume Ids ofthe Calorimeter.
const CaloExtension * getCaloExtension(const xAOD::TrackParticle &track)
Retrieve a pointer to the CaloExtension linked with the passed TrackParticle.
std::optional< ActsTrk::TrackContainer::ConstTrackProxy > getActsTrack(const xAOD::TrackParticle &trkPart)
Return the proxy to the Acts track from which the track particle was made frome.
Definition Decoration.cxx:9
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
constexpr float MeVtoGeV
ID3PD * m_tree
Pointer to the ID3PD object used.
for(size_t i=0;i< m_blockFillers.size();i++)
Fill one block.
int uniqueID(const T &p)
double localPolarAngle(const Acts::BoundTrackParameters &pars, const Acts::Logger &logger)
Returns the local angular polar angle of the track parameter.
double longitudinalParam(const Acts::BoundTrackParameters &pars, const Acts::Logger &logger)
Returns the longitudinal local track parameter which is defined as.
Acts::BoundTrackParameters boundSegmentPars(const ActsTrk::GeometryContext &gctx, const MuonGMR4::MuonDetectorManager &detMgr, const xAOD::MuonSegment &segment, const Acts::ParticleHypothesis hypot=Acts::ParticleHypothesis::muon())
Returns the segment parameters as boundTrackParameters.
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::vector< MsTrackSeed > MsTrackSeedContainer
Definition MsTrackSeed.h:96
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
std::vector< const xAOD::MuonSegment * > getTruthSegments(const xAOD::TruthParticle &truthMuon)
Returns the segments associated to the truth muon.
DataVector< MuonTag > MuonTagContainer
Definition MuonTag.h:125
const xAOD::MuonSegment * getMatchedTruthSegment(const xAOD::MuonSegment &segment)
Returns the truth-matched segment.
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
Class to store array like branches into the n-tuples.
Definition HitValAlg.cxx:19
LayerIndex toLayerIndex(ChIndex index)
convert ChIndex into LayerIndex
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition P4Helpers.h:34
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
bool dPhi(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
const xAOD::TruthParticle * getTruthParticle(const xAOD::IParticle &p)
Return the truthParticle associated to the given IParticle (if any).
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
TrackParticle_v1 TrackParticle
Reference the current persistent version:
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
TruthParticle_v1 TruthParticle
Typedef to implementation.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Muon_v1 Muon
Reference the current persistent version:
Definition Muon.h:13
setWord1 uint16_t
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
MuonSegment_v1 MuonSegment
Reference the current persistent version:
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10