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