ATLAS Offline Software
Loading...
Searching...
No Matches
JpsiPlusDs1Cascade.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5// JpsiPlusDs1Cascade.cxx, (c) ATLAS Detector software
12#include "BPhysPVCascadeTools.h"
15#include <algorithm>
17
20
21namespace DerivationFramework {
22 typedef ElementLink<xAOD::VertexContainer> VertexLink;
23 typedef std::vector<VertexLink> VertexLinkVector;
24 typedef std::vector<const xAOD::TrackParticle*> TrackBag;
25
27
28 // retrieving vertex Fitter
29 ATH_CHECK( m_iVertexFitter.retrieve());
30
31 // retrieving the V0 tools
32 ATH_CHECK( m_V0Tools.retrieve());
33
34 // retrieving the Cascade tools
35 ATH_CHECK( m_CascadeTools.retrieve());
36
37 // Get the beam spot service
38 ATH_CHECK(m_eventInfo_key.initialize());
39
40 auto gendata = std::make_unique<GenData>();
41 if(m_mass_jpsi < 0. ) m_mass_jpsi = gendata->particleMass(MC::JPSI).value();
42 if(m_vtx0MassHypo < 0.) m_vtx0MassHypo = gendata->particleMass(MC::BCPLUS).value();
43 if(m_vtx1MassHypo < 0.) m_vtx1MassHypo = gendata->particleMass(MC::D0).value();
44 if(m_vtx2MassHypo < 0.) m_vtx2MassHypo = gendata->particleMass(MC::K0S).value();
45 if(m_vtx0Daug1MassHypo < 0.) m_vtx0Daug1MassHypo = gendata->particleMass(MC::MUON).value();
46 if(m_vtx0Daug2MassHypo < 0.) m_vtx0Daug2MassHypo = gendata->particleMass(MC::MUON).value();
47 if(m_vtx0Daug3MassHypo < 0.) m_vtx0Daug3MassHypo = gendata->particleMass(MC::PIPLUS).value();
48 if(m_vtx1Daug1MassHypo < 0.) m_vtx1Daug1MassHypo = gendata->particleMass(MC::PIPLUS).value();
49 if(m_vtx1Daug2MassHypo < 0.) m_vtx1Daug2MassHypo = gendata->particleMass(MC::KPLUS).value();
50 if(m_vtx2Daug1MassHypo < 0.) m_vtx2Daug1MassHypo = gendata->particleMass(MC::PIPLUS).value();
51 if(m_vtx2Daug2MassHypo < 0.) m_vtx2Daug2MassHypo = gendata->particleMass(MC::PIPLUS).value();
52
53 return StatusCode::SUCCESS;
54 }
55
56
57 StatusCode JpsiPlusDs1Cascade::addBranches(const EventContext& ctx) const
58 {
59 std::vector<Trk::VxCascadeInfo*> cascadeinfoContainer;
60 constexpr int topoN = 3;
61 std::array<xAOD::VertexContainer*, topoN> Vtxwritehandles;
62 std::array<xAOD::VertexAuxContainer*, topoN> Vtxwritehandlesaux;
63 if(m_cascadeOutputsKeys.size() !=topoN) { ATH_MSG_FATAL("Incorrect number of VtxContainers"); return StatusCode::FAILURE; }
64
65 for(int i =0; i<topoN;i++){
66 Vtxwritehandles[i] = new xAOD::VertexContainer();
67 Vtxwritehandlesaux[i] = new xAOD::VertexAuxContainer();
68 Vtxwritehandles[i]->setStore(Vtxwritehandlesaux[i]);
69 ATH_CHECK(evtStore()->record(Vtxwritehandles[i] , m_cascadeOutputsKeys[i] )); // FIXME Use Handles
70 ATH_CHECK(evtStore()->record(Vtxwritehandlesaux[i], m_cascadeOutputsKeys[i] + "Aux.")); // FIXME Use Handles
71 }
72
73 //----------------------------------------------------
74 // retrieve primary vertices
75 //----------------------------------------------------
76 const xAOD::Vertex * primaryVertex(nullptr);
77 const xAOD::VertexContainer *pvContainer(nullptr);
78 ATH_CHECK(evtStore()->retrieve(pvContainer, m_VxPrimaryCandidateName)); // FIXME Use Handles
79 ATH_MSG_DEBUG("Found " << m_VxPrimaryCandidateName << " in StoreGate!");
80
81 if (pvContainer->size()==0){
82 ATH_MSG_WARNING("You have no primary vertices: " << pvContainer->size());
83 return StatusCode::RECOVERABLE;
84 } else {
85 primaryVertex = (*pvContainer)[0];
86 }
87
88 //----------------------------------------------------
89 // Try to retrieve refitted primary vertices
90 //----------------------------------------------------
91 xAOD::VertexContainer* refPvContainer{};
92 xAOD::VertexAuxContainer* refPvAuxContainer{};
93 if (m_refitPV) {
95 // refitted PV container exists. Get it from the store gate
96 ATH_CHECK(evtStore()->retrieve(refPvContainer , m_refPVContainerName )); // FIXME Use Handles
97 ATH_CHECK(evtStore()->retrieve(refPvAuxContainer, m_refPVContainerName + "Aux.")); // FIXME Use Handles
98 } else {
99 // refitted PV container does not exist. Create a new one.
100 refPvContainer = new xAOD::VertexContainer;
101 refPvAuxContainer = new xAOD::VertexAuxContainer;
102 refPvContainer->setStore(refPvAuxContainer);
103 ATH_CHECK(evtStore()->record(refPvContainer , m_refPVContainerName)); // FIXME Use Handles
104 ATH_CHECK(evtStore()->record(refPvAuxContainer, m_refPVContainerName+"Aux.")); // FIXME Use Handles
105 }
106 }
107
108 ATH_CHECK(performSearch(&cascadeinfoContainer, ctx));
109
111 if(not evt.isValid()) ATH_MSG_ERROR("Cannot Retrieve " << m_eventInfo_key.key() );
112 BPhysPVCascadeTools helper(&(*m_CascadeTools), evt.cptr());
113 helper.SetMinNTracksInPV(m_PV_minNTracks);
114
115 // Decorators for the main vertex: chi2, ndf, pt and pt error, plus the D0, K0 vertex variables
116 SG::Decorator<VertexLinkVector> CascadeV1LinksDecor("CascadeVertex1Links");
117 SG::Decorator<VertexLinkVector> CascadeV2LinksDecor("CascadeVertex2Links");
118 SG::Decorator<VertexLinkVector> JpsipiLinksDecor("JpsipiVertexLinks");
119 SG::Decorator<VertexLinkVector> D0LinksDecor("D0VertexLinks");
120 SG::Decorator<VertexLinkVector> K0LinksDecor("K0VertexLinks");
121 SG::Decorator<float> chi2_decor("ChiSquared");
122 SG::Decorator<float> ndof_decor("NumberDoF");
123 SG::Decorator<float> Pt_decor("Pt");
124 SG::Decorator<float> PtErr_decor("PtErr");
125 SG::Decorator<float> Mass_svdecor("D0_mass");
126 SG::Decorator<float> MassErr_svdecor("D0_massErr");
127 SG::Decorator<float> Pt_svdecor("D0_Pt");
128 SG::Decorator<float> PtErr_svdecor("D0_PtErr");
129 SG::Decorator<float> Lxy_svdecor("D0_Lxy");
130 SG::Decorator<float> LxyErr_svdecor("D0_LxyErr");
131 SG::Decorator<float> Tau_svdecor("D0_Tau");
132 SG::Decorator<float> TauErr_svdecor("D0_TauErr");
133
134 SG::Decorator<float> Mass_sv2decor("K0_mass");
135 SG::Decorator<float> MassErr_sv2decor("K0_massErr");
136 SG::Decorator<float> Pt_sv2decor("K0_Pt");
137 SG::Decorator<float> PtErr_sv2decor("K0_PtErr");
138 SG::Decorator<float> Lxy_sv2decor("K0_Lxy");
139 SG::Decorator<float> LxyErr_sv2decor("K0_LxyErr");
140 SG::Decorator<float> Tau_sv2decor("K0_Tau");
141 SG::Decorator<float> TauErr_sv2decor("K0_TauErr");
142
143 SG::Decorator<float> MassJpsi_decor("Jpsi_mass");
144 SG::Decorator<float> MassPiD0_decor("PiD0_mass");
145 SG::Decorator<float> MassPiD0K0_decor("PiD0K0_mass");
146
147 SG::Decorator<float> MassMumu_decor("Mumu_mass");
148 SG::Decorator<float> MassKpi_svdecor("Kpi_mass");
149 SG::Decorator<float> MassPipi_sv2decor("Pipi_mass");
150
151 ATH_MSG_DEBUG("cascadeinfoContainer size " << cascadeinfoContainer.size());
152
153 // Get Jpsi+pi container and identify the input Jpsi+pi
154 const xAOD::VertexContainer *jpsipiContainer{};
155 ATH_CHECK(evtStore()->retrieve(jpsipiContainer , m_vertexContainerKey )); // FIXME Use Handles
156 // Get D0 container and identify the input D0
157 const xAOD::VertexContainer *d0Container{};
158 ATH_CHECK(evtStore()->retrieve(d0Container , m_vertexD0ContainerKey )); // FIXME Use Handles
159 // Get K0 container and identify the input K0
160 const xAOD::VertexContainer *k0Container{};
161 ATH_CHECK(evtStore()->retrieve(k0Container , m_vertexK0ContainerKey )); // FIXME Use Handles
162
163 for (Trk::VxCascadeInfo* x : cascadeinfoContainer) {
164 if(x==nullptr) {
165 ATH_MSG_ERROR("cascadeinfoContainer is null");
166 //x is dereferenced if we pass this
167 return StatusCode::FAILURE;
168 }
169
170 // the cascade fitter returns:
171 // std::vector<xAOD::Vertex*>, each xAOD::Vertex contains the refitted track parameters (perigee at the vertex position)
172 // vertices[iv] the links to the original TPs and a covariance of size 3+5*NTRK; the chi2 of the total fit
173 // is split between the cascade vertices as per track contribution
174 // std::vector< std::vector<TLorentzVector> >, each std::vector<TLorentzVector> contains the refitted momenta (TLorentzVector)
175 // momenta[iv][...] of all tracks in the corresponding vertex, including any pseudotracks (from cascade vertices)
176 // originating in this vertex; the masses are as assigned in the cascade fit
177 // std::vector<Amg::MatrixX>, the corresponding covariance matrices in momentum space
178 // covariance[iv]
179 // int nDoF, double Chi2
180 //
181 // the invariant mass, pt, lifetime etc. errors should be calculated using the covariance matrices in momentum space as these
182 // take into account the full track-track and track-vertex correlations
183 //
184 // 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.
185 // The covariance terms between the two vertices are not stored. In momentum space momenta[0] contains the 2 V0 tracks,
186 // their momenta add up to the momentum of the 3rd track in momenta[1], the first two being the Jpsi tracks
187
188 const std::vector<xAOD::Vertex*> &cascadeVertices = x->vertices();
189 if(cascadeVertices.size()!=topoN)
190 ATH_MSG_ERROR("Incorrect number of vertices");
191 if(cascadeVertices[0] == nullptr || cascadeVertices[1] == nullptr || cascadeVertices[2] == nullptr) ATH_MSG_ERROR("Error null vertex");
192 // Keep vertices (bear in mind that they come in reverse order!)
193 for(int i =0;i<topoN;i++) Vtxwritehandles[i]->push_back(cascadeVertices[i]);
194
195 x->setSVOwnership(false); // Prevent Container from deleting vertices
196 const auto mainVertex = cascadeVertices[2]; // this is the B_c+/- vertex
197 const std::vector< std::vector<TLorentzVector> > &moms = x->getParticleMoms();
198
199 // Set links to cascade vertices
200 std::vector<const xAOD::Vertex*> verticestoLink;
201 verticestoLink.push_back(cascadeVertices[0]);
202 //if(Vtxwritehandles[1] == nullptr) ATH_MSG_ERROR("Vtxwritehandles[1] is null");
203 if(Vtxwritehandles[2] == nullptr) ATH_MSG_ERROR("Vtxwritehandles[2] is null");
204 if(!BPhysPVCascadeTools::LinkVertices(CascadeV1LinksDecor, verticestoLink, Vtxwritehandles[0], cascadeVertices[2]))
205 ATH_MSG_ERROR("Error decorating with cascade vertices");
206
207 verticestoLink.clear();
208 verticestoLink.push_back(cascadeVertices[1]);
209 if(!BPhysPVCascadeTools::LinkVertices(CascadeV2LinksDecor, verticestoLink, Vtxwritehandles[1], cascadeVertices[2]))
210 ATH_MSG_ERROR("Error decorating with cascade vertices");
211
212 // Identify the input Jpsi+pi
213 const xAOD::Vertex* jpsipiVertex = BPhysPVCascadeTools::FindVertex<3>(jpsipiContainer, cascadeVertices[2]);
214 ATH_MSG_DEBUG("1 pt Jpsi+pi tracks " << cascadeVertices[2]->trackParticle(0)->pt() << ", " << cascadeVertices[2]->trackParticle(1)->pt() << ", " << cascadeVertices[2]->trackParticle(2)->pt());
215 if (jpsipiVertex) ATH_MSG_DEBUG("2 pt Jpsi+pi tracks " << jpsipiVertex->trackParticle(0)->pt() << ", " << jpsipiVertex->trackParticle(1)->pt() << ", " << jpsipiVertex->trackParticle(2)->pt());
216
217 // Identify the input D0
218 const xAOD::Vertex* d0Vertex = BPhysPVCascadeTools::FindVertex<2>(d0Container, cascadeVertices[1]);;
219 ATH_MSG_DEBUG("1 pt D0 tracks " << cascadeVertices[1]->trackParticle(0)->pt() << ", " << cascadeVertices[1]->trackParticle(1)->pt());
220 if (d0Vertex) ATH_MSG_DEBUG("2 pt D0 tracks " << d0Vertex->trackParticle(0)->pt() << ", " << d0Vertex->trackParticle(1)->pt());
221
222 // Identify the input K_S0
223 const xAOD::Vertex* k0Vertex = BPhysPVCascadeTools::FindVertex<2>(k0Container, cascadeVertices[0]);;
224 ATH_MSG_DEBUG("1 pt K_S0 tracks " << cascadeVertices[0]->trackParticle(0)->pt() << ", " << cascadeVertices[0]->trackParticle(1)->pt());
225 if (k0Vertex) ATH_MSG_DEBUG("2 pt K_S0 tracks " << k0Vertex->trackParticle(0)->pt() << ", " << k0Vertex->trackParticle(1)->pt());
226
227 // Set links to input vertices
228 std::vector<const xAOD::Vertex*> jpsipiVerticestoLink;
229 if (jpsipiVertex) jpsipiVerticestoLink.push_back(jpsipiVertex);
230 else ATH_MSG_WARNING("Could not find linking Jpsi+pi");
231 if(!BPhysPVCascadeTools::LinkVertices(JpsipiLinksDecor, jpsipiVerticestoLink, jpsipiContainer, cascadeVertices[2]))
232 ATH_MSG_ERROR("Error decorating with Jpsi+pi vertices");
233
234 std::vector<const xAOD::Vertex*> d0VerticestoLink;
235 if (d0Vertex) d0VerticestoLink.push_back(d0Vertex);
236 else ATH_MSG_WARNING("Could not find linking D0");
237 if(!BPhysPVCascadeTools::LinkVertices(D0LinksDecor, d0VerticestoLink, d0Container, cascadeVertices[2]))
238 ATH_MSG_ERROR("Error decorating with D0 vertices");
239
240 std::vector<const xAOD::Vertex*> k0VerticestoLink;
241 if (k0Vertex) k0VerticestoLink.push_back(k0Vertex);
242 else ATH_MSG_WARNING("Could not find linking K_S0");
243 if(!BPhysPVCascadeTools::LinkVertices(K0LinksDecor, k0VerticestoLink, k0Container, cascadeVertices[2]))
244 ATH_MSG_ERROR("Error decorating with K_S0 vertices");
245
246 bool tagD0(true);
247 if (jpsipiVertex){
248 if(abs(m_Dx_pid)==421 && (jpsipiVertex->trackParticle(2)->charge()==-1)) tagD0 = false;
249 }
250
251 double mass_b = m_vtx0MassHypo;
252 double mass_d0 = m_vtx1MassHypo;
253 double mass_k0 = m_vtx2MassHypo;
254 std::vector<double> massesJpsipi;
255 massesJpsipi.push_back(m_vtx0Daug1MassHypo);
256 massesJpsipi.push_back(m_vtx0Daug2MassHypo);
257 massesJpsipi.push_back(m_vtx0Daug3MassHypo);
258 std::vector<double> massesD0;
259 if(tagD0){
260 massesD0.push_back(m_vtx1Daug1MassHypo);
261 massesD0.push_back(m_vtx1Daug2MassHypo);
262 }else{ // Change the oreder of masses for D*-->D0bar pi-, D0bar->K+pi-
263 massesD0.push_back(m_vtx1Daug2MassHypo);
264 massesD0.push_back(m_vtx1Daug1MassHypo);
265 }
266 std::vector<double> massesK0;
267 massesK0.push_back(m_vtx2Daug1MassHypo);
268 massesK0.push_back(m_vtx2Daug2MassHypo);
269 std::vector<double> Masses;
270 Masses.push_back(m_vtx0Daug1MassHypo);
271 Masses.push_back(m_vtx0Daug2MassHypo);
272 Masses.push_back(m_vtx0Daug3MassHypo);
273 Masses.push_back(m_vtx1MassHypo);
274 Masses.push_back(m_vtx2MassHypo);
275
276 // loop over candidates -- Don't apply PV_minNTracks requirement here
277 // because it may result in exclusion of the high-pt PV.
278 // get good PVs
279
280 xAOD::BPhysHypoHelper vtx(m_hypoName, mainVertex);
281
283
284 // Decorate main vertex
285 //
286 // 1.a) mass, mass error
287 BPHYS_CHECK( vtx.setMass(m_CascadeTools->invariantMass(moms[2])) );
288 BPHYS_CHECK( vtx.setMassErr(m_CascadeTools->invariantMassError(moms[2],x->getCovariance()[2])) );
289 // 1.b) pt and pT error (the default pt of mainVertex is != the pt of the full cascade fit!)
290 Pt_decor(*mainVertex) = m_CascadeTools->pT(moms[2]);
291 PtErr_decor(*mainVertex) = m_CascadeTools->pTError(moms[2],x->getCovariance()[2]);
292 // 1.c) chi2 and ndof (the default chi2 of mainVertex is != the chi2 of the full cascade fit!)
293 chi2_decor(*mainVertex) = x->fitChi2();
294 ndof_decor(*mainVertex) = x->nDoF();
295
296 float massMumu = 0.;
297 if (jpsipiVertex) {
298 TLorentzVector p4_mu1, p4_mu2;
299 p4_mu1.SetPtEtaPhiM(jpsipiVertex->trackParticle(0)->pt(),
300 jpsipiVertex->trackParticle(0)->eta(),
301 jpsipiVertex->trackParticle(0)->phi(), m_vtx0Daug1MassHypo);
302 p4_mu2.SetPtEtaPhiM(jpsipiVertex->trackParticle(1)->pt(),
303 jpsipiVertex->trackParticle(1)->eta(),
304 jpsipiVertex->trackParticle(1)->phi(), m_vtx0Daug2MassHypo);
305 massMumu = (p4_mu1 + p4_mu2).M();
306 }
307 MassMumu_decor(*mainVertex) = massMumu;
308
309 float massKpi = 0.;
310 if (d0Vertex) {
311 TLorentzVector p4_ka, p4_pi;
312 if(tagD0){
313 p4_pi.SetPtEtaPhiM(d0Vertex->trackParticle(0)->pt(),
314 d0Vertex->trackParticle(0)->eta(),
315 d0Vertex->trackParticle(0)->phi(), m_vtx1Daug1MassHypo);
316 p4_ka.SetPtEtaPhiM(d0Vertex->trackParticle(1)->pt(),
317 d0Vertex->trackParticle(1)->eta(),
318 d0Vertex->trackParticle(1)->phi(), m_vtx1Daug2MassHypo);
319 }else{ // Change the oreder of masses for D*-->D0bar pi-, D0bar->K+pi-
320 p4_pi.SetPtEtaPhiM(d0Vertex->trackParticle(1)->pt(),
321 d0Vertex->trackParticle(1)->eta(),
322 d0Vertex->trackParticle(1)->phi(), m_vtx1Daug1MassHypo);
323 p4_ka.SetPtEtaPhiM(d0Vertex->trackParticle(0)->pt(),
324 d0Vertex->trackParticle(0)->eta(),
325 d0Vertex->trackParticle(0)->phi(), m_vtx1Daug2MassHypo);
326 }
327 massKpi = (p4_ka + p4_pi).M();
328 }
329 MassKpi_svdecor(*mainVertex) = massKpi;
330
331 float massPipi = 0.;
332 if (k0Vertex) {
333 TLorentzVector p4_pip, p4_pim;
334 p4_pip.SetPtEtaPhiM(k0Vertex->trackParticle(0)->pt(),
335 k0Vertex->trackParticle(0)->eta(),
336 k0Vertex->trackParticle(0)->phi(), m_vtx2Daug1MassHypo);
337 p4_pim.SetPtEtaPhiM(k0Vertex->trackParticle(1)->pt(),
338 k0Vertex->trackParticle(1)->eta(),
339 k0Vertex->trackParticle(1)->phi(), m_vtx2Daug2MassHypo);
340 massPipi = (p4_pip + p4_pim).M();
341 }
342 MassPipi_sv2decor(*mainVertex) = massPipi;
343
344 MassJpsi_decor(*mainVertex) = (moms[2][0] + moms[2][1]).M();
345 MassPiD0_decor(*mainVertex) = (moms[2][2] + moms[2][4]).M();
346 MassPiD0K0_decor(*mainVertex) = (moms[2][2] + moms[2][4] + moms[2][3]).M();
347
348 ATH_CHECK(helper.FillCandwithRefittedVertices(m_refitPV, pvContainer,
349 refPvContainer, &(*m_pvRefitter), m_PV_max, m_DoVertexType, x, 2, mass_b, vtx));
350
351 // 4) decorate the main vertex with D0 vertex mass, pt, lifetime and lxy values (plus errors)
352 // D0 points to the main vertex, so lifetime and lxy are w.r.t the main vertex
353 Mass_svdecor(*mainVertex) = m_CascadeTools->invariantMass(moms[1]);
354 MassErr_svdecor(*mainVertex) = m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1]);
355 Pt_svdecor(*mainVertex) = m_CascadeTools->pT(moms[1]);
356 PtErr_svdecor(*mainVertex) = m_CascadeTools->pTError(moms[1],x->getCovariance()[1]);
357 Lxy_svdecor(*mainVertex) = m_CascadeTools->lxy(moms[1],cascadeVertices[1],cascadeVertices[2]);
358 LxyErr_svdecor(*mainVertex) = m_CascadeTools->lxyError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2]);
359 Tau_svdecor(*mainVertex) = m_CascadeTools->tau(moms[1],cascadeVertices[1],cascadeVertices[2]);
360 TauErr_svdecor(*mainVertex) = m_CascadeTools->tauError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2]);
361
362 // 5) decorate the main vertex with K_S0 vertex mass, pt, lifetime and lxy values (plus errors)
363 // K_S0 points to the main vertex, so lifetime and lxy are w.r.t the main vertex
364 Mass_sv2decor(*mainVertex) = m_CascadeTools->invariantMass(moms[0]);
365 MassErr_sv2decor(*mainVertex) = m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0]);
366 Pt_sv2decor(*mainVertex) = m_CascadeTools->pT(moms[0]);
367 PtErr_sv2decor(*mainVertex) = m_CascadeTools->pTError(moms[0],x->getCovariance()[0]);
368 Lxy_sv2decor(*mainVertex) = m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[2]);
369 LxyErr_sv2decor(*mainVertex) = m_CascadeTools->lxyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2]);
370 Tau_sv2decor(*mainVertex) = m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[2]);
371 TauErr_sv2decor(*mainVertex) = m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2]);
372
373 // Some checks in DEBUG mode
374 ATH_MSG_DEBUG("chi2 " << x->fitChi2()
375 << " chi2_1 " << m_V0Tools->chisq(cascadeVertices[0])
376 << " chi2_2 " << m_V0Tools->chisq(cascadeVertices[1])
377 << " chi2_3 " << m_V0Tools->chisq(cascadeVertices[2])
378 << " vprob " << m_CascadeTools->vertexProbability(x->nDoF(),x->fitChi2()));
379 ATH_MSG_DEBUG("ndf " << x->nDoF() << " ndf_1 " << m_V0Tools->ndof(cascadeVertices[0]) << " ndf_2 " << m_V0Tools->ndof(cascadeVertices[1]) << " ndf_3 " << m_V0Tools->ndof(cascadeVertices[2]));
380 ATH_MSG_DEBUG("V0Tools mass_k0 " << m_V0Tools->invariantMass(cascadeVertices[0],massesK0)
381 << " error " << m_V0Tools->invariantMassError(cascadeVertices[0],massesK0)
382 << " mass_d0 " << m_V0Tools->invariantMass(cascadeVertices[1],massesD0)
383 << " error " << m_V0Tools->invariantMassError(cascadeVertices[1],massesD0)
384 << " mass_J " << m_V0Tools->invariantMass(cascadeVertices[2],massesJpsipi)
385 << " error " << m_V0Tools->invariantMassError(cascadeVertices[2],massesJpsipi));
386 // masses and errors, using track masses assigned in the fit
387 double Mass_B = m_CascadeTools->invariantMass(moms[2]);
388 double Mass_D0 = m_CascadeTools->invariantMass(moms[1]);
389 double Mass_K0 = m_CascadeTools->invariantMass(moms[0]);
390 double Mass_B_err = m_CascadeTools->invariantMassError(moms[2],x->getCovariance()[2]);
391 double Mass_D0_err = m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1]);
392 double Mass_K0_err = m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0]);
393 ATH_MSG_DEBUG("Mass_B " << Mass_B << " Mass_D0 " << Mass_D0 << " Mass_K0 " << Mass_K0);
394 ATH_MSG_DEBUG("Mass_B_err " << Mass_B_err << " Mass_D0_err " << Mass_D0_err << " Mass_K0_err " << Mass_K0_err);
395 double mprob_B = m_CascadeTools->massProbability(mass_b,Mass_B,Mass_B_err);
396 double mprob_D0 = m_CascadeTools->massProbability(mass_d0,Mass_D0,Mass_D0_err);
397 double mprob_K0 = m_CascadeTools->massProbability(mass_k0,Mass_K0,Mass_K0_err);
398 ATH_MSG_DEBUG("mprob_B " << mprob_B << " mprob_D0 " << mprob_D0 << " mprob_K0 " << mprob_K0);
399 // masses and errors, assigning user defined track masses
400 ATH_MSG_DEBUG("Mass_b " << m_CascadeTools->invariantMass(moms[2],Masses)
401 << " Mass_d0 " << m_CascadeTools->invariantMass(moms[1],massesD0)
402 << " Mass_k0 " << m_CascadeTools->invariantMass(moms[0],massesD0));
403 ATH_MSG_DEBUG("Mass_b_err " << m_CascadeTools->invariantMassError(moms[2],x->getCovariance()[2],Masses)
404 << " Mass_d0_err " << m_CascadeTools->invariantMassError(moms[1],x->getCovariance()[1],massesD0)
405 << " Mass_k0_err " << m_CascadeTools->invariantMassError(moms[0],x->getCovariance()[0],massesK0));
406 ATH_MSG_DEBUG("pt_b " << m_CascadeTools->pT(moms[2])
407 << " pt_d " << m_CascadeTools->pT(moms[1])
408 << " pt_d0 " << m_V0Tools->pT(cascadeVertices[1])
409 << " pt_k " << m_CascadeTools->pT(moms[0])
410 << " pt_k0 " << m_V0Tools->pT(cascadeVertices[0]));
411 ATH_MSG_DEBUG("ptErr_b " << m_CascadeTools->pTError(moms[2],x->getCovariance()[2])
412 << " ptErr_d " << m_CascadeTools->pTError(moms[1],x->getCovariance()[1])
413 << " ptErr_d0 " << m_V0Tools->pTError(cascadeVertices[1])
414 << " ptErr_k " << m_CascadeTools->pTError(moms[0],x->getCovariance()[0])
415 << " ptErr_k0 " << m_V0Tools->pTError(cascadeVertices[0]));
416 ATH_MSG_DEBUG("lxy_B " << m_V0Tools->lxy(cascadeVertices[2],primaryVertex) << " lxy_D " << m_V0Tools->lxy(cascadeVertices[1],cascadeVertices[2]) << " lxy_K " << m_V0Tools->lxy(cascadeVertices[0],cascadeVertices[2]));
417 ATH_MSG_DEBUG("lxy_b " << m_CascadeTools->lxy(moms[2],cascadeVertices[2],primaryVertex) << " lxy_d " << m_CascadeTools->lxy(moms[1],cascadeVertices[1],cascadeVertices[2]) << " lxy_k " << m_CascadeTools->lxy(moms[0],cascadeVertices[0],cascadeVertices[2]));
418 ATH_MSG_DEBUG("lxyErr_b " << m_CascadeTools->lxyError(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex)
419 << " lxyErr_d " << m_CascadeTools->lxyError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2])
420 << " lxyErr_d0 " << m_V0Tools->lxyError(cascadeVertices[1],cascadeVertices[2])
421 << " lxyErr_k " << m_CascadeTools->lxyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2])
422 << " lxyErr_k0 " << m_V0Tools->lxyError(cascadeVertices[0],cascadeVertices[2]));
423 ATH_MSG_DEBUG("tau_B " << m_CascadeTools->tau(moms[2],cascadeVertices[2],primaryVertex,mass_b)
424 << " tau_d0 " << m_V0Tools->tau(cascadeVertices[1],cascadeVertices[2],massesD0)
425 << " tau_k0 " << m_V0Tools->tau(cascadeVertices[0],cascadeVertices[2],massesK0));
426 ATH_MSG_DEBUG("tau_b " << m_CascadeTools->tau(moms[2],cascadeVertices[2],primaryVertex)
427 << " tau_d " << m_CascadeTools->tau(moms[1],cascadeVertices[1],cascadeVertices[2])
428 << " tau_D " << m_CascadeTools->tau(moms[1],cascadeVertices[1],cascadeVertices[2],mass_d0)
429 << " tau_k " << m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[2])
430 << " tau_K " << m_CascadeTools->tau(moms[0],cascadeVertices[0],cascadeVertices[2],mass_k0));
431 ATH_MSG_DEBUG("tauErr_b " << m_CascadeTools->tauError(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex)
432 << " tauErr_d " << m_CascadeTools->tauError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2])
433 << " tauErr_d0 " << m_V0Tools->tauError(cascadeVertices[1],cascadeVertices[2],massesD0)
434 << " tauErr_k " << m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2])
435 << " tauErr_k0 " << m_V0Tools->tauError(cascadeVertices[0],cascadeVertices[2],massesK0));
436 ATH_MSG_DEBUG("TauErr_b " << m_CascadeTools->tauError(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex,mass_b)
437 << " TauErr_d " << m_CascadeTools->tauError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2],mass_d0)
438 << " TauErr_d0 " << m_V0Tools->tauError(cascadeVertices[1],cascadeVertices[2],massesD0,mass_d0)
439 << " TauErr_k " << m_CascadeTools->tauError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2],mass_k0)
440 << " TauErr_k0 " << m_V0Tools->tauError(cascadeVertices[0],cascadeVertices[2],massesD0,mass_k0));
441
442 ATH_MSG_DEBUG("CascadeTools main vert wrt PV " << " CascadeTools SV " << " V0Tools SV");
443 ATH_MSG_DEBUG("a0z " << m_CascadeTools->a0z(moms[2],cascadeVertices[2],primaryVertex)
444 << ", " << m_CascadeTools->a0z(moms[1],cascadeVertices[1],cascadeVertices[2])
445 << ", " << m_CascadeTools->a0z(moms[0],cascadeVertices[0],cascadeVertices[2])
446 << ", " << m_V0Tools->a0z(cascadeVertices[1],cascadeVertices[2])
447 << ", " << m_V0Tools->a0z(cascadeVertices[0],cascadeVertices[2]));
448 ATH_MSG_DEBUG("a0zErr " << m_CascadeTools->a0zError(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex)
449 << ", " << m_CascadeTools->a0zError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2])
450 << ", " << m_CascadeTools->a0zError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2])
451 << ", " << m_V0Tools->a0zError(cascadeVertices[1],cascadeVertices[2])
452 << ", " << m_V0Tools->a0zError(cascadeVertices[0],cascadeVertices[2]));
453 ATH_MSG_DEBUG("a0xy " << m_CascadeTools->a0xy(moms[2],cascadeVertices[2],primaryVertex)
454 << ", " << m_CascadeTools->a0xy(moms[1],cascadeVertices[1],cascadeVertices[2])
455 << ", " << m_CascadeTools->a0xy(moms[0],cascadeVertices[0],cascadeVertices[2])
456 << ", " << m_V0Tools->a0xy(cascadeVertices[1],cascadeVertices[2])
457 << ", " << m_V0Tools->a0xy(cascadeVertices[0],cascadeVertices[2]));
458 ATH_MSG_DEBUG("a0xyErr " << m_CascadeTools->a0xyError(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex)
459 << ", " << m_CascadeTools->a0xyError(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2])
460 << ", " << m_CascadeTools->a0xyError(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2])
461 << ", " << m_V0Tools->a0xyError(cascadeVertices[1],cascadeVertices[2])
462 << ", " << m_V0Tools->a0xyError(cascadeVertices[0],cascadeVertices[2]));
463 ATH_MSG_DEBUG("a0 " << m_CascadeTools->a0(moms[2],cascadeVertices[2],primaryVertex)
464 << ", " << m_CascadeTools->a0(moms[1],cascadeVertices[1],cascadeVertices[2])
465 << ", " << m_CascadeTools->a0(moms[0],cascadeVertices[0],cascadeVertices[2])
466 << ", " << m_V0Tools->a0(cascadeVertices[1],cascadeVertices[2])
467 << ", " << m_V0Tools->a0(cascadeVertices[0],cascadeVertices[2]));
468 ATH_MSG_DEBUG("a0Err " << m_CascadeTools->a0Error(moms[2],x->getCovariance()[2],cascadeVertices[2],primaryVertex)
469 << ", " << m_CascadeTools->a0Error(moms[1],x->getCovariance()[1],cascadeVertices[1],cascadeVertices[2])
470 << ", " << m_CascadeTools->a0Error(moms[0],x->getCovariance()[0],cascadeVertices[0],cascadeVertices[2])
471 << ", " << m_V0Tools->a0Error(cascadeVertices[1],cascadeVertices[2])
472 << ", " << m_V0Tools->a0Error(cascadeVertices[0],cascadeVertices[2]));
473 ATH_MSG_DEBUG("x0 " << m_V0Tools->vtx(cascadeVertices[0]).x() << " y0 " << m_V0Tools->vtx(cascadeVertices[0]).y() << " z0 " << m_V0Tools->vtx(cascadeVertices[0]).z());
474 ATH_MSG_DEBUG("x1 " << m_V0Tools->vtx(cascadeVertices[1]).x() << " y1 " << m_V0Tools->vtx(cascadeVertices[1]).y() << " z1 " << m_V0Tools->vtx(cascadeVertices[1]).z());
475 ATH_MSG_DEBUG("x2 " << m_V0Tools->vtx(cascadeVertices[2]).x() << " y2 " << m_V0Tools->vtx(cascadeVertices[2]).y() << " z2 " << m_V0Tools->vtx(cascadeVertices[2]).z());
476 ATH_MSG_DEBUG("X0 " << primaryVertex->x() << " Y0 " << primaryVertex->y() << " Z0 " << primaryVertex->z());
477 ATH_MSG_DEBUG("rxy0 " << m_V0Tools->rxy(cascadeVertices[0]) << " rxyErr0 " << m_V0Tools->rxyError(cascadeVertices[0]));
478 ATH_MSG_DEBUG("rxy1 " << m_V0Tools->rxy(cascadeVertices[1]) << " rxyErr1 " << m_V0Tools->rxyError(cascadeVertices[1]));
479 ATH_MSG_DEBUG("rxy2 " << m_V0Tools->rxy(cascadeVertices[2]) << " rxyErr2 " << m_V0Tools->rxyError(cascadeVertices[2]));
480 ATH_MSG_DEBUG("Rxy0 wrt PV " << m_V0Tools->rxy(cascadeVertices[0],primaryVertex) << " RxyErr0 wrt PV " << m_V0Tools->rxyError(cascadeVertices[0],primaryVertex));
481 ATH_MSG_DEBUG("Rxy1 wrt PV " << m_V0Tools->rxy(cascadeVertices[1],primaryVertex) << " RxyErr1 wrt PV " << m_V0Tools->rxyError(cascadeVertices[1],primaryVertex));
482 ATH_MSG_DEBUG("Rxy2 wrt PV " << m_V0Tools->rxy(cascadeVertices[2],primaryVertex) << " RxyErr2 wrt PV " << m_V0Tools->rxyError(cascadeVertices[2],primaryVertex));
483 ATH_MSG_DEBUG("number of covariance matrices " << (x->getCovariance()).size());
484 } // loop over cascadeinfoContainer
485
486 // Deleting cascadeinfo since this won't be stored.
487 // Vertices have been kept in m_cascadeOutputs and should be owned by their container
488 for (auto x : cascadeinfoContainer) delete x;
489
490 return StatusCode::SUCCESS;
491 }
492
493
494 JpsiPlusDs1Cascade::JpsiPlusDs1Cascade(const std::string& t, const std::string& n, const IInterface* p) : base_class(t,n,p),
498 m_cascadeOutputsKeys{ "JpsiPlusDs1CascadeVtx1", "JpsiPlusDs1CascadeVtx2", "JpsiPlusDs1CascadeVtx3" },
499 m_VxPrimaryCandidateName("PrimaryVertices"),
500 m_jpsiMassLower(0.0),
501 m_jpsiMassUpper(10000.0),
503 m_jpsipiMassUpper(10000.0),
504 m_D0MassLower(0.0),
505 m_D0MassUpper(10000.0),
506 m_K0MassLower(0.0),
507 m_K0MassUpper(10000.0),
508 m_DstMassLower(0.0),
509 m_DstMassUpper(10000.0),
510 m_MassLower(0.0),
511 m_MassUpper(20000.0),
512 m_vtx0MassHypo(-1),
513 m_vtx1MassHypo(-1),
514 m_vtx2MassHypo(-1),
522 m_mass_jpsi(-1),
523 m_Dx_pid(421),
524 m_constrD0(true),
525 m_constrK0(true),
526 m_constrJpsi(true),
527 m_chi2cut(-1.0),
528 m_iVertexFitter("Trk::TrkVKalVrtFitter"),
529 m_pvRefitter("Analysis::PrimaryVertexRefitter"),
530 m_V0Tools("Trk::V0Tools"),
531 m_CascadeTools("DerivationFramework::CascadeTools")
532 {
533 declareProperty("JpsipiVertices", m_vertexContainerKey);
534 declareProperty("D0Vertices", m_vertexD0ContainerKey);
535 declareProperty("K0Vertices", m_vertexK0ContainerKey);
536 declareProperty("VxPrimaryCandidateName", m_VxPrimaryCandidateName);
537 declareProperty("RefPVContainerName", m_refPVContainerName = "RefittedPrimaryVertices");
538 declareProperty("JpsiMassLowerCut", m_jpsiMassLower);
539 declareProperty("JpsiMassUpperCut", m_jpsiMassUpper);
540 declareProperty("JpsipiMassLowerCut", m_jpsipiMassLower);
541 declareProperty("JpsipiMassUpperCut", m_jpsipiMassUpper);
542 declareProperty("D0MassLowerCut", m_D0MassLower);
543 declareProperty("D0MassUpperCut", m_D0MassUpper);
544 declareProperty("K0MassLowerCut", m_K0MassLower);
545 declareProperty("K0MassUpperCut", m_K0MassUpper);
546 declareProperty("DstMassLowerCut", m_DstMassLower);
547 declareProperty("DstMassUpperCut", m_DstMassUpper);
548 declareProperty("MassLowerCut", m_MassLower);
549 declareProperty("MassUpperCut", m_MassUpper);
550 declareProperty("HypothesisName", m_hypoName = "Bc");
551 declareProperty("Vtx0MassHypo", m_vtx0MassHypo);
552 declareProperty("Vtx1MassHypo", m_vtx1MassHypo);
553 declareProperty("Vtx2MassHypo", m_vtx2MassHypo);
554 declareProperty("Vtx0Daug1MassHypo", m_vtx0Daug1MassHypo);
555 declareProperty("Vtx0Daug2MassHypo", m_vtx0Daug2MassHypo);
556 declareProperty("Vtx0Daug3MassHypo", m_vtx0Daug3MassHypo);
557 declareProperty("Vtx1Daug1MassHypo", m_vtx1Daug1MassHypo);
558 declareProperty("Vtx1Daug2MassHypo", m_vtx1Daug2MassHypo);
559 declareProperty("Vtx2Daug1MassHypo", m_vtx2Daug1MassHypo);
560 declareProperty("Vtx2Daug2MassHypo", m_vtx2Daug2MassHypo);
561 declareProperty("JpsiMass", m_mass_jpsi);
562 declareProperty("DxHypothesis", m_Dx_pid);
563 declareProperty("ApplyD0MassConstraint", m_constrD0);
564 declareProperty("ApplyK0MassConstraint", m_constrK0);
565 declareProperty("ApplyJpsiMassConstraint", m_constrJpsi);
566 declareProperty("Chi2Cut", m_chi2cut);
567 declareProperty("RefitPV", m_refitPV = true);
568 declareProperty("MaxnPV", m_PV_max = 999);
569 declareProperty("MinNTracksInPV", m_PV_minNTracks = 0);
570 declareProperty("DoVertexType", m_DoVertexType = 7);
571 declareProperty("TrkVertexFitterTool", m_iVertexFitter);
572 declareProperty("PVRefitter", m_pvRefitter);
573 declareProperty("V0Tools", m_V0Tools);
574 declareProperty("CascadeTools", m_CascadeTools);
575 declareProperty("CascadeVertexCollections", m_cascadeOutputsKeys);
576 }
577
579
580 StatusCode JpsiPlusDs1Cascade::performSearch(std::vector<Trk::VxCascadeInfo*> *cascadeinfoContainer, const EventContext& ctx) const
581 {
582 ATH_MSG_DEBUG( "JpsiPlusDs1Cascade::performSearch" );
583 assert(cascadeinfoContainer!=nullptr);
584
585 // Get TrackParticle container (for setting links to the original tracks)
586 const xAOD::TrackParticleContainer *trackContainer{};
587 ATH_CHECK(evtStore()->retrieve(trackContainer , "InDetTrackParticles" )); // FIXME Use Handles
588
589 // Get Jpsi+pi container
590 const xAOD::VertexContainer *jpsipiContainer{};
591 ATH_CHECK(evtStore()->retrieve(jpsipiContainer , m_vertexContainerKey )); // FIXME Use Handles
592
593 // Get D0 container
594 const xAOD::VertexContainer *d0Container{};
595 ATH_CHECK(evtStore()->retrieve(d0Container , m_vertexD0ContainerKey )); // FIXME Use Handles
596
597 // Get K_S0 container
598 const xAOD::VertexContainer *k0Container{};
599 ATH_CHECK(evtStore()->retrieve(k0Container , m_vertexK0ContainerKey )); // FIXME Use Handles
600
601 double mass_d0 = m_vtx1MassHypo;
602 double mass_k0 = m_vtx2MassHypo;
603 std::vector<const xAOD::TrackParticle*> tracksJpsipi;
604 std::vector<const xAOD::TrackParticle*> tracksJpsi;
605 std::vector<const xAOD::TrackParticle*> tracksD0;
606 std::vector<const xAOD::TrackParticle*> tracksK0;
607 std::vector<const xAOD::TrackParticle*> tracksBc;
608 std::vector<double> massesJpsipi;
609 massesJpsipi.push_back(m_vtx0Daug1MassHypo);
610 massesJpsipi.push_back(m_vtx0Daug2MassHypo);
611 massesJpsipi.push_back(m_vtx0Daug3MassHypo);
612 std::vector<double> massesD0;
613 massesD0.push_back(m_vtx1Daug1MassHypo);
614 massesD0.push_back(m_vtx1Daug2MassHypo);
615 std::vector<double> massesD0b; // Change the oreder of masses for D*-->D0bar pi-, D0bar->K+pi-
616 massesD0b.push_back(m_vtx1Daug2MassHypo);
617 massesD0b.push_back(m_vtx1Daug1MassHypo);
618 std::vector<double> massesK0;
619 massesK0.push_back(m_vtx2Daug1MassHypo);
620 massesK0.push_back(m_vtx2Daug2MassHypo);
621 std::vector<double> Masses;
622 Masses.push_back(m_vtx0Daug1MassHypo);
623 Masses.push_back(m_vtx0Daug2MassHypo);
624 Masses.push_back(m_vtx0Daug3MassHypo);
625 Masses.push_back(m_vtx1MassHypo);
626 Masses.push_back(m_vtx2MassHypo);
627
628 // Select J/psi pi+ candidates before calling cascade fit
629 std::vector<const xAOD::Vertex*> selectedJpsipiCandidates;
630 for(auto vxcItr=jpsipiContainer->cbegin(); vxcItr!=jpsipiContainer->cend(); ++vxcItr) {
631
632 // Check the passed flag first
633 const xAOD::Vertex* vtx = *vxcItr;
634 SG::Accessor<Char_t> flagAcc1("passed_Jpsipi");
635 if(flagAcc1.isAvailable(*vtx)){
636 if(!flagAcc1(*vtx)) continue;
637 }
638
639 // Check J/psi candidate invariant mass and skip if need be
640 TLorentzVector p4Mup_in, p4Mum_in;
641 p4Mup_in.SetPtEtaPhiM((*vxcItr)->trackParticle(0)->pt(),
642 (*vxcItr)->trackParticle(0)->eta(),
643 (*vxcItr)->trackParticle(0)->phi(), m_vtx0Daug1MassHypo);
644 p4Mum_in.SetPtEtaPhiM((*vxcItr)->trackParticle(1)->pt(),
645 (*vxcItr)->trackParticle(1)->eta(),
646 (*vxcItr)->trackParticle(1)->phi(), m_vtx0Daug2MassHypo);
647 double mass_Jpsi = (p4Mup_in + p4Mum_in).M();
648 ATH_MSG_DEBUG("Jpsi mass " << mass_Jpsi);
649 if (mass_Jpsi < m_jpsiMassLower || mass_Jpsi > m_jpsiMassUpper) {
650 ATH_MSG_DEBUG(" Original Jpsi candidate rejected by the mass cut: mass = "
651 << mass_Jpsi << " != (" << m_jpsiMassLower << ", " << m_jpsiMassUpper << ")" );
652 continue;
653 }
654
655 // Check J/psi pi+ candidate invariant mass and skip if need be
656 double mass_Jpsipi = m_V0Tools->invariantMass(*vxcItr, massesJpsipi);
657 ATH_MSG_DEBUG("Jpsipi mass " << mass_Jpsipi);
658 if (mass_Jpsipi < m_jpsipiMassLower || mass_Jpsipi > m_jpsipiMassUpper) {
659 ATH_MSG_DEBUG(" Original Jpsipi candidate rejected by the mass cut: mass = "
660 << mass_Jpsipi << " != (" << m_jpsipiMassLower << ", " << m_jpsipiMassUpper << ")" );
661 continue;
662 }
663
664 selectedJpsipiCandidates.push_back(*vxcItr);
665 }
666 if(selectedJpsipiCandidates.size()<1) return StatusCode::SUCCESS;
667
668 // Select the D0/D0b candidates before calling cascade fit
669 std::vector<const xAOD::Vertex*> selectedD0Candidates;
670 for(auto vxcItr=d0Container->cbegin(); vxcItr!=d0Container->cend(); ++vxcItr) {
671
672 // Check the passed flag first
673 const xAOD::Vertex* vtx = *vxcItr;
674 SG::Accessor<Char_t> flagAcc1("passed_D0");
675 SG::Accessor<Char_t> flagAcc2("passed_D0b");
676 bool isD0(true);
677 bool isD0b(true);
678 if(flagAcc1.isAvailable(*vtx)){
679 if(!flagAcc1(*vtx)) isD0 = false;
680 }
681 if(flagAcc2.isAvailable(*vtx)){
682 if(!flagAcc2(*vtx)) isD0b = false;
683 }
684 if(!(isD0||isD0b)) continue;
685
686 // Ensure the total charge is correct
687 if ((*vxcItr)->trackParticle(0)->charge() != 1 || (*vxcItr)->trackParticle(1)->charge() != -1) {
688 ATH_MSG_DEBUG(" Original D0/D0-bar candidate rejected by the charge requirement: "
689 << (*vxcItr)->trackParticle(0)->charge() << ", " << (*vxcItr)->trackParticle(1)->charge() );
690 continue;
691 }
692
693 // Check D0/D0bar candidate invariant mass and skip if need be
694 double mass_D0 = m_V0Tools->invariantMass(*vxcItr,massesD0);
695 double mass_D0b = m_V0Tools->invariantMass(*vxcItr,massesD0b);
696 ATH_MSG_DEBUG("D0 mass " << mass_D0 << ", D0b mass "<<mass_D0b);
697 if ((mass_D0 < m_D0MassLower || mass_D0 > m_D0MassUpper) && (mass_D0b < m_D0MassLower || mass_D0b > m_D0MassUpper)) {
698 ATH_MSG_DEBUG(" Original D0 candidate rejected by the mass cut: mass = "
699 << mass_D0 << " != (" << m_D0MassLower << ", " << m_D0MassUpper << ") "
700 << mass_D0b << " != (" << m_D0MassLower << ", " << m_D0MassUpper << ") " );
701 continue;
702 }
703
704 selectedD0Candidates.push_back(*vxcItr);
705 }
706 if(selectedD0Candidates.size()<1) return StatusCode::SUCCESS;
707
708 // Select the D0/D0b candidates before calling cascade fit
709 std::vector<const xAOD::Vertex*> selectedK0Candidates;
710 const SG::Accessor<Char_t> flagAcc1("passed_K0");
711 for(auto vxcItr=k0Container->cbegin(); vxcItr!=k0Container->cend(); ++vxcItr) {
712 // Check the passed flag first
713 const xAOD::Vertex* vtx = *vxcItr;
714 if(flagAcc1.isAvailable(*vtx)){
715 if(!flagAcc1(*vtx)) continue;
716 }
717
718 // Check K_S0 candidate invariant mass and skip if need be
719 double mass_K0 = m_V0Tools->invariantMass(*vxcItr, massesK0);
720 ATH_MSG_DEBUG("K_S0 mass " << mass_K0);
721 if (mass_K0 < m_K0MassLower || mass_K0 > m_K0MassUpper) {
722 ATH_MSG_DEBUG(" Original K_S0 candidate rejected by the mass cut: mass = "
723 << mass_K0 << " != (" << m_K0MassLower << ", " << m_K0MassUpper << ")" );
724 continue;
725 }
726
727 selectedK0Candidates.push_back(*vxcItr);
728 }
729 if(selectedK0Candidates.size()<1) return StatusCode::SUCCESS;
730
731 // Select J/psi D*+ candidates
732 // Iterate over Jpsi+pi vertices
733 for(const auto & jpsipi:selectedJpsipiCandidates) {
734
735 size_t jpsipiTrkNum = jpsipi->nTrackParticles();
736 if (jpsipiTrkNum != 3 ) {
737 ATH_MSG_INFO("problems with Jpsi+pi input");
738 }
739 tracksJpsipi.clear();
740 tracksJpsi.clear();
741 for( unsigned int it=0; it<jpsipiTrkNum; it++) tracksJpsipi.push_back(jpsipi->trackParticle(it));
742 for( unsigned int it=0; it<jpsipiTrkNum-1; it++) tracksJpsi.push_back(jpsipi->trackParticle(it));
743
744 bool tagD0(true);
745 if(abs(m_Dx_pid)==421 && jpsipi->trackParticle(2)->charge()==-1) tagD0 = false;
746
747 TLorentzVector p4_pi1; // Momentum of soft pion
748 p4_pi1.SetPtEtaPhiM(jpsipi->trackParticle(2)->pt(),
749 jpsipi->trackParticle(2)->eta(),
750 jpsipi->trackParticle(2)->phi(), m_vtx0Daug3MassHypo);
751
752 // Iterate over D0/D0bar vertices
753 for(const auto & pD0 : selectedD0Candidates) {
754
755 // Check identical tracks in input
756 if(std::find(tracksJpsipi.cbegin(), tracksJpsipi.cend(), pD0->trackParticle(0)) != tracksJpsipi.cend()) continue;
757 if(std::find(tracksJpsipi.cbegin(), tracksJpsipi.cend(), pD0->trackParticle(1)) != tracksJpsipi.cend()) continue;
758
759 TLorentzVector p4_ka, p4_pi2;
760 if(tagD0){ // for D*+
761 p4_pi2.SetPtEtaPhiM(pD0->trackParticle(0)->pt(),
762 pD0->trackParticle(0)->eta(),
763 pD0->trackParticle(0)->phi(), m_vtx1Daug1MassHypo);
764 p4_ka.SetPtEtaPhiM( pD0->trackParticle(1)->pt(),
765 pD0->trackParticle(1)->eta(),
766 pD0->trackParticle(1)->phi(), m_vtx1Daug2MassHypo);
767 }else{ // change the order in the case of D*-
768 p4_pi2.SetPtEtaPhiM(pD0->trackParticle(1)->pt(),
769 pD0->trackParticle(1)->eta(),
770 pD0->trackParticle(1)->phi(), m_vtx1Daug1MassHypo);
771 p4_ka.SetPtEtaPhiM( pD0->trackParticle(0)->pt(),
772 pD0->trackParticle(0)->eta(),
773 pD0->trackParticle(0)->phi(), m_vtx1Daug2MassHypo);
774 }
775 // Check D*+/- candidate invariant mass and skip if need be
776 double mass_Dst= (p4_pi1 + p4_ka + p4_pi2).M();
777 ATH_MSG_DEBUG("D*+/- mass " << mass_Dst);
778 if (mass_Dst < m_DstMassLower || mass_Dst > m_DstMassUpper) {
779 ATH_MSG_DEBUG(" Original D*+/- candidate rejected by the mass cut: mass = "
780 << mass_Dst << " != (" << m_DstMassLower << ", " << m_DstMassUpper << ")" );
781 continue;
782 }
783
784 size_t d0TrkNum = pD0->nTrackParticles();
785 tracksD0.clear();
786 for( unsigned int it=0; it<d0TrkNum; it++) tracksD0.push_back(pD0->trackParticle(it));
787 if (tracksD0.size() != 2 || massesD0.size() != 2 ) {
788 ATH_MSG_INFO("problems with D0 input");
789 }
790
791 // Iterate over K0 vertices
792 for(const auto & k0 : selectedK0Candidates) {
793
794 // Check identical tracks in input
795 if(std::find(tracksJpsipi.cbegin(), tracksJpsipi.cend(), k0->trackParticle(0)) != tracksJpsipi.cend()) continue;
796 if(std::find(tracksJpsipi.cbegin(), tracksJpsipi.cend(), k0->trackParticle(1)) != tracksJpsipi.cend()) continue;
797 if(std::find(tracksD0.cbegin(), tracksD0.cend(), k0->trackParticle(0)) != tracksD0.cend()) continue;
798 if(std::find(tracksD0.cbegin(), tracksD0.cend(), k0->trackParticle(1)) != tracksD0.cend()) continue;
799
800 size_t k0TrkNum = k0->nTrackParticles();
801 tracksK0.clear();
802 for( unsigned int it=0; it<k0TrkNum; it++) tracksK0.push_back(k0->trackParticle(it));
803 if (tracksK0.size() != 2 || massesK0.size() != 2 ) {
804 ATH_MSG_INFO("problems with K0 input");
805 }
806
807 ATH_MSG_DEBUG("using tracks" << tracksJpsipi[0] << ", " << tracksJpsipi[1] << ", " << tracksJpsipi[2] << ", " << tracksD0[0] << ", " << tracksD0[1] << ", " << tracksK0[0] << ", " << tracksK0[1]);
808
809 tracksBc.clear();
810 for( unsigned int it=0; it<jpsipiTrkNum; it++) tracksBc.push_back(jpsipi->trackParticle(it));
811 for( unsigned int it=0; it<d0TrkNum; it++) tracksBc.push_back(pD0->trackParticle(it));
812 for( unsigned int it=0; it<k0TrkNum; it++) tracksBc.push_back(k0->trackParticle(it));
813
814
815 // Apply the user's settings to the fitter
816 // Reset
817 std::unique_ptr<Trk::IVKalState> state (m_iVertexFitter->makeState(ctx));
818 // Robustness
819 int robustness = 0;
820 m_iVertexFitter->setRobustness(robustness, *state);
821 // Build up the topology
822 // Vertex list
823 std::vector<Trk::VertexID> vrtList;
824 // K_S0 vertex
825 Trk::VertexID vK0ID;
826 if (m_constrK0) {
827 vK0ID = m_iVertexFitter->startVertex(tracksK0,massesK0, *state, mass_k0);
828 } else {
829 vK0ID = m_iVertexFitter->startVertex(tracksK0,massesK0, *state);
830 }
831 vrtList.push_back(vK0ID);
832 // D0 vertex
833 Trk::VertexID vD0ID;
834 if (m_constrD0) {
835 if(tagD0) vD0ID = m_iVertexFitter->nextVertex(tracksD0,massesD0, *state, mass_d0);
836 else vD0ID = m_iVertexFitter->nextVertex(tracksD0,massesD0b, *state, mass_d0);
837 } else {
838 if(tagD0) vD0ID = m_iVertexFitter->nextVertex(tracksD0,massesD0, *state);
839 else vD0ID = m_iVertexFitter->nextVertex(tracksD0,massesD0b, *state);
840 }
841 vrtList.push_back(vD0ID);
842 // B vertex including Jpsi+pi
843 Trk::VertexID vBcID = m_iVertexFitter->nextVertex(tracksJpsipi,massesJpsipi,vrtList, *state);
844 if (m_constrJpsi) {
845 std::vector<Trk::VertexID> cnstV;
846 cnstV.clear();
847 if ( !m_iVertexFitter->addMassConstraint(vBcID,tracksJpsi,cnstV, *state, m_mass_jpsi).isSuccess() ) {
848 ATH_MSG_WARNING("addMassConstraint failed");
849 //return StatusCode::FAILURE;
850 }
851 }
852 // Do the work
853 std::unique_ptr<Trk::VxCascadeInfo> result(m_iVertexFitter->fitCascade(*state));
854
855 if (result != nullptr) {
856
857 // reset links to original tracks
858 BPhysPVCascadeTools::PrepareVertexLinks(result.get(), trackContainer);
859 ATH_MSG_DEBUG("storing tracks " << ((result->vertices())[0])->trackParticle(0) << ", "
860 << ((result->vertices())[0])->trackParticle(1) << ", "
861 << ((result->vertices())[1])->trackParticle(0) << ", "
862 << ((result->vertices())[1])->trackParticle(1) << ", "
863 << ((result->vertices())[2])->trackParticle(0) << ", "
864 << ((result->vertices())[2])->trackParticle(1) << ", "
865 << ((result->vertices())[2])->trackParticle(2));
866 // necessary to prevent memory leak
867 result->setSVOwnership(true);
868
869 // Chi2/DOF cut
870 double bChi2DOF = result->fitChi2()/result->nDoF();
871 ATH_MSG_DEBUG("Candidate chi2/DOF is " << bChi2DOF);
872 bool chi2CutPassed = (m_chi2cut <= 0.0 || bChi2DOF < m_chi2cut);
873
874 const std::vector< std::vector<TLorentzVector> > &moms = result->getParticleMoms();
875 double mass = m_CascadeTools->invariantMass(moms[2]);
876 if(chi2CutPassed) {
877 if (mass >= m_MassLower && mass <= m_MassUpper) {
878 cascadeinfoContainer->push_back(result.release());
879 } else {
880 ATH_MSG_DEBUG("Candidate rejected by the mass cut: mass = "
881 << mass << " != (" << m_MassLower << ", " << m_MassUpper << ")" );
882 }
883 }
884 }
885
886 } //Iterate over K0 vertices
887
888 } //Iterate over D0 vertices
889
890 } //Iterate over Jpsi+pi vertices
891
892 ATH_MSG_DEBUG("cascadeinfoContainer size " << cascadeinfoContainer->size());
893
894 return StatusCode::SUCCESS;
895 }
896
897}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
#define BPHYS_CHECK(EXP)
Useful CHECK macro.
: B-physics xAOD helpers.
ATLAS-specific HepMC functions.
#define x
const_iterator cbegin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
const_iterator cend() const noexcept
Return a const_iterator pointing past the end of the collection.
static void PrepareVertexLinks(Trk::VxCascadeInfo *result, const xAOD::TrackParticleContainer *importedTrackCollection)
static const xAOD::Vertex * FindVertex(const xAOD::VertexContainer *c, const xAOD::Vertex *v)
static void SetVectorInfo(xAOD::BPhysHelper &, const Trk::VxCascadeInfo *)
static bool LinkVertices(SG::Decorator< VertexLinkVector > &decor, const std::vector< const xAOD::Vertex * > &vertices, const xAOD::VertexContainer *vertexContainer, const xAOD::Vertex *vert)
std::vector< std::string > m_cascadeOutputsKeys
PublicToolHandle< DerivationFramework::CascadeTools > m_CascadeTools
PublicToolHandle< Trk::V0Tools > m_V0Tools
std::string m_hypoName
name of the mass hypothesis.
JpsiPlusDs1Cascade(const std::string &t, const std::string &n, const IInterface *p)
ToolHandle< Trk::TrkVKalVrtFitter > m_iVertexFitter
virtual StatusCode initialize() override
virtual StatusCode addBranches(const EventContext &ctx) const override
std::string m_VxPrimaryCandidateName
Name of primary vertex container // FIXME Use Handles.
PublicToolHandle< Analysis::PrimaryVertexRefitter > m_pvRefitter
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo_key
StatusCode performSearch(std::vector< Trk::VxCascadeInfo * > *cascadeinfoContainer, const EventContext &ctx) const
Helper class to provide type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
bool setMass(const float val)
Set given invariant mass and its error.
bool setMassErr(const float val)
invariant mass error
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .).
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
float charge() const
Returns the charge.
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.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:116
THE reconstruction tool.
std::vector< const xAOD::TrackParticle * > TrackBag
ElementLink< xAOD::VertexContainer > VertexLink
std::vector< VertexLink > VertexLinkVector
static const int KPLUS
static const int MUON
static const int BCPLUS
static const int K0S
static const int PIPLUS
static const int JPSI
static const int D0
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
VertexAuxContainer_v1 VertexAuxContainer
Definition of the current jet auxiliary container.
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".