12#include <framework/gearbox/Const.h>
13#include <framework/logging/Logger.h>
15#include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
18#include <initializer_list>
25 ROOT::Math::XYZVector& position,
26 ROOT::Math::XYZVector& momentum,
int& charge)
34 int charge,
double Bz,
37 Eigen::Matrix<double, 5, 6>& jacobian)
40 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMomentum(0), positionAndMomentum(1), positionAndMomentum(2)),
41 ROOT::Math::XYZVector(positionAndMomentum(3), positionAndMomentum(4), positionAndMomentum(5)),
45 positionAndMomentum(1));
47 const double alpha = helix.
getAlpha(Bz);
53 Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
55 const double px = positionAndMomentum(3);
56 const double py = positionAndMomentum(4);
57 const double pt = hypot(px, py);
58 const double cosPhi0 = px / pt;
59 const double sinPhi0 = py / pt;
62 jacobianRot(iX, iX) = cosPhi0;
63 jacobianRot(iX, iY) = sinPhi0;
64 jacobianRot(iY, iX) = -sinPhi0;
65 jacobianRot(iY, iY) = cosPhi0;
66 jacobianRot(iZ, iZ) = 1.0;
68 jacobianRot(iPx, iPx) = cosPhi0;
69 jacobianRot(iPx, iPy) = sinPhi0;
70 jacobianRot(iPy, iPx) = -sinPhi0;
71 jacobianRot(iPy, iPy) = cosPhi0;
72 jacobianRot(iPz, iPz) = 1.0;
75 const double pz = positionAndMomentum(5);
76 const double invPt = 1 / pt;
77 const double invPtSquared = invPt * invPt;
78 Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
79 jacobianToHelixParameters(iD0, iY) = -1;
80 jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
81 jacobianToHelixParameters(iPhi0, iPy) = invPt;
82 jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
83 jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
84 jacobianToHelixParameters(iTanLambda, iPz) = invPt;
85 jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
86 jacobianToHelixParameters(iZ0, iZ) = 1;
88 jacobian = jacobianToHelixParameters * jacobianRot;
96 case 1 : rc =
"d0 : " ; break ;
97 case 2 : rc =
"phi0 : " ; break ;
98 case 3 : rc =
"omega : " ; break ;
99 case 4 : rc =
"z0 : " ; break ;
100 case 5 : rc =
"tandip: " ; break ;
101 case 6 : rc =
"L : " ; break ;
110 case 1 : rc =
"x : " ; break ;
111 case 2 : rc =
"y : " ; break ;
112 case 3 : rc =
"z : " ; break ;
113 case 4 : rc =
"px : " ; break ;
114 case 5 : rc =
"py : " ; break ;
115 case 6 : rc =
"pz : " ; break ;
128 B2INFO(
"charge: " << charge);
133 int charge,
double Bz,
135 Eigen::Matrix<double, 5, 6>& jacobian)
138 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMom(0), positionAndMom(1), positionAndMom(2)),
139 ROOT::Math::XYZVector(positionAndMom(3), positionAndMom(4), positionAndMom(5)),
147 ROOT::Math::XYZVector postmp;
148 ROOT::Math::XYZVector momtmp;
150 for (
int jin = 0; jin < 6; ++jin) {
151 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
152 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
153 if (jin == 0) postmp.SetX(postmp.X() + delta);
154 if (jin == 1) postmp.SetY(postmp.Y() + delta);
155 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
156 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
157 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
158 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
161 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
162 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
163 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
164 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
172 const Eigen::Matrix<double, 1, 6>& positionAndMom,
173 int charge,
double Bz,
175 Eigen::Matrix<double, 5, 6>& jacobian,
182 ROOT::Math::XYZVector postmp;
183 ROOT::Math::XYZVector momtmp;
185 for (
int jin = 0; jin < 6; ++jin) {
186 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
187 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
188 if (jin == 0) postmp.SetX(postmp.X() + delta);
189 if (jin == 1) postmp.SetY(postmp.Y() + delta);
190 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
191 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
192 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
193 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
196 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
197 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
198 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
199 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
205 inline double sqr(
double x) {
return x * x ; }
210 if (phi < -TMath::Pi()) rc += TMath::TwoPi();
211 else if (phi > TMath::Pi()) rc -= TMath::TwoPi();
218 double& flt1,
double& flt2,
219 ROOT::Math::XYZVector& vertex,
bool parallel)
222 const double d0_1 = helix1.
getD0();
223 const double phi0_1 = helix1.
getPhi0();
224 const double omega_1 = helix1.
getOmega();
226 const double d0_2 = helix2.
getD0();
227 const double phi0_2 = helix2.
getPhi0();
228 const double omega_2 = helix2.
getOmega();
231 const double r_1 = 1 / omega_1 ;
232 const double r_2 = 1 / omega_2 ;
236 const double x0_1 = (r_1 + d0_1) * sin(phi0_1) ;
237 const double y0_1 = -(r_1 + d0_1) * cos(phi0_1) ;
239 const double x0_2 = (r_2 + d0_2) * sin(phi0_2) ;
240 const double y0_2 = -(r_2 + d0_2) * cos(phi0_2) ;
243 const double deltax = x0_2 - x0_1 ;
244 const double deltay = y0_2 - y0_1 ;
252 const double phi = - atan2(deltax, deltay) ;
253 const double phinot = phi > 0 ? phi - TMath::Pi() : phi + TMath::Pi() ;
254 phi1[0] = r_1 < 0 ? phi : phinot ;
255 phi2[0] = r_2 > 0 ? phi : phinot ;
258 const double R1 = fabs(r_1) ;
259 const double R2 = fabs(r_2) ;
260 const double Rmin = R1 < R2 ? R1 : R2 ;
261 const double Rmax = R1 > R2 ? R1 : R2 ;
262 const double dX = hypot(deltax, deltay) ;
264 if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
269 const double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
273 const double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
277 }
else if (dX < Rmax) {
279 if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
280 else phi1[0] = r_1 < 0 ? phi : phinot ;
286 double x1[2], y1[2], x2[2], y2[2];
287 for (
int i = 0; i < nsolutions; i++) {
288 x1[i] = r_1 * sin(phi1[i]) + x0_1 ;
289 y1[i] = -r_1 * cos(phi1[i]) + y0_1 ;
290 x2[i] = r_2 * sin(phi2[i]) + x0_2 ;
291 y2[i] = -r_2 * cos(phi2[i]) + y0_2 ;
298 const int nturnsmax = 10;
301 for (
int i = 0; i < nsolutions; ++i) {
306 std::vector<double> z1s;
307 for (
int n1 = 0; n1 <= nturnsmax; ++n1) {
310 for (
int sn1 : {n1, -n1}) {
312 if (sn1 == 0 || (-82 <= tmpz1 && tmpz1 <= 158)) {
314 z1s.push_back(tmpz1);
326 for (
int n2 = 0; n2 <= nturnsmax; ++n2) {
329 for (
int sn2 : {n2, -n2}) {
331 if (sn2 == 0 || (-82 <= tmpz2 && tmpz2 <= 158)) {
335 const auto i1best = std::min_element(
336 z1s.cbegin(), z1s.cend(), [&tmpz2](
const double & z1a,
const double & z1b) {
337 return fabs(z1a - tmpz2) < fabs(z1b - tmpz2);
339 const double tmpz1 = *i1best;
341 if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
359 vertex.SetX(0.5 * (x1[ibest] + x2[ibest]));
360 vertex.SetY(0.5 * (y1[ibest] + y2[ibest]));
361 vertex.SetZ(0.5 * (z1 + z2));
363 return std::hypot(x2[ibest] - x1[ibest], y2[ibest] - y1[ibest], z2 - z1);
368 const ROOT::Math::XYZVector& point,
371 const double d0 = helix.
getD0();
372 const double phi0 = helix.
getPhi0();
373 const double omega = helix.
getOmega();
374 const double z0 = helix.
getZ0();
376 const double cosdip = cos(atan(tandip)) ;
378 const double r = 1 / omega ;
380 const double x0 = - (r + d0) * sin(phi0) ;
381 const double y0 = (r + d0) * cos(phi0) ;
383 const double deltax = x0 - point.X() ;
384 const double deltay = y0 - point.Y() ;
386 const double pi = TMath::Pi();
387 double phi = - atan2(deltax, deltay) ;
388 if (r < 0) phi = phi > 0 ? phi - pi : phi + pi ;
391 const double x = r * sin(phi) + x0 ;
392 const double y = -r * cos(phi) + y0 ;
396 const double dphi =
phidomain(phi - phi0) ;
397 for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
398 const double l = (dphi + n * TMath::TwoPi()) / omega ;
399 const double tmpz = (z0 + l * tandip) ;
400 if (first || fabs(tmpz - point.Z()) < fabs(z - point.Z())) {
406 return sqrt(sqr(x - point.X()) + sqr(y - point.Y()) + sqr(z - point.Z())) ;
412 const double z __attribute__((unused)),
422 const double aq = charge / alpha;
424 const double pt = std::hypot(px, py);
425 const double pt2 = pt * pt;
426 const double pt3 = pt2 * pt;
427 const double aq2 = aq * aq;
429 const double x2 = x * x;
430 const double y2 = y * y;
431 const double r = x2 + y2;
433 const double px2 = px * px;
434 const double py2 = py * py;
436 const double px0 = px - aq * y;
437 const double py0 = py + aq * x;
439 const double pt02 = px0 * px0 + py0 * py0;
440 const double pt0 = std::sqrt(pt02);
441 double sqrt13 = pt0 / pt;
444 jacobian(0, 0) = py0 / pt0;
445 jacobian(0, 1) = -px0 / pt0;
447 jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
448 (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
449 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
451 jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
452 (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
453 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
457 jacobian(1, 0) = aq * px0 / pt02;
458 jacobian(1, 1) = aq * py0 / pt02;
460 jacobian(1, 3) = -py0 / pt02;
461 jacobian(1, 4) = px0 / pt02;
468 jacobian(2, 3) = - aq * px / pt3;
469 jacobian(2, 4) = - aq * py / pt3;
473 jacobian(3, 0) = -pz * px0 / pt02;
474 jacobian(3, 1) = -pz * py0 / pt02;
476 jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
477 jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
478 jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq;
484 jacobian(4, 3) = -pz * px / pt3;
485 jacobian(4, 4) = -pz * py / pt3;
486 jacobian(4, 5) = 1. / pt;
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 printVertexPar(const ROOT::Math::XYZVector &position, const ROOT::Math::XYZVector &momentum, int charge)
Print the vertex parameters.
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 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 double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, ROOT::Math::XYZVector &vertex, bool parallel=false)
POCA between two tracks.
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.