ATLAS Offline Software
JpsiXPlusDisplaced.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  Contact: Xin Chen <xin.chen@cern.ch>
4 */
10 #include "GaudiKernel/IPartPropSvc.h"
16 #include "HepPDT/ParticleDataTable.hh"
17 #include "VxVertex/RecVertex.h"
19 #include <algorithm>
20 #include <functional>
21 
22 namespace DerivationFramework {
24  typedef std::vector<VertexLink> VertexLinkVector;
25 
26  JpsiXPlusDisplaced::JpsiXPlusDisplaced(const std::string& type, const std::string& name, const IInterface* parent) : AthAlgTool(type,name,parent),
27  m_vertexJXContainerKey("InputJXVertices"),
28  m_vertexV0ContainerKey("InputV0Vertices"),
29  m_vertexDisVContainerKey(""),
30  m_cascadeOutputKeys({"JpsiXPlusDisplacedVtx1_sub", "JpsiXPlusDisplacedVtx1", "JpsiXPlusDisplacedVtx2", "JpsiXPlusDisplacedVtx3"}),
31  m_refitV0(false),
32  m_v0VtxOutputKey(""),
33  m_disVtxOutputKey(""),
34  m_TrkParticleCollection("InDetTrackParticles"),
35  m_VxPrimaryCandidateName("PrimaryVertices"),
36  m_refPVContainerName("RefittedPrimaryVertices"),
37  m_eventInfo_key("EventInfo"),
38  m_beamSpotDecoKeys({"EventInfo.beamPosX","EventInfo.beamPosY","EventInfo.beamPosZ"}),
39  m_jxMassLower(0.0),
40  m_jxMassUpper(30000.0),
41  m_jpsiMassLower(0.0),
42  m_jpsiMassUpper(20000.0),
43  m_diTrackMassLower(-1.0),
44  m_diTrackMassUpper(-1.0),
45  m_V0Hypothesis("Lambda"),
46  m_V0MassLower(0.0),
47  m_V0MassUpper(20000.0),
48  m_lxyV0_cut(-999.0),
49  m_doV0Enum(false),
50  m_decorV0P(false),
51  m_minMass_gamma(-1.0),
52  m_chi2cut_gamma(-1.0),
53  m_DisplacedMassLower(0.0),
54  m_DisplacedMassUpper(30000.0),
55  m_lxyDisV_cut(-999.0),
56  m_MassLower(0.0),
57  m_MassUpper(41000.0),
58  m_jxDaug_num(4),
59  m_jxDaug1MassHypo(-1),
60  m_jxDaug2MassHypo(-1),
61  m_jxDaug3MassHypo(-1),
62  m_jxDaug4MassHypo(-1),
63  m_disVDaug_num(3),
64  m_disVDaug3MassHypo(-1),
65  m_extraTrkMassHypo(-1),
66  m_extraTrkMinPt(500),
67  m_massJX(-1),
68  m_massJpsi(-1),
69  m_massX(-1),
70  m_massDisV(-1),
71  m_massV0(-1),
72  m_massMainV(-1),
73  m_constrJX(false),
74  m_constrJpsi(false),
75  m_constrX(false),
76  m_constrDisV(false),
77  m_constrV0(false),
78  m_constrMainV(false),
79  m_JXSubVtx(true),
80  m_chi2cut_JX(-1.0),
81  m_chi2cut_V0(-1.0),
82  m_chi2cut_DisV(-1.0),
83  m_chi2cut(-1.0),
84  m_useTRT(false),
85  m_ptTRT(400),
86  m_d0_cut(2),
87  m_maxJXCandidates(0),
88  m_maxV0Candidates(0),
89  m_maxDisVCandidates(0),
90  m_maxMainVCandidates(0),
91  m_iVertexFitter("Trk::TrkVKalVrtFitter"),
92  m_iV0Fitter("Trk::V0VertexFitter"),
93  m_iGammaFitter("Trk::TrkVKalVrtFitter"),
94  m_pvRefitter("Analysis::PrimaryVertexRefitter", this),
95  m_V0Tools("Trk::V0Tools"),
96  m_trackToVertexTool("Reco::TrackToVertex"),
97  m_trkSelector("InDet::TrackSelectorTool"),
98  m_v0TrkSelector("InDet::TrackSelectorTool"),
99  m_CascadeTools("DerivationFramework::CascadeTools")
100  {
101  declareProperty("JXVertices", m_vertexJXContainerKey);
102  declareProperty("V0Vertices", m_vertexV0ContainerKey);
103  declareProperty("DisplacedVertices", m_vertexDisVContainerKey);
104  declareProperty("JXVtxHypoNames", m_vertexJXHypoNames);
105  declareProperty("V0VtxHypoNames", m_vertexV0HypoNames);
106  declareProperty("CascadeVertexCollections", m_cascadeOutputKeys); // size is 3 or 4 only
107  declareProperty("RefitV0", m_refitV0);
108  declareProperty("OutoutV0VtxCollection", m_v0VtxOutputKey);
109  declareProperty("OutoutDisVtxCollection", m_disVtxOutputKey);
110  declareProperty("TrackParticleCollection", m_TrkParticleCollection);
111  declareProperty("VxPrimaryCandidateName", m_VxPrimaryCandidateName);
112  declareProperty("RefPVContainerName", m_refPVContainerName);
113  declareProperty("JXMassLowerCut", m_jxMassLower); // only effective when m_jxDaug_num>2
114  declareProperty("JXMassUpperCut", m_jxMassUpper); // only effective when m_jxDaug_num>2
115  declareProperty("JpsiMassLowerCut", m_jpsiMassLower);
116  declareProperty("JpsiMassUpperCut", m_jpsiMassUpper);
117  declareProperty("DiTrackMassLower", m_diTrackMassLower); // only effective when m_jxDaug_num=4
118  declareProperty("DiTrackMassUpper", m_diTrackMassUpper); // only effective when m_jxDaug_num=4
119  declareProperty("V0Hypothesis", m_V0Hypothesis); // "Ks" or "Lambda"
120  declareProperty("V0MassLowerCut", m_V0MassLower);
121  declareProperty("V0MassUpperCut", m_V0MassUpper);
122  declareProperty("LxyV0Cut", m_lxyV0_cut);
123  declareProperty("DoV0Enumeration", m_doV0Enum);
124  declareProperty("DecorateV0Momentum", m_decorV0P); // only effective when m_refitV0=true and m_constrV0=true
125  declareProperty("MassCutGamma", m_minMass_gamma);
126  declareProperty("Chi2CutGamma", m_chi2cut_gamma);
127  declareProperty("DisplacedMassLowerCut", m_DisplacedMassLower); // only effective when m_disVDaug_num=3
128  declareProperty("DisplacedMassUpperCut", m_DisplacedMassUpper); // only effective when m_disVDaug_num=3
129  declareProperty("LxyDisVtxCut", m_lxyDisV_cut); // only effective when m_disVDaug_num=3
130  declareProperty("MassLowerCut", m_MassLower);
131  declareProperty("MassUpperCut", m_MassUpper);
132  declareProperty("HypothesisName", m_hypoName = "TQ");
133  declareProperty("NumberOfJXDaughters", m_jxDaug_num); // 2, or 3, or 4 only
134  declareProperty("JXDaug1MassHypo", m_jxDaug1MassHypo);
135  declareProperty("JXDaug2MassHypo", m_jxDaug2MassHypo);
136  declareProperty("JXDaug3MassHypo", m_jxDaug3MassHypo);
137  declareProperty("JXDaug4MassHypo", m_jxDaug4MassHypo);
138  declareProperty("NumberOfDisVDaughters", m_disVDaug_num); // 2 or 3 only
139  declareProperty("DisVDaug3MassHypo", m_disVDaug3MassHypo); // only effective when m_disVDaug_num=3
140  declareProperty("ExtraTrackMassHypo", m_extraTrkMassHypo); // for decays like B- -> J/psi Lambda pbar, the extra track is pbar (for m_disVDaug_num=2 only now)
141  declareProperty("ExtraTrackMinPt", m_extraTrkMinPt); // only effective if m_extraTrkMassHypo>0
142  declareProperty("JXMass", m_massJX); // only effective when m_jxDaug_num>2
143  declareProperty("JpsiMass", m_massJpsi);
144  declareProperty("XMass", m_massX); // only effective when m_jxDaug_num=4
145  declareProperty("DisVtxMass", m_massDisV); // only effective when m_disVDaug_num=3
146  declareProperty("V0Mass", m_massV0);
147  declareProperty("MainVtxMass", m_massMainV);
148  declareProperty("ApplyJXMassConstraint", m_constrJX);
149  declareProperty("ApplyJpsiMassConstraint", m_constrJpsi); // only effective when m_jxDaug_num>2
150  declareProperty("ApplyXMassConstraint", m_constrX); // only effective when m_jxDaug_num=4
151  declareProperty("ApplyDisVMassConstraint", m_constrDisV); // only effective when m_disVDaug_num=3
152  declareProperty("ApplyV0MassConstraint", m_constrV0);
153  declareProperty("ApplyMainVMassConstraint", m_constrMainV);
154  declareProperty("HasJXSubVertex", m_JXSubVtx);
155  declareProperty("Chi2CutJX", m_chi2cut_JX);
156  declareProperty("Chi2CutV0", m_chi2cut_V0);
157  declareProperty("Chi2CutDisV", m_chi2cut_DisV); // only effective when m_disVDaug_num=3
158  declareProperty("Chi2Cut", m_chi2cut);
159  declareProperty("UseTRT", m_useTRT); // only effective when m_disVDaug_num=3
160  declareProperty("PtTRT", m_ptTRT); // only effective when m_disVDaug_num=3
161  declareProperty("Trackd0Cut", m_d0_cut); // only effective when m_disVDaug_num=3
162  declareProperty("MaxJXCandidates", m_maxJXCandidates);
163  declareProperty("MaxV0Candidates", m_maxV0Candidates);
164  declareProperty("MaxDisVCandidates", m_maxDisVCandidates); // only effective when m_disVDaug_num=3
165  declareProperty("MaxMainVCandidates", m_maxMainVCandidates);
166  declareProperty("RefitPV", m_refitPV = true);
167  declareProperty("MaxnPV", m_PV_max = 1000);
168  declareProperty("MinNTracksInPV", m_PV_minNTracks = 0);
169  declareProperty("DoVertexType", m_DoVertexType = 7);
170  declareProperty("TrkVertexFitterTool", m_iVertexFitter);
171  declareProperty("V0VertexFitterTool", m_iV0Fitter);
172  declareProperty("GammaFitterTool", m_iGammaFitter);
173  declareProperty("PVRefitter", m_pvRefitter);
174  declareProperty("V0Tools", m_V0Tools);
175  declareProperty("TrackToVertexTool", m_trackToVertexTool);
176  declareProperty("TrackSelectorTool", m_trkSelector);
177  declareProperty("V0TrackSelectorTool", m_v0TrkSelector);
178  declareProperty("CascadeTools", m_CascadeTools);
179  }
180 
182  if(m_V0Hypothesis != "Ks" && m_V0Hypothesis != "Lambda") {
183  ATH_MSG_FATAL("Incorrect V0 container hypothesis - not recognized");
184  return StatusCode::FAILURE;
185  }
186 
187  if(m_jxDaug_num<2 || m_jxDaug_num>4 || m_disVDaug_num<2 || m_disVDaug_num>3) {
188  ATH_MSG_FATAL("Incorrect number of JX or DisVtx daughters");
189  return StatusCode::FAILURE;
190  }
191 
192  if(m_disVDaug_num==3 && m_vertexDisVContainerKey.key() != "" && m_refitV0) {
193  ATH_MSG_FATAL("Can not retrieve an input displaced vertex container and ask for V0 refits at the same time");
194  return StatusCode::FAILURE;
195  }
196 
197  // retrieving vertex Fitter
198  ATH_CHECK( m_iVertexFitter.retrieve() );
199 
200  // retrieving V0 vertex Fitter
201  ATH_CHECK( m_iV0Fitter.retrieve() );
202 
203  // retrieving photon conversion vertex Fitter
204  ATH_CHECK( m_iGammaFitter.retrieve() );
205 
206  // retrieving primary vertex refitter
207  ATH_CHECK( m_pvRefitter.retrieve() );
208 
209  // retrieving the V0 tool
210  ATH_CHECK( m_V0Tools.retrieve() );
211 
212  // retrieving the TrackToVertex extrapolator tool
213  ATH_CHECK( m_trackToVertexTool.retrieve() );
214 
215  // retrieving the track selector tool
216  ATH_CHECK( m_trkSelector.retrieve() );
217 
218  // retrieving the V0 track selector tool
219  ATH_CHECK( m_v0TrkSelector.retrieve() );
220 
221  // retrieving the Cascade tools
222  ATH_CHECK( m_CascadeTools.retrieve() );
223 
224  ATH_CHECK( m_vertexJXContainerKey.initialize() );
225  ATH_CHECK( m_vertexV0ContainerKey.initialize() );
227  ATH_CHECK( m_VxPrimaryCandidateName.initialize() );
229  ATH_CHECK( m_refPVContainerName.initialize() );
230  ATH_CHECK( m_cascadeOutputKeys.initialize() );
232  ATH_CHECK( m_beamSpotDecoKeys.initialize() );
235 
236  IPartPropSvc* partPropSvc = nullptr;
237  ATH_CHECK( service("PartPropSvc", partPropSvc, true) );
238  auto pdt = partPropSvc->PDT();
239 
240  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Generators/TruthUtils/TruthUtils/AtlasPID.h
241  m_mass_e = BPhysPVCascadeTools::getParticleMass(pdt, MC::ELECTRON);
249 
250  // retrieve particle masses
256 
262 
263  return StatusCode::SUCCESS;
264  }
265 
266  StatusCode JpsiXPlusDisplaced::performSearch(std::vector<Trk::VxCascadeInfo*> *cascadeinfoContainer, xAOD::VertexContainer* V0OutputContainer, xAOD::VertexContainer* disVtxOutputContainer) const {
267  ATH_MSG_DEBUG( "JpsiXPlusDisplaced::performSearch" );
268  assert(cascadeinfoContainer!=nullptr);
269 
270  // Get TrackParticle container
272  ATH_CHECK( trackContainer.isValid() );
273 
274  // Get the PrimaryVertices container
275  const xAOD::Vertex* primaryVertex(nullptr);
277  ATH_CHECK( pvContainer.isValid() );
278  if (pvContainer.cptr()->size()==0) {
279  ATH_MSG_WARNING("You have no primary vertices: " << pvContainer.cptr()->size());
280  return StatusCode::RECOVERABLE;
281  }
282  else primaryVertex = (*pvContainer.cptr())[0];
283 
284  std::vector<double> massesJX;
285  massesJX.push_back(m_jxDaug1MassHypo);
286  massesJX.push_back(m_jxDaug2MassHypo);
287  if(m_jxDaug_num>=3) massesJX.push_back(m_jxDaug3MassHypo);
288  if(m_jxDaug_num==4) massesJX.push_back(m_jxDaug4MassHypo);
289  std::vector<double> massesV0_ppi;
290  massesV0_ppi.push_back(m_mass_proton);
291  massesV0_ppi.push_back(m_mass_pion);
292  std::vector<double> massesV0_pip;
293  massesV0_pip.push_back(m_mass_pion);
294  massesV0_pip.push_back(m_mass_proton);
295  std::vector<double> massesV0_pipi;
296  massesV0_pipi.push_back(m_mass_pion);
297  massesV0_pipi.push_back(m_mass_pion);
298 
299  // Get Jpsi+X container
301  ATH_CHECK( jxContainer.isValid() );
302 
303  // Get V0 container
305  ATH_CHECK( V0Container.isValid() );
306 
307  // Get disV container
308  SG::ReadHandle<xAOD::VertexContainer> disVtxInputContainer;
309  if(m_disVDaug_num==3 && m_vertexDisVContainerKey.key() != "") {
311  ATH_CHECK( disVtxInputContainer.isValid() );
312  }
313 
314  auto ctx = Gaudi::Hive::currentContext();
318  Amg::Vector3D beamspot = Amg::Vector3D(beamPosX(0), beamPosY(0), beamPosZ(0));
319 
320  // Select the 3rd track displaced from the beam spot center
321  std::vector<const xAOD::TrackParticle*> tracksDisplaced;
322  if(m_disVDaug_num==3 && m_vertexDisVContainerKey.key()=="") {
323  for(auto tpIt=trackContainer.cptr()->begin(); tpIt!=trackContainer.cptr()->end(); ++tpIt) {
324  const xAOD::TrackParticle* TP = (*tpIt);
325  // V0 track selection (https://gitlab.cern.ch/atlas/athena/-/blob/main/InnerDetector/InDetRecTools/InDetTrackSelectorTool/src/InDetConversionTrackSelectorTool.cxx)
326  if(m_v0TrkSelector->decision(*TP, primaryVertex)) {
327  uint8_t temp(0);
328  uint8_t nclus(0);
329  if(TP->summaryValue(temp, xAOD::numberOfPixelHits)) nclus += temp;
330  if(TP->summaryValue(temp, xAOD::numberOfSCTHits) ) nclus += temp;
331  if(!m_useTRT && nclus == 0) continue;
332 
333  bool trk_cut = false;
334  if(nclus != 0) trk_cut = true;
335  if(nclus == 0 && TP->pt()>=m_ptTRT) trk_cut = true;
336  if(!trk_cut) continue;
337 
338  // track is used if std::abs(d0/sig_d0) > d0_cut for PV
339  if(!d0Pass(TP,primaryVertex,beamspot)) continue;
340 
341  tracksDisplaced.push_back(TP);
342  }
343  }
344  }
345 
346  // Accessors of V0 with photon conversion info and no-mass-constraint track momenta
347  SG::AuxElement::Accessor<std::string> mAcc_type("Type_V0Vtx");
348  SG::AuxElement::Accessor<int> mAcc_gfit("gamma_fit");
349  SG::AuxElement::Accessor<float> mAcc_gmass("gamma_mass");
350  SG::AuxElement::Accessor<float> mAcc_gmasserr("gamma_massError");
351  SG::AuxElement::Accessor<float> mAcc_gchisq("gamma_chisq");
352  SG::AuxElement::Accessor<int> mAcc_gndof("gamma_ndof");
353  SG::AuxElement::Accessor<float> mAcc_gprob("gamma_probability");
354  SG::AuxElement::Accessor< std::vector<float> > trk_pxAcc("TrackPx_V0nc");
355  SG::AuxElement::Accessor< std::vector<float> > trk_pyAcc("TrackPy_V0nc");
356  SG::AuxElement::Accessor< std::vector<float> > trk_pzAcc("TrackPz_V0nc");
357  // Decorators of V0 vertices
358  SG::AuxElement::Decorator<std::string> mDec_type("Type_V0Vtx");
359  SG::AuxElement::Decorator<int> mDec_gfit("gamma_fit");
360  SG::AuxElement::Decorator<float> mDec_gmass("gamma_mass");
361  SG::AuxElement::Decorator<float> mDec_gmasserr("gamma_massError");
362  SG::AuxElement::Decorator<float> mDec_gchisq("gamma_chisq");
363  SG::AuxElement::Decorator<int> mDec_gndof("gamma_ndof");
364  SG::AuxElement::Decorator<float> mDec_gprob("gamma_probability");
365  SG::AuxElement::Decorator< std::vector<float> > trk_pxDeco("TrackPx_V0nc");
366  SG::AuxElement::Decorator< std::vector<float> > trk_pyDeco("TrackPy_V0nc");
367  SG::AuxElement::Decorator< std::vector<float> > trk_pzDeco("TrackPz_V0nc");
368 
369  std::vector<float> trk_px;
370  std::vector<float> trk_py;
371  std::vector<float> trk_pz;
372  std::vector<const xAOD::TrackParticle*> tracksV0;
373 
374  // Select the V0 candidates before calling cascade fit
375  std::vector<std::pair<const xAOD::Vertex*,V0Enum> > selectedV0Candidates_EXISTING;
376  std::vector<std::pair<xAOD::Vertex*,V0Enum> > selectedV0Candidates_CREATED;
377  for(auto vxcItr=V0Container.ptr()->begin(); vxcItr!=V0Container.ptr()->end(); ++vxcItr) {
378  const xAOD::Vertex* vtx = *vxcItr;
379  // Check the passed flags first
380  bool passed = false;
381  for(const std::string& name : m_vertexV0HypoNames) {
382  SG::AuxElement::Accessor<Char_t> flagAcc("passed_"+name);
383  if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
384  passed = true;
385  }
386  }
387  if(m_vertexV0HypoNames.size() && !passed) continue;
388 
389  V0Enum opt(UNKNOWN); double massV0(0);
390  if(m_doV0Enum) {
391  // determine V0 candidate track masses
392  double massSig_V0_Lambda1 = std::abs(m_V0Tools->invariantMass(vtx, massesV0_ppi)-m_mass_Lambda)/m_V0Tools->invariantMassError(vtx, massesV0_ppi);
393  double massSig_V0_Lambda2 = std::abs(m_V0Tools->invariantMass(vtx, massesV0_pip)-m_mass_Lambda)/m_V0Tools->invariantMassError(vtx, massesV0_pip);
394  double massSig_V0_Ks = std::abs(m_V0Tools->invariantMass(vtx, massesV0_pipi)-m_mass_Ks)/m_V0Tools->invariantMassError(vtx, massesV0_pipi);
395  if(massSig_V0_Lambda1<=massSig_V0_Lambda2 && massSig_V0_Lambda1<=massSig_V0_Ks) {
396  opt = LAMBDA;
397  massV0 = m_V0Tools->invariantMass(vtx, massesV0_ppi);
398  }
399  else if(massSig_V0_Lambda2<=massSig_V0_Lambda1 && massSig_V0_Lambda2<=massSig_V0_Ks) {
400  opt = LAMBDABAR;
401  massV0 = m_V0Tools->invariantMass(vtx, massesV0_pip);
402  }
403  else if(massSig_V0_Ks<=massSig_V0_Lambda1 && massSig_V0_Ks<=massSig_V0_Lambda2) {
404  opt = KS;
405  massV0 = m_V0Tools->invariantMass(vtx, massesV0_pipi);
406  }
407 
408  if(massV0<m_V0MassLower || massV0>m_V0MassUpper) continue;
409  }
410  else {
411  std::string type_V0Vtx;
412  if(mAcc_type.isAvailable(*vtx)) type_V0Vtx = mAcc_type(*vtx);
413  if(type_V0Vtx == "Lambda") opt = LAMBDA;
414  else if(type_V0Vtx == "Lambdabar") opt = LAMBDABAR;
415  else if(type_V0Vtx == "Ks") opt = KS;
416  else opt = UNKNOWN;
417  }
418 
419  if(opt==UNKNOWN) continue;
420  if((opt==LAMBDA || opt==LAMBDABAR) && m_V0Hypothesis != "Lambda") continue;
421  if(opt==KS && m_V0Hypothesis != "Ks") continue;
422 
423  tracksV0.clear();
424  for(size_t i=0; i<vtx->nTrackParticles(); i++) tracksV0.push_back(vtx->trackParticle(i));
425  Amg::Vector3D vtxPos = m_V0Tools->vtx(vtx);
426 
427  int gamma_fit = 0; int gamma_ndof = 0;
428  double gamma_chisq = 999999., gamma_prob = -1., gamma_mass = -1., gamma_massErr = -1.;
429  if(mAcc_gfit.isAvailable(*vtx)) {
430  gamma_fit = mAcc_gfit.isAvailable(*vtx) ? mAcc_gfit(*vtx) : 0;
431  gamma_mass = mAcc_gmass.isAvailable(*vtx) ? mAcc_gmass(*vtx) : -1;
432  gamma_massErr = mAcc_gmasserr.isAvailable(*vtx) ? mAcc_gmasserr(*vtx) : -1;
433  gamma_chisq = mAcc_gchisq.isAvailable(*vtx) ? mAcc_gchisq(*vtx) : 999999;
434  gamma_ndof = mAcc_gndof.isAvailable(*vtx) ? mAcc_gndof(*vtx) : 0;
435  gamma_prob = mAcc_gprob.isAvailable(*vtx) ? mAcc_gprob(*vtx) : -1;
436  }
437  else {
438  std::unique_ptr<xAOD::Vertex> gammaVtx = std::unique_ptr<xAOD::Vertex>( m_iGammaFitter->fit(tracksV0, vtxPos) );
439  if (gammaVtx) {
440  gamma_fit = 1;
441  gamma_mass = m_V0Tools->invariantMass(gammaVtx.get(),m_mass_e,m_mass_e);
442  gamma_massErr = m_V0Tools->invariantMassError(gammaVtx.get(),m_mass_e,m_mass_e);
443  gamma_chisq = m_V0Tools->chisq(gammaVtx.get());
444  gamma_ndof = m_V0Tools->ndof(gammaVtx.get());
445  gamma_prob = m_V0Tools->vertexProbability(gammaVtx.get());
446  }
447  }
448  if(gamma_fit==1 && gamma_mass<m_minMass_gamma && gamma_chisq/gamma_ndof<m_chi2cut_gamma) continue;
449 
450  // store track momenta at vertex before refit
451  trk_px.clear(); trk_py.clear(); trk_pz.clear();
452  for(size_t i=0; i<vtx->vxTrackAtVertex().size(); ++i) {
453  const Trk::TrackParameters* aPerigee = vtx->vxTrackAtVertex()[i].perigeeAtVertex();
454  if(aPerigee) {
455  trk_px.push_back( aPerigee->momentum()[Trk::px] );
456  trk_py.push_back( aPerigee->momentum()[Trk::py] );
457  trk_pz.push_back( aPerigee->momentum()[Trk::pz] );
458  }
459  }
460 
461  if(m_refitV0) {
462  std::unique_ptr<xAOD::Vertex> V0vtx;
463  if(m_constrV0) {
464  std::vector<double> massesV0;
465  if(opt == LAMBDA) massesV0 = massesV0_ppi;
466  else if(opt == LAMBDABAR) massesV0 = massesV0_pip;
467  else if(opt == KS) massesV0 = massesV0_pipi;
468  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/TrkVertexFitter/TrkV0Fitter/TrkV0Fitter/TrkV0VertexFitter.h
469  V0vtx = std::unique_ptr<xAOD::Vertex>( m_iV0Fitter->fit(tracksV0, massesV0, m_massV0, 0, vtxPos) );
470  }
471  else {
472  V0vtx = std::unique_ptr<xAOD::Vertex>( m_iV0Fitter->fit(tracksV0, vtxPos) );
473  }
474  if(V0vtx && V0vtx->chiSquared()>=0) {
475  double chi2DOF = V0vtx->chiSquared()/V0vtx->numberDoF();
476  if(m_chi2cut_V0>0 && chi2DOF>m_chi2cut_V0) continue;
477 
478  xAOD::BPhysHelper V0_helper(V0vtx.get());
479  V0_helper.setRefTrks(); // AOD only method
480 
481  V0vtx->clearTracks();
483  newLink1.setElement(tracksV0[0]);
484  newLink1.setStorableObject(*trackContainer.cptr());
486  newLink2.setElement(tracksV0[1]);
487  newLink2.setStorableObject(*trackContainer.cptr());
488  V0vtx->addTrackAtVertex(newLink1);
489  V0vtx->addTrackAtVertex(newLink2);
490 
491  mDec_gfit(*V0vtx.get()) = gamma_fit;
492  mDec_gmass(*V0vtx.get()) = gamma_mass;
493  mDec_gmasserr(*V0vtx.get()) = gamma_massErr;
494  mDec_gchisq(*V0vtx.get()) = gamma_chisq;
495  mDec_gndof(*V0vtx.get()) = gamma_ndof;
496  mDec_gprob(*V0vtx.get()) = gamma_prob;
497  if(opt==LAMBDA) mDec_type(*V0vtx.get()) = "Lambda";
498  else if(opt==LAMBDABAR) mDec_type(*V0vtx.get()) = "Lambdabar";
499  else if(opt==KS) mDec_type(*V0vtx.get()) = "Ks";
500  if(m_constrV0 && m_decorV0P) {
501  trk_pxDeco(*V0vtx.get()) = trk_px;
502  trk_pyDeco(*V0vtx.get()) = trk_py;
503  trk_pzDeco(*V0vtx.get()) = trk_pz;
504  }
505  selectedV0Candidates_CREATED.push_back(std::pair<xAOD::Vertex*,V0Enum>{V0vtx.release(),opt});
506  }
507  } // refitV0
508  else { // no refit of V0
509  double chi2DOF = vtx->chiSquared()/vtx->numberDoF();
510  if(m_chi2cut_V0>0 && chi2DOF>m_chi2cut_V0) continue;
511  mDec_gfit(*vtx) = gamma_fit;
512  mDec_gmass(*vtx) = gamma_mass;
513  mDec_gmasserr(*vtx) = gamma_massErr;
514  mDec_gchisq(*vtx) = gamma_chisq;
515  mDec_gndof(*vtx) = gamma_ndof;
516  mDec_gprob(*vtx) = gamma_prob;
517  if(opt==LAMBDA) mDec_type(*vtx) = "Lambda";
518  else if(opt==LAMBDABAR) mDec_type(*vtx) = "Lambdabar";
519  else if(opt==KS) mDec_type(*vtx) = "Ks";
520  selectedV0Candidates_EXISTING.push_back(std::pair<const xAOD::Vertex*,V0Enum>{vtx,opt});
521  }
522  } // V0Container loop
523 
524  if(m_refitV0) {
525  if(selectedV0Candidates_CREATED.size()==0) return StatusCode::SUCCESS;
526  std::sort( selectedV0Candidates_CREATED.begin(), selectedV0Candidates_CREATED.end(), [](std::pair<xAOD::Vertex*,V0Enum> a, std::pair<xAOD::Vertex*,V0Enum> b) { return a.first->chiSquared()/a.first->numberDoF() < b.first->chiSquared()/b.first->numberDoF(); } );
527  if(m_maxV0Candidates>0 && selectedV0Candidates_CREATED.size()>m_maxV0Candidates) {
528  for(auto it=selectedV0Candidates_CREATED.begin()+m_maxV0Candidates; it!=selectedV0Candidates_CREATED.end(); it++) delete it->first;
529  selectedV0Candidates_CREATED.erase(selectedV0Candidates_CREATED.begin()+m_maxV0Candidates, selectedV0Candidates_CREATED.end());
530  }
531  }
532  else {
533  if(selectedV0Candidates_EXISTING.size()==0) return StatusCode::SUCCESS;
534  std::sort( selectedV0Candidates_EXISTING.begin(), selectedV0Candidates_EXISTING.end(), [](std::pair<const xAOD::Vertex*,V0Enum> a, std::pair<const xAOD::Vertex*,V0Enum> b) { return a.first->chiSquared()/a.first->numberDoF() < b.first->chiSquared()/b.first->numberDoF(); } );
535  if(m_maxV0Candidates>0 && selectedV0Candidates_EXISTING.size()>m_maxV0Candidates) {
536  selectedV0Candidates_EXISTING.erase(selectedV0Candidates_EXISTING.begin()+m_maxV0Candidates, selectedV0Candidates_EXISTING.end());
537  }
538  }
539 
540  if(selectedV0Candidates_CREATED.size() && V0OutputContainer) {
541  for(auto v0VItr=selectedV0Candidates_CREATED.begin(); v0VItr!=selectedV0Candidates_CREATED.end(); ++v0VItr) V0OutputContainer->push_back(v0VItr->first);
542  }
543 
544  // Make the displaced candidates if needed
545  std::vector<std::pair<const xAOD::Vertex*,size_t> > disVtxContainer_EXISTING;
546  std::vector<std::pair<xAOD::Vertex*,size_t> > disVtxContainer_CREATED;
547  if(m_disVDaug_num==3) {
548  if(m_vertexDisVContainerKey.key()=="") {
549  if(m_refitV0) {
550  for(size_t it=0; it<selectedV0Candidates_CREATED.size(); ++it) {
551  std::pair<xAOD::Vertex*,V0Enum> elem = selectedV0Candidates_CREATED[it];
552  for(auto trkItr=tracksDisplaced.cbegin(); trkItr!=tracksDisplaced.cend(); ++trkItr) {
553  xAOD::Vertex* disVtx = fitDisVtx(elem.first,elem.second,*trkItr,trackContainer.cptr());
554  if(disVtx) disVtxContainer_CREATED.push_back(std::pair<xAOD::Vertex*,size_t>{disVtx,it});
555  }
556  }
557  }
558  else {
559  for(size_t it=0; it<selectedV0Candidates_EXISTING.size(); ++it) {
560  std::pair<const xAOD::Vertex*,V0Enum> elem = selectedV0Candidates_EXISTING[it];
561  for(auto trkItr=tracksDisplaced.cbegin(); trkItr!=tracksDisplaced.cend(); ++trkItr) {
562  xAOD::Vertex* disVtx = fitDisVtx(elem.first,elem.second,*trkItr,trackContainer.cptr());
563  if(disVtx) disVtxContainer_CREATED.push_back(std::pair<xAOD::Vertex*,size_t>{disVtx,it});
564  }
565  }
566  }
567 
568  std::sort( disVtxContainer_CREATED.begin(), disVtxContainer_CREATED.end(), [](std::pair<xAOD::Vertex*,size_t> a, std::pair<xAOD::Vertex*,size_t> b) {
569  SG::AuxElement::Accessor<float> ChiSquared("ChiSquared_Cascade");
570  SG::AuxElement::Accessor<int> nDoF("nDoF_Cascade");
571  float chi2_a = ChiSquared.isAvailable(*a.first) ? ChiSquared(*a.first) : 999999;
572  int ndof_a = nDoF.isAvailable(*a.first) ? nDoF(*a.first) : 1;
573  float chi2_b = ChiSquared.isAvailable(*b.first) ? ChiSquared(*b.first) : 999999;
574  int ndof_b = nDoF.isAvailable(*b.first) ? nDoF(*b.first) : 1;
575  return chi2_a/ndof_a < chi2_b/ndof_b; } );
576  if(m_maxDisVCandidates>0 && disVtxContainer_CREATED.size()>m_maxDisVCandidates) {
577  for(auto it=disVtxContainer_CREATED.begin()+m_maxDisVCandidates; it!=disVtxContainer_CREATED.end(); it++) delete it->first;
578  disVtxContainer_CREATED.erase(disVtxContainer_CREATED.begin()+m_maxDisVCandidates, disVtxContainer_CREATED.end());
579  }
580  } // disVtxInputContainer==0
581  else { // disVtxInputContainer!=0
582  for(auto vxcItr=disVtxInputContainer.cptr()->begin(); vxcItr!=disVtxInputContainer.cptr()->end(); ++vxcItr) {
583  const xAOD::Vertex* vtx = *vxcItr;
584  SG::AuxElement::Accessor<VertexLink> cascadeVertexLinkAcc("CascadeVertexLink");
585  if(cascadeVertexLinkAcc.isAvailable(*vtx)) {
586  const VertexLink& cascadeVertexLink = cascadeVertexLinkAcc(*vtx);
587  if(cascadeVertexLink.isValid()) {
588  const xAOD::Vertex* V0Vtx = *cascadeVertexLink;
589  for(size_t it=0; it<selectedV0Candidates_EXISTING.size(); ++it) {
590  std::pair<const xAOD::Vertex*,V0Enum> elem = selectedV0Candidates_EXISTING[it];
591  if(BPhysPVCascadeTools::VerticesMatchTracks<2>(elem.first,V0Vtx)) {
592  disVtxContainer_EXISTING.push_back(std::pair<const xAOD::Vertex*,size_t>{vtx,it});
593  break;
594  }
595  }
596  }
597  }
598  }
599  if(disVtxInputContainer.cptr()->size() != disVtxContainer_EXISTING.size()) ATH_MSG_ERROR("Input and selected displaced vertex containers have different sizes");
600 
601  std::sort( disVtxContainer_EXISTING.begin(), disVtxContainer_EXISTING.end(), [](std::pair<const xAOD::Vertex*,size_t> a, std::pair<const xAOD::Vertex*,size_t> b) {
602  SG::AuxElement::Accessor<float> ChiSquared("ChiSquared_Cascade");
603  SG::AuxElement::Accessor<int> nDoF("nDoF_Cascade");
604  float chi2_a = ChiSquared.isAvailable(*a.first) ? ChiSquared(*a.first) : 999999;
605  int ndof_a = nDoF.isAvailable(*a.first) ? nDoF(*a.first) : 1;
606  float chi2_b = ChiSquared.isAvailable(*b.first) ? ChiSquared(*b.first) : 999999;
607  int ndof_b = nDoF.isAvailable(*b.first) ? nDoF(*b.first) : 1;
608  return chi2_a/ndof_a < chi2_b/ndof_b; } );
609  if(m_maxDisVCandidates>0 && disVtxContainer_EXISTING.size()>m_maxDisVCandidates) {
610  disVtxContainer_EXISTING.erase(disVtxContainer_EXISTING.begin()+m_maxDisVCandidates, disVtxContainer_EXISTING.end());
611  }
612  }
613 
614  if((m_vertexDisVContainerKey.key()=="" && disVtxContainer_CREATED.size()==0) || (m_vertexDisVContainerKey.key()!="" && disVtxContainer_EXISTING.size()==0)) {
615  if(!V0OutputContainer) {
616  for(auto it=selectedV0Candidates_CREATED.begin(); it!=selectedV0Candidates_CREATED.end(); it++) delete it->first;
617  }
618  return StatusCode::SUCCESS;
619  }
620 
621  if(disVtxContainer_CREATED.size() && disVtxOutputContainer) {
622  for(auto disVItr=disVtxContainer_CREATED.begin(); disVItr!=disVtxContainer_CREATED.end(); ++disVItr) {
623  disVtxOutputContainer->push_back(disVItr->first);
624 
625  SG::AuxElement::Decorator<VertexLink> cascadeVertexLinkDecor("CascadeVertexLink");
626  VertexLink vertexLink;
627  if(V0OutputContainer) {
628  vertexLink.setElement(V0OutputContainer->at(disVItr->second));
629  vertexLink.setStorableObject(*V0OutputContainer);
630  }
631  else if(!m_refitV0) {
632  const xAOD::Vertex* V0Vtx = FindVertex<2>(V0Container.ptr(), selectedV0Candidates_EXISTING[disVItr->second].first);
633  vertexLink.setElement(V0Vtx);
634  vertexLink.setStorableObject(*V0Container.ptr());
635  }
636  cascadeVertexLinkDecor(*disVItr->first) = vertexLink;
637  }
638  }
639  } // m_disVDaug_num==3
640 
641  // Select the JX candidates before calling cascade fit
642  std::vector<const xAOD::Vertex*> selectedJXCandidates;
643  for(auto vxcItr=jxContainer.ptr()->begin(); vxcItr!=jxContainer.ptr()->end(); ++vxcItr) {
644  // Check the passed flag first
645  const xAOD::Vertex* vtx = *vxcItr;
646  bool passed = false;
647  for(const std::string& name : m_vertexJXHypoNames) {
648  SG::AuxElement::Accessor<Char_t> flagAcc("passed_"+name);
649  if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
650  passed = true;
651  }
652  }
653  if(m_vertexJXHypoNames.size() && !passed) continue;
654 
655  // Check Psi candidate invariant mass and skip if need be
656  if(m_jxDaug_num>2) {
657  double mass_jx = m_V0Tools->invariantMass(*vxcItr,massesJX);
658  if(mass_jx < m_jxMassLower || mass_jx > m_jxMassUpper) continue;
659  }
660 
661  // Add loose cut on Jpsi mass from e.g. JX -> Jpsi pi+ pi-
662  TLorentzVector p4_mu1, p4_mu2;
663  p4_mu1.SetPtEtaPhiM( vtx->trackParticle(0)->pt(),
664  vtx->trackParticle(0)->eta(),
665  vtx->trackParticle(0)->phi(), m_jxDaug1MassHypo);
666  p4_mu2.SetPtEtaPhiM( vtx->trackParticle(1)->pt(),
667  vtx->trackParticle(1)->eta(),
668  vtx->trackParticle(1)->phi(), m_jxDaug2MassHypo);
669  double mass_jpsi = (p4_mu1 + p4_mu2).M();
670  if (mass_jpsi < m_jpsiMassLower || mass_jpsi > m_jpsiMassUpper) continue;
671 
673  TLorentzVector p4_trk1, p4_trk2;
674  p4_trk1.SetPtEtaPhiM( vtx->trackParticle(2)->pt(),
675  vtx->trackParticle(2)->eta(),
676  vtx->trackParticle(2)->phi(), m_jxDaug3MassHypo);
677  p4_trk2.SetPtEtaPhiM( vtx->trackParticle(3)->pt(),
678  vtx->trackParticle(3)->eta(),
679  vtx->trackParticle(3)->phi(), m_jxDaug4MassHypo);
680  double mass_diTrk = (p4_trk1 + p4_trk2).M();
681  if (mass_diTrk < m_diTrackMassLower || mass_diTrk > m_diTrackMassUpper) continue;
682  }
683 
684  double chi2DOF = vtx->chiSquared()/vtx->numberDoF();
685  if(m_chi2cut_JX>0 && chi2DOF>m_chi2cut_JX) continue;
686 
687  selectedJXCandidates.push_back(vtx);
688  }
689 
690  if(selectedJXCandidates.size()==0) {
691  if(!V0OutputContainer) {
692  for(auto it=selectedV0Candidates_CREATED.begin(); it!=selectedV0Candidates_CREATED.end(); it++) delete it->first;
693  }
694  if(!disVtxOutputContainer) {
695  for(auto it=disVtxContainer_CREATED.begin(); it!=disVtxContainer_CREATED.end(); it++) delete it->first;
696  }
697  return StatusCode::SUCCESS;
698  }
699 
700  std::sort( selectedJXCandidates.begin(), selectedJXCandidates.end(), [](const xAOD::Vertex* a, const xAOD::Vertex* b) { return a->chiSquared()/a->numberDoF() < b->chiSquared()/b->numberDoF(); } );
701  if(m_maxJXCandidates>0 && selectedJXCandidates.size()>m_maxJXCandidates) {
702  selectedJXCandidates.erase(selectedJXCandidates.begin()+m_maxJXCandidates, selectedJXCandidates.end());
703  }
704 
705  // Select JX+DisV candidates
706  // Iterate over JX vertices
707  for(auto jxItr=selectedJXCandidates.begin(); jxItr!=selectedJXCandidates.end(); ++jxItr) {
708  // Iterate over displaced vertices
709  if(m_disVDaug_num==2) {
710  if(m_refitV0) {
711  for(auto V0Itr=selectedV0Candidates_CREATED.begin(); V0Itr!=selectedV0Candidates_CREATED.end(); ++V0Itr) {
712  Trk::VxCascadeInfo* result = fitMainVtx(*jxItr, massesJX, V0Itr->first, V0Itr->second, trackContainer.cptr());
713  if(result) cascadeinfoContainer->push_back(result);
714  }
715  }
716  else {
717  for(auto V0Itr=selectedV0Candidates_EXISTING.begin(); V0Itr!=selectedV0Candidates_EXISTING.end(); ++V0Itr) {
718  Trk::VxCascadeInfo* result = fitMainVtx(*jxItr, massesJX, V0Itr->first, V0Itr->second, trackContainer.cptr());
719  if(result) cascadeinfoContainer->push_back(result);
720  }
721  }
722  }
723  else if(m_disVDaug_num==3) {
724  if(m_vertexDisVContainerKey.key()=="") {
725  for(auto disVItr=disVtxContainer_CREATED.begin(); disVItr!=disVtxContainer_CREATED.end(); ++disVItr) {
726  const xAOD::Vertex* disVtx = disVItr->first;
727  const xAOD::Vertex* V0Vtx(nullptr); V0Enum V0(UNKNOWN);
728  if(m_refitV0) {
729  V0Vtx = selectedV0Candidates_CREATED[disVItr->second].first;
730  V0 = selectedV0Candidates_CREATED[disVItr->second].second;
731  }
732  else {
733  V0Vtx = selectedV0Candidates_EXISTING[disVItr->second].first;
734  V0 = selectedV0Candidates_EXISTING[disVItr->second].second;
735  }
736  Trk::VxCascadeInfo* result = fitMainVtx(*jxItr, massesJX, disVtx, V0Vtx, V0, trackContainer.cptr());
737  if(result) cascadeinfoContainer->push_back(result);
738  }
739  }
740  else {
741  for(auto disVItr=disVtxContainer_EXISTING.begin(); disVItr!=disVtxContainer_EXISTING.end(); ++disVItr) {
742  const xAOD::Vertex* disVtx = disVItr->first;
743  const xAOD::Vertex* V0Vtx = selectedV0Candidates_EXISTING[disVItr->second].first;
744  V0Enum V0 = selectedV0Candidates_EXISTING[disVItr->second].second;
745  Trk::VxCascadeInfo* result = fitMainVtx(*jxItr, massesJX, disVtx, V0Vtx, V0, trackContainer.cptr());
746  if(result) cascadeinfoContainer->push_back(result);
747  }
748  }
749  } // m_disVDaug_num==3
750  } // Iterate over JX vertices
751 
752  // clean up transient objects
753  if(!disVtxOutputContainer) {
754  for(auto disVItr=disVtxContainer_CREATED.begin(); disVItr!=disVtxContainer_CREATED.end(); ++disVItr) delete disVItr->first;
755  }
756  if(!V0OutputContainer) {
757  for(auto v0VItr=selectedV0Candidates_CREATED.begin(); v0VItr!=selectedV0Candidates_CREATED.end(); ++v0VItr) delete v0VItr->first;
758  }
759 
760  return StatusCode::SUCCESS;
761  }
762 
764  size_t topoN = (m_disVDaug_num==2 ? 3 : 4);
765  if(!m_JXSubVtx) topoN--;
766 
767  if(m_cascadeOutputKeys.size() != topoN) {
768  ATH_MSG_FATAL("Incorrect number of output cascade vertices");
769  return StatusCode::FAILURE;
770  }
771 
772  std::array<SG::WriteHandle<xAOD::VertexContainer>, 4> VtxWriteHandles; int ikey(0);
774  VtxWriteHandles[ikey] = SG::WriteHandle<xAOD::VertexContainer>(key);
775  ATH_CHECK( VtxWriteHandles[ikey].record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
776  ikey++;
777  }
778 
779  //----------------------------------------------------
780  // retrieve primary vertices
781  //----------------------------------------------------
783  ATH_CHECK( pvContainer.isValid() );
784  if (pvContainer.cptr()->size()==0) {
785  ATH_MSG_WARNING("You have no primary vertices: " << pvContainer.cptr()->size());
786  return StatusCode::RECOVERABLE;
787  }
788 
789  //----------------------------------------------------
790  // Record refitted primary vertices
791  //----------------------------------------------------
793  if(m_refitPV) {
795  ATH_CHECK( refPvContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
796  }
797 
798  // output V0 vertices
799  SG::WriteHandle<xAOD::VertexContainer> V0OutputContainer;
800  if(m_v0VtxOutputKey.key() != "") {
802  ATH_CHECK( V0OutputContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
803  }
804 
805  // output displaced vertices
806  SG::WriteHandle<xAOD::VertexContainer> disVtxOutputContainer;
807  if(m_disVDaug_num==3 && m_disVtxOutputKey.key() != "") {
809  ATH_CHECK( disVtxOutputContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
810  }
811 
812  std::vector<Trk::VxCascadeInfo*> cascadeinfoContainer;
813  ATH_CHECK( performSearch(&cascadeinfoContainer, m_v0VtxOutputKey.key() != "" ? V0OutputContainer.ptr() : 0, m_disVDaug_num==3 && m_disVtxOutputKey.key() != "" ? disVtxOutputContainer.ptr() : 0) );
814 
815  std::sort( cascadeinfoContainer.begin(), cascadeinfoContainer.end(), [](Trk::VxCascadeInfo* a, Trk::VxCascadeInfo* b) { return a->fitChi2()/a->nDoF() < b->fitChi2()/b->nDoF(); } );
816  if(m_maxMainVCandidates>0 && cascadeinfoContainer.size()>m_maxMainVCandidates) {
817  for(auto it=cascadeinfoContainer.begin()+m_maxMainVCandidates; it!=cascadeinfoContainer.end(); it++) delete *it;
818  cascadeinfoContainer.erase(cascadeinfoContainer.begin()+m_maxMainVCandidates, cascadeinfoContainer.end());
819  }
820 
822  ATH_CHECK( evt.isValid() );
824  helper.SetMinNTracksInPV(m_PV_minNTracks);
825 
826  // Decorators for the main vertex: chi2, ndf, pt and pt error, plus the V0 vertex variables
827  SG::AuxElement::Decorator<VertexLinkVector> CascadeLinksDecor("CascadeVertexLinks");
828  SG::AuxElement::Decorator<VertexLinkVector> JXLinksDecor("JXVertexLinks");
829  SG::AuxElement::Decorator<VertexLinkVector> V0LinksDecor("V0VertexLinks");
830  SG::AuxElement::Decorator<float> chi2_decor("ChiSquared");
831  SG::AuxElement::Decorator<int> ndof_decor("nDoF");
832  SG::AuxElement::Decorator<float> Pt_decor("Pt");
833  SG::AuxElement::Decorator<float> PtErr_decor("PtErr");
834 
835  SG::AuxElement::Decorator<float> lxy_SV0_decor("lxy_SV0");
836  SG::AuxElement::Decorator<float> lxyErr_SV0_decor("lxyErr_SV0");
837  SG::AuxElement::Decorator<float> a0xy_SV0_decor("a0xy_SV0");
838  SG::AuxElement::Decorator<float> a0xyErr_SV0_decor("a0xyErr_SV0");
839  SG::AuxElement::Decorator<float> a0z_SV0_decor("a0z_SV0");
840  SG::AuxElement::Decorator<float> a0zErr_SV0_decor("a0zErr_SV0");
841 
842  SG::AuxElement::Decorator<float> lxy_SV1_decor("lxy_SV1");
843  SG::AuxElement::Decorator<float> lxyErr_SV1_decor("lxyErr_SV1");
844  SG::AuxElement::Decorator<float> a0xy_SV1_decor("a0xy_SV1");
845  SG::AuxElement::Decorator<float> a0xyErr_SV1_decor("a0xyErr_SV1");
846  SG::AuxElement::Decorator<float> a0z_SV1_decor("a0z_SV1");
847  SG::AuxElement::Decorator<float> a0zErr_SV1_decor("a0zErr_SV1");
848 
849  SG::AuxElement::Decorator<float> lxy_SV2_decor("lxy_SV2");
850  SG::AuxElement::Decorator<float> lxyErr_SV2_decor("lxyErr_SV2");
851  SG::AuxElement::Decorator<float> a0xy_SV2_decor("a0xy_SV2");
852  SG::AuxElement::Decorator<float> a0xyErr_SV2_decor("a0xyErr_SV2");
853  SG::AuxElement::Decorator<float> a0z_SV2_decor("a0z_SV2");
854  SG::AuxElement::Decorator<float> a0zErr_SV2_decor("a0zErr_SV2");
855 
856  SG::AuxElement::Decorator<float> chi2_V2_decor("ChiSquared_V2");
857  SG::AuxElement::Decorator<int> ndof_V2_decor("nDoF_V2");
858 
859  // Get the input containers
861  ATH_CHECK( jxContainer.isValid() );
863  ATH_CHECK( V0Container.isValid() );
864 
865  for(auto cascade_info : cascadeinfoContainer) {
866  if(cascade_info==nullptr) {
867  ATH_MSG_ERROR("CascadeInfo is null");
868  continue;
869  }
870 
871  const std::vector<xAOD::Vertex*> &cascadeVertices = cascade_info->vertices();
872  if(cascadeVertices.size() != topoN) ATH_MSG_ERROR("Incorrect number of vertices");
873  for(size_t i=0; i<topoN; i++) {
874  if(cascadeVertices[i]==nullptr) ATH_MSG_ERROR("Error null vertex");
875  }
876 
877  cascade_info->setSVOwnership(false); // Prevent Container from deleting vertices
878  const auto mainVertex = cascadeVertices[topoN-1]; // this is the mother vertex
879  const std::vector< std::vector<TLorentzVector> > &moms = cascade_info->getParticleMoms();
880 
881  // Identify the input JX
882  int ijx = m_JXSubVtx ? topoN-2 : topoN-1;
883  const xAOD::Vertex* jxVtx(nullptr);
884  if(m_jxDaug_num==4) jxVtx = FindVertex<4>(jxContainer.ptr(), cascadeVertices[ijx]);
885  else if(m_jxDaug_num==3) jxVtx = FindVertex<3>(jxContainer.ptr(), cascadeVertices[ijx]);
886  else jxVtx = FindVertex<2>(jxContainer.ptr(), cascadeVertices[ijx]);
887 
888  xAOD::BPhysHypoHelper vtx(m_hypoName, mainVertex);
889 
890  // Get refitted track momenta from all vertices, charged tracks only
891  BPhysPVCascadeTools::SetVectorInfo(vtx, cascade_info);
892  vtx.setPass(true);
893 
894  //
895  // Decorate main vertex
896  //
897  // mass, mass error
898  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/TrkVertexFitter/TrkVKalVrtFitter/TrkVKalVrtFitter/VxCascadeInfo.h
899  BPHYS_CHECK( vtx.setMass(m_CascadeTools->invariantMass(moms[topoN-1])) );
900  BPHYS_CHECK( vtx.setMassErr(m_CascadeTools->invariantMassError(moms[topoN-1],cascade_info->getCovariance()[topoN-1])) );
901  // pt and pT error (the default pt of mainVertex is != the pt of the full cascade fit!)
902  Pt_decor(*mainVertex) = m_CascadeTools->pT(moms[topoN-1]);
903  PtErr_decor(*mainVertex) = m_CascadeTools->pTError(moms[topoN-1],cascade_info->getCovariance()[topoN-1]);
904  // chi2 and ndof (the default chi2 of mainVertex is != the chi2 of the full cascade fit!)
905  chi2_decor(*mainVertex) = cascade_info->fitChi2();
906  ndof_decor(*mainVertex) = cascade_info->nDoF();
907 
908  if(m_disVDaug_num==2) {
909  // decorate the newly fitted V0 vertex
910  lxy_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->lxy(moms[0],cascadeVertices[0],mainVertex);
911  lxyErr_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->lxyError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],mainVertex);
912  a0z_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->a0z(moms[0],cascadeVertices[0],mainVertex);
913  a0zErr_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->a0zError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],mainVertex);
914  a0xy_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->a0xy(moms[0],cascadeVertices[0],mainVertex);
915  a0xyErr_SV1_decor(*cascadeVertices[0]) = m_CascadeTools->a0xyError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],mainVertex);
916  }
917  else {
918  // decorate the newly fitted V0 vertex
919  lxy_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[1]);
920  lxyErr_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->lxyError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],cascadeVertices[1]);
921  a0z_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->a0z(moms[0],cascadeVertices[0],cascadeVertices[1]);
922  a0zErr_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->a0zError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],cascadeVertices[1]);
923  a0xy_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->a0xy(moms[0],cascadeVertices[0],cascadeVertices[1]);
924  a0xyErr_SV0_decor(*cascadeVertices[0]) = m_CascadeTools->a0xyError(moms[0],cascade_info->getCovariance()[0],cascadeVertices[0],cascadeVertices[1]);
925 
926  // decorate the newly fitted disV vertex
927  lxy_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->lxy(moms[1],cascadeVertices[1],mainVertex);
928  lxyErr_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->lxyError(moms[1],cascade_info->getCovariance()[1],cascadeVertices[1],mainVertex);
929  a0xy_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->a0z(moms[1],cascadeVertices[1],mainVertex);
930  a0xyErr_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->a0zError(moms[1],cascade_info->getCovariance()[1],cascadeVertices[1],mainVertex);
931  a0z_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->a0xy(moms[1],cascadeVertices[1],mainVertex);
932  a0zErr_SV1_decor(*cascadeVertices[1]) = m_CascadeTools->a0xyError(moms[1],cascade_info->getCovariance()[1],cascadeVertices[1],mainVertex);
933  }
934 
935  // decorate the newly fitted JX vertex
936  if(m_JXSubVtx) {
937  lxy_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->lxy(moms[ijx],cascadeVertices[ijx],mainVertex);
938  lxyErr_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->lxyError(moms[ijx],cascade_info->getCovariance()[ijx],cascadeVertices[ijx],mainVertex);
939  a0z_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->a0z(moms[ijx],cascadeVertices[ijx],mainVertex);
940  a0zErr_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->a0zError(moms[ijx],cascade_info->getCovariance()[ijx],cascadeVertices[ijx],mainVertex);
941  a0xy_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->a0xy(moms[ijx],cascadeVertices[ijx],mainVertex);
942  a0xyErr_SV2_decor(*cascadeVertices[ijx]) = m_CascadeTools->a0xyError(moms[ijx],cascade_info->getCovariance()[ijx],cascadeVertices[ijx],mainVertex);
943  }
944 
945  chi2_V2_decor(*cascadeVertices[ijx]) = m_V0Tools->chisq(jxVtx);
946  ndof_V2_decor(*cascadeVertices[ijx]) = m_V0Tools->ndof(jxVtx);
947 
948  double Mass_Moth = m_CascadeTools->invariantMass(moms[topoN-1]);
949  ATH_CHECK(helper.FillCandwithRefittedVertices(m_refitPV, pvContainer.cptr(), m_refitPV ? refPvContainer.ptr() : 0, &(*m_pvRefitter), m_PV_max, m_DoVertexType, cascade_info, topoN-1, Mass_Moth, vtx));
950 
951  for(size_t i=0; i<topoN; i++) {
952  VtxWriteHandles[i].ptr()->push_back(cascadeVertices[i]);
953  }
954 
955  // Set links to cascade vertices
956  VertexLinkVector precedingVertexLinks;
957  VertexLink vertexLink1;
958  vertexLink1.setElement(cascadeVertices[0]);
959  vertexLink1.setStorableObject(*VtxWriteHandles[0].ptr());
960  if( vertexLink1.isValid() ) precedingVertexLinks.push_back( vertexLink1 );
961  if(topoN>=3) {
962  VertexLink vertexLink2;
963  vertexLink2.setElement(cascadeVertices[1]);
964  vertexLink2.setStorableObject(*VtxWriteHandles[1].ptr());
965  if( vertexLink2.isValid() ) precedingVertexLinks.push_back( vertexLink2 );
966  }
967  if(topoN==4) {
968  VertexLink vertexLink3;
969  vertexLink3.setElement(cascadeVertices[2]);
970  vertexLink3.setStorableObject(*VtxWriteHandles[2].ptr());
971  if( vertexLink3.isValid() ) precedingVertexLinks.push_back( vertexLink3 );
972  }
973  CascadeLinksDecor(*mainVertex) = precedingVertexLinks;
974  } // loop over cascadeinfoContainer
975 
976  // Deleting cascadeinfo since this won't be stored.
977  // Vertices have been kept in m_cascadeOutputs and should be owned by their container
978  for (auto cascade_info : cascadeinfoContainer) delete cascade_info;
979 
980  return StatusCode::SUCCESS;
981  }
982 
983  bool JpsiXPlusDisplaced::d0Pass(const xAOD::TrackParticle* track, const xAOD::Vertex* PV, const Amg::Vector3D& beamspot) const {
984  bool pass = false;
985  auto ctx = Gaudi::Hive::currentContext();
986  if(PV) {
987  auto per = m_trackToVertexTool->perigeeAtVertex(ctx, *track, PV->position());
988  if(per == 0) return pass;
989  double d0 = per->parameters()[Trk::d0];
990  double sig_d0 = sqrt((*per->covariance())(0,0));
991  if(std::abs(d0/sig_d0) > m_d0_cut) pass = true;
992  }
993  else {
994  auto per = m_trackToVertexTool->perigeeAtVertex(ctx, *track, beamspot);
995  if(per == 0) return pass;
996  double d0 = per->parameters()[Trk::d0];
997  double sig_d0 = sqrt((*per->covariance())(0,0));
998  if(std::abs(d0/sig_d0) > m_d0_cut) pass = true;
999  }
1000  return pass;
1001  }
1002 
1003  xAOD::Vertex* JpsiXPlusDisplaced::fitDisVtx(const xAOD::Vertex* V0vtx, const V0Enum V0, const xAOD::TrackParticle* track3, const xAOD::TrackParticleContainer* trackContainer) const {
1004  xAOD::Vertex* disVtx(nullptr);
1005 
1006  // Check overlap
1007  std::vector<const xAOD::TrackParticle*> tracksV0;
1008  for(size_t i=0; i<V0vtx->nTrackParticles(); i++) tracksV0.push_back(V0vtx->trackParticle(i));
1009  if(std::find(tracksV0.cbegin(), tracksV0.cend(), track3) != tracksV0.cend()) return disVtx;
1010 
1011  std::vector<double> massesV0;
1012  if(V0==LAMBDA) massesV0 = std::vector<double>{m_mass_proton,m_mass_pion};
1013  else if(V0==LAMBDABAR) massesV0 = std::vector<double>{m_mass_pion,m_mass_proton};
1014  else if(V0==KS) massesV0 = std::vector<double>{m_mass_pion,m_mass_pion};
1015  xAOD::BPhysHelper V0_helper(V0vtx);
1016  TLorentzVector p4_v0, tmp;
1017  for(int i=0; i<V0_helper.nRefTrks(); i++) p4_v0 += V0_helper.refTrk(i,massesV0[i]);
1018  tmp.SetPtEtaPhiM(track3->pt(),track3->eta(),track3->phi(),m_disVDaug3MassHypo);
1019  // A rough mass window cut, as V0 and the track are not from a common vertex
1020  if ((p4_v0+tmp).M() < m_DisplacedMassLower || (p4_v0+tmp).M() > m_DisplacedMassUpper) return disVtx;
1021 
1022  std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
1023  int robustness = 0;
1024  m_iVertexFitter->setRobustness(robustness, *state);
1025  std::vector<Trk::VertexID> vrtList;
1026  // V0 vertex
1027  Trk::VertexID vID;
1028  if(m_constrV0) vID = m_iVertexFitter->startVertex(tracksV0,massesV0,*state,m_massV0);
1029  else vID = m_iVertexFitter->startVertex(tracksV0,massesV0,*state);
1030  vrtList.push_back(vID);
1031  // Mother vertex
1032  std::vector<const xAOD::TrackParticle*> tracksDis3{track3};
1033  std::vector<double> massesDis3{m_disVDaug3MassHypo};
1034  if (m_constrDisV) m_iVertexFitter->nextVertex(tracksDis3,massesDis3,vrtList,*state,m_massDisV);
1035  else m_iVertexFitter->nextVertex(tracksDis3,massesDis3,vrtList,*state);
1036  // Do the work
1037  std::unique_ptr<Trk::VxCascadeInfo> cascade_info = std::unique_ptr<Trk::VxCascadeInfo>( m_iVertexFitter->fitCascade(*state) );
1038  if(cascade_info != nullptr) {
1039  BPhysPVCascadeTools::PrepareVertexLinks(cascade_info.get(), trackContainer);
1040  cascade_info->setSVOwnership(false);
1041  const std::vector<xAOD::Vertex*>& disVertices = cascade_info->vertices();
1042  double chi2NDF = cascade_info->fitChi2()/cascade_info->nDoF();
1043  if(m_chi2cut_DisV<=0 || chi2NDF < m_chi2cut_DisV) {
1044  xAOD::BPhysHelper disV_helper(disVertices[1]);
1045  // Get refitted track momenta from all vertices, charged tracks only
1046  BPhysPVCascadeTools::SetVectorInfo(disV_helper, cascade_info.get());
1047 
1048  SG::AuxElement::Decorator<float> chi2_decor("ChiSquared_Cascade");
1049  SG::AuxElement::Decorator<int> ndof_decor("nDoF_Cascade");
1050  chi2_decor(*disVertices[1]) = cascade_info->fitChi2();
1051  ndof_decor(*disVertices[1]) = cascade_info->nDoF();
1052 
1053  disVtx = disVertices[1];
1054  }
1055  else delete disVertices[1];
1056  delete disVertices[0]; // always delete the newly fitted V0 vertices
1057  }
1058  return disVtx;
1059  }
1060 
1061  Trk::VxCascadeInfo* JpsiXPlusDisplaced::fitMainVtx(const xAOD::Vertex* JXvtx, std::vector<double>& massesJX, const xAOD::Vertex* V0vtx, const V0Enum V0, const xAOD::TrackParticleContainer* trackContainer) const {
1062  Trk::VxCascadeInfo* result(nullptr);
1063 
1064  std::vector<const xAOD::TrackParticle*> tracksJX;
1065  for(size_t i=0; i<JXvtx->nTrackParticles(); i++) tracksJX.push_back(JXvtx->trackParticle(i));
1066  if (tracksJX.size() != massesJX.size()) {
1067  ATH_MSG_ERROR("Problems with JX input: number of tracks or track mass inputs is not correct!");
1068  return result;
1069  }
1070  // Check identical tracks in input
1071  if(std::find(tracksJX.cbegin(), tracksJX.cend(), V0vtx->trackParticle(0)) != tracksJX.cend()) return result;
1072  if(std::find(tracksJX.cbegin(), tracksJX.cend(), V0vtx->trackParticle(1)) != tracksJX.cend()) return result;
1073  std::vector<const xAOD::TrackParticle*> tracksV0;
1074  for(size_t j=0; j<V0vtx->nTrackParticles(); j++) tracksV0.push_back(V0vtx->trackParticle(j));
1075 
1076  std::vector<const xAOD::TrackParticle*> tracksJpsi;
1077  tracksJpsi.push_back(tracksJX[0]);
1078  tracksJpsi.push_back(tracksJX[1]);
1079  std::vector<const xAOD::TrackParticle*> tracksX;
1080  if(m_jxDaug_num>=3) tracksX.push_back(tracksJX[2]);
1081  if(m_jxDaug_num==4) tracksX.push_back(tracksJX[3]);
1082 
1083  std::vector<double> massesV0;
1084  if(V0==LAMBDA) massesV0 = std::vector<double>{m_mass_proton,m_mass_pion};
1085  else if(V0==LAMBDABAR) massesV0 = std::vector<double>{m_mass_pion,m_mass_proton};
1086  else if(V0==KS) massesV0 = std::vector<double>{m_mass_pion,m_mass_pion};
1087 
1088  TLorentzVector p4_moth, tmp;
1089  for(size_t it=0; it<JXvtx->nTrackParticles(); it++) {
1090  tmp.SetPtEtaPhiM(JXvtx->trackParticle(it)->pt(), JXvtx->trackParticle(it)->eta(), JXvtx->trackParticle(it)->phi(), massesJX[it]);
1091  p4_moth += tmp;
1092  }
1093  xAOD::BPhysHelper V0_helper(V0vtx);
1094  for(int it=0; it<V0_helper.nRefTrks(); it++) {
1095  p4_moth += V0_helper.refTrk(it,massesV0[it]);
1096  }
1097 
1098  SG::AuxElement::Decorator<float> chi2_V1_decor("ChiSquared_V1");
1099  SG::AuxElement::Decorator<int> ndof_V1_decor("nDoF_V1");
1100  SG::AuxElement::Decorator<std::string> type_V1_decor("Type_V1");
1101 
1102  SG::AuxElement::Accessor<int> mAcc_gfit("gamma_fit");
1103  SG::AuxElement::Accessor<float> mAcc_gmass("gamma_mass");
1104  SG::AuxElement::Accessor<float> mAcc_gmasserr("gamma_massError");
1105  SG::AuxElement::Accessor<float> mAcc_gchisq("gamma_chisq");
1106  SG::AuxElement::Accessor<int> mAcc_gndof("gamma_ndof");
1107  SG::AuxElement::Accessor<float> mAcc_gprob("gamma_probability");
1108  SG::AuxElement::Accessor< std::vector<float> > trk_pxAcc("TrackPx_V0nc");
1109  SG::AuxElement::Accessor< std::vector<float> > trk_pyAcc("TrackPy_V0nc");
1110  SG::AuxElement::Accessor< std::vector<float> > trk_pzAcc("TrackPz_V0nc");
1111 
1112  SG::AuxElement::Decorator<int> mDec_gfit("gamma_fit");
1113  SG::AuxElement::Decorator<float> mDec_gmass("gamma_mass");
1114  SG::AuxElement::Decorator<float> mDec_gmasserr("gamma_massError");
1115  SG::AuxElement::Decorator<float> mDec_gchisq("gamma_chisq");
1116  SG::AuxElement::Decorator<int> mDec_gndof("gamma_ndof");
1117  SG::AuxElement::Decorator<float> mDec_gprob("gamma_probability");
1118  SG::AuxElement::Decorator< std::vector<float> > trk_pxDeco("TrackPx_V0nc");
1119  SG::AuxElement::Decorator< std::vector<float> > trk_pyDeco("TrackPy_V0nc");
1120  SG::AuxElement::Decorator< std::vector<float> > trk_pzDeco("TrackPz_V0nc");
1121 
1122  std::vector<float> trk_px;
1123  std::vector<float> trk_py;
1124  std::vector<float> trk_pz;
1125 
1126  if(m_extraTrkMassHypo<=0) {
1127  if (p4_moth.M() < m_MassLower || p4_moth.M() > m_MassUpper) return result;
1128 
1129  // Apply the user's settings to the fitter
1130  std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
1131  // Robustness: http://cdsweb.cern.ch/record/685551
1132  int robustness = 0;
1133  m_iVertexFitter->setRobustness(robustness, *state);
1134  // Build up the topology
1135  // Vertex list
1136  std::vector<Trk::VertexID> vrtList;
1137  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/TrkVertexFitter/TrkVKalVrtFitter/TrkVKalVrtFitter/IVertexCascadeFitter.h
1138  // V0 vertex
1139  Trk::VertexID vID1;
1140  if (m_constrV0) {
1141  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state,m_massV0);
1142  } else {
1143  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state);
1144  }
1145  vrtList.push_back(vID1);
1146  Trk::VertexID vID2;
1147  if(m_JXSubVtx) {
1148  // JX vertex
1149  if (m_constrJX && m_jxDaug_num>2) {
1150  vID2 = m_iVertexFitter->nextVertex(tracksJX,massesJX,*state,m_massJX);
1151  } else {
1152  vID2 = m_iVertexFitter->nextVertex(tracksJX,massesJX,*state);
1153  }
1154  vrtList.push_back(vID2);
1155  // Mother vertex including JX and V0
1156  std::vector<const xAOD::TrackParticle*> tp; tp.clear();
1157  std::vector<double> tp_masses; tp_masses.clear();
1158  if(m_constrMainV) {
1159  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList,*state,m_massMainV);
1160  } else {
1161  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList,*state);
1162  }
1163  }
1164  else { // m_JXSubVtx=false
1165  // Mother vertex including JX and V0
1166  if(m_constrMainV) {
1167  vID2 = m_iVertexFitter->nextVertex(tracksJX,massesJX,vrtList,*state,m_massMainV);
1168  } else {
1169  vID2 = m_iVertexFitter->nextVertex(tracksJX,massesJX,vrtList,*state);
1170  }
1171  if (m_constrJX && m_jxDaug_num>2) {
1172  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1173  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksJX,cnstV,*state,m_massJX).isSuccess() ) {
1174  ATH_MSG_WARNING("addMassConstraint for JX failed");
1175  }
1176  }
1177  }
1178  if (m_constrJpsi) {
1179  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1180  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksJpsi,cnstV,*state,m_massJpsi).isSuccess() ) {
1181  ATH_MSG_WARNING("addMassConstraint for Jpsi failed");
1182  }
1183  }
1184  if (m_constrX && m_jxDaug_num==4 && m_massX>0) {
1185  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1186  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksX,cnstV,*state,m_massX).isSuccess() ) {
1187  ATH_MSG_WARNING("addMassConstraint for X failed");
1188  }
1189  }
1190  // Do the work
1191  std::unique_ptr<Trk::VxCascadeInfo> fit_result = std::unique_ptr<Trk::VxCascadeInfo>( m_iVertexFitter->fitCascade(*state) );
1192 
1193  if (fit_result != nullptr) {
1194  for(auto v : fit_result->vertices()) {
1195  if(v->nTrackParticles()==0) {
1196  std::vector<ElementLink<xAOD::TrackParticleContainer> > nullLinkVector;
1197  v->setTrackParticleLinks(nullLinkVector);
1198  }
1199  }
1200  // reset links to original tracks
1201  BPhysPVCascadeTools::PrepareVertexLinks(fit_result.get(), trackContainer);
1202 
1203  // necessary to prevent memory leak
1204  fit_result->setSVOwnership(true);
1205 
1206  // Chi2/DOF cut
1207  double chi2DOF = fit_result->fitChi2()/fit_result->nDoF();
1208  bool chi2CutPassed = (m_chi2cut <= 0.0 || chi2DOF < m_chi2cut);
1209 
1210  const std::vector<std::vector<TLorentzVector> > &moms = fit_result->getParticleMoms();
1211  const std::vector<xAOD::Vertex*> &cascadeVertices = fit_result->vertices();
1212  size_t iMoth = cascadeVertices.size()-1;
1213  double lxy_SV1 = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[iMoth]);
1214  if(chi2CutPassed && lxy_SV1>m_lxyV0_cut) {
1215  chi2_V1_decor(*cascadeVertices[0]) = V0vtx->chiSquared();
1216  ndof_V1_decor(*cascadeVertices[0]) = V0vtx->numberDoF();
1217  if(V0==LAMBDA) type_V1_decor(*cascadeVertices[0]) = "Lambda";
1218  else if(V0==LAMBDABAR) type_V1_decor(*cascadeVertices[0]) = "Lambdabar";
1219  else if(V0==KS) type_V1_decor(*cascadeVertices[0]) = "Ks";
1220  mDec_gfit(*cascadeVertices[0]) = mAcc_gfit.isAvailable(*V0vtx) ? mAcc_gfit(*V0vtx) : 0;
1221  mDec_gmass(*cascadeVertices[0]) = mAcc_gmass.isAvailable(*V0vtx) ? mAcc_gmass(*V0vtx) : -1;
1222  mDec_gmasserr(*cascadeVertices[0]) = mAcc_gmasserr.isAvailable(*V0vtx) ? mAcc_gmasserr(*V0vtx) : -1;
1223  mDec_gchisq(*cascadeVertices[0]) = mAcc_gchisq.isAvailable(*V0vtx) ? mAcc_gchisq(*V0vtx) : 999999;
1224  mDec_gndof(*cascadeVertices[0]) = mAcc_gndof.isAvailable(*V0vtx) ? mAcc_gndof(*V0vtx) : 0;
1225  mDec_gprob(*cascadeVertices[0]) = mAcc_gprob.isAvailable(*V0vtx) ? mAcc_gprob(*V0vtx) : -1;
1226  trk_px.clear(); trk_py.clear(); trk_pz.clear();
1227  if(trk_pxAcc.isAvailable(*V0vtx)) trk_px = trk_pxAcc(*V0vtx);
1228  if(trk_pyAcc.isAvailable(*V0vtx)) trk_py = trk_pyAcc(*V0vtx);
1229  if(trk_pzAcc.isAvailable(*V0vtx)) trk_pz = trk_pzAcc(*V0vtx);
1230  trk_pxDeco(*cascadeVertices[0]) = trk_px;
1231  trk_pyDeco(*cascadeVertices[0]) = trk_py;
1232  trk_pzDeco(*cascadeVertices[0]) = trk_pz;
1233 
1234  result = fit_result.release();
1235  }
1236  }
1237  } // m_extraTrkMassHypo<=0
1238  else { // m_extraTrkMassHypo>0
1239  std::vector<double> massesJXExtra;
1240  for(size_t i=0; i<massesJX.size(); i++) massesJXExtra.push_back(massesJX[i]);
1241  massesJXExtra.push_back(m_extraTrkMassHypo);
1242 
1243  for(auto tpIter=trackContainer->cbegin(); tpIter!=trackContainer->cend(); ++tpIter) {
1244  const xAOD::TrackParticle* tpExtra = (*tpIter);
1245  if ( tpExtra->pt()<m_extraTrkMinPt ) continue;
1246  if ( !m_trkSelector->decision(*tpExtra, NULL) ) continue;
1247  // Check identical tracks in input
1248  if(std::find(tracksJX.cbegin(),tracksJX.cend(),tpExtra) != tracksJX.cend()) continue;
1249  if(std::find(tracksV0.cbegin(),tracksV0.cend(),tpExtra) != tracksV0.cend()) continue;
1250 
1251  TLorentzVector tmp;
1252  tmp.SetPtEtaPhiM(tpExtra->pt(),tpExtra->eta(),tpExtra->phi(),m_extraTrkMassHypo);
1253  if ((p4_moth+tmp).M() < m_MassLower || (p4_moth+tmp).M() > m_MassUpper) continue;
1254 
1255  std::vector<const xAOD::TrackParticle*> tracksJXExtra;
1256  for(size_t it=0; it<tracksJX.size(); it++) tracksJXExtra.push_back(tracksJX[it]);
1257  tracksJXExtra.push_back(tpExtra);
1258 
1259  // Apply the user's settings to the fitter
1260  std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
1261  // Robustness: http://cdsweb.cern.ch/record/685551
1262  int robustness = 0;
1263  m_iVertexFitter->setRobustness(robustness, *state);
1264  // Build up the topology
1265  // Vertex list
1266  std::vector<Trk::VertexID> vrtList;
1267  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/TrkVertexFitter/TrkVKalVrtFitter/TrkVKalVrtFitter/IVertexCascadeFitter.h
1268  // V0 vertex
1269  Trk::VertexID vID1;
1270  if (m_constrV0) {
1271  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state,m_massV0);
1272  } else {
1273  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state);
1274  }
1275  vrtList.push_back(vID1);
1276  Trk::VertexID vID2;
1277  if(m_JXSubVtx) {
1278  // JXExtra vertex
1279  vID2 = m_iVertexFitter->nextVertex(tracksJXExtra,massesJXExtra,*state);
1280  vrtList.push_back(vID2);
1281  // Mother vertex including JX, V0 and the extra track
1282  std::vector<const xAOD::TrackParticle*> tp; tp.clear();
1283  std::vector<double> tp_masses; tp_masses.clear();
1284  if(m_constrMainV) {
1285  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList,*state,m_massMainV);
1286  } else {
1287  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList,*state);
1288  }
1289  }
1290  else { // m_JXSubVtx=false
1291  // Mother vertex including JX and V0 and the extra track
1292  if(m_constrMainV) {
1293  vID2 = m_iVertexFitter->nextVertex(tracksJXExtra,massesJXExtra,vrtList,*state,m_massMainV);
1294  } else {
1295  vID2 = m_iVertexFitter->nextVertex(tracksJXExtra,massesJXExtra,vrtList,*state);
1296  }
1297  }
1298  if (m_constrJX && m_jxDaug_num>2) {
1299  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1300  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksJX,cnstV,*state,m_massJX).isSuccess() ) {
1301  ATH_MSG_WARNING("addMassConstraint for JX failed");
1302  }
1303  }
1304  if (m_constrJpsi) {
1305  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1306  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksJpsi,cnstV,*state,m_massJpsi).isSuccess() ) {
1307  ATH_MSG_WARNING("addMassConstraint for Jpsi failed");
1308  }
1309  }
1310  if (m_constrX && m_jxDaug_num==4 && m_massX>0) {
1311  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1312  if ( !m_iVertexFitter->addMassConstraint(vID2,tracksX,cnstV,*state,m_massX).isSuccess() ) {
1313  ATH_MSG_WARNING("addMassConstraint for X failed");
1314  }
1315  }
1316  // Do the work
1317  std::unique_ptr<Trk::VxCascadeInfo> fit_result = std::unique_ptr<Trk::VxCascadeInfo>( m_iVertexFitter->fitCascade(*state) );
1318 
1319  if (fit_result != nullptr) {
1320  for(auto v : fit_result->vertices()) {
1321  if(v->nTrackParticles()==0) {
1322  std::vector<ElementLink<xAOD::TrackParticleContainer> > nullLinkVector;
1323  v->setTrackParticleLinks(nullLinkVector);
1324  }
1325  }
1326  // reset links to original tracks
1327  BPhysPVCascadeTools::PrepareVertexLinks(fit_result.get(), trackContainer);
1328 
1329  // necessary to prevent memory leak
1330  fit_result->setSVOwnership(true);
1331 
1332  // Chi2/DOF cut
1333  double chi2DOF = fit_result->fitChi2()/fit_result->nDoF();
1334  bool chi2CutPassed = (m_chi2cut <= 0.0 || chi2DOF < m_chi2cut);
1335  const std::vector<std::vector<TLorentzVector> > &moms = fit_result->getParticleMoms();
1336  const std::vector<xAOD::Vertex*> &cascadeVertices = fit_result->vertices();
1337  size_t iMoth = cascadeVertices.size()-1;
1338  double lxy_SV1 = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[iMoth]);
1339  if(chi2CutPassed && lxy_SV1>m_lxyV0_cut) {
1340  chi2_V1_decor(*cascadeVertices[0]) = V0vtx->chiSquared();
1341  ndof_V1_decor(*cascadeVertices[0]) = V0vtx->numberDoF();
1342  if(V0==LAMBDA) type_V1_decor(*cascadeVertices[0]) = "Lambda";
1343  else if(V0==LAMBDABAR) type_V1_decor(*cascadeVertices[0]) = "Lambdabar";
1344  else if(V0==KS) type_V1_decor(*cascadeVertices[0]) = "Ks";
1345  mDec_gfit(*cascadeVertices[0]) = mAcc_gfit.isAvailable(*V0vtx) ? mAcc_gfit(*V0vtx) : 0;
1346  mDec_gmass(*cascadeVertices[0]) = mAcc_gmass.isAvailable(*V0vtx) ? mAcc_gmass(*V0vtx) : -1;
1347  mDec_gmasserr(*cascadeVertices[0]) = mAcc_gmasserr.isAvailable(*V0vtx) ? mAcc_gmasserr(*V0vtx) : -1;
1348  mDec_gchisq(*cascadeVertices[0]) = mAcc_gchisq.isAvailable(*V0vtx) ? mAcc_gchisq(*V0vtx) : 999999;
1349  mDec_gndof(*cascadeVertices[0]) = mAcc_gndof.isAvailable(*V0vtx) ? mAcc_gndof(*V0vtx) : 0;
1350  mDec_gprob(*cascadeVertices[0]) = mAcc_gprob.isAvailable(*V0vtx) ? mAcc_gprob(*V0vtx) : -1;
1351  trk_px.clear(); trk_py.clear(); trk_pz.clear();
1352  if(trk_pxAcc.isAvailable(*V0vtx)) trk_px = trk_pxAcc(*V0vtx);
1353  if(trk_pyAcc.isAvailable(*V0vtx)) trk_py = trk_pyAcc(*V0vtx);
1354  if(trk_pzAcc.isAvailable(*V0vtx)) trk_pz = trk_pzAcc(*V0vtx);
1355  trk_pxDeco(*cascadeVertices[0]) = trk_px;
1356  trk_pyDeco(*cascadeVertices[0]) = trk_py;
1357  trk_pzDeco(*cascadeVertices[0]) = trk_pz;
1358 
1359  result = fit_result.release();
1360  }
1361  }
1362  } // loop over trackContainer
1363  } // m_extraTrkMassHypo>0
1364 
1365  return result;
1366  }
1367 
1368  Trk::VxCascadeInfo* JpsiXPlusDisplaced::fitMainVtx(const xAOD::Vertex* JXvtx, std::vector<double>& massesJX, const xAOD::Vertex* disVtx, const xAOD::Vertex* V0vtx, const V0Enum V0, const xAOD::TrackParticleContainer* trackContainer) const {
1369  Trk::VxCascadeInfo* result(nullptr);
1370 
1371  std::vector<const xAOD::TrackParticle*> tracksJX;
1372  for(size_t i=0; i<JXvtx->nTrackParticles(); i++) tracksJX.push_back(JXvtx->trackParticle(i));
1373  if (tracksJX.size() != massesJX.size()) {
1374  ATH_MSG_ERROR("Problems with JX input: number of tracks or track mass inputs is not correct!");
1375  return result;
1376  }
1377  // Check identical tracks in input
1378  if(std::find(tracksJX.cbegin(), tracksJX.cend(), V0vtx->trackParticle(0)) != tracksJX.cend()) return result;
1379  if(std::find(tracksJX.cbegin(), tracksJX.cend(), V0vtx->trackParticle(1)) != tracksJX.cend()) return result;
1380  std::vector<const xAOD::TrackParticle*> tracksV0;
1381  for(size_t j=0; j<V0vtx->nTrackParticles(); j++) tracksV0.push_back(V0vtx->trackParticle(j));
1382 
1383  if(std::find(tracksJX.cbegin(), tracksJX.cend(), disVtx->trackParticle(0)) != tracksJX.cend()) return result;
1384  std::vector<const xAOD::TrackParticle*> tracks3{disVtx->trackParticle(0)};
1385 
1386  std::vector<const xAOD::TrackParticle*> tracksJpsi;
1387  tracksJpsi.push_back(tracksJX[0]);
1388  tracksJpsi.push_back(tracksJX[1]);
1389  std::vector<const xAOD::TrackParticle*> tracksX;
1390  if(m_jxDaug_num>=3) tracksX.push_back(tracksJX[2]);
1391  if(m_jxDaug_num==4) tracksX.push_back(tracksJX[3]);
1392 
1393  std::vector<double> massesV0;
1394  if(V0==LAMBDA) massesV0 = std::vector<double>{m_mass_proton,m_mass_pion};
1395  else if(V0==LAMBDABAR) massesV0 = std::vector<double>{m_mass_pion,m_mass_proton};
1396  else if(V0==KS) massesV0 = std::vector<double>{m_mass_pion,m_mass_pion};
1397 
1398  std::vector<double> massesDis3 = {m_disVDaug3MassHypo};
1399 
1400  std::vector<double> massesDisV = massesV0;
1401  massesDisV.push_back(massesDis3[0]);
1402 
1403  TLorentzVector p4_moth, tmp;
1404  for(size_t it=0; it<JXvtx->nTrackParticles(); it++) {
1405  tmp.SetPtEtaPhiM(JXvtx->trackParticle(it)->pt(), JXvtx->trackParticle(it)->eta(), JXvtx->trackParticle(it)->phi(), massesJX[it]);
1406  p4_moth += tmp;
1407  }
1408  xAOD::BPhysHelper disV_helper(disVtx);
1409  for(int it=0; it<disV_helper.nRefTrks(); it++) {
1410  p4_moth += disV_helper.refTrk(it,massesDisV[it]);
1411  }
1412  if (p4_moth.M() < m_MassLower || p4_moth.M() > m_MassUpper) return result;
1413 
1414  std::vector<float> trk_px;
1415  std::vector<float> trk_py;
1416  std::vector<float> trk_pz;
1417 
1418  // Apply the user's settings to the fitter
1419  std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
1420  // Robustness: http://cdsweb.cern.ch/record/685551
1421  int robustness = 0;
1422  m_iVertexFitter->setRobustness(robustness, *state);
1423  // Build up the topology
1424  // Vertex list
1425  std::vector<Trk::VertexID> vrtList;
1426  std::vector<Trk::VertexID> vrtList2;
1427  // https://gitlab.cern.ch/atlas/athena/-/blob/main/Tracking/TrkVertexFitter/TrkVKalVrtFitter/TrkVKalVrtFitter/IVertexCascadeFitter.h
1428  // V0 vertex
1429  Trk::VertexID vID1;
1430  if (m_constrV0) {
1431  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state,m_massV0);
1432  } else {
1433  vID1 = m_iVertexFitter->startVertex(tracksV0,massesV0,*state);
1434  }
1435  vrtList.push_back(vID1);
1436  // Displaced vertex
1437  Trk::VertexID vID2;
1438  if (m_constrDisV) {
1439  vID2 = m_iVertexFitter->nextVertex(tracks3,massesDis3,vrtList,*state,m_massDisV);
1440  } else {
1441  vID2 = m_iVertexFitter->nextVertex(tracks3,massesDis3,vrtList,*state);
1442  }
1443  vrtList2.push_back(vID2);
1444  Trk::VertexID vID3;
1445  if(m_JXSubVtx) {
1446  // JX vertex
1447  if (m_constrJX && m_jxDaug_num>2) {
1448  vID3 = m_iVertexFitter->nextVertex(tracksJX,massesJX,*state,m_massJX);
1449  } else {
1450  vID3 = m_iVertexFitter->nextVertex(tracksJX,massesJX,*state);
1451  }
1452  vrtList2.push_back(vID3);
1453  // Mother vertex including JX and DisV
1454  std::vector<const xAOD::TrackParticle*> tp; tp.clear();
1455  std::vector<double> tp_masses; tp_masses.clear();
1456  if(m_constrMainV) {
1457  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList2,*state,m_massMainV);
1458  } else {
1459  m_iVertexFitter->nextVertex(tp,tp_masses,vrtList2,*state);
1460  }
1461  }
1462  else { // m_JXSubVtx=false
1463  // Mother vertex including JX and DisV
1464  if(m_constrMainV) {
1465  vID3 = m_iVertexFitter->nextVertex(tracksJX,massesJX,vrtList2,*state,m_massMainV);
1466  } else {
1467  vID3 = m_iVertexFitter->nextVertex(tracksJX,massesJX,vrtList2,*state);
1468  }
1469  if (m_constrJX && m_jxDaug_num>2) {
1470  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1471  if ( !m_iVertexFitter->addMassConstraint(vID3,tracksJX,cnstV,*state,m_massJX).isSuccess() ) {
1472  ATH_MSG_WARNING("addMassConstraint for JX failed");
1473  }
1474  }
1475  }
1476  if (m_constrJpsi) {
1477  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1478  if ( !m_iVertexFitter->addMassConstraint(vID3,tracksJpsi,cnstV,*state,m_massJpsi).isSuccess() ) {
1479  ATH_MSG_WARNING("addMassConstraint for Jpsi failed");
1480  }
1481  }
1482  if (m_constrX && m_jxDaug_num==4 && m_massX>0) {
1483  std::vector<Trk::VertexID> cnstV; cnstV.clear();
1484  if ( !m_iVertexFitter->addMassConstraint(vID3,tracksX,cnstV,*state,m_massX).isSuccess() ) {
1485  ATH_MSG_WARNING("addMassConstraint for X failed");
1486  }
1487  }
1488  // Do the work
1489  std::unique_ptr<Trk::VxCascadeInfo> fit_result = std::unique_ptr<Trk::VxCascadeInfo>( m_iVertexFitter->fitCascade(*state) );
1490 
1491  if (fit_result != nullptr) {
1492  for(auto v : fit_result->vertices()) {
1493  if(v->nTrackParticles()==0) {
1494  std::vector<ElementLink<xAOD::TrackParticleContainer> > nullLinkVector;
1495  v->setTrackParticleLinks(nullLinkVector);
1496  }
1497  }
1498  // reset links to original tracks
1499  BPhysPVCascadeTools::PrepareVertexLinks(fit_result.get(), trackContainer);
1500 
1501  // necessary to prevent memory leak
1502  fit_result->setSVOwnership(true);
1503 
1504  // Chi2/DOF cut
1505  double chi2DOF = fit_result->fitChi2()/fit_result->nDoF();
1506  bool chi2CutPassed = (m_chi2cut <= 0.0 || chi2DOF < m_chi2cut);
1507 
1508  const std::vector<std::vector<TLorentzVector> > &moms = fit_result->getParticleMoms();
1509  const std::vector<xAOD::Vertex*> &cascadeVertices = fit_result->vertices();
1510  size_t iMoth = cascadeVertices.size()-1;
1511  double lxy_SV1_sub = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[1]);
1512  double lxy_SV1 = m_CascadeTools->lxy(moms[1],cascadeVertices[1],cascadeVertices[iMoth]);
1513 
1514  if(chi2CutPassed && lxy_SV1>m_lxyDisV_cut && lxy_SV1_sub>m_lxyV0_cut) {
1515  SG::AuxElement::Accessor<float> ChiSquared("ChiSquared_Cascade");
1516  SG::AuxElement::Accessor<int> nDoF("nDoF_Cascade");
1517 
1518  SG::AuxElement::Decorator<float> chi2_V1_decor("ChiSquared_V1");
1519  SG::AuxElement::Decorator<int> ndof_V1_decor("nDoF_V1");
1520  SG::AuxElement::Decorator<float> chi2_V0_decor("ChiSquared_V0");
1521  SG::AuxElement::Decorator<int> ndof_V0_decor("nDoF_V0");
1522  SG::AuxElement::Decorator<std::string> type_V0_decor("Type_V0");
1523 
1524  SG::AuxElement::Accessor<int> mAcc_gfit("gamma_fit");
1525  SG::AuxElement::Accessor<float> mAcc_gmass("gamma_mass");
1526  SG::AuxElement::Accessor<float> mAcc_gmasserr("gamma_massError");
1527  SG::AuxElement::Accessor<float> mAcc_gchisq("gamma_chisq");
1528  SG::AuxElement::Accessor<int> mAcc_gndof("gamma_ndof");
1529  SG::AuxElement::Accessor<float> mAcc_gprob("gamma_probability");
1530  SG::AuxElement::Accessor< std::vector<float> > trk_pxAcc("TrackPx_V0nc");
1531  SG::AuxElement::Accessor< std::vector<float> > trk_pyAcc("TrackPy_V0nc");
1532  SG::AuxElement::Accessor< std::vector<float> > trk_pzAcc("TrackPz_V0nc");
1533 
1534  SG::AuxElement::Decorator<int> mDec_gfit("gamma_fit");
1535  SG::AuxElement::Decorator<float> mDec_gmass("gamma_mass");
1536  SG::AuxElement::Decorator<float> mDec_gmasserr("gamma_massError");
1537  SG::AuxElement::Decorator<float> mDec_gchisq("gamma_chisq");
1538  SG::AuxElement::Decorator<int> mDec_gndof("gamma_ndof");
1539  SG::AuxElement::Decorator<float> mDec_gprob("gamma_probability");
1540  SG::AuxElement::Decorator< std::vector<float> > trk_pxDeco("TrackPx_V0nc");
1541  SG::AuxElement::Decorator< std::vector<float> > trk_pyDeco("TrackPy_V0nc");
1542  SG::AuxElement::Decorator< std::vector<float> > trk_pzDeco("TrackPz_V0nc");
1543 
1544  chi2_V1_decor(*cascadeVertices[1]) = ChiSquared.isAvailable(*disVtx) ? ChiSquared(*disVtx) : 999999;
1545  ndof_V1_decor(*cascadeVertices[1]) = nDoF.isAvailable(*disVtx) ? nDoF(*disVtx) : 1;
1546  chi2_V0_decor(*cascadeVertices[0]) = V0vtx->chiSquared();
1547  ndof_V0_decor(*cascadeVertices[0]) = V0vtx->numberDoF();
1548  if(V0==LAMBDA) type_V0_decor(*cascadeVertices[0]) = "Lambda";
1549  else if(V0==LAMBDABAR) type_V0_decor(*cascadeVertices[0]) = "Lambdabar";
1550  else if(V0==KS) type_V0_decor(*cascadeVertices[0]) = "Ks";
1551  mDec_gfit(*cascadeVertices[0]) = mAcc_gfit.isAvailable(*V0vtx) ? mAcc_gfit(*V0vtx) : 0;
1552  mDec_gmass(*cascadeVertices[0]) = mAcc_gmass.isAvailable(*V0vtx) ? mAcc_gmass(*V0vtx) : -1;
1553  mDec_gmasserr(*cascadeVertices[0]) = mAcc_gmasserr.isAvailable(*V0vtx) ? mAcc_gmasserr(*V0vtx) : -1;
1554  mDec_gchisq(*cascadeVertices[0]) = mAcc_gchisq.isAvailable(*V0vtx) ? mAcc_gchisq(*V0vtx) : 999999;
1555  mDec_gndof(*cascadeVertices[0]) = mAcc_gndof.isAvailable(*V0vtx) ? mAcc_gndof(*V0vtx) : 0;
1556  mDec_gprob(*cascadeVertices[0]) = mAcc_gprob.isAvailable(*V0vtx) ? mAcc_gprob(*V0vtx) : -1;
1557  trk_px.clear(); trk_py.clear(); trk_pz.clear();
1558  if(trk_pxAcc.isAvailable(*V0vtx)) trk_px = trk_pxAcc(*V0vtx);
1559  if(trk_pyAcc.isAvailable(*V0vtx)) trk_py = trk_pyAcc(*V0vtx);
1560  if(trk_pzAcc.isAvailable(*V0vtx)) trk_pz = trk_pzAcc(*V0vtx);
1561  trk_pxDeco(*cascadeVertices[0]) = trk_px;
1562  trk_pyDeco(*cascadeVertices[0]) = trk_py;
1563  trk_pzDeco(*cascadeVertices[0]) = trk_pz;
1564 
1565  result = fit_result.release();
1566  }
1567  }
1568 
1569  return result;
1570  }
1571 
1572  template<size_t NTracks>
1574  for (const xAOD::Vertex* v1 : *cont) {
1575  assert(v1->nTrackParticles() == NTracks);
1576  std::array<const xAOD::TrackParticle*, NTracks> a1;
1577  std::array<const xAOD::TrackParticle*, NTracks> a2;
1578  for(size_t i=0; i<NTracks; i++){
1579  a1[i] = v1->trackParticle(i);
1580  a2[i] = v->trackParticle(i);
1581  }
1582  std::sort(a1.begin(), a1.end());
1583  std::sort(a2.begin(), a2.end());
1584  if(a1 == a2) return v1;
1585  }
1586  return nullptr;
1587  }
1588 }
DerivationFramework::JpsiXPlusDisplaced::m_vertexJXHypoNames
std::vector< std::string > m_vertexJXHypoNames
Definition: JpsiXPlusDisplaced.h:53
DerivationFramework::JpsiXPlusDisplaced::FindVertex
const xAOD::Vertex * FindVertex(const xAOD::VertexContainer *cont, const xAOD::Vertex *v) const
Definition: JpsiXPlusDisplaced.cxx:1573
DerivationFramework::JpsiXPlusDisplaced::addBranches
virtual StatusCode addBranches() const override
Pass the thinning service
Definition: JpsiXPlusDisplaced.cxx:763
xAOD::BPhysHypoHelper::setMass
bool setMass(const float val)
Set given invariant mass and its error.
Definition: BPhysHypoHelper.cxx:49
DerivationFramework::JpsiXPlusDisplaced::m_trkSelector
ToolHandle< Trk::ITrackSelectorTool > m_trkSelector
Definition: JpsiXPlusDisplaced.h:125
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
DerivationFramework::JpsiXPlusDisplaced::m_jxDaug2MassHypo
double m_jxDaug2MassHypo
Definition: JpsiXPlusDisplaced.h:87
Trk::VxSecVertexInfo::setSVOwnership
void setSVOwnership(bool Ownership)
Definition: VxSecVertexInfo.h:118
RecVertex.h
DerivationFramework::JpsiXPlusDisplaced::m_mass_Bpm
double m_mass_Bpm
Definition: JpsiXPlusDisplaced.h:141
Trk::py
@ py
Definition: ParamDefs.h:66
V0Tools.h
DerivationFramework::JpsiXPlusDisplaced::m_jxDaug3MassHypo
double m_jxDaug3MassHypo
Definition: JpsiXPlusDisplaced.h:88
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
DerivationFramework::JpsiXPlusDisplaced::m_ptTRT
double m_ptTRT
Definition: JpsiXPlusDisplaced.h:112
DerivationFramework::JpsiXPlusDisplaced::m_mass_e
double m_mass_e
Definition: JpsiXPlusDisplaced.h:134
DerivationFramework::JpsiXPlusDisplaced::m_MassUpper
double m_MassUpper
Definition: JpsiXPlusDisplaced.h:84
DerivationFramework::JpsiXPlusDisplaced::m_iVertexFitter
ToolHandle< Trk::TrkVKalVrtFitter > m_iVertexFitter
Definition: JpsiXPlusDisplaced.h:119
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
xAOD::BPhysHelper
Definition: BPhysHelper.h:71
Trk::VxCascadeInfo
Definition: VxCascadeInfo.h:75
DerivationFramework::JpsiXPlusDisplaced::m_extraTrkMinPt
double m_extraTrkMinPt
Definition: JpsiXPlusDisplaced.h:93
xAOD::BPhysHelper::nRefTrks
int nRefTrks()
Returns number of stored refitted track momenta.
Definition: BPhysHelper.cxx:115
DerivationFramework::JpsiXPlusDisplaced::m_iV0Fitter
ToolHandle< Trk::TrkV0VertexFitter > m_iV0Fitter
Definition: JpsiXPlusDisplaced.h:120
DerivationFramework::JpsiXPlusDisplaced::m_vertexV0ContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexV0ContainerKey
Definition: JpsiXPlusDisplaced.h:51
Trk::VertexID
int VertexID
Definition: IVertexCascadeFitter.h:23
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
JpsiXPlusDisplaced.h
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
VertexPointEstimator.h
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
DerivationFramework::JpsiXPlusDisplaced::m_constrJpsi
bool m_constrJpsi
Definition: JpsiXPlusDisplaced.h:101
DerivationFramework::JpsiXPlusDisplaced::m_DoVertexType
int m_DoVertexType
Definition: JpsiXPlusDisplaced.h:132
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
DerivationFramework::JpsiXPlusDisplaced::m_doV0Enum
bool m_doV0Enum
Definition: JpsiXPlusDisplaced.h:76
DerivationFramework::JpsiXPlusDisplaced::m_maxMainVCandidates
unsigned int m_maxMainVCandidates
Definition: JpsiXPlusDisplaced.h:117
DerivationFramework::JpsiXPlusDisplaced::m_d0_cut
double m_d0_cut
Definition: JpsiXPlusDisplaced.h:113
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
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
xAOD::VxType::V0Vtx
@ V0Vtx
Vertex from V0 decay.
Definition: TrackingPrimitives.h:575
DerivationFramework::JpsiXPlusDisplaced::m_mass_mu
double m_mass_mu
Definition: JpsiXPlusDisplaced.h:135
DerivationFramework::JpsiXPlusDisplaced::LAMBDA
@ LAMBDA
Definition: JpsiXPlusDisplaced.h:40
Trk::VxSecVertexInfo::vertices
const std::vector< xAOD::Vertex * > & vertices() const
Definition: VxSecVertexInfo.cxx:100
DerivationFramework::JpsiXPlusDisplaced::m_massDisV
double m_massDisV
Definition: JpsiXPlusDisplaced.h:97
xAOD::TrackParticle_v1::summaryValue
bool summaryValue(uint8_t &value, const SummaryType &information) const
Accessor for TrackSummary values.
Definition: TrackParticle_v1.cxx:736
DerivationFramework::JpsiXPlusDisplaced::m_PV_minNTracks
size_t m_PV_minNTracks
Definition: JpsiXPlusDisplaced.h:131
skel.it
it
Definition: skel.GENtoEVGEN.py:423
DerivationFramework::JpsiXPlusDisplaced::m_jxDaug4MassHypo
double m_jxDaug4MassHypo
Definition: JpsiXPlusDisplaced.h:89
ParticleTest.tp
tp
Definition: ParticleTest.py:25
DerivationFramework::JpsiXPlusDisplaced::m_mass_pion
double m_mass_pion
Definition: JpsiXPlusDisplaced.h:136
DerivationFramework::JpsiXPlusDisplaced::m_jxDaug1MassHypo
double m_jxDaug1MassHypo
Definition: JpsiXPlusDisplaced.h:86
DataVector::cend
const_iterator cend() const noexcept
Return a const_iterator pointing past the end of the collection.
xAOD::numberOfPixelHits
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
Definition: TrackingPrimitives.h:259
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
DerivationFramework::JpsiXPlusDisplaced::m_chi2cut
double m_chi2cut
Definition: JpsiXPlusDisplaced.h:110
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
DerivationFramework::JpsiXPlusDisplaced::m_massMainV
double m_massMainV
Definition: JpsiXPlusDisplaced.h:99
Trk::VxCascadeInfo::nDoF
int nDoF() const
Definition: VxCascadeInfo.h:133
DerivationFramework::JpsiXPlusDisplaced::m_chi2cut_DisV
double m_chi2cut_DisV
Definition: JpsiXPlusDisplaced.h:109
Trk::pz
@ pz
global momentum (cartesian)
Definition: ParamDefs.h:67
DerivationFramework::JpsiXPlusDisplaced::m_mass_Ks
double m_mass_Ks
Definition: JpsiXPlusDisplaced.h:139
DerivationFramework::JpsiXPlusDisplaced::m_v0VtxOutputKey
SG::WriteHandleKey< xAOD::VertexContainer > m_v0VtxOutputKey
Definition: JpsiXPlusDisplaced.h:57
TrkVKalVrtFitter.h
DerivationFramework::JpsiXPlusDisplaced::m_vertexV0HypoNames
std::vector< std::string > m_vertexV0HypoNames
Definition: JpsiXPlusDisplaced.h:54
Rec::nDoF
double nDoF(const Trk::Track &track)
Definition: OutwardsCombinedMuonTrackBuilder.cxx:31
runBeamSpotCalibration.helper
helper
Definition: runBeamSpotCalibration.py:112
DerivationFramework::JpsiXPlusDisplaced::m_trackToVertexTool
ToolHandle< Reco::ITrackToVertex > m_trackToVertexTool
Definition: JpsiXPlusDisplaced.h:124
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
DerivationFramework::JpsiXPlusDisplaced::m_constrMainV
bool m_constrMainV
Definition: JpsiXPlusDisplaced.h:105
DerivationFramework::JpsiXPlusDisplaced::m_vertexDisVContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexDisVContainerKey
Definition: JpsiXPlusDisplaced.h:52
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
V0Container
Definition: V0Container.h:22
xAOD::BPhysHypoHelper
Definition: BPhysHypoHelper.h:73
DerivationFramework::BPhysPVCascadeTools::SetVectorInfo
static void SetVectorInfo(xAOD::BPhysHelper &, const Trk::VxCascadeInfo *)
Definition: BPhysPVCascadeTools.cxx:424
BPHYS_CHECK
#define BPHYS_CHECK(EXP)
Useful CHECK macro.
Definition: BPhysHelper.h:738
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
DerivationFramework::JpsiXPlusDisplaced::m_jpsiMassUpper
double m_jpsiMassUpper
Definition: JpsiXPlusDisplaced.h:69
SG::WriteHandleKey
Property holding a SG store/key/clid from which a WriteHandle is made.
Definition: StoreGate/StoreGate/WriteHandleKey.h:40
DerivationFramework::JpsiXPlusDisplaced::m_disVDaug_num
int m_disVDaug_num
Definition: JpsiXPlusDisplaced.h:90
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:58
lumiFormat.i
int i
Definition: lumiFormat.py:92
xAOD::BPhysHypoHelper::setPass
bool setPass(bool passVal)
get the pass flag for this hypothesis
Definition: BPhysHypoHelper.cxx:364
DerivationFramework::JpsiXPlusDisplaced::m_refitV0
bool m_refitV0
Definition: JpsiXPlusDisplaced.h:56
DerivationFramework::JpsiXPlusDisplaced::m_V0Tools
ToolHandle< Trk::V0Tools > m_V0Tools
Definition: JpsiXPlusDisplaced.h:123
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.
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
BPhysHypoHelper.h
: B-physcis xAOD helpers.
DerivationFramework::JpsiXPlusDisplaced::m_disVDaug3MassHypo
double m_disVDaug3MassHypo
Definition: JpsiXPlusDisplaced.h:91
DerivationFramework::JpsiXPlusDisplaced::UNKNOWN
@ UNKNOWN
Definition: JpsiXPlusDisplaced.h:40
DerivationFramework::JpsiXPlusDisplaced::m_VxPrimaryCandidateName
SG::ReadHandleKey< xAOD::VertexContainer > m_VxPrimaryCandidateName
Definition: JpsiXPlusDisplaced.h:60
DerivationFramework::JpsiXPlusDisplaced::m_v0TrkSelector
ToolHandle< Trk::ITrackSelectorTool > m_v0TrkSelector
Definition: JpsiXPlusDisplaced.h:126
Trk::VxCascadeInfo::fitChi2
double fitChi2() const
Definition: VxCascadeInfo.h:134
DerivationFramework::JpsiXPlusDisplaced::m_constrJX
bool m_constrJX
Definition: JpsiXPlusDisplaced.h:100
TRT::Track::d0
@ d0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:62
Trk::px
@ px
Definition: ParamDefs.h:65
test_pyathena.parent
parent
Definition: test_pyathena.py:15
DerivationFramework::BPhysPVCascadeTools::PrepareVertexLinks
static void PrepareVertexLinks(Trk::VxCascadeInfo *result, const xAOD::TrackParticleContainer *importedTrackCollection)
Definition: BPhysPVCascadeTools.cxx:204
DerivationFramework::JpsiXPlusDisplaced::m_beamSpotDecoKeys
SG::ReadDecorHandleKeyArray< xAOD::EventInfo > m_beamSpotDecoKeys
Definition: JpsiXPlusDisplaced.h:63
MUON
xAOD::Muon MUON
D3PD INCLUDES.
Definition: TileCellFillerTool.h:37
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
DerivationFramework::JpsiXPlusDisplaced::m_massX
double m_massX
Definition: JpsiXPlusDisplaced.h:96
DerivationFramework::JpsiXPlusDisplaced::m_chi2cut_JX
double m_chi2cut_JX
Definition: JpsiXPlusDisplaced.h:107
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
DerivationFramework::JpsiXPlusDisplaced::fitMainVtx
Trk::VxCascadeInfo * fitMainVtx(const xAOD::Vertex *JXvtx, std::vector< double > &massesJX, const xAOD::Vertex *V0vtx, const V0Enum V0, const xAOD::TrackParticleContainer *trackContainer) const
Definition: JpsiXPlusDisplaced.cxx:1061
xAOD::Vertex_v1::clearTracks
void clearTracks()
Remove all tracks from the vertex.
Definition: Vertex_v1.cxx:331
Trk::ParametersBase
Definition: ParametersBase.h:55
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::JpsiXPlusDisplaced::m_V0MassUpper
double m_V0MassUpper
Definition: JpsiXPlusDisplaced.h:74
DerivationFramework::VertexLink
ElementLink< xAOD::VertexContainer > VertexLink
Definition: Cascade3Plus1.cxx:23
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
DerivationFramework::JpsiXPlusDisplaced::m_chi2cut_V0
double m_chi2cut_V0
Definition: JpsiXPlusDisplaced.h:108
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
DerivationFramework::JpsiXPlusDisplaced::m_diTrackMassUpper
double m_diTrackMassUpper
Definition: JpsiXPlusDisplaced.h:71
BPhysPVCascadeTools.h
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
DerivationFramework::JpsiXPlusDisplaced::m_diTrackMassLower
double m_diTrackMassLower
Definition: JpsiXPlusDisplaced.h:70
DerivationFramework::JpsiXPlusDisplaced::m_MassLower
double m_MassLower
Definition: JpsiXPlusDisplaced.h:83
DerivationFramework::JpsiXPlusDisplaced::m_constrX
bool m_constrX
Definition: JpsiXPlusDisplaced.h:102
DerivationFramework::JpsiXPlusDisplaced::m_useTRT
bool m_useTRT
Definition: JpsiXPlusDisplaced.h:111
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
Trk::d0
@ d0
Definition: ParamDefs.h:69
pmontree.opt
opt
Definition: pmontree.py:16
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
DerivationFramework::BPhysPVCascadeTools
Definition: BPhysPVCascadeTools.h:34
DerivationFramework::JpsiXPlusDisplaced::m_refitPV
bool m_refitPV
Definition: JpsiXPlusDisplaced.h:129
DerivationFramework::JpsiXPlusDisplaced::m_maxJXCandidates
unsigned int m_maxJXCandidates
Definition: JpsiXPlusDisplaced.h:114
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DerivationFramework::JpsiXPlusDisplaced::KS
@ KS
Definition: JpsiXPlusDisplaced.h:40
DerivationFramework::JpsiXPlusDisplaced::m_lxyV0_cut
double m_lxyV0_cut
Definition: JpsiXPlusDisplaced.h:75
CascadeTools.h
DerivationFramework::JpsiXPlusDisplaced::m_CascadeTools
ToolHandle< DerivationFramework::CascadeTools > m_CascadeTools
Definition: JpsiXPlusDisplaced.h:127
DerivationFramework::JpsiXPlusDisplaced::m_jxMassUpper
double m_jxMassUpper
Definition: JpsiXPlusDisplaced.h:67
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::VxCascadeInfo::getParticleMoms
const std::vector< std::vector< TLorentzVector > > & getParticleMoms() const
Definition: VxCascadeInfo.h:131
DerivationFramework::JpsiXPlusDisplaced::m_hypoName
std::string m_hypoName
Definition: JpsiXPlusDisplaced.h:64
DerivationFramework::JpsiXPlusDisplaced::d0Pass
bool d0Pass(const xAOD::TrackParticle *track, const xAOD::Vertex *PV, const Amg::Vector3D &beamspot) const
Definition: JpsiXPlusDisplaced.cxx:983
DerivationFramework::JpsiXPlusDisplaced::m_disVtxOutputKey
SG::WriteHandleKey< xAOD::VertexContainer > m_disVtxOutputKey
Definition: JpsiXPlusDisplaced.h:58
IVertexFitter.h
DerivationFramework::JpsiXPlusDisplaced::fitDisVtx
xAOD::Vertex * fitDisVtx(const xAOD::Vertex *V0vtx, const V0Enum V0, const xAOD::TrackParticle *track3, const xAOD::TrackParticleContainer *trackContainer) const
Definition: JpsiXPlusDisplaced.cxx:1003
DerivationFramework::JpsiXPlusDisplaced::m_chi2cut_gamma
double m_chi2cut_gamma
Definition: JpsiXPlusDisplaced.h:79
DerivationFramework::JpsiXPlusDisplaced::m_mass_Lambda
double m_mass_Lambda
Definition: JpsiXPlusDisplaced.h:138
VxCascadeInfo.h
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.
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
python.PyAthena.v
v
Definition: PyAthena.py:157
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
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
DerivationFramework::VertexLinkVector
std::vector< VertexLink > VertexLinkVector
Definition: Cascade3Plus1.cxx:24
DerivationFramework::JpsiXPlusDisplaced::JpsiXPlusDisplaced
JpsiXPlusDisplaced(const std::string &type, const std::string &name, const IInterface *parent)
Definition: JpsiXPlusDisplaced.cxx:26
a
TList * a
Definition: liststreamerinfos.cxx:10
DerivationFramework::JpsiXPlusDisplaced::m_constrDisV
bool m_constrDisV
Definition: JpsiXPlusDisplaced.h:103
xAOD::Vertex_v1::chiSquared
float chiSquared() const
Returns the of the vertex fit as float.
DerivationFramework::JpsiXPlusDisplaced::m_TrkParticleCollection
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_TrkParticleCollection
Definition: JpsiXPlusDisplaced.h:59
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
xAOD::BPhysHelper::refTrk
TVector3 refTrk(const size_t index)
Returns i-th refitted track 3-momentum.
Definition: BPhysHelper.cxx:126
DerivationFramework::JpsiXPlusDisplaced::initialize
virtual StatusCode initialize() override
Definition: JpsiXPlusDisplaced.cxx:181
DerivationFramework::JpsiXPlusDisplaced::m_pvRefitter
ToolHandle< Analysis::PrimaryVertexRefitter > m_pvRefitter
Definition: JpsiXPlusDisplaced.h:122
DerivationFramework::JpsiXPlusDisplaced::m_mass_Xi
double m_mass_Xi
Definition: JpsiXPlusDisplaced.h:140
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::JpsiXPlusDisplaced::m_DisplacedMassUpper
double m_DisplacedMassUpper
Definition: JpsiXPlusDisplaced.h:81
V0Container
V0Container
Definition: TrkEventTPCnv.cxx:157
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DerivationFramework::JpsiXPlusDisplaced::performSearch
StatusCode performSearch(std::vector< Trk::VxCascadeInfo * > *cascadeinfoContainer, xAOD::VertexContainer *V0OutputContainer, xAOD::VertexContainer *disVtxOutputContainer) const
Definition: JpsiXPlusDisplaced.cxx:266
DerivationFramework::JpsiXPlusDisplaced::m_lxyDisV_cut
double m_lxyDisV_cut
Definition: JpsiXPlusDisplaced.h:82
DerivationFramework::JpsiXPlusDisplaced::m_eventInfo_key
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo_key
Definition: JpsiXPlusDisplaced.h:62
DerivationFramework::JpsiXPlusDisplaced::m_cascadeOutputKeys
SG::WriteHandleKeyArray< xAOD::VertexContainer > m_cascadeOutputKeys
Definition: JpsiXPlusDisplaced.h:55
DerivationFramework::JpsiXPlusDisplaced::m_constrV0
bool m_constrV0
Definition: JpsiXPlusDisplaced.h:104
DerivationFramework::JpsiXPlusDisplaced::m_massV0
double m_massV0
Definition: JpsiXPlusDisplaced.h:98
DerivationFramework::JpsiXPlusDisplaced::m_JXSubVtx
bool m_JXSubVtx
Definition: JpsiXPlusDisplaced.h:106
DerivationFramework::JpsiXPlusDisplaced::m_PV_max
int m_PV_max
Definition: JpsiXPlusDisplaced.h:130
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
xAOD::numberOfSCTHits
@ numberOfSCTHits
number of hits in SCT [unit8_t].
Definition: TrackingPrimitives.h:268
DerivationFramework::JpsiXPlusDisplaced::LAMBDABAR
@ LAMBDABAR
Definition: JpsiXPlusDisplaced.h:40
SG::ConstAccessor< T, AuxAllocator_t< T > >::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
DerivationFramework::JpsiXPlusDisplaced::m_minMass_gamma
double m_minMass_gamma
Definition: JpsiXPlusDisplaced.h:78
DataVector::cbegin
const_iterator cbegin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
DerivationFramework::JpsiXPlusDisplaced::m_DisplacedMassLower
double m_DisplacedMassLower
Definition: JpsiXPlusDisplaced.h:80
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
DerivationFramework::JpsiXPlusDisplaced::m_decorV0P
bool m_decorV0P
Definition: JpsiXPlusDisplaced.h:77
DerivationFramework::JpsiXPlusDisplaced::m_extraTrkMassHypo
double m_extraTrkMassHypo
Definition: JpsiXPlusDisplaced.h:92
xAOD::Vertex_v1::vxTrackAtVertex
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
Definition: Vertex_v1.cxx:181
AthAlgTool
Definition: AthAlgTool.h:26
DerivationFramework::JpsiXPlusDisplaced::m_jxDaug_num
int m_jxDaug_num
Definition: JpsiXPlusDisplaced.h:85
DerivationFramework::JpsiXPlusDisplaced::m_V0Hypothesis
std::string m_V0Hypothesis
Definition: JpsiXPlusDisplaced.h:72
SG::AllowEmpty
@ AllowEmpty
Definition: StoreGate/StoreGate/VarHandleKey.h:30
DerivationFramework::JpsiXPlusDisplaced::m_iGammaFitter
ToolHandle< Trk::IVertexFitter > m_iGammaFitter
Definition: JpsiXPlusDisplaced.h:121
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
DerivationFramework::JpsiXPlusDisplaced::m_vertexJXContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexJXContainerKey
Definition: JpsiXPlusDisplaced.h:50
HepMCHelpers.h
xAOD::BPhysHypoHelper::setMassErr
bool setMassErr(const float val)
invariant mass error
Definition: BPhysHypoHelper.cxx:54
DerivationFramework::JpsiXPlusDisplaced::V0Enum
V0Enum
Definition: JpsiXPlusDisplaced.h:40
DerivationFramework::JpsiXPlusDisplaced::m_massJX
double m_massJX
Definition: JpsiXPlusDisplaced.h:94
DerivationFramework::JpsiXPlusDisplaced::m_maxV0Candidates
unsigned int m_maxV0Candidates
Definition: JpsiXPlusDisplaced.h:115
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
VertexAuxContainer.h
xAOD::TrackParticle_v1::phi
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .)
DerivationFramework::JpsiXPlusDisplaced::m_refPVContainerName
SG::WriteHandleKey< xAOD::VertexContainer > m_refPVContainerName
Definition: JpsiXPlusDisplaced.h:61
DerivationFramework::JpsiXPlusDisplaced::m_massJpsi
double m_massJpsi
Definition: JpsiXPlusDisplaced.h:95
DerivationFramework::JpsiXPlusDisplaced::m_mass_proton
double m_mass_proton
Definition: JpsiXPlusDisplaced.h:137
DerivationFramework::JpsiXPlusDisplaced::m_maxDisVCandidates
unsigned int m_maxDisVCandidates
Definition: JpsiXPlusDisplaced.h:116
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37