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);
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
483 if (!truthTrk || !m_truthTrks) {
484 return nullptr;
485 }
486 for (const xAOD::IParticle* thisPart : m_truthTrks->getCached()) {
487 if (thisPart == truthTrk || truthTrk == xAOD::TruthHelpers::getTruthParticle(*thisPart)) {
488 return dynamic_cast<const xAOD::TruthParticle*>(thisPart);
489 }
490 }
491 return nullptr;
492 }
493
495 const EventContext& ctx) const {
496 return findTagMatchingToId(idTrack, m_idTagKey, ctx);
497 }
499 const EventContext& ctx) const {
500 return findTagMatchingToId(idTrack, m_segTagKey, ctx);
501 }
502
503 std::vector<const xAOD::MuonSegment*>
505 const EventContext& ctx) const {
506 std::vector<const xAOD::MuonSegment*> compatibleSegs{};
507 if (const xAOD::TruthParticle* truthPart = truthTreeParticle(idTrack); truthPart != nullptr) {
508 std::vector<const xAOD::MuonSegment*> truthSegs = getTruthSegments(*truthPart);
509 const xAOD::MuonSegmentContainer* recoSegs{nullptr};
510 SG::get(recoSegs, m_recoSegmentKey, ctx).ignore();
511 std::copy_if(recoSegs->begin(), recoSegs->end(), std::back_inserter(compatibleSegs),
512 [&truthSegs](const xAOD::MuonSegment* recoSeg){
513 return Acts::rangeContainsValue(truthSegs, getMatchedTruthSegment(*recoSeg));
514 });
515 if (!compatibleSegs.empty()) {
516 return compatibleSegs;
517 }
518 }
519
520 const xAOD::MuonContainer* muons{nullptr};
521 SG::get(muons,m_muonKey, ctx).ignore();
522 for (const xAOD::Muon* muon : *muons) {
523 if (muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle) == &idTrack) {
524 for (std::size_t s = 0; s < muon->nMuonSegments() ; ++s) {
525 compatibleSegs.push_back(muon->muonSegment(s));
526 }
527 break;
528 }
529 }
530 return compatibleSegs;
531 }
532
534 return m_detMgr->getSectorEnvelope(segment.chamberIndex(), segment.sector(), segment.etaIndex());
535 }
536
539 const EventContext& ctx) {
540
541 SegmentTagVariables result{};
543 const std::vector<const xAOD::MuonSegment*> compatibleSegs = getAssociatedSegments(idTrack, ctx);
544 if (compatibleSegs.empty()) {
545 return result;
546 }
548 const ActsTrk::CaloExtension* caloExt = ActsTrk::getCaloExtension(idTrack);
549 if (!caloExt) {
550 return result;
551 }
552 std::optional<Acts::BoundTrackParameters> startPars = caloExt->lastParameters();
553 if (!startPars) {
554 return result;
555 }
556
557 const MuonR4::MuonTag* muTag = findMuTagIMO(idTrack, ctx);
558
559 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
560
561 auto nextParameters = [&](const xAOD::MuonSegment& segment) {
563 const MuonGMR4::SpectrometerSector* msSector = getEnvelope(segment);
564 const Acts::Surface& target{msSector->surface()};
565 if (target.geometryId() == startPars->referenceSurface().geometryId()) {
566 return true;
567 }
568 if (muTag) {
569 auto surfPars = muTag->extrapolatedParsID(Acts::toUnderlying(segment.chamberIndex()));
570 if (surfPars) {
571 startPars = surfPars;
572 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Recycle cached parameters from muTag\n"
573 <<(*startPars));
574 return true;
575 }
576 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Extrapolation to "<<printID(segment)<<" failed somehow");
577 }
578
579 auto extpPars = m_extrapolationTool->propagate(ctx, *startPars, target);
580 if (!extpPars.ok()) {
581 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Extrapolation keeps failing");
582 return false;
583 }
584 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Updated parameters to \n"<<(*extpPars));
585 startPars = *extpPars;
586 return true;
587 };
588
589 const xAOD::MuonSegment* bestSeg{nullptr};
590 float bestMatchScore{std::numeric_limits<float>::max()};
591 Acts::BoundVector bestPars{Acts::BoundVector::Zero()};
592
593 auto dumpBestSeg = [&]() {
594 if (!bestSeg) {
595 return;
596 }
597 result.recoSegs.push_back(m_recoSegs->push_back(*bestSeg));
598 result.matchScores.push_back(bestMatchScore);
599 result.deltaPhi.push_back(toDeg(bestPars[Acts::eBoundPhi]));
600 result.deltaTheta.push_back(toDeg(bestPars[Acts::eBoundTheta]));
601 result.deltaY0.push_back(bestPars[Acts::eBoundLoc1]);
602 result.deltaX0.push_back(bestPars[Acts::eBoundLoc0]);
603 result.goodExtp.push_back(1);
604 result.taggedSeg.push_back(muTag && Acts::rangeContainsValue(muTag->segments(), bestSeg));
605 bestSeg = nullptr;
606 bestMatchScore = std::numeric_limits<float>::max();
607 bestPars = Acts::BoundVector::Zero();
608 };
609
610 for (auto segItr = compatibleSegs.begin(); segItr != compatibleSegs.end(); ) {
611 const xAOD::MuonSegment* testMe{*segItr};
613 if (!nextParameters(*testMe)) {
614 result.recoSegs.push_back(m_recoSegs->push_back(*testMe));
615 result.matchScores.push_back(-1.f);
616 result.deltaX0.push_back(1._m);
617 result.deltaY0.push_back(1._m);
618 result.deltaTheta.push_back(180.);
619 result.deltaPhi.push_back(180.);
620 result.goodExtp.push_back(0);
621 result.taggedSeg.push_back(0);
622 segItr = std::find_if(std::next(segItr),compatibleSegs.end(), [&](const xAOD::MuonSegment* assocSeg){
623 return getEnvelope(*testMe) != getEnvelope(*assocSeg);
624 });
625 } else {
626 ++segItr;
627 }
629 if (bestSeg && getEnvelope(*testMe) != getEnvelope(*bestSeg)) {
630 dumpBestSeg();
631 }
632 const Acts::BoundTrackParameters segmentPars{MuonR4::SegmentFit::boundSegmentPars(tgContext, *m_detMgr, *testMe)};
633 Acts::BoundVector dPars = segmentPars.parameters() - startPars->parameters();
635 if (!testMe->nPhiLayers()) {
636 dPars[Acts::eBoundPhi] = dPars[Acts::eBoundLoc0] = 0.;
637 } else {
638 dPars[Acts::eBoundPhi] = P4Helpers::deltaPhi(dPars[Acts::eBoundPhi], 0.);
639 }
640
641 dPars[Acts::eBoundQOverP] = dPars[Acts::eBoundTime] = 0.;
642 Acts::BoundMatrix covariance{Acts::BoundMatrix::Identity()};
643 covariance(Acts::eBoundLoc0, Acts::eBoundLoc0) = Acts::square(m_toleranceX0.value());
644 covariance(Acts::eBoundLoc1, Acts::eBoundLoc1) = Acts::square(m_toleranceY0.value());
645 covariance(Acts::eBoundTheta, Acts::eBoundTheta) = Acts::square(m_toleranceTheta.value());
646 covariance(Acts::eBoundPhi, Acts::eBoundPhi) = Acts::square(m_tolerancePhi.value());
647 if (startPars->covariance()) {
648 covariance += (*startPars->covariance());
649 }
650 if (segmentPars.covariance()) {
651 covariance += (*segmentPars.covariance());
652 }
653 const float chi2 = dPars.dot(covariance.inverse()*dPars);
654 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Difference: "<<Acts::toString(dPars)
655 <<", covariance: \n"<<Acts::toString(covariance)<<",\nchi2: "<<chi2);
656 if (chi2 < bestMatchScore) {
657 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Best parameters on surface thus far");
658 bestMatchScore = chi2;
659 bestSeg = testMe;
660 bestPars = std::move(dPars);
661 }
662 }
663 dumpBestSeg();
664 return result;
665 }
666
667
668 StatusCode MsTrackTester::dumpLegacyTracks(const EventContext& ctx) {
669
670 //This for now is to be able to retrieve the matching between the legacy segments and tracks ...
671 const xAOD::MuonContainer* legacyMuons{nullptr};
672 ATH_CHECK(SG::get(legacyMuons, m_legacyMuonKey, ctx));
673
674 if (!legacyMuons) {
675 return StatusCode::SUCCESS;
676 }
677
678 for (const xAOD::Muon* muon : *legacyMuons) {
679 ATH_MSG_VERBOSE("iMuon " << muon->index() << " pT: "<<(muon->pt() *MeVtoGeV)<<" [GeV], eta: "
680 <<muon->eta() <<", phi: "<<toDeg(muon->phi())<<", q: "<<muon->charge()
681 <<", nSegments: "<<muon->nMuonSegments());
682 const xAOD::TrackParticle* track = muon->trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle);
683 if (!track) {
684 continue;
685 }
686 m_summaryTool->copySummary(m_summaryTool->makeSummary(ctx, *track->track()), *track);
687 m_legacyTrks->push_back(track);
688 auto trkIdx = m_legacyTrks->find(track);
689 for (size_t s = 0; s < muon->nMuonSegments(); ++s) {
690 const xAOD::MuonSegment* segment = muon->muonSegment(s);
691 auto segIdx = m_legacyRecoSegs->push_back(*segment);
692 ATH_MSG_VERBOSE(std::format( "Legacy muon-segment link: segment {:} @{:}, eta: {:.2f}, phi {:.2f}",
693 printID(*segment), Amg::toString(segment->position()),
694 segment->direction().eta(), toDeg(segment->direction().phi())));
695 m_legacySegToTrkLinks[segIdx] = trkIdx;
696 }
697 }
698
699 //Dump also legacy segments
700 const xAOD::MuonSegmentContainer* legacyRecoSegs{nullptr};
701 ATH_CHECK(SG::get(legacyRecoSegs, m_legacySegmentKey, ctx));
702
703 if (legacyRecoSegs->size()) {
704 m_legacySegToTrkLinks[legacyRecoSegs->size()-1];
705 for (const xAOD::MuonSegment* seg : *legacyRecoSegs) {
706 //Store all segments
707 m_legacyRecoSegs->push_back(*seg);
708 }
709 }
710
711 const xAOD::TrackParticleContainer* legacyTrks{nullptr};
712 ATH_CHECK(SG::get(legacyTrks, m_legacyTrackKey, ctx));
713
714 for (const xAOD::TrackParticle* track : *legacyTrks) {
715 m_summaryTool->copySummary(m_summaryTool->makeSummary(ctx, *track->track()), *track);
716 m_legacyTrks->push_back(track);
717 }
718
719 return StatusCode::SUCCESS;
720 }
721 StatusCode MsTrackTester::dumpTruthContent(const EventContext& ctx) {
722 if (!m_isMC) {
723 return StatusCode::SUCCESS;
724 }
725 const xAOD::MuonSegmentContainer* truthSegs{nullptr};
726 ATH_CHECK(SG::get(truthSegs, m_truthSegmentKey, ctx));
727
728
729 for (const xAOD::MuonSegment* seg : *truthSegs) {
730 ATH_MSG_VERBOSE("Dump truth segment "<<printID(*seg)<<" @"<<
731 Amg::toString(seg->position())<<", eta: "<<seg->direction().eta()
732 <<", phi: "<<toDeg(seg->direction().phi()));
733 m_truthSegs->push_back(*seg);
734 }
735 if (truthSegs->size()) {
736 m_truthSegToRecoLink[truthSegs->size()-1];
737 }
738
739
740 const xAOD::TruthParticleContainer* truthMuons{nullptr};
741 ATH_CHECK(SG::get(truthMuons, m_truthKey, ctx));
742 const std::size_t nT = truthMuons->size() - 1;
743 if (!truthMuons->empty()) {
748 }
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 m_truthTrks->push_back(*truth);
754 }
755
756 return StatusCode::SUCCESS;
757 }
758 StatusCode MsTrackTester::dumpRecoContent(const EventContext& ctx) {
759 const xAOD::MuonContainer* muons{nullptr};
760 ATH_CHECK(SG::get(muons, m_muonKey, ctx));
762 const xAOD::MuonSegmentContainer* recoSegments{nullptr};
763 ATH_CHECK(SG::get(recoSegments, m_recoSegmentKey, ctx));
764
765 const MuonR4::MsTrackSeedContainer* trkSeeds{nullptr};
766 ATH_CHECK(SG::get(trkSeeds, m_msTrkSeedKey, ctx));
767
768 const xAOD::TrackParticleContainer* idTracks{nullptr};
769 ATH_CHECK(SG::get(idTracks, m_idTrackKey, ctx));
770
771 const MuonR4::MuonTagContainer* idTags{nullptr};
772 ATH_CHECK(SG::get(idTags, m_idTagKey, ctx));
773
774 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
775 const Acts::MagneticFieldContext mfContext = m_ctxProvider.getMagneticFieldContext(ctx);
776
777 MagField::AtlasFieldCache magField{};
778 mfContext.get<const AtlasFieldCacheCondObj*>()->getInitializedCache(magField);
779
780 std::unordered_map<const xAOD::TruthParticle*,
781 std::vector<unsigned>> truthToSeedMatchCounter{};
782
783 if (!trkSeeds->empty()) {
784 m_seedTruthLink[trkSeeds->size() -1];
785 }
786
787 for (const MuonR4::MsTrackSeed& seed : *trkSeeds) {
788 unsigned int seedIdx = m_seedPos.size();
789 m_seedPos += seed.position();
790 m_seedType+= Acts::toUnderlying(seed.location());
791 m_seedSector += seed.sector().sector();
792 m_seedSummary->push_back(ctx, seed);
793
794 auto startPars = m_seedingTool->estimateStartParameters(ctx, seed);
795 if (startPars.ok()) {
796 m_seedDir += (*startPars).direction();
797 } else {
798 m_seedDir += Amg::Vector3D::UnitZ();
799 }
800 // m_seedDir
801 ATH_MSG_VERBOSE(" Dump new seed: "<<seed);
802 for (const xAOD::MuonSegment* seg : seed.segments()){
803 m_seedRecoSegMatch[seedIdx].push_back(m_recoSegs->push_back(*seg));
804 if (const xAOD::MuonSegment* truthSeg = MuonR4::getMatchedTruthSegment(*seg);
805 truthSeg != nullptr) {
806 std::vector<unsigned>& matchCounter = truthToSeedMatchCounter[MuonR4::getTruthMatchedParticle(*truthSeg)];
807 if (seedIdx >= matchCounter.size()) {
808 matchCounter.resize(seedIdx +1);
809 }
810 ++matchCounter[seedIdx];
811 }
812 }
813 const auto[seedLength, theta] = calcSeedLength(tgContext, seed);
814 m_seedLength+= seedLength;
816 m_seedQP += m_seedingTool->estimateQtimesP(tgContext, seed, magField) / Gaudi::Units::GeV;
817 m_seedGood += startPars.ok();
818 }
820 for (auto& [truthMuon, matches] : truthToSeedMatchCounter) {
821 const unsigned tIndex = m_truthTrks->find(truthMuon);
822 if (tIndex >= m_truthTrks->size()) {
823 continue;
824 }
826 while (std::count_if(matches.begin(), matches.end(),
827 [](const unsigned nMatched){
828 return nMatched > 0;
829 })) {
830 auto bestMatch = std::ranges::max_element(matches);
831 const std::size_t seedIdx = std::distance(matches.begin(), bestMatch);
832 m_truthMuToSeedIdx[tIndex].push_back(seedIdx);
833
834 m_seedTruthLink[seedIdx] = tIndex;
835 m_truthMuToSeedCounter[tIndex].push_back(*bestMatch);
836 (*bestMatch) = 0;
837 }
838 }
839
840 for (const xAOD::Muon* muon : *muons) {
841 m_muonTrks->push_back(muon);
842 }
843
844 for (const xAOD::MuonSegment* seg : *recoSegments) {
845 m_recoSegs->push_back(*seg);
846 }
847
849 if (idTracks) {
850 m_nIdTracks = idTracks->size();
851 for (const xAOD::TrackParticle* idTrk : *idTracks) {
852 if (m_truthTrks->find([idTrk](const xAOD::IParticle* p){
853 return xAOD::TruthHelpers::getTruthParticle(*idTrk) ==
854 xAOD::TruthHelpers::getTruthParticle(*p);
855 }) < m_truthTrks->size()) {
856 m_idTracks->push_back(idTrk);
857 }
858 }
859 }
860 if (idTags) {
861 m_nIdTags = idTags->size();
862 for (const MuonR4::MuonTag* idTag : *idTags) {
864 if (idTag->extrapolatedParsID(Acts::hashString("@CaloExit"))){
865 m_idTracks->push_back(idTag->idTrack());
866 }
867 }
868 }
869 return StatusCode::SUCCESS;
870 }
871 StatusCode MsTrackTester::execute(const EventContext& ctx) {
875
876 ATH_CHECK(m_tree.fill(ctx));
877 return StatusCode::SUCCESS;
878 }
880 ATH_CHECK(m_tree.write());
881 return StatusCode::SUCCESS;
882 }
883}
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, const std::string &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 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.
const xAOD::TruthParticle * truthTreeParticle(const xAOD::IParticle &part) const
Returns the matched truth particle that is dumped in the tree.
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.
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:69
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:
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