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 const xAOD::TrackParticle* newTrack = workVertex.newExtrapolatedTracks[i].get();
92 // copy transfers ownership of the shared_ptr in wrkvrt to container
93 xAOD::TrackParticle* containerTrack = MuSAExtrapolatedTracksContainer->push_back(new xAOD::TrackParticle());
94 *containerTrack=*newTrack;
95
96 // Link the new tracks to the vertex
97 ElementLink<xAOD::TrackParticleContainer> link_trk(*MuSAExtrapolatedTracksContainer, MuSAExtrapolatedTracksContainer->size() - 1);
98 MuSAVertex->addTrackAtVertex(link_trk, 1.0);
99
100 //Also link the extrapolated tracks and vertices to their original muons -- extrapolated tracks and their muons should have the same index in workVertex
101
102 bool muonLinkSuccess = false;
103 bool MSTPLinkSuccess = false;
104
107 muonLinkSuccess = link_muon.toContainedElement(muonContainer, workVertex.muonCandidates[i]);
108
109 const xAOD::Muon* muon = muonContainer[link_muon.index()];
110 const xAOD::TrackParticle* MSTP = muon->trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
111 if (MSTP) {
112 MSTPLinkSuccess = link_MSTP.toContainedElement(MSTPContainer, MSTP);
113 }
114
115 // Check that links are valid
116 if (!MSTPLinkSuccess) {
117 ATH_MSG_WARNING("Failed to link MSTP!");
118 } else {
119 acc_MSTPLink(*containerTrack) = link_MSTP;
120 auto& mstpLinks = acc_MSTPLinks(*MuSAVertex);
121 mstpLinks.push_back(link_MSTP);
122 }
123
124 if (!muonLinkSuccess) {
125 ATH_MSG_WARNING("Failed to link muon!");
126 } else {
127 acc_MuonLink(*containerTrack) = link_muon;
128 auto& muonLinks = acc_MuonLinks(*MuSAVertex);
129 muonLinks.push_back(link_muon);
130 }
131 }
132
133 MuSAVertex->setPosition(workVertex.pos);
135 MuSAVertex->setFitQuality(workVertex.chi2, 1);
136 std::vector<float> fCov(workVertex.cov.cbegin(), workVertex.cov.cend());
137 MuSAVertex->setCovariance(fCov);
138
139 vtx_pxAcc(*MuSAVertex) = workVertex.mom.Px();
140 vtx_pyAcc(*MuSAVertex) = workVertex.mom.Py();
141 vtx_pzAcc(*MuSAVertex) = workVertex.mom.Pz();
142
143 vtx_massAcc(*MuSAVertex) = workVertex.mom.M();
144 vtx_chargeAcc(*MuSAVertex) = workVertex.charge;
145
146 minOpAngAcc(*MuSAVertex) = workVertex.minOpAng;
147
148 chi2_coreAcc(*MuSAVertex) = workVertex.chi2Core;
149 ndof_coreAcc(*MuSAVertex) = 1;
150 chi2_assocAcc(*MuSAVertex) = workVertex.chi2;
151 ndof_assocAcc(*MuSAVertex) = workVertex.ndof();
152
153 TLorentzVector sumP4_muon;
154 TLorentzVector sumP4_electron;
155 TLorentzVector sumP4_selected;
156
157 constexpr double muonMass = 105.658; // Muon mass in MeV
158
159 for (size_t i = 0; i < workVertex.newExtrapolatedTracks.size(); i++) {
160 const xAOD::TrackParticle* track = workVertex.newExtrapolatedTracks[i].get();
161 double pt_wrtSV = track->pt();
162 double eta_wrtSV = track->eta();
163 double phi_wrtSV = track->phi();
164
165 TLorentzVector p4wrtSV_muon;
166 TLorentzVector p4wrtSV_electron;
167
168 p4wrtSV_muon.SetPtEtaPhiM(pt_wrtSV, eta_wrtSV, phi_wrtSV, muonMass);
169 p4wrtSV_electron.SetPtEtaPhiM(pt_wrtSV, eta_wrtSV, phi_wrtSV, VKalVrtAthena::PhysConsts::mass_electron);
170
171 sumP4_muon += p4wrtSV_muon;
172 sumP4_electron += p4wrtSV_electron;
173 sumP4_selected += p4wrtSV_muon;
174
175 size_t trackIndex = MuSAVertex->trackParticleLinks()[i].index();
176 xAOD::TrackParticle* containerTrack = MuSAExtrapolatedTracksContainer->at(trackIndex);
177
178 std::unique_ptr<Trk::Perigee> sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *containerTrack, workVertex.pos);
179 if (!sv_perigee) {
180 ATH_MSG_WARNING("Failed in obtaining the SV perigee for track!");
181 continue;
182 }
183
184 double qOverP_wrtSV = sv_perigee->parameters()[Trk::qOverP];
185 double theta_wrtSV = sv_perigee->parameters()[Trk::theta];
186 double p_wrtSV = 1.0 / std::abs(qOverP_wrtSV);
187 pt_wrtSV = p_wrtSV * sin(theta_wrtSV);
188 eta_wrtSV = -log(tan(theta_wrtSV / 2.0));
189 phi_wrtSV = sv_perigee->parameters()[Trk::phi];
190 double d0_wrtSV = sv_perigee->parameters()[Trk::d0];
191 double z0_wrtSV = sv_perigee->parameters()[Trk::z0];
192 double sqrd0Err_wrtSV = (*sv_perigee->covariance())(Trk::d0, Trk::d0);
193 double sqrz0Err_wrtSV = (*sv_perigee->covariance())(Trk::z0, Trk::z0);
194 double sqrQoPErr_wrtSV = (*sv_perigee->covariance())(Trk::qOverP, Trk::qOverP);
195
196 qOverP_wrtSVAcc(*containerTrack) = qOverP_wrtSV;
197 theta_wrtSVAcc(*containerTrack) = theta_wrtSV;
198 p_wrtSVAcc(*containerTrack) = p_wrtSV;
199 pt_wrtSVAcc(*containerTrack) = pt_wrtSV;
200 eta_wrtSVAcc(*containerTrack) = eta_wrtSV;
201 phi_wrtSVAcc(*containerTrack) = phi_wrtSV;
202 d0_wrtSVAcc(*containerTrack) = d0_wrtSV;
203 z0_wrtSVAcc(*containerTrack) = z0_wrtSV;
204 sqrd0Err_wrtSVAcc(*containerTrack) = sqrd0Err_wrtSV;
205 sqrz0Err_wrtSVAcc(*containerTrack) = sqrz0Err_wrtSV;
206 sqrQoPErr_wrtSVAcc(*containerTrack) = sqrQoPErr_wrtSV;
207 }
208
209 massAcc(*MuSAVertex) = sumP4_muon.M();
210 mass_eAcc(*MuSAVertex) = sumP4_electron.M();
211 mass_selectedTracksAcc(*MuSAVertex) = sumP4_selected.M();
212 num_trksAcc(*MuSAVertex) = workVertex.nTracksTotal();
213 num_selectedTracksAcc(*MuSAVertex) = workVertex.selectedTrackIndices.size();
214 num_associatedTracksAcc(*MuSAVertex) = workVertex.associatedTrackIndices.size();
215 dCloseVrtAcc(*MuSAVertex) = workVertex.closestWrkVrtValue;
216 }
217 return StatusCode::SUCCESS;
218}
219
220StatusCode MuSAVtxFitter::execute(const EventContext& ctx) const
221{
223 ATH_CHECK(muonContainer.isValid());
224
225 SG::ReadHandle MSTPContainer(m_MSTPContainer, ctx);
226 ATH_CHECK(MSTPContainer.isValid());
227
228 SG::ReadHandle eventInfo(m_eventInfo, ctx);
229 ATH_CHECK(eventInfo.isValid());
230
231 SG::WriteHandle MuSAVtxContainer(m_MuSAVertices, ctx);
232 ATH_CHECK(MuSAVtxContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
233
234 SG::WriteHandle MuSAExtrapolatedTracksContainer(m_MuSAExtrapolatedTracks, ctx);
235 ATH_CHECK(MuSAExtrapolatedTracksContainer.record(std::make_unique<xAOD::TrackParticleContainer>(), std::make_unique<xAOD::TrackParticleAuxContainer>()));
236
237 std::vector<MuSAVtxFitterTool::WrkVrt> workVerticesContainer;
238
239 // Perform primary MuSA vertex fit
240 ATH_CHECK(m_MuSAVtxFitterTool->doMuSAVtxFit(workVerticesContainer, *muonContainer, *eventInfo, ctx));
241
242 // If there's no MuSA vertices to begin with, stop here to avoid wasting CPU cycles
243 if (workVerticesContainer.empty()) {
244 ATH_MSG_DEBUG("No MuSA vertices found");
245 return StatusCode::SUCCESS;
246 }
247
248 // Perform user-configurable post-fit selections
249 ATH_CHECK(m_MuSAVtxFitterTool->doPostFitSelections(workVerticesContainer));
250
251 // If there's no MuSA vertices remaining, stop here to again avoid wasting CPU cycles
252 if (workVerticesContainer.empty()) {
253 ATH_MSG_DEBUG("No MuSA vertices found after post-fit selection!");
254 return StatusCode::SUCCESS;
255 }
256
257 // Perform "ambiguity resolution" to prevent re-used SA muons in events with more than one MuSA vtx
258 ATH_CHECK(m_MuSAVtxFitterTool->selectBestVertices(workVerticesContainer));
259
260 // Again avoiding wasting CPU cycles if no MuSA vertices remain
261 if (workVerticesContainer.empty()) {
262 ATH_MSG_DEBUG("No MuSA vertices found after best overlap selection!");
263 return StatusCode::SUCCESS;
264 } else {
265 ATH_MSG_DEBUG("Found " << workVerticesContainer.size() << " MuSA vertices");
266 }
267
268 ATH_CHECK(fillCollections(workVerticesContainer, MuSAVtxContainer.ptr(), MuSAExtrapolatedTracksContainer.ptr(), *muonContainer, *MSTPContainer, ctx));
269 ATH_MSG_DEBUG("Saved MuSA collections!");
270
271 return StatusCode::SUCCESS;
272}
273}
#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:572
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".