8#include "AthLinks/ElementLink.h"
9#include "Identifier/Identifier.h"
15#include "Acts/Surfaces/PlaneSurface.hpp"
18#include <unordered_set>
21using namespace Acts::UnitLiterals;
24 using IdSet_t = std::unordered_set<Identifier>;
25 unsigned int countMatched(
const std::unordered_set<const xAOD::MuonSimHit*>& simHits,
26 const IdSet_t& matchIds) {
28 return matchIds.count(
hit->identify());
37 return Acts::Vector4::Zero();
57 return StatusCode::SUCCESS;
70 std::vector<IdDecorHandle_t> idDecorHandles{};
72 idDecorHandles.emplace_back(hitKey, ctx);
75 using IdSet_t = std::unordered_set<Identifier>;
76 using TruthTuple_t = std::tuple<const xAOD::TruthParticle*, IdSet_t>;
77 std::vector<TruthTuple_t> truthPartWithIds{};
79 std::vector<const xAOD::TruthParticle*> bkgMuons{};
80 truthPartWithIds.reserve(truthParticles->
size());
82 segLinkDecor(*truthMuon).clear();
84 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Truth muon "<<truthMuon->pt()<<
", eta: "<<truthMuon->eta()
85 <<
", phi: "<<(truthMuon->phi() / 1._degree)<<
", id: "<<
HepMC::uniqueID(truthMuon));
86 for (
const IdDecorHandle_t& hitDecor : idDecorHandles) {
87 std::ranges::transform(hitDecor(*truthMuon), std::inserter(assocIds, assocIds.begin()),
88 [
this](
unsigned long long rawId){
89 const Identifier id{rawId};
94 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Truth muon with pt: "<<(truthMuon->pt() / 1_GeV)
95 <<
", eta: "<<truthMuon->eta()<<
", phi: "<<truthMuon->phi()
96 <<
", uniqueID: "<<
HepMC::uniqueID(truthMuon)<<
", associated hits: "<<assocIds.size());
97 if (assocIds.empty()) {
98 bkgMuons.push_back(truthMuon);
100 truthPartWithIds.emplace_back(std::make_tuple(truthMuon, std::move(assocIds)));
108 TruthPartDecor_t truthLinkDecor{m_truthLinkKey, ctx};
110 std::vector<const xAOD::MuonSegment*> bkgSegments{};
114 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Reconstructed truth segment "
117 <<
", phi: "<<segment->sector()<<
", nPrecHits: "<<segment->nPrecisionHits()
118 <<
", nDoF: "<<segment->numberDoF()<<
" sim hits: "<<simHits.size());
119 if (msgLvl(MSG::VERBOSE)){
120 std::vector<const xAOD::MuonSimHit*> sortedHits{simHits.begin(), simHits.end()};
122 return a->identify() <
b->identify();
125 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Associated sim hit: "<<m_idHelperSvc->toString(
hit->identify())
128 <<
", "<<
hit->genParticleLink());
132 if (!(*simHits.begin())->genParticleLink().isValid()) {
133 bkgSegments.push_back(segment);
134 truthLinkDecor(*segment) = TruthPartLink_t{};
138 const auto best_itr = std::ranges::max_element(truthPartWithIds,
139 [&simHits](
const TruthTuple_t& truthTupleA,
140 const TruthTuple_t& truthTupleB) {
141 return countMatched(simHits, std::get<1>(truthTupleA)) <
142 countMatched(simHits, std::get<1>(truthTupleB));
144 if (best_itr == truthPartWithIds.end()) {
145 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - No truth particle matched the truth hits of the segment");
148 if (1.*countMatched(simHits, std::get<1>(*best_itr)) < 0.5* simHits.size()) {
149 if (msgLvl(MSG::VERBOSE)) {
150 for (
const auto& [truthMuon, assocIds]: truthPartWithIds){
151 std::stringstream unMatchedStr{};
154 if (!assocIds.count(
hit->identify())){
155 unMatchedStr<<
" *** "<<m_idHelperSvc->toString(
hit->identify())<<std::endl;
165 <<counts<<
", unmatched: "<<std::endl<<unMatchedStr.str());
171 segLinkDecor(*truthPart).emplace_back(segments, segment->index());
172 truthLinkDecor(*segment) = TruthPartLink_t{truthParticles, truthPart->index()};
175 matchPileupSegments(ctx, bkgMuons, bkgSegments, truthLinkDecor, segLinkDecor);
182 std::ranges::sort(linkedSegs,[&pos, &dir](
const SegLink_t& linkA,
const SegLink_t& linkB){
183 return dir.dot((*linkA)->position() - pos) <
184 dir.dot((*linkB)->position() - pos);
187 return StatusCode::SUCCESS;
190 const std::vector<const xAOD::TruthParticle*>& pileUpMuons,
191 const std::vector<const xAOD::MuonSegment*>& pileUpSegments,
196 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Matching between pile-up segments & muons is disabled");
199 if (pileUpMuons.empty() || pileUpSegments.empty()) {
200 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Segments ("<<pileUpSegments.size()<<
") or muons ("
201 <<pileUpMuons.size()<<
") are empty -> nothing to do");
205 std::stringstream sstr{};
207 sstr<<
" *** pT: "<<(bkgMuon->pt() / 1_GeV)<<
", eta: "<<bkgMuon->eta()
208 <<
", phi: "<<(bkgMuon->phi() / 1_degree)<<
", pdgId: "<<bkgMuon->pdgId()
210 <<
", uid: "<<bkgMuon->uid() <<std::endl;
212 sstr<<
"\n To these segments: "<<std::endl;
213 unsigned int counter{0};
215 sstr<<
" "<<(counter++)<<
") "<<
Amg::toString(bkgSeg->position())
216 <<
", phi: "<<(bkgSeg->position().
phi() / 1_degree)<<
", eta: "<<(bkgSeg->position().
eta())
217 <<
", pT: "<< (acc_pt(*bkgSeg) / 1_GeV)
219 <<
", sector: "<<bkgSeg->sector()<<
", nPrecHits: "<<bkgSeg->nPrecisionHits()
220 <<
", chi2: "<<(bkgSeg->chiSquared() / std::max(bkgSeg->numberDoF(), 1.f))
221 <<
", nDoF: "<<bkgSeg->numberDoF()<<std::endl;
223 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - \nMatch the following muons "<<std::endl<<sstr.str());
225 std::vector<char> segmentMatched(pileUpSegments.size(), 0);
227 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
230 const Acts::Vector4 fourPos = vertexPos(*bkgMuon);
235 auto startSurf = Acts::Surface::makeShared<Acts::PlaneSurface>(
Amg::getTranslate3D(start));
238 Acts::BoundMatrix initialCov{Acts::BoundMatrix::Identity()};
240 auto initialPars = Acts::BoundTrackParameters::create(tgContext, startSurf, fourPos, threeMom.unit(),
241 bkgMuon->charge() / threeMom.mag(),
242 initialCov, Acts::ParticleHypothesis::muon());
243 if(!initialPars.ok()) {
244 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - Failed to create start parameters");
248 <<
Amg::toString(threeMom) <<
", pT: "<<(threeMom.perp() / 1_GeV)
249 <<
" GeV, eta: "<<threeMom.eta()<<
", phi: "<<(threeMom.phi() / 1_degree)<<
", q: "<<bkgMuon->charge());
251 for (std::size_t sIdx =0 ; sIdx < pileUpSegments.size(); ++sIdx) {
253 if (segmentMatched[sIdx]) {
257 if (acc_q(*bkgSeg) != bkgMuon->charge()) {
258 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Segment charge does not match");
264 const double lDist = std::abs(
Amg::lineDistance(segPos, segDir, start, threeMom.unit()));
265 const double dPhi = std::abs(segPos.deltaPhi(threeMom));
267 <<
", "<<
Amg::toString(segDir) <<
", lDist: "<<lDist<<
", dPhi: "<<(dPhi / 1_degree));
274 if (!propPars.ok()) {
275 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Extrapolation failed.");
279 const Amg::Vector2D dPosExtp = propPars->localPosition() - (sector->globalToLocalTransform(tgContext) * segPos).segment<2>(0);
280 const double dThetaExtp = std::abs(segDir.theta() - propPars->theta());
281 const double dPhiExtp = std::abs(segDir.phi() - propPars->phi());
283 <<
", dTheta:"<<(dThetaExtp / 1._degree)<<
", dPhi: "<<(dPhiExtp / 1._degree));
288 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Parameters differ too much. Cut values"
293 truthSegDecor(*bkgMuon).emplace_back(truthPartDecor.
container(), bkgSeg->index());
294 segmentMatched[sIdx] =
true;
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
ATLAS-specific HepMC functions.
Handle class for reading a decoration on an object.
Handle class for adding a decoration to an object.
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
size_type size() const noexcept
Returns the number of elements in the collection.
ElementLink implementation for ROOT usage.
Gaudi::Property< std::vector< std::string > > m_simHitIds
List of simHit id decorations to read from the truth particle.
Gaudi::Property< bool > m_includePileUpObjs
Property checking whether a pile-up muons shall be matched to pile-up segments.
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the muon detector manager.
xAOD::ContainerDecorator< xAOD::TruthParticleContainer, TruthSegLinkVec_t > TruthSegLinkDecor_t
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_truthLinkKey
Key of the truthParticleLink decorated onto the segment.
ActsTrk::ContextUtility m_ctxProvider
Context provider for geometry, magnetic field and calibration contexts.
ElementLink< xAOD::TruthParticleContainer > TruthPartLink_t
virtual StatusCode initialize() override final
Gaudi::Property< double > m_pileUpObjExtpDthetaCut
Cut on the delta theta between the bkg segment and the extrapolated parameters.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthKey
Key to the truth particle container to associate.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc to decode the Identifiers.
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_segLinkKey
Declaration of the segmentLink to the truth particle.
Gaudi::Property< double > m_pileUpObjDPhiCut
Delta phi cut between particle momentum & segment position to start the extrapolation.
Gaudi::Property< double > m_pileUpObjExtpDyCut
Cut on the delta y0 between the bkg segment and the extrapolated parameters.
xAOD::ContainerDecorator< xAOD::MuonSegmentContainer, TruthPartLink_t > TruthPartDecor_t
void matchPileupSegments(const EventContext &ctx, const std::vector< const xAOD::TruthParticle * > &pileUpMuons, const std::vector< const xAOD::MuonSegment * > &pileUpSegments, TruthPartDecor_t &truthPartDecor, TruthSegLinkDecor_t &truthSegDecor) const
Match truth muons without any HEPMC link with truth segments reconstructed in the MS.
virtual StatusCode execute(const EventContext &ctx) const override final
Gaudi::Property< double > m_pileUpObjExtpDphiCut
Cut on the delta phi between the bkg segment and the extrapolated parameters.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_segmentKey
Key to the truth segment container to associate.
SG::ReadDecorHandleKeyArray< xAOD::TruthParticleContainer > m_simHitKeys
Declaration of the dependency on the simHit decorations.
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
Track extrapolation tool.
Gaudi::Property< double > m_pileUpObjExtpDxCut
Cut on the delta x0 between the bkg segment and the extrapolated parameters.
Helper class to provide constant type-safe access to aux data.
Property holding a SG store/key/clid/attr name from which a ReadDecorHandle is made.
Handle class for reading a decoration on an object.
Auxiliary class to instantiate WriteDecorHandles.The handles can be created in an empty state.
const Cont_t * container() const
Returns the underlying container.
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 ).
bool hasProdVtx() const
Check for a production vertex on this particle.
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
float z() const
Vertex longitudinal distance along the beam line form the origin.
float y() const
Vertex y displacement.
float t() const
Vertex time.
float x() const
Vertex x displacement.
std::pair< Amg::Vector3D, double > convertPosFromActs(const Acts::Vector4 &actsPos)
Converts an Acts 4-vector into a pair of an Athena spatial vector and the passed time.
Acts::Vector4 convertMomToActs(const Amg::Vector3D &threeMom, const double mass=0.)
Converts a three momentum vector from Athena together with the associated particle mass into an Acts ...
Acts::Vector4 convertPosToActs(const Amg::Vector3D &athenaPos, const double athenaTime=0.)
Converts a position vector & time from Athena units into Acts units.
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
double lineDistance(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
: Calculates the shortest distance between two lines
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
This header ties the generic definitions in this package.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
std::vector< SegLink_t > SegLinkVec_t
ElementLink< xAOD::MuonSegmentContainer > SegLink_t
const std::string & chName(ChIndex index)
convert ChIndex into a string
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
TruthVertex_v1 TruthVertex
Typedef to implementation.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
TruthParticle_v1 TruthParticle
Typedef to implementation.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.