ATLAS Offline Software
Loading...
Searching...
No Matches
MuSAVtxFitter.cxx
Go to the documentation of this file.
1/*
2Copyright (C) 2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Header include
11#include "VrtSecInclusive/Constants.h"
12
13namespace {
14 // accessors for vertex links
16 const SG::AuxElement::Accessor<std::vector<ElementLink<xAOD::MuonContainer>>> acc_MuonLinks("MuSAVtx_MuonLinks");
17 const SG::AuxElement::Accessor<ElementLink<xAOD::MuonContainer>> acc_MuonLink("MuSATrk_MuonLink");
18 const SG::AuxElement::Accessor<ElementLink<xAOD::TrackParticleContainer>> acc_MSTPLink("MuSATrk_MSTPLink");
19 // accessors for vertex properties
20 const SG::AuxElement::Accessor<float> vtx_pxAcc("vtx_px");
21 const SG::AuxElement::Accessor<float> vtx_pyAcc("vtx_py");
22 const SG::AuxElement::Accessor<float> vtx_pzAcc("vtx_pz");
23 const SG::AuxElement::Accessor<float> vtx_massAcc("vtx_mass");
24 const SG::AuxElement::Accessor<float> vtx_chargeAcc("vtx_charge");
25 const SG::AuxElement::Accessor<float> minOpAngAcc("minOpAng");
26 const SG::AuxElement::Accessor<float> chi2_coreAcc("chi2_core");
27 const SG::AuxElement::Accessor<float> ndof_coreAcc("ndof_core");
28 const SG::AuxElement::Accessor<float> chi2_assocAcc("chi2_assoc");
29 const SG::AuxElement::Accessor<float> ndof_assocAcc("ndof_assoc");
30 const SG::AuxElement::Accessor<float> massAcc("mass");
31 const SG::AuxElement::Accessor<float> mass_eAcc("mass_e");
32 const SG::AuxElement::Accessor<float> mass_selectedTracksAcc("mass_selectedTracks");
33 const SG::AuxElement::Accessor<int> num_trksAcc("num_trks");
34 const SG::AuxElement::Accessor<int> num_selectedTracksAcc("num_selectedTracks");
35 const SG::AuxElement::Accessor<int> num_associatedTracksAcc("num_associatedTracks");
36 const SG::AuxElement::Accessor<float> dCloseVrtAcc("dCloseVrt");
37 // accessors for track parameters wrt vertex
38 const SG::AuxElement::Accessor<float> qOverP_wrtSVAcc("qOverP_wrtSV");
39 const SG::AuxElement::Accessor<float> theta_wrtSVAcc("theta_wrtSV");
40 const SG::AuxElement::Accessor<float> p_wrtSVAcc("p_wrtSV");
41 const SG::AuxElement::Accessor<float> pt_wrtSVAcc("pt_wrtSV");
42 const SG::AuxElement::Accessor<float> eta_wrtSVAcc("eta_wrtSV");
43 const SG::AuxElement::Accessor<float> phi_wrtSVAcc("phi_wrtSV");
44 const SG::AuxElement::Accessor<float> d0_wrtSVAcc("d0_wrtSV");
45 const SG::AuxElement::Accessor<float> z0_wrtSVAcc("z0_wrtSV");
46 const SG::AuxElement::Accessor<float> sqrd0Err_wrtSVAcc("sqrd0Err_wrtSV");
47 const SG::AuxElement::Accessor<float> sqrz0Err_wrtSVAcc("sqrz0Err_wrtSV");
48 const SG::AuxElement::Accessor<float> sqrQoPErr_wrtSVAcc("sqrQoPErr_wrtSV");
49}
50
51namespace Rec {
52
54
56{
57 ATH_CHECK( m_muonContainer.initialize() );
58 ATH_CHECK( m_MSTPContainer.initialize() );
59 ATH_CHECK( m_eventInfo.initialize() );
60 ATH_CHECK( m_MuSAVertices.initialize() );
61 ATH_CHECK( m_MuSAExtrapolatedTracks.initialize() );
62
63 ATH_CHECK( m_MuSAVtxFitterTool.retrieve() );
64 ATH_MSG_DEBUG("Retrieved tool " << m_MuSAVtxFitterTool);
65
66 ATH_CHECK( m_trackToVertexTool.retrieve() );
67 ATH_MSG_DEBUG("Retrieved tool " << m_trackToVertexTool);
68
69 ATH_MSG_DEBUG("Initialization successful");
70
71 return StatusCode::SUCCESS;
72
73}
74
75StatusCode MuSAVtxFitter::fillCollections(std::vector<MuSAVtxFitterTool::WrkVrt>& workVerticesContainer,
76 xAOD::VertexContainer* MuSAVtxContainer,
77 xAOD::TrackParticleContainer* MuSAExtrapolatedTracksContainer,
79 const xAOD::TrackParticleContainer& MSTPContainer,
80 const EventContext& ctx) const
81{
82 ATH_MSG_DEBUG("MuSAVtxFitter::fillCollections");
83 for (const auto& workVertex : workVerticesContainer) {
84
85 xAOD::Vertex* MuSAVertex = new xAOD::Vertex();
86 MuSAVtxContainer->emplace_back(MuSAVertex);
87
88 // Place the new extrapolated tracks in the new container (we need the index for bookkeeping)
89 for (size_t i = 0; i < workVertex.newExtrapolatedTracks.size(); i++) {
90
91 // copy transfers ownership of the shared_ptr in wrkvrt to container
92 xAOD::TrackParticle* containerTrack = MuSAExtrapolatedTracksContainer->push_back(new xAOD::TrackParticle());
93 *containerTrack=*workVertex.newExtrapolatedTracks[i];
94
95 // Link the new tracks to the vertex
96 ElementLink<xAOD::TrackParticleContainer> link_trk(*MuSAExtrapolatedTracksContainer, MuSAExtrapolatedTracksContainer->size() - 1);
97 MuSAVertex->addTrackAtVertex(link_trk, 1.0);
98
99 //Also link the extrapolated tracks and vertices to their original muons -- extrapolated tracks and their muons should have the same index in workVertex
100
101 bool muonLinkSuccess = false;
102 bool MSTPLinkSuccess = false;
103
106 muonLinkSuccess = link_muon.toContainedElement(muonContainer, workVertex.muonCandidates[i]);
107
108 const xAOD::Muon* muon = muonContainer[link_muon.index()];
109 const xAOD::TrackParticle* MSTP = muon->trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
110 if (MSTP) {
111 MSTPLinkSuccess = link_MSTP.toContainedElement(MSTPContainer, MSTP);
112 }
113
114 // Check that links are valid
115 if (!MSTPLinkSuccess) {
116 ATH_MSG_WARNING("Failed to link MSTP!");
117 } else {
118 acc_MSTPLink(*containerTrack) = link_MSTP;
119 auto& mstpLinks = acc_MSTPLinks(*MuSAVertex);
120 mstpLinks.push_back(link_MSTP);
121 }
122
123 if (!muonLinkSuccess) {
124 ATH_MSG_WARNING("Failed to link muon!");
125 } else {
126 acc_MuonLink(*containerTrack) = link_muon;
127 auto& muonLinks = acc_MuonLinks(*MuSAVertex);
128 muonLinks.push_back(link_muon);
129 }
130 }
131
132 MuSAVertex->setPosition(workVertex.pos);
134 MuSAVertex->setFitQuality(workVertex.chi2, 1);
135 std::vector<float> fCov(workVertex.cov.cbegin(), workVertex.cov.cend());
136 MuSAVertex->setCovariance(fCov);
137
138 vtx_pxAcc(*MuSAVertex) = workVertex.mom.Px();
139 vtx_pyAcc(*MuSAVertex) = workVertex.mom.Py();
140 vtx_pzAcc(*MuSAVertex) = workVertex.mom.Pz();
141
142 vtx_massAcc(*MuSAVertex) = workVertex.mom.M();
143 vtx_chargeAcc(*MuSAVertex) = workVertex.charge;
144
145 minOpAngAcc(*MuSAVertex) = workVertex.minOpAng;
146
147 chi2_coreAcc(*MuSAVertex) = workVertex.chi2Core;
148 ndof_coreAcc(*MuSAVertex) = 1;
149 chi2_assocAcc(*MuSAVertex) = workVertex.chi2;
150 ndof_assocAcc(*MuSAVertex) = workVertex.ndof();
151
152 TLorentzVector sumP4_muon;
153 TLorentzVector sumP4_electron;
154 TLorentzVector sumP4_selected;
155
156 constexpr double muonMass = 105.658; // Muon mass in MeV
157
158 for (size_t i = 0; i < workVertex.newExtrapolatedTracks.size(); i++) {
159 const xAOD::TrackParticle* track = workVertex.newExtrapolatedTracks[i].get();
160 double pt_wrtSV = track->pt();
161 double eta_wrtSV = track->eta();
162 double phi_wrtSV = track->phi();
163
164 TLorentzVector p4wrtSV_muon;
165 TLorentzVector p4wrtSV_electron;
166
167 p4wrtSV_muon.SetPtEtaPhiM(pt_wrtSV, eta_wrtSV, phi_wrtSV, muonMass);
168 p4wrtSV_electron.SetPtEtaPhiM(pt_wrtSV, eta_wrtSV, phi_wrtSV, VKalVrtAthena::PhysConsts::mass_electron);
169
170 sumP4_muon += p4wrtSV_muon;
171 sumP4_electron += p4wrtSV_electron;
172 sumP4_selected += p4wrtSV_muon;
173
174 size_t trackIndex = MuSAVertex->trackParticleLinks()[i].index();
175 xAOD::TrackParticle* containerTrack = MuSAExtrapolatedTracksContainer->at(trackIndex);
176
177 std::unique_ptr<Trk::Perigee> sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *containerTrack, workVertex.pos);
178 if (!sv_perigee) {
179 ATH_MSG_WARNING("Failed in obtaining the SV perigee for track!");
180 continue;
181 }
182
183 double qOverP_wrtSV = sv_perigee->parameters()[Trk::qOverP];
184 double theta_wrtSV = sv_perigee->parameters()[Trk::theta];
185 double p_wrtSV = 1.0 / std::abs(qOverP_wrtSV);
186 pt_wrtSV = p_wrtSV * sin(theta_wrtSV);
187 eta_wrtSV = -log(tan(theta_wrtSV / 2.0));
188 phi_wrtSV = sv_perigee->parameters()[Trk::phi];
189 double d0_wrtSV = sv_perigee->parameters()[Trk::d0];
190 double z0_wrtSV = sv_perigee->parameters()[Trk::z0];
191 double sqrd0Err_wrtSV = (*sv_perigee->covariance())(Trk::d0, Trk::d0);
192 double sqrz0Err_wrtSV = (*sv_perigee->covariance())(Trk::z0, Trk::z0);
193 double sqrQoPErr_wrtSV = (*sv_perigee->covariance())(Trk::qOverP, Trk::qOverP);
194
195 qOverP_wrtSVAcc(*containerTrack) = qOverP_wrtSV;
196 theta_wrtSVAcc(*containerTrack) = theta_wrtSV;
197 p_wrtSVAcc(*containerTrack) = p_wrtSV;
198 pt_wrtSVAcc(*containerTrack) = pt_wrtSV;
199 eta_wrtSVAcc(*containerTrack) = eta_wrtSV;
200 phi_wrtSVAcc(*containerTrack) = phi_wrtSV;
201 d0_wrtSVAcc(*containerTrack) = d0_wrtSV;
202 z0_wrtSVAcc(*containerTrack) = z0_wrtSV;
203 sqrd0Err_wrtSVAcc(*containerTrack) = sqrd0Err_wrtSV;
204 sqrz0Err_wrtSVAcc(*containerTrack) = sqrz0Err_wrtSV;
205 sqrQoPErr_wrtSVAcc(*containerTrack) = sqrQoPErr_wrtSV;
206 }
207
208 massAcc(*MuSAVertex) = sumP4_muon.M();
209 mass_eAcc(*MuSAVertex) = sumP4_electron.M();
210 mass_selectedTracksAcc(*MuSAVertex) = sumP4_selected.M();
211 num_trksAcc(*MuSAVertex) = workVertex.nTracksTotal();
212 num_selectedTracksAcc(*MuSAVertex) = workVertex.selectedTrackIndices.size();
213 num_associatedTracksAcc(*MuSAVertex) = workVertex.associatedTrackIndices.size();
214 dCloseVrtAcc(*MuSAVertex) = workVertex.closestWrkVrtValue;
215 }
216 return StatusCode::SUCCESS;
217}
218
219StatusCode MuSAVtxFitter::execute(const EventContext& ctx) const
220{
222 ATH_CHECK(muonContainer.isValid());
223
224 SG::ReadHandle MSTPContainer(m_MSTPContainer, ctx);
225 ATH_CHECK(MSTPContainer.isValid());
226
227 SG::ReadHandle eventInfo(m_eventInfo, ctx);
228 ATH_CHECK(eventInfo.isValid());
229
230 SG::WriteHandle MuSAVtxContainer(m_MuSAVertices, ctx);
231 ATH_CHECK(MuSAVtxContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
232
233 SG::WriteHandle MuSAExtrapolatedTracksContainer(m_MuSAExtrapolatedTracks, ctx);
234 ATH_CHECK(MuSAExtrapolatedTracksContainer.record(std::make_unique<xAOD::TrackParticleContainer>(), std::make_unique<xAOD::TrackParticleAuxContainer>()));
235
236 std::vector<MuSAVtxFitterTool::WrkVrt> workVerticesContainer;
237
238 // Perform primary MuSA vertex fit
239 ATH_CHECK(m_MuSAVtxFitterTool->doMuSAVtxFit(workVerticesContainer, *muonContainer, *eventInfo, ctx));
240
241 // If there's no MuSA vertices to begin with, stop here to avoid wasting CPU cycles
242 if (workVerticesContainer.empty()) {
243 ATH_MSG_DEBUG("No MuSA vertices found");
244 return StatusCode::SUCCESS;
245 }
246
247 // Perform user-configurable post-fit selections
248 ATH_CHECK(m_MuSAVtxFitterTool->doPostFitSelections(workVerticesContainer));
249
250 // If there's no MuSA vertices remaining, stop here to again avoid wasting CPU cycles
251 if (workVerticesContainer.empty()) {
252 ATH_MSG_DEBUG("No MuSA vertices found after post-fit selection!");
253 return StatusCode::SUCCESS;
254 }
255
256 // Perform "ambiguity resolution" to prevent re-used SA muons in events with more than one MuSA vtx
257 ATH_CHECK(m_MuSAVtxFitterTool->selectBestVertices(workVerticesContainer));
258
259 // Again avoiding wasting CPU cycles if no MuSA vertices remain
260 if (workVerticesContainer.empty()) {
261 ATH_MSG_DEBUG("No MuSA vertices found after best overlap selection!");
262 return StatusCode::SUCCESS;
263 } else {
264 ATH_MSG_DEBUG("Found " << workVerticesContainer.size() << " MuSA vertices");
265 }
266
267 ATH_CHECK(fillCollections(workVerticesContainer, MuSAVtxContainer.ptr(), MuSAExtrapolatedTracksContainer.ptr(), *muonContainer, *MSTPContainer, ctx));
268 ATH_MSG_DEBUG("Saved MuSA collections!");
269
270 return StatusCode::SUCCESS;
271}
272}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for adding a decoration to an object.
xAOD::MuonContainer * muonContainer
value_type emplace_back(value_type pElem)
Add an element to the end of the collection.
const T * at(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_MSTPContainer
virtual ~MuSAVtxFitter()
StatusCode fillCollections(std::vector< MuSAVtxFitterTool::WrkVrt > &workVerticesContainer, xAOD::VertexContainer *MuSAVtxContainer, xAOD::TrackParticleContainer *MuSAExtrapolatedTracksContainer, const xAOD::MuonContainer &muonContainer, const xAOD::TrackParticleContainer &MSTPContainer, const EventContext &ctx) const
SG::ReadHandleKey< xAOD::MuonContainer > m_muonContainer
SG::WriteHandleKey< xAOD::VertexContainer > m_MuSAVertices
virtual StatusCode execute(const EventContext &ctx) const override
SG::WriteHandleKey< xAOD::TrackParticleContainer > m_MuSAExtrapolatedTracks
ToolHandle< Reco::ITrackToVertex > m_trackToVertexTool
virtual StatusCode initialize() override
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
ToolHandle< Rec::MuSAVtxFitterTool > m_MuSAVtxFitterTool
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:573
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
void addTrackAtVertex(const ElementLink< TrackParticleContainer > &tr, float weight=1.0)
Add a new track to the vertex.
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
void setVertexType(VxType::VertexType vType)
Set the type of the vertex.
void setCovariance(const std::vector< float > &value)
Sets the covariance matrix as a simple vector of values.
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Gaudi Tools.
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
@ SecVtx
Secondary vertex.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
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".