ATLAS Offline Software
Loading...
Searching...
No Matches
JpsiPlusV0Cascade.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "JpsiPlusV0Cascade.h"
10#include "BPhysPVCascadeTools.h"
14#include <algorithm>
15#include "HepPDT/ParticleDataTable.hh"
18
19namespace DerivationFramework {
20 typedef ElementLink<xAOD::VertexContainer> VertexLink;
21 typedef std::vector<VertexLink> VertexLinkVector;
22 typedef std::vector<const xAOD::TrackParticle*> TrackBag;
23
24
25 JpsiPlusV0Cascade::JpsiPlusV0Cascade(const std::string& t, const std::string& n, const IInterface* p) : base_class(t,n,p)
26 {
27 }
28
29
31
32
34 ATH_CHECK(m_eventInfo_key.initialize());
35 ATH_CHECK(m_vertexContainerKey.initialize());
37 ATH_CHECK(m_cascadeOutputsKeys.initialize());
41 ATH_CHECK(m_refPVContainerName.initialize());
42
43 // retrieving vertex Fitter
44 ATH_CHECK( m_iVertexFitter.retrieve() );
45 ATH_MSG_DEBUG("Retrieved tool " << m_iVertexFitter);
46
47 // retrieving the V0 tools
48 ATH_CHECK( m_V0Tools.retrieve() );
49 ATH_MSG_INFO("Retrieved tool " << m_V0Tools);
50
51 // retrieving the Cascade tools
52 ATH_CHECK( m_CascadeTools.retrieve() );
53 ATH_MSG_INFO("Retrieved tool " << m_CascadeTools);
54
55 ATH_CHECK( m_partPropSvc.retrieve() );
56 const HepPDT::ParticleDataTable* pdt = m_partPropSvc->PDT();
57
58 // retrieve particle masses
68 ATH_CHECK(m_RelinkContainers.initialize());
69
70 return StatusCode::SUCCESS;
71 }
72
73
74 StatusCode JpsiPlusV0Cascade::addBranches(const EventContext& ctx) const
75 {
76 std::vector<Trk::VxCascadeInfo*> cascadeinfoContainer;
77 constexpr int topoN = 2;
78 std::array<SG::WriteHandle<xAOD::VertexContainer>, topoN> Vtxwritehandles;
79 if (m_cascadeOutputsKeys.size() !=topoN) { ATH_MSG_FATAL("Incorrect number of VtxContainers"); return StatusCode::FAILURE; }
80
81 for (int i =0; i<topoN;i++) {
82 Vtxwritehandles[i] = SG::makeHandle(m_cascadeOutputsKeys[i], ctx);
83 ATH_CHECK( Vtxwritehandles[i].record (std::make_unique<xAOD::VertexContainer>(),
84 std::make_unique<xAOD::VertexAuxContainer>()) );
85 }
86
87 //----------------------------------------------------
88 // retrieve primary vertices
89 //----------------------------------------------------
91 if (!pvContainer.isValid()) {
92 ATH_MSG_ERROR("Failed to find xAOD::VertexContainer named " << m_VxPrimaryCandidateName.key() << " in EventStore.");
93 return StatusCode::FAILURE;
94 }
95 ATH_MSG_DEBUG("Found " << m_VxPrimaryCandidateName << " in StoreGate!");
96
97 if (pvContainer->size()==0){
98 ATH_MSG_WARNING("You have no primary vertices: " << pvContainer->size());
99 return StatusCode::RECOVERABLE;
100 }
101 const xAOD::Vertex * primaryVertex = (*pvContainer)[0];
102
103 //----------------------------------------------------
104 // Try to retrieve refitted primary vertices
105 //----------------------------------------------------
107 if (m_refitPV) {
108 // refitted PV container does not exist. Create a new one.
109 refPvContainer = SG::makeHandle(m_refPVContainerName, ctx);
110 ATH_CHECK(refPvContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
111 }
112
113 ATH_CHECK(performSearch(cascadeinfoContainer, ctx));
114
116 if(not evt.isValid()) ATH_MSG_ERROR("Cannot Retrieve " << m_eventInfo_key.key() );
117 BPhysPVCascadeTools helper(&(*m_CascadeTools), evt.cptr());
118 helper.SetMinNTracksInPV(m_PV_minNTracks);
119
120 // Decorators for the main vertex: chi2, ndf, pt and pt error, plus the V0 vertex variables
121 SG::AuxElement::Decorator<VertexLinkVector> CascadeLinksDecor("CascadeVertexLinks");
122 SG::AuxElement::Decorator<VertexLinkVector> JpsiLinksDecor("JpsiVertexLinks");
123 SG::AuxElement::Decorator<VertexLinkVector> V0LinksDecor("V0VertexLinks");
124 SG::AuxElement::Decorator<float> chi2_decor("ChiSquared");
125 SG::AuxElement::Decorator<float> ndof_decor("NumberDoF");
127 SG::AuxElement::Decorator<float> PtErr_decor("PtErr");
128 SG::AuxElement::Decorator<float> Mass_svdecor("V0_mass");
129 SG::AuxElement::Decorator<float> MassErr_svdecor("V0_massErr");
130 SG::AuxElement::Decorator<float> Pt_svdecor("V0_Pt");
131 SG::AuxElement::Decorator<float> PtErr_svdecor("V0_PtErr");
132 SG::AuxElement::Decorator<float> Lxy_svdecor("V0_Lxy");
133 SG::AuxElement::Decorator<float> LxyErr_svdecor("V0_LxyErr");
134 SG::AuxElement::Decorator<float> Tau_svdecor("V0_Tau");
135 SG::AuxElement::Decorator<float> TauErr_svdecor("V0_TauErr");
136
137 ATH_MSG_DEBUG("cascadeinfoContainer size " << cascadeinfoContainer.size());
138
139 // Get Jpsi container and identify the input Jpsi
141 if (!jpsiContainer.isValid()) {
142 ATH_MSG_ERROR("Failed to find xAOD::VertexContainer named " << m_vertexContainerKey.key() << " in EventStore.");
143 return StatusCode::FAILURE;
144 }
146 if (!v0Container.isValid()) {
147 ATH_MSG_ERROR("Failed to find xAOD::VertexContainer named " << m_vertexV0ContainerKey.key() << " in EventStore.");
148 return StatusCode::FAILURE;
149 }
150
151 for (Trk::VxCascadeInfo* x : cascadeinfoContainer) {
152 if(x==nullptr) {
153 ATH_MSG_ERROR("cascadeinfoContainer is null");
154 //x is dereferenced if we pass this
155 return StatusCode::FAILURE;
156 }
157
158 // the cascade fitter returns:
159 // std::vector<xAOD::Vertex*>, each xAOD::Vertex contains the refitted track parameters (perigee at the vertex position)
160 // vertices[iv] the links to the original TPs and a covariance of size 3+5*NTRK; the chi2 of the total fit
161 // is split between the cascade vertices as per track contribution
162 // std::vector< std::vector<TLorentzVector> >, each std::vector<TLorentzVector> contains the refitted momenta (TLorentzVector)
163 // momenta[iv][...] of all tracks in the corresponding vertex, including any pseudotracks (from cascade vertices)
164 // originating in this vertex; the masses are as assigned in the cascade fit
165 // std::vector<Amg::MatrixX>, the corresponding covariance matrices in momentum space
166 // covariance[iv]
167 // int nDoF, double Chi2
168 //
169 // the invariant mass, pt, lifetime etc. errors should be calculated using the covariance matrices in momentum space as these
170 // take into account the full track-track and track-vertex correlations
171 //
172 // in the case of Jpsi+V0: vertices[0] is the V0 vertex, vertices[1] is the B/Lambda_b(bar) vertex, containing the 2 Jpsi tracks.
173 // The covariance terms between the two vertices are not stored. In momentum space momenta[0] contains the 2 V0 tracks,
174 // their momenta add up to the momentum of the 3rd track in momenta[1], the first two being the Jpsi tracks
175
176 const std::vector<xAOD::Vertex*> &cascadeVertices = x->vertices();
177 if(cascadeVertices.size()!=topoN)
178 ATH_MSG_ERROR("Incorrect number of vertices");
179 if(cascadeVertices[0] == nullptr || cascadeVertices[1] == nullptr) ATH_MSG_ERROR("Error null vertex");
180 // Keep vertices (bear in mind that they come in reverse order!)
181 for(int i =0;i<topoN;i++) Vtxwritehandles[i]->push_back(cascadeVertices[i]);
182
183 x->setSVOwnership(false); // Prevent Container from deleting vertices
184 const auto mainVertex = cascadeVertices[1]; // this is the Bd (Bd, Lambda_b, Lambda_bbar) vertex
185 //const auto v0Vertex = cascadeVertices[0]; // this is the V0 (Kshort, Lambda, Lambdabar) vertex
186 const std::vector< std::vector<TLorentzVector> > &moms = x->getParticleMoms();
187
188 // Set links to cascade vertices
189 std::vector<const xAOD::Vertex*> verticestoLink;
190 verticestoLink.push_back(cascadeVertices[0]);
191 if(!Vtxwritehandles[1].isValid()) ATH_MSG_ERROR("Vtxwritehandles[1] is not valid");
192 if(!BPhysPVCascadeTools::LinkVertices(CascadeLinksDecor, verticestoLink, Vtxwritehandles[0].cptr(), cascadeVertices[1]))
193 ATH_MSG_ERROR("Error decorating with cascade vertices");
194
195 // Identify the input Jpsi
196 const xAOD::Vertex* jpsiVertex = BPhysPVCascadeTools::FindVertex<2>(jpsiContainer.cptr(), cascadeVertices[1]);
197 ATH_MSG_DEBUG("1 pt Jpsi tracks " << cascadeVertices[1]->trackParticle(0)->pt() << ", " << cascadeVertices[1]->trackParticle(1)->pt());
198 if (jpsiVertex) ATH_MSG_DEBUG("2 pt Jpsi tracks " << jpsiVertex->trackParticle(0)->pt() << ", " << jpsiVertex->trackParticle(1)->pt());
199
200 // Identify the input V0
201 const xAOD::Vertex* v0Vertex = BPhysPVCascadeTools::FindVertex<2>(v0Container.cptr(), cascadeVertices[0]);;
202 ATH_MSG_DEBUG("1 pt V0 tracks " << cascadeVertices[0]->trackParticle(0)->pt() << ", " << cascadeVertices[0]->trackParticle(1)->pt());
203 if (v0Vertex) ATH_MSG_DEBUG("2 pt V0 tracks " << v0Vertex->trackParticle(0)->pt() << ", " << v0Vertex->trackParticle(1)->pt());
204
205 // Set links to input vertices
206 std::vector<const xAOD::Vertex*> jpsiVerticestoLink;
207 if (jpsiVertex) jpsiVerticestoLink.push_back(jpsiVertex);
208 else ATH_MSG_WARNING("Could not find linking Jpsi");
209 if(!BPhysPVCascadeTools::LinkVertices(JpsiLinksDecor, jpsiVerticestoLink, jpsiContainer.cptr(), cascadeVertices[1]))
210 ATH_MSG_ERROR("Error decorating with Jpsi vertices");
211
212 std::vector<const xAOD::Vertex*> v0VerticestoLink;
213 if (v0Vertex) v0VerticestoLink.push_back(v0Vertex);
214 else ATH_MSG_WARNING("Could not find linking V0");
215 if(!BPhysPVCascadeTools::LinkVertices(V0LinksDecor, v0VerticestoLink, v0Container.cptr(), cascadeVertices[1]))
216 ATH_MSG_ERROR("Error decorating with V0 vertices");
217
218 double mass_v0 = m_mass_ks;
219 double mass_b = m_mass_b0;
220 double mass_track = MC::isElectron(m_jpsi_trk_pdg.value()) ? m_mass_electron : m_mass_muon;
221 std::vector<double> massesJpsi(2, mass_track);
222 std::vector<double> massesV0;
223 std::vector<double> Masses(2, mass_track);
224 if (m_v0_pid == 310) {
225 massesV0.push_back(m_mass_pion);
226 massesV0.push_back(m_mass_pion);
227 Masses.push_back(m_mass_ks);
228 } else if (m_v0_pid == 3122) {
229 massesV0.push_back(m_mass_proton);
230 massesV0.push_back(m_mass_pion);
231 Masses.push_back(m_mass_lambda);
232 mass_v0 = m_mass_lambda;
233 mass_b = m_mass_lambdaB;
234 } else if (m_v0_pid == -3122) {
235 massesV0.push_back(m_mass_pion);
236 massesV0.push_back(m_mass_proton);
237 Masses.push_back(m_mass_lambda);
238 mass_v0 = m_mass_lambda;
239 mass_b = m_mass_lambdaB;
240 }
241
242 // loop over candidates -- Don't apply PV_minNTracks requirement here
243 // because it may result in exclusion of the high-pt PV.
244 // get good PVs
245
246 xAOD::BPhysHypoHelper vtx(m_hypoName, mainVertex);
247
249
250
251 // Decorate main vertex
252 //
253 // 1.a) mass, mass error
254 BPHYS_CHECK( vtx.setMass(m_CascadeTools->invariantMass(moms[1])) );
255 BPHYS_CHECK( vtx.setMassErr(m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1])) );
256 // 1.b) pt and pT error (the default pt of mainVertex is != the pt of the full cascade fit!)
257 Pt_decor(*mainVertex) = m_CascadeTools->pT(moms[1]);
258 PtErr_decor(*mainVertex) = m_CascadeTools->pTError(moms[1],x->getCovariance()[1]);
259 // 1.c) chi2 and ndof (the default chi2 of mainVertex is != the chi2 of the full cascade fit!)
260 chi2_decor(*mainVertex) = x->fitChi2();
261 ndof_decor(*mainVertex) = x->nDoF();
262
263 xAOD::VertexContainer *refPVContainer{};
264 if (m_refitPV) { refPVContainer = refPvContainer.ptr(); }
265 ATH_CHECK(helper.FillCandwithRefittedVertices(m_refitPV, pvContainer.cptr(),
266 refPVContainer, &(*m_pvRefitter), m_PV_max, m_DoVertexType, x, 1, mass_b, vtx));
267
268
269 // 4) decorate the main vertex with V0 vertex mass, pt, lifetime and lxy values (plus errors)
270 // V0 points to the main vertex, so lifetime and lxy are w.r.t the main vertex
271 Mass_svdecor(*mainVertex) = m_CascadeTools->invariantMass(moms[0]);
272 MassErr_svdecor(*mainVertex) = m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0]);
273 Pt_svdecor(*mainVertex) = m_CascadeTools->pT(moms[0]);
274 PtErr_svdecor(*mainVertex) = m_CascadeTools->pTError(moms[0],x->getCovariance()[0]);
275 Lxy_svdecor(*mainVertex) = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[1]);
276 LxyErr_svdecor(*mainVertex) = m_CascadeTools->lxyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1]);
277 Tau_svdecor(*mainVertex) = m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[1]);
278 TauErr_svdecor(*mainVertex) = m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1]);
279
280 // Some checks in DEBUG mode
281 ATH_MSG_DEBUG("chi2 " << x->fitChi2()
282 << " chi2_1 " << m_V0Tools->chisq(cascadeVertices[0])
283 << " chi2_2 " << m_V0Tools->chisq(cascadeVertices[1])
284 << " vprob " << m_CascadeTools->vertexProbability(x->nDoF(),x->fitChi2()));
285 ATH_MSG_DEBUG("ndf " << x->nDoF() << " ndf_1 " << m_V0Tools->ndof(cascadeVertices[0]) << " ndf_2 " << m_V0Tools->ndof(cascadeVertices[1]));
286 ATH_MSG_DEBUG("V0Tools mass_v0 " << m_V0Tools->invariantMass(cascadeVertices[0],massesV0)
287 << " error " << m_V0Tools->invariantMassError(cascadeVertices[0],massesV0)
288 << " mass_J " << m_V0Tools->invariantMass(cascadeVertices[1],massesJpsi)
289 << " error " << m_V0Tools->invariantMassError(cascadeVertices[1],massesJpsi));
290 // masses and errors, using track masses assigned in the fit
291 double Mass_B = m_CascadeTools->invariantMass(moms[1]);
292 double Mass_V0 = m_CascadeTools->invariantMass(moms[0]);
293 double Mass_B_err = m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1]);
294 double Mass_V0_err = m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0]);
295 ATH_MSG_DEBUG("Mass_B " << Mass_B << " Mass_V0 " << Mass_V0);
296 ATH_MSG_DEBUG("Mass_B_err " << Mass_B_err << " Mass_V0_err " << Mass_V0_err);
297 double mprob_B = m_CascadeTools->massProbability(mass_b,Mass_B,Mass_B_err);
298 double mprob_V0 = m_CascadeTools->massProbability(mass_v0,Mass_V0,Mass_V0_err);
299 ATH_MSG_DEBUG("mprob_B " << mprob_B << " mprob_V0 " << mprob_V0);
300 // masses and errors, assigning user defined track masses
301 ATH_MSG_DEBUG("Mass_b " << m_CascadeTools->invariantMass(moms[1],Masses)
302 << " Mass_v0 " << m_CascadeTools->invariantMass(moms[0],massesV0));
303 ATH_MSG_DEBUG("Mass_b_err " << m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1],Masses)
304 << " Mass_v0_err " << m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0],massesV0));
305 ATH_MSG_DEBUG("pt_b " << m_CascadeTools->pT(moms[1])
306 << " pt_v " << m_CascadeTools->pT(moms[0])
307 << " pt_v0 " << m_V0Tools->pT(cascadeVertices[0]));
308 ATH_MSG_DEBUG("ptErr_b " << m_CascadeTools->pTError(moms[1],x->getCovariance()[1])
309 << " ptErr_v " << m_CascadeTools->pTError(moms[0],x->getCovariance()[0])
310 << " ptErr_v0 " << m_V0Tools->pTError(cascadeVertices[0]));
311 ATH_MSG_DEBUG("lxy_B " << m_V0Tools->lxy(cascadeVertices[1],primaryVertex) << " lxy_V " << m_V0Tools->lxy(cascadeVertices[0],cascadeVertices[1]));
312 ATH_MSG_DEBUG("lxy_b " << m_CascadeTools->lxy(moms[1],cascadeVertices[1],primaryVertex) << " lxy_v " << m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[1]));
313 ATH_MSG_DEBUG("lxyErr_b " << m_CascadeTools->lxyError(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex)
314 << " lxyErr_v " << m_CascadeTools->lxyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1])
315 << " lxyErr_v0 " << m_V0Tools->lxyError(cascadeVertices[0],cascadeVertices[1]));
316 ATH_MSG_DEBUG("tau_B " << m_CascadeTools->tau(moms[1],cascadeVertices[1],primaryVertex,mass_b)
317 << " tau_v0 " << m_V0Tools->tau(cascadeVertices[0],cascadeVertices[1],massesV0));
318 ATH_MSG_DEBUG("tau_b " << m_CascadeTools->tau(moms[1],cascadeVertices[1],primaryVertex)
319 << " tau_v " << m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[1])
320 << " tau_V " << m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[1],mass_v0));
321 ATH_MSG_DEBUG("tauErr_b " << m_CascadeTools->tauError(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex)
322 << " tauErr_v " << m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1])
323 << " tauErr_v0 " << m_V0Tools->tauError(cascadeVertices[0],cascadeVertices[1],massesV0));
324 ATH_MSG_DEBUG("TauErr_b " << m_CascadeTools->tauError(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex,mass_b)
325 << " TauErr_v " << m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1],mass_v0)
326 << " TauErr_v0 " << m_V0Tools->tauError(cascadeVertices[0],cascadeVertices[1],massesV0,mass_v0));
327
328 ATH_MSG_DEBUG("CascadeTools main vert wrt PV " << " CascadeTools SV " << " V0Tools SV");
329 ATH_MSG_DEBUG("a0z " << m_CascadeTools->a0z(moms[1],cascadeVertices[1],primaryVertex)
330 << ", " << m_CascadeTools->a0z(moms[0],cascadeVertices[0],cascadeVertices[1])
331 << ", " << m_V0Tools->a0z(cascadeVertices[0],cascadeVertices[1]));
332 ATH_MSG_DEBUG("a0zErr " << m_CascadeTools->a0zError(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex)
333 << ", " << m_CascadeTools->a0zError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1])
334 << ", " << m_V0Tools->a0zError(cascadeVertices[0],cascadeVertices[1]));
335 ATH_MSG_DEBUG("a0xy " << m_CascadeTools->a0xy(moms[1],cascadeVertices[1],primaryVertex)
336 << ", " << m_CascadeTools->a0xy(moms[0],cascadeVertices[0],cascadeVertices[1])
337 << ", " << m_V0Tools->a0xy(cascadeVertices[0],cascadeVertices[1]));
338 ATH_MSG_DEBUG("a0xyErr " << m_CascadeTools->a0xyError(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex)
339 << ", " << m_CascadeTools->a0xyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1])
340 << ", " << m_V0Tools->a0xyError(cascadeVertices[0],cascadeVertices[1]));
341 ATH_MSG_DEBUG("a0 " << m_CascadeTools->a0(moms[1],cascadeVertices[1],primaryVertex)
342 << ", " << m_CascadeTools->a0(moms[0],cascadeVertices[0],cascadeVertices[1])
343 << ", " << m_V0Tools->a0(cascadeVertices[0],cascadeVertices[1]));
344 ATH_MSG_DEBUG("a0Err " << m_CascadeTools->a0Error(moms[1],x->getCovariance()[1],cascadeVertices[1],primaryVertex)
345 << ", " << m_CascadeTools->a0Error(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[1])
346 << ", " << m_V0Tools->a0Error(cascadeVertices[0],cascadeVertices[1]));
347 ATH_MSG_DEBUG("x0 " << m_V0Tools->vtx(cascadeVertices[0]).x() << " y0 " << m_V0Tools->vtx(cascadeVertices[0]).y() << " z0 " << m_V0Tools->vtx(cascadeVertices[0]).z());
348 ATH_MSG_DEBUG("x1 " << m_V0Tools->vtx(cascadeVertices[1]).x() << " y1 " << m_V0Tools->vtx(cascadeVertices[1]).y() << " z1 " << m_V0Tools->vtx(cascadeVertices[1]).z());
349 ATH_MSG_DEBUG("X0 " << primaryVertex->x() << " Y0 " << primaryVertex->y() << " Z0 " << primaryVertex->z());
350 ATH_MSG_DEBUG("rxy0 " << m_V0Tools->rxy(cascadeVertices[0]) << " rxyErr0 " << m_V0Tools->rxyError(cascadeVertices[0]));
351 ATH_MSG_DEBUG("rxy1 " << m_V0Tools->rxy(cascadeVertices[1]) << " rxyErr1 " << m_V0Tools->rxyError(cascadeVertices[1]));
352 ATH_MSG_DEBUG("Rxy0 wrt PV " << m_V0Tools->rxy(cascadeVertices[0],primaryVertex) << " RxyErr0 wrt PV " << m_V0Tools->rxyError(cascadeVertices[0],primaryVertex));
353 ATH_MSG_DEBUG("Rxy1 wrt PV " << m_V0Tools->rxy(cascadeVertices[1],primaryVertex) << " RxyErr1 wrt PV " << m_V0Tools->rxyError(cascadeVertices[1],primaryVertex));
354 ATH_MSG_DEBUG("number of covariance matrices " << (x->getCovariance()).size());
355 } // loop over cascadeinfoContainer
356
357 // Deleting cascadeinfo since this won't be stored.
358 // Vertices have been kept in m_cascadeOutputs and should be owned by their container
359 for (auto x : cascadeinfoContainer) delete x;
360
361 return StatusCode::SUCCESS;
362 }
363
364
365 StatusCode JpsiPlusV0Cascade::performSearch(std::vector<Trk::VxCascadeInfo*>& cascadeinfoContainer, const EventContext& ctx) const
366 {
367 ATH_MSG_DEBUG( "JpsiPlusV0Cascade::performSearch" );
368
369 // Get TrackParticle containers (for setting links to the original tracks)
371 if (!jpsiTrackContainer.isValid()) {
372 ATH_MSG_ERROR("Failed to find xAOD::TrackParticleContainer named " << m_jpsiTrackContainerName.key() << " in EventStore.");
373 return StatusCode::FAILURE;
374 }
376 if (!v0TrackContainer.isValid()) {
377 ATH_MSG_ERROR("Failed to find xAOD::TrackParticleContainer named " << m_v0TrackContainerName.key() << " in EventStore.");
378 return StatusCode::FAILURE;
379 }
380
381 // Get Jpsi container - TODO might be cleaner to retrieve these once and pass to this method?
383 if (!jpsiContainer.isValid()) {
384 ATH_MSG_ERROR("Failed to find xAOD::VertexContainer named " << m_vertexContainerKey.key() << " in EventStore.");
385 return StatusCode::FAILURE;
386 }
388 if (!v0Container.isValid()) {
389 ATH_MSG_ERROR("Failed to find xAOD::VertexContainer named " << m_vertexV0ContainerKey.key() << " in EventStore.");
390 return StatusCode::FAILURE;
391 }
392
393 double mass_v0 = m_mass_ks;
394 double mass_tracks = MC::isElectron(m_jpsi_trk_pdg.value()) ? m_mass_electron : m_mass_muon;
395 std::vector<const xAOD::TrackParticle*> tracksJpsi;
396 std::vector<const xAOD::TrackParticle*> tracksV0;
397 std::vector<double> massesJpsi(2, mass_tracks);
398 std::vector<double> massesV0;
399 std::vector<double> Masses(2, mass_tracks);
400 if (m_v0_pid == 310) {
401 massesV0.push_back(m_mass_pion);
402 massesV0.push_back(m_mass_pion);
403 Masses.push_back(m_mass_ks);
404 } else if (m_v0_pid == 3122) {
405 massesV0.push_back(m_mass_proton);
406 massesV0.push_back(m_mass_pion);
407 mass_v0 = m_mass_lambda;
408 Masses.push_back(m_mass_lambda);
409 } else if (m_v0_pid == -3122) {
410 massesV0.push_back(m_mass_pion);
411 massesV0.push_back(m_mass_proton);
412 mass_v0 = m_mass_lambda;
413 Masses.push_back(m_mass_lambda);
414 }
415 std::vector<const xAOD::TrackParticleContainer*> trackCols;
416 for(const auto &str : m_RelinkContainers){
418 trackCols.push_back(handle.cptr());
419 }
420
421
422 for(auto jpsi : *jpsiContainer) { //Iterate over Jpsi vertices
423
424 size_t jpsiTrkNum = jpsi->nTrackParticles();
425 tracksJpsi.clear();
426 for( unsigned int it=0; it<jpsiTrkNum; it++) tracksJpsi.push_back(jpsi->trackParticle(it));
427
428 if (tracksJpsi.size() != 2 || massesJpsi.size() != 2 ) {
429 ATH_MSG_INFO("problems with Jpsi input");
430 }
431 double mass_Jpsi = m_V0Tools->invariantMass(jpsi,massesJpsi);
432 ATH_MSG_DEBUG("Jpsi mass " << mass_Jpsi);
433 if (mass_Jpsi < m_jpsiMassLower || mass_Jpsi > m_jpsiMassUpper) {
434 ATH_MSG_DEBUG(" Original Jpsi candidate rejected by the mass cut: mass = "
435 << mass_Jpsi << " != (" << m_jpsiMassLower << ", " << m_jpsiMassUpper << ")" );
436 continue;
437 }
438
439 for(auto v0 : *v0Container) { //Iterate over V0 vertices
440
441 size_t v0TrkNum = v0->nTrackParticles();
442 tracksV0.clear();
443 for( unsigned int it=0; it<v0TrkNum; it++) tracksV0.push_back(v0->trackParticle(it));
444 if (tracksV0.size() != 2 || massesV0.size() != 2 ) {
445 ATH_MSG_INFO("problems with V0 input");
446 }
447 double mass_V0 = m_V0Tools->invariantMass(v0,massesV0);
448 ATH_MSG_DEBUG("V0 mass " << mass_V0);
449 if (mass_V0 < m_V0MassLower || mass_V0 > m_V0MassUpper) {
450 ATH_MSG_DEBUG(" Original V0 candidate rejected by the mass cut: mass = "
451 << mass_V0 << " != (" << m_V0MassLower << ", " << m_V0MassUpper << ")" );
452 continue;
453 }
454 ATH_MSG_DEBUG("using tracks" << tracksJpsi[0] << ", " << tracksJpsi[1] << ", " << tracksV0[0] << ", " << tracksV0[1]);
455 if(!BPhysPVCascadeTools::uniqueCollection(tracksJpsi, tracksV0)) continue;
456
457 // Apply the user's settings to the fitter
458 // Reset
459 std::unique_ptr<Trk::IVKalState> state = m_iVertexFitter->makeState();
460 // Robustness
461 int robustness = 0;
462 m_iVertexFitter->setRobustness(robustness, *state);
463 // Build up the topology
464 // Vertex list
465 std::vector<Trk::VertexID> vrtList;
466 // V0 vertex
467 Trk::VertexID vID;
468 if (m_constrV0) {
469 vID = m_iVertexFitter->startVertex(tracksV0,massesV0,*state, mass_v0);
470 } else {
471 vID = m_iVertexFitter->startVertex(tracksV0,massesV0, *state);
472 }
473 vrtList.push_back(vID);
474 // B vertex including Jpsi
475 Trk::VertexID vID2 = m_iVertexFitter->nextVertex(tracksJpsi,massesJpsi,vrtList, *state);
476 if (m_constrJpsi) {
477 std::vector<Trk::VertexID> cnstV;
478 cnstV.clear();
479 if ( !m_iVertexFitter->addMassConstraint(vID2,tracksJpsi,cnstV,*state, m_mass_jpsi).isSuccess() ) {
480 ATH_MSG_WARNING("addMassConstraint failed");
481 //return StatusCode::FAILURE;
482 }
483 }
484 // Do the work
485 std::unique_ptr<Trk::VxCascadeInfo> result(m_iVertexFitter->fitCascade(*state));
486
487 if (result) {
488 // reset links to original tracks
489 if(trackCols.empty()) BPhysPVCascadeTools::PrepareVertexLinks(result.get(), v0TrackContainer.cptr());
490 else BPhysPVCascadeTools::PrepareVertexLinks(result.get(), trackCols);
491
492 ATH_MSG_DEBUG("storing tracks " << ((result->vertices())[0])->trackParticle(0) << ", "
493 << ((result->vertices())[0])->trackParticle(1) << ", "
494 << ((result->vertices())[1])->trackParticle(0) << ", "
495 << ((result->vertices())[1])->trackParticle(1));
496
497 // necessary to prevent memory leak
498 result->setSVOwnership(true);
499 const std::vector< std::vector<TLorentzVector> > &moms = result->getParticleMoms();
500 if(moms.size() < 2){
501 ATH_MSG_FATAL("Incorrect size " << __FILE__ << __LINE__ );
502 return StatusCode::FAILURE;
503 }
504 double mass = m_CascadeTools->invariantMass(moms[1]);
505 if (mass >= m_MassLower && mass <= m_MassUpper) {
506
507 cascadeinfoContainer.push_back(result.release());
508 } else {
509 ATH_MSG_DEBUG("Candidate rejected by the mass cut: mass = "
510 << mass << " != (" << m_MassLower << ", " << m_MassUpper << ")" );
511 }
512 }
513
514 } //Iterate over V0 vertices
515
516 } //Iterate over Jpsi vertices
517
518 ATH_MSG_DEBUG("cascadeinfoContainer size " << cascadeinfoContainer.size());
519
520 return StatusCode::SUCCESS;
521 }
522
523
524
525}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
#define BPHYS_CHECK(EXP)
Useful CHECK macro.
: B-physics xAOD helpers.
ATLAS-specific HepMC functions.
#define x
static bool uniqueCollection(const std::vector< const xAOD::TrackParticle * > &)
static bool LinkVertices(SG::AuxElement::Decorator< VertexLinkVector > &decor, const std::vector< const xAOD::Vertex * > &vertices, const xAOD::VertexContainer *vertexContainer, const xAOD::Vertex *vert)
static void PrepareVertexLinks(Trk::VxCascadeInfo *result, const xAOD::TrackParticleContainer *importedTrackCollection)
static double getParticleMass(const HepPDT::ParticleDataTable *pdt, int pdg)
static const xAOD::Vertex * FindVertex(const xAOD::VertexContainer *c, const xAOD::Vertex *v)
static void SetVectorInfo(xAOD::BPhysHelper &, const Trk::VxCascadeInfo *)
PublicToolHandle< Trk::TrkVKalVrtFitter > m_iVertexFitter
Gaudi::Property< double > m_V0MassUpper
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexContainerKey
SG::ReadHandleKey< xAOD::VertexContainer > m_VxPrimaryCandidateName
Name of primary vertex container.
ToolHandle< Analysis::PrimaryVertexRefitter > m_pvRefitter
PublicToolHandle< DerivationFramework::CascadeTools > m_CascadeTools
JpsiPlusV0Cascade(const std::string &t, const std::string &n, const IInterface *p)
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_jpsiTrackContainerName
virtual StatusCode addBranches(const EventContext &ctx) const override
Gaudi::Property< double > m_V0MassLower
SG::ReadHandleKeyArray< xAOD::TrackParticleContainer > m_RelinkContainers
PublicToolHandle< Trk::V0Tools > m_V0Tools
StatusCode performSearch(std::vector< Trk::VxCascadeInfo * > &cascadeinfoContainer, const EventContext &ctx) const
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexV0ContainerKey
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo_key
ServiceHandle< IPartPropSvc > m_partPropSvc
SG::WriteHandleKey< xAOD::VertexContainer > m_refPVContainerName
virtual StatusCode initialize() override
Gaudi::Property< size_t > m_PV_minNTracks
Gaudi::Property< double > m_jpsiMassUpper
Gaudi::Property< std::string > m_hypoName
name of the mass hypothesis.
Gaudi::Property< double > m_jpsiMassLower
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_v0TrackContainerName
SG::WriteHandleKeyArray< xAOD::VertexContainer > m_cascadeOutputsKeys
SG::Decorator< T, ALLOC > Decorator
Definition AuxElement.h:575
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
bool setMass(const float val)
Set given invariant mass and its error.
bool setMassErr(const float val)
invariant mass error
virtual double pt() const override final
The transverse momentum ( ) of the particle.
float z() const
Returns the z position.
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
float y() const
Returns the y position.
float x() const
Returns the x position.
THE reconstruction tool.
std::vector< const xAOD::TrackParticle * > TrackBag
ElementLink< xAOD::VertexContainer > VertexLink
std::vector< VertexLink > VertexLinkVector
static const int MUON
bool isElectron(const T &p)
static const int ELECTRON
static const int K0S
static const int LAMBDAB0
static const int PIPLUS
static const int JPSI
static const int B0
static const int LAMBDA0
static const int PROTON
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.