19 #include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
22 #include "CLHEP/Vector/LorentzVector.h"
29 declareInterface<V0Tools>(
this);
32 V0Tools::~V0Tools() =
default;
37 return StatusCode::SUCCESS;
40 double V0Tools::invariantMass(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
const
42 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
44 return invariantMass(vxCandidate,
masses);
49 double V0Tools::invariantMass(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
51 double px = 0.,
py = 0.,
pz = 0.,
e = 0.;
53 if (
masses.size() != NTrk) {
54 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
57 for(
unsigned int it=0;
it<NTrk;
it++) {
60 px += lorentz_trk.Px();
61 py += lorentz_trk.Py();
62 pz += lorentz_trk.Pz();
67 return (msq>0.) ? sqrt(msq) : 0.;
70 double V0Tools::invariantMassError(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
const
72 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
74 return invariantMassError(vxCandidate,
masses);
77 double V0Tools::invariantMassError(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
80 if (
masses.size() != NTrk) {
81 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
84 double error = -999999.;
85 auto fullCov = convertCovMatrix(vxCandidate);
86 if (fullCov.size() == 0) {
87 ATH_MSG_DEBUG(
"0 pointer for full covariance. Making-up one from the vertex and tracks covariances");
90 unsigned int ndim = fullCov.rows();
92 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
94 }
else if (ndim == 3*NTrk+3) {
102 double V0Tools::massErrorV0Fitter(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
const
104 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
106 return massErrorV0Fitter(vxCandidate,
masses);
109 double V0Tools::massErrorV0Fitter(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
112 if (
masses.size() != NTrk) {
113 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
116 auto fullCov = convertCovMatrix(vxCandidate);
117 if (fullCov.size() == 0)
return -999999.;
118 unsigned int ndim = fullCov.rows();
119 double E=0., Px=0., Py=0., Pz=0.;
120 std::vector<double>phi(NTrk), theta(NTrk),
qOverP(NTrk),
charge(NTrk),
e(NTrk);
121 std::vector<double>dm2dphi(NTrk), dm2dtheta(NTrk), dm2dqOverP(NTrk);
122 for(
unsigned int it=0;
it<NTrk;
it++) {
125 double trkCharge = 1.;
126 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
132 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
140 double msq =
E*
E - Px*Px - Py*Py - Pz*Pz;
141 double mass = (msq>0.) ? sqrt(msq) : 0.;
143 for(
unsigned int it=0;
it<NTrk;
it++) {
152 for(
unsigned int it=0;
it<NTrk;
it++) {
153 D_vec(5*
it+0,0) = 0.;
154 D_vec(5*
it+1,0) = 0.;
155 D_vec(5*
it+2,0) = dm2dphi[
it];
156 D_vec(5*
it+3,0) = dm2dtheta[
it];
157 D_vec(5*
it+4,0) = dm2dqOverP[
it];
159 Amg::MatrixX V0_merr = D_vec.transpose() * fullCov.block(0,0,ndim-3,ndim-3) * D_vec;
161 double massVarsq = V0_merr(0,0);
162 if (massVarsq <= 0.)
ATH_MSG_DEBUG(
"massError: negative sqrt massVarsq " << massVarsq);
163 double massVar = (massVarsq>0.) ? sqrt(massVarsq) : 0.;
164 double massErr = massVar/(2.*
mass);
168 double V0Tools::massErrorVKalVrt(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
const
170 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
171 return massErrorVKalVrt(vxCandidate,
masses);
174 double V0Tools::massErrorVKalVrt(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
177 if (
masses.size() != NTrk) {
178 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
181 std::vector<xAOD::TrackParticle::FourMom_t> particleMom(NTrk);
182 std::vector<
AmgMatrix(3,3)> particleDeriv(NTrk);
184 AmgMatrix(3,3) tmpDeriv; tmpDeriv.setZero();
185 auto fullCov = convertCovMatrix(vxCandidate);
186 if (fullCov.
size() == 0) return -999999.;
188 for(
unsigned int it=0;
it<NTrk;
it++){
191 double phi = bPer->parameters()[
Trk::phi];
192 double theta = bPer->parameters()[
Trk::theta];
194 double px =
cos(phi)*
sin(theta)/fabs(invP);
195 double py =
sin(phi)*
sin(theta)/fabs(invP);
196 double pz =
cos(theta)/fabs(invP);
198 double e = (esq>0.) ? sqrt(esq) : 0.;
201 particleMom[
it] =
tmp;
205 tmpDeriv(0,0) = -
tmp.Py();
206 tmpDeriv(1,0) =
tmp.Px();
208 tmpDeriv(0,1) =
cos(phi) *
tmp.Pz();
209 tmpDeriv(1,1) =
sin(phi) *
tmp.Pz();
210 tmpDeriv(2,1) = -
sin(theta)/fabs(invP);
211 tmpDeriv(0,2) = -
tmp.Px()/invP;
212 tmpDeriv(1,2) = -
tmp.Py()/invP;
213 tmpDeriv(2,2) = -
tmp.Pz()/invP;
214 particleDeriv[
it] = tmpDeriv;
218 std::vector<double> Deriv(3*NTrk+3, 0.);
219 for(
unsigned int it=0;
it<NTrk;
it++){
221 double dMdPx = ( totalMom.E() * particleMom[
it].Px()/particleMom[
it].E() - totalMom.Px() ) / totalMom.M();
222 double dMdPy = ( totalMom.E() * particleMom[
it].Py()/particleMom[
it].E() - totalMom.Py() ) / totalMom.M();
223 double dMdPz = ( totalMom.E() * particleMom[
it].Pz()/particleMom[
it].E() - totalMom.Pz() ) / totalMom.M();
225 double dMdPhi = dMdPx*particleDeriv[
it](0,0) + dMdPy*particleDeriv[
it](1,0) + dMdPz*particleDeriv[
it](2,0);
226 double dMdTheta = dMdPx*particleDeriv[
it](0,1) + dMdPy*particleDeriv[
it](1,1) + dMdPz*particleDeriv[
it](2,1);
227 double dMdInvP = dMdPx*particleDeriv[
it](0,2) + dMdPy*particleDeriv[
it](1,2) + dMdPz*particleDeriv[
it](2,2);
229 Deriv[3*
it + 3 + 0] = dMdPhi; Deriv[3*
it + 3 + 1] = dMdTheta; Deriv[3*
it + 3 + 2] = dMdInvP;
234 for(
unsigned int i=0;
i<3*NTrk+3;
i++){
235 for(
unsigned int j=0; j<3*NTrk+3; j++){
236 err += Deriv[
i]*( fullCov)(
i,j)*Deriv[j];
240 return (
err>0.) ? sqrt(
err) : 0.;
243 double V0Tools::massErrorVxCandidate(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
const
245 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
247 return massErrorVxCandidate(vxCandidate,
masses);
250 double V0Tools::massErrorVxCandidate(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
253 if (
masses.size() != NTrk) {
254 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
257 double E=0., Px=0., Py=0., Pz=0.;
258 std::vector<double>phi(NTrk), theta(NTrk),
qOverP(NTrk),
charge(NTrk),
e(NTrk);
259 std::vector<double>dm2dphi(NTrk), dm2dtheta(NTrk), dm2dqOverP(NTrk);
261 for(
unsigned int it=0;
it<NTrk;
it++) {
265 V0_cor(5*
it+2,5*
it+2) = (*cov_tmp)(2,2);
266 V0_cor(5*
it+2,5*
it+3) = (*cov_tmp)(2,3);
267 V0_cor(5*
it+2,5*
it+4) = (*cov_tmp)(2,4);
268 V0_cor(5*
it+3,5*
it+3) = (*cov_tmp)(3,3);
269 V0_cor(5*
it+3,5*
it+4) = (*cov_tmp)(3,4);
270 V0_cor(5*
it+4,5*
it+4) = (*cov_tmp)(4,4);
271 V0_cor(5*
it+3,5*
it+2) = (*cov_tmp)(2,3);
272 V0_cor(5*
it+4,5*
it+2) = (*cov_tmp)(2,4);
273 V0_cor(5*
it+4,5*
it+3) = (*cov_tmp)(3,4);
274 double trkCharge = 1.;
275 if (bPer->parameters()(
Trk::qOverP) < 0.) trkCharge = -1.;
281 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
289 double msq =
E*
E - Px*Px - Py*Py - Pz*Pz;
290 double mass = (msq>0.) ? sqrt(msq) : 0.;
292 for(
unsigned int it=0;
it<NTrk;
it++) {
301 for(
unsigned int it=0;
it<NTrk;
it++) {
302 D_vec(5*
it+0,0) = 0.;
303 D_vec(5*
it+1,0) = 0.;
304 D_vec(5*
it+2,0) = dm2dphi[
it];
305 D_vec(5*
it+3,0) = dm2dtheta[
it];
306 D_vec(5*
it+4,0) = dm2dqOverP[
it];
309 Amg::MatrixX V0_merr = D_vec.transpose() * V0_cor * D_vec;
311 double massVarsq = V0_merr(0,0);
312 if (massVarsq <= 0.)
ATH_MSG_DEBUG(
"massError: negative sqrt massVarsq " << massVarsq);
313 double massVar = (massVarsq>0.) ? sqrt(massVarsq) : 0.;
314 double massErr = massVar/(2.*
mass);
318 double V0Tools::invariantMassProbability(
const xAOD::Vertex * vxCandidate,
double V0Mass,
double posTrackMass,
double negTrackMass)
const
320 std::array<double, 2>
masses = {posTrackMass , negTrackMass};
322 return invariantMassProbability(vxCandidate,V0Mass,
masses);
325 double V0Tools::invariantMassProbability(
const xAOD::Vertex * vxCandidate,
double V0Mass, std::span<const double>
masses)
const
327 double mass = invariantMass(vxCandidate,
masses);
328 double massErr = invariantMassError(vxCandidate,
masses);
333 Genfun::CumulativeChiSquare myCumulativeChiSquare(
ndf);
335 double achi2prob = 1.-myCumulativeChiSquare(
chi2);
347 double V0Tools::massProbability(
double V0Mass,
double mass,
double massErr)
const
351 double chi2 = (V0Mass -
mass)*(V0Mass -
mass)/(massErr*massErr);
353 Genfun::CumulativeChiSquare myCumulativeChiSquare(
ndf);
355 double achi2prob = 1.-myCumulativeChiSquare(
chi2);
377 if (NTrk != 2)
return mom;
378 for(
unsigned int it=0;
it<NTrk;
it++) {
389 if (NTrk != 2)
return mom;
390 for(
unsigned int it=0;
it<NTrk;
it++) {
401 for(
unsigned int it=0;
it<NTrk;
it++) {
412 double e = (
tmp>0.) ? sqrt(
tmp) : 0.;
422 double e = (
tmp>0.) ? sqrt(
tmp) : 0.;
432 double e = (
tmp>0.) ? sqrt(
tmp) : 0.;
441 double e = (
tmp>0.) ? sqrt(
tmp) : 0.;
457 double V0Tools::vertexProbability(
const xAOD::Vertex * vxCandidate)
const
459 float dof =
ndof(vxCandidate);
461 Genfun::CumulativeChiSquare myCumulativeChiSquare(dof);
462 float chi = chisq(vxCandidate);
464 double chi2prob = 1.-myCumulativeChiSquare(chi);
484 return vxCandidate->
position().perp();
500 double rxy = (rxysq>0.) ? sqrt(rxysq) : 0.;
501 double drdx =
dx/rxy;
502 double drdy =
dy/rxy;
506 Amg::
MatrixX rxy_err = D_vec.transpose() *
cov.block(0,0,2,2) * D_vec;
507 double rxyVar = rxy_err(0,0);
514 double dx = vxCandidate->position().x();
515 double dy = vxCandidate->position().y();
516 double rxyVar = rxy_var(
dx,
dy,
cov);
517 if (rxyVar <= 0.)
ATH_MSG_DEBUG(
"rxyError: negative sqrt rxyVar " << rxyVar);
518 return (rxyVar>0.) ? sqrt(rxyVar) : 0.;
525 double dx = vert.x();
526 double dy = vert.y();
528 if (rxyVar <= 0.)
ATH_MSG_DEBUG(
"rxyError: negative sqrt rxyVar " << rxyVar);
529 return (rxyVar>0.) ? sqrt(rxyVar) : 0.;
536 double dx = vert.x();
537 double dy = vert.y();
539 if (rxyVar <= 0.)
ATH_MSG_DEBUG(
"rxyError: negative sqrt rxyVar " << rxyVar);
540 return (rxyVar>0.) ? sqrt(rxyVar) : 0.;
545 return V0Momentum(vxCandidate).perp();
552 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
553 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
554 std::vector<double>dPTdqOverP(NTrk), dPTdtheta(NTrk), dPTdphi(NTrk);
556 auto fullCov = convertCovMatrix(vxCandidate);
557 for(
unsigned int it=0;
it<NTrk;
it++) {
559 double trkCharge = 1.;
560 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
561 double phi = bPer->parameters()[
Trk::phi];
562 double theta = bPer->parameters()[
Trk::theta];
573 double PTsq = Px*Px+Py*Py;
574 double PT = (PTsq>0.) ? sqrt(PTsq) : 0.;
576 for(
unsigned int it=0;
it<NTrk;
it++) {
577 dPTdqOverP[
it] = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
578 dPTdtheta[
it] = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
579 dPTdphi[
it] = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
582 unsigned int ndim = 0;
583 if (fullCov.size() == 0) {
586 ndim = fullCov.rows();
590 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
592 for(
unsigned int it=0;
it<NTrk;
it++) {
593 D_vec(5*
it+0,0) = 0.;
594 D_vec(5*
it+1,0) = 0.;
595 D_vec(5*
it+2,0) = dPTdphi[
it];
596 D_vec(5*
it+3,0) = dPTdtheta[
it];
597 D_vec(5*
it+4,0) = dPTdqOverP[
it];
599 if (fullCov.size() == 0) {
601 PtErrSq = D_vec.transpose() * V0_cov * D_vec;
603 PtErrSq = D_vec.transpose() * fullCov.block(0,0,5*NTrk-1,5*NTrk-1) * D_vec;
605 }
else if (ndim == 3*NTrk+3) {
607 for(
unsigned int it=0;
it<NTrk;
it++) {
608 D_vec(3*
it+0,0) = dPTdphi[
it];
609 D_vec(3*
it+1,0) = dPTdtheta[
it];
610 D_vec(3*
it+2,0) = dPTdqOverP[
it];
612 PtErrSq = D_vec.transpose() * fullCov.block(3,3,ndim-3,ndim-3) * D_vec;
615 double PtErrsq = PtErrSq(0,0);
616 if (PtErrsq <= 0.)
ATH_MSG_DEBUG(
"ptError: negative sqrt PtErrsq " << PtErrsq);
617 return (PtErrsq>0.) ? sqrt(PtErrsq) : 0.;
622 assert(vxCandidate!=0);
623 if(
nullptr == vxCandidate) {
630 double p2 =
P.mag2();
631 double pdr =
P.dot((
sv -
pv));
632 return sv -
P*pdr/
p2;
644 double sepVarsq = sepVarsqMat(0,0);
645 if (sepVarsq <= 0.)
ATH_MSG_DEBUG(
"separation: negative sqrt sepVarsq " << sepVarsq);
646 double sepVar = (sepVarsq>0.) ? sqrt(sepVarsq) : 0.;
659 double sepVarsq = sepVarsqMat(0,0);
660 if (sepVarsq <= 0.)
ATH_MSG_DEBUG(
"separation: negative sqrt sepVarsq " << sepVarsq);
661 double sepVar = (sepVarsq>0.) ? sqrt(sepVarsq) : 0.;
667 double cosineTheta_xy = cosTheta_xy(vxCandidate,
vertex);
668 double sinTheta_xy = ((1.-cosineTheta_xy*cosineTheta_xy)>0.) ? sqrt((1.-cosineTheta_xy*cosineTheta_xy)) : 0.;
669 return (vtx(vxCandidate)-
vertex->position()).perp() * sinTheta_xy;
683 double cosineTheta = cosTheta(vxCandidate,
vertex);
684 double sinTheta = ((1.-cosineTheta*cosineTheta)>0.) ? sqrt((1.-cosineTheta*cosineTheta)) : 0.;
685 return (vtx(vxCandidate)-
vertex->position()).mag() * sinTheta;
693 double dx = vert.x();
694 double dy = vert.y();
695 double dz = vert.z();
696 double Px=0., Py=0., Pz=0.;
697 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
698 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
699 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk);
700 std::vector<double>da0dqOverP(NTrk), da0dtheta(NTrk), da0dphi(NTrk);
702 auto fullCov = convertCovMatrix(vxCandidate);
703 for(
unsigned int it=0;
it<NTrk;
it++) {
705 double trkCharge = 1.;
706 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
707 double phi = bPer->parameters()[
Trk::phi];
708 double theta = bPer->parameters()[
Trk::theta];
722 double P2 = Px*Px+Py*Py+Pz*Pz;
723 double B = Px*
dx+Py*
dy+Pz*dz;
725 double da0dx = (Px*Pz)/P2;
726 double da0dy = (Py*Pz)/P2;
727 double da0dz = (Pz*Pz)/P2 - 1.;
728 double da0dx0 = -da0dx;
729 double da0dy0 = -da0dy;
730 double da0dz0 = -da0dz;
731 for(
unsigned int it=0;
it<NTrk;
it++) {
732 double dP2dqOverP = 2.*(Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it]);
733 double dP2dtheta = 2.*(Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it]);
734 double dP2dphi = 2.*(Px*dpxdphi[
it]+Py*dpydphi[
it]);
735 da0dqOverP[
it] = (B*(P2*dpzdqOverP[
it]-Pz*dP2dqOverP) +
736 Pz*P2*(
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it]+dz*dpzdqOverP[
it]))/(P2*P2);
737 da0dtheta[
it] = (B*(P2*dpzdtheta[
it]-Pz*dP2dtheta) +
738 Pz*P2*(
dx*dpxdtheta[
it]+
dy*dpydtheta[
it]+dz*dpzdtheta[
it]))/(P2*P2);
739 da0dphi[
it] = -(B*Pz*dP2dphi -
740 Pz*P2*(
dx*dpxdphi[
it]+
dy*dpydphi[
it]))/(P2*P2);
743 unsigned int ndim = 0;
744 if (fullCov.size() != 0) {
745 ndim = fullCov.rows();
751 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
753 for(
unsigned int it=0;
it<NTrk;
it++) {
756 D_vec(5*
it+2) = da0dphi[
it];
757 D_vec(5*
it+3) = da0dtheta[
it];
758 D_vec(5*
it+4) = da0dqOverP[
it];
760 D_vec(5*NTrk+0) = da0dx;
761 D_vec(5*NTrk+1) = da0dy;
762 D_vec(5*NTrk+2) = da0dz;
763 D_vec(5*NTrk+3) = da0dx0;
764 D_vec(5*NTrk+4) = da0dy0;
765 D_vec(5*NTrk+5) = da0dz0;
768 if (fullCov.size() != 0) {
769 W_mat.block(0,0,ndim,ndim) = fullCov;
772 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
773 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
775 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
776 V0_err = D_vec.transpose() * W_mat * D_vec;
777 }
else if (ndim == 3*NTrk+3) {
782 for(
unsigned int it=0;
it<NTrk;
it++) {
783 D_vec(3*
it+3) = da0dphi[
it];
784 D_vec(3*
it+4) = da0dtheta[
it];
785 D_vec(3*
it+5) = da0dqOverP[
it];
787 D_vec(3*NTrk+3) = da0dx0;
788 D_vec(3*NTrk+4) = da0dy0;
789 D_vec(3*NTrk+5) = da0dz0;
792 W_mat.block(0,0,ndim,ndim) = fullCov;
793 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
794 V0_err = D_vec.transpose() * W_mat * D_vec;
797 double a0Errsq = V0_err(0,0);
798 if (a0Errsq <= 0.)
ATH_MSG_DEBUG(
"a0Error: negative sqrt a0Errsq " << a0Errsq);
799 double a0Err = (a0Errsq>0.) ? sqrt(a0Errsq) : 0.;
805 return a0Error(vxCandidate,
vertex,
false);
812 double dx = vert.x();
813 double dy = vert.y();
814 double dz = vert.z();
815 double Px=0., Py=0., Pz=0.;
816 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
817 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
818 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk);
819 std::vector<double>da0dqOverP(NTrk), da0dtheta(NTrk), da0dphi(NTrk);
821 auto fullCov = convertCovMatrix(vxCandidate);
822 for(
unsigned int it=0;
it<NTrk;
it++) {
824 double trkCharge = 1.;
825 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
826 double phi = bPer->parameters()[
Trk::phi];
827 double theta = bPer->parameters()[
Trk::theta];
846 cosineTheta = cosTheta(vxCandidate,
vertex);
849 cosineTheta = cosTheta_xy(vxCandidate,
vertex);
850 a0val = a0xy(vxCandidate,
vertex);
854 double P = sqrt(Px*Px+Py*Py+Pz*Pz);
857 double da0dx = (Px/
P*
r*cosineTheta -
dx)/a0val;
858 double da0dy = (Py/
P*
r*cosineTheta -
dy)/a0val;
859 double da0dz = (Pz/
P*
r*cosineTheta - dz)/a0val;
860 double da0dx0 = -da0dx;
861 double da0dy0 = -da0dy;
862 double da0dz0 = -da0dz;
863 for(
unsigned int it=0;
it<NTrk;
it++) {
864 da0dqOverP[
it] = -(
r*cosineTheta/
P)*(da0dx*dpxdqOverP[
it]+da0dy*dpydqOverP[
it]+da0dz*dpzdqOverP[
it]);
865 da0dtheta[
it] = -(
r*cosineTheta/
P)*(da0dx*dpxdtheta[
it]+da0dy*dpydtheta[
it]+da0dz*dpzdtheta[
it]);
866 da0dphi[
it] = -(
r*cosineTheta/
P)*(da0dx*dpxdphi[
it]+da0dy*dpydphi[
it]);
869 unsigned int ndim = 0;
870 if (fullCov.size() != 0) {
871 ndim = fullCov.rows();
877 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
879 for(
unsigned int it=0;
it<NTrk;
it++) {
882 D_vec(5*
it+2) = da0dphi[
it];
883 D_vec(5*
it+3) = da0dtheta[
it];
884 D_vec(5*
it+4) = da0dqOverP[
it];
886 D_vec(5*NTrk+0) = da0dx;
887 D_vec(5*NTrk+1) = da0dy;
888 D_vec(5*NTrk+2) = da0dz;
889 D_vec(5*NTrk+3) = da0dx0;
890 D_vec(5*NTrk+4) = da0dy0;
891 D_vec(5*NTrk+5) = da0dz0;
894 if (fullCov.size() != 0) {
895 W_mat.block(0,0,ndim,ndim) = fullCov;
898 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
899 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
901 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
902 V0_err = D_vec.transpose() * W_mat * D_vec;
903 }
else if (ndim == 3*NTrk+3) {
908 for(
unsigned int it=0;
it<NTrk;
it++) {
909 D_vec(3*
it+3) = da0dphi[
it];
910 D_vec(3*
it+4) = da0dtheta[
it];
911 D_vec(3*
it+5) = da0dqOverP[
it];
913 D_vec(3*NTrk+3) = da0dx0;
914 D_vec(3*NTrk+4) = da0dy0;
915 D_vec(3*NTrk+5) = da0dz0;
918 W_mat.block(0,0,ndim,ndim) = fullCov;
919 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
920 V0_err = D_vec.transpose() * W_mat * D_vec;
923 double a0Errsq = V0_err(0,0);
924 if (a0Errsq <= 0.)
ATH_MSG_DEBUG(
"a0Error: negative sqrt a0Errsq " << a0Errsq);
925 double a0Err = (a0Errsq>0.) ? sqrt(a0Errsq) : 0.;
932 double dx = vert.x();
933 double dy = vert.y();
942 double dx = vert.x();
943 double dy = vert.y();
946 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
947 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
948 std::vector<double>dLxydqOverP(NTrk), dLxydtheta(NTrk), dLxydphi(NTrk);
950 auto fullCov = convertCovMatrix(vxCandidate);
951 for(
unsigned int it=0;
it<NTrk;
it++) {
953 double trkCharge = 1.;
954 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
955 double phi = bPer->parameters()[
Trk::phi];
956 double theta = bPer->parameters()[
Trk::theta];
967 double PTsq = Px*Px+Py*Py;
968 double PT = (PTsq>0.) ? sqrt(PTsq) : 0.;
969 double LXYoverPT = (Px*
dx+Py*
dy)/PTsq;
971 for(
unsigned int it=0;
it<NTrk;
it++) {
972 double dPTdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
973 double dPTdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
974 double dPTdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
975 dLxydqOverP[
it] = (
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it])/
PT-LXYoverPT*dPTdqOverP;
976 dLxydtheta[
it] = (
dx*dpxdtheta[
it]+
dy*dpydtheta[
it])/
PT-LXYoverPT*dPTdtheta;
977 dLxydphi[
it] = (
dx*dpxdphi[
it]+
dy*dpydphi[
it])/
PT-LXYoverPT*dPTdphi;
979 double dLxydx = Px/
PT;
980 double dLxydy = Py/
PT;
981 double dLxydx0 = -dLxydx;
982 double dLxydy0 = -dLxydy;
984 unsigned int ndim = 0;
985 if (fullCov.size() != 0) {
986 ndim = fullCov.rows();
992 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
994 for(
unsigned int it=0;
it<NTrk;
it++) {
997 D_vec(5*
it+2) = dLxydphi[
it];
998 D_vec(5*
it+3) = dLxydtheta[
it];
999 D_vec(5*
it+4) = dLxydqOverP[
it];
1001 D_vec(5*NTrk+0) = dLxydx;
1002 D_vec(5*NTrk+1) = dLxydy;
1003 D_vec(5*NTrk+2) = 0.;
1004 D_vec(5*NTrk+3) = dLxydx0;
1005 D_vec(5*NTrk+4) = dLxydy0;
1006 D_vec(5*NTrk+5) = 0.;
1008 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1009 if (fullCov.size() != 0) {
1010 W_mat.block(0,0,ndim,ndim) = fullCov;
1013 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1014 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1016 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1017 V0_err = D_vec.transpose() * W_mat * D_vec;
1018 }
else if (ndim == 3*NTrk+3) {
1023 for(
unsigned int it=0;
it<NTrk;
it++) {
1024 D_vec(3*
it+3) = dLxydphi[
it];
1025 D_vec(3*
it+4) = dLxydtheta[
it];
1026 D_vec(3*
it+5) = dLxydqOverP[
it];
1028 D_vec(3*NTrk+3) = dLxydx0;
1029 D_vec(3*NTrk+4) = dLxydy0;
1030 D_vec(3*NTrk+5) = 0.;
1032 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1033 W_mat.block(0,0,ndim,ndim) = fullCov;
1034 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1035 V0_err = D_vec.transpose() * W_mat * D_vec;
1038 double LxyErrsq = V0_err(0,0);
1039 if (LxyErrsq <= 0.)
ATH_MSG_DEBUG(
"lxyError: negative sqrt LxyErrsq " << LxyErrsq);
1040 return (LxyErrsq>0.) ? sqrt(LxyErrsq) : 0.;
1046 double dx = vert.x();
1047 double dy = vert.y();
1048 double dz = vert.z();
1057 double dx = vert.x();
1058 double dy = vert.y();
1059 double dz = vert.z();
1061 double Px=0., Py=0., Pz=0.;
1062 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
1063 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
1064 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk);
1065 std::vector<double>dLxyzdqOverP(NTrk), dLxyzdtheta(NTrk), dLxyzdphi(NTrk);
1067 auto fullCov = convertCovMatrix(vxCandidate);
1068 for(
unsigned int it=0;
it<NTrk;
it++) {
1070 double trkCharge = 1.;
1071 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
1072 double phi = bPer->parameters()[
Trk::phi];
1073 double theta = bPer->parameters()[
Trk::theta];
1087 double Psq = Px*Px+Py*Py+Pz*Pz;
1088 double P = (Psq>0.) ? sqrt(Psq) : 0.;
1089 double LXYZoverP = (Px*
dx+Py*
dy+Pz*dz)/Psq;
1091 for(
unsigned int it=0;
it<NTrk;
it++) {
1092 double dPdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it])/
P;
1093 double dPdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/
P;
1094 double dPdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
P;
1095 dLxyzdqOverP[
it] = (
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it]+dz*dpzdqOverP[
it])/
P-LXYZoverP*dPdqOverP;
1096 dLxyzdtheta[
it] = (
dx*dpxdtheta[
it]+
dy*dpydtheta[
it]+dz*dpzdtheta[
it])/
P-LXYZoverP*dPdtheta;
1097 dLxyzdphi[
it] = (
dx*dpxdphi[
it]+
dy*dpydphi[
it])/
P-LXYZoverP*dPdphi;
1099 double dLxyzdx = Px/
P;
1100 double dLxyzdy = Py/
P;
1101 double dLxyzdz = Pz/
P;
1102 double dLxyzdx0 = -dLxyzdx;
1103 double dLxyzdy0 = -dLxyzdy;
1104 double dLxyzdz0 = -dLxyzdz;
1106 unsigned int ndim = 0;
1107 if (fullCov.size() != 0) {
1108 ndim = fullCov.rows();
1114 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
1116 for(
unsigned int it=0;
it<NTrk;
it++) {
1119 D_vec(5*
it+2) = dLxyzdphi[
it];
1120 D_vec(5*
it+3) = dLxyzdtheta[
it];
1121 D_vec(5*
it+4) = dLxyzdqOverP[
it];
1123 D_vec(5*NTrk+0) = dLxyzdx;
1124 D_vec(5*NTrk+1) = dLxyzdy;
1125 D_vec(5*NTrk+2) = dLxyzdz;
1126 D_vec(5*NTrk+3) = dLxyzdx0;
1127 D_vec(5*NTrk+4) = dLxyzdy0;
1128 D_vec(5*NTrk+5) = dLxyzdz0;
1130 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1131 if (fullCov.size() != 0) {
1132 W_mat.block(0,0,ndim,ndim) = fullCov;
1135 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1136 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1138 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1139 V0_err = D_vec.transpose() * W_mat * D_vec;
1140 }
else if (ndim == 3*NTrk+3) {
1145 for(
unsigned int it=0;
it<NTrk;
it++) {
1146 D_vec(3*
it+3) = dLxyzdphi[
it];
1147 D_vec(3*
it+4) = dLxyzdtheta[
it];
1148 D_vec(3*
it+5) = dLxyzdqOverP[
it];
1150 D_vec(3*NTrk+3) = dLxyzdx0;
1151 D_vec(3*NTrk+4) = dLxyzdy0;
1152 D_vec(3*NTrk+5) = dLxyzdz0;
1154 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1155 W_mat.block(0,0,ndim,ndim) = fullCov;
1156 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1157 V0_err = D_vec.transpose() * W_mat * D_vec;
1160 double LxyzErrsq = V0_err(0,0);
1161 if (LxyzErrsq <= 0.)
ATH_MSG_DEBUG(
"lxyzError: negative sqrt LxyzErrsq " << LxyzErrsq);
1162 return (LxyzErrsq>0.) ? sqrt(LxyzErrsq) : 0.;
1167 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
1175 if (
masses.size() != NTrk) {
1176 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1180 double CONST = 1000./299.792;
1181 double M = invariantMass(vxCandidate,
masses);
1182 double LXY = lxy(vxCandidate,
vertex);
1183 double PT = V0Momentum(vxCandidate).perp();
1189 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
1197 if (
masses.size() != NTrk) {
1198 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1203 double mass = invariantMass(vxCandidate,
masses);
1207 double deltaTau = -(massV0-
mass)*cov_i12/cov_i11;
1208 return Tau + deltaTau;
1214 double CONST = 1000./299.792;
1215 double LXY = lxy(vxCandidate,
vertex);
1216 double PT = V0Momentum(vxCandidate).perp();
1223 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
1232 if (
masses.size() != NTrk) {
1233 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1237 double CONST = 1000./299.792;
1238 double PT = V0Momentum(vxCandidate).perp();
1240 double dx = vert.x();
1241 double dy = vert.y();
1242 double M = invariantMass(vxCandidate,
masses);
1243 double E=0., Px=0., Py=0., Pz=0.;
1244 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
1245 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
1246 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk), dedqOverP(NTrk);
1247 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
1249 auto fullCov = convertCovMatrix(vxCandidate);
1250 for(
unsigned int it=0;
it<NTrk;
it++) {
1252 double trkCharge = 1.;
1253 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
1254 double phi = bPer->parameters()[
Trk::phi];
1255 double theta = bPer->parameters()[
Trk::theta];
1258 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
1273 double LXY = Px*
dx+Py*
dy;
1275 for(
unsigned int it=0;
it<NTrk;
it++) {
1276 double dMdqOverP = -(Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it]-
E*dedqOverP[
it])/M;
1277 double dMdtheta = -(Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/M;
1278 double dMdphi = -(Px*dpxdphi[
it]+Py*dpydphi[
it])/M;
1279 double dPTdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
1280 double dPTdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
1281 double dPTdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
1282 double dLXYdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it];
1283 double dLXYdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it];
1284 double dLXYdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
1285 dTaudqOverP[
it] = (LXY*dMdqOverP+M*dLXYdqOverP)/(
PT*
PT)-(2.*LXY*M*dPTdqOverP)/(
PT*
PT*
PT);
1286 dTaudtheta[
it] = (LXY*dMdtheta+M*dLXYdtheta)/(
PT*
PT)-(2.*LXY*M*dPTdtheta)/(
PT*
PT*
PT);
1287 dTaudphi[
it] = (LXY*dMdphi+M*dLXYdphi)/(
PT*
PT)-(2.*LXY*M*dPTdphi)/(
PT*
PT*
PT);
1289 double dTaudx = (M*Px)/(
PT*
PT);
1290 double dTaudy = (M*Py)/(
PT*
PT);
1291 double dTaudx0 = -dTaudx;
1292 double dTaudy0 = -dTaudy;
1294 unsigned int ndim = 0;
1295 if (fullCov.size() != 0) {
1296 ndim = fullCov.rows();
1302 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
1304 for(
unsigned int it=0;
it<NTrk;
it++) {
1307 D_vec(5*
it+2) = dTaudphi[
it];
1308 D_vec(5*
it+3) = dTaudtheta[
it];
1309 D_vec(5*
it+4) = dTaudqOverP[
it];
1311 D_vec(5*NTrk+0) = dTaudx;
1312 D_vec(5*NTrk+1) = dTaudy;
1313 D_vec(5*NTrk+2) = 0.;
1314 D_vec(5*NTrk+3) = dTaudx0;
1315 D_vec(5*NTrk+4) = dTaudy0;
1316 D_vec(5*NTrk+5) = 0.;
1318 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1319 if (fullCov.size() != 0) {
1320 W_mat.block(0,0,ndim,ndim) = fullCov;
1323 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1324 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1326 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1327 V0_err = D_vec.transpose() * W_mat * D_vec;
1328 }
else if (ndim == 3*NTrk+3) {
1333 for(
unsigned int it=0;
it<NTrk;
it++) {
1334 D_vec(3*
it+3) = dTaudphi[
it];
1335 D_vec(3*
it+4) = dTaudtheta[
it];
1336 D_vec(3*
it+5) = dTaudqOverP[
it];
1338 D_vec(3*NTrk+3) = dTaudx0;
1339 D_vec(3*NTrk+4) = dTaudy0;
1340 D_vec(3*NTrk+5) = 0.;
1342 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1343 W_mat.block(0,0,ndim,ndim) = fullCov;
1344 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1345 V0_err = D_vec.transpose() * W_mat * D_vec;
1348 double tauErrsq = V0_err(0,0);
1349 if (tauErrsq <= 0.)
ATH_MSG_DEBUG(
"tauError: negative sqrt tauErrsq " << tauErrsq);
1350 double tauErr = (tauErrsq>0.) ? sqrt(tauErrsq) : 0.;
1351 return CONST*tauErr;
1354 double V0Tools::tauError(
const xAOD::Vertex * vxCandidate,
const xAOD::Vertex*
vertex,
double posTrackMass,
double negTrackMass,
double massV0)
const
1356 std::array<double, 2>
masses = {posTrackMass, negTrackMass};
1364 if (
masses.size() != NTrk) {
1365 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1368 double error = -999999.;
1372 if (cov_i11 > 0.)
error = 1./sqrt(cov_i11);
1380 double CONST = 1000./299.792;
1381 double PT = V0Momentum(vxCandidate).perp();
1383 double dx = vecsub.x();
1384 double dy = vecsub.y();
1386 double Px=0., Py=0.;
1387 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
1388 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
1389 std::vector<double>dPTdtheta(NTrk), dPTdphi(NTrk);
1390 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
1392 auto fullCov = convertCovMatrix(vxCandidate);
1393 for(
unsigned int it=0;
it<NTrk;
it++) {
1395 double trkCharge = 1.;
1396 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
1397 double phi = bPer->parameters()[
Trk::phi];
1398 double theta = bPer->parameters()[
Trk::theta];
1409 double LXY = Px*
dx+Py*
dy;
1411 for(
unsigned int it=0;
it<NTrk;
it++) {
1412 double dPTdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
1413 double dPTdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
1414 double dPTdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
1415 double dLXYdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it];
1416 double dLXYdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it];
1417 double dLXYdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
1418 dTaudqOverP[
it] = M*dLXYdqOverP/(
PT*
PT)-(2.*LXY*M*dPTdqOverP)/(
PT*
PT*
PT);
1419 dTaudtheta[
it] = M*dLXYdtheta/(
PT*
PT)-(2.*LXY*M*dPTdtheta)/(
PT*
PT*
PT);
1420 dTaudphi[
it] = M*dLXYdphi/(
PT*
PT)-(2.*LXY*M*dPTdphi)/(
PT*
PT*
PT);
1422 double dTaudx = (M*Px)/(
PT*
PT);
1423 double dTaudy = (M*Py)/(
PT*
PT);
1424 double dTaudx0 = -dTaudx;
1425 double dTaudy0 = -dTaudy;
1427 unsigned int ndim = 0;
1428 if (fullCov.size() != 0) {
1429 ndim = fullCov.rows();
1435 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
1437 for(
unsigned int it=0;
it<NTrk;
it++) {
1440 D_vec(5*
it+2) = dTaudphi[
it];
1441 D_vec(5*
it+3) = dTaudtheta[
it];
1442 D_vec(5*
it+4) = dTaudqOverP[
it];
1444 D_vec(5*NTrk+0) = dTaudx;
1445 D_vec(5*NTrk+1) = dTaudy;
1446 D_vec(5*NTrk+2) = 0.;
1447 D_vec(5*NTrk+3) = dTaudx0;
1448 D_vec(5*NTrk+4) = dTaudy0;
1449 D_vec(5*NTrk+5) = 0.;
1451 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1452 if (fullCov.size() != 0) {
1453 W_mat.block(0,0,ndim,ndim) = fullCov;
1456 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1457 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1459 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1460 V0_err = D_vec.transpose() * W_mat * D_vec;
1461 }
else if (ndim == 3*NTrk+3) {
1466 for(
unsigned int it=0;
it<NTrk;
it++) {
1467 D_vec(3*
it+3) = dTaudphi[
it];
1468 D_vec(3*
it+4) = dTaudtheta[
it];
1469 D_vec(3*
it+5) = dTaudqOverP[
it];
1471 D_vec(3*NTrk+3) = dTaudx0;
1472 D_vec(3*NTrk+4) = dTaudy0;
1473 D_vec(3*NTrk+5) = 0.;
1475 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1476 W_mat.block(0,0,ndim,ndim) = fullCov;
1477 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1478 V0_err = D_vec.transpose() * W_mat * D_vec;
1481 double tauErrsq = V0_err(0,0);
1482 if (tauErrsq <= 0.)
ATH_MSG_DEBUG(
"tauError: negative sqrt tauErrsq " << tauErrsq);
1483 double tauErr = (tauErrsq>0.) ? sqrt(tauErrsq) : 0.;
1484 return CONST*tauErr;
1490 if (
masses.size() != NTrk) {
1491 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1495 double CONST = 1000./299.792;
1496 double M = invariantMass(vxCandidate,
masses);
1497 double LXYZ = lxyz(vxCandidate,
vertex);
1498 double P = V0Momentum(vxCandidate).mag();
1505 double CONST = 1000./299.792;
1506 double LXYZ = lxyz(vxCandidate,
vertex);
1507 double P = V0Momentum(vxCandidate).mag();
1515 if (
masses.size() != NTrk) {
1516 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
1520 double CONST = 1000./299.792;
1521 double P = V0Momentum(vxCandidate).mag();
1523 double dx = vert.x();
1524 double dy = vert.y();
1525 double dz = vert.z();
1526 double M = invariantMass(vxCandidate,
masses);
1527 double E=0., Px=0., Py=0., Pz=0.;
1528 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
1529 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
1530 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk), dedqOverP(NTrk);
1531 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
1533 auto fullCov = convertCovMatrix(vxCandidate);
1534 for(
unsigned int it=0;
it<NTrk;
it++) {
1536 double trkCharge = 1.;
1537 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
1538 double phi = bPer->parameters()[
Trk::phi];
1539 double theta = bPer->parameters()[
Trk::theta];
1542 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
1557 double LXYZ = Px*
dx+Py*
dy+Pz*dz;
1559 for(
unsigned int it=0;
it<NTrk;
it++) {
1560 double dMdqOverP = -(Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it]-
E*dedqOverP[
it])/M;
1561 double dMdtheta = -(Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/M;
1562 double dMdphi = -(Px*dpxdphi[
it]+Py*dpydphi[
it])/M;
1563 double dPdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it])/
P;
1564 double dPdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/
P;
1565 double dPdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
P;
1566 double dLXYZdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it]+dz*dpzdqOverP[
it];
1567 double dLXYZdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it]+dz*dpzdtheta[
it];
1568 double dLXYZdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
1569 dTaudqOverP[
it] = (LXYZ*dMdqOverP+M*dLXYZdqOverP)/(
P*
P)-(2.*LXYZ*M*dPdqOverP)/(
P*
P*
P);
1570 dTaudtheta[
it] = (LXYZ*dMdtheta+M*dLXYZdtheta)/(
P*
P)-(2.*LXYZ*M*dPdtheta)/(
P*
P*
P);
1571 dTaudphi[
it] = (LXYZ*dMdphi+M*dLXYZdphi)/(
P*
P)-(2.*LXYZ*M*dPdphi)/(
P*
P*
P);
1573 double dTaudx = (M*Px)/(
P*
P);
1574 double dTaudy = (M*Py)/(
P*
P);
1575 double dTaudz = (M*Pz)/(
P*
P);
1576 double dTaudx0 = -dTaudx;
1577 double dTaudy0 = -dTaudy;
1578 double dTaudz0 = -dTaudz;
1580 unsigned int ndim = 0;
1581 if (fullCov.size() != 0) {
1582 ndim = fullCov.rows();
1588 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
1590 for(
unsigned int it=0;
it<NTrk;
it++) {
1593 D_vec(5*
it+2) = dTaudphi[
it];
1594 D_vec(5*
it+3) = dTaudtheta[
it];
1595 D_vec(5*
it+4) = dTaudqOverP[
it];
1597 D_vec(5*NTrk+0) = dTaudx;
1598 D_vec(5*NTrk+1) = dTaudy;
1599 D_vec(5*NTrk+2) = dTaudz;
1600 D_vec(5*NTrk+3) = dTaudx0;
1601 D_vec(5*NTrk+4) = dTaudy0;
1602 D_vec(5*NTrk+5) = dTaudz0;
1604 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1605 if (fullCov.size() != 0) {
1606 W_mat.block(0,0,ndim,ndim) = fullCov;
1609 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1610 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1612 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1613 V0_err = D_vec.transpose() * W_mat * D_vec;
1614 }
else if (ndim == 3*NTrk+3) {
1619 for(
unsigned int it=0;
it<NTrk;
it++) {
1620 D_vec(3*
it+3) = dTaudphi[
it];
1621 D_vec(3*
it+4) = dTaudtheta[
it];
1622 D_vec(3*
it+5) = dTaudqOverP[
it];
1624 D_vec(3*NTrk+3) = dTaudx0;
1625 D_vec(3*NTrk+4) = dTaudy0;
1626 D_vec(3*NTrk+5) = dTaudz0;
1628 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1629 W_mat.block(0,0,ndim,ndim) = fullCov;
1630 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1631 V0_err = D_vec.transpose() * W_mat * D_vec;
1634 double tauErrsq = V0_err(0,0);
1635 if (tauErrsq <= 0.)
ATH_MSG_DEBUG(
"tauError: negative sqrt tauErrsq " << tauErrsq);
1636 double tauErr = (tauErrsq>0.) ? sqrt(tauErrsq) : 0.;
1637 return CONST*tauErr;
1644 double CONST = 1000./299.792;
1645 double P = V0Momentum(vxCandidate).mag();
1647 double dx = vecsub.x();
1648 double dy = vecsub.y();
1649 double dz = vecsub.z();
1651 double Px=0., Py=0., Pz=0.;
1652 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
1653 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
1654 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk);
1655 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
1657 auto fullCov = convertCovMatrix(vxCandidate);
1658 for(
unsigned int it=0;
it<NTrk;
it++) {
1660 double trkCharge = 1.;
1661 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
1662 double phi = bPer->parameters()[
Trk::phi];
1663 double theta = bPer->parameters()[
Trk::theta];
1677 double LXYZ = Px*
dx+Py*
dy+Pz*dz;
1679 for(
unsigned int it=0;
it<NTrk;
it++) {
1680 double dPdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it])/
P;
1681 double dPdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/
P;
1682 double dPdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
P;
1683 double dLXYZdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it]+dz*dpzdqOverP[
it];
1684 double dLXYZdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it]+dz*dpzdtheta[
it];
1685 double dLXYZdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
1686 dTaudqOverP[
it] = M*dLXYZdqOverP/(
P*
P)-(2.*LXYZ*M*dPdqOverP)/(
P*
P*
P);
1687 dTaudtheta[
it] = M*dLXYZdtheta/(
P*
P)-(2.*LXYZ*M*dPdtheta)/(
P*
P*
P);
1688 dTaudphi[
it] = M*dLXYZdphi/(
P*
P)-(2.*LXYZ*M*dPdphi)/(
P*
P*
P);
1690 double dTaudx = (M*Px)/(
P*
P);
1691 double dTaudy = (M*Py)/(
P*
P);
1692 double dTaudz = (M*Pz)/(
P*
P);
1693 double dTaudx0 = -dTaudx;
1694 double dTaudy0 = -dTaudy;
1695 double dTaudz0 = -dTaudz;
1697 unsigned int ndim = 0;
1698 if (fullCov.size() != 0) {
1699 ndim = fullCov.rows();
1705 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
1707 for(
unsigned int it=0;
it<NTrk;
it++) {
1710 D_vec(5*
it+2) = dTaudphi[
it];
1711 D_vec(5*
it+3) = dTaudtheta[
it];
1712 D_vec(5*
it+4) = dTaudqOverP[
it];
1714 D_vec(5*NTrk+0) = dTaudx;
1715 D_vec(5*NTrk+1) = dTaudy;
1716 D_vec(5*NTrk+2) = dTaudz;
1717 D_vec(5*NTrk+3) = dTaudx0;
1718 D_vec(5*NTrk+4) = dTaudy0;
1719 D_vec(5*NTrk+5) = dTaudz0;
1721 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
1722 if (fullCov.size() != 0) {
1723 W_mat.block(0,0,ndim,ndim) = fullCov;
1726 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
1727 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
1729 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
1730 V0_err = D_vec.transpose() * W_mat * D_vec;
1731 }
else if (ndim == 3*NTrk+3) {
1736 for(
unsigned int it=0;
it<NTrk;
it++) {
1737 D_vec(3*
it+3) = dTaudphi[
it];
1738 D_vec(3*
it+4) = dTaudtheta[
it];
1739 D_vec(3*
it+5) = dTaudqOverP[
it];
1741 D_vec(3*NTrk+3) = dTaudx0;
1742 D_vec(3*NTrk+4) = dTaudy0;
1743 D_vec(3*NTrk+5) = dTaudz0;
1745 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
1746 W_mat.block(0,0,ndim,ndim) = fullCov;
1747 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
1748 V0_err = D_vec.transpose() * W_mat * D_vec;
1751 double tauErrsq = V0_err(0,0);
1752 if (tauErrsq <= 0.)
ATH_MSG_DEBUG(
"tauError: negative sqrt tauErrsq " << tauErrsq);
1753 double tauErr = (tauErrsq>0.) ? sqrt(tauErrsq) : 0.;
1754 return CONST*tauErr;
1757 double V0Tools::thetaStar(
const xAOD::Vertex * vxCandidate,
double mass1,
double mass2)
1762 CLHEP::HepLorentzVector v1(
V1.Px(),
V1.Py(),
V1.Pz(),
V1.E());
1763 CLHEP::HepLorentzVector
v2(V2.Px(),V2.Py(),V2.Pz(),V2.E());
1764 CLHEP::HepLorentzVector
v0 = v1 +
v2;
1765 CLHEP::Hep3Vector boost_v0 =
v0.boostVector();
1767 v1.boost( boost_v0 );
1768 v2.boost( boost_v0 );
1769 theta =
v0.angle( v1.vect() );
1773 double V0Tools::cosThetaStar(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
1777 CLHEP::HepLorentzVector posMom(PosMom.Px(),PosMom.Py(),PosMom.Pz(),PosMom.E());
1778 CLHEP::HepLorentzVector negMom(NegMom.Px(),NegMom.Py(),NegMom.Pz(),NegMom.E());
1779 return cosThetaStar(posMom, negMom);
1782 double V0Tools::cosThetaStar(
const CLHEP::HepLorentzVector & posTrack,
const CLHEP::HepLorentzVector & negTrack)
1784 CLHEP::HepLorentzVector
v0(posTrack + negTrack);
1785 double Mv0 =
v0.m();
1786 double Mplus = posTrack.m();
1787 double Mminus= negTrack.m();
1789 double pssq = (Mv0*Mv0-(Mplus+Mminus)*(Mplus+Mminus))*(Mv0*Mv0-(Mplus-Mminus)*(Mplus-Mminus));
1790 double ps = (pssq>0.) ? sqrt(pssq) : 0.;
1792 double pp =
v0.px()*posTrack.px() +
v0.py()*posTrack.py() +
v0.pz()*posTrack.pz();
1793 return (
v0.e()*pp - Pv0*Pv0*posTrack.e())/( Mv0*ps*Pv0);
1797 double V0Tools::phiStar(
const xAOD::Vertex * vxCandidate,
double posTrackMass,
double negTrackMass)
1801 CLHEP::HepLorentzVector v_pos(V_pos.Px(),V_pos.Py(),V_pos.Pz(),V_pos.E());
1802 CLHEP::HepLorentzVector v_neg(V_neg.Px(),V_neg.Py(),V_neg.Pz(),V_neg.E());
1803 return phiStar(v_pos+v_neg,v_pos);
1806 double V0Tools::phiStar(
const CLHEP::HepLorentzVector &
v0,
const CLHEP::HepLorentzVector &
track)
1808 double phiStar = -999999.;
1809 CLHEP::Hep3Vector V0 =
v0.getV();
1810 CLHEP::Hep3Vector trk =
track.getV();
1812 trk.rotateZ(-V0.phi());
1813 trk.rotateY(-V0.theta());
1820 phiStar = atan2(trk.y(),trk.x());
1826 auto mom = V0Momentum(vxCandidate);
1827 auto vtx1 = vtx(vxCandidate);
1829 return (
mom.dot(vtx1))/(
mom.mag()*(vtx1).
mag());
1834 auto mom = V0Momentum(vxCandidate);
1835 auto vtx1 = vtx(vxCandidate);
1836 vtx1 -=
vertex->position();
1837 return (
mom.dot((vtx1)))/(
mom.mag()*(vtx1).
mag());
1842 auto mom = V0Momentum(vxCandidate);
1843 auto vtx1 = vtx(vxCandidate);
1845 double pT =
mom.perp();
1846 return (
mom.x()*vtx1.x()+
mom.y()*vtx1.y())/(
pT*vtx1.perp());
1851 auto mom = V0Momentum(vxCandidate);
1852 auto vtx1 = vtx(vxCandidate);
1853 vtx1 -=
vertex->position();
1854 double pT =
mom.perp();
1855 return (
mom.x()*vtx1.x()+
mom.y()*vtx1.y())/(
pT*vtx1.perp());
1862 for(
unsigned int it=0;
it<NTrk;
it++) {
1881 if (NTrk != 2)
return origTrk;
1882 for(
unsigned int it=0;
it<NTrk;
it++) {
1892 if (NTrk != 2)
return origTrk;
1893 for(
unsigned int it=0;
it<NTrk;
it++) {
2140 double V0Tools::invariantMassBeforeFitIP(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
2142 double px = 0.,
py = 0.,
pz = 0.,
e = 0.;
2144 if (
masses.size() != NTrk) {
2145 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2148 for(
unsigned int it=0;
it<NTrk;
it++) {
2151 if (TP ==
nullptr)
return -999999.;
2152 TLorentzVector Tp4 = TP->
p4();
2157 double pe = (pesq>0.) ? sqrt(pesq) : 0.;
2162 return (msq>0.) ? sqrt(msq) : 0.;
2165 double V0Tools::invariantMassBeforeFit(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses,
const EventContext& ctx,
const Trk::IExtrapolator* extrapolator)
const
2168 double px = 0.,
py = 0.,
pz = 0.,
e = 0.;
2170 if (
masses.size() != NTrk) {
2171 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2174 for(
unsigned int it=0;
it<NTrk;
it++) {
2177 if (TP ==
nullptr)
return -999999.;
2178 std::unique_ptr<const Trk::TrackParameters> extrPer =
2180 if (extrPer ==
nullptr)
2186 double pe = (pesq>0.) ? sqrt(pesq) : 0.;
2191 return (msq>0.) ? sqrt(msq) : 0.;
2194 double V0Tools::invariantMassBeforeFit(
const xAOD::Vertex * vxCandidate,
2198 double px = 0.,
py = 0.,
pz = 0.,
e = 0.;
2201 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2204 for(
unsigned int it=0;
it<NTrk;
it++) {
2207 if (TP ==
nullptr)
return -999999.;
2208 std::unique_ptr<const Trk::TrackParameters> extrPer =
2210 if (extrPer ==
nullptr)
2216 double pe = (pesq>0.) ? sqrt(pesq) : 0.;
2221 return (msq>0.) ? sqrt(msq) : 0.;
2224 double V0Tools::invariantMassErrorBeforeFitIP(
const xAOD::Vertex * vxCandidate, std::span<const double>
masses)
const
2227 if (
masses.size() != NTrk) {
2228 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2231 double mass = invariantMassBeforeFitIP(vxCandidate,
masses);
2232 double E=0., Px=0., Py=0., Pz=0.;
2233 std::vector<double>phi(NTrk), theta(NTrk),
qOverP(NTrk),
charge(NTrk),
e(NTrk);
2234 std::vector<double>dm2dphi(NTrk), dm2dtheta(NTrk), dm2dqOverP(NTrk);
2236 for(
unsigned int it=0;
it<NTrk;
it++) {
2239 if (TP ==
nullptr)
return -999999.;
2241 V0_cor(5*
it+2,5*
it+2) = cov_tmp(2,2);
2242 V0_cor(5*
it+2,5*
it+3) = cov_tmp(2,3);
2243 V0_cor(5*
it+2,5*
it+4) = cov_tmp(2,4);
2244 V0_cor(5*
it+3,5*
it+3) = cov_tmp(3,3);
2245 V0_cor(5*
it+3,5*
it+4) = cov_tmp(3,4);
2246 V0_cor(5*
it+4,5*
it+4) = cov_tmp(4,4);
2247 V0_cor(5*
it+3,5*
it+2) = cov_tmp(2,3);
2248 V0_cor(5*
it+4,5*
it+2) = cov_tmp(2,4);
2249 V0_cor(5*
it+4,5*
it+3) = cov_tmp(3,4);
2251 phi[
it] = TP->
phi();
2255 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
2258 TLorentzVector p4 = TP->
p4();
2265 for(
unsigned int it=0;
it<NTrk;
it++) {
2274 for(
unsigned int it=0;
it<NTrk;
it++) {
2275 D_vec(5*
it+0,0) = 0.;
2276 D_vec(5*
it+1,0) = 0.;
2277 D_vec(5*
it+2,0) = dm2dphi[
it];
2278 D_vec(5*
it+3,0) = dm2dtheta[
it];
2279 D_vec(5*
it+4,0) = dm2dqOverP[
it];
2281 Amg::MatrixX V0_merr = D_vec.transpose() * V0_cor * D_vec;
2283 double massVarsq = V0_merr(0,0);
2284 if (massVarsq <= 0.)
ATH_MSG_DEBUG(
"massError: negative sqrt massVarsq " << massVarsq);
2285 double massVar = (massVarsq>0.) ? sqrt(massVarsq) : 0.;
2286 double massErr = massVar/(2.*
mass);
2294 if (
masses.size() != NTrk) {
2295 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2299 return invariantMassErrorBeforeFit(vxCandidate,
masses,
vertex, ctx, extrap);
2303 double V0Tools::invariantMassErrorBeforeFit(
const xAOD::Vertex * vxCandidate,
2307 if (
masses.size() != NTrk) {
2308 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2312 double E=0., Px=0., Py=0., Pz=0.;
2313 std::vector<double>phi(NTrk), theta(NTrk),
qOverP(NTrk),
charge(NTrk),
e(NTrk);
2314 std::vector<double>dm2dphi(NTrk), dm2dtheta(NTrk), dm2dqOverP(NTrk);
2316 for(
unsigned int it=0;
it<NTrk;
it++) {
2319 if (TP ==
nullptr)
return -999999.;
2320 std::unique_ptr<const Trk::TrackParameters> extrPer =
2322 if (extrPer ==
nullptr)
2324 const AmgSymMatrix(5)* cov_tmp = extrPer->covariance();
2325 V0_cor(5*
it+2,5*
it+2) = (*cov_tmp)(2,2);
2326 V0_cor(5*
it+2,5*
it+3) = (*cov_tmp)(2,3);
2327 V0_cor(5*
it+2,5*
it+4) = (*cov_tmp)(2,4);
2328 V0_cor(5*
it+3,5*
it+3) = (*cov_tmp)(3,3);
2329 V0_cor(5*
it+3,5*
it+4) = (*cov_tmp)(3,4);
2330 V0_cor(5*
it+4,5*
it+4) = (*cov_tmp)(4,4);
2331 V0_cor(5*
it+3,5*
it+2) = (*cov_tmp)(2,3);
2332 V0_cor(5*
it+4,5*
it+2) = (*cov_tmp)(2,4);
2333 V0_cor(5*
it+4,5*
it+3) = (*cov_tmp)(3,4);
2339 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
2347 double msq =
E*
E - Px*Px - Py*Py - Pz*Pz;
2348 double mass = (msq>0.) ? sqrt(msq) : 0.;
2350 for(
unsigned int it=0;
it<NTrk;
it++) {
2359 for(
unsigned int it=0;
it<NTrk;
it++) {
2360 D_vec(5*
it+0,0) = 0.;
2361 D_vec(5*
it+1,0) = 0.;
2362 D_vec(5*
it+2,0) = dm2dphi[
it];
2363 D_vec(5*
it+3,0) = dm2dtheta[
it];
2364 D_vec(5*
it+4,0) = dm2dqOverP[
it];
2366 Amg::MatrixX V0_merr = D_vec.transpose() * V0_cor * D_vec;
2368 double massVarsq = V0_merr(0,0);
2369 if (massVarsq <= 0.)
ATH_MSG_DEBUG(
"massError: negative sqrt massVarsq " << massVarsq);
2370 double massVar = (massVarsq>0.) ? sqrt(massVarsq) : 0.;
2371 double massErr = massVar/(2.*
mass);
2380 if (
masses.size() != NTrk) {
2381 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2385 double CONST = 1000./299.792;
2386 double PT = V0Momentum(vxCandidate).perp();
2388 double dx = vert.x();
2389 double dy = vert.y();
2390 double M = invariantMass(vxCandidate,
masses);
2391 double E=0., Px=0., Py=0., Pz=0.;
2392 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
2393 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
2394 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk), dedqOverP(NTrk);
2395 std::vector<double>dMdqOverP(NTrk), dMdtheta(NTrk), dMdphi(NTrk);
2396 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
2398 auto fullCov = convertCovMatrix(vxCandidate);
2399 for(
unsigned int it=0;
it<NTrk;
it++) {
2401 double trkCharge = 1.;
2402 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
2403 double phi = bPer->parameters()[
Trk::phi];
2404 double theta = bPer->parameters()[
Trk::theta];
2407 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
2422 double LXY = Px*
dx+Py*
dy;
2424 for(
unsigned int it=0;
it<NTrk;
it++) {
2425 dMdqOverP[
it] = -(Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it]-
E*dedqOverP[
it])/M;
2426 dMdtheta[
it] = -(Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/M;
2427 dMdphi[
it] = -(Px*dpxdphi[
it]+Py*dpydphi[
it])/M;
2428 double dPTdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
2429 double dPTdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
2430 double dPTdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
2431 double dLXYdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it];
2432 double dLXYdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it];
2433 double dLXYdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
2434 dTaudqOverP[
it] = (LXY*dMdqOverP[
it]+M*dLXYdqOverP)/(
PT*
PT)-(2.*LXY*M*dPTdqOverP)/(
PT*
PT*
PT);
2435 dTaudtheta[
it] = (LXY*dMdtheta[
it]+M*dLXYdtheta)/(
PT*
PT)-(2.*LXY*M*dPTdtheta)/(
PT*
PT*
PT);
2436 dTaudphi[
it] = (LXY*dMdphi[
it]+M*dLXYdphi)/(
PT*
PT)-(2.*LXY*M*dPTdphi)/(
PT*
PT*
PT);
2438 double dTaudx = (M*Px)/(
PT*
PT);
2439 double dTaudy = (M*Py)/(
PT*
PT);
2440 double dTaudx0 = -dTaudx;
2441 double dTaudy0 = -dTaudy;
2443 unsigned int ndim = 0;
2444 if (fullCov.size() != 0) {
2445 ndim = fullCov.rows();
2451 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
2453 for(
unsigned int it=0;
it<NTrk;
it++) {
2454 D_mat(5*
it+0,0) = 0.;
2455 D_mat(5*
it+1,0) = 0.;
2458 D_mat(5*
it+4,0) =
CONST*dTaudqOverP[
it];
2459 D_mat(5*
it+0,1) = 0.;
2460 D_mat(5*
it+1,1) = 0.;
2461 D_mat(5*
it+2,1) = dMdphi[
it];
2462 D_mat(5*
it+3,1) = dMdtheta[
it];
2463 D_mat(5*
it+4,1) = dMdqOverP[
it];
2465 D_mat(5*NTrk+0,0) =
CONST*dTaudx;
2466 D_mat(5*NTrk+1,0) =
CONST*dTaudy;
2467 D_mat(5*NTrk+2,0) = 0.;
2468 D_mat(5*NTrk+3,0) =
CONST*dTaudx0;
2469 D_mat(5*NTrk+4,0) =
CONST*dTaudy0;
2470 D_mat(5*NTrk+5,0) = 0.;
2471 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
2472 if (fullCov.size() != 0) {
2473 W_mat.block(0,0,ndim,ndim) = fullCov;
2476 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
2477 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
2479 W_mat.block(5*NTrk+3,5*NTrk+3,3,3) =
vertex->covariancePosition();
2480 V0_err = D_mat.transpose() * W_mat * D_mat;
2481 }
else if (ndim == 3*NTrk+3) {
2483 D_mat(0,0) =
CONST*dTaudx;
2484 D_mat(1,0) =
CONST*dTaudy;
2486 for(
unsigned int it=0;
it<NTrk;
it++) {
2489 D_mat(3*
it+5,0) =
CONST*dTaudqOverP[
it];
2490 D_mat(3*
it+3,1) = dMdphi[
it];
2491 D_mat(3*
it+4,1) = dMdtheta[
it];
2492 D_mat(3*
it+5,1) = dMdqOverP[
it];
2494 D_mat(3*NTrk+3,0) =
CONST*dTaudx0;
2495 D_mat(3*NTrk+4,0) =
CONST*dTaudy0;
2496 D_mat(3*NTrk+5,0) = 0.;
2497 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
2498 W_mat.block(0,0,ndim,ndim) = fullCov;
2499 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
2500 V0_err = D_mat.transpose() * W_mat * D_mat;
2508 for(
unsigned int it=0;
it<NTrk;
it++){
2511 V0_cov(5*
it+2,5*
it+2) = (*cov_tmp)(2,2);
2512 V0_cov(5*
it+2,5*
it+3) = (*cov_tmp)(2,3);
2513 V0_cov(5*
it+2,5*
it+4) = (*cov_tmp)(2,4);
2514 V0_cov(5*
it+3,5*
it+3) = (*cov_tmp)(3,3);
2515 V0_cov(5*
it+3,5*
it+4) = (*cov_tmp)(3,4);
2516 V0_cov(5*
it+4,5*
it+4) = (*cov_tmp)(4,4);
2517 V0_cov(5*
it+3,5*
it+2) = (*cov_tmp)(2,3);
2518 V0_cov(5*
it+4,5*
it+2) = (*cov_tmp)(2,4);
2519 V0_cov(5*
it+4,5*
it+3) = (*cov_tmp)(3,4);
2529 if (
masses.size() != NTrk) {
2530 ATH_MSG_DEBUG(
"The provided number of masses does not match the number of tracks in the vertex");
2534 double CONST = 1000./299.792;
2535 double PT = V0Momentum(vxCandidate).perp();
2537 double dx = vert.x();
2538 double dy = vert.y();
2539 double M = invariantMass(vxCandidate,
masses);
2540 double E=0., Px=0., Py=0., Pz=0.;
2541 std::vector<double>dpxdqOverP(NTrk), dpxdtheta(NTrk), dpxdphi(NTrk);
2542 std::vector<double>dpydqOverP(NTrk), dpydtheta(NTrk), dpydphi(NTrk);
2543 std::vector<double>dpzdqOverP(NTrk), dpzdtheta(NTrk), dedqOverP(NTrk);
2544 std::vector<double>dMdqOverP(NTrk), dMdtheta(NTrk), dMdphi(NTrk);
2545 std::vector<double>dTaudqOverP(NTrk), dTaudtheta(NTrk), dTaudphi(NTrk);
2547 auto fullCov = convertCovMatrix(vxCandidate);
2548 for(
unsigned int it=0;
it<NTrk;
it++) {
2550 double trkCharge = 1.;
2551 if (bPer->parameters()[
Trk::qOverP] < 0.) trkCharge = -1.;
2552 double phi = bPer->parameters()[
Trk::phi];
2553 double theta = bPer->parameters()[
Trk::theta];
2556 double pe = (
tmp>0.) ? sqrt(
tmp) : 0.;
2571 double LXY = Px*
dx+Py*
dy;
2573 for(
unsigned int it=0;
it<NTrk;
it++) {
2574 dMdqOverP[
it] = -(Px*dpxdqOverP[
it]+Py*dpydqOverP[
it]+Pz*dpzdqOverP[
it]-
E*dedqOverP[
it])/M;
2575 dMdtheta[
it] = -(Px*dpxdtheta[
it]+Py*dpydtheta[
it]+Pz*dpzdtheta[
it])/M;
2576 dMdphi[
it] = -(Px*dpxdphi[
it]+Py*dpydphi[
it])/M;
2577 double dPTdqOverP = (Px*dpxdqOverP[
it]+Py*dpydqOverP[
it])/
PT;
2578 double dPTdtheta = (Px*dpxdtheta[
it]+Py*dpydtheta[
it])/
PT;
2579 double dPTdphi = (Px*dpxdphi[
it]+Py*dpydphi[
it])/
PT;
2580 double dLXYdqOverP =
dx*dpxdqOverP[
it]+
dy*dpydqOverP[
it];
2581 double dLXYdtheta =
dx*dpxdtheta[
it]+
dy*dpydtheta[
it];
2582 double dLXYdphi =
dx*dpxdphi[
it]+
dy*dpydphi[
it];
2583 dTaudqOverP[
it] = (LXY*dMdqOverP[
it]+M*dLXYdqOverP)/(
PT*
PT)-(2.*LXY*M*dPTdqOverP)/(
PT*
PT*
PT);
2584 dTaudtheta[
it] = (LXY*dMdtheta[
it]+M*dLXYdtheta)/(
PT*
PT)-(2.*LXY*M*dPTdtheta)/(
PT*
PT*
PT);
2585 dTaudphi[
it] = (LXY*dMdphi[
it]+M*dLXYdphi)/(
PT*
PT)-(2.*LXY*M*dPTdphi)/(
PT*
PT*
PT);
2587 double dTaudx = (M*Px)/(
PT*
PT);
2588 double dTaudy = (M*Py)/(
PT*
PT);
2589 double dTaudx0 = -dTaudx;
2590 double dTaudy0 = -dTaudy;
2592 unsigned int ndim = 0;
2593 if (fullCov.size() != 0) {
2594 ndim = fullCov.rows();
2599 if (ndim == 5*NTrk+3 || ndim == 5*NTrk+6) {
2601 for(
unsigned int it=0;
it<NTrk;
it++) {
2602 D_mat(5*
it+0,0) = 0.;
2603 D_mat(5*
it+1,0) = 0.;
2606 D_mat(5*
it+4,0) =
CONST*dTaudqOverP[
it];
2607 D_mat(5*
it+0,1) = 0.;
2608 D_mat(5*
it+1,1) = 0.;
2609 D_mat(5*
it+2,1) = dMdphi[
it];
2610 D_mat(5*
it+3,1) = dMdtheta[
it];
2611 D_mat(5*
it+4,1) = dMdqOverP[
it];
2613 D_mat(5*NTrk+0,0) =
CONST*dTaudx;
2614 D_mat(5*NTrk+1,0) =
CONST*dTaudy;
2615 D_mat(5*NTrk+2,0) = 0.;
2616 D_mat(5*NTrk+3,0) =
CONST*dTaudx0;
2617 D_mat(5*NTrk+4,0) =
CONST*dTaudy0;
2618 D_mat(5*NTrk+5,0) = 0.;
2619 Amg::MatrixX W_mat(5*NTrk+6,5*NTrk+6); W_mat.setZero();
2620 if (fullCov.size() != 0) {
2621 W_mat.block(0,0,ndim,ndim) = fullCov;
2624 W_mat.block(0,0,V0_cov.rows(),V0_cov.rows()) = V0_cov;
2625 W_mat.block(5*NTrk,5*NTrk,3,3) = vxCandidate->covariancePosition();
2627 W_mat.block(5*NTrk+3,5*NTrk,3,3) =
vertex->covariancePosition();
2628 V0_err = D_mat.transpose() * W_mat * D_mat;
2629 }
else if (ndim == 3*NTrk+3) {
2631 D_mat(0,0) =
CONST*dTaudx;
2632 D_mat(1,0) =
CONST*dTaudy;
2634 for(
unsigned int it=0;
it<NTrk;
it++) {
2637 D_mat(3*
it+5,0) =
CONST*dTaudqOverP[
it];
2638 D_mat(3*
it+3,1) = dMdphi[
it];
2639 D_mat(3*
it+4,1) = dMdtheta[
it];
2640 D_mat(3*
it+5,1) = dMdqOverP[
it];
2642 D_mat(3*NTrk+3,0) =
CONST*dTaudx0;
2643 D_mat(3*NTrk+4,0) =
CONST*dTaudy0;
2644 D_mat(3*NTrk+5,0) = 0.;
2645 Amg::MatrixX W_mat(3*NTrk+6,3*NTrk+6); W_mat.setZero();
2646 W_mat.block(0,0,ndim,ndim) = fullCov;
2647 W_mat.block(3*NTrk+3,3*NTrk+3,3,3) =
vertex->covariancePosition();
2648 V0_err = D_mat.transpose() * W_mat * D_mat;
2660 if (
matrix.size() == (3*NTrk+3)*(3*NTrk+3+1)/2) {
2662 }
else if (
matrix.size() == (5*NTrk+3)*(5*NTrk+3+1)/2) {
2671 for (
int i=1;
i<= ndim;
i++) {
2672 for (
int j=1; j<=
i; j++){
2676 mtx.fillSymmetric(
i-1,j-1,
matrix[ij]);