ATLAS Offline Software
MuSAVtxFitter.cxx
Go to the documentation of this file.
1 /*
2 Copyright (C) 2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Header include
11 #include "VrtSecInclusive/Constants.h"
12 
13 namespace {
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 
51 namespace Rec {
52 
54 
56 {
60  ATH_CHECK( m_MuSAVertices.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 
75 StatusCode 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);
134  MuSAVertex->setVertexType(xAOD::VxType::SecVtx);
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  xAOD::TrackParticle* containerTrack = MuSAExtrapolatedTracksContainer->at(i);
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 
219 StatusCode 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 }
muonContainer
xAOD::MuonContainer * muonContainer
Definition: TrigGlobEffCorrValidation.cxx:188
Rec::MuSAVtxFitter::m_muonContainer
SG::ReadHandleKey< xAOD::MuonContainer > m_muonContainer
Definition: MuSAVtxFitter.h:42
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:196
xAOD::Vertex_v1::setPosition
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
Rec::MuSAVtxFitter::m_MuSAExtrapolatedTracks
SG::WriteHandleKey< xAOD::TrackParticleContainer > m_MuSAExtrapolatedTracks
Definition: MuSAVtxFitter.h:50
xAOD::Vertex_v1::setFitQuality
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Definition: Vertex_v1.cxx:150
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition: Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
DataVector::emplace_back
value_type emplace_back(value_type pElem)
Add an element to the end of the collection.
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
Trk::z0
@ z0
Definition: ParamDefs.h:64
xAOD::Vertex_v1::setCovariance
void setCovariance(const std::vector< float > &value)
Sets the covariance matrix as a simple vector of values.
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
Rec::MuSAVtxFitter::m_MuSAVertices
SG::WriteHandleKey< xAOD::VertexContainer > m_MuSAVertices
Definition: MuSAVtxFitter.h:47
Rec::MuSAVtxFitter::m_trackToVertexTool
ToolHandle< Reco::ITrackToVertex > m_trackToVertexTool
Definition: MuSAVtxFitter.h:54
xAOD::Vertex_v1::setVertexType
void setVertexType(VxType::VertexType vType)
Set the type of the vertex.
Rec::MuSAVtxFitter::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: MuSAVtxFitter.cxx:219
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
TrackParticleAuxContainer.h
Rec::MuSAVtxFitter::m_MSTPContainer
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_MSTPContainer
Definition: MuSAVtxFitter.h:44
lumiFormat.i
int i
Definition: lumiFormat.py:85
Rec
Name: MuonSpContainer.h Package : offline/Reconstruction/MuonIdentification/muonEvent.
Definition: FakeTrackBuilder.h:10
Trk::theta
@ theta
Definition: ParamDefs.h:66
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SG::WriteHandle::ptr
pointer_type ptr()
Dereference the pointer.
xAOD::VxType::SecVtx
@ SecVtx
Secondary vertex.
Definition: TrackingPrimitives.h:573
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
WriteDecorHandle.h
Handle class for adding a decoration to an object.
MuSAVtxFitter.h
Rec::MuSAVtxFitter::m_eventInfo
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
Definition: MuSAVtxFitter.h:43
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
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
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Rec::MuSAVtxFitter::~MuSAVtxFitter
virtual ~MuSAVtxFitter()
VKalVrtAthena::PhysConsts::mass_electron
constexpr double mass_electron
Definition: Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/Constants.h:15
Trk::d0
@ d0
Definition: ParamDefs.h:63
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
MuSAVtxFitterTool.h
Rec::MuSAVtxFitter::initialize
virtual StatusCode initialize() override
Definition: MuSAVtxFitter.cxx:55
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
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
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
Rec::MuSAVtxFitter::m_MuSAVtxFitterTool
ToolHandle< Rec::MuSAVtxFitterTool > m_MuSAVtxFitterTool
Definition: MuSAVtxFitter.h:53
Trk::phi
@ phi
Definition: ParamDefs.h:75
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
Rec::MuSAVtxFitter::fillCollections
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
Definition: MuSAVtxFitter.cxx:75
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
VertexAuxContainer.h