ATLAS Offline Software
VertexIterativeFitMergingTool.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 // Local
9 
10 // C/C++
11 #include <cmath>
12 #include <iostream>
13 #include <sstream>
14 
15 //=============================================================================
17  const std::string &name,
18  const std::string &type,
19  const IInterface *parent
20 ):
22 {
23  declareInterface<Prompt::IVertexMergingTool>(this);
24 }
25 
26 //=============================================================================
28 {
29  ATH_CHECK(m_vertexFitterTool.retrieve());
30  ATH_CHECK(m_histSvc.retrieve());
31 
32  ATH_CHECK(makeHist(m_histNvtx2TrkInit, "nvtx_2trk_init", 25, -0.5, 24.5));
33  ATH_CHECK(makeHist(m_histNvtx2TrkPass, "nvtx_2trk_pass", 25, -0.5, 24.5));
34  ATH_CHECK(makeHist(m_histNvtx2TrkUnmerged, "nvtx_2trk_unmerged", 25, -0.5, 24.5));
35  ATH_CHECK(makeHist(m_histNvtxMerged, "nvtx_merged", 25, -0.5, 24.5));
36 
37  ATH_CHECK(makeHist(m_histNewVtxFitChi2, "newVtxFit_chi2", 100, 0.0, 50.0));
38  ATH_CHECK(makeHist(m_histNewVtxFitProb, "newVtxFit_prob", 100, 0.0, 1.0));
39 
40  ATH_CHECK(makeHist(m_histNewVtxFitDistToCurr, "newVtxFit_dist_toCurr", 100, 0.0, 10.0));
41  ATH_CHECK(makeHist(m_histNewVtxFitDistToSeed, "newVtxFit_dist_toSeed", 100, 0.0, 10.0));
42  ATH_CHECK(makeHist(m_histNewVtxFitDistToSeedPass, "newVtxFit_dist_toSeed_pass", 100, 0.0, 10.0));
43  ATH_CHECK(makeHist(m_histNewVtxFitDistToSeedFail, "newVtxFit_dist_toSeed_fail", 100, 0.0, 10.0));
44 
45  ATH_CHECK(makeHist(m_histNewVtxFitProbCandOverSeed, "newVtxFit_prob_candOverSeed", 100, 0.0, 4.0));
46  ATH_CHECK(makeHist(m_histNewVtxFitProbCandOverSeedPass, "newVtxFit_prob_candOverSeed_pass", 100, 0.0, 4.0));
47  ATH_CHECK(makeHist(m_histNewVtxFitProbCandOverSeedFail, "newVtxFit_prob_candOverSeed_fail", 100, 0.0, 4.0));
48  ATH_CHECK(makeHist(m_histNewVtxFitProbCandOverSeed3Trk, "newVtxFit_prob_candOverSeed_3trk", 100, 0.0, 4.0));
49  ATH_CHECK(makeHist(m_histNewVtxFitProbCandOverSeed3TrkPass, "newVtxFit_prob_candOverSeed_3trk_pass", 100, 0.0, 4.0));
50 
51  ATH_CHECK(makeHist(m_histVtx2TrkPairDist, "Vtx2trkPair_dist", 100, 0.0, 100.0));
52  ATH_CHECK(makeHist(m_histVtx2trkPairDistZoom, "Vtx2trkPair_dist_zoom", 100, 0.0, 10.0));
53  ATH_CHECK(makeHist(m_histVtx2TrkPairSig1, "Vtx2trkPair_sig1", 100, 0.0, 20.0));
54  ATH_CHECK(makeHist(m_histVtx2TrkPairSig2, "Vtx2trkPair_sig2", 100, 0.0, 20.0));
55 
56  ATH_CHECK(makeHist(m_histSelectedTrackCountAll, "selectedTrack_CountAll", 25, -0.5, 24.5));
57  ATH_CHECK(makeHist(m_histSelectedTrackCountMatch2Vtx , "selectedTrack_CountMatch2Vtx", 25, -0.5, 24.5));
58  ATH_CHECK(makeHist(m_histSelectedTrackCountWithout2Vtx, "selectedTrack_CountWithout2Vtx", 25, -0.5, 24.5));
59 
60  ATH_CHECK(makeHist(m_histVtxWithoutLepton2TrkNTrack, "vtxWithoutLepton2trk_NTrack", 25, -0.5, 24.5));
61  ATH_CHECK(makeHist(m_histVtxWithoutLepton2TrkNPass, "vtxWithoutLepton2trk_NPass", 25, -0.5, 24.5));
62  ATH_CHECK(makeHist(m_histVtxWithoutLepton2TrkNPassUnmerged, "vtxWithoutLepton2trk_NPassUnmerged", 25, -0.5, 24.5));
63  ATH_CHECK(makeHist(m_histVtxWithoutLepton2TrkNMerged, "vtxWithoutLepton2trk_NMerged", 25, -0.5, 24.5));
64 
65  return StatusCode::SUCCESS;
66 }
67 
69  const FittingInput &input,
70  const xAOD::TrackParticle *tracklep,
71  std::vector<std::unique_ptr<xAOD::Vertex>> &initVtxs,
72  const std::vector<const xAOD::TrackParticle *> &selectedTracks
73 )
74 {
75  //
76  // Merge initial (2-track) vertices into new merged vertices with three tracks or more
77  //
78 
79  ATH_MSG_DEBUG("===========================================================================" << std::endl
80  << name() << "::mergeInitVertices - start processing");
81 
82 
83  /*
84  We store the initial vertices that pass selection in their own list
85  with ownership, as this needs to be passed later to the MergeResults.
86  */
88  std::vector<std::unique_ptr<xAOD::Vertex>> vtxsInitPassed;
89 
90  for(std::unique_ptr<xAOD::Vertex> &vtx: initVtxs) {
91  if(passVertexSelection(vtx.get())) {
92  ATH_MSG_DEBUG("pushing vertex into result.vtxInitPassed");
93  result.vtxsInitPassed.push_back(vtx.get());
94  vtxsInitPassed.push_back(std::move(vtx));
95  }
96  }
97 
98  const unsigned nvtxInit = initVtxs.size();
99  const unsigned nvtxPass = result.vtxsInitPassed.size();
100 
101  fillTH1(m_histNvtx2TrkInit, nvtxInit);
102 
103  //
104  // Find tracks that do not form 2-track vertex with lepton track
105  //
106  ATH_MSG_DEBUG(name() << "::mergeInitVertices - processes vertexes without lepton");
107 
108  std::vector<const xAOD::TrackParticle *> tracksWithoutVertex = getTracksWithoutVertex(
109  result.vtxsInitPassed, selectedTracks
110  );
111 
112  // Rank the tracks by pT, will keep the top `m_maxExtraTracks` tracks
113  // for fitting vertexes without lepton
114  if(tracksWithoutVertex.size() > m_maxExtraTracks) {
115  ATH_MSG_DEBUG(" number of tracks without good lepton+track vertex: " << tracksWithoutVertex.size() << std::endl
116  << " will only keep the top " << m_maxExtraTracks << " tracks");
117 
118  std::sort(tracksWithoutVertex.begin(), tracksWithoutVertex.end(), Prompt::SortByIDTrackPt());
119 
120  tracksWithoutVertex.erase(tracksWithoutVertex.begin() + m_maxExtraTracks, tracksWithoutVertex.end());
121  }
122 
123 
124  MergeResultNotOwner resultExtra;
125  std::vector<std::unique_ptr<xAOD::Vertex>> twoTrackVtxInit = fit2TrackVertexes(input, tracksWithoutVertex, Prompt::kTwoTrackVtxWithoutLepton);
126 
128  name() << "::mergeInitVertices - will merge vertexes without lepton" << std::endl
129  << " number of selected tracks without good lepton+track vertex: "
130  << tracksWithoutVertex .size() << std::endl
131  << " number of 2-track vertexes without lepton: "
132  << resultExtra.vtxsInitPassed.size()
133  );
134 
135  //
136  // Merge 2-track vertex without lepton only when there are two or more vertices
137  //
138  mergeIteratively2TrackVtxs(input, twoTrackVtxInit, resultExtra, Prompt::kIterativeFitVtxWithoutLepton);
139 
140  if(resultExtra.vtxsInitPassed.size() > 1) {
141  //
142  // Fill histograms only when there are two or more vertices
143  //
144  fillTH1(m_histVtxWithoutLepton2TrkNTrack, tracksWithoutVertex.size());
145  fillTH1(m_histVtxWithoutLepton2TrkNPass, resultExtra.vtxsInitPassed.size());
146  fillTH1(m_histVtxWithoutLepton2TrkNPassUnmerged, resultExtra.vtxsInitPassedNotMerged.size());
147  fillTH1(m_histVtxWithoutLepton2TrkNMerged, resultExtra.vtxsNewMerged.size());
148  }
149 
150  ATH_MSG_DEBUG(name() << "::mergeInitVertices - finished merging vertexes without lepton" << std::endl
151  << " number of tracks without good lepton+track vertex: " << tracksWithoutVertex.size() << std::endl
152  << " number of 2-track vertexes without lepton: " << resultExtra.vtxsInitPassed.size() << std::endl
153  << " number of unmerged 2-track vertexes without lepton: " << resultExtra.vtxsInitPassedNotMerged.size() << std::endl
154  << " number of merged vertexes without lepton: " << resultExtra.vtxsNewMerged.size());
155 
156  //
157  // Next, processes 2-track vertexes that contain lepton track
158  //
159  ATH_MSG_DEBUG("===========================================================================" << std::endl
160  << name() << "::mergeInitVertices - process 2-track vertexes with lepton" << std::endl
161  << " lepton track pT=" << tracklep->pt() << std::endl
162  << " number of initial 2-track vertices: " << initVtxs.size() << std::endl
163  << " number of selected 2-track vertices: " << result.vtxsInitPassed.size() << std::endl
164  << " number of selected ID tracks: " << selectedTracks.size() );
165 
166  //
167  // Merge 2-track vertexes that contain lepton track
168  //
169  mergeIteratively2TrackVtxs(input, vtxsInitPassed, result, Prompt::kIterativeFitVtx);
170 
171  if(result.vtxsInitPassed.size() > 1) {
172  //
173  // Fill histograms only when there are at least two vertexes to merge
174  //
175  fillTH1(m_histNvtx2TrkPass, nvtxPass);
176  fillTH1(m_histNvtx2TrkUnmerged, result.vtxsInitPassedNotMerged.size());
177  fillTH1(m_histNvtxMerged, result.vtxsNewMerged .size());
178  }
179 
180  //
181  // Erase vector of 2-track vertices without lepton that were merged
182  //
183  resultExtra.vtxsInitPassed.clear();
184 
185  //
186  // Add vertices without lepton track to result
187  //
188  result.vtxsInitPassedNotMerged.insert(
189  result.vtxsInitPassedNotMerged.end(),
190  std::make_move_iterator(resultExtra.vtxsInitPassedNotMerged.begin()),
191  std::make_move_iterator(resultExtra.vtxsInitPassedNotMerged.end())
192  );
193 
194  result.vtxsNewMerged.insert(
195  result.vtxsNewMerged.end(),
196  std::make_move_iterator(resultExtra.vtxsNewMerged.begin()),
197  std::make_move_iterator(resultExtra.vtxsNewMerged.end())
198  );
199 
200  ATH_MSG_DEBUG("==========================================" << std::endl
201  << "mergeInitVertices report" << std::endl
202  << " \tnumber of initial 2-track vertices: "
203  << initVtxs.size() << std::endl
204  << "\tnumber of passed 2-track vertices: "
205  << result.vtxsInitPassed.size() << std::endl
206  << "\tnumber of unmerged 2-track vertices: "
207  << result.vtxsInitPassedNotMerged.size() << std::endl
208  << "\tnumber of merged vertices: "
209  << result.vtxsNewMerged.size() << std::endl
210  << std::endl
211  << "\tnumber of tracks without good lepton+track vertex: "
212  << tracksWithoutVertex.size() << std::endl
213  << "\tnumber of 2-track vertexes without lepton: "
214  << resultExtra.vtxsInitPassed.size() << std::endl
215  << "\tnumber of unmerged 2-track vertexes without lepton: "
216  << resultExtra.vtxsInitPassedNotMerged.size() << std::endl
217  << "\tnumber of merged vertexes without lepton: "
218  << resultExtra.vtxsNewMerged.size() << std::endl
219  << name() << "::mergeInitVertices - ALL DONE" << std::endl
220  << "=========================================="
221  );
222 
223 
224  return result;
225 }
226 
228  const FittingInput &input,
229  std::vector<std::unique_ptr<xAOD::Vertex>> &initVtxs,
231  const VtxType vtxType
232 )
233 {
234  /*
235  This function merges iterively vertexes with this algorithm:
236  o) Sort 2-track vertexes by sum of track pT
237  o) Select the vertex with the highest sum of track pT as the seed vertex
238  - Sort all other vertexes by the distance to the seed vertex
239  - Add tracks from the closest vertex to the selected vertex
240  - Fit new vertex:
241  -- if the new vertex passes cuts, select as the new seed vertex
242  -- if the new vertex fails cuts, continue with the original seed vertex
243  -- Remove this closest vertex from the list
244  - Resort remaining tracks by the distance to the seed vertex and repeat
245  o) Remove the 2-track vertexes that were merged from the global list and repeat
246  */
247 
248  // Only 0 or 1 2-track vertices - add the vertex to not merged list and return
249  if(result.vtxsInitPassed.size() < 2) {
250  result.vtxsInitPassedNotMerged = std::move(initVtxs);
251 
252  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - too few vertexes: nothing more to do");
253 
254  return false;
255  }
256 
257  //
258  // Make 2-track vertex data structures
259  //
260  std::vector<TwoTrackVtx> vtxs2Track;
261 
262  for(std::unique_ptr<xAOD::Vertex> &vtx: initVtxs) {
263  if(vtx->nTrackParticles() != 2) {
264  ATH_MSG_WARNING("mergeIteratively2TrackVtxs - wrong number of tracks: " << vtx->nTrackParticles());
265  continue;
266  }
267 
268  if(vtx->nTrackParticles() !=2 ) {
269  ATH_MSG_WARNING("mergeIteratively2TrackVtxs - vertex does not contain 2 TrackParticles: ntrack=" << vtx->nTrackParticles());
270  continue;
271  }
272 
273  TwoTrackVtx vtx2track;
274  vtx2track.trackId0 = vtx->trackParticle(0);
275  vtx2track.trackId1 = vtx->trackParticle(1);
276 
277  if(!vtx2track.trackId0 || !vtx2track.trackId1) {
278  ATH_MSG_WARNING("mergeIteratively2TrackVtxs - failed to find TrackParticles for 2-track vertex");
279  continue;
280  }
281 
282  vtx2track.vertex = vtx.get();
283  vtx2track.vertexFitProb = Prompt::getVertexFitProb(vtx.get());
284  vtx2track.sumTrackPt = vtx2track.trackId0->pt() + vtx2track.trackId1->pt();
285 
286  vtxs2Track.push_back(vtx2track);
287  }
288 
289  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - start processing with " << vtxs2Track.size() << " input vertexes ");
290 
291  if(vtxs2Track.size() < 2) {
292  ATH_MSG_WARNING("mergeIteratively2TrackVtxs - logic error: found only " << vtxs2Track.size() << " 2-track vertex");
293  return false;
294  }
295 
296  //
297  // Sort 2-track vertexes by ID track pT
298  //
299  std::sort(vtxs2Track.begin(), vtxs2Track.end(), Prompt::SortTwoTrackVtxBySumTrackPt());
300 
301  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - number of 2 track passed vertexes=" << vtxs2Track.size());
302 
303  for(const TwoTrackVtx &vtx: vtxs2Track) {
304  ATH_MSG_DEBUG("Input vertex with 2 tracks sum pT=" << vtx.sumTrackPt << "\n " << vtxAsStr(vtx.vertex, true));
305  }
306 
307  //
308  // Plot distances between all unique pairs of 2-track vertexes
309  //
310  plotVertexDistances(vtxs2Track);
311 
312  //
313  // Iterative fit vertices for merging:
314  //
315  std::vector<TwoTrackVtx>::iterator currVit = vtxs2Track.begin();
316 
317  /*
318  Seed new vertex with 2-track vertex containing
319  highest pT ID track (non-lepton track)
320  */
321  while(currVit != vtxs2Track.end()) {
322  xAOD::Vertex* seedVtx = currVit->vertex;
323 
324  /*
325  We potentially generate a new vertex here,
326  so it has to be a unique_ptr. If the vertex could not be merged,
327  then the newMergedVtx will remain a nullptr.
328  */
329  std::unique_ptr<xAOD::Vertex> newMergedVtx = nullptr;
330  getNewMergedVertex(
331  seedVtx, newMergedVtx, input, currVit, vtxs2Track, vtxType
332  );
333 
334  // Check to see if the new merged vertex is not a nullptr
335  // (i.e., if the vertex could be merged)
336  if(newMergedVtx) {
337  // Remove 2-track vertexes that were merged
338  removeMerged2TrackVertexes(newMergedVtx.get(), vtxs2Track);
339 
340  // Reset current vertex iterator to beginning
341  currVit = vtxs2Track.begin();
342 
343  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - new merged vertex:\n" << vtxAsStr(newMergedVtx.get(), false));
344 
345  // Save new merged vertex (it is new because it is distinct from seed vertex)
346  result.vtxsNewMerged.push_back(std::move(newMergedVtx));
347  }
348  else {
349  //
350  // This vertex could not be merged - try next one
351  //
352  ++currVit;
353 
354  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - could not merge 2-track vertex:\n" << vtxAsStr(seedVtx, false));
355  }
356  }
357 
358  //
359  // Record unmerged two-track vertexes
360  //
361  for(std::unique_ptr<xAOD::Vertex> &vtxUniquePtr: initVtxs) {
362  for(TwoTrackVtx &vtx: vtxs2Track) {
363  if (vtxUniquePtr.get() == vtx.vertex){
364  result.vtxsInitPassedNotMerged.push_back(std::move(vtxUniquePtr));
365 
366  ATH_MSG_DEBUG("Unmerged " << vtxAsStr(vtx.vertex, true));
367  }
368  }
369  }
370 
371  ATH_MSG_DEBUG(name() << "::mergeIteratively2TrackVtxs - finished processing:" << std::endl
372  << " number of unmerged 2-track vertexes=" << vtxs2Track .size() << std::endl
373  << " number of merged vertexes=" << result.vtxsNewMerged.size() );
374 
375  for(TwoTrackVtx &vtx: vtxs2Track) {
376  ATH_MSG_DEBUG("Unmerged " << vtxAsStr(vtx.vertex, true));
377  }
378 
379  for(const std::unique_ptr<xAOD::Vertex>& vtx: result.vtxsNewMerged) {
380  ATH_MSG_DEBUG("Merged " << vtxAsStr(vtx.get(), true));
381  }
382 
383  return true;
384 }
385 
387  xAOD::Vertex* seedVtx,
388  std::unique_ptr<xAOD::Vertex> &newMergedVtx,
389  const FittingInput &input,
391  std::vector<TwoTrackVtx> &vtxs2Track,
392  const VtxType vtxType
393 ) {
394  // Generate a list of 2-track vertices other than the seed vertex
395  std::vector<TwoTrackVtx> others;
396 
397  for(std::vector<TwoTrackVtx>::iterator vit = vtxs2Track.begin(); vit != vtxs2Track.end(); ++vit) {
398  if(vit != currVit) {
399  others.push_back(*vit);
400  }
401  }
402 
403  // Sort other vertices by distance to the seed vertex
404  std::sort(others.begin(), others.end(), Prompt::SortTwoTrackVtxByDistToSeed(seedVtx));
405 
406  // Call recursive function to fit seed+closest vertex pairs
407  xAOD::Vertex* mergedVtx = fitSeedVertexCluster(
408  input, seedVtx, vtxType, others
409  );
410 
411  /*
412  If the returned vertex is the seed vertex, that means that the
413  vertex could not be merged. We do not want to return it because
414  then we would assign two unique_ptrs to the same underlying
415  vertex object. Instead, we leave newMergedVtx as a nullptr
416 
417  If they are different, then we do in fact have a new vertex,
418  and we are safe to encapsulate it in a unique_ptr.
419  */
420  if (mergedVtx == seedVtx){
421  newMergedVtx.reset(nullptr);
422  } else {
423  newMergedVtx.reset(mergedVtx);
424  }
425 }
426 
427 //=============================================================================
429  const FittingInput &input,
430  xAOD::Vertex* seedVtx,
431  const VtxType vtxType,
432  std::vector<TwoTrackVtx> &others
433 )
434 {
435  //
436  // Reached end of the recursive loop
437  //
438  if(others.empty()) {
439  return seedVtx;
440  }
441 
442  //
443  // Re-sort other vertices by distance to the seed vertex - needed because seed position changes when vertices are merged
444  //
445  std::sort(others.begin(), others.end(), Prompt::SortTwoTrackVtxByDistToSeed(seedVtx));
446 
447  // Take closest vertex
448  xAOD::Vertex* currVtx = others.front().vertex;
449 
450  if(!currVtx) {
451  ATH_MSG_WARNING("VertexIterativeFitMergingTool::fitSeedVertexCluster - current vertex is null pointer");
452  return seedVtx;
453  }
454 
455  //
456  // Remove closest vertex from the list
457  //
458  others.erase(others.begin());
459 
460  /*
461  Found nearby vertex - fit merged vertex
462  */
463  std::unique_ptr<xAOD::Vertex> candVtx =fitSeedPlusOtherVertex(
464  input, seedVtx, currVtx, vtxType
465  );
466 
467  if(!candVtx) {
468  //
469  // Failed to fit new vertex - continue with current seed vertex
470  //
471 
472  ATH_MSG_DEBUG("fitSeedVertexCluster - NEW MERGED VERTEX FIT FAILED" << std::endl
473  << "---------------------------------------------------------------------------");
474 
475  return fitSeedVertexCluster(input, std::move(seedVtx), vtxType, others);
476  }
477 
478  const double probCand = getVertexFitProb(candVtx.get());
479  const double probSeed = getVertexFitProb(seedVtx);
480 
481  double probCandOverSeed = -1.0;
482 
483  if(probSeed > 0.0) {
484  probCandOverSeed = probCand/probSeed;
485  }
486 
487  const double distToSeed = getDistance(seedVtx, candVtx.get());
488  const double distToCurr = getDistance(currVtx, candVtx.get());
489 
490  fillTH1(m_histNewVtxFitChi2, candVtx->chiSquared());
491  fillTH1(m_histNewVtxFitProb, probCand);
492 
493  fillTH1(m_histNewVtxFitDistToSeed, distToSeed);
494  fillTH1(m_histNewVtxFitDistToCurr, distToCurr);
495  fillTH1(m_histNewVtxFitProbCandOverSeed, probCandOverSeed);
496 
497  if(seedVtx->nTrackParticles() > 2) {
498  fillTH1(m_histNewVtxFitProbCandOverSeed3Trk, probCandOverSeed);
499  }
500 
501  std::stringstream str;
502 
503 
504  str << " dist to seed=" << distToSeed << ", probCandOverSeed=" << probCandOverSeed << std::endl
505  << " seed: " << vtxAsStr(seedVtx, false) << std::endl
506  << " curr: " << vtxAsStr(currVtx, true)
507  << " cand: " << vtxAsStr(candVtx.get(), true)
508  << "fitSeedVertexCluster - finished" << std::endl
509  << "---------------------------------------------------------------------------" << std::endl;
510 
511 
512 
513  if(!(passVertexSelection(candVtx.get()) && probCandOverSeed > m_minCandOverSeedFitProbRatio)) {
514  //
515  // New fitted merged vertex failed selection
516  //
517 
518  ATH_MSG_DEBUG("fitSeedVertexCluster - FAIL NEW MERGED VERTEX\n" << str.str());
519 
520 
521  fillTH1(m_histNewVtxFitDistToSeedFail, distToSeed);
522  fillTH1(m_histNewVtxFitProbCandOverSeedFail, probCandOverSeed);
523 
524  //
525  // Continue with current seed vertex
526  //
527  return fitSeedVertexCluster(input, seedVtx, vtxType, others);
528  }
529 
530  fillTH1(m_histNewVtxFitDistToSeedPass, distToSeed);
531  fillTH1(m_histNewVtxFitProbCandOverSeedPass, probCandOverSeed);
532 
533  if(seedVtx->nTrackParticles() > 2) {
534  fillTH1(m_histNewVtxFitProbCandOverSeed3TrkPass, probCand/probSeed);
535  }
536 
537  //
538  // Succesfully fitted new vertex
539  //
540 
541  ATH_MSG_DEBUG("fitSeedVertexCluster - PASS NEW MERGED VERTEX" << str.str());
542 
543 
544  return fitSeedVertexCluster(input, candVtx, vtxType, others);
545 }
546 
547 // this signature is only called recursively, if a merged vertex candidate has been
548 // found. Ensures that we release the final merged candidate to hand it
549 // back to the original caller.
551  const FittingInput &input,
552  std::unique_ptr<xAOD::Vertex> & seedVtx,
553  const VtxType vtxType,
554  std::vector<TwoTrackVtx> &others
555 ){
556  // remember the seed vertex before the call
557  xAOD::Vertex* originalSeed = seedVtx.get();
558  // call the original signature
559  xAOD::Vertex* iterationResult = fitSeedVertexCluster(input,seedVtx.get(), vtxType,others);
560  // if the iteration has finished (it is returning the seed), release the seed vertex.
561  // This will be re-captured by the top level caller after exiting the recursion stack.
562  if (iterationResult == originalSeed) return seedVtx.release();
563  // otherwise, return the iteration result. The seed vertex will be deleted
564  // when the call stack unwinds.
565  else return iterationResult;
566 }
567 
569  const xAOD::Vertex *mergedVtx,
570  std::vector<TwoTrackVtx> &vtxs
571 ) const {
572  if(!mergedVtx) {
573  ATH_MSG_WARNING("VertexIterativeFitMergingTool::removeMerged2TrackVertexes - merged vertex is null pointer");
574  return 0;
575  }
576 
577  unsigned icount = 0;
578  std::vector<TwoTrackVtx>::iterator vit = vtxs.begin();
579 
580  while(vit != vtxs.end()) {
581  int iCountMatchedTrack = 0;
582 
583  for(unsigned k = 0; k < mergedVtx->nTrackParticles(); ++k) {
584  const xAOD::TrackParticle *track = mergedVtx->trackParticle(k);
585 
586  if(!track) {
587  ATH_MSG_WARNING("removeMerged2TrackVertexes - merged vertex contains null TrackParticle pointer");
588  continue;
589  }
590 
591  if(vit->trackId0 == track) { iCountMatchedTrack++; }
592  if(vit->trackId1 == track) { iCountMatchedTrack++; }
593  }
594 
595  if(iCountMatchedTrack == 2) {
596  //
597  // Found 2-track vertex that was merged - remove this vertex
598  //
599  vit = vtxs.erase(vit);
600  icount++;
601 
602  ATH_MSG_DEBUG("removeMerged2TrackVertexes - removed merged 2-track vertex");
603  }
604  else {
605  ++vit;
606 
607  ATH_MSG_DEBUG("removeMerged2TrackVertexes - skip unmerged 2-track vertex");
608  }
609  }
610 
612  name() << "::removeMerged2TrackVertexes - merged vertex ntrack=" << mergedVtx->nTrackParticles()
613  << ", removed " << icount << " merged 2-track vertexes"
614  );
615 
616  return icount;
617 }
618 
619 //=============================================================================
621  const std::vector<TwoTrackVtx> &others
622 ) {
623  for(std::vector<TwoTrackVtx>::const_iterator fit = others.begin(); fit != others.end(); ++fit) {
624  for(std::vector<TwoTrackVtx>::const_iterator sit = fit+1; sit != others.end(); ++sit) {
625  const double dist = Prompt::getDistance(fit->vertex, sit->vertex);
626  const double sig1 = Prompt::getNormDist(fit->vertex->position(), sit->vertex->position(), fit->vertex->covariance(), msg(MSG::WARNING));
627  const double sig2 = Prompt::getNormDist(fit->vertex->position(), sit->vertex->position(), sit->vertex->covariance(), msg(MSG::WARNING));
628 
629  fillTH1(m_histVtx2TrkPairDist, dist);
630  fillTH1(m_histVtx2trkPairDistZoom, dist);
631  fillTH1(m_histVtx2TrkPairSig1, sig1);
632  fillTH1(m_histVtx2TrkPairSig2, sig2);
633  }
634  }
635 }
636 
637 //=============================================================================
638 std::vector<const xAOD::TrackParticle *> Prompt::VertexIterativeFitMergingTool::getTracksWithoutVertex(
639  const std::vector<xAOD::Vertex*> &passVtxs,
640  const std::vector<const xAOD::TrackParticle *> &selectedTracks
641 )
642 {
643  //
644  // Plot unmatched tracks
645  //
646  std::vector<const xAOD::TrackParticle *> tracksWithoutVertex;
647 
648  unsigned iCountDoMatch = 0;
649 
650  for(const xAOD::TrackParticle *track: selectedTracks) {
651  bool match = false;
652 
653  for(const xAOD::Vertex *vtx: passVtxs) {
654  for(unsigned k = 0; k < vtx->nTrackParticles(); ++k) {
655  const xAOD::TrackParticle *vtxTrack = vtx->trackParticle(k);
656 
657  if(vtxTrack == track) {
658  match = true;
659  break;
660  }
661  }
662  }
663 
664  if(match) {
665  iCountDoMatch++;
666  }
667  else {
668  tracksWithoutVertex.push_back(track);
669  }
670  }
671 
672  fillTH1(m_histSelectedTrackCountAll, selectedTracks.size());
673  fillTH1(m_histSelectedTrackCountMatch2Vtx, iCountDoMatch);
674  fillTH1(m_histSelectedTrackCountWithout2Vtx, tracksWithoutVertex.size());
675 
676  return tracksWithoutVertex;
677 }
678 
679 //=============================================================================
681 {
682  //
683  // Check whether vertex passes quality cuts
684  //
685  if(!vtx) {
686  ATH_MSG_WARNING("passVertexSelection - input vertex is null pointer");
687  return false;
688  }
689 
690  if(!(vtx->numberDoF() > 0 && vtx->chiSquared() >= 0)) {
691  return false;
692  }
693 
694  const double fitProb = Prompt::getVertexFitProb(vtx);
695 
696  ATH_MSG_DEBUG("passVertexSelection - vertex pointer=" << vtx << " chi2/ndof=" << vtx->chiSquared() << "/" << vtx->numberDoF() << ", prob=" << fitProb);
697 
698  return fitProb > m_minFitProb;
699 }
700 
701 //=============================================================================
703  const FittingInput &input,
704  const xAOD::Vertex *seedVtx,
705  const xAOD::Vertex *otherVtx,
706  const VtxType vtxType
707 )
708 {
709  //
710  // Fit two 2-track vertexes
711  //
712  if(!seedVtx) {
713  ATH_MSG_WARNING("fitSeedPlusOtherVertex - null seed Vertex pointer");
714  return 0;
715  }
716 
717  if(!otherVtx) {
718  ATH_MSG_WARNING("fitSeedPlusOtherVertex - null other Vertex pointer");
719  return 0;
720  }
721 
722  if(otherVtx->nTrackParticles() != 2) {
723  ATH_MSG_WARNING("fitSeedPlusOtherVertex - other Vertex does not have 2 tracks: ntrack=" << otherVtx->nTrackParticles());
724  return 0;
725  }
726 
727  //
728  // Collect tracks from the seed vertex
729  //
730  std::vector<const xAOD::TrackParticle *> tracks;
731 
732  for(unsigned k = 0; k < seedVtx->nTrackParticles(); ++k) {
733  const xAOD::TrackParticle *track = seedVtx->trackParticle(k);
734 
735  if(track) {
736  tracks.push_back(track);
737  }
738  else {
739  ATH_MSG_WARNING("fitSeedPlusOtherVertex - seed vertex contains TrackParticle null pointer");
740  }
741  }
742 
743  //
744  // Collect tracks from other vertices
745  //
746  for(unsigned k = 0; k < otherVtx->nTrackParticles(); ++k) {
747  const xAOD::TrackParticle *track = otherVtx->trackParticle(k);
748 
749  if(track) {
750  tracks.push_back(track);
751  }
752  else {
753  ATH_MSG_WARNING("fitSeedPlusOtherVertex - other vertex contains TrackParticle null pointer");
754  }
755  }
756 
757  //
758  // Fit new vertex
759  //
760  std::unique_ptr<xAOD::Vertex> secVtx = m_vertexFitterTool->fitVertexWithSeed(
761  input, tracks, seedVtx->position(), vtxType
762  );
763 
764  if(!secVtx) {
765  ATH_MSG_WARNING("fitSeedPlusOtherVertex - failed to fit vertex");
766  return 0;
767  }
768 
769  return secVtx;
770 }
771 
772 std::vector<std::unique_ptr<xAOD::Vertex>> Prompt::VertexIterativeFitMergingTool::fit2TrackVertexes(
773  const FittingInput &input,
774  std::vector<const xAOD::TrackParticle *> &selectedTracks,
775  const VtxType vtxType
776 )
777 {
778  //
779  // Fit all possible combinations of two 2-track vertexes
780  //
781  std::vector<std::unique_ptr<xAOD::Vertex>> passVtxs;
782 
783  if(selectedTracks.size() < 2) {
784  ATH_MSG_DEBUG("fit2TrackVertexeses - 0 or 1 input tracks - nothing to do");
785  return passVtxs;
786  }
787 
788  ATH_MSG_DEBUG(name() << "::fit2TrackVertexes - start with " << selectedTracks.size() << " tracks");
789 
790  //
791  // Sort tracks by decreasing pT
792  //
793  std::sort(selectedTracks.begin(), selectedTracks.end(), SortTracksByPt());
794 
795  unsigned icount = 0;
796 
797  for(std::vector<const xAOD::TrackParticle *>::const_iterator it1 = selectedTracks.begin(); it1 != selectedTracks.end(); ++it1) {
798  for(std::vector<const xAOD::TrackParticle *>::const_iterator it2 = it1 + 1; it2 != selectedTracks.end(); ++it2) {
799  const xAOD::TrackParticle *track1 = *it1;
800  const xAOD::TrackParticle *track2 = *it2;
801 
802  if(!track1 || !track2) {
803  ATH_MSG_WARNING("fit2TrackVertexeses - logic error: TrackParticle null pointer");
804  continue;
805  }
806 
807  std::vector<const xAOD::TrackParticle *> fit_tracks = {track1, track2};
808 
809  //
810  // Fit new vertex
811  //
812  std::unique_ptr<xAOD::Vertex> vtx = m_vertexFitterTool->fitVertexWithPrimarySeed(
813  input, fit_tracks, vtxType
814  );
815 
816  icount++;
817 
818  if(!vtx) {
819  ATH_MSG_WARNING("fit2TrackVertexeses - failed to fit vertex");
820  continue;
821  }
822 
823  if(passVertexSelection(vtx.get())) {
824  ATH_MSG_DEBUG("fit2TrackVertexeses - pass vertex: " << vtxAsStr(vtx.get(), true));
825  passVtxs.push_back(std::move(vtx));
826  }
827  }
828  }
829 
830  ATH_MSG_DEBUG(name() << "::fit2TrackVertexes - finished processing: " << std::endl
831  << " number of input tracks: " << selectedTracks.size() << std::endl
832  << " number of 2-track combinations: " << icount << std::endl
833  << " number of passed 2-track vertexes: " << passVtxs .size() << std::endl
834  << name() << "::fit2TrackVertexes - all is done" );
835 
836  return passVtxs;
837 }
838 
839 //=============================================================================
840 StatusCode Prompt::VertexIterativeFitMergingTool::makeHist(TH1 *&h, const std::string &key, int nbin, double xmin, double xmax)
841 {
842  //
843  // Initiliase histogram pointer. If configured to run in validation mode, then create and register histogram
844  //
845  h = 0;
846 
847  if(m_outputStream.empty() || key.empty()) {
848  return StatusCode::SUCCESS;
849  }
850 
851  const std::string hname = name() + "_" + key;
852  const std::string hist_key = "/"+m_outputStream+"/"+hname;
853 
854  h = new TH1D(hname.c_str(), hname.c_str(), nbin, xmin, xmax);
855  h->SetDirectory(0);
856 
857  return m_histSvc->regHist(hist_key, h);
858 }
Prompt::SortTracksByPt
Definition: VertexIterativeFitMergingTool.h:78
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
Prompt::MergeResultNotOwner::vtxsInitPassed
std::vector< xAOD::Vertex * > vtxsInitPassed
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:72
Prompt::VertexIterativeFitMergingTool::fitSeedVertexCluster
xAOD::Vertex * fitSeedVertexCluster(const FittingInput &input, xAOD::Vertex *seedVtx, const VtxType vtxType, std::vector< TwoTrackVtx > &others)
Definition: VertexIterativeFitMergingTool.cxx:428
PromptUtils.h
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
Prompt::VertexIterativeFitMergingTool::fitSeedPlusOtherVertex
std::unique_ptr< xAOD::Vertex > fitSeedPlusOtherVertex(const FittingInput &input, const xAOD::Vertex *seedVtx, const xAOD::Vertex *otherVtx, const VtxType vtxType)
Definition: VertexIterativeFitMergingTool.cxx:702
Prompt::VertexIterativeFitMergingTool::mergeInitVertices
virtual MergeResultNotOwner mergeInitVertices(const FittingInput &input, const xAOD::TrackParticle *tracklep, std::vector< std::unique_ptr< xAOD::Vertex >> &initVtxs, const std::vector< const xAOD::TrackParticle * > &selectedTracks) override
Definition: VertexIterativeFitMergingTool.cxx:68
Prompt::getVertexFitProb
double getVertexFitProb(const xAOD::Vertex *vtx)
Definition: PromptUtils.cxx:21
dqt_zlumi_pandas.hname
string hname
Definition: dqt_zlumi_pandas.py:279
Prompt::VertexIterativeFitMergingTool::fit2TrackVertexes
std::vector< std::unique_ptr< xAOD::Vertex > > fit2TrackVertexes(const FittingInput &input, std::vector< const xAOD::TrackParticle * > &selectedTracks, const VtxType vtxType)
Definition: VertexIterativeFitMergingTool.cxx:772
Prompt::VertexIterativeFitMergingTool::makeHist
StatusCode makeHist(TH1 *&h, const std::string &key, int nbin, double xmin, double xmax)
Definition: VertexIterativeFitMergingTool.cxx:840
Prompt::TwoTrackVtx::vertex
xAOD::Vertex * vertex
Definition: VertexIterativeFitMergingTool.h:72
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
Prompt::VertexIterativeFitMergingTool::VertexIterativeFitMergingTool
VertexIterativeFitMergingTool(const std::string &name, const std::string &type, const IInterface *parent)
Definition: VertexIterativeFitMergingTool.cxx:16
Prompt::vtxAsStr
std::string vtxAsStr(const xAOD::Vertex *vtx, bool print_tracks=false)
Definition: PromptUtils.cxx:172
Prompt::VertexIterativeFitMergingTool::plotVertexDistances
void plotVertexDistances(const std::vector< TwoTrackVtx > &others)
Definition: VertexIterativeFitMergingTool.cxx:620
Prompt::FittingInput
Definition: IVertexFittingTool.h:60
Prompt::kTwoTrackVtxWithoutLepton
@ kTwoTrackVtxWithoutLepton
Definition: IVertexFittingTool.h:63
Prompt::TwoTrackVtx::sumTrackPt
double sumTrackPt
Definition: VertexIterativeFitMergingTool.h:77
Prompt::VertexIterativeFitMergingTool::removeMerged2TrackVertexes
unsigned removeMerged2TrackVertexes(const xAOD::Vertex *mergedVtx, std::vector< TwoTrackVtx > &vtxs) const
Definition: VertexIterativeFitMergingTool.cxx:568
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
Prompt::MergeResultNotOwner::vtxsInitPassedNotMerged
std::vector< std::unique_ptr< xAOD::Vertex > > vtxsInitPassedNotMerged
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:73
Prompt::VertexIterativeFitMergingTool::getTracksWithoutVertex
std::vector< const xAOD::TrackParticle * > getTracksWithoutVertex(const std::vector< xAOD::Vertex * > &passVtxs, const std::vector< const xAOD::TrackParticle * > &selectedTracks)
Definition: VertexIterativeFitMergingTool.cxx:638
Prompt::getNormDist
double getNormDist(const Amg::Vector3D &PrimVtx, const Amg::Vector3D &SecVtx, const std::vector< float > &ErrorMatrix, MsgStream &msg)
Definition: PromptUtils.cxx:57
Prompt::VertexIterativeFitMergingTool::passVertexSelection
bool passVertexSelection(const xAOD::Vertex *vtx) const
Definition: VertexIterativeFitMergingTool.cxx:680
Prompt::getDistance
double getDistance(const xAOD::Vertex *vtx1, const xAOD::Vertex *vtx2)
Definition: PromptUtils.cxx:41
xmin
double xmin
Definition: listroot.cxx:60
Prompt::VertexIterativeFitMergingTool::initialize
virtual StatusCode initialize() override
Definition: VertexIterativeFitMergingTool.cxx:27
DetDescrDictionaryDict::it1
std::vector< HWIdentifier >::iterator it1
Definition: DetDescrDictionaryDict.h:17
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Prompt::TwoTrackVtx::trackId0
const xAOD::TrackParticle * trackId0
Definition: VertexIterativeFitMergingTool.h:73
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
VertexIterativeFitMergingTool.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Prompt::TwoTrackVtx::vertexFitProb
double vertexFitProb
Definition: VertexIterativeFitMergingTool.h:76
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Prompt::VertexIterativeFitMergingTool::getNewMergedVertex
void getNewMergedVertex(xAOD::Vertex *seedVtx, std::unique_ptr< xAOD::Vertex > &newMergedVtx, const FittingInput &input, std::vector< TwoTrackVtx >::iterator &currVit, std::vector< TwoTrackVtx > &vtxs2Track, const VtxType vtxType)
Definition: VertexIterativeFitMergingTool.cxx:386
xAOD::Vertex_v1::trackParticle
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
Definition: Vertex_v1.cxx:249
MuonValidation_CreateResolutionProfiles.fit
def fit(h, emin, emax)
Definition: MuonValidation_CreateResolutionProfiles.py:69
Prompt::SortByIDTrackPt
Definition: PromptUtils.h:67
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
VarHolder.h
Prompt::VtxType
VtxType
Definition: IVertexFittingTool.h:48
xAOD::Vertex_v1::numberDoF
float numberDoF() const
Returns the number of degrees of freedom of the vertex fit as float.
Prompt::TwoTrackVtx::trackId1
const xAOD::TrackParticle * trackId1
Definition: VertexIterativeFitMergingTool.h:74
Prompt::MergeResultNotOwner::vtxsNewMerged
std::vector< std::unique_ptr< xAOD::Vertex > > vtxsNewMerged
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:70
Prompt::SortTwoTrackVtxByDistToSeed
Definition: VertexIterativeFitMergingTool.h:85
xAOD::Vertex_v1::chiSquared
float chiSquared() const
Returns the of the vertex fit as float.
h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
Prompt::TwoTrackVtx
Definition: VertexIterativeFitMergingTool.h:59
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Prompt::fillTH1
void fillTH1(TH1 *h, double val, double weight=1.0)
Definition: PromptUtils.cxx:104
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Prompt::kIterativeFitVtx
@ kIterativeFitVtx
Definition: IVertexFittingTool.h:62
Prompt::kIterativeFitVtxWithoutLepton
@ kIterativeFitVtxWithoutLepton
Definition: IVertexFittingTool.h:64
xmax
double xmax
Definition: listroot.cxx:61
Prompt::SortTwoTrackVtxBySumTrackPt
Definition: VertexIterativeFitMergingTool.h:72
str
Definition: BTagTrackIpAccessor.cxx:11
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::VertexIterativeFitMergingTool::mergeIteratively2TrackVtxs
bool mergeIteratively2TrackVtxs(const FittingInput &input, std::vector< std::unique_ptr< xAOD::Vertex >> &initVtxs, MergeResultNotOwner &result, const VtxType vtxType)
Definition: VertexIterativeFitMergingTool.cxx:227
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:356
fitman.k
k
Definition: fitman.py:528
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
Prompt::MergeResultNotOwner
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:69