10#include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
14#include <framework/gearbox/Const.h>
15#include <framework/logging/Logger.h>
16#include <framework/dataobjects/Helix.h>
19#include <initializer_list>
26 ROOT::Math::XYZVector& position,
27 ROOT::Math::XYZVector& momentum,
int& charge)
35 int charge,
double Bz,
38 Eigen::Matrix<double, 5, 6>& jacobian)
41 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMomentum(0), positionAndMomentum(1), positionAndMomentum(2)),
42 ROOT::Math::XYZVector(positionAndMomentum(3), positionAndMomentum(4), positionAndMomentum(5)),
46 positionAndMomentum(1));
48 const double alpha = helix.
getAlpha(Bz);
54 Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
56 const double px = positionAndMomentum(3);
57 const double py = positionAndMomentum(4);
58 const double pt = hypot(px, py);
59 const double cosPhi0 = px / pt;
60 const double sinPhi0 = py / pt;
63 jacobianRot(iX, iX) = cosPhi0;
64 jacobianRot(iX, iY) = sinPhi0;
65 jacobianRot(iY, iX) = -sinPhi0;
66 jacobianRot(iY, iY) = cosPhi0;
67 jacobianRot(iZ, iZ) = 1.0;
69 jacobianRot(iPx, iPx) = cosPhi0;
70 jacobianRot(iPx, iPy) = sinPhi0;
71 jacobianRot(iPy, iPx) = -sinPhi0;
72 jacobianRot(iPy, iPy) = cosPhi0;
73 jacobianRot(iPz, iPz) = 1.0;
76 const double pz = positionAndMomentum(5);
77 const double invPt = 1 / pt;
78 const double invPtSquared = invPt * invPt;
79 Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
80 jacobianToHelixParameters(iD0, iY) = -1;
81 jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
82 jacobianToHelixParameters(iPhi0, iPy) = invPt;
83 jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
84 jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
85 jacobianToHelixParameters(iTanLambda, iPz) = invPt;
86 jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
87 jacobianToHelixParameters(iZ0, iZ) = 1;
89 jacobian = jacobianToHelixParameters * jacobianRot;
97 case 1 : rc =
"d0 : " ; break ;
98 case 2 : rc =
"phi0 : " ; break ;
99 case 3 : rc =
"omega : " ; break ;
100 case 4 : rc =
"z0 : " ; break ;
101 case 5 : rc =
"tandip: " ; break ;
102 case 6 : rc =
"L : " ; break ;
111 case 1 : rc =
"x : " ; break ;
112 case 2 : rc =
"y : " ; break ;
113 case 3 : rc =
"z : " ; break ;
114 case 4 : rc =
"px : " ; break ;
115 case 5 : rc =
"py : " ; break ;
116 case 6 : rc =
"pz : " ; break ;
129 B2INFO(
"charge: " << charge);
134 int charge,
double Bz,
139 Eigen::Matrix<double, 5, 6>& jacobian)
142 helix =
Belle2::Helix(ROOT::Math::XYZVector(positionAndMom(0), positionAndMom(1), positionAndMom(2)),
143 ROOT::Math::XYZVector(positionAndMom(3), positionAndMom(4), positionAndMom(5)),
151 ROOT::Math::XYZVector postmp;
152 ROOT::Math::XYZVector momtmp;
154 for (
int jin = 0; jin < 6; ++jin) {
155 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
156 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
157 if (jin == 0) postmp.SetX(postmp.X() + delta);
158 if (jin == 1) postmp.SetY(postmp.Y() + delta);
159 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
160 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
161 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
162 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
165 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
166 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
167 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
168 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
176 const Eigen::Matrix<double, 1, 6>& positionAndMom,
177 int charge,
double Bz,
182 Eigen::Matrix<double, 5, 6>& jacobian,
189 ROOT::Math::XYZVector postmp;
190 ROOT::Math::XYZVector momtmp;
192 for (
int jin = 0; jin < 6; ++jin) {
193 postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
194 momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
195 if (jin == 0) postmp.SetX(postmp.X() + delta);
196 if (jin == 1) postmp.SetY(postmp.Y() + delta);
197 if (jin == 2) postmp.SetZ(postmp.Z() + delta);
198 if (jin == 3) momtmp.SetX(momtmp.X() + delta);
199 if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
200 if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
203 jacobian(iD0, jin) = (helixPlusDelta.
getD0() - helix.
getD0()) / delta ;
204 jacobian(iPhi0, jin) = (helixPlusDelta.
getPhi0() - helix.
getPhi0()) / delta ;
205 jacobian(iOmega, jin) = (helixPlusDelta.
getOmega() - helix.
getOmega()) / delta ;
206 jacobian(iZ0, jin) = (helixPlusDelta.
getZ0() - helix.
getZ0()) / delta ;
212 inline double sqr(
double x) {
return x * x ; }
217 if (phi < -TMath::Pi()) rc += TMath::TwoPi();
218 else if (phi > TMath::Pi()) rc -= TMath::TwoPi();
225 double& flt1,
double& flt2,
226 Eigen::Vector3d& vertex,
bool parallel)
229 const double d0_1 = helix1.
getD0();
230 const double phi0_1 = helix1.
getPhi0();
231 const double omega_1 = helix1.
getOmega();
233 const double d0_2 = helix2.
getD0();
234 const double phi0_2 = helix2.
getPhi0();
235 const double omega_2 = helix2.
getOmega();
238 const double r_1 = 1 / omega_1 ;
239 const double r_2 = 1 / omega_2 ;
243 const double x0_1 = (r_1 + d0_1) * sin(phi0_1) ;
244 const double y0_1 = -(r_1 + d0_1) * cos(phi0_1) ;
246 const double x0_2 = (r_2 + d0_2) * sin(phi0_2) ;
247 const double y0_2 = -(r_2 + d0_2) * cos(phi0_2) ;
250 const double deltax = x0_2 - x0_1 ;
251 const double deltay = y0_2 - y0_1 ;
259 const double phi = - atan2(deltax, deltay) ;
260 const double phinot = phi > 0 ? phi - TMath::Pi() : phi + TMath::Pi() ;
261 phi1[0] = r_1 < 0 ? phi : phinot ;
262 phi2[0] = r_2 > 0 ? phi : phinot ;
265 const double R1 = fabs(r_1) ;
266 const double R2 = fabs(r_2) ;
267 const double Rmin = R1 < R2 ? R1 : R2 ;
268 const double Rmax = R1 > R2 ? R1 : R2 ;
269 const double dX = hypot(deltax, deltay) ;
271 if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
276 const double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
280 const double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
284 }
else if (dX < Rmax) {
287 if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
289 else phi1[0] = r_1 < 0 ? phi : phinot ;
295 double x1[2], y1[2], x2[2], y2[2];
296 for (
int i = 0; i < nsolutions; i++) {
297 x1[i] = r_1 * sin(phi1[i]) + x0_1 ;
298 y1[i] = -r_1 * cos(phi1[i]) + y0_1 ;
299 x2[i] = r_2 * sin(phi2[i]) + x0_2 ;
300 y2[i] = -r_2 * cos(phi2[i]) + y0_2 ;
307 const int nturnsmax = 10;
310 for (
int i = 0; i < nsolutions; ++i) {
315 std::vector<double> z1s;
316 for (
int n1 = 0; n1 <= nturnsmax; ++n1) {
319 for (
int sn1 : {n1, -n1}) {
321 if (sn1 == 0 || (-82 <= tmpz1 && tmpz1 <= 158)) {
323 z1s.push_back(tmpz1);
335 for (
int n2 = 0; n2 <= nturnsmax; ++n2) {
338 for (
int sn2 : {n2, -n2}) {
340 if (sn2 == 0 || (-82 <= tmpz2 && tmpz2 <= 158)) {
344 const auto i1best = std::min_element(
345 z1s.cbegin(), z1s.cend(), [&tmpz2](
const double & z1a,
const double & z1b) {
346 return fabs(z1a - tmpz2) < fabs(z1b - tmpz2);
348 const double tmpz1 = *i1best;
350 if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
368 vertex.x() = 0.5 * (x1[ibest] + x2[ibest]);
369 vertex.y() = 0.5 * (y1[ibest] + y2[ibest]);
370 vertex.z() = 0.5 * (z1 + z2);
372 return std::hypot(x2[ibest] - x1[ibest], y2[ibest] - y1[ibest], z2 - z1);
377 const ROOT::Math::XYZVector& point,
380 const double d0 = helix.
getD0();
381 const double phi0 = helix.
getPhi0();
382 const double omega = helix.
getOmega();
383 const double z0 = helix.
getZ0();
385 const double cosdip = cos(atan(tandip)) ;
387 const double r = 1 / omega ;
389 const double x0 = - (r + d0) * sin(phi0) ;
390 const double y0 = (r + d0) * cos(phi0) ;
392 const double deltax = x0 - point.X() ;
393 const double deltay = y0 - point.Y() ;
395 const double pi = TMath::Pi();
396 double phi = - atan2(deltax, deltay) ;
397 if (r < 0) phi = phi > 0 ? phi - pi : phi + pi ;
400 const double x = r * sin(phi) + x0 ;
401 const double y = -r * cos(phi) + y0 ;
405 const double dphi =
phidomain(phi - phi0) ;
406 for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
407 const double l = (dphi + n * TMath::TwoPi()) / omega ;
408 const double tmpz = (z0 + l * tandip) ;
409 if (first || fabs(tmpz - point.Z()) < fabs(z - point.Z())) {
415 return sqrt(sqr(x - point.X()) + sqr(y - point.Y()) + sqr(z - point.Z())) ;
422 const double z __attribute__((unused)),
432 const double aq = charge / alpha;
434 const double pt = std::hypot(px, py);
435 const double pt2 = pt * pt;
436 const double pt3 = pt2 * pt;
437 const double aq2 = aq * aq;
439 const double x2 = x * x;
440 const double y2 = y * y;
441 const double r = x2 + y2;
443 const double px2 = px * px;
444 const double py2 = py * py;
446 const double px0 = px - aq * y;
447 const double py0 = py + aq * x;
449 const double pt02 = px0 * px0 + py0 * py0;
450 const double pt0 = std::sqrt(pt02);
451 double sqrt13 = pt0 / pt;
454 jacobian(0, 0) = py0 / pt0;
455 jacobian(0, 1) = -px0 / pt0;
457 jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
458 (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
459 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
461 jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
462 (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
463 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
467 jacobian(1, 0) = aq * px0 / pt02;
468 jacobian(1, 1) = aq * py0 / pt02;
470 jacobian(1, 3) = -py0 / pt02;
471 jacobian(1, 4) = px0 / pt02;
478 jacobian(2, 3) = - aq * px / pt3;
479 jacobian(2, 4) = - aq * py / pt3;
483 jacobian(3, 0) = -pz * px0 / pt02;
484 jacobian(3, 1) = -pz * py0 / pt02;
486 jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
487 jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
488 jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq;
494 jacobian(4, 3) = -pz * px / pt3;
495 jacobian(4, 4) = -pz * py / pt3;
496 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 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.
static double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, Eigen::Vector3d &vertex, bool parallel=false)
POCA between two tracks.