ATLAS Offline Software
VertexFittingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 // Local
9 
10 // Athena
12 
13 // C/C++
14 #include <cmath>
15 #include <iostream>
16 #include <sstream>
17 
18 using namespace std;
19 
20 //=============================================================================
22  const std::string& t, const std::string &name, const IInterface* p
23 ): AthAlgTool(t, name, p),
24  m_countNumberOfFits (0),
25  m_countNumberOfFitsFailed (0),
26  m_countNumberOfFitsInvalid(0)
27 {
28  declareInterface<Prompt::IVertexFittingTool>(this);
29 }
30 
31 //=============================================================================
33 {
34  ATH_CHECK(m_vertexFitter.retrieve());
35 
36  if(m_doSeedVertexFit) {
37  ATH_CHECK(m_seedVertexFitter.retrieve());
38  }
39 
40  m_distToPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_distToPriVtxName);
41  m_normDistToPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_normDistToPriVtxName);
42  m_distToRefittedPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_distToRefittedPriVtxName);
43  m_normDistToRefittedPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_normDistToRefittedPriVtxName);
44  m_distToRefittedRmLepPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_distToRefittedRmLepPriVtxName);
45  m_normDistToRefittedRmLepPriVtx = std::make_unique<SG::AuxElement::Decorator<float> > (m_normDistToRefittedRmLepPriVtxName);
46 
47  m_timer.Reset();
48 
49  ATH_MSG_DEBUG("VertexFittingSvc::initialize - doSeedVertexFit = " << m_doSeedVertexFit);
50  ATH_MSG_DEBUG("VertexFittingSvc::initialize - vertexFitter = " << m_vertexFitter.name());
51 
52  return StatusCode::SUCCESS;
53 }
54 
55 //=============================================================================
57 {
58  //
59  // Delete pointers
60  //
61  m_timer.Stop();
62 
63  ATH_MSG_INFO("VertexFittingSvc::finalize - number of total fits: " << m_countNumberOfFits);
64  ATH_MSG_INFO("VertexFittingSvc::finalize - number of failed fits: " << m_countNumberOfFitsFailed);
65  ATH_MSG_INFO("VertexFittingSvc::finalize - number of invalid vtxs: " << m_countNumberOfFitsInvalid);
66  ATH_MSG_INFO("VertexFittingSvc::finalize - fitting timer: " << PrintResetStopWatch(m_timer));
67 
68  return StatusCode::SUCCESS;
69 }
70 
71 //=============================================================================
73  const FittingInput &input,
74  const std::vector<const xAOD::TrackParticle* > &tracks,
75  VtxType vtxType
76 )
77 {
78  //
79  // Make new secondary vertex
80  //
81  TimerScopeHelper timer(m_timer);
82  m_countNumberOfFits++;
83 
84  if(!input.priVtx) {
85  ATH_MSG_WARNING("fitVertexWithPrimarySeed -- missing primary vertex");
86  return nullptr;
87  }
88 
89  // Fit a new secondary vertex
90  std::unique_ptr<xAOD::Vertex> secondaryVtx = getSecondaryVertexWithSeed(
91  tracks, input.inDetTracks, input.priVtx->position()
92  );
93 
94  if(!secondaryVtx) {
95  m_countNumberOfFitsFailed++;
96  ATH_MSG_WARNING("fitVertexWithPrimarySeed -- failed to fit vertex");
97  return nullptr;
98  }
99 
100  if(!isValidVertex(secondaryVtx.get())) {
101  m_countNumberOfFitsInvalid++;
102 
103  ATH_MSG_WARNING("fitVertexWithPrimarySeed -- failed to get valid vertex");
104  return nullptr;
105  }
106 
107  m_secondaryVertexIndex++;
108 
109  // Decorate the newly created vertex
110  static const SG::AuxElement::Accessor<int> indexAcc("SecondaryVertexIndex");
111  static const SG::AuxElement::Accessor<int> typeAcc("SVType");
112 
113  indexAcc(*secondaryVtx) = m_secondaryVertexIndex;
114  typeAcc(*secondaryVtx) = static_cast<int>(vtxType);
115 
116  decorateNewSecondaryVertex(input, secondaryVtx.get());
117 
118  return secondaryVtx;
119 }
120 
121 //=============================================================================
122 std::unique_ptr<xAOD::Vertex> Prompt::VertexFittingTool::fitVertexWithSeed(
123  const FittingInput &input,
124  const std::vector<const xAOD::TrackParticle* > &tracks,
125  const Amg::Vector3D& seed,
126  VtxType vtxType
127 )
128 {
129  //
130  // Make new secondary vertex
131  //
132  TimerScopeHelper timer(m_timer);
133  m_countNumberOfFits++;
134 
135  std::unique_ptr<xAOD::Vertex> secondaryVtx = getSecondaryVertexWithSeed(
136  tracks, input.inDetTracks, seed
137  );
138 
139  if(!secondaryVtx) {
140  m_countNumberOfFitsFailed++;
141 
142  ATH_MSG_WARNING("fitVertexWithSeed -- failed to fit vertex");
143  return nullptr;
144  }
145 
146  if(!isValidVertex(secondaryVtx.get())) {
147  m_countNumberOfFitsInvalid++;
148 
149  ATH_MSG_WARNING("fitVertexWithSeed -- failed to get valid vertex");
150  return nullptr;
151  }
152 
153  m_secondaryVertexIndex++;
154 
155  // Decorate the newly created vertex
156  static const SG::AuxElement::Accessor<int> indexAcc("SecondaryVertexIndex");
157  static const SG::AuxElement::Accessor<int> typeAcc("SVType");
158 
159  indexAcc(*secondaryVtx) = m_secondaryVertexIndex;
160  typeAcc(*secondaryVtx) = static_cast<int>(vtxType);
161 
162  decorateNewSecondaryVertex(input, secondaryVtx.get());
163 
164  return secondaryVtx;
165 }
166 
167 //=============================================================================
169 {
170  //
171  // Check if vertex is valid
172  //
173  bool bad_vtx = false;
174 
175  if(!vtx){
176  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- invalid vtx pointer!!!");
177  return false;
178  }
179 
180  if(vtx->covariance().empty()) {
181  bad_vtx = true;
182  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- empty vtx covariance!!!");
183  }
184 
185  float chisquared = -9999;
186 
187  if(!getVar(vtx, chisquared, "chiSquared")) {
188  bad_vtx = true;
189  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- not valid vtx chiSquared!!!");
190  }
191 
192  float numberdof = -9999;
193 
194  if(!getVar(vtx, numberdof, "numberDoF")) {
195  bad_vtx = true;
196  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- not valid vtx numberDoF!!!");
197  }
198 
199  if(std::isnan(vtx->x()) || std::isnan(vtx->y()) || std::isnan(vtx->z())) {
200  bad_vtx = true;
201  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- vertex coordinate is nan");
202  }
203 
204  if(bad_vtx) {
205  ATH_MSG_WARNING("VertexFittingSvc::Validate_Vertex -- bad vertex!!!");
206  ATH_MSG_INFO(printPromptVertexAsStr(vtx, msg(MSG::WARNING)));
207  }
208 
209  return !bad_vtx;
210 }
211 
212 //=============================================================================
213 void Prompt::VertexFittingTool::removeDoubleEntries(std::vector<const xAOD::TrackParticle*>& tracks)
214 {
215  const unsigned nbefore = tracks.size();
216 
217  sort(tracks.begin(), tracks.end());
218 
219  typename std::vector<const xAOD::TrackParticle*>::iterator TransfEnd = std::unique(tracks.begin(), tracks.end());
220 
221  tracks.erase(TransfEnd, tracks.end());
222 
223  if(nbefore != tracks.size()) {
224  ATH_MSG_DEBUG("removeDoubleEntries nbefore != tracks.size()): " << nbefore << " != " << tracks.size());
225  }
226 }
227 
228 //=============================================================================
230  const FittingInput &input,
231  xAOD::Vertex *secVtx
232 )
233 {
234  //
235  // Decorate secondary vertex with all useful information
236  //
237  if(!secVtx) {
238  ATH_MSG_WARNING("decorateNewSecondaryVertex - invalid pointer");
239  return false;
240  }
241 
242  //
243  // Decorate secondary vertex with the distance/norm_distance it from Prmary Vertex, Refitted Primary vertex and Refitted Primary Vertex that removed lepton itself.
244  //
245  float distToPriVtx = -1;
246  float normDistToPriVtx = -1;
247  float distToRefittedPriVtx = -1;
248  float normDistToRefittedPriVtx = -1;
249  float distToRefittedRmLepPriVtx = -1;
250  float normDistToRefittedRmLepPriVtx = -1;
251 
252  if(input.priVtx) {
253  distToPriVtx = Prompt::getDistance(input.priVtx->position(), secVtx->position());
254  normDistToPriVtx = Prompt::getNormDist(input.priVtx->position(), secVtx->position(), secVtx->covariance(), msg(MSG::WARNING));
255  }
256 
257  if(input.refittedPriVtx) {
258  distToRefittedPriVtx = Prompt::getDistance(input.refittedPriVtx->position(), secVtx->position());
259  normDistToRefittedPriVtx = Prompt::getNormDist(input.refittedPriVtx->position(), secVtx->position(), secVtx->covariance(), msg(MSG::WARNING));
260  }
261 
262  if(input.refittedPriVtxWithoutLep) {
263  distToRefittedRmLepPriVtx = Prompt::getDistance(input.refittedPriVtxWithoutLep->position(), secVtx->position());
264  normDistToRefittedRmLepPriVtx = Prompt::getNormDist(input.refittedPriVtxWithoutLep->position(), secVtx->position(), secVtx->covariance(), msg(MSG::WARNING));
265  }
266 
267  (*m_distToPriVtx) (*secVtx) = distToPriVtx;
268  (*m_normDistToPriVtx) (*secVtx) = normDistToPriVtx;
269  (*m_distToRefittedPriVtx) (*secVtx) = distToRefittedPriVtx;
270  (*m_normDistToRefittedPriVtx) (*secVtx) = normDistToRefittedPriVtx;
271  (*m_distToRefittedRmLepPriVtx) (*secVtx) = distToRefittedRmLepPriVtx;
272  (*m_normDistToRefittedRmLepPriVtx)(*secVtx) = normDistToRefittedRmLepPriVtx;
273 
274  return true;
275 }
276 
277 //=============================================================================
279  const std::vector<const xAOD::TrackParticle*> &tracks,
280  const xAOD::TrackParticleContainer *inDetTracks,
281  const Amg::Vector3D& seed
282 )
283 {
284  //
285  // Fit one vertex with given tracks
286  //
287  std::vector<const xAOD::TrackParticle*> tracksForFit(tracks);
288 
289  ATH_MSG_DEBUG("getSecondaryVertexWithSeed -- before remove " << tracksForFit.size());
290 
291  removeDoubleEntries(tracksForFit);
292 
293  ATH_MSG_DEBUG("getSecondaryVertexWithSeed -- after remove " << tracksForFit.size());
294 
295  if(tracksForFit.size() < 2) {
296  ATH_MSG_WARNING("getSecondaryVertexWithSeed -- cannot fit vertex with one or zero input track: ntrack=" << tracksForFit.size());
297  return 0;
298  }
299 
300  //
301  // Run fit
302  //
303  ATH_MSG_DEBUG(name() << "::getSecondaryVertexWithSeed -- N tracks = " << tracksForFit.size());
304 
305  for(const xAOD::TrackParticle* track: tracksForFit) {
306  ATH_MSG_DEBUG( name() << "::getSecondaryVertexWithSeed -- track pt, eta = " << track->pt() << "," << track->eta());
307  ATH_MSG_DEBUG( name() << "::getSecondaryVertexWithSeed -- track chi2 = " << track->chiSquared());
308  }
309 
310  xAOD::Vertex *newVertex = 0;
311  std::unique_ptr<xAOD::Vertex> seedVertex;
312 
313  if(m_doSeedVertexFit) {
314  seedVertex = std::unique_ptr<xAOD::Vertex>(m_seedVertexFitter->fit(tracksForFit, seed));
315 
316  if(seedVertex.get() && !isValidVertex(seedVertex.get())) {
317  ATH_MSG_DEBUG("getSecondaryVertexWithSeed -- failed to fit seed vertex");
318 
319  seedVertex.reset();
320  }
321  }
322 
323  if(seedVertex.get()) {
324  newVertex = m_vertexFitter->fit(tracksForFit, seedVertex->position());
325  }
326  else {
327  newVertex = m_vertexFitter->fit(tracksForFit, seed);
328  }
329 
330  if(!newVertex) {
331  ATH_MSG_INFO("getSecondaryVertexWithSeed -- failed to fit vertex and fitter returned null xAOD::Vertex pointer");
332  return 0;
333  }
334 
335  //
336  // Save vertex tracks
337  //
338  std::vector<ElementLink< xAOD::TrackParticleContainer> > tpLinks;
339 
340  if(inDetTracks) {
341  //
342  // Record links to ID tracks if container pointer is provided
343  //
344  for(const xAOD::TrackParticle *selectedtrack: tracksForFit) {
346 
347  tpLink.toContainedElement(*inDetTracks, selectedtrack);
348  tpLinks.push_back(tpLink);
349  }
350  }
351 
352  newVertex->setTrackParticleLinks(tpLinks);
353 
354  TLorentzVector Momentum;
355 
356  for(const xAOD::TrackParticle* track: tracksForFit) {
357  Momentum += static_cast<TLorentzVector>(track->p4());
358  }
359 
360  xAOD::SecVtxHelper::setVertexMass(newVertex, Momentum.M()); // "mass"
361 
362  // newVertex was returned from the vertex fitter as a raw pointer
363  // It looks like Trk::IVertexFitter::fit function expects
364  // memory management to be done by the caller.
365  // Therefore, we take ownership by casting to a unique_ptr
366 
367  std::unique_ptr<xAOD::Vertex> returnPtr(newVertex);
368 
369  return returnPtr;
370 }
371 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::Vertex_v1::x
float x() const
Returns the x position.
PromptUtils.h
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
Prompt::getVar
bool getVar(T1 &obj, T2 &value, const std::string &var_name)
Definition: PromptUtils.h:72
VertexFittingTool.h
Prompt::VertexFittingTool::getSecondaryVertexWithSeed
std::unique_ptr< xAOD::Vertex > getSecondaryVertexWithSeed(const std::vector< const xAOD::TrackParticle * > &tracks, const xAOD::TrackParticleContainer *inDetTracks, const Amg::Vector3D &seed)
Definition: VertexFittingTool.cxx:278
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
Prompt::VertexFittingTool::finalize
virtual StatusCode finalize() override
Definition: VertexFittingTool.cxx:56
SecVtxHelper.h
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Prompt::FittingInput
Definition: IVertexFittingTool.h:60
Prompt::PrintResetStopWatch
std::string PrintResetStopWatch(TStopwatch &watch)
Definition: PromptUtils.cxx:244
Prompt::VertexFittingTool::fitVertexWithSeed
virtual std::unique_ptr< xAOD::Vertex > fitVertexWithSeed(const FittingInput &input, const std::vector< const xAOD::TrackParticle * > &tracks, const Amg::Vector3D &seed, VtxType vtxType) override
Definition: VertexFittingTool.cxx:122
std::sort
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:554
python.utils.AtlRunQueryTimer.timer
def timer(name, disabled=False)
Definition: AtlRunQueryTimer.py:86
Prompt::getNormDist
double getNormDist(const Amg::Vector3D &PrimVtx, const Amg::Vector3D &SecVtx, const std::vector< float > &ErrorMatrix, MsgStream &msg)
Definition: PromptUtils.cxx:57
Prompt::VertexFittingTool::fitVertexWithPrimarySeed
virtual std::unique_ptr< xAOD::Vertex > fitVertexWithPrimarySeed(const FittingInput &input, const std::vector< const xAOD::TrackParticle * > &tracks, VtxType vtx) override
Definition: VertexFittingTool.cxx:72
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Prompt::getDistance
double getDistance(const xAOD::Vertex *vtx1, const xAOD::Vertex *vtx2)
Definition: PromptUtils.cxx:41
Prompt::VertexFittingTool::VertexFittingTool
VertexFittingTool(const std::string &t, const std::string &name, const IInterface *p)
Definition: VertexFittingTool.cxx:21
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
std::unique
std::reverse_iterator< DataModel_detail::iterator< DVL > > unique(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, BinaryPredicate pred)
Specialization of unique for DataVector/List.
Definition: DVL_algorithms.h:199
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
Prompt::printPromptVertexAsStr
std::string printPromptVertexAsStr(const xAOD::Vertex *vtx, MsgStream &msg)
Definition: PromptUtils.cxx:127
xAOD::Vertex_v1::setTrackParticleLinks
void setTrackParticleLinks(const TrackParticleLinks_t &trackParticles)
Set all track particle links at once.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Prompt::VertexFittingTool::isValidVertex
virtual bool isValidVertex(const xAOD::Vertex *vtx) const override
Definition: VertexFittingTool.cxx:168
xAOD::Vertex_v1::z
float z() const
Returns the z position.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
Prompt::VertexFittingTool::initialize
virtual StatusCode initialize() override
Definition: VertexFittingTool.cxx:32
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Prompt::VertexFittingTool::decorateNewSecondaryVertex
bool decorateNewSecondaryVertex(const FittingInput &input, xAOD::Vertex *secVtx)
Definition: VertexFittingTool.cxx:229
Prompt::VtxType
VtxType
Definition: IVertexFittingTool.h:48
xAOD::Vertex_v1::covariance
const std::vector< float > & covariance() const
Returns the covariance matrix as a simple vector of values.
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
Prompt::VertexFittingTool::removeDoubleEntries
void removeDoubleEntries(std::vector< const xAOD::TrackParticle * > &tracks)
Definition: VertexFittingTool.cxx:213
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::Vertex_v1::y
float y() const
Returns the y position.
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
AthAlgTool
Definition: AthAlgTool.h:26
Prompt::TimerScopeHelper
Definition: PromptUtils.h:112
xAOD::SecVtxHelper::setVertexMass
void setVertexMass(xAOD::Vertex *, float value)
Definition: SecVtxHelper.cxx:18
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7