16#include "Acts/Definitions/Units.hpp"
23using namespace Acts::UnitLiterals;
27 constexpr double toDeg(
const double rad) {
28 return rad / 1._degree;
38 if (matchedSegs.empty()) {
51 const auto [barrelLength, barrelTheta] =
calcSeedLength(gctx, barrelSeed);
52 const auto [endcapLength, endcapTheta] =
calcSeedLength(gctx, endcapSeed);
53 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Constructed new seed from truth muon wih pT:"
54 <<(truthMuon.pt()/ Gaudi::Units::GeV)<<
" [GeV], eta: "<<truthMuon.eta()
55 <<
", phi: "<<toDeg(truthMuon.phi())<<
", q: "<<truthMuon.charge()
56 <<
", matchedSeg: "<<matchedSegs.size()<<
" barrel (L/theta): "<<barrelLength
57 <<
"/"<<barrelTheta<<
" - endcap (L/theta): "
58 <<endcapLength<<
"/"<<endcapTheta<<
"\n"<<barrelSeed);
59 if (barrelLength < 0 && endcapLength < 0) {
63 return barrelLength < 0 || std::abs(endcapLength) < barrelLength
64 ? endcapSeed : barrelSeed;
69 double maxL{-1.*Gaudi::Units::km}, minL{1.*Gaudi::Units::km},
70 maxTheta{-181.}, minTheta{181};
73 if (!
m_seeder->withinBounds(projPos, seed.location())) {
76 const double projected = projPos[seed.location()==Location::Barrel];
77 const double theta = seg->direction().theta();
78 minL = std::min(minL, projected);
79 maxL = std::max(maxL, projected);
80 minTheta = std::min(minTheta, toDeg(
theta));
81 maxTheta = std::max(maxTheta, toDeg(
theta));
83 return std::make_pair(maxL - minL, maxTheta - minTheta);
109 m_seeder = std::make_unique<MuonR4::MsTrackSeeder>(name(), std::move(seederCfg));
117 return m_segSelector->passSeedingQuality(Gaudi::Hive::currentContext(),
122 return m_segSelector->passTrackQuality(Gaudi::Hive::currentContext(),
133 const unsigned linkIdx = truthS ?
m_truthSegs->push_back(*truthS) : -1;
153 unsigned short linkIdx =
m_truthTrks->find(truthP);
156 for (
auto loc : {Location::Barrel, Location::Endcap}) {
158 std::format(
"TruthSegments_has{}Proj", loc), [loc,
this](
const SG::AuxElement* aux){
164 if (
m_seeder->withinBounds(projPos, loc)) {
179 std::vector<unsigned short>>>(
m_tree,
181 std::vector<unsigned short> idx{};
191 return getTruthSegments(p).size();
197 const auto truthSegs = getTruthSegments(p);
198 if (truthSegs.size() < 2) {
204 return toDeg(
m_seeder->estimateTwoStationP(*truthSegs.front(), *truthSegs.back(),
208 auto cone = std::make_shared<VectorBranch<float>>(m_tree,
209 std::format(
"{}_seedThetaCone", m_truthTrks->name()));
210 auto qTimesP = std::make_shared<VectorBranch<float>>(m_tree,
211 std::format(
"{}_qTimesP", m_truthTrks->name()));
213 m_tree.addBranch(cone);
214 m_tree.addBranch(qTimesP);
217 std::format(
"{:}_seedLength", m_truthTrks->name()), [cone, qTimesP,
this] (
const xAOD::TruthParticle& p) ->
float {
220 const EventContext& ctx{Gaudi::Hive::currentContext()};
221 (void)
SG::get(magCache, m_fieldCacheKey, ctx).isSuccess();
222 (void)
SG::get(gctx, m_geoCtxKey, ctx).isSuccess();
224 auto truthSeed = makeSeedFromTruth(*gctx, p);
227 qTimesP->push_back(0);
230 auto [
length,
theta] = calcSeedLength(*gctx, *truthSeed);
231 cone->push_back(
theta);
232 qTimesP->push_back(m_seeder->estimateQtimesP(*gctx, *magCache, *truthSeed) / Gaudi::Units::GeV);
237 m_tree.addBranch(m_truthTrks);
238 m_trkTruthLinks.emplace_back(m_truthSegmentKey,
"truthParticleLink");
239 m_trkTruthLinks.emplace_back(m_truthKey,
"truthSegmentLinks");
240 m_trkTruthLinks.emplace_back(m_recoSegmentKey,
"truthSegmentLink");
241 m_trkTruthLinks.emplace_back(m_muonKey,
"truthParticleLink");
244 m_tree.addBranch(m_recoSegs);
245 m_tree.addBranch(std::make_unique<EventInfoBranch>(m_tree, evOpts));
247 static const std::vector<std::string> trackSummaries{
249 "innerSmallHits",
"innerLargeHits",
"innerSmallHoles",
"innerLargeHoles",
251 "middleSmallHits",
"middleLargeHits",
"middleSmallHoles",
254 "outerSmallHits",
"outerLargeHits",
"outerSmallHoles",
"outerLargeHoles",
256 "extendedSmallHits",
"extendedLargeHits",
"extendedSmallHoles",
257 "extendedLargeHoles",
258 "innerTriggerEtaHits",
"innerTriggerPhiHits",
259 "middleTriggerEtaHits",
"middleTriggerPhiHits",
260 "outerTriggerEtaHits",
"outerTriggerPhiHits",
262 "innerTriggerEtaHoles",
"innerTriggerPhiHoles",
263 "middleTriggerEtaHoles",
"middleTriggerPhiHoles",
264 "outerTriggerEtaHoles",
"outerTriggerPhiHoles",
266 if(!m_legacyTrackKey.empty()) {
267 m_legacyTrks = std::make_unique<IParticleFourMomBranch>(m_tree,
"LegacyMSTrks");
268 m_legacyTrks->addVariable(std::make_unique<TrackChi2Branch>(*m_legacyTrks));
273 for (
const auto& summary : trackSummaries) {
276 m_tree.addBranch(m_legacyTrks);
277 m_legacyRecoSegs = std::make_unique<SegmentVariables>(m_tree, m_legacySegmentKey.key(),
"LegacyRecoSegments", msgLevel());
278 m_tree.addBranch(m_legacyRecoSegs);
281 m_seedSummary = std::make_shared<TrackSummaryModule>(m_tree,
"MsTrkSeed", m_summaryTool.get());
282 m_muonTrks = std::make_shared<IParticleFourMomBranch>(m_tree,
"ActsMuons");
283 m_muonTrks->addVariable(std::make_unique<TrackChi2Branch>(*m_muonTrks));
284 m_muonTrks->addVariable<
uint16_t>(
"allAuthors");
285 m_muonTrks->addVariable<
uint16_t>(
"author");
288 std::vector<unsigned short>>>(m_tree,
289 std::format(
"{:}_segmentLinks", m_muonTrks->name()), [&] (
const xAOD::Muon& p){
290 std::vector<unsigned short> idx{};
291 for (
unsigned seg = 0 ; seg <
p.nMuonSegments(); ++seg) {
292 idx.push_back(m_recoSegs->push_back(*
p.muonSegment(seg)));
298 std::format(
"{:}_seedLink", m_muonTrks->name()), [&] (
const xAOD::Muon& p) ->
unsigned short {
299 using enum xAOD::Muon::TrackParticleType;
300 const xAOD::TrackParticle* msTrack = p.trackParticle(MuonSpectrometerTrackParticle);
306 THROW_EXCEPTION(
"Cannot find the associated ms track from the primary track");
308 return actsTrk->component<std::size_t>(
"parentSeed");
315 },
"truth",
"ActsMuon");
318 for (
const auto& summary : trackSummaries) {
321 m_tree.addBranch(m_muonTrks);
323 m_tree.addBranch(m_seedSummary);
327 return StatusCode::SUCCESS;
336 return StatusCode::SUCCESS;
340 ATH_MSG_VERBOSE(
"iMuon " << muon->index() <<
" pT: "<<(muon->pt() *MeVtoGeV)<<
" [GeV], eta: "
341 <<muon->eta() <<
", phi: "<<toDeg(muon->phi())<<
", q: "<<muon->charge()
342 <<
", nSegments: "<<muon->nMuonSegments());
343 const xAOD::TrackParticle* track = muon->trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle);
350 for (
size_t s = 0; s < muon->nMuonSegments(); ++s) {
353 ATH_MSG_VERBOSE(std::format(
"Legacy muon-segment link: segment {:} @{:}, eta: {:.2f}, phi {:.2f}",
364 if (legacyRecoSegs->
size()) {
380 return StatusCode::SUCCESS;
384 return StatusCode::SUCCESS;
397 Amg::toString(seg->position())<<
", eta: "<<seg->direction().eta()
398 <<
", phi: "<<toDeg(seg->direction().phi()));
401 if (truthSegs->
size()) {
408 const std::size_t nT = truthMuons->
size() - 1;
409 if (!truthMuons->
empty()) {
418 <<
", eta: "<<truth->eta()<<
", phi: "<<toDeg(truth->phi())<<
", q: "<<truth->charge());
422 return StatusCode::SUCCESS;
441 std::vector<unsigned>> truthToSeedMatchCounter{};
443 if (!trkSeeds->empty()) {
450 m_seedType+= Acts::toUnderlying(seed.location());
457 truthSeg !=
nullptr) {
459 if (seedIdx >= matchCounter.size()) {
460 matchCounter.resize(seedIdx +1);
462 ++matchCounter[seedIdx];
468 m_seedQP +=
m_seeder->estimateQtimesP(*gctx, *magCache, seed) / Gaudi::Units::GeV;
471 for (
auto& [truthMuon, matches] : truthToSeedMatchCounter) {
472 const unsigned tIndex =
m_truthTrks->find(truthMuon);
477 while (std::count_if(matches.begin(), matches.end(),
478 [](
const unsigned nMatched){
481 auto bestMatch = std::ranges::max_element(matches);
482 const std::size_t seedIdx = std::distance(matches.begin(), bestMatch);
499 return StatusCode::SUCCESS;
507 return StatusCode::SUCCESS;
511 return StatusCode::SUCCESS;
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Handle class for reading from StoreGate.
const ServiceHandle< StoreGateSvc > & detStore() const
StatusCode addVariable(const std::string &name, T *&ptr, const std::string &docstring="")
Add a variable to the tuple.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
void addSegment(const xAOD::MuonSegment *seg)
Append a segment to the seed.
void setPosition(Amg::Vector3D &&pos)
set the seed's position
MsTrackSeed::Location Location
Enum toggling whether the segment is in the endcap or barrel.
const MuonGMR4::MuonDetectorManager * m_detMgr
std::optional< MuonR4::MsTrackSeed > makeSeedFromTruth(const ActsTrk::GeometryContext &gctx, const xAOD::TruthParticle &truthMuon) const
Construct MS track seed from the truth associated segments.
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.
MuonVal::VectorBranch< unsigned short > & m_legacySegToTrkLinks
Link of the legacy track to the legacy segment.
ParticleBranchPtr_t m_truthTrks
std::unique_ptr< MuonR4::MsTrackSeeder > m_seeder
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::MatrixBranch< unsigned short > & m_truthMuRecoSegLinks
Links from the truth muon to the segments.
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.
ActsTrk::GeoContextReadKey_t m_geoCtxKey
Dependency on the geometry alignment.
StatusCode execute(const EventContext &ctx) override final
Execute method.
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< bool > m_isMC
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.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheKey
Dependency on the magnetic field.
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.
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.
MuonKey_t m_legacyMuonKey
Legacy muons.
MuonVal::VectorBranch< float > & m_seedLength
Maximum separation between the segments on the reference plane.
ToolHandle< MuonR4::ISegmentSelectionTool > m_segSelector
Segment selection tool to pick the good quality segments.
SegmentKey_t m_recoSegmentKey
Primary segment container.
MuonVal::MuonTesterTree m_tree
SegmentKey_t m_truthSegmentKey
Segment from the truth hits.
StatusCode finalize() override final
std::shared_ptr< TrackSummaryModule > m_seedSummary
Hit summary on the track seed.
MuonVal::VectorBranch< unsigned short > & m_seedTruthLink
Link to the truth muon.
std::pair< double, double > calcSeedLength(const ActsTrk::GeometryContext &gctx, const MuonR4::MsTrackSeed &seed) const
Calculate the length of the seed and the theta deflection angle The length is defined as the spread o...
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...
Class providing the definition of the 4-vector interface.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
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.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
ID3PD * m_tree
Pointer to the ID3PD object used.
for(size_t i=0;i< m_blockFillers.size();i++)
Fill one block.
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
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
std::vector< const xAOD::MuonSegment * > getTruthSegments(const xAOD::TruthParticle &truthMuon)
Returns the segments associated to the truth muon.
const xAOD::MuonSegment * getMatchedTruthSegment(const xAOD::MuonSegment &segment)
Returns the truth-matched segment.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::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.
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.
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:
TruthParticle_v1 TruthParticle
Typedef to implementation.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Muon_v1 Muon
Reference the current persistent version:
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.
double endcapDiscRadius
Radius of the endcap discs.
const MuonGMR4::MuonDetectorManager * detMgr
Detector manager to fetch the sector enevelope transforms.
double seedHalfLength
Maximum separation of point on the cylinder to be picked up onto a seed.
#define THROW_EXCEPTION(MESSAGE)