12 #include <framework/gearbox/Const.h>
13 #include <framework/logging/Logger.h>
15 #include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
17 namespace TreeFitter {
21 ROOT::Math::XYZVector& position,
22 ROOT::Math::XYZVector& momentum,
int& charge)
30 int charge,
double Bz,
33 Eigen::Matrix<double, 5, 6>& jacobian)
36 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMomentum(0), positionAndMomentum(1), positionAndMomentum(2)),
37 ROOT::Math::XYZVector(positionAndMomentum(3), positionAndMomentum(4), positionAndMomentum(5)),
41 positionAndMomentum(1));
43 const double alpha = helix.
getAlpha(Bz);
49 Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
51 const double px = positionAndMomentum(3);
52 const double py = positionAndMomentum(4);
53 const double pt = hypot(px, py);
54 const double cosPhi0 = px / pt;
55 const double sinPhi0 = py / pt;
58 jacobianRot(iX, iX) = cosPhi0;
59 jacobianRot(iX, iY) = sinPhi0;
60 jacobianRot(iY, iX) = -sinPhi0;
61 jacobianRot(iY, iY) = cosPhi0;
62 jacobianRot(iZ, iZ) = 1.0;
64 jacobianRot(iPx, iPx) = cosPhi0;
65 jacobianRot(iPx, iPy) = sinPhi0;
66 jacobianRot(iPy, iPx) = -sinPhi0;
67 jacobianRot(iPy, iPy) = cosPhi0;
68 jacobianRot(iPz, iPz) = 1.0;
71 const double pz = positionAndMomentum(5);
72 const double invPt = 1 / pt;
73 const double invPtSquared = invPt * invPt;
74 Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
75 jacobianToHelixParameters(iD0, iY) = -1;
76 jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
77 jacobianToHelixParameters(iPhi0, iPy) = invPt;
78 jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
79 jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
80 jacobianToHelixParameters(iTanLambda, iPz) = invPt;
81 jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
82 jacobianToHelixParameters(iZ0, iZ) = 1;
84 jacobian = jacobianToHelixParameters * jacobianRot;
92 case 1 : rc =
"d0 : " ; break ;
93 case 2 : rc =
"phi0 : " ; break ;
94 case 3 : rc =
"omega : " ; break ;
95 case 4 : rc =
"z0 : " ; break ;
96 case 5 : rc =
"tandip: " ; break ;
97 case 6 : rc =
"L : " ; break ;
106 case 1 : rc =
"x : " ; break ;
107 case 2 : rc =
"y : " ; break ;
108 case 3 : rc =
"z : " ; break ;
109 case 4 : rc =
"px : " ; break ;
110 case 5 : rc =
"py : " ; break ;
111 case 6 : rc =
"pz : " ; break ;
118 for (
int i = 0; i < 3; ++i)
120 for (
int i = 0; i < 3; ++i)
122 B2INFO(
"charge: " << charge);
127 int charge,
double Bz,
129 Eigen::Matrix<double, 5, 6>& jacobian)
132 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMom(0), positionAndMom(1), positionAndMom(2)),
133 ROOT::Math::XYZVector(positionAndMom(3), positionAndMom(4), positionAndMom(5)),
141 ROOT::Math::XYZVector postmp;
142 ROOT::Math::XYZVector momtmp;
144 for (
int jin = 0; jin < 6; ++jin) {
145 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
146 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
147 if (jin == 0) postmp.SetX(postmp.X() + delta);
148 if (jin == 1) postmp.SetY(postmp.Y() + delta);
149 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
150 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
151 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
152 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
155 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
156 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
157 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
158 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
166 const Eigen::Matrix<double, 1, 6>& positionAndMom,
167 int charge,
double Bz,
169 Eigen::Matrix<double, 5, 6>& jacobian,
176 ROOT::Math::XYZVector postmp;
177 ROOT::Math::XYZVector momtmp;
179 for (
int jin = 0; jin < 6; ++jin) {
180 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
181 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
182 if (jin == 0) postmp.SetX(postmp.X() + delta);
183 if (jin == 1) postmp.SetY(postmp.Y() + delta);
184 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
185 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
186 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
187 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
190 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
191 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
192 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
193 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
199 inline double sqr(
double x) {
return x * x ; }
204 if (phi < -TMath::Pi()) rc += TMath::TwoPi();
205 else if (phi > TMath::Pi()) rc -= TMath::TwoPi();
212 double& flt1,
double& flt2,
216 const double d0_1 = helix1.
getD0();
217 const double phi0_1 = helix1.
getPhi0();
218 const double omega_1 = helix1.
getOmega();
219 const double z0_1 = helix1.
getZ0();
221 const double cosdip_1 = cos(atan(tandip_1)) ;
223 const double d0_2 = helix2.
getD0();
224 const double phi0_2 = helix2.
getPhi0();
225 const double omega_2 = helix2.
getOmega();
226 const double z0_2 = helix2.
getZ0();
228 const double cosdip_2 = cos(atan(tandip_2)) ;
230 const double r_1 = 1 / omega_1 ;
231 const double r_2 = 1 / omega_2 ;
233 const double x0_1 = - (r_1 + d0_1) * sin(phi0_1) ;
234 const double y0_1 = (r_1 + d0_1) * cos(phi0_1) ;
236 const double x0_2 = - (r_2 + d0_2) * sin(phi0_2) ;
237 const double y0_2 = (r_2 + d0_2) * cos(phi0_2) ;
239 const double deltax = x0_2 - x0_1 ;
240 const double deltay = y0_2 - y0_1 ;
247 const double pi = TMath::Pi();
248 const double phi = - atan2(deltax, deltay) ;
249 const double phinot = phi > 0 ? phi - pi : phi + pi ;
250 phi1[0] = r_1 < 0 ? phi : phinot ;
251 phi2[0] = r_2 > 0 ? phi : phinot ;
253 const double R1 = fabs(r_1) ;
254 const double R2 = fabs(r_2) ;
255 const double Rmin = R1 < R2 ? R1 : R2 ;
256 const double Rmax = R1 > R2 ? R1 : R2 ;
257 const double dX = sqrt(deltax * deltax + deltay * deltay) ;
259 if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
262 const double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
266 const double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
270 }
else if (dX < Rmax) {
271 if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
272 else phi1[0] = r_1 < 0 ? phi : phinot ;
276 double z1(0), z2(0) ;
280 for (
int i = 0; i < nsolutions; ++i) {
281 const double dphi1 =
phidomain(phi1[i] - phi0_1) ;
282 const double dphi2 =
phidomain(phi2[i] - phi0_2) ;
284 for (
int n1 = 1 - ncirc; n1 <= 1 + ncirc ; ++n1) {
285 const double l1 = (dphi1 + n1 * TMath::TwoPi()) / omega_1 ;
286 const double tmpz1 = (z0_1 + l1 * tandip_1) ;
287 if (n1 != 0 && fabs(tmpz1) > 100)
290 for (
int n2 = 1 - ncirc ; n2 <= 1 + ncirc; ++n2) {
291 double l2 = (dphi2 + n2 * TMath::TwoPi()) / omega_2 ;
292 double tmpz2 = (z0_2 + l2 * tandip_2) ;
293 if (n2 != 0 && fabs(tmpz2) > 100)
296 if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
301 flt1 = l1 / cosdip_1 ;
302 flt2 = l2 / cosdip_2 ;
308 const double x1 = r_1 * sin(phi1[ibest]) + x0_1 ;
309 const double y1 = -r_1 * cos(phi1[ibest]) + y0_1 ;
311 const double x2 = r_2 * sin(phi2[ibest]) + x0_2 ;
312 const double y2 = -r_2 * cos(phi2[ibest]) + y0_2 ;
314 vertex.SetX(0.5 * (x1 + x2));
315 vertex.SetY(0.5 * (y1 + y2));
316 vertex.SetZ(0.5 * (z1 + z2));
318 return sqrt(sqr(x2 - x1) + sqr(y2 - y1) + sqr(z2 - z1)) ;
326 const double d0 = helix.
getD0();
327 const double phi0 = helix.
getPhi0();
328 const double omega = helix.
getOmega();
329 const double z0 = helix.
getZ0();
331 const double cosdip = cos(atan(tandip)) ;
333 const double r = 1 / omega ;
335 const double x0 = - (r + d0) * sin(phi0) ;
336 const double y0 = (r + d0) * cos(phi0) ;
338 const double deltax = x0 - point.
X() ;
339 const double deltay = y0 - point.
Y() ;
341 const double pi = TMath::Pi();
342 double phi = - atan2(deltax, deltay) ;
343 if (r < 0) phi = phi > 0 ? phi - pi : phi + pi ;
346 const double x = r * sin(phi) + x0 ;
347 const double y = -r * cos(phi) + y0 ;
351 const double dphi =
phidomain(phi - phi0) ;
352 for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
353 const double l = (dphi + n * TMath::TwoPi()) / omega ;
354 const double tmpz = (z0 + l * tandip) ;
355 if (first || fabs(tmpz - point.
Z()) < fabs(z - point.
Z())) {
361 return sqrt(sqr(x - point.
X()) + sqr(y - point.
Y()) + sqr(z - point.
Z())) ;
367 const double z __attribute__((unused)),
377 const double aq = charge / alpha;
379 const double pt = std::hypot(px, py);
380 const double pt2 = pt * pt;
381 const double pt3 = pt2 * pt;
382 const double aq2 = aq * aq;
384 const double x2 = x * x;
385 const double y2 = y * y;
386 const double r = x2 + y2;
388 const double px2 = px * px;
389 const double py2 = py * py;
391 const double px0 = px - aq * y;
392 const double py0 = py + aq * x;
394 const double pt02 = px0 * px0 + py0 * py0;
395 const double pt0 = std::sqrt(pt02);
396 double sqrt13 = pt0 / pt;
399 jacobian(0, 0) = py0 / pt0;
400 jacobian(0, 1) = -px0 / pt0;
402 jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
403 (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
404 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
406 jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
407 (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
408 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
412 jacobian(1, 0) = aq * px0 / pt02;
413 jacobian(1, 1) = aq * py0 / pt02;
415 jacobian(1, 3) = -py0 / pt02;
416 jacobian(1, 4) = px0 / pt02;
423 jacobian(2, 3) = - aq * px / pt3;
424 jacobian(2, 4) = - aq * py / pt3;
428 jacobian(3, 0) = -pz * px0 / pt02;
429 jacobian(3, 1) = -pz * py0 / pt02;
431 jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
432 jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
433 jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq;
439 jacobian(4, 3) = -pz * px / pt3;
440 jacobian(4, 4) = -pz * py / pt3;
441 jacobian(4, 5) = 1. / pt;
DataType Z() const
access variable Z (= .at(2) without boundary check)
DataType X() const
access variable X (= .at(0) without boundary check)
DataType Y() const
access variable Y (= .at(1) without boundary check)
static const double speedOfLight
[cm/ns]
This class represents an ideal helix in perigee parameterization.
short getChargeSign() const
Return track charge sign (1, 0 or -1).
double getArcLength2DAtXY(const double &x, const double &y) const
Calculates the two dimensional arc length at which the circle in the xy projection is closest to the ...
static double getAlpha(const double bZ)
Calculates the alpha value for a given magnetic field in Tesla.
double getOmega() const
Getter for omega, which is a signed curvature measure of the track.
ROOT::Math::XYZVector getPositionAtArcLength2D(const double &arcLength2D) const
Calculates the position on the helix at the given two dimensional arc length.
double getD0() const
Getter for d0, which is the signed distance to the perigee in the r-phi plane.
double getTanLambda() const
Getter for tan lambda, which is the z over two dimensional arc length slope of the track.
double getZ0() const
Getter for z0, which is the z coordinate of the perigee.
ROOT::Math::XYZVector getMomentumAtArcLength2D(const double &arcLength2D, const double &bz) const
Calculates the momentum vector at the given two dimensional arc length.
double getPhi0() const
Getter for phi0, which is the azimuth angle of the transverse momentum at the perigee.
static std::string vertexParName(int i)
map of the vertex parameters by list index
static void helixFromVertex(const Eigen::Matrix< double, 1, 6 > &positionAndMomentum, int charge, double Bz, Belle2::Helix &helix, double &L, Eigen::Matrix< double, 5, 6 > &jacobian)
vertex --> helix
static void getHelixAndJacobianFromVertexNumerical(const Eigen::Matrix< double, 1, 6 > &positionAndMom, int charge, double Bz, Belle2::Helix &helix, Eigen::Matrix< double, 5, 6 > &jacobian)
get helix and jacobian from a vertex
static void vertexFromHelix(const Belle2::Helix &helix, double L, double Bz, ROOT::Math::XYZVector &position, ROOT::Math::XYZVector &momentum, int &charge)
helix --> vertex
static void printVertexPar(const Belle2::B2Vector3D &position, const Belle2::B2Vector3D &momentum, int charge)
Print the vertex parameters.
static double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, Belle2::B2Vector3D &vertex, bool parallel=false)
POCA between two tracks.
static void getJacobianFromVertexNumerical(const Eigen::Matrix< double, 1, 6 > &positionAndMom, int charge, double Bz, const Belle2::Helix &helix, Eigen::Matrix< double, 5, 6 > &jacobian, double delta=1e-5)
get jacobian from a vertex
static std::string helixParName(int i)
map of the helix parameters by list index
static double phidomain(const double phi)
the domain of phi
static void getJacobianToCartesianFrameworkHelix(Eigen::Matrix< double, 5, 6 > &jacobian, const double x, const double y, const double z, const double px, const double py, const double pz, const double bfield, const double charge)
get the jacobian dh={helix pars}/dx={x,y,z,px,py,pz} for the implementation of the framework helix.