ATLAS Offline Software
PsiPlusPsiSingleVertex.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
5 // PsiPlusPsiSingleVertex.cxx, (c) ATLAS Detector software
15 #include "HepPDT/ParticleDataTable.hh"
17 #include <algorithm>
18 
19 namespace DerivationFramework {
21  typedef std::vector<VertexLink> VertexLinkVector;
23  typedef std::vector<TrackParticleLink> TrackParticleLinkVector;
24 
25  PsiPlusPsiSingleVertex::PsiPlusPsiSingleVertex(const std::string& type, const std::string& name, const IInterface* parent) : AthAlgTool(type,name,parent),
26  m_vertexPsi1ContainerKey(""),
27  m_vertexPsi2ContainerKey(""),
28  m_outputsKeys({"Psi1Vtx", "Psi2Vtx", "MainVtx"}),
29  m_VxPrimaryCandidateName("PrimaryVertices"),
30  m_trackContainerName("InDetTrackParticles"),
31  m_eventInfo_key("EventInfo"),
32  m_jpsi1MassLower(0.0),
33  m_jpsi1MassUpper(20000.0),
34  m_diTrack1MassLower(-1.0),
35  m_diTrack1MassUpper(-1.0),
36  m_psi1MassLower(0.0),
37  m_psi1MassUpper(25000.0),
38  m_jpsi2MassLower(0.0),
39  m_jpsi2MassUpper(20000.0),
40  m_diTrack2MassLower(-1.0),
41  m_diTrack2MassUpper(-1.0),
42  m_psi2MassLower(0.0),
43  m_psi2MassUpper(25000.0),
44  m_MassLower(0.0),
45  m_MassUpper(31000.0),
46  m_vtx1Daug_num(4),
47  m_vtx1Daug1MassHypo(-1),
48  m_vtx1Daug2MassHypo(-1),
49  m_vtx1Daug3MassHypo(-1),
50  m_vtx1Daug4MassHypo(-1),
51  m_vtx2Daug_num(4),
52  m_vtx2Daug1MassHypo(-1),
53  m_vtx2Daug2MassHypo(-1),
54  m_vtx2Daug3MassHypo(-1),
55  m_vtx2Daug4MassHypo(-1),
56  m_maxCandidates(0),
57  m_mass_jpsi1(-1),
58  m_mass_diTrk1(-1),
59  m_mass_psi1(-1),
60  m_mass_jpsi2(-1),
61  m_mass_diTrk2(-1),
62  m_mass_psi2(-1),
63  m_constrJpsi1(false),
64  m_constrDiTrk1(false),
65  m_constrPsi1(false),
66  m_constrJpsi2(false),
67  m_constrDiTrk2(false),
68  m_constrPsi2(false),
69  m_chi2cut(-1.0),
70  m_iVertexFitter("Trk::TrkVKalVrtFitter"),
71  m_pvRefitter("Analysis::PrimaryVertexRefitter", this),
72  m_V0Tools("Trk::V0Tools")
73  {
74  declareProperty("Psi1Vertices", m_vertexPsi1ContainerKey);
75  declareProperty("Psi2Vertices", m_vertexPsi2ContainerKey);
76  declareProperty("Psi1VtxHypoNames", m_vertexPsi1HypoNames);
77  declareProperty("Psi2VtxHypoNames", m_vertexPsi2HypoNames);
78  declareProperty("VxPrimaryCandidateName", m_VxPrimaryCandidateName);
79  declareProperty("TrackContainerName", m_trackContainerName);
80  declareProperty("RefPVContainerName", m_refPVContainerName = "RefittedPrimaryVertices");
81  declareProperty("Jpsi1MassLowerCut", m_jpsi1MassLower);
82  declareProperty("Jpsi1MassUpperCut", m_jpsi1MassUpper);
83  declareProperty("DiTrack1MassLower", m_diTrack1MassLower); // only effective when m_vtx1Daug_num=4
84  declareProperty("DiTrack1MassUpper", m_diTrack1MassUpper); // only effective when m_vtx1Daug_num=4
85  declareProperty("Psi1MassLowerCut", m_psi1MassLower);
86  declareProperty("Psi1MassUpperCut", m_psi1MassUpper);
87  declareProperty("Jpsi2MassLowerCut", m_jpsi2MassLower);
88  declareProperty("Jpsi2MassUpperCut", m_jpsi2MassUpper);
89  declareProperty("DiTrack2MassLower", m_diTrack2MassLower); // only effective when m_vtx2Daug_num=4
90  declareProperty("DiTrack2MassUpper", m_diTrack2MassUpper); // only effective when m_vtx2Daug_num=4
91  declareProperty("Psi2MassLowerCut", m_psi2MassLower);
92  declareProperty("Psi2MassUpperCut", m_psi2MassUpper);
93  declareProperty("MassLowerCut", m_MassLower);
94  declareProperty("MassUpperCut", m_MassUpper);
95  declareProperty("HypothesisName", m_hypoName = "TQ");
96  declareProperty("NumberOfPsi1Daughters", m_vtx1Daug_num);
97  declareProperty("Vtx1Daug1MassHypo", m_vtx1Daug1MassHypo);
98  declareProperty("Vtx1Daug2MassHypo", m_vtx1Daug2MassHypo);
99  declareProperty("Vtx1Daug3MassHypo", m_vtx1Daug3MassHypo);
100  declareProperty("Vtx1Daug4MassHypo", m_vtx1Daug4MassHypo);
101  declareProperty("NumberOfPsi2Daughters", m_vtx2Daug_num);
102  declareProperty("Vtx2Daug1MassHypo", m_vtx2Daug1MassHypo);
103  declareProperty("Vtx2Daug2MassHypo", m_vtx2Daug2MassHypo);
104  declareProperty("Vtx2Daug3MassHypo", m_vtx2Daug3MassHypo);
105  declareProperty("Vtx2Daug4MassHypo", m_vtx2Daug4MassHypo);
106  declareProperty("MaxCandidates", m_maxCandidates);
107  declareProperty("Jpsi1Mass", m_mass_jpsi1);
108  declareProperty("DiTrack1Mass", m_mass_diTrk1);
109  declareProperty("Psi1Mass", m_mass_psi1);
110  declareProperty("Jpsi2Mass", m_mass_jpsi2);
111  declareProperty("DiTrack2Mass", m_mass_diTrk2);
112  declareProperty("Psi2Mass", m_mass_psi2);
113  declareProperty("ApplyJpsi1MassConstraint", m_constrJpsi1);
114  declareProperty("ApplyDiTrk1MassConstraint", m_constrDiTrk1); // only effective when m_vtx1Daug_num=4
115  declareProperty("ApplyPsi1MassConstraint", m_constrPsi1);
116  declareProperty("ApplyJpsi2MassConstraint", m_constrJpsi2);
117  declareProperty("ApplyDiTrk2MassConstraint", m_constrDiTrk2); // only effective when m_vtx2Daug_num=4
118  declareProperty("ApplyPsi2MassConstraint", m_constrPsi2);
119  declareProperty("Chi2Cut", m_chi2cut);
120  declareProperty("RefitPV", m_refitPV = true);
121  declareProperty("MaxnPV", m_PV_max = 1000);
122  declareProperty("MinNTracksInPV", m_PV_minNTracks = 0);
123  declareProperty("DoVertexType", m_DoVertexType = 7);
124  declareProperty("TrkVertexFitterTool", m_iVertexFitter);
125  declareProperty("PVRefitter", m_pvRefitter);
126  declareProperty("V0Tools", m_V0Tools);
127  declareProperty("OutputVertexCollections", m_outputsKeys);
128  }
129 
131  // retrieving vertex Fitter
132  ATH_CHECK( m_iVertexFitter.retrieve() );
133 
134  // retrieve PV refitter
135  ATH_CHECK( m_pvRefitter.retrieve() );
136 
137  // retrieving the V0 tools
138  ATH_CHECK( m_V0Tools.retrieve() );
139 
140  ATH_CHECK( m_vertexPsi1ContainerKey.initialize() );
141  ATH_CHECK( m_vertexPsi2ContainerKey.initialize() );
142  ATH_CHECK( m_VxPrimaryCandidateName.initialize() );
144  ATH_CHECK( m_refPVContainerName.initialize() );
145  ATH_CHECK( m_outputsKeys.initialize() );
147 
148  ATH_CHECK( m_partPropSvc.retrieve() );
149  auto pdt = m_partPropSvc->PDT();
150 
151  // retrieve particle masses
152  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Generators/TruthUtils/TruthUtils/AtlasPID.h
157 
166 
167  return StatusCode::SUCCESS;
168  }
169 
171  if (m_vtx1Daug_num < 2 || m_vtx1Daug_num > 4 || m_vtx2Daug_num < 2 || m_vtx2Daug_num > 4) {
172  ATH_MSG_FATAL("Incorrect number of Psi daughters");
173  return StatusCode::FAILURE;
174  }
175 
176  constexpr int topoN = 3;
177  if(m_outputsKeys.size() != topoN) {
178  ATH_MSG_FATAL("Incorrect number of VtxContainers");
179  return StatusCode::FAILURE;
180  }
181  std::array<SG::WriteHandle<xAOD::VertexContainer>, topoN> VtxWriteHandles; int ikey(0);
183  VtxWriteHandles[ikey] = SG::WriteHandle<xAOD::VertexContainer>(key);
184  ATH_CHECK( VtxWriteHandles[ikey].record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
185  ikey++;
186  }
187 
188  //----------------------------------------------------
189  // retrieve primary vertices
190  //----------------------------------------------------
192  ATH_CHECK( pvContainer.isValid() );
193  if (pvContainer.cptr()->size()==0) {
194  ATH_MSG_WARNING("You have no primary vertices: " << pvContainer.cptr()->size());
195  return StatusCode::RECOVERABLE;
196  }
197 
198  // Get TrackParticle container (for setting links to the original tracks)
200  ATH_CHECK( trackContainer.isValid() );
201 
202  std::vector<const xAOD::TrackParticle*> tracksJpsi1;
203  std::vector<const xAOD::TrackParticle*> tracksDiTrk1;
204  std::vector<const xAOD::TrackParticle*> tracksPsi1;
205  std::vector<const xAOD::TrackParticle*> tracksJpsi2;
206  std::vector<const xAOD::TrackParticle*> tracksDiTrk2;
207  std::vector<const xAOD::TrackParticle*> tracksPsi2;
208  std::vector<const xAOD::TrackParticle*> inputTracks;
209  std::vector<double> massesPsi1;
210  massesPsi1.push_back(m_vtx1Daug1MassHypo);
211  massesPsi1.push_back(m_vtx1Daug2MassHypo);
212  if(m_vtx1Daug_num>=3) massesPsi1.push_back(m_vtx1Daug3MassHypo);
213  if(m_vtx1Daug_num==4) massesPsi1.push_back(m_vtx1Daug4MassHypo);
214  std::vector<double> massesPsi2;
215  massesPsi2.push_back(m_vtx2Daug1MassHypo);
216  massesPsi2.push_back(m_vtx2Daug2MassHypo);
217  if(m_vtx2Daug_num>=3) massesPsi2.push_back(m_vtx2Daug3MassHypo);
218  if(m_vtx2Daug_num==4) massesPsi2.push_back(m_vtx2Daug4MassHypo);
219  std::vector<double> massesInputTracks;
220  massesInputTracks.reserve(massesPsi1.size() + massesPsi2.size());
221  for(auto mass : massesPsi1) massesInputTracks.push_back(mass);
222  for(auto mass : massesPsi2) massesInputTracks.push_back(mass);
223 
224  // Get Psi1 container
226  ATH_CHECK( psi1Container.isValid() );
228  ATH_CHECK( psi2Container.isValid() );
229 
230  // Select the psi1 candidates before calling fit
231  std::vector<const xAOD::Vertex*> selectedPsi1Candidates;
232  for(auto vxcItr=psi1Container->cbegin(); vxcItr!=psi1Container->cend(); ++vxcItr) {
233  // Check the passed flag first
234  const xAOD::Vertex* vtx = *vxcItr;
235  bool passed = false;
236  for(size_t i=0; i<m_vertexPsi1HypoNames.size(); i++) {
238  if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
239  passed = true;
240  }
241  }
242  if(m_vertexPsi1HypoNames.size() && !passed) continue;
243 
244  // Check psi1 candidate invariant mass and skip if need be
245  if(m_vtx1Daug_num>2) {
246  double mass_psi1 = m_V0Tools->invariantMass(*vxcItr, massesPsi1);
247  if (mass_psi1 < m_psi1MassLower || mass_psi1 > m_psi1MassUpper) continue;
248  }
249 
250  TLorentzVector p4_mu1, p4_mu2;
251  p4_mu1.SetPtEtaPhiM( (*vxcItr)->trackParticle(0)->pt(),
252  (*vxcItr)->trackParticle(0)->eta(),
253  (*vxcItr)->trackParticle(0)->phi(), m_vtx1Daug1MassHypo);
254  p4_mu2.SetPtEtaPhiM( (*vxcItr)->trackParticle(1)->pt(),
255  (*vxcItr)->trackParticle(1)->eta(),
256  (*vxcItr)->trackParticle(1)->phi(), m_vtx1Daug2MassHypo);
257  double mass_jpsi1 = (p4_mu1 + p4_mu2).M();
258  if (mass_jpsi1 < m_jpsi1MassLower || mass_jpsi1 > m_jpsi1MassUpper) continue;
259 
261  TLorentzVector p4_trk1, p4_trk2;
262  p4_trk1.SetPtEtaPhiM( (*vxcItr)->trackParticle(2)->pt(),
263  (*vxcItr)->trackParticle(2)->eta(),
264  (*vxcItr)->trackParticle(2)->phi(), m_vtx1Daug3MassHypo);
265  p4_trk2.SetPtEtaPhiM( (*vxcItr)->trackParticle(3)->pt(),
266  (*vxcItr)->trackParticle(3)->eta(),
267  (*vxcItr)->trackParticle(3)->phi(), m_vtx1Daug4MassHypo);
268  double mass_diTrk1 = (p4_trk1 + p4_trk2).M();
269  if (mass_diTrk1 < m_diTrack1MassLower || mass_diTrk1 > m_diTrack1MassUpper) continue;
270  }
271 
272  selectedPsi1Candidates.push_back(*vxcItr);
273  }
274 
275  // Select the psi2 candidates before calling fit
276  std::vector<const xAOD::Vertex*> selectedPsi2Candidates;
277  for(auto vxcItr=psi2Container->cbegin(); vxcItr!=psi2Container->cend(); ++vxcItr) {
278  // Check the passed flag first
279  const xAOD::Vertex* vtx = *vxcItr;
280  bool passed = false;
281  for(size_t i=0; i<m_vertexPsi2HypoNames.size(); i++) {
283  if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
284  passed = true;
285  }
286  }
287  if(m_vertexPsi2HypoNames.size() && !passed) continue;
288 
289  // Check psi2 candidate invariant mass and skip if need be
290  if(m_vtx2Daug_num>2) {
291  double mass_psi2 = m_V0Tools->invariantMass(*vxcItr,massesPsi2);
292  if(mass_psi2 < m_psi2MassLower || mass_psi2 > m_psi2MassUpper) continue;
293  }
294 
295  TLorentzVector p4_mu1, p4_mu2;
296  p4_mu1.SetPtEtaPhiM( (*vxcItr)->trackParticle(0)->pt(),
297  (*vxcItr)->trackParticle(0)->eta(),
298  (*vxcItr)->trackParticle(0)->phi(), m_vtx2Daug1MassHypo);
299  p4_mu2.SetPtEtaPhiM( (*vxcItr)->trackParticle(1)->pt(),
300  (*vxcItr)->trackParticle(1)->eta(),
301  (*vxcItr)->trackParticle(1)->phi(), m_vtx2Daug2MassHypo);
302  double mass_jpsi2 = (p4_mu1 + p4_mu2).M();
303  if (mass_jpsi2 < m_jpsi2MassLower || mass_jpsi2 > m_jpsi2MassUpper) continue;
304 
306  TLorentzVector p4_trk1, p4_trk2;
307  p4_trk1.SetPtEtaPhiM( (*vxcItr)->trackParticle(2)->pt(),
308  (*vxcItr)->trackParticle(2)->eta(),
309  (*vxcItr)->trackParticle(2)->phi(), m_vtx2Daug3MassHypo);
310  p4_trk2.SetPtEtaPhiM( (*vxcItr)->trackParticle(3)->pt(),
311  (*vxcItr)->trackParticle(3)->eta(),
312  (*vxcItr)->trackParticle(3)->phi(), m_vtx2Daug4MassHypo);
313  double mass_diTrk2 = (p4_trk1 + p4_trk2).M();
314  if (mass_diTrk2 < m_diTrack2MassLower || mass_diTrk2 > m_diTrack2MassUpper) continue;
315  }
316  selectedPsi2Candidates.push_back(*vxcItr);
317  }
318 
319  std::vector<std::pair<const xAOD::Vertex*, const xAOD::Vertex*> > candidatePairs;
320  for(auto psi1Itr=selectedPsi1Candidates.cbegin(); psi1Itr!=selectedPsi1Candidates.cend(); ++psi1Itr) {
321  tracksPsi1.clear();
322  tracksPsi1.reserve((*psi1Itr)->nTrackParticles());
323  for(size_t i=0; i<(*psi1Itr)->nTrackParticles(); i++) tracksPsi1.push_back((*psi1Itr)->trackParticle(i));
324  for(auto psi2Itr=selectedPsi2Candidates.cbegin(); psi2Itr!=selectedPsi2Candidates.cend(); ++psi2Itr) {
325  bool skip = false;
326  for(size_t j=0; j<(*psi2Itr)->nTrackParticles(); j++) {
327  if(std::find(tracksPsi1.cbegin(), tracksPsi1.cend(), (*psi2Itr)->trackParticle(j)) != tracksPsi1.cend()) { skip = true; break; }
328  }
329  if(skip) continue;
331  for(size_t ic=0; ic<candidatePairs.size(); ic++) {
332  const xAOD::Vertex* psi1Vertex = candidatePairs[ic].first;
333  const xAOD::Vertex* psi2Vertex = candidatePairs[ic].second;
334  if((psi1Vertex == *psi1Itr && psi2Vertex == *psi2Itr) || (psi1Vertex == *psi2Itr && psi2Vertex == *psi1Itr)) { skip = true; break; }
335  }
336  }
337  if(skip) continue;
338  candidatePairs.push_back(std::pair<const xAOD::Vertex*, const xAOD::Vertex*>(*psi1Itr,*psi2Itr));
339  }
340  }
341 
342  std::sort( candidatePairs.begin(), candidatePairs.end(), [](std::pair<const xAOD::Vertex*, const xAOD::Vertex*> a, std::pair<const xAOD::Vertex*, const xAOD::Vertex*> b) { return a.first->chiSquared()/a.first->numberDoF()+a.second->chiSquared()/a.second->numberDoF() < b.first->chiSquared()/b.first->numberDoF()+b.second->chiSquared()/b.second->numberDoF(); } );
343  if(m_maxCandidates>0 && candidatePairs.size()>m_maxCandidates) {
344  candidatePairs.erase(candidatePairs.begin()+m_maxCandidates, candidatePairs.end());
345  }
346 
347  for(size_t ic=0; ic<candidatePairs.size(); ic++) {
348  const xAOD::Vertex* psi1Vertex = candidatePairs[ic].first;
349  const xAOD::Vertex* psi2Vertex = candidatePairs[ic].second;
350 
351  tracksPsi1.clear();
352  tracksPsi1.reserve(psi1Vertex->nTrackParticles());
353  for(size_t it=0; it<psi1Vertex->nTrackParticles(); it++) tracksPsi1.push_back(psi1Vertex->trackParticle(it));
354  if (tracksPsi1.size() != massesPsi1.size()) {
355  ATH_MSG_ERROR("Problems with Psi1 input: number of tracks or track mass inputs is not correct!");
356  }
357  tracksPsi2.clear();
358  tracksPsi2.reserve(psi2Vertex->nTrackParticles());
359  for(size_t it=0; it<psi2Vertex->nTrackParticles(); it++) tracksPsi2.push_back(psi2Vertex->trackParticle(it));
360  if (tracksPsi2.size() != massesPsi2.size()) {
361  ATH_MSG_ERROR("Problems with Psi2 input: number of tracks or track mass inputs is not correct!");
362  }
363 
364  tracksJpsi1.clear();
365  tracksJpsi1.push_back(psi1Vertex->trackParticle(0));
366  tracksJpsi1.push_back(psi1Vertex->trackParticle(1));
367  tracksDiTrk1.clear();
368  if(m_vtx1Daug_num==4) {
369  tracksDiTrk1.push_back(psi1Vertex->trackParticle(2));
370  tracksDiTrk1.push_back(psi1Vertex->trackParticle(3));
371  }
372  tracksJpsi2.clear();
373  tracksJpsi2.push_back(psi2Vertex->trackParticle(0));
374  tracksJpsi2.push_back(psi2Vertex->trackParticle(1));
375  tracksDiTrk2.clear();
376  if(m_vtx2Daug_num==4) {
377  tracksDiTrk2.push_back(psi2Vertex->trackParticle(2));
378  tracksDiTrk2.push_back(psi2Vertex->trackParticle(3));
379  }
380 
381  TLorentzVector p4_moth;
382  TLorentzVector tmp;
383  for(size_t it=0; it<psi1Vertex->nTrackParticles(); it++) {
384  tmp.SetPtEtaPhiM(psi1Vertex->trackParticle(it)->pt(),psi1Vertex->trackParticle(it)->eta(),psi1Vertex->trackParticle(it)->phi(),massesPsi1[it]);
385  p4_moth += tmp;
386  }
387  for(size_t it=0; it<psi2Vertex->nTrackParticles(); it++) {
388  tmp.SetPtEtaPhiM(psi2Vertex->trackParticle(it)->pt(),psi2Vertex->trackParticle(it)->eta(),psi2Vertex->trackParticle(it)->phi(),massesPsi2[it]);
389  p4_moth += tmp;
390  }
391  if (p4_moth.M() < m_MassLower || p4_moth.M() > m_MassUpper) continue;
392 
393  inputTracks.clear();
394  inputTracks.push_back(psi1Vertex->trackParticle(0));
395  inputTracks.push_back(psi1Vertex->trackParticle(1));
396  if(m_vtx1Daug_num>=3) inputTracks.push_back(psi1Vertex->trackParticle(2));
397  if(m_vtx1Daug_num==4) inputTracks.push_back(psi1Vertex->trackParticle(3));
398  inputTracks.push_back(psi2Vertex->trackParticle(0));
399  inputTracks.push_back(psi2Vertex->trackParticle(1));
400  if(m_vtx2Daug_num>=3) inputTracks.push_back(psi2Vertex->trackParticle(2));
401  if(m_vtx2Daug_num==4) inputTracks.push_back(psi2Vertex->trackParticle(3));
402 
403  // start the fit
404  std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
405  m_iVertexFitter->setMassInputParticles(massesInputTracks, *state);
406  if (m_constrJpsi1) {
407  m_iVertexFitter->setMassForConstraint(m_mass_jpsi1, std::array<int,2>{1,2}, *state);
408  }
409  if (m_constrPsi1 && m_vtx1Daug_num>=3) {
410  m_iVertexFitter->setMassForConstraint(m_mass_psi1, m_vtx1Daug_num==4 ? std::vector<int>{1,2,3,4} : std::vector<int>{1,2,3}, *state);
411  }
412  if (m_constrDiTrk1 && m_vtx1Daug_num==4) {
413  m_iVertexFitter->setMassForConstraint(m_mass_diTrk1, std::array<int,2>{3,4}, *state);
414  }
415  if (m_constrJpsi2) {
416  m_iVertexFitter->setMassForConstraint(m_mass_jpsi2, std::array<int,2>{m_vtx1Daug_num+1,m_vtx1Daug_num+2}, *state);
417  }
418  if (m_constrPsi2 && m_vtx2Daug_num>=3) {
419  m_iVertexFitter->setMassForConstraint(m_mass_psi2, m_vtx1Daug_num==4 ? std::vector<int>{m_vtx1Daug_num+1,m_vtx1Daug_num+2,m_vtx1Daug_num+3,m_vtx1Daug_num+4} : std::vector<int>{m_vtx1Daug_num+1,m_vtx1Daug_num+2,m_vtx1Daug_num+3}, *state);
420  }
421  if (m_constrDiTrk2 && m_vtx2Daug_num==4) {
422  m_iVertexFitter->setMassForConstraint(m_mass_diTrk2, std::array<int,2>{m_vtx1Daug_num+3,m_vtx1Daug_num+4}, *state);
423  }
424 
425  // Starting point
426  Amg::Vector3D startingPoint((psi1Vertex->x()+psi2Vertex->x())/2,(psi1Vertex->y()+psi2Vertex->y())/2,(psi1Vertex->z()+psi2Vertex->z())/2);
427 
428  // do the fit
429  std::unique_ptr<xAOD::Vertex> theResult( m_iVertexFitter->fit(inputTracks, startingPoint, *state) );
430 
431  if(theResult != nullptr){
432  // Chi2/DOF cut
433  double chi2DOF = theResult->chiSquared()/theResult->numberDoF();
434  bool chi2CutPassed = (m_chi2cut <= 0.0 || chi2DOF < m_chi2cut);
435  if(chi2CutPassed) {
436  TrackParticleLinkVector tpLinkVector;
437  for(size_t i=0; i<theResult->trackParticleLinks().size(); i++) {
438  TrackParticleLink mylink = theResult->trackParticleLinks()[i];
439  mylink.setStorableObject(*trackContainer.ptr(), true);
440  tpLinkVector.push_back( mylink );
441  }
442  theResult->clearTracks();
443  theResult->setTrackParticleLinks( tpLinkVector );
444 
445  xAOD::Vertex* psi1Vertex_ = new xAOD::Vertex(*psi1Vertex);
446  xAOD::BPhysHelper psi1_helper(psi1Vertex_);
447  psi1_helper.setRefTrks();
448  TrackParticleLinkVector tpLinkVector_psi1;
449  for(size_t i=0; i<psi1Vertex_->trackParticleLinks().size(); i++) {
450  TrackParticleLink mylink = psi1Vertex_->trackParticleLinks()[i];
451  mylink.setStorableObject(*trackContainer.ptr(), true);
452  tpLinkVector_psi1.push_back( mylink );
453  }
454  psi1Vertex_->clearTracks();
455  psi1Vertex_->setTrackParticleLinks( tpLinkVector_psi1 );
456 
457  xAOD::Vertex* psi2Vertex_ = new xAOD::Vertex(*psi2Vertex);
458  xAOD::BPhysHelper psi2_helper(psi2Vertex_);
459  psi2_helper.setRefTrks();
460  TrackParticleLinkVector tpLinkVector_psi2;
461  for(size_t i=0; i<psi2Vertex_->trackParticleLinks().size(); i++) {
462  TrackParticleLink mylink = psi2Vertex_->trackParticleLinks()[i];
463  mylink.setStorableObject(*trackContainer.ptr(), true);
464  tpLinkVector_psi2.push_back( mylink );
465  }
466  psi2Vertex_->clearTracks();
467  psi2Vertex_->setTrackParticleLinks( tpLinkVector_psi2 );
468 
469  VtxWriteHandles[0].ptr()->push_back(psi1Vertex_);
470  VtxWriteHandles[1].ptr()->push_back(psi2Vertex_);
471 
472  // Set links to preceding vertices
473  VertexLinkVector precedingVertexLinks;
474  VertexLink vertexLink1;
475  vertexLink1.setElement(psi1Vertex_);
476  vertexLink1.setStorableObject(*VtxWriteHandles[0].ptr());
477  if( vertexLink1.isValid() ) precedingVertexLinks.push_back( vertexLink1 );
478  VertexLink vertexLink2;
479  vertexLink2.setElement(psi2Vertex_);
480  vertexLink2.setStorableObject(*VtxWriteHandles[1].ptr());
481  if( vertexLink2.isValid() ) precedingVertexLinks.push_back( vertexLink2 );
482 
483  SG::AuxElement::Decorator<VertexLinkVector> PrecedingLinksDecor("PrecedingVertexLinks");
484  PrecedingLinksDecor(*theResult.get()) = precedingVertexLinks;
485 
486  xAOD::BPhysHypoHelper vtx(m_hypoName, theResult.get());
487  vtx.setRefTrks();
488  vtx.setPass(true);
489 
490  VtxWriteHandles[2].ptr()->push_back(theResult.release()); //ptr is released preventing deletion
491  }
492  }
493  } //Iterate over candidatePairs vertices
494 
496  ATH_CHECK( evt.isValid() );
497  BPhysPVTools helper(&(*m_V0Tools), evt.cptr());
498  helper.SetMinNTracksInPV(m_PV_minNTracks);
499 
500  if(m_refitPV) {
502  ATH_CHECK( refPvContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
503 
504  if(VtxWriteHandles[2]->size()>0) {
505  for(int i=0; i<topoN; i++) {
506  StatusCode SC = helper.FillCandwithRefittedVertices(VtxWriteHandles[i].ptr(), pvContainer.cptr(), refPvContainer.ptr(), &(*m_pvRefitter), m_PV_max, m_DoVertexType);
507  if(SC.isFailure()){
508  ATH_MSG_FATAL("FillCandwithRefittedVertices failed - check the vertices you passed");
509  return SC;
510  }
511  }
512  }
513  }
514  else {
515  if(VtxWriteHandles[2]->size()>0) {
516  for(int i=0; i<topoN; i++) {
517  StatusCode SC = helper.FillCandExistingVertices(VtxWriteHandles[i].ptr(), pvContainer.cptr(), m_DoVertexType);
518  if(SC.isFailure()){
519  ATH_MSG_FATAL("FillCandExistingVertices failed - check the vertices you passed");
520  return SC;
521  }
522  }
523  }
524  }
525 
526  return StatusCode::SUCCESS;
527  }
528 }
BPhysPVTools.h
DerivationFramework::PsiPlusPsiSingleVertex::m_DoVertexType
int m_DoVertexType
Definition: PsiPlusPsiSingleVertex.h:94
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
xAOD::Vertex_v1::x
float x() const
Returns the x position.
V0Tools.h
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
DerivationFramework::PsiPlusPsiSingleVertex::m_PV_max
int m_PV_max
Definition: PsiPlusPsiSingleVertex.h:93
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
xAOD::BPhysHelper
Definition: BPhysHelper.h:71
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx1Daug2MassHypo
double m_vtx1Daug2MassHypo
Definition: PsiPlusPsiSingleVertex.h:61
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition: Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
TrigCompositeUtils::passed
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
Definition: TrigCompositeUtilsRoot.cxx:117
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
DerivationFramework::PsiPlusPsiSingleVertex::m_maxCandidates
unsigned int m_maxCandidates
Definition: PsiPlusPsiSingleVertex.h:69
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx2Daug3MassHypo
double m_vtx2Daug3MassHypo
Definition: PsiPlusPsiSingleVertex.h:67
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
DerivationFramework::PsiPlusPsiSingleVertex::m_partPropSvc
ServiceHandle< IPartPropSvc > m_partPropSvc
Definition: PsiPlusPsiSingleVertex.h:88
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
DerivationFramework::PsiPlusPsiSingleVertex::m_vertexPsi2HypoNames
std::vector< std::string > m_vertexPsi2HypoNames
Definition: PsiPlusPsiSingleVertex.h:39
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
DerivationFramework::PsiPlusPsiSingleVertex::m_constrDiTrk2
bool m_constrDiTrk2
Definition: PsiPlusPsiSingleVertex.h:81
DerivationFramework::PsiPlusPsiSingleVertex::m_constrDiTrk1
bool m_constrDiTrk1
Definition: PsiPlusPsiSingleVertex.h:78
xAOD::TrackParticle_v1::eta
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
Definition: TrackParticle_v1.cxx:77
DerivationFramework::BPhysPVCascadeTools::getParticleMass
static double getParticleMass(const HepPDT::ParticleDataTable *pdt, int pdg)
Definition: BPhysPVCascadeTools.cxx:491
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_psi2
double m_mass_psi2
Definition: PsiPlusPsiSingleVertex.h:76
xAOD::Vertex_v1::trackParticleLinks
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
DerivationFramework::PsiPlusPsiSingleVertex::m_psi1MassUpper
double m_psi1MassUpper
Definition: PsiPlusPsiSingleVertex.h:50
skel.it
it
Definition: skel.GENtoEVGEN.py:396
DerivationFramework::TrackParticleLinkVector
std::vector< TrackParticleLink > TrackParticleLinkVector
Definition: PsiPlusPsiSingleVertex.cxx:23
DerivationFramework::BPhysPVTools
Definition: BPhysPVTools.h:25
DerivationFramework::PsiPlusPsiSingleVertex::m_refitPV
bool m_refitPV
Definition: PsiPlusPsiSingleVertex.h:90
DataVector::cend
const_iterator cend() const noexcept
Return a const_iterator pointing past the end of the collection.
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx1Daug_num
int m_vtx1Daug_num
Definition: PsiPlusPsiSingleVertex.h:59
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_psi1
double m_mass_psi1
Definition: PsiPlusPsiSingleVertex.h:73
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx1Daug4MassHypo
double m_vtx1Daug4MassHypo
Definition: PsiPlusPsiSingleVertex.h:63
DerivationFramework::PsiPlusPsiSingleVertex::m_psi2MassUpper
double m_psi2MassUpper
Definition: PsiPlusPsiSingleVertex.h:56
TrkVKalVrtFitter.h
DerivationFramework::PsiPlusPsiSingleVertex::m_chi2cut
double m_chi2cut
Definition: PsiPlusPsiSingleVertex.h:83
runBeamSpotCalibration.helper
helper
Definition: runBeamSpotCalibration.py:112
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
PsiPlusPsiSingleVertex.h
xAOD::BPhysHypoHelper
Definition: BPhysHypoHelper.h:73
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_diTrk2
double m_mass_diTrk2
Definition: PsiPlusPsiSingleVertex.h:75
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
SG::WriteHandleKey
Property holding a SG store/key/clid from which a WriteHandle is made.
Definition: StoreGate/StoreGate/WriteHandleKey.h:40
DerivationFramework::PsiPlusPsiSingleVertex::m_constrJpsi1
bool m_constrJpsi1
Definition: PsiPlusPsiSingleVertex.h:77
DerivationFramework::PsiPlusPsiSingleVertex::m_vertexPsi1ContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexPsi1ContainerKey
Definition: PsiPlusPsiSingleVertex.h:36
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:59
python.TrigInDetConfig.inputTracks
inputTracks
Definition: TrigInDetConfig.py:183
lumiFormat.i
int i
Definition: lumiFormat.py:85
xAOD::BPhysHypoHelper::setPass
bool setPass(bool passVal)
get the pass flag for this hypothesis
Definition: BPhysHypoHelper.cxx:364
DerivationFramework::PsiPlusPsiSingleVertex::m_eventInfo_key
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo_key
Definition: PsiPlusPsiSingleVertex.h:43
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_diTrk1
double m_mass_diTrk1
Definition: PsiPlusPsiSingleVertex.h:72
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_jpsi1
double m_mass_jpsi1
Definition: PsiPlusPsiSingleVertex.h:71
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SG::WriteHandle::ptr
pointer_type ptr()
Dereference the pointer.
BPhysHypoHelper.h
: B-physcis xAOD helpers.
DerivationFramework::PsiPlusPsiSingleVertex::m_MassLower
double m_MassLower
Definition: PsiPlusPsiSingleVertex.h:57
DerivationFramework::PsiPlusPsiSingleVertex::m_trackContainerName
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackContainerName
Definition: PsiPlusPsiSingleVertex.h:42
DerivationFramework::PsiPlusPsiSingleVertex::m_mass_jpsi2
double m_mass_jpsi2
Definition: PsiPlusPsiSingleVertex.h:74
xAOD::Vertex_v1::setTrackParticleLinks
void setTrackParticleLinks(const TrackParticleLinks_t &trackParticles)
Set all track particle links at once.
DerivationFramework::PsiPlusPsiSingleVertex::m_diTrack2MassLower
double m_diTrack2MassLower
Definition: PsiPlusPsiSingleVertex.h:53
DerivationFramework::PsiPlusPsiSingleVertex::m_diTrack2MassUpper
double m_diTrack2MassUpper
Definition: PsiPlusPsiSingleVertex.h:54
test_pyathena.parent
parent
Definition: test_pyathena.py:15
DerivationFramework::PsiPlusPsiSingleVertex::m_pvRefitter
ToolHandle< Analysis::PrimaryVertexRefitter > m_pvRefitter
Definition: PsiPlusPsiSingleVertex.h:86
DerivationFramework::PsiPlusPsiSingleVertex::addBranches
virtual StatusCode addBranches() const override
Pass the thinning service
Definition: PsiPlusPsiSingleVertex.cxx:170
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
TRT_PAI_gasdata::SC
const float SC[NC]
Cross sections for Carbon.
Definition: TRT_PAI_gasdata.h:255
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
xAOD::Vertex_v1::clearTracks
void clearTracks()
Remove all tracks from the vertex.
Definition: Vertex_v1.cxx:331
DerivationFramework::PsiPlusPsiSingleVertex::m_PV_minNTracks
size_t m_PV_minNTracks
Definition: PsiPlusPsiSingleVertex.h:95
xAOD::Vertex_v1::z
float z() const
Returns the z position.
DerivationFramework
THE reconstruction tool.
Definition: ParticleSortingAlg.h:24
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
DerivationFramework::PsiPlusPsiSingleVertex::m_hypoName
std::string m_hypoName
Definition: PsiPlusPsiSingleVertex.h:92
DerivationFramework::VertexLink
ElementLink< xAOD::VertexContainer > VertexLink
Definition: Cascade3Plus1.cxx:23
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
BPhysPVCascadeTools.h
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
grepfile.ic
int ic
Definition: grepfile.py:33
DerivationFramework::PsiPlusPsiSingleVertex::m_MassUpper
double m_MassUpper
Definition: PsiPlusPsiSingleVertex.h:58
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
DerivationFramework::PsiPlusPsiSingleVertex::m_outputsKeys
SG::WriteHandleKeyArray< xAOD::VertexContainer > m_outputsKeys
Definition: PsiPlusPsiSingleVertex.h:40
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx1Daug3MassHypo
double m_vtx1Daug3MassHypo
Definition: PsiPlusPsiSingleVertex.h:62
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx2Daug_num
int m_vtx2Daug_num
Definition: PsiPlusPsiSingleVertex.h:64
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
DerivationFramework::PsiPlusPsiSingleVertex::PsiPlusPsiSingleVertex
PsiPlusPsiSingleVertex(const std::string &t, const std::string &n, const IInterface *p)
Definition: PsiPlusPsiSingleVertex.cxx:25
DerivationFramework::PsiPlusPsiSingleVertex::m_jpsi1MassUpper
double m_jpsi1MassUpper
Definition: PsiPlusPsiSingleVertex.h:46
DerivationFramework::PsiPlusPsiSingleVertex::m_V0Tools
ToolHandle< Trk::V0Tools > m_V0Tools
Definition: PsiPlusPsiSingleVertex.h:87
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
IVertexFitter.h
DerivationFramework::PsiPlusPsiSingleVertex::m_constrPsi2
bool m_constrPsi2
Definition: PsiPlusPsiSingleVertex.h:82
DerivationFramework::PsiPlusPsiSingleVertex::m_VxPrimaryCandidateName
SG::ReadHandleKey< xAOD::VertexContainer > m_VxPrimaryCandidateName
Name of primary vertex container.
Definition: PsiPlusPsiSingleVertex.h:41
DerivationFramework::PsiPlusPsiSingleVertex::m_diTrack1MassLower
double m_diTrack1MassLower
Definition: PsiPlusPsiSingleVertex.h:47
SG::ReadHandle::ptr
const_pointer_type ptr()
Dereference the pointer.
xAOD::Vertex_v1::numberDoF
float numberDoF() const
Returns the number of degrees of freedom of the vertex fit as float.
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
xAOD::BPhysHelper::setRefTrks
bool setRefTrks(std::vector< float > px, std::vector< float > py, std::vector< float > pz)
Sets refitted track momenta.
Definition: BPhysHelper.cxx:286
DerivationFramework::PsiPlusPsiSingleVertex::initialize
virtual StatusCode initialize() override
Definition: PsiPlusPsiSingleVertex.cxx:130
DerivationFramework::VertexLinkVector
std::vector< VertexLink > VertexLinkVector
Definition: Cascade3Plus1.cxx:24
DerivationFramework::PsiPlusPsiSingleVertex::m_vertexPsi2ContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexPsi2ContainerKey
Definition: PsiPlusPsiSingleVertex.h:37
a
TList * a
Definition: liststreamerinfos.cxx:10
xAOD::Vertex_v1::chiSquared
float chiSquared() const
Returns the of the vertex fit as float.
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
DerivationFramework::PsiPlusPsiSingleVertex::m_refPVContainerName
SG::WriteHandleKey< xAOD::VertexContainer > m_refPVContainerName
Definition: PsiPlusPsiSingleVertex.h:91
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::PsiPlusPsiSingleVertex::m_vertexPsi1HypoNames
std::vector< std::string > m_vertexPsi1HypoNames
Definition: PsiPlusPsiSingleVertex.h:38
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DerivationFramework::PsiPlusPsiSingleVertex::m_diTrack1MassUpper
double m_diTrack1MassUpper
Definition: PsiPlusPsiSingleVertex.h:48
DerivationFramework::PsiPlusPsiSingleVertex::m_constrJpsi2
bool m_constrJpsi2
Definition: PsiPlusPsiSingleVertex.h:80
xAOD::Vertex_v1::y
float y() const
Returns the y position.
DerivationFramework::PsiPlusPsiSingleVertex::m_jpsi2MassUpper
double m_jpsi2MassUpper
Definition: PsiPlusPsiSingleVertex.h:52
DerivationFramework::PsiPlusPsiSingleVertex::m_iVertexFitter
ToolHandle< Trk::TrkVKalVrtFitter > m_iVertexFitter
Definition: PsiPlusPsiSingleVertex.h:85
DerivationFramework::TrackParticleLink
ElementLink< xAOD::TrackParticleContainer > TrackParticleLink
Definition: PsiPlusPsiSingleVertex.cxx:22
SG::ConstAccessor< T, AuxAllocator_t< T > >::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx1Daug1MassHypo
double m_vtx1Daug1MassHypo
Definition: PsiPlusPsiSingleVertex.h:60
DataVector::cbegin
const_iterator cbegin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx2Daug4MassHypo
double m_vtx2Daug4MassHypo
Definition: PsiPlusPsiSingleVertex.h:68
skip
bool skip
Definition: TrigGlobEffCorrValidation.cxx:190
AthAlgTool
Definition: AthAlgTool.h:26
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx2Daug1MassHypo
double m_vtx2Daug1MassHypo
Definition: PsiPlusPsiSingleVertex.h:65
DerivationFramework::PsiPlusPsiSingleVertex::m_vtx2Daug2MassHypo
double m_vtx2Daug2MassHypo
Definition: PsiPlusPsiSingleVertex.h:66
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
HepMCHelpers.h
VertexAuxContainer.h
xAOD::TrackParticle_v1::phi
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .)
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DerivationFramework::PsiPlusPsiSingleVertex::m_constrPsi1
bool m_constrPsi1
Definition: PsiPlusPsiSingleVertex.h:79