ATLAS Offline Software
BTagVrtSecMulti.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Header include
7 //-------------------------------------------------
8 // Other stuff
11 
12 #include "boost/graph/bron_kerbosch_all_cliques.hpp"
13 #include "TMath.h"
14 #include "TH1D.h"
15 #include "TH2D.h"
16 #include "TProfile.h"
17 
18 #include <algorithm>
19 
20 
33 
34 
35 namespace InDet{
36 
37 const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not coming from B,C-decays
38 
39 
40 std::vector<xAOD::Vertex*>
42  const xAOD::Vertex& primVrt,
43  const TLorentzVector& jetDir,
44  std::vector<double>& results,
45  compatibilityGraph_t& compatibilityGraph) const
46 {
47 
48  const double probVrtMergeLimit = 0.01;
49 
50  int inpNPart = 0;
51  if (xAODwrk) {
52  inpNPart = xAODwrk->InpTrk.size();
53  xAODwrk->FoundSecondTracks.clear(); // Input clearing for failure return
54  results.clear(); // Input clearing for failure return
55  }
56  ATH_MSG_DEBUG( "InDet getVrtSecMulti() called with NPart=" << inpNPart );
57 
58  std::vector<xAOD::Vertex*> finalVertices(0);
59 
60  if (inpNPart < 2) {
61  return finalVertices;
62  } // 0,1 track => nothing to do!
63 
64  float evtWgt = 1.;
65  const EventContext & ctx = Gaudi::Hive::currentContext();
67  if (eventInfo.isValid()) {
68  if(eventInfo->hasBeamSpotWeight()) evtWgt *= eventInfo->beamSpotWeight();
69  } else ATH_MSG_DEBUG("No event info object found!");
70 
71 
72  long int nTracks = 0;
73  TLorentzVector momentumJet;
74  int nRefPVTrk = 0;
75  if (xAODwrk) {
76  nRefPVTrk = selGoodTrkParticle(xAODwrk->InpTrk, primVrt, jetDir, xAODwrk->listJetTracks,evtWgt);
77  while (!xAODwrk->listJetTracks.empty() &&
78  xAODwrk->listJetTracks[0]->pt() / jetDir.Pt() > 1.){
79  xAODwrk->listJetTracks.erase(xAODwrk->listJetTracks.begin());
80  }
81  nTracks = xAODwrk->listJetTracks.size();
82  momentumJet = totalMom(xAODwrk->listJetTracks);
83  }
84 
85  if (nTracks < 2) {
86  return finalVertices;
87  } // 0,1 selected track => nothing to do!
88 
89 
90  ATH_MSG_DEBUG("Number of selected tracks inside jet= " << nTracks);
91 
92  if (m_fillHist) {
93  Hists& h = getHists();
94  h.m_hb_jmom->Fill(momentumJet.Perp(), evtWgt);
95  h.m_hb_ntrkjet->Fill(static_cast<double>(nTracks), evtWgt);
96  }
97 
98  //
99  // InpTrk[] - input track list
100  // listJetTracks[] - list of good tracks in jet for vertex search
101  //------------------------------------------------------------
102  // Initial track list ready
103  // Find 2track vertices
104  //
105 
106  std::vector<double> inpMass(nTracks, m_massPi);
107  double vrt2TrackNumber = 0;
108 
109  if (xAODwrk) {
110  select2TrVrt(xAODwrk->listJetTracks,
111  xAODwrk->TracksForFit,
112  primVrt,
113  jetDir,
114  inpMass,
115  nRefPVTrk,
116  xAODwrk->TrkFromV0,
117  xAODwrk->listSecondTracks,
118  compatibilityGraph);
119  if (xAODwrk->TrkFromV0.size() > 1) {
120  removeDoubleEntries(xAODwrk->TrkFromV0);
121  AnalysisUtils::Sort::pT(&(xAODwrk->TrkFromV0));
122  }
123  vrt2TrackNumber = xAODwrk->listSecondTracks.size()/2.0;
126  }
127 
128 
129  ATH_MSG_DEBUG(" Found different tracks in pairs=" << vrt2TrackNumber);
130 
131  //
132  // listSecondTracks[] - list of all tracks which participate in some
133  // 2-track vertex TrkFromV0[] - "bad" tracks from any
134  // V0/material/conversion m_Incomp[] - main vector of pointers for
135  // multivertex search
136  //-----------------------------------------------------------------------------------------------------
137  // Secondary track list is ready
138  // Creation of initial vertex set
139  //
140 
141  std::unique_ptr<std::vector<WrkVrt>> wrkVrtSet = std::make_unique<std::vector<WrkVrt>>();
142  WrkVrt newvrt;
143  newvrt.Good = true;
144  std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
145  StatusCode sc;
146 
147  //================================================== Boost version (don't
148  //forget to uncomment addEdge in select2TrVrt()
149  std::vector<std::vector<int>> allCliques;
150  bron_kerbosch_all_cliques(compatibilityGraph, clique_visitor(allCliques));
151 
152  for (const auto& clique : allCliques) {
153 
154  newvrt.selTrk.clear();
155  if (xAODwrk) xAODwrk->tmpListTracks.clear();
156 
157  for (int i_trk : clique){
158  newvrt.selTrk.push_back(i_trk);
159  if(xAODwrk) xAODwrk->tmpListTracks.push_back(xAODwrk->listJetTracks.at(i_trk));
160  }
161 
162  if (xAODwrk) sc = VKalVrtFitFastBase(xAODwrk->tmpListTracks, newvrt.vertex, *state);
163  if (sc.isFailure() ||
164  newvrt.vertex.perp() > m_rLayer2 * 2.) {
165  // No initial estimation
166  m_fitSvc->setApproximateVertex(primVrt.x(),
167  primVrt.y(),
168  primVrt.z(),
169  *state); // Use as starting point
170  if (m_multiWithPrimary)
171  m_fitSvc->setApproximateVertex(0., 0., 0., *state);
172  } else {
173  Amg::Vector3D vDist = newvrt.vertex - primVrt.position();
174  double jetVrtDir = jetDir.Px() * vDist.x() + jetDir.Py() * vDist.y() +
175  jetDir.Pz() * vDist.z();
176  if (m_multiWithPrimary) jetVrtDir = std::abs(jetVrtDir); // Always positive when primary vertex is seeked for
177  if (jetVrtDir > 0.) {
178  // Good initial estimation
179  m_fitSvc->setApproximateVertex(newvrt.vertex.x(),
180  newvrt.vertex.y(),
181  newvrt.vertex.z(),
182  *state); //Use as starting point
183  } else {
184  m_fitSvc->setApproximateVertex(primVrt.x(), primVrt.y(), primVrt.z(), *state);
185  }
186  }
187 
188  sc = StatusCode::FAILURE;
189  if (xAODwrk) {
190  sc = VKalVrtFitBase(xAODwrk->tmpListTracks,
191  newvrt.vertex,
192  newvrt.vertexMom,
193  newvrt.vertexCharge,
194  newvrt.vertexCov,
195  newvrt.chi2PerTrk,
196  newvrt.trkAtVrt,
197  newvrt.chi2,
198  *state,
199  false);
200  }
201  if (sc.isFailure()) continue; // Bad fit - goto next solution
202 
203  if (clique.size() == 2 && newvrt.chi2 > 10.) continue; // Bad 2track vertex
204 
205  if (newvrt.chi2PerTrk.size() == 2){
206  newvrt.chi2PerTrk[0] = newvrt.chi2PerTrk[1] = newvrt.chi2 / 2.;
207  }
208  newvrt.Good = true;
209  newvrt.nCloseVrt = 0;
210  newvrt.dCloseVrt = 1000000.;
211  newvrt.projectedVrt =
212  jetProjDist(newvrt.vertex, primVrt, jetDir); // 3D SV-PV distance
213  wrkVrtSet->push_back(newvrt);
214  }
215 
216  //
217  //========= Initial cleaning of solutions
218  //-Remove worst track from vertices with very bad Chi2
219  bool disassembled = false;
220 
221  do {
222  disassembled = false;
223  int NSoluI = (*wrkVrtSet).size();
224  for (int iv = 0; iv < NSoluI; iv++) {
225  WrkVrt vrt = (*wrkVrtSet)[iv];
226  if (!vrt.Good || vrt.selTrk.size() == 2) continue;
227  if (TMath::Prob(vrt.chi2, 2 * vrt.selTrk.size() - 3) < 1.e-3) {
228  if (xAODwrk) disassembleVertex(wrkVrtSet.get(), iv, xAODwrk->listJetTracks, *state);
229  disassembled = true;
230  }
231  }
232  }while(disassembled);
233 
234  //-Remove vertices fully contained in other vertices
235  while( (*wrkVrtSet).size()>1 ){
236  int tmpN = (*wrkVrtSet).size();
237 
238  int iv = 0;
239  for(; iv<tmpN-1; iv++){
240  WrkVrt vert_i = (*wrkVrtSet)[iv];
241  if(!vert_i.Good ) continue;
242  int ntrk_i = (*wrkVrtSet)[iv].selTrk.size();
243 
244  int jv = iv+1;
245  for(; jv<tmpN; jv++){
246  WrkVrt vert_j = (*wrkVrtSet)[jv];
247  if(!vert_j.Good ) continue;
248  int ntrk_j = (*wrkVrtSet)[jv].selTrk.size();
249 
250  int nTCom = nTrkCommon(wrkVrtSet.get(), iv, jv);
251  if(nTCom==ntrk_i){
252  (*wrkVrtSet).erase((*wrkVrtSet).begin()+iv);
253  break;
254  }
255  else if(nTCom==ntrk_j){
256  (*wrkVrtSet).erase((*wrkVrtSet).begin()+jv);
257  break;
258  }
259  }
260  if(jv!=tmpN) break; // One vertex is erased. Restart check
261 
262  }
263  if(iv==tmpN-1) break; // No vertex deleted
264 
265  } // end while( (*wrkVrtSet).size()>1 )
266 
267 
268  //
269  //- Try to merge all vertices with common tracks
270  std::multimap<int,std::pair<int,int>> vrtWithCommonTrk;
271  std::multimap<int,std::pair<int,int>>::reverse_iterator icvrt;
272  do{
273  int NSoluI = (*wrkVrtSet).size();
274  vrtWithCommonTrk.clear();
275  for(int iv = 0; iv<NSoluI-1; iv++ ){
276  for(int jv = iv+1; jv<NSoluI; jv++){
277  if(!(*wrkVrtSet)[iv].Good || !(*wrkVrtSet)[jv].Good) continue;
278  int nTCom=nTrkCommon(wrkVrtSet.get(), iv, jv);
279  if(!nTCom)continue;
280  vrtWithCommonTrk.emplace(nTCom,std::make_pair(iv,jv));
281  }
282  }
283 
284  for(icvrt = vrtWithCommonTrk.rbegin(); icvrt!=vrtWithCommonTrk.rend(); ++icvrt){
285  int nTCom = (*icvrt).first;
286  int iv = (*icvrt).second.first;
287  int jv = (*icvrt).second.second;
288  int nTrkI = (*wrkVrtSet)[iv].selTrk.size();
289  int nTrkJ = (*wrkVrtSet)[jv].selTrk.size();
290  double probV = -1.;
291  if (xAODwrk) {
292  probV = mergeAndRefitVertices(wrkVrtSet.get(), iv, jv, newvrt, xAODwrk->listJetTracks, *state);
293  }
294 
295  if(probV<probVrtMergeLimit){
296  if(nTrkI==2 || nTrkJ==2 || nTCom<2) {
297  continue;
298  }
299  if(nTCom>nTrkI-nTCom || nTCom>nTrkJ-nTCom){
300  //2 and more common tracks for NTr>=3 vertices. Merge anyway.
301  if(xAODwrk) mergeAndRefitOverlapVertices( wrkVrtSet.get(), iv, jv, xAODwrk->listJetTracks, *state);
302  break; //Vertex list is changed. Restart merging from scratch.
303  }
304  continue; //Continue merging loop
305  }
306 
307  newvrt.Good = true;
308  (*wrkVrtSet).push_back(newvrt);
309  (*wrkVrtSet)[iv].Good = false;
310  (*wrkVrtSet)[jv].Good = false;
311  break; //Merging successful. Break merging loop and remake list of connected vertices
312  } // end for(icvrt)
313 
314  } while( icvrt != vrtWithCommonTrk.rend() );
315 
316 
317  if(m_fillHist){
318  int cvgood=0;
319  for(const auto& vrt : (*wrkVrtSet)){
320  if(vrt.Good) cvgood++;
321  }
322  Hists& h = getHists();
323  h.m_hb_rawVrtN->Fill( static_cast<float>(cvgood), evtWgt);
324  }
325 
326  //-Remove all bad vertices from the working set
327  for(auto &tmpV : (*wrkVrtSet) ) {
328  if(tmpV.vertex.perp()>m_rLayer3+10.) tmpV.Good = false; //Vertices outside Pixel detector
329  TLorentzVector SVPV(tmpV.vertex.x()-primVrt.x(),
330  tmpV.vertex.y()-primVrt.y(),
331  tmpV.vertex.z()-primVrt.z(), 1.);
332  if(jetDir.DeltaR(SVPV)>m_coneForTag) tmpV.Good = false; // SV is outside of the jet cone
333  }
334 
335  unsigned int tmpV = 0;
336  while( tmpV<(*wrkVrtSet).size() ){
337  if( !(*wrkVrtSet)[tmpV].Good ) (*wrkVrtSet).erase((*wrkVrtSet).begin()+tmpV);
338  else tmpV++;
339  }
340 
341  if((*wrkVrtSet).empty()){ // No vertices at all
342  return finalVertices;
343  }
344 
345  std::vector< std::vector<float> > trkScore(0);
346  if(xAODwrk && m_useTrackClassificator){
347  for(auto &trk : xAODwrk->listJetTracks) trkScore.push_back(m_trackClassificator->trkTypeWgts(trk, primVrt, jetDir));
348  }
349 
350  for(auto &tmpV : (*wrkVrtSet) ) tmpV.projectedVrt=jetProjDist(tmpV.vertex, primVrt, jetDir); //Setup ProjectedVrt
351 
352  //----------------------------------------------------------------------------
353  // Here we have the overlapping solutions.
354  // Vertices may have only 1 common track.
355  // Now solution cleaning
356 
357  std::unique_ptr<std::vector< std::deque<long int> > > trkInVrt = std::make_unique<std::vector<std::deque<long int>>>(nTracks);
358  trackClassification(wrkVrtSet.get(), trkInVrt.get());
359 
360  double foundMaxT;
361  long int selectedTrack, selectedVertex;
362  int foundV1, foundV2;
363 
364  state = m_fitSvc->makeState();
365  while( ( foundMaxT = MaxOfShared(wrkVrtSet.get(), trkInVrt.get(), selectedTrack, selectedVertex) ) > 0) {
366 
367  double foundMinVrtDst = 1000000.;
368  if(foundMaxT<m_trackDetachCut) foundMinVrtDst = minVrtVrtDist(wrkVrtSet.get(), foundV1, foundV2);
369 
370  //Choice of action
371  if( foundMaxT<m_trackDetachCut && foundMinVrtDst<m_vertexMergeCut
372  && nTrkCommon(wrkVrtSet.get(), foundV1, foundV2) ){
373 
374  bool vrtMerged=false; //to check whether something is really merged
375  while(foundMinVrtDst<m_vertexMergeCut){
376  if(foundV1<foundV2) std::swap(foundV1, foundV2); // Always drop vertex with smallest number
377 
378  double probV = 0.;
379  if (xAODwrk) probV = mergeAndRefitVertices(wrkVrtSet.get(), foundV1, foundV2, newvrt, xAODwrk->listJetTracks, *state);
380 
381  if(probV>probVrtMergeLimit && newvrt.vertexMom.M()<c_vrtBCMassLimit){
382  // Good merged vertex found
383  double tstDst = jetProjDist(newvrt.vertex, primVrt, jetDir);
384  if(tstDst>0.){
385  // only positive vertex directions are accepted as merging result
386  std::swap((*wrkVrtSet)[foundV1], newvrt);
387  (*wrkVrtSet)[foundV1].projectedVrt = tstDst;
388  (*wrkVrtSet)[foundV2].Good = false; //Drop vertex
389  (*wrkVrtSet)[foundV2].selTrk.clear(); //Clean dropped vertex
390  vrtMerged=true;
391  }
392  }
393 
394  (*wrkVrtSet)[foundV1].nCloseVrt = -1;
395  (*wrkVrtSet)[foundV1].dCloseVrt = 1000000.; //For minVrtVrtDistNext optimisation(!)
396  (*wrkVrtSet)[foundV2].nCloseVrt = -1;
397  (*wrkVrtSet)[foundV2].dCloseVrt = 1000000.; //Exclude given pair
398  foundMinVrtDst = minVrtVrtDistNext(wrkVrtSet.get(), foundV1, foundV2); //Check other vertices
399 
400  } // end while(foundMinVrtDst<m_vertexMergeCut)
401 
402  if(vrtMerged){
403  trkInVrt->resize(nTracks);
404  trackClassification(wrkVrtSet.get(), trkInVrt.get());
405  continue; // Something was merged => goto next cycle. Otherwise break the found track-vertex link
406  }
407 
408  } // end choice of action
409 
410  removeTrackFromVertex(wrkVrtSet.get(), trkInVrt.get(), selectedTrack, selectedVertex);
411 
412  sc = StatusCode::FAILURE;
413  if(xAODwrk) sc = refitVertex( wrkVrtSet.get(), selectedVertex, xAODwrk->listJetTracks, *state, false);
414 
415  (*wrkVrtSet)[selectedVertex].projectedVrt = jetProjDist((*wrkVrtSet)[selectedVertex].vertex, primVrt, jetDir);
416 
417  if( sc.isFailure() ) (*wrkVrtSet)[selectedVertex].Good = false; //bad vertex
418  if( (*wrkVrtSet)[selectedVertex].projectedVrt<0.
419  && (*wrkVrtSet)[selectedVertex].selTrk.size()==2 ){
420  (*wrkVrtSet)[selectedVertex].Good = false; // 2track vertex migrates behind PV - drop it.
421  }
422 
423  } // end while( (foundMaxT = MaxOfShared)>0 )
424 
425 
426  //
427  // Final check/merge for close vertices
428  //
429  double minDistVV = minVrtVrtDist( wrkVrtSet.get(), foundV1, foundV2); //recalculate VV distances
430  while ( minDistVV < m_vertexMergeCut) {
431  if(foundV1<foundV2) std::swap(foundV1, foundV2);
432 
433  double probV = 0.;
434  if(xAODwrk) probV = mergeAndRefitVertices(wrkVrtSet.get(), foundV1, foundV2, newvrt, xAODwrk->listJetTracks, *state);
435 
436  if(probV>probVrtMergeLimit && newvrt.vertexMom.M()<c_vrtBCMassLimit){
437  // Good merged vertex found
438  double tstDst = jetProjDist(newvrt.vertex, primVrt, jetDir);
439  if(tstDst>0.){
440  // only positive vertex directions are accepted as merging result
441  std::swap((*wrkVrtSet)[foundV1],newvrt);
442  (*wrkVrtSet)[foundV1].projectedVrt = tstDst;
443  (*wrkVrtSet)[foundV2].Good = false; //Drop vertex
444  (*wrkVrtSet)[foundV2].selTrk.clear(); //Clean dropped vertex
445  }
446  }
447 
448  (*wrkVrtSet)[foundV1].nCloseVrt = -1;
449  (*wrkVrtSet)[foundV1].dCloseVrt = 1000000.; //For minVrtVrtDistNext optimisation(!)
450  (*wrkVrtSet)[foundV2].nCloseVrt = -1;
451  (*wrkVrtSet)[foundV2].dCloseVrt = 1000000.; //Exclude given pair
452  minDistVV = minVrtVrtDistNext(wrkVrtSet.get(), foundV1, foundV2);
453  }
454 
455  //
456  // Try to improve vertices with big Chi2 if something went wrong. Just precaution.
457  for(unsigned int iv=0; iv<wrkVrtSet->size(); iv++) {
458  WrkVrt vert_i = (*wrkVrtSet)[iv];
459  if(!vert_i.Good) continue; //don't work on vertex which is already bad
460  if( vert_i.selTrk.size()<3 ) continue;
461 
462  double tmpProb = TMath::Prob( vert_i.chi2, 2*vert_i.selTrk.size()-3 ); //Chi2 of the original vertex
463  if(tmpProb<0.001){
464  if(xAODwrk) tmpProb = improveVertexChi2(wrkVrtSet.get(), iv, xAODwrk->listJetTracks, *state, false);
465  if(tmpProb<0.001) vert_i.Good = false;
466  vert_i.projectedVrt = jetProjDist(vert_i.vertex, primVrt, jetDir);
467  }
468  }
469 
470  // Final vertex selection/cleaning
471  state = m_fitSvc->makeState();
472 
473  //--------- Start with 1-track vertices
474  //=First check if the track was detached from a multitrack vertex. If so - reattach.
475  for(auto &ntrVrt : (*wrkVrtSet)){
476  if(!ntrVrt.Good || ntrVrt.selTrk.size()<=1) continue;
477 
478  for(auto &onetVrt : (*wrkVrtSet)){
479  if(!onetVrt.Good || onetVrt.selTrk.size()!=1) continue;
480 
481  if(ntrVrt.detachedTrack==onetVrt.selTrk[0]){
482  WrkVrt newV(ntrVrt);
483  newV.selTrk.push_back(ntrVrt.detachedTrack);
484  double vProb = 0.;
485  if(xAODwrk) vProb = refitVertex(newV, xAODwrk->listJetTracks, *state, true);
486  if(vProb>probVrtMergeLimit){
487  onetVrt.Good=false;
488  ntrVrt=newV;
489  ntrVrt.detachedTrack=-1;
490  }
491  break;
492  }
493  }
494  }
495 
496  //=Recheck if the track was detached from a 2track vertex. If so - reattach.
497  for(auto &iVrt : (*wrkVrtSet)){
498  if(!iVrt.Good || iVrt.selTrk.size()!=1) continue;
499 
500  for(auto &jVrt : (*wrkVrtSet)){
501  if(!jVrt.Good || jVrt.selTrk.size()!=1) continue;
502 
503  if(iVrt.detachedTrack==jVrt.selTrk[0]){
504  WrkVrt newV(iVrt);
505  newV.selTrk.push_back(iVrt.detachedTrack);
506  double vProb = 0.;
507  if(xAODwrk) vProb = refitVertex(newV, xAODwrk->listJetTracks, *state, true);
508  if(vProb>probVrtMergeLimit){
509  jVrt.Good = false;
510  iVrt = newV;
511  iVrt.detachedTrack = -1;
512  }
513  break;
514  }
515  }
516 
517  }
518 
519 
520  for(auto &ntrVrt : (*wrkVrtSet)){
521  if(!ntrVrt.Good || ntrVrt.selTrk.size()<=1) continue;
522 
523  for(auto tr : ntrVrt.selTrk){
524  for(auto &onetVrt : (*wrkVrtSet)){
525  if(!onetVrt.Good || onetVrt.selTrk.size()!=1) continue;
526 
527  if(onetVrt.detachedTrack==tr){
528  WrkVrt newV(ntrVrt);
529  newV.selTrk.push_back(onetVrt.selTrk[0]);
530  double vProb = 0.;
531  if(xAODwrk) vProb = refitVertex( newV, xAODwrk->listJetTracks, *state, true);
532  if(vProb>probVrtMergeLimit){
533  onetVrt.Good = false;
534  ntrVrt = newV;
535  }
536  }
537 
538  }
539  }
540 
541  } // end for(auto &ntrVrt : (*wrkVrtSet))
542 
543 
544  for(auto & curVrt : (*wrkVrtSet) ) {
545  if(!curVrt.Good ) continue; //don't work on vertex which is already bad
546  if( std::abs(curVrt.vertex.z())>650. ){
547  curVrt.Good = false;
548  continue;
549  } //vertex outside Pixel det. For ALL vertices
550  if(curVrt.selTrk.size() != 1) continue;
551 
552  curVrt.Good = false; // Make them bad by default
553 
555  // 1track vertices left unassigned from good 2tr vertices
556  double Signif3D = 0.;
557  vrtVrtDist(primVrt,curVrt.vertex, curVrt.vertexCov, Signif3D); //VK non-projected Signif3D is worse
558  double tmpProb = TMath::Prob(curVrt.chi2, 1); //Chi2 of the original 2tr vertex
559 
560  bool trkGood = false;
561  if(xAODwrk) trkGood = check1TrVertexInPixel(xAODwrk->listJetTracks[curVrt.selTrk[0]], curVrt.vertex, curVrt.vertexCov);
562 
563  if(trkGood && tmpProb>0.01){
564  // accept only good tracks coming from good 2tr vertex
565  std::vector<double> Impact,ImpactError;
566  double Signif3DP = 0;
567  if(xAODwrk) Signif3DP = m_fitSvc->VKalGetImpact(xAODwrk->listJetTracks[curVrt.selTrk[0]], primVrt.position(), 1, Impact, ImpactError, *state);
568 
569  if(m_fillHist && curVrt.vertex.perp()>20.){
570  Hists& h = getHists();
571  h.m_hb_diffPS->Fill(Signif3DP, evtWgt);
572  }
573 
574  if(Signif3DP>2.*m_trkSigCut && Signif3D>m_sel2VrtSigCut) curVrt.Good = true; // accept only tracks which are far from primary vertex
575  }
576 
577  }
578 
579  } // end for(auto & curVrt : (*wrkVrtSet) )
580 
581 
582  for(auto& curVrt : (*wrkVrtSet)){
583  if(!curVrt.Good ) continue; //don't work on vertex which is already bad
584  int nth = curVrt.selTrk.size();
585  if(nth==1) continue; // 1track vertices are treated already
586 
587  double Signif3D = 0.;
588  vrtVrtDist(primVrt,curVrt.vertex, curVrt.vertexCov, Signif3D); //VK non-projected Signif3D is worse
589  if(xAODwrk) xAODwrk->tmpListTracks.resize(nth);
590 
591  for(int i = 0; i < nth; i++) {
592  if(xAODwrk) xAODwrk->tmpListTracks[i] = xAODwrk->listJetTracks[curVrt.selTrk[i]];
593  }
594  curVrt.Good = false; // Make all vertices bad for futher selection
595 
596  if(nth <= 1) continue; // Definitely bad vertices
597  if(curVrt.projectedVrt<0.) continue; // Remove vertices behind primary one
598 
599  if(TMath::Prob( curVrt.chi2, 2*nth-3)<0.001) continue; // Bad Chi2 of refitted vertex
600 
601  if(nth==2 && xAODwrk){
602  // Check track pixel hit patterns vs vertex position.
604  if(!check2TrVertexInPixel(xAODwrk->tmpListTracks[0],xAODwrk->tmpListTracks[1],curVrt.vertex,curVrt.vertexCov))continue;
605  }
606 
607  // Check track first measured points vs vertex position.
609  float ihitR = xAODwrk->tmpListTracks[0]->radiusOfFirstHit();
610  float jhitR = xAODwrk->tmpListTracks[1]->radiusOfFirstHit();
611  float vrErr = vrtRadiusError(curVrt.vertex, curVrt.vertexCov);
612  if(std::abs(ihitR-jhitR)>25.) continue; // Hits in different pixel layers
613  if(curVrt.vertex.perp()-std::min(ihitR,jhitR) > 2.*vrErr) continue; // Vertex is behind hit in pixel
614  }
615 
616  }
617 
618  //--- Check interactions on pixel layers
619  if(m_fillHist && nth==2){
620  Hists& h = getHists();
621  h.m_hb_r2d->Fill(curVrt.vertex.perp(), evtWgt);
622  }
623 
625  double xvt = curVrt.vertex.x();
626  double yvt = curVrt.vertex.y();
627  double zvt = curVrt.vertex.z();
628  double Rvt = std::hypot(xvt,yvt);
629  int bin = m_ITkPixMaterialMap->FindBin(zvt,Rvt);
630  if(m_ITkPixMaterialMap->GetBinContent(bin)>0) continue;
631  }
632 
633  if(m_fillHist && nth==2){
634  Hists& h = getHists();
635  h.m_hb_r2d->Fill(curVrt.vertex.perp(), evtWgt);
636  }
637 
638  //--- Check V0s and conversions
639  if(nth==2 && curVrt.vertexCharge==0 && curVrt.detachedTrack<0){
640  double mass_PiPi = curVrt.vertexMom.M();
641  double mass_PPi = massV0(curVrt.trkAtVrt,m_massP,m_massPi);
642  double mass_EE = massV0(curVrt.trkAtVrt,m_massE,m_massE);
643  if(m_fillHist){
644  Hists& h = getHists();
645  h.m_hb_massPiPi->Fill(mass_PiPi, evtWgt);
646  h.m_hb_massPPi ->Fill(mass_PPi, evtWgt);
647  if(curVrt.vertex.perp()>20.) h.m_hb_massEE->Fill(mass_EE, evtWgt);
648  }
649 
650  if(std::abs(mass_PiPi-m_massK0) < 22.) continue;
651  if(std::abs(mass_PPi-m_massLam) < 8.) continue;
652  if(mass_EE < 60. && curVrt.vertex.perp() > 20.) continue;
653  }
654 
655  if(m_fillHist){
656  Hists& h = getHists();
657  h.m_hb_sig3DTot->Fill(Signif3D, evtWgt);
658  }
659  if(Signif3D<m_sel2VrtSigCut)continue; //Main PV-SV distance quality cut
660 
661  curVrt.Good = true; // Vertex is absolutely good
662 
663  } // end for(auto& curVrt : (*wrkVrtSet))
664 
665  //--Final cleaning of the 1-track vertices set. Must be behind all other cleanings.
666  if(m_multiWithOneTrkVrt) clean1TrVertexSet(wrkVrtSet.get());
667 
668  //Checks
669  int n2trVrt = 0; // N of vertices with 2 tracks
670  int nNtrVrt = 0; // N vertices with 3 and more tracks
671  int ngoodVertices = 0; // Final number of good vertices
672  std::vector<WrkVrt> goodVertices(0);
673 
674  for(auto & iv : (*wrkVrtSet)) {
675  int nth = iv.selTrk.size();
676  if(nth == 0) continue; // Definitely bad vertices
677 
678  if(iv.Good){
679  ngoodVertices++;
680  goodVertices.emplace_back(iv);
681  if(nth==2) n2trVrt++;
682  if(nth>=3) nNtrVrt++;
683  }
684  }
685 
686  if(ngoodVertices == 0 || (n2trVrt+nNtrVrt)==0){ // No good vertices at all
687  return finalVertices;
688  }
689 
690  //sorting
691  while(1){
692  bool swapDone = false; // Sort on XY distance from (0.,0.)
693  for(unsigned int iv = 0; iv<goodVertices.size()-1; iv++) {
694  if(goodVertices[iv].vertex.perp() > goodVertices[iv+1].vertex.perp()){
695  std::swap( goodVertices[iv], goodVertices[iv+1] );
696  swapDone = true;
697  }
698  }
699  if(!swapDone) break;
700  }
701 
702  while(1){
703  bool swapDone = false; // Then sort on Projected dist if R<20.
704  for(unsigned int iv = 0; iv<goodVertices.size()-1; iv++) {
705  if(goodVertices[iv+1].vertex.perp() > 400.) continue;
706  if(goodVertices[iv].projectedVrt > goodVertices[iv+1].projectedVrt){
707  std::swap( goodVertices[iv], goodVertices[iv+1] );
708  swapDone = true;
709  }
710  }
711  if(!swapDone) break;
712  }
713 
714  if(ngoodVertices>1){
715  if( goodVertices[1].vertexMom.M()-goodVertices[0].vertexMom.M() > 5000.){
716  std::swap( goodVertices[0], goodVertices[1] );
717  }
718  }
719 
720  if(m_fillHist){
721  Hists& h = getHists();
722  h.m_hb_distVV->Fill(minVrtVrtDist(wrkVrtSet.get(), foundV1, foundV2), evtWgt);
723  }
724 
725 
726  //----------------------------------------------------------------------------------
727  // Nonused tracks for one-track-vertex search
728  //
729  // VK - It tries to recover tracks which were already rejected on previous stages of algorithm.
730 
731  std::vector<int> nonusedTrk(0);
732  for(int trk=0; trk<nTracks; trk++){
733  bool present = false;
734 
735  for(const auto& iv : (*wrkVrtSet)){
736  if(iv.Good){
737  for(auto t_in_V : iv.selTrk){
738  if(trk==t_in_V){
739  present = true;
740  break;
741  }
742  }
743  }
744  if(present) break;
745  }
746 
747  if(!present) nonusedTrk.push_back(trk);
748  }
749 
750  struct MatchedSV{int indVrt; double Signif3D;};
751  std::vector<MatchedSV> matchSV(0);
752 
753  for(const auto& i_trk : nonusedTrk){
754  MatchedSV tmpV = {0, 1.e9};
755 
756  for(unsigned int iv = 0; iv<goodVertices.size(); iv++){
757  //--Find vertex closest to the given track
758  if(!goodVertices[iv].Good) continue;
759  if(goodVertices[iv].selTrk.size()<2) continue;
760  if(vrtVrtDist(primVrt, goodVertices[iv].vertex, goodVertices[iv].vertexCov, jetDir) < 10.) continue; //--Too close to PV
761 
762  double Signif = 0.;
763  std::vector<double> Impact, ImpactError;
764  if(xAODwrk) Signif = m_fitSvc->VKalGetImpact(xAODwrk->listJetTracks[i_trk], goodVertices[iv].vertex, 1, Impact, ImpactError, *state);
765  if(Signif<tmpV.Signif3D){
766  tmpV.Signif3D = Signif;
767  tmpV.indVrt=iv;
768  }
769  }
770 
771  matchSV.push_back(tmpV);
772  }
773 
774  for(int iv = 0; iv<static_cast<int>(goodVertices.size()); iv++){
775  WrkVrt newV(goodVertices[iv]);
776  bool addedT = false;
777  std::map<double,int> addTrk;
778 
779  for(unsigned int it = 0; it<nonusedTrk.size(); it++){
780  if(matchSV[it].indVrt==iv) addTrk[matchSV[it].Signif3D]=it;
781  }
782 
783  std::map<double,int>::iterator atrk=addTrk.begin();
784  if(!addTrk.empty()){
785  if(atrk->first<4.){
786  newV.selTrk.push_back(nonusedTrk[atrk->second]);
787  addedT=true;
788  }
789  }
790 
791  if(addTrk.size()>1){
792  ++atrk;
793  if(atrk->first<4.){
794  newV.selTrk.push_back(nonusedTrk[atrk->second]);
795  }
796  }
797 
798  if(addedT){
799  double vProb = 0.;
800  if(xAODwrk) vProb = refitVertex(newV, xAODwrk->listJetTracks, *state, true);
801  if(vProb>0.01) goodVertices[iv] = newV;
802  else{
803  std::vector<WrkVrt> TestVertices(1,newV);
804  if(xAODwrk) vProb = improveVertexChi2(&TestVertices, 0, xAODwrk->listJetTracks, *state, true);
805  if(vProb>0.01) goodVertices[iv] = TestVertices[0];
806  }
807  }
808 
809  } // end for(unsigned int iv)
810 
811 
812  //-------------------------------------------
813  // Saving and final cleaning
814  //
815  int ngoodVertices_final = 0; // Final number of good vertices
816  int n1trVrt = 0; // Final number of good 1-track vertices
817  TLorentzVector vertexMom;
818  bool isPrimaryVertex = true;
819 
820  for(auto& vrt : goodVertices){
821  int nth = vrt.selTrk.size();
822  if(xAODwrk) xAODwrk->tmpListTracks.clear();
823 
824  for(int i = 0; i < nth; i++) {
825  int j = vrt.selTrk[i]; // Track number
826  if(xAODwrk) xAODwrk->tmpListTracks.push_back( xAODwrk->listJetTracks[j] );
827  }
828 
829  if( m_fillHist ){
830  Hists& h = getHists();
831  if(nth==1) h.m_hb_r1dc->Fill(vrt.vertex.perp(), evtWgt);
832  if(nth==2) h.m_hb_r2dc->Fill(vrt.vertex.perp(), evtWgt);
833  if(nth==3) h.m_hb_r3dc->Fill(vrt.vertex.perp(), evtWgt);
834  if(nth> 3) h.m_hb_rNdc->Fill(vrt.vertex.perp(), evtWgt);
835  double Signif3D = vrtVrtDist(primVrt, vrt.vertex, vrt.vertexCov, jetDir);
836 
837  if(nth==2){
838  if(vrt.vertexCharge==0) h.m_hb_totmass2T1->Fill(vrt.vertexMom.M(), evtWgt);
839  else h.m_hb_totmass2T2->Fill(vrt.vertexMom.M(), evtWgt);
840  h.m_hb_sig3D2tr->Fill(Signif3D , evtWgt);
841  if(vrt.vertexCharge==0) h.m_hb_totmassEE->Fill(massV0(vrt.trkAtVrt, m_massE, m_massE), evtWgt);
842 
843  }
844  else if(vrt.vertexMom.M()>6000.) h.m_hb_sig3D1tr->Fill(Signif3D, evtWgt);
845  else h.m_hb_sig3DNtr->Fill(Signif3D, evtWgt);
846  }
847 
848  // xAOD::Vertex creation-----------------------------
849  xAOD::Vertex * tmpVertex=new (std::nothrow) xAOD::Vertex();
850  if(!tmpVertex){ //Premature stop due memory allocation failure
851  return finalVertices;
852  }
853  tmpVertex->makePrivateStore();
854  tmpVertex->setPosition(vrt.vertex);
855 
856  std::vector<float> floatErrMtx;
857  floatErrMtx.resize(6);
858  for(int i = 0; i<6; i++) floatErrMtx[i] = vrt.vertexCov[i];
859  tmpVertex->setCovariance(floatErrMtx);
860 
861  tmpVertex->setFitQuality(vrt.chi2, (float)(nth*2-3));
862 
863  std::vector<Trk::VxTrackAtVertex> & tmpVTAV = tmpVertex->vxTrackAtVertex();
864  tmpVTAV.clear();
865 
866  for(int ii = 0; ii<nth; ii++) {
867  AmgSymMatrix(5) CovMtxP;
868  CovMtxP.setIdentity();
869  Trk::Perigee * tmpMeasPer = new Trk::Perigee( 0., 0.,
870  vrt.trkAtVrt[ii][0],
871  vrt.trkAtVrt[ii][1],
872  vrt.trkAtVrt[ii][2],
873  Trk::PerigeeSurface(vrt.vertex),
874  std::move(CovMtxP) );
875  tmpVTAV.emplace_back( 1., tmpMeasPer );
876 
877  if(xAODwrk){
879  TEL.setElement( xAODwrk->tmpListTracks[ii] );
880  const xAOD::TrackParticleContainer* cont = (const xAOD::TrackParticleContainer* ) (xAODwrk->tmpListTracks[ii]->container() );
881  TEL.setStorableObject(*cont);
882  tmpVertex->addTrackAtVertex(TEL,1.);
883  }
884  }
885 
886  finalVertices.push_back(tmpVertex);
887  ngoodVertices_final++;
888  if(nth==1) n1trVrt++;
889 
890  if(isPrimaryVertex && m_multiWithPrimary ){ // skip primary vertex if present
891  isPrimaryVertex = false; // for next vertices in the loop
892  continue;
893  }
894 
895  vertexMom += vrt.vertexMom;
896 
897  } // end for(const auto& vrt : goodVertices)
898 
899  if(m_fillHist){
900  Hists& h = getHists();
901  h.m_hb_goodvrtN->Fill(ngoodVertices_final+0.1, evtWgt);
902  h.m_curTup->ewgt = evtWgt;
903  if(n1trVrt) h.m_hb_goodvrtN->Fill(n1trVrt+15., evtWgt);
904  fillNVrtNTup(goodVertices, trkScore, primVrt, jetDir);
905  }
906 
907  if(ngoodVertices_final==0){
908  return finalVertices;
909  }
910 
911  //-----------------------------------------------------------------------------------
912  // Saving of results
913  //
914  //
915  double totMass = vertexMom.M();
916  results.push_back(totMass); //1st
917  double eRatio = vertexMom.E()/momentumJet.E();
918  results.push_back(eRatio<1. ? eRatio : 1.); //2nd
919  results.push_back(vrt2TrackNumber); //3rd
920  results.push_back(nTracks); //4th
921  if(xAODwrk) results.push_back(xAODwrk->listSecondTracks.size()); //5th
922  results.push_back(0.); //6th - not clear what to use here -> return 0.
923  results.push_back(momentumJet.E()); //7th
924 
925  if(m_fillHist){
926  Hists& h = getHists();
927  h.m_hb_ratio->Fill( results[1], evtWgt);
928  h.m_hb_totmass->Fill( results[0], evtWgt);
929  h.m_hb_nvrt2->Fill( results[2], evtWgt);
930  h.m_hb_mom->Fill( momentumJet.Perp(), evtWgt);
931  }
932 
933  return finalVertices;
934 
935 }
936 
937 
938 
939 
940  /* Service routines*/
941 
942  //-----------------------------------------------------------------------------------
943  // Detach the worst Chi2 track from the vertex and join it (if possible) with other track
944  // from the vertex into additional 2-track vertices
945  //
946  template <class Particle>
947  void InDetVKalVxInJetTool::disassembleVertex(std::vector<WrkVrt> *wrkVrtSet, int iv,
948  std::vector<const Particle*> AllTracks,
949  Trk::IVKalState& istate)
950  const
951  {
952  WrkVrt newvrt;
953  newvrt.Good = true;
954  std::vector<const Particle*> ListBaseTracks;
955  int NTrk = (*wrkVrtSet)[iv].selTrk.size();
956  int SelT = -1;
957  if(NTrk<3) return;
958 
959  StatusCode sc;
960  //=== To get robust definition of most bad outlier
961  m_fitSvc->setRobustness(5, istate);
962  sc = refitVertex(wrkVrtSet, iv, AllTracks, istate, false);
963  if(sc.isFailure()){
964  (*wrkVrtSet)[iv].Good = false;
965  return;
966  }
967 
968  m_fitSvc->setRobustness(0, istate);
969  double Chi2Max=0.;
970  for(int i = 0; i<NTrk; i++){
971  if((*wrkVrtSet)[iv].chi2PerTrk[i]>Chi2Max) {
972  Chi2Max = (*wrkVrtSet)[iv].chi2PerTrk[i];
973  SelT = i;
974  }
975  }
976 
977  unsigned int NVrtCur = wrkVrtSet->size();
978  for(int i = 0; i<NTrk; i++){
979  if(i==SelT) continue;
980  ListBaseTracks.clear();
981  ListBaseTracks.push_back( AllTracks[(*wrkVrtSet)[iv].selTrk[i]] );
982  ListBaseTracks.push_back( AllTracks[(*wrkVrtSet)[iv].selTrk[SelT]] );
983  newvrt.selTrk.resize(2);
984  newvrt.selTrk[0] = (*wrkVrtSet)[iv].selTrk[i];
985  newvrt.selTrk[1] = (*wrkVrtSet)[iv].selTrk[SelT];
986 
987  sc = VKalVrtFitFastBase(ListBaseTracks,newvrt.vertex,istate);
988  if( sc.isFailure() ) continue;
989  if( newvrt.vertex.perp() > m_rLayer2*2. ) newvrt.vertex = Amg::Vector3D(0.,0.,0.);
990  m_fitSvc->setApproximateVertex(newvrt.vertex[0], newvrt.vertex[1], newvrt.vertex[2], istate);
991 
992  sc=VKalVrtFitBase(ListBaseTracks,
993  newvrt.vertex,
994  newvrt.vertexMom,
995  newvrt.vertexCharge,
996  newvrt.vertexCov,
997  newvrt.chi2PerTrk,
998  newvrt.trkAtVrt,
999  newvrt.chi2,
1000  istate, false);
1001  if(sc.isFailure() ) continue;
1002  if(newvrt.chi2>10.) continue; // Too bad 2-track vertex fit
1003 
1004  newvrt.chi2PerTrk[0] = newvrt.chi2PerTrk[1] = newvrt.chi2/2.;
1005  newvrt.nCloseVrt = 0;
1006  newvrt.dCloseVrt = 1000000.;
1007  newvrt.projectedVrt = 0.9999;
1008 
1009  if(wrkVrtSet->size()==NVrtCur){
1010  wrkVrtSet->push_back(newvrt);
1011  continue;
1012  } // just the first added vertex
1013 
1014  if( (*wrkVrtSet).at(NVrtCur).chi2<newvrt.chi2 ) continue; // previously added 2tr vertex was better
1015 
1016  wrkVrtSet->pop_back();
1017  wrkVrtSet->push_back(newvrt);
1018  } // end for(int i = 0; i<NTrk; i++)
1019 
1020  (*wrkVrtSet)[iv].selTrk.erase( (*wrkVrtSet)[iv].selTrk.begin() + SelT ); //remove track
1021  sc = refitVertex(wrkVrtSet, iv, AllTracks, istate, false);
1022  if( sc.isFailure() ) (*wrkVrtSet)[iv].Good = false;
1023  }
1024 
1025 
1026  void InDetVKalVxInJetTool::clean1TrVertexSet(std::vector<WrkVrt> *wrkVrtSet)
1027  {
1028  std::vector<int> countVT(wrkVrtSet->size(),0);
1029  std::vector<int> linkedVrt(wrkVrtSet->size(),0);
1030  //--- Mark as bad the 1track vertex if the detached track is NOT present in any remaining good vertex (>=2tr)
1031 
1032  for(unsigned int i1tv = 0; i1tv<wrkVrtSet->size(); i1tv++) {
1033  WrkVrt vrt1 = (*wrkVrtSet)[i1tv];
1034  if( vrt1.selTrk.size()!=1) continue;
1035  if(!vrt1.Good) continue;
1036  int Trk1 = vrt1.detachedTrack;
1037 
1038  int foundInGoodVrt = 0;
1039  for(unsigned int mtv=0; mtv<wrkVrtSet->size(); mtv++) { //cycle over good vertices with many tracks
1040  WrkVrt vrtm = (*wrkVrtSet)[mtv];
1041  if( vrtm.selTrk.size()<2) continue;
1042  if(!vrtm.Good) continue;
1043 
1044  if( std::find(vrtm.selTrk.begin(), vrtm.selTrk.end(), Trk1) != vrtm.selTrk.end()){
1045  foundInGoodVrt++;
1046  countVT[mtv]++;
1047  linkedVrt[i1tv] = mtv; //Linked vertex found
1048  }
1049  }
1050 
1051  if(!foundInGoodVrt) vrt1.Good=false; // Make the vertex bad
1052  }
1053 
1054  //---Select SINGLE 1tr-vertex from many pointing to one multi-track vertex
1055  for(int mtv = 0; mtv<static_cast<int>(wrkVrtSet->size()); mtv++) {
1056  WrkVrt vrtm = (*wrkVrtSet)[mtv];
1057  if(vrtm.selTrk.size()<2) continue;
1058  if(!vrtm.Good) continue;
1059  if(countVT[mtv] < 1) continue;
1060 
1061  double distM = 1.e9;
1062  int best1TVrt = -1;
1063  for(unsigned int i1tv = 0; i1tv<wrkVrtSet->size(); i1tv++) {
1064  WrkVrt vrt1 = (*wrkVrtSet)[i1tv];
1065  if(vrt1.selTrk.size()!=1) continue;
1066  if(!vrt1.Good) continue;
1067  if(linkedVrt[i1tv]!=mtv) continue;
1068 
1069  double dist = (vrtm.vertexMom+vrt1.vertexMom).M();
1070  if(dist < distM){
1071  distM = dist;
1072  best1TVrt = i1tv;
1073  }
1074  vrt1.Good=false;
1075  }
1076 
1077  if(best1TVrt>-1 && distM<c_vrtBCMassLimit) (*wrkVrtSet)[best1TVrt].Good=true;
1078  }
1079  }
1080 
1081 
1082  void InDetVKalVxInJetTool::trackClassification(std::vector<WrkVrt> *wrkVrtSet,
1083  std::vector< std::deque<long int> > *TrkInVrt)
1084 
1085  {
1086  int NSet = wrkVrtSet->size();
1087  for(int iv = 0; iv<NSet; iv++) {
1088  if(!(*wrkVrtSet)[iv].Good) continue;
1089  int NTrkAtVrt = (*wrkVrtSet)[iv].selTrk.size();
1090  if(NTrkAtVrt<2) continue;
1091 
1092  for(int jt = 0; jt<NTrkAtVrt; jt++){
1093  int tracknum = (*wrkVrtSet)[iv].selTrk[jt];
1094  (*TrkInVrt).at(tracknum).push_back(iv);
1095  }
1096  }
1097  }
1098 
1099 
1100  double InDetVKalVxInJetTool::MaxOfShared(std::vector<WrkVrt> *wrkVrtSet,
1101  std::vector< std::deque<long int> > *TrkInVrt,
1102  long int & selectedTrack,
1103  long int & selectedVertex)
1104 
1105  {
1106  long int NTrack = TrkInVrt->size();
1107  double MaxOf = -999999999, SelectedProb = -1.;
1108  int NShareMax = 0;
1109  for(const auto& trk : (*TrkInVrt)){
1110  int NVrt = trk.size(); // Number of vertices for this track
1111  if(NVrt > NShareMax) NShareMax=NVrt;
1112  }
1113  if(NShareMax<=1) return MaxOf; // No shared tracks
1114 
1115  for(int it = 0; it<NTrack; it++) {
1116  int NVrt = (*TrkInVrt)[it].size(); // Number of vertices for this track
1117  if( NVrt <= 1 ) continue; // Should ALWAYS be checked for safety
1118  if( NVrt < NShareMax ) continue; // Not a shared track with maximal sharing
1119 
1120  int N2trVrt = 0;
1121  for(auto &vrtn : (*TrkInVrt)[it] ){
1122  if((*wrkVrtSet).at(vrtn).selTrk.size()==2) N2trVrt++;
1123  } //count number of 2-track vertices
1124 
1125  for(const auto& VertexNumber : (*TrkInVrt)[it]){
1126  WrkVrt vrt = (*wrkVrtSet).at(VertexNumber);
1127  if(!vrt.Good) continue;
1128  int NTrkInVrt = vrt.selTrk.size();
1129  if( NTrkInVrt <= 1) continue; // one track vertex - nothing to do
1130  if(N2trVrt>0 && N2trVrt<NShareMax && NTrkInVrt>2) continue; // Mixture of multi-track and 2-track vrts. Skip multi-track then.
1131 
1132  for(int itmp = 0; itmp<NTrkInVrt; itmp++){
1133  if( vrt.selTrk[itmp] == it ) { // Track found.
1134  double Chi2Red = vrt.chi2PerTrk.at(itmp); // Normal Chi2 seems the best
1135  if(NTrkInVrt==2){
1136  Chi2Red = vrt.chi2/2.; //VK 2track vertices with Normal Chi2Red
1137  if(vrt.vertexMom.M()>c_vrtBCMassLimit) Chi2Red = 100.; //VK break immediately very heavy 2tr vertices
1138  }
1139 
1140  double prob_vrt = TMath::Prob(vrt.chi2, 2*vrt.selTrk.size()-3);
1141  if( MaxOf < Chi2Red ){
1142  if(MaxOf>0 && prob_vrt>0.01 && SelectedProb<0.01) continue; // Don't disassemble good vertices if a bad one is present
1143  MaxOf = Chi2Red;
1144  selectedTrack = it;
1145  selectedVertex = VertexNumber;
1146  SelectedProb = prob_vrt;
1147  }
1148  }
1149  }
1150 
1151  } // end for(const auto& VertexNumber)
1152 
1153  } // end for(int it = 0; it<NTrack; it++)
1154 
1155  //-- Additional check for a common track in 2tr-2tr/Ntr vertex topology
1156  if( (*TrkInVrt)[selectedTrack].size() == 2){
1157  int v1 = (*TrkInVrt)[selectedTrack][0];
1158  int v2 = (*TrkInVrt)[selectedTrack][1];
1159  WrkVrt vrt1 = (*wrkVrtSet)[v1];
1160  WrkVrt vrt2 = (*wrkVrtSet)[v2];
1161  double prb1 = TMath::Prob(vrt1.chi2, 2*vrt1.selTrk.size()-3);
1162  double prb2 = TMath::Prob(vrt2.chi2, 2*vrt2.selTrk.size()-3);
1163  double dst1 = vrt1.projectedVrt;
1164  double dst2 = vrt2.projectedVrt;
1165 
1166  if(prb1>0.05 && prb2>0.05){
1167  if(vrt1.selTrk.size()==2 && vrt2.selTrk.size()==2){
1168  if (selectedVertex==v1 && dst2<dst1) selectedVertex = v2; // Swap to remove the closest to PV vertex
1169  else if(selectedVertex==v2 && dst1<dst2) selectedVertex = v1; // Swap to remove the closest to PV vertex
1170 
1171  double M1 = vrt1.vertexMom.M();
1172  double M2 = vrt2.vertexMom.M();
1173  if( M1>c_vrtBCMassLimit && M2<c_vrtBCMassLimit ) selectedVertex = v1;
1174  if( M1<c_vrtBCMassLimit && M2>c_vrtBCMassLimit ) selectedVertex = v2;
1175  }
1176 
1177  if( vrt1.selTrk.size()+vrt2.selTrk.size() > 4){
1178  if( vrt1.selTrk.size()==2 && dst1>dst2) selectedVertex = v2;
1179  if( vrt2.selTrk.size()==2 && dst2>dst1) selectedVertex = v1;
1180  }
1181  }
1182  }
1183 
1184  return MaxOf;
1185  }
1186 
1187 
1188  void InDetVKalVxInJetTool::removeTrackFromVertex(std::vector<WrkVrt> *wrkVrtSet,
1189  std::vector< std::deque<long int> > *TrkInVrt,
1190  long int & selectedTrack,
1191  long int & selectedVertex)
1192  const
1193  {
1194  int posInVrtFit = 0; //Position of selectedTrack in vertex fit track list.
1196  WrkVrt vrt = (*wrkVrtSet)[selectedVertex];
1197  std::deque<long int> trk = (*TrkInVrt).at(selectedTrack);
1198 
1199  for(it = vrt.selTrk.begin(); it!=vrt.selTrk.end(); ++it) {
1200  if( (*it) == selectedTrack ) {
1201  vrt.selTrk.erase(it); break;
1202  }
1203  posInVrtFit++;
1204  }
1205 
1206  for(it = trk.begin(); it!=trk.end(); ++it) {
1207  if( (*it) == selectedVertex ) {
1208  trk.erase(it); break;
1209  }
1210  }
1211 
1212  vrt.detachedTrack = selectedTrack;
1213 
1214  //Check if track is removed from 2tr vertex => then sharing of track left should also be decreased
1215  if( vrt.selTrk.size() == 1){
1216  long int LeftTrack = vrt.selTrk[0]; // track left in 1tr vertex
1217  for(it = (*TrkInVrt).at(LeftTrack).begin(); it!=(*TrkInVrt)[LeftTrack].end(); ++it) {
1218  if( (*it) == selectedVertex ) {
1219  (*TrkInVrt)[LeftTrack].erase(it); break;
1220  }
1221  }
1222 
1223  if( TMath::Prob(vrt.chi2, 1) < 0.05 ) vrt.Good = false; // Not really good Chi2 for one-track vertex
1224  if( vrt.vertexMom.M()>c_vrtBCMassLimit) vrt.Good = false; // Vertex is too heavy
1225 
1226  int ipos = 0;
1227  if(posInVrtFit==0) ipos = 1; // Position of remaining track in previous 2track vertex fit
1228  vrt.vertexMom = momAtVrt(vrt.trkAtVrt[ipos]); //Redefine vertexMom using remaining track
1229  if(!(*TrkInVrt)[LeftTrack].empty()) vrt.Good = false; //Vertex is declared false only if remaining track is still linked to another vertex
1230  vrt.trkAtVrt.erase(vrt.trkAtVrt.begin()+posInVrtFit); //Remove also TrkAtVrt
1231  }
1232 
1233  }
1234 
1235  //
1236  // Number of common tracks for 2 vertices
1237  //
1238  int InDetVKalVxInJetTool::nTrkCommon( std::vector<WrkVrt> *wrkVrtSet,
1239  int V1, int V2)
1240 
1241  {
1242  WrkVrt vrt1 = (*wrkVrtSet).at(V1);
1243  WrkVrt vrt2 = (*wrkVrtSet).at(V2);
1244  int NTrk_V1 = vrt1.selTrk.size(); if( NTrk_V1< 2) return 0; // Bad vertex
1245  int NTrk_V2 = vrt2.selTrk.size(); if( NTrk_V2< 2) return 0; // Bad vertex
1246 
1247  int nTrkCom = 0;
1248  if(NTrk_V1 < NTrk_V2){
1249  for(const auto& trk : vrt1.selTrk){
1250  if(std::find(vrt2.selTrk.begin(), vrt2.selTrk.end(), trk) != vrt2.selTrk.end()) nTrkCom++;
1251  }
1252  } else {
1253  for(const auto& trk : vrt2.selTrk){
1254  if( std::find(vrt1.selTrk.begin(), vrt1.selTrk.end(), trk) != vrt1.selTrk.end()) nTrkCom++;
1255  }
1256  }
1257  return nTrkCom;
1258  }
1259 
1260  //
1261  // Minimal normalized vertex-vertex distance
1262  //
1263  double InDetVKalVxInJetTool::minVrtVrtDist(std::vector<WrkVrt> *wrkVrtSet, int & V1, int & V2)
1264  const
1265  {
1266  V1 = V2 = 0;
1267  for(auto& vrt : (*wrkVrtSet)){
1268  vrt.dCloseVrt = 1000000.;
1269  vrt.nCloseVrt = -1;
1270  }
1271  double foundMinVrtDst = 1000000.;
1272 
1273  for(unsigned int iv = 0; iv<wrkVrtSet->size()-1; iv++) {
1274  WrkVrt vrt_i = (*wrkVrtSet)[iv];
1275  if( vrt_i.selTrk.size()< 2) continue; // Bad vertices
1276  if(!vrt_i.Good ) continue; // Bad vertices
1277 
1278  for(unsigned int jv = iv+1; jv<wrkVrtSet->size(); jv++) {
1279  WrkVrt vrt_j = (*wrkVrtSet)[jv];
1280  if( vrt_j.selTrk.size()< 2) continue; // Bad vertices
1281  if(!vrt_j.Good ) continue; // Bad vertices
1282  double tmp = std::abs(vrt_i.vertex.x()-vrt_j.vertex.x())
1283  + std::abs(vrt_i.vertex.y()-vrt_j.vertex.y())
1284  + std::abs(vrt_i.vertex.z()-vrt_j.vertex.z());
1285  if(tmp>20.) continue;
1286 
1287  double tmpDst = vrtVrtDist(vrt_i.vertex, vrt_i.vertexCov,
1288  vrt_j.vertex, vrt_j.vertexCov);
1289  if(tmpDst < foundMinVrtDst){
1290  foundMinVrtDst = tmpDst;
1291  V1 = iv;
1292  V2 = jv;
1293  }
1294  if(tmpDst < vrt_i.dCloseVrt){
1295  vrt_i.dCloseVrt = tmpDst;
1296  vrt_i.nCloseVrt = jv;
1297  }
1298  if(tmpDst < vrt_j.dCloseVrt){
1299  vrt_j.dCloseVrt=tmpDst;
1300  vrt_j.nCloseVrt=iv;
1301  }
1302 
1303  }
1304  }
1305 
1306  return foundMinVrtDst;
1307  }
1308 
1309  //
1310  // Give minimal distance between nonmodifed yet vertices
1311  //
1312  double InDetVKalVxInJetTool::minVrtVrtDistNext(std::vector<WrkVrt> *wrkVrtSet, int & V1, int & V2)
1313  {
1314  V1 = 0; V2 = 0;
1315  double foundMinVrtDst = 1000000.;
1316 
1317  for(unsigned int iv = 0; iv<wrkVrtSet->size()-1; iv++) {
1318  WrkVrt vrt_i = (*wrkVrtSet)[iv];
1319  if(vrt_i.selTrk.size()< 2) continue; // Bad vertex
1320  if(vrt_i.nCloseVrt==-1) continue; // Used vertex
1321 
1322  if(vrt_i.dCloseVrt<foundMinVrtDst){
1323  int vtmp = vrt_i.nCloseVrt;
1324  if((*wrkVrtSet)[vtmp].nCloseVrt==-1) continue; // Close vertex to given [iv] one is modified already
1325  foundMinVrtDst = vrt_i.dCloseVrt;
1326  V1 = iv;
1327  V2 = vtmp;
1328  }
1329  }
1330 
1331  return foundMinVrtDst;
1332  }
1333 
1334  //
1335  // Check two close vertices by explicit vertex fit and create combined vertex if successful
1336  //
1337  template <class Particle>
1338  double InDetVKalVxInJetTool::mergeAndRefitVertices(std::vector<WrkVrt> *wrkVrtSet, int V1, int V2, WrkVrt & newvrt,
1339  std::vector<const Particle*> & AllTrackList,
1340  Trk::IVKalState& istate)
1341  const
1342  {
1343  WrkVrt vrt1 = (*wrkVrtSet)[V1];
1344  WrkVrt vrt2 = (*wrkVrtSet)[V2];
1345  if(!vrt1.Good) return -1.; //bad vertex
1346  if(!vrt2.Good) return -1.; //bad vertex
1347 
1348  newvrt.Good = true;
1349  int NTrk_V1 = vrt1.selTrk.size();
1350  int NTrk_V2 = vrt2.selTrk.size();
1351  newvrt.selTrk.resize(NTrk_V1+NTrk_V2);
1352  std::copy(vrt1.selTrk.begin(), vrt1.selTrk.end(), newvrt.selTrk.begin());
1353  std::copy(vrt2.selTrk.begin(), vrt2.selTrk.end(), newvrt.selTrk.begin()+NTrk_V1);
1354 
1355  std::deque<long int>::iterator TransfEnd ;
1356  sort( newvrt.selTrk.begin(), newvrt.selTrk.end() );
1357  TransfEnd = unique( newvrt.selTrk.begin(), newvrt.selTrk.end() );
1358  newvrt.selTrk.erase( TransfEnd, newvrt.selTrk.end());
1359 
1360  std::vector<const Particle*> fitTrackList(0);
1361  for(const auto& trk : newvrt.selTrk) fitTrackList.push_back( AllTrackList[trk] );
1362 
1363  m_fitSvc->setApproximateVertex( 0.5*(vrt1.vertex[0]+vrt2.vertex[0]),
1364  0.5*(vrt1.vertex[1]+vrt2.vertex[1]),
1365  0.5*(vrt1.vertex[2]+vrt2.vertex[2]),
1366  istate);
1367 
1368  StatusCode sc=VKalVrtFitBase(fitTrackList,
1369  newvrt.vertex,
1370  newvrt.vertexMom,
1371  newvrt.vertexCharge,
1372  newvrt.vertexCov,
1373  newvrt.chi2PerTrk,
1374  newvrt.trkAtVrt,
1375  newvrt.chi2,
1376  istate,
1377  false);
1378  if( sc.isFailure() ) return -1.;
1379  if( newvrt.chi2>500. ) return -1.; //VK protection
1380  if( newvrt.chi2PerTrk.size()==2) newvrt.chi2PerTrk[0] = newvrt.chi2PerTrk[1] = newvrt.chi2/2.;
1381  return TMath::Prob(newvrt.chi2, 2*newvrt.selTrk.size()-3);
1382  }
1383 
1384 
1385  //================== Intelligent merge of multitrack vertices with 2 and more common tracks
1386  template <class Particle>
1387  void InDetVKalVxInJetTool::mergeAndRefitOverlapVertices(std::vector<WrkVrt> *wrkVrtSet, int V1, int V2,
1388  std::vector<const Particle*> & AllTrackList,
1389  Trk::IVKalState& istate) const
1390  {
1391  WrkVrt vrt1 = (*wrkVrtSet)[V1];
1392  WrkVrt vrt2 = (*wrkVrtSet)[V2];
1393  if(!vrt1.Good)return; //bad vertex
1394  if(!vrt2.Good)return; //bad vertex
1395 
1396  WrkVrt newvrt;
1397  newvrt.Good = true;
1398  if( nTrkCommon( wrkVrtSet, V1, V2)<2 )return; //No overlap
1399  //- V1 should become ref. vertex. Another Vrt tracks will be added to it.
1400  if( vrt1.selTrk.size() < vrt2.selTrk.size() ) std::swap(V1,V2); //Vertex with NTrk=max is chosen
1401  else if( vrt1.selTrk.size() == vrt2.selTrk.size() ){
1402  if( vrt1.chi2 > vrt2.chi2 ) std::swap(V1,V2); // Vertex with minimal Chi2 is chosen
1403  }
1404 
1405  //- Fill base track list for new vertex
1406  newvrt.selTrk.resize( vrt1.selTrk.size() );
1407  std::copy(vrt1.selTrk.begin(), vrt1.selTrk.end(), newvrt.selTrk.begin());
1408  //- Identify non-common tracks in second vertex
1409  std::vector<int> noncommonTrk(0);
1410  for(auto &it : vrt2.selTrk){
1411  if( std::find(vrt1.selTrk.begin(), vrt1.selTrk.end(), it) == vrt1.selTrk.end() ) noncommonTrk.push_back(it);
1412  }
1413 
1414  // Try to add non-common tracks one by one
1415  std::vector<const Particle*> fitTrackList(0);
1416  std::vector<int> detachedTrk(0);
1417  StatusCode sc;
1418  WrkVrt bestVrt;
1419  bool foundMerged = false;
1420 
1421  for(auto nct : noncommonTrk){
1422  fitTrackList.clear();
1423  for(const auto& trk : newvrt.selTrk) fitTrackList.push_back( AllTrackList[trk] );
1424  fitTrackList.push_back( AllTrackList.at(nct) );
1425 
1426  m_fitSvc->setApproximateVertex(vrt1.vertex[0], vrt1.vertex[1], vrt1.vertex[2], istate);
1427  sc = VKalVrtFitBase(fitTrackList, newvrt.vertex, newvrt.vertexMom,
1428  newvrt.vertexCharge, newvrt.vertexCov,
1429  newvrt.chi2PerTrk, newvrt.trkAtVrt, newvrt.chi2,
1430  istate, false);
1431  if( sc.isFailure() || TMath::Prob(newvrt.chi2, 2*newvrt.selTrk.size()+2-3)<0.001 ) {
1432  detachedTrk.push_back(nct);
1433  continue;
1434  }
1435 
1436  newvrt.selTrk.push_back(nct); // Compatible track. Add to common vertex.
1437  bestVrt = newvrt;
1438  foundMerged = true;
1439  }
1440 
1441  if(foundMerged) vrt1=bestVrt;
1442  vrt2.Good=false;
1443 
1444  // Now detached tracks
1445  if(detachedTrk.size()>1){
1446  WrkVrt nVrt;
1447  fitTrackList.clear();
1448  nVrt.selTrk.clear();
1449 
1450  for(auto nct : detachedTrk){
1451  fitTrackList.push_back( AllTrackList[nct] );
1452  nVrt.selTrk.push_back(nct);
1453  }
1454 
1455  m_fitSvc->setApproximateVertex(vrt2.vertex[0], vrt2.vertex[1], vrt2.vertex[2], istate);
1456  sc = VKalVrtFitBase(fitTrackList, nVrt.vertex, nVrt.vertexMom,
1457  nVrt.vertexCharge, nVrt.vertexCov,
1458  nVrt.chi2PerTrk, nVrt.trkAtVrt, nVrt.chi2,
1459  istate, false);
1460  if(sc.isSuccess()) (*wrkVrtSet).push_back(nVrt);
1461 
1462  } else if( detachedTrk.size()==1 ){
1463  bool tFound = false;
1464  for( auto &vrt : (*wrkVrtSet) ){
1465  if( !vrt.Good || vrt.selTrk.size()<2 ) continue;
1466  if( std::find(vrt.selTrk.begin(), vrt.selTrk.end(), detachedTrk[0]) != vrt.selTrk.end() ) {
1467  tFound=true; break;
1468  }
1469  }
1470 
1471  if(!tFound) { //Track is not present in other vertices.
1472  double Chi2min = 1.e9;
1473  int selectedTrk = -1;
1474  WrkVrt saveVrt;
1475  fitTrackList.resize(2);
1476  fitTrackList[0]= AllTrackList[detachedTrk[0]];
1477 
1478  for(auto trk : vrt2.selTrk){
1479  if(trk==detachedTrk[0]) continue;
1480  WrkVrt nVrt;
1481  nVrt.Good = true;
1482  fitTrackList[1] = AllTrackList[trk];
1483  m_fitSvc->setApproximateVertex(vrt2.vertex[0], vrt2.vertex[1], vrt2.vertex[2], istate);
1484  sc = VKalVrtFitBase(fitTrackList, nVrt.vertex, nVrt.vertexMom,
1485  nVrt.vertexCharge, nVrt.vertexCov,
1486  nVrt.chi2PerTrk, nVrt.trkAtVrt, nVrt.chi2,
1487  istate, false);
1488  if(sc.isSuccess() && nVrt.chi2<Chi2min) {
1489  Chi2min = nVrt.chi2;
1490  saveVrt = nVrt;
1491  selectedTrk = trk;
1492  }
1493  }
1494 
1495  if(Chi2min<1.e9){
1496  saveVrt.selTrk.resize(1);
1497  saveVrt.selTrk[0] = detachedTrk[0];
1498  saveVrt.detachedTrack = selectedTrk;
1499  saveVrt.vertexMom = momAtVrt(saveVrt.trkAtVrt[0]); //redefine vertex momentum
1500  (*wrkVrtSet).push_back(saveVrt);
1501  }
1502  } // end if(!tFound)
1503 
1504  } // end else if( detachedTrk.size()==1 )
1505 
1506  }
1507 
1508  //
1509  // Iterate track removal until vertex get good Chi2
1510  //
1511  template <class Particle>
1512  double InDetVKalVxInJetTool::improveVertexChi2(std::vector<WrkVrt> *wrkVrtSet, int V, std::vector<const Particle*> & AllTrackList,
1513  Trk::IVKalState& istate,
1514  bool ifCovV0)
1515  const
1516  {
1517  WrkVrt vrt = (*wrkVrtSet)[V];
1518  int NTrk = vrt.selTrk.size();
1519  if( NTrk<2 ) return 0.;
1520 
1521  double Prob=TMath::Prob(vrt.chi2, 2*NTrk-3);
1522  //----Start track removal iterations
1523  while(Prob<0.01){
1524  NTrk = vrt.selTrk.size();
1525  if(NTrk==2) return Prob;
1526 
1527  int SelT = -1;
1528  double Chi2Max = 0.;
1529  for(int i = 0; i<NTrk; i++){
1530  double Chi2 = vrt.chi2PerTrk[i];
1531  if(Chi2>Chi2Max){
1532  Chi2Max = Chi2;
1533  SelT = i;
1534  }
1535  }
1536 
1537  if (SelT<0) return 0;
1538  vrt.detachedTrack=vrt.selTrk[SelT];
1539  vrt.selTrk.erase( vrt.selTrk.begin() + SelT ); //remove track
1540  StatusCode sc = refitVertex(wrkVrtSet, V, AllTrackList, istate, ifCovV0);
1541  if(sc.isFailure()) return 0.;
1542 
1543  Prob = TMath::Prob(vrt.chi2, 2*(NTrk-1)-3);
1544  }
1545  return Prob;
1546  }
1547 
1548 
1549  template <class Particle>
1550  StatusCode InDetVKalVxInJetTool::refitVertex(std::vector<WrkVrt> *wrkVrtSet,
1551  int selectedVertex,
1552  std::vector<const Particle*> & selectedTracks,
1553  Trk::IVKalState& istate,
1554  bool ifCovV0) const
1555  {
1556  WrkVrt vrt = (*wrkVrtSet)[selectedVertex];
1557  int nth = vrt.selTrk.size();
1558  if(nth<2) return StatusCode::SUCCESS;
1559 
1560  double vProb = refitVertex(vrt, selectedTracks, istate, ifCovV0);
1561  if(vProb<0) return StatusCode::FAILURE;
1562  else return StatusCode::SUCCESS;
1563  }
1564 
1565 
1566  template <class Particle>
1568  std::vector<const Particle*> & selectedTracks,
1569  Trk::IVKalState& istate,
1570  bool ifCovV0) const
1571  {
1572  int nth = Vrt.selTrk.size();
1573  if(nth<2) return -1.;
1574 
1575  std::vector<const Particle*> ListTracks(0);
1576  for(const auto& j : Vrt.selTrk) ListTracks.push_back( selectedTracks[j] );
1577  Vrt.Good = false;
1578  Vrt.chi2PerTrk.resize(nth);
1579  for(int i = 0; i < nth; i++) Vrt.chi2PerTrk[i]=100000.+i; //VK safety
1580 
1581  m_fitSvc->setApproximateVertex(Vrt.vertex[0], Vrt.vertex[1], Vrt.vertex[2], istate);
1582  StatusCode SC = VKalVrtFitBase(ListTracks, Vrt.vertex, Vrt.vertexMom,
1583  Vrt.vertexCharge, Vrt.vertexCov,
1584  Vrt.chi2PerTrk, Vrt.trkAtVrt, Vrt.chi2,
1585  istate, ifCovV0);
1586  if(SC.isSuccess()) Vrt.Good = true;
1587  else{
1588  Vrt.Good = false;
1589  return -1.;
1590  }
1591 
1592  if(Vrt.chi2PerTrk.size()==2) Vrt.chi2PerTrk[0] = Vrt.chi2PerTrk[1] = Vrt.chi2/2.;
1593  return TMath::Prob(Vrt.chi2, 2*nth-1);
1594  }
1595 
1596  bool InDetVKalVxInJetTool::isPart(std::deque<long int> test, std::deque<long int> base)
1597  {
1598  std::deque<long int>::iterator trk = test.begin();
1599  for(trk = test.begin(); trk!=test.end(); ++trk){
1600  if(std::find(base.begin(), base.end(), (*trk)) == base.end()) return false; //element not found => test is not part of base
1601  }
1602  return true;
1603  }
1604 
1605  double InDetVKalVxInJetTool::jetProjDist(Amg::Vector3D & SecVrt,const xAOD::Vertex &primVrt,const TLorentzVector &jetDir)
1606  {
1607  Amg::Vector3D vv = SecVrt-primVrt.position();
1608  return ( vv.x()*jetDir.X()+vv.y()*jetDir.Y()+vv.z()*jetDir.Z() )/ jetDir.P();
1609  }
1610 
1611 } //end namespace
1612 
1613 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
base
std::string base
Definition: hcg.cxx:78
InDet::InDetVKalVxInJetTool::WrkVrt::selTrk
std::deque< long int > selTrk
Definition: InDetVKalVxInJetTool.h:335
InDet::InDetVKalVxInJetTool::WrkVrt
Definition: InDetVKalVxInJetTool.h:334
xAOD::Vertex_v1::x
float x() const
Returns the x position.
xAOD::Vertex_v1::setPosition
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
InDet::InDetVKalVxInJetTool::WrkVrt::nCloseVrt
int nCloseVrt
Definition: InDetVKalVxInJetTool.h:343
InDet::workVectorArrxAOD::TrkFromV0
std::vector< const xAOD::TrackParticle * > TrkFromV0
Definition: InDetVKalVxInJetTool.h:96
InDetVKalVxInJetTool.h
xAOD::Vertex_v1::setFitQuality
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Definition: Vertex_v1.cxx:150
InDet::InDetVKalVxInJetTool::m_trackDetachCut
double m_trackDetachCut
Definition: InDetVKalVxInJetTool.h:218
InDet::InDetVKalVxInJetTool::Hists
Definition: InDetVKalVxInJetTool.h:124
InDet::InDetVKalVxInJetTool::m_fitSvc
Trk::TrkVKalVrtFitter * m_fitSvc
Definition: InDetVKalVxInJetTool.h:222
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
InDet::workVectorArrxAOD::InpTrk
std::vector< const xAOD::TrackParticle * > InpTrk
Definition: InDetVKalVxInJetTool.h:94
InDet::InDetVKalVxInJetTool::getHists
Hists & getHists() const
Definition: InDetVKalVxInJetTool.cxx:493
Trk::TrkVKalVrtFitter::setRobustness
virtual void setRobustness(int, IVKalState &istate) const override final
Definition: SetFitOptions.cxx:116
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
InDet::InDetVKalVxInJetTool::vrtRadiusError
static double vrtRadiusError(const Amg::Vector3D &secVrt, const std::vector< double > &vrtErr)
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:262
InDet::InDetVKalVxInJetTool::jetProjDist
static double jetProjDist(Amg::Vector3D &SecVrt, const xAOD::Vertex &primVrt, const TLorentzVector &JetDir)
Definition: BTagVrtSecMulti.cxx:1605
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
InDet
DUMMY Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
skel.it
it
Definition: skel.GENtoEVGEN.py:423
bin
Definition: BinsDiffFromStripMedian.h:43
InDet::InDetVKalVxInJetTool::m_sel2VrtSigCut
double m_sel2VrtSigCut
Definition: InDetVKalVxInJetTool.h:188
Trk::Perigee
ParametersT< 5, Charged, PerigeeSurface > Perigee
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:29
Trk::TrkVKalVrtFitter::VKalGetImpact
virtual double VKalGetImpact(const xAOD::TrackParticle *, const Amg::Vector3D &Vertex, const long int Charge, dvect &Impact, dvect &ImpactError, IVKalState &istate) const override final
Definition: VKalGetImpact.cxx:91
InDet::workVectorArrxAOD::FoundSecondTracks
std::vector< std::vector< const xAOD::TrackParticle * > > FoundSecondTracks
Definition: InDetVKalVxInJetTool.h:95
InDet::InDetVKalVxInJetTool::WrkVrt::trkAtVrt
std::vector< std::vector< double > > trkAtVrt
Definition: InDetVKalVxInJetTool.h:341
InDet::InDetVKalVxInJetTool::minVrtVrtDist
double minVrtVrtDist(std::vector< WrkVrt > *WrkVrtSet, int &V1, int &V2) const
Definition: BTagVrtSecMulti.cxx:1263
InDet::workVectorArrxAOD::tmpListTracks
std::vector< const xAOD::TrackParticle * > tmpListTracks
Definition: InDetVKalVxInJetTool.h:91
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
InDet::InDetVKalVxInJetTool::WrkVrt::Good
bool Good
Definition: InDetVKalVxInJetTool.h:334
TrigInDetValidation_Base.test
test
Definition: TrigInDetValidation_Base.py:144
InDet::InDetVKalVxInJetTool::massV0
static double massV0(std::vector< std::vector< double > > &trkAtVrt, double massP, double massPi)
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:292
InDet::InDetVKalVxInJetTool::m_useITkMaterialRejection
bool m_useITkMaterialRejection
Definition: InDetVKalVxInJetTool.h:233
InDet::InDetVKalVxInJetTool::WrkVrt::vertexMom
TLorentzVector vertexMom
Definition: InDetVKalVxInJetTool.h:337
xAOD::Vertex_v1::setCovariance
void setCovariance(const std::vector< float > &value)
Sets the covariance matrix as a simple vector of values.
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
InDet::InDetVKalVxInJetTool::m_multiWithPrimary
bool m_multiWithPrimary
Definition: InDetVKalVxInJetTool.h:212
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:52
InDet::InDetVKalVxInJetTool::WrkVrt::projectedVrt
double projectedVrt
Definition: InDetVKalVxInJetTool.h:345
TrkVKalVrtFitter.h
InDet::InDetVKalVxInJetTool::mergeAndRefitVertices
double mergeAndRefitVertices(std::vector< WrkVrt > *WrkVrtSet, int V1, int V2, WrkVrt &newvrt, std::vector< const Particle * > &AllTrackList, Trk::IVKalState &istate) const
Definition: BTagVrtSecMulti.cxx:1338
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
InDet::InDetVKalVxInJetTool::fillNVrtNTup
void fillNVrtNTup(std::vector< WrkVrt > &vrtSet, std::vector< std::vector< float > > &trkScore, const xAOD::Vertex &primVrt, const TLorentzVector &jetDir) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:550
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
InDet::workVectorArrxAOD::listJetTracks
std::vector< const xAOD::TrackParticle * > listJetTracks
Definition: InDetVKalVxInJetTool.h:90
InDet::InDetVKalVxInJetTool::WrkVrt::vertexCharge
long int vertexCharge
Definition: InDetVKalVxInJetTool.h:338
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
InDet::c_vrtBCMassLimit
const double c_vrtBCMassLimit
Definition: BTagVrtSec.cxx:66
InDet::InDetVKalVxInJetTool::m_trkSigCut
double m_trkSigCut
Definition: InDetVKalVxInJetTool.h:189
InDet::InDetVKalVxInJetTool::VKalVrtFitBase
StatusCode VKalVrtFitBase(const std::vector< const xAOD::TrackParticle * > &listPart, Amg::Vector3D &Vertex, TLorentzVector &Momentum, long int &Charge, std::vector< double > &ErrorMatrix, std::vector< double > &Chi2PerTrk, std::vector< std::vector< double > > &TrkAtVrt, double &Chi2, Trk::IVKalState &istate, bool ifCovV0) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:417
InDet::InDetVKalVxInJetTool::m_useTrackClassificator
bool m_useTrackClassificator
Definition: InDetVKalVxInJetTool.h:225
lumiFormat.i
int i
Definition: lumiFormat.py:92
InDet::InDetVKalVxInJetTool::m_vertexMergeCut
double m_vertexMergeCut
Definition: InDetVKalVxInJetTool.h:217
Trk::TrkVKalVrtFitter::setApproximateVertex
virtual void setApproximateVertex(double X, double Y, double Z, IVKalState &istate) const override final
Definition: SetFitOptions.cxx:108
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
InDet::InDetVKalVxInJetTool::totalMom
TLorentzVector totalMom(const std::vector< const Trk::Perigee * > &inpTrk) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:354
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
InDet::workVectorArrxAOD
Definition: InDetVKalVxInJetTool.h:89
AnalysisUtils::Sort::pT
void pT(COLL *coll)
sort by pT
Definition: AnalysisMisc.h:468
TRT_PAI_gasdata::SC
const float SC[NC]
Cross sections for Carbon.
Definition: TRT_PAI_gasdata.h:255
InDet::InDetVKalVxInJetTool::WrkVrt::vertex
Amg::Vector3D vertex
Definition: InDetVKalVxInJetTool.h:336
InDet::InDetVKalVxInJetTool::selGoodTrkParticle
int selGoodTrkParticle(const std::vector< const xAOD::TrackParticle * > &inpPart, const xAOD::Vertex &primVrt, const TLorentzVector &jetDir, std::vector< const xAOD::TrackParticle * > &selPart, float evtWgt=1.) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/CutTrk.cxx:103
xAOD::Vertex_v1::z
float z() const
Returns the z position.
InDet::InDetVKalVxInJetTool::removeDoubleEntries
void removeDoubleEntries(std::vector< const Trk * > &) const
Definition: InDetVKalVxInJetTool.h:550
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
DataVector< xAOD::TrackParticle_v1 >
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
InDet::InDetVKalVxInJetTool::disassembleVertex
void disassembleVertex(std::vector< WrkVrt > *WrkVrtSet, int iv, std::vector< const Particle * > AllTracks, Trk::IVKalState &istate) const
Definition: BTagVrtSecMulti.cxx:947
InDet::clique_visitor
Definition: InDetVKalVxInJetTool.h:559
InDet::InDetVKalVxInJetTool::m_ITkPixMaterialMap
std::unique_ptr< TH2D > m_ITkPixMaterialMap
Definition: InDetVKalVxInJetTool.h:236
InDet::InDetVKalVxInJetTool::getVrtSecMulti
std::vector< xAOD::Vertex * > getVrtSecMulti(workVectorArrxAOD *, const xAOD::Vertex &primVrt, const TLorentzVector &jetDir, std::vector< double > &results, compatibilityGraph_t &compatibilityGraph) const
Definition: BTagVrtSecMulti.cxx:41
InDet::InDetVKalVxInJetTool::VKalVrtFitFastBase
StatusCode VKalVrtFitFastBase(const std::vector< const xAOD::TrackParticle * > &listPart, Amg::Vector3D &Vertex, Trk::IVKalState &istate) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:408
InDet::InDetVKalVxInJetTool::m_massE
const double m_massE
Definition: InDetVKalVxInJetTool.h:240
min
#define min(a, b)
Definition: cfImp.cxx:40
InDet::InDetVKalVxInJetTool::m_coneForTag
double m_coneForTag
Definition: InDetVKalVxInJetTool.h:186
InDet::workVectorArrxAOD::listSecondTracks
std::vector< const xAOD::TrackParticle * > listSecondTracks
Definition: InDetVKalVxInJetTool.h:92
InDet::InDetVKalVxInJetTool::isPart
static bool isPart(std::deque< long int > test, std::deque< long int > base)
Definition: BTagVrtSecMulti.cxx:1596
InDet::InDetVKalVxInJetTool::m_rLayer2
double m_rLayer2
Definition: InDetVKalVxInJetTool.h:205
InDet::InDetVKalVxInJetTool::trackClassification
static void trackClassification(std::vector< WrkVrt > *wrkVrtSet, std::vector< std::deque< long int > > *trkInVrt)
Definition: BTagVrtSecMulti.cxx:1082
SG::AuxElement::makePrivateStore
void makePrivateStore()
Create a new (empty) private store for this object.
Definition: AuxElement.cxx:172
python.ami.results
def results
Definition: ami.py:386
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
InDet::InDetVKalVxInJetTool::refitVertex
StatusCode refitVertex(std::vector< WrkVrt > *WrkVrtSet, int selectedVertex, std::vector< const Particle * > &selectedTracks, Trk::IVKalState &istate, bool ifCovV0) const
Definition: BTagVrtSecMulti.cxx:1550
InDet::InDetVKalVxInJetTool::WrkVrt::vertexCov
std::vector< double > vertexCov
Definition: InDetVKalVxInJetTool.h:339
InDet::InDetVKalVxInJetTool::clean1TrVertexSet
static void clean1TrVertexSet(std::vector< WrkVrt > *WrkVrtSet)
Definition: BTagVrtSecMulti.cxx:1026
InDet::InDetVKalVxInJetTool::removeTrackFromVertex
void removeTrackFromVertex(std::vector< WrkVrt > *wrkVrtSet, std::vector< std::deque< long int > > *trkInVrt, long int &selectedTrack, long int &selectedVertex) const
Definition: BTagVrtSecMulti.cxx:1188
InDet::InDetVKalVxInJetTool::WrkVrt::chi2
double chi2
Definition: InDetVKalVxInJetTool.h:342
ReadCellNoiseFromCoolCompare.v2
v2
Definition: ReadCellNoiseFromCoolCompare.py:364
InDet::InDetVKalVxInJetTool::m_useVertexCleaningPix
bool m_useVertexCleaningPix
Definition: InDetVKalVxInJetTool.h:208
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
InDet::InDetVKalVxInJetTool::mergeAndRefitOverlapVertices
void mergeAndRefitOverlapVertices(std::vector< WrkVrt > *WrkVrtSet, int V1, int V2, std::vector< const Particle * > &AllTrackLis, Trk::IVKalState &istate) const
Definition: BTagVrtSecMulti.cxx:1387
InDet::InDetVKalVxInJetTool::MaxOfShared
static double MaxOfShared(std::vector< WrkVrt > *WrkVrtSet, std::vector< std::deque< long int > > *trkInVrt, long int &selectedTrack, long int &selectedVertex)
Definition: BTagVrtSecMulti.cxx:1100
InDet::InDetVKalVxInJetTool::m_multiWithOneTrkVrt
bool m_multiWithOneTrkVrt
Definition: InDetVKalVxInJetTool.h:215
h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
InDet::InDetVKalVxInJetTool::momAtVrt
TLorentzVector momAtVrt(const std::vector< double > &inpTrk) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:385
Trk::IVKalState
Definition: IVKalState.h:21
InDet::InDetVKalVxInJetTool::m_rLayer3
double m_rLayer3
Definition: InDetVKalVxInJetTool.h:206
InDet::InDetVKalVxInJetTool::m_eventInfoKey
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Definition: InDetVKalVxInJetTool.h:227
InDet::InDetVKalVxInJetTool::m_massLam
const double m_massLam
Definition: InDetVKalVxInJetTool.h:242
xAOD::Vertex_v1::y
float y() const
Returns the y position.
InDet::InDetVKalVxInJetTool::m_trackClassificator
ToolHandle< IInDetTrkInJetType > m_trackClassificator
Definition: InDetVKalVxInJetTool.h:226
InDet::InDetVKalVxInJetTool::improveVertexChi2
double improveVertexChi2(std::vector< WrkVrt > *WrkVrtSet, int V, std::vector< const Particle * > &AllTracks, Trk::IVKalState &istate, bool ifCovV0) const
Definition: BTagVrtSecMulti.cxx:1512
InDet::InDetVKalVxInJetTool::m_massPi
const double m_massPi
Definition: InDetVKalVxInJetTool.h:238
InDet::InDetVKalVxInJetTool::WrkVrt::chi2PerTrk
std::vector< double > chi2PerTrk
Definition: InDetVKalVxInJetTool.h:340
InDet::InDetVKalVxInJetTool::check2TrVertexInPixel
bool check2TrVertexInPixel(const Track *p1, const Track *p2, Amg::Vector3D &, std::vector< double > &) const
Definition: BTagVrtSec.cxx:921
InDet::workVectorArrxAOD::TracksForFit
std::vector< const xAOD::TrackParticle * > TracksForFit
Definition: InDetVKalVxInJetTool.h:93
calibdata.copy
bool copy
Definition: calibdata.py:27
InDet::InDetVKalVxInJetTool::WrkVrt::dCloseVrt
double dCloseVrt
Definition: InDetVKalVxInJetTool.h:344
xAOD::Vertex_v1::vxTrackAtVertex
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
Definition: Vertex_v1.cxx:181
InDet::InDetVKalVxInJetTool::m_fillHist
bool m_fillHist
Definition: InDetVKalVxInJetTool.h:196
InDet::InDetVKalVxInJetTool::compatibilityGraph_t
boost::adjacency_list< boost::listS, boost::vecS, boost::undirectedS > compatibilityGraph_t
Definition: InDetVKalVxInJetTool.h:331
PlotCalibFromCool.vv
vv
Definition: PlotCalibFromCool.py:716
InDet::InDetVKalVxInJetTool::m_useVertexCleaningFMP
bool m_useVertexCleaningFMP
Definition: InDetVKalVxInJetTool.h:209
AnalysisMisc.h
InDet::InDetVKalVxInJetTool::m_massP
const double m_massP
Definition: InDetVKalVxInJetTool.h:239
InDet::InDetVKalVxInJetTool::vrtVrtDist
double vrtVrtDist(const xAOD::Vertex &primVrt, const Amg::Vector3D &SecVrt, const std::vector< double > &VrtErr, double &Signif) const
Definition: InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx:126
InDet::InDetVKalVxInJetTool::m_massK0
const double m_massK0
Definition: InDetVKalVxInJetTool.h:241
InDet::InDetVKalVxInJetTool::nTrkCommon
static int nTrkCommon(std::vector< WrkVrt > *WrkVrtSet, int V1, int V2)
Definition: BTagVrtSecMulti.cxx:1238
Trk::TrkVKalVrtFitter::makeState
virtual std::unique_ptr< IVKalState > makeState(const EventContext &ctx) const override final
Definition: TrkVKalVrtFitter.cxx:118
InDet::InDetVKalVxInJetTool::check1TrVertexInPixel
bool check1TrVertexInPixel(const Track *p1, Amg::Vector3D &, std::vector< double > &) const
Definition: InDetVKalVxInJetTool.h:575
InDet::InDetVKalVxInJetTool::WrkVrt::detachedTrack
int detachedTrack
Definition: InDetVKalVxInJetTool.h:346
InDet::InDetVKalVxInJetTool::select2TrVrt
int select2TrVrt(std::vector< const Trk * > &SelectedTracks, std::vector< const Trk * > &TracksForFit, const xAOD::Vertex &primVrt, const TLorentzVector &JetDir, std::vector< double > &InpMass, int &nRefPVTrk, std::vector< const Trk * > &TrkFromV0, std::vector< const Trk * > &ListSecondTracks, compatibilityGraph_t &compatibilityGraph, float evtWgt=1) const
InDet::InDetVKalVxInJetTool::minVrtVrtDistNext
static double minVrtVrtDistNext(std::vector< WrkVrt > *WrkVrtSet, int &V1, int &V2)
Definition: BTagVrtSecMulti.cxx:1312