ATLAS Offline Software
MuSAVtxJPsiValidationAlg.cxx
Go to the documentation of this file.
1 /*
2 Copyright (C) 2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // this algorithm produces a J/Psi candidate muons container to be passed to the MuSAVtxFitter
6 // to be used in "tag and probe" style studies on the MuSA performance
10 #include "xAODMuon/Muon.h"
11 #include "xAODMuon/MuonContainer.h"
13 #include "xAODTracking/Vertex.h"
15 #include "AthLinks/ElementLink.h"
18 #include "VrtSecInclusive/Constants.h"
20 
21 namespace {
22  // Accessors for vertex properties
23  const SG::AuxElement::Accessor<float> vtx_pxAcc("vtx_px");
24  const SG::AuxElement::Accessor<float> vtx_pyAcc("vtx_py");
25  const SG::AuxElement::Accessor<float> vtx_pzAcc("vtx_pz");
26  const SG::AuxElement::Accessor<float> vtx_massAcc("vtx_mass");
27  const SG::AuxElement::Accessor<float> vtx_chargeAcc("vtx_charge");
28  const SG::AuxElement::Accessor<float> minOpAngAcc("minOpAng");
29  const SG::AuxElement::Accessor<float> chi2_coreAcc("chi2_core");
30  const SG::AuxElement::Accessor<float> ndof_coreAcc("ndof_core");
31  const SG::AuxElement::Accessor<float> chi2_assocAcc("chi2_assoc");
32  const SG::AuxElement::Accessor<float> ndof_assocAcc("ndof_assoc");
33  const SG::AuxElement::Accessor<float> massAcc("mass");
34  const SG::AuxElement::Accessor<float> mass_eAcc("mass_e");
35  const SG::AuxElement::Accessor<float> mass_selectedTracksAcc("mass_selectedTracks");
36  const SG::AuxElement::Accessor<int> num_trksAcc("num_trks");
37  const SG::AuxElement::Accessor<int> num_selectedTracksAcc("num_selectedTracks");
38  const SG::AuxElement::Accessor<int> num_associatedTracksAcc("num_associatedTracks");
39  const SG::AuxElement::Accessor<float> dCloseVrtAcc("dCloseVrt");
40 }
41 
42 namespace Rec {
43 
46 {}
47 
51  ATH_CHECK(m_JPsiMuonContainer.initialize());
52  ATH_CHECK(m_JPsiVertexContainer.initialize());
54 
55  ATH_CHECK(m_JPsiFinderTool.retrieve());
56  ATH_MSG_DEBUG("Retrieved J/Psi finder tool: " << m_JPsiFinderTool);
57 
58  ATH_MSG_DEBUG("Initialization successful");
59 
60  return StatusCode::SUCCESS;
61 }
62 
64 
65  const EventContext& ctx = Gaudi::Hive::currentContext();
66 
68  ATH_CHECK(muonContainer.isValid());
69 
71  ATH_CHECK(evtInfo.isValid());
72 
74  ATH_CHECK(JPsiMuonContainer.record(std::make_unique<xAOD::MuonContainer>(), std::make_unique<xAOD::MuonAuxContainer>()));
75 
77  ATH_CHECK(JPsiVertexContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
78 
80  ATH_CHECK(JPsiTrackParticleContainer.record(std::make_unique<xAOD::TrackParticleContainer>(), std::make_unique<xAOD::TrackParticleAuxContainer>()));
81 
82  // 1) Run J/Psi finder
83  auto jpsiVtxs = std::make_unique<xAOD::VertexContainer>();
84  auto jpsiAux = std::make_unique<xAOD::VertexAuxContainer>();
85  jpsiVtxs->setStore(jpsiAux.get());
86  ATH_CHECK(m_JPsiFinderTool->performSearch(ctx, *jpsiVtxs));
87 
88  if (jpsiVtxs->empty()) {
89  ATH_MSG_DEBUG("No J/Psi candidates found");
90  return StatusCode::SUCCESS;
91  } else {
92  ATH_MSG_DEBUG("Found " << jpsiVtxs->size() << " J/Psi candidates");
93  }
94 
95  for (const xAOD::Vertex* vtx : *jpsiVtxs) {
96  const auto& links = vtx->trackParticleLinks();
97  if (links.size() == 2) {
98  const xAOD::TrackParticle* tp1 = links[0].isValid() ? *links[0] : nullptr;
99  const xAOD::TrackParticle* tp2 = links[1].isValid() ? *links[1] : nullptr;
100  const xAOD::Muon* mu1 = tp1 ? findMuonFromTrack(tp1, muonContainer.cptr()) : nullptr;
101  const xAOD::Muon* mu2 = tp2 ? findMuonFromTrack(tp2, muonContainer.cptr()) : nullptr;
102 
103  if (!mu1 && !mu2) {
104  ATH_MSG_WARNING("No muons found for J/Psi vertex with index " << vtx->index());
105  continue;
106  } else if (!mu1 || !mu2) {
107  ATH_MSG_WARNING("Only one muon found for J/Psi vertex with index " << vtx->index());
108  } else {
109  ATH_MSG_DEBUG("Found J/Psi vertex with index " << vtx->index() << " and muons: " << mu1->index() << ", " << mu2->index());
110  }
111 
112  if (mu1) JPsiMuonContainer->push_back(new xAOD::Muon(*mu1));
113  if (mu2) JPsiMuonContainer->push_back(new xAOD::Muon(*mu2));
114  }
115 
116  // vertices right out of JPsiFinder have vxTrackAtVertex decorators that can't be saved to container
117  // thus we make a fresh copy to avoid this issue
118  xAOD::Vertex* newVtx = new xAOD::Vertex();
119  JPsiVertexContainer->push_back(newVtx); // add the vertex to the container first
120 
121  // Set properties of the new vertex
122  newVtx->setPosition(vtx->position());
123  newVtx->setCovariance(vtx->covariance());
124  newVtx->setFitQuality(vtx->chiSquared(), vtx->numberDoF());
125  newVtx->setVertexType(vtx->vertexType());
126 
127  // copy track particle links
128  for (const auto& link : vtx->trackParticleLinks()) {
129  if (!link.isValid()) continue;
130  const xAOD::TrackParticle* oldTrack = *link;
131  xAOD::TrackParticle* newTrack = new xAOD::TrackParticle();
132  newTrack->makePrivateStore(*oldTrack);
133  JPsiTrackParticleContainer->push_back(newTrack);
134  ElementLink<xAOD::TrackParticleContainer> newLink(*JPsiTrackParticleContainer, newTrack->index());
135  newVtx->addTrackAtVertex(newLink, 1.0); // weight is set to 1.0 for simplicity
136  }
137 
138  // add identical decos to musa for comparison
139  constexpr double muonMass = 105.658; // Muon mass in MeV
140  TLorentzVector sumP4_muon, sumP4_electron, sumP4_selected;
141  std::vector<const xAOD::TrackParticle*> vtxTracks;
142 
143  int vtxCharge = 0;
144 
145  for (const auto& link : newVtx->trackParticleLinks()) {
146  const xAOD::TrackParticle* track = link.isValid() ? *link : nullptr;
147  if (!track) continue;
148 
149  double pt = track->pt();
150  double eta = track->eta();
151  double phi = track->phi();
152 
153  TLorentzVector p4_muon, p4_electron;
154  p4_muon.SetPtEtaPhiM(pt, eta, phi, muonMass);
155  p4_electron.SetPtEtaPhiM(pt, eta, phi, VKalVrtAthena::PhysConsts::mass_electron);
156 
157  sumP4_muon += p4_muon;
158  sumP4_electron += p4_electron;
159  sumP4_selected += p4_muon; // assuming selected tracks are muons...
160 
161  vtxCharge += track->charge();
162  vtxTracks.push_back(track);
163  }
164 
165  //calculate opening angle between two tracks
166  float vtxDeltaR = 0;
167  if (vtxTracks.size() == 2) {
168  float dEta = vtxTracks[0]->eta() - vtxTracks[1]->eta();
169  float dPhi = std::abs(vtxTracks[0]->phi() - vtxTracks[1]->phi());
170  if (dPhi > M_PI) dPhi = 2 * M_PI - dPhi;
171  vtxDeltaR = std::sqrt(dEta * dEta + dPhi * dPhi);
172  }
173 
174  vtx_pxAcc(*newVtx) = sumP4_muon.Px();
175  vtx_pyAcc(*newVtx) = sumP4_muon.Py();
176  vtx_pzAcc(*newVtx) = sumP4_muon.Pz();
177  vtx_massAcc(*newVtx) = sumP4_muon.M();
178  vtx_chargeAcc(*newVtx) = vtxCharge;
179  minOpAngAcc(*newVtx) = vtxDeltaR;
180  chi2_coreAcc(*newVtx) = vtx->chiSquared();
181  ndof_coreAcc(*newVtx) = vtx->numberDoF();
182  chi2_assocAcc(*newVtx) = vtx->chiSquared();
183  ndof_assocAcc(*newVtx) = vtx->numberDoF();
184  massAcc(*newVtx) = sumP4_muon.M();
185  mass_eAcc(*newVtx) = sumP4_electron.M();
186  mass_selectedTracksAcc(*newVtx) = sumP4_selected.M();
187  num_trksAcc(*newVtx) = links.size();
188  num_selectedTracksAcc(*newVtx) = links.size(); // Assuming all tracks are selected
189  num_associatedTracksAcc(*newVtx) = links.size(); // Assuming all tracks are associated
190  dCloseVrtAcc(*newVtx) = 0; // not implemented but assigned for comparison to MuSA
191  }
192 
193  return StatusCode::SUCCESS;
194 }
195 
197  for (const xAOD::Muon* mu : *muons) {
198  if (mu->trackParticle(xAOD::Muon::CombinedTrackParticle) == tp) return mu;
199  if (mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) == tp) return mu;
200  }
201  return nullptr;
202 }
203 
204 } // namespace Rec
muonContainer
xAOD::MuonContainer * muonContainer
Definition: TrigGlobEffCorrValidation.cxx:188
xAOD::Vertex_v1::setPosition
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
xAOD::Vertex_v1::setFitQuality
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Definition: Vertex_v1.cxx:150
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition: Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
Muon.h
Rec::MuSAVtxJPsiValidationAlg::m_JPsiTrackParticleContainer
SG::WriteHandleKey< xAOD::TrackParticleContainer > m_JPsiTrackParticleContainer
Definition: MuSAVtxJPsiValidationAlg.h:32
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
xAOD::Vertex_v1::trackParticleLinks
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
Rec::MuSAVtxJPsiValidationAlg::m_eventInfo
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
Definition: MuSAVtxJPsiValidationAlg.h:28
test_pyathena.pt
pt
Definition: test_pyathena.py:11
M_PI
#define M_PI
Definition: ActiveFraction.h:11
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Rec::MuSAVtxJPsiValidationAlg::m_JPsiVertexContainer
SG::WriteHandleKey< xAOD::VertexContainer > m_JPsiVertexContainer
Definition: MuSAVtxJPsiValidationAlg.h:31
xAOD::Vertex_v1::setCovariance
void setCovariance(const std::vector< float > &value)
Sets the covariance matrix as a simple vector of values.
Rec::MuSAVtxJPsiValidationAlg::m_muonContainer
SG::ReadHandleKey< xAOD::MuonContainer > m_muonContainer
Definition: MuSAVtxJPsiValidationAlg.h:27
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
xAOD::TrackParticle
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Definition: Event/xAOD/xAODTracking/xAODTracking/TrackParticle.h:13
MuonAuxContainer.h
xAOD::Vertex_v1::setVertexType
void setVertexType(VxType::VertexType vType)
Set the type of the vertex.
xAOD::Vertex_v1::addTrackAtVertex
void addTrackAtVertex(const ElementLink< TrackParticleContainer > &tr, float weight=1.0)
Add a new track to the vertex.
Definition: Vertex_v1.cxx:314
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
TrackParticleAuxContainer.h
Rec
Name: MuonSpContainer.h Package : offline/Reconstruction/MuonIdentification/muonEvent.
Definition: FakeTrackBuilder.h:10
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
DMTest::links
links
Definition: CLinks_v1.cxx:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TauGNNUtils::Variables::Track::dEta
bool dEta(const xAOD::TauJet &tau, const xAOD::TauTrack &track, float &out)
Definition: TauGNNUtils.cxx:401
MuSAVtxJPsiValidationAlg.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Rec::MuSAVtxJPsiValidationAlg::m_JPsiFinderTool
ToolHandle< Analysis::JpsiFinder > m_JPsiFinderTool
Definition: MuSAVtxJPsiValidationAlg.h:34
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Vertex.h
Rec::MuSAVtxJPsiValidationAlg::MuSAVtxJPsiValidationAlg
MuSAVtxJPsiValidationAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: MuSAVtxJPsiValidationAlg.cxx:44
AthAlgorithm
Definition: AthAlgorithm.h:47
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
VKalVrtAthena::PhysConsts::mass_electron
constexpr double mass_electron
Definition: Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/Constants.h:15
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::AuxElement::makePrivateStore
void makePrivateStore()
Create a new (empty) private store for this object.
Definition: AuxElement.cxx:192
MuonContainer.h
Rec::MuSAVtxJPsiValidationAlg::execute
virtual StatusCode execute() override
Definition: MuSAVtxJPsiValidationAlg.cxx:63
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
VertexContainer.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
JpsiFinder.h
TauGNNUtils::Variables::Track::dPhi
bool dPhi(const xAOD::TauJet &tau, const xAOD::TauTrack &track, float &out)
Definition: TauGNNUtils.cxx:412
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
Rec::MuSAVtxJPsiValidationAlg::findMuonFromTrack
const xAOD::Muon * findMuonFromTrack(const xAOD::TrackParticle *tp, const xAOD::MuonContainer *muons)
Definition: MuSAVtxJPsiValidationAlg.cxx:196
CaloNoise_fillDB.mu
mu
Definition: CaloNoise_fillDB.py:51
Rec::MuSAVtxJPsiValidationAlg::m_JPsiMuonContainer
SG::WriteHandleKey< xAOD::MuonContainer > m_JPsiMuonContainer
Definition: MuSAVtxJPsiValidationAlg.h:30
Rec::MuSAVtxJPsiValidationAlg::initialize
virtual StatusCode initialize() override
Definition: MuSAVtxJPsiValidationAlg.cxx:48
VertexAuxContainer.h