59 ATH_MSG_FATAL(
"Incorrect number of Psi daughters (should be 3 or 4)");
60 return StatusCode::FAILURE;
63 constexpr int topoN = 3;
66 return StatusCode::FAILURE;
68 std::array<SG::WriteHandle<xAOD::VertexContainer>, topoN> VtxWriteHandles;
int ikey(0);
71 ATH_CHECK( VtxWriteHandles[ikey].record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
80 if (pvContainer.
cptr()->size()==0) {
82 return StatusCode::RECOVERABLE;
91 ATH_CHECK( refPvContainer.
record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()) );
94 std::vector<Trk::VxCascadeInfo*> cascadeinfoContainer;
95 std::vector<Trk::VxCascadeInfo*> cascadeinfoContainer_noConstr;
104 SG::AuxElement::Decorator<VertexLinkVector> CascadeLinksDecor(
"CascadeVertexLinks");
105 SG::AuxElement::Decorator<VertexLinkVector> PsiLinksDecor(
"PsiVertexLinks");
106 SG::AuxElement::Decorator<VertexLinkVector> JpsiLinksDecor(
"JpsiVertexLinks");
107 SG::AuxElement::Decorator<float> chi2_decor(
"ChiSquared");
108 SG::AuxElement::Decorator<int> ndof_decor(
"nDoF");
109 SG::AuxElement::Decorator<float> chi2_nc_decor(
"ChiSquared_nc");
110 SG::AuxElement::Decorator<int> ndof_nc_decor(
"nDoF_nc");
111 SG::AuxElement::Decorator<float> Pt_decor(
"Pt");
112 SG::AuxElement::Decorator<float> PtErr_decor(
"PtErr");
113 SG::AuxElement::Decorator<float> chi2_SV1_decor(
"ChiSquared_SV1");
114 SG::AuxElement::Decorator<float> chi2_nc_SV1_decor(
"ChiSquared_nc_SV1");
115 SG::AuxElement::Decorator<float> chi2_V1_decor(
"ChiSquared_V1");
116 SG::AuxElement::Decorator<int> ndof_V1_decor(
"nDoF_V1");
117 SG::AuxElement::Decorator<float> lxy_SV1_decor(
"lxy_SV1");
118 SG::AuxElement::Decorator<float> lxyErr_SV1_decor(
"lxyErr_SV1");
119 SG::AuxElement::Decorator<float> a0xy_SV1_decor(
"a0xy_SV1");
120 SG::AuxElement::Decorator<float> a0xyErr_SV1_decor(
"a0xyErr_SV1");
121 SG::AuxElement::Decorator<float> a0z_SV1_decor(
"a0z_SV1");
122 SG::AuxElement::Decorator<float> a0zErr_SV1_decor(
"a0zErr_SV1");
123 SG::AuxElement::Decorator<float> chi2_SV2_decor(
"ChiSquared_SV2");
124 SG::AuxElement::Decorator<float> chi2_nc_SV2_decor(
"ChiSquared_nc_SV2");
125 SG::AuxElement::Decorator<float> chi2_V2_decor(
"ChiSquared_V2");
126 SG::AuxElement::Decorator<int> ndof_V2_decor(
"nDoF_V2");
127 SG::AuxElement::Decorator<float> lxy_SV2_decor(
"lxy_SV2");
128 SG::AuxElement::Decorator<float> lxyErr_SV2_decor(
"lxyErr_SV2");
129 SG::AuxElement::Decorator<float> a0xy_SV2_decor(
"a0xy_SV2");
130 SG::AuxElement::Decorator<float> a0xyErr_SV2_decor(
"a0xyErr_SV2");
131 SG::AuxElement::Decorator<float> a0z_SV2_decor(
"a0z_SV2");
132 SG::AuxElement::Decorator<float> a0zErr_SV2_decor(
"a0zErr_SV2");
140 for(
size_t ic=0; ic<cascadeinfoContainer.size(); ic++) {
142 if(cascade_info==
nullptr) {
149 const std::vector<xAOD::Vertex*> &cascadeVertices = cascade_info->
vertices();
150 if(cascadeVertices.size() != topoN)
ATH_MSG_ERROR(
"Incorrect number of vertices");
151 if(cascadeVertices[0]==
nullptr || cascadeVertices[1]==
nullptr || cascadeVertices[2]==
nullptr)
ATH_MSG_ERROR(
"Error null vertex");
153 for(
int i=0; i<topoN; i++) VtxWriteHandles[i].ptr()->push_back(cascadeVertices[i]);
156 const auto mainVertex = cascadeVertices[2];
157 const std::vector< std::vector<TLorentzVector> > &moms = cascade_info->
getParticleMoms();
160 std::vector<VertexLink> precedingVertexLinks;
164 if( vertexLink1.
isValid() ) precedingVertexLinks.push_back( vertexLink1 );
168 if( vertexLink2.
isValid() ) precedingVertexLinks.push_back( vertexLink2 );
169 CascadeLinksDecor(*mainVertex) = precedingVertexLinks;
179 std::vector<const xAOD::Vertex*> jpsiVerticestoLink;
180 if(jpsiVertex) jpsiVerticestoLink.push_back(jpsiVertex);
184 std::vector<const xAOD::Vertex*> psiVerticestoLink;
185 if(psiVertex) psiVerticestoLink.push_back(psiVertex);
206 chi2_decor(*mainVertex) = cascade_info->
fitChi2();
207 ndof_decor(*mainVertex) = cascade_info->
nDoF();
208 chi2_nc_decor(*mainVertex) = cascade_info_noConstr ? cascade_info_noConstr->
fitChi2() : -999999.;
209 ndof_nc_decor(*mainVertex) = cascade_info_noConstr ? cascade_info_noConstr->
nDoF() : -1;
212 chi2_SV1_decor(*cascadeVertices[0]) =
m_V0Tools->chisq(cascadeVertices[0]);
213 chi2_nc_SV1_decor(*cascadeVertices[0]) = cascade_info_noConstr ?
m_V0Tools->chisq(cascade_info_noConstr->
vertices()[0]) : -999999.;
214 chi2_V1_decor(*cascadeVertices[0]) =
m_V0Tools->chisq(psiVertex);
215 ndof_V1_decor(*cascadeVertices[0]) =
m_V0Tools->ndof(psiVertex);
216 lxy_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->lxy(moms[0],cascadeVertices[0],mainVertex);
217 lxyErr_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->lxyError(moms[0],cascade_info->
getCovariance()[0],cascadeVertices[0],mainVertex);
218 a0z_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->a0z(moms[0],cascadeVertices[0],mainVertex);
219 a0zErr_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->a0zError(moms[0],cascade_info->
getCovariance()[0],cascadeVertices[0],mainVertex);
220 a0xy_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->a0xy(moms[0],cascadeVertices[0],mainVertex);
221 a0xyErr_SV1_decor(*cascadeVertices[0]) =
m_CascadeTools->a0xyError(moms[0],cascade_info->
getCovariance()[0],cascadeVertices[0],mainVertex);
224 chi2_SV2_decor(*cascadeVertices[1]) =
m_V0Tools->chisq(cascadeVertices[1]);
225 chi2_nc_SV2_decor(*cascadeVertices[1]) = cascade_info_noConstr ?
m_V0Tools->chisq(cascade_info_noConstr->
vertices()[1]) : -999999.;
226 chi2_V2_decor(*cascadeVertices[1]) =
m_V0Tools->chisq(jpsiVertex);
227 ndof_V2_decor(*cascadeVertices[1]) =
m_V0Tools->ndof(jpsiVertex);
228 lxy_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->lxy(moms[1],cascadeVertices[1],mainVertex);
229 lxyErr_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->lxyError(moms[1],cascade_info->
getCovariance()[1],cascadeVertices[1],mainVertex);
230 a0z_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->a0z(moms[1],cascadeVertices[1],mainVertex);
231 a0zErr_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->a0zError(moms[1],cascade_info->
getCovariance()[1],cascadeVertices[1],mainVertex);
232 a0xy_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->a0xy(moms[1],cascadeVertices[1],mainVertex);
233 a0xyErr_SV2_decor(*cascadeVertices[1]) =
m_CascadeTools->a0xyError(moms[1],cascade_info->
getCovariance()[1],cascadeVertices[1],mainVertex);
241 for (
auto cascade_info : cascadeinfoContainer)
delete cascade_info;
242 for (
auto cascade_info_noConstr : cascadeinfoContainer_noConstr)
delete cascade_info_noConstr;
244 return StatusCode::SUCCESS;
336 StatusCode
JpsiPlusPsiCascade::performSearch(std::vector<Trk::VxCascadeInfo*> *cascadeinfoContainer, std::vector<Trk::VxCascadeInfo*> *cascadeinfoContainer_noConstr,
const EventContext& ctx)
const {
338 assert(cascadeinfoContainer!=
nullptr && cascadeinfoContainer_noConstr!=
nullptr);
344 std::vector<const xAOD::TrackParticle*> tracksJpsi;
345 std::vector<const xAOD::TrackParticle*> tracksDiTrk;
346 std::vector<const xAOD::TrackParticle*> tracksPsi;
347 std::vector<const xAOD::TrackParticle*> tracksJpsi2;
348 std::vector<double> massesPsi;
364 std::vector<const xAOD::Vertex*> selectedJpsiCandidates;
365 for(
auto vxcItr=jpsiContainer.
cptr()->cbegin(); vxcItr!=jpsiContainer.
cptr()->cend(); ++vxcItr) {
371 if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
378 double mass_jpsi2 =
m_V0Tools->invariantMass(*vxcItr, massesJpsi2);
379 if (mass_jpsi2 < m_jpsi2MassLower || mass_jpsi2 >
m_jpsi2MassUpper)
continue;
381 double chi2DOF = (*vxcItr)->chiSquared()/(*vxcItr)->numberDoF();
384 selectedJpsiCandidates.push_back(*vxcItr);
386 if(selectedJpsiCandidates.size()==0)
return StatusCode::SUCCESS;
389 std::vector<const xAOD::Vertex*> selectedPsiCandidates;
390 for(
auto vxcItr=psiContainer.
cptr()->cbegin(); vxcItr!=psiContainer.
cptr()->cend(); ++vxcItr) {
396 if(flagAcc.isAvailable(*vtx) && flagAcc(*vtx)) {
403 double mass_psi =
m_V0Tools->invariantMass(*vxcItr,massesPsi);
404 if(mass_psi < m_psiMassLower || mass_psi >
m_psiMassUpper)
continue;
407 TLorentzVector p4_mu1, p4_mu2;
408 p4_mu1.SetPtEtaPhiM( (*vxcItr)->trackParticle(0)->pt(),
409 (*vxcItr)->trackParticle(0)->eta(),
411 p4_mu2.SetPtEtaPhiM( (*vxcItr)->trackParticle(1)->pt(),
412 (*vxcItr)->trackParticle(1)->eta(),
414 double mass_jpsi = (p4_mu1 + p4_mu2).M();
415 if (mass_jpsi < m_jpsiMassLower || mass_jpsi >
m_jpsiMassUpper)
continue;
418 TLorentzVector p4_trk1, p4_trk2;
419 p4_trk1.SetPtEtaPhiM( (*vxcItr)->trackParticle(2)->pt(),
420 (*vxcItr)->trackParticle(2)->eta(),
422 p4_trk2.SetPtEtaPhiM( (*vxcItr)->trackParticle(3)->pt(),
423 (*vxcItr)->trackParticle(3)->eta(),
425 double mass_diTrk = (p4_trk1 + p4_trk2).M();
429 double chi2DOF = (*vxcItr)->chiSquared()/(*vxcItr)->numberDoF();
432 selectedPsiCandidates.push_back(*vxcItr);
434 if(selectedPsiCandidates.size()==0)
return StatusCode::SUCCESS;
436 std::vector<std::pair<const xAOD::Vertex*, const xAOD::Vertex*> > candidatePairs;
437 for(
auto jpsiItr=selectedJpsiCandidates.cbegin(); jpsiItr!=selectedJpsiCandidates.cend(); ++jpsiItr) {
439 for(
size_t i=0; i<(*jpsiItr)->nTrackParticles(); i++) tracksJpsi2.push_back((*jpsiItr)->trackParticle(i));
440 for(
auto psiItr=selectedPsiCandidates.cbegin(); psiItr!=selectedPsiCandidates.cend(); ++psiItr) {
442 for(
size_t j=0; j<(*psiItr)->nTrackParticles(); j++) {
443 if(std::find(tracksJpsi2.cbegin(), tracksJpsi2.cend(), (*psiItr)->trackParticle(j)) != tracksJpsi2.cend()) {
skip =
true;
break; }
446 candidatePairs.push_back(std::pair<const xAOD::Vertex*, const xAOD::Vertex*>(*jpsiItr,*psiItr));
450 std::sort( candidatePairs.begin(), candidatePairs.end(), [](std::pair<const xAOD::Vertex*, const xAOD::Vertex*>
a, std::pair<const xAOD::Vertex*, const xAOD::Vertex*> b) { return a.first->chiSquared()/a.first->numberDoF()+a.second->chiSquared()/a.second->numberDoF() < b.first->chiSquared()/b.first->numberDoF()+b.second->chiSquared()/b.second->numberDoF(); } );
452 candidatePairs.erase(candidatePairs.begin()+
m_maxCandidates, candidatePairs.end());
455 for(
size_t ic=0; ic<candidatePairs.size(); ic++) {
456 const xAOD::Vertex* jpsiVertex = candidatePairs[ic].first;
457 const xAOD::Vertex* psiVertex = candidatePairs[ic].second;
461 if (tracksJpsi2.size() != 2 || massesJpsi2.size() != 2) {
462 ATH_MSG_ERROR(
"Problems with Jpsi input: number of tracks or track mass inputs is not 2!");
466 if (tracksPsi.size() != massesPsi.size()) {
467 ATH_MSG_ERROR(
"Problems with Psi input: number of tracks or track mass inputs is not correct!");
479 TLorentzVector p4_moth;
492 std::unique_ptr<Trk::IVKalState> state =
m_iVertexFitter->makeState(ctx);
498 std::vector<Trk::VertexID> vrtList;
507 vrtList.push_back(vID1);
515 vrtList.push_back(vID2);
517 std::vector<const xAOD::TrackParticle*> tp; tp.clear();
518 std::vector<double> tp_masses; tp_masses.clear();
521 std::vector<Trk::VertexID> cnstV; cnstV.clear();
527 std::vector<Trk::VertexID> cnstV; cnstV.clear();
533 std::unique_ptr<Trk::VxCascadeInfo> result(
m_iVertexFitter->fitCascade(*state));
536 if (result !=
nullptr) {
537 for(
auto v : result->vertices()) {
538 if(v->nTrackParticles()==0) {
539 std::vector<ElementLink<xAOD::TrackParticleContainer> > nullLinkVector;
540 v->setTrackParticleLinks(nullLinkVector);
547 result->setSVOwnership(
true);
550 double chi2DOF = result->fitChi2()/result->nDoF();
554 cascadeinfoContainer->push_back(result.release());
562 std::unique_ptr<Trk::IVKalState> state (
m_iVertexFitter->makeState(ctx));
564 std::vector<Trk::VertexID> vrtList_nc;
567 vrtList_nc.push_back(vID1_nc);
569 vrtList_nc.push_back(vID2_nc);
571 std::vector<const xAOD::TrackParticle*> tp; tp.clear();
572 std::vector<double> tp_masses; tp_masses.clear();
575 std::unique_ptr<Trk::VxCascadeInfo> result_nc(
m_iVertexFitter->fitCascade(*state));
577 if (result_nc !=
nullptr) {
578 for(
auto v : result_nc->vertices()) {
579 if(v->nTrackParticles()==0) {
580 std::vector<ElementLink<xAOD::TrackParticleContainer> > nullLinkVector;
581 v->setTrackParticleLinks(nullLinkVector);
588 result_nc->setSVOwnership(
true);
589 cascadeinfoContainer_noConstr->push_back(result_nc.release());
591 else cascadeinfoContainer_noConstr->push_back(0);
593 else cascadeinfoContainer_noConstr->push_back(0);
597 return StatusCode::SUCCESS;