12 #include <framework/gearbox/Const.h>
13 #include <framework/logging/Logger.h>
16 #include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
18 namespace TreeFitter {
23 TVector3& momentum,
int& charge)
25 position = helix.getPositionAtArcLength2D(L);
26 momentum = helix.getMomentumAtArcLength2D(L, Bz);
27 charge = helix.getChargeSign();
31 int charge,
double Bz,
34 Eigen::Matrix<double, 5, 6>& jacobian)
38 TVector3 position(positionAndMomentum(0),
39 positionAndMomentum(1),
40 positionAndMomentum(2));
41 TVector3 momentum(positionAndMomentum(3),
42 positionAndMomentum(4),
43 positionAndMomentum(5));
46 L = helix.getArcLength2DAtXY(positionAndMomentum(0),
47 positionAndMomentum(1));
49 const double alpha = helix.getAlpha(Bz);
55 Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
57 const double px = positionAndMomentum(3);
58 const double py = positionAndMomentum(4);
59 const double pt = hypot(px, py);
60 const double cosPhi0 = px / pt;
61 const double sinPhi0 = py / pt;
64 jacobianRot(iX, iX) = cosPhi0;
65 jacobianRot(iX, iY) = sinPhi0;
66 jacobianRot(iY, iX) = -sinPhi0;
67 jacobianRot(iY, iY) = cosPhi0;
68 jacobianRot(iZ, iZ) = 1.0;
70 jacobianRot(iPx, iPx) = cosPhi0;
71 jacobianRot(iPx, iPy) = sinPhi0;
72 jacobianRot(iPy, iPx) = -sinPhi0;
73 jacobianRot(iPy, iPy) = cosPhi0;
74 jacobianRot(iPz, iPz) = 1.0;
77 const double pz = positionAndMomentum(5);
78 const double invPt = 1 / pt;
79 const double invPtSquared = invPt * invPt;
80 Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
81 jacobianToHelixParameters(iD0, iY) = -1;
82 jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
83 jacobianToHelixParameters(iPhi0, iPy) = invPt;
84 jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
85 jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
86 jacobianToHelixParameters(iTanLambda, iPz) = invPt;
87 jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
88 jacobianToHelixParameters(iZ0, iZ) = 1;
90 jacobian = jacobianToHelixParameters * jacobianRot;
98 case 1 : rc =
"d0 : " ; break ;
99 case 2 : rc =
"phi0 : " ; break ;
100 case 3 : rc =
"omega : " ; break ;
101 case 4 : rc =
"z0 : " ; break ;
102 case 5 : rc =
"tandip: " ; break ;
103 case 6 : rc =
"L : " ; break ;
112 case 1 : rc =
"x : " ; break ;
113 case 2 : rc =
"y : " ; break ;
114 case 3 : rc =
"z : " ; break ;
115 case 4 : rc =
"px : " ; break ;
116 case 5 : rc =
"py : " ; break ;
117 case 6 : rc =
"pz : " ; break ;
124 for (
int i = 0; i < 3; ++i)
126 for (
int i = 0; i < 3; ++i)
128 B2INFO(
"charge: " << charge);
133 int charge,
double Bz,
136 Eigen::Matrix<double, 5, 6>& jacobian)
139 TVector3 position(positionAndMom(0),
143 TVector3 momentum(positionAndMom(3),
157 for (
int jin = 0; jin < 6; ++jin) {
158 for (
int i = 0; i < 3; ++i) {
159 postmp[i] = positionAndMom(i);
160 momtmp[i] = positionAndMom(i + 3);
163 postmp[jin] += delta;
165 momtmp[jin - 3] += delta;
169 jacobian(iD0, jin) = (helixPlusDelta.getD0() - helix.getD0()) / delta ;
170 jacobian(iPhi0, jin) = (helixPlusDelta.getPhi0() - helix.getPhi0()) / delta ;
171 jacobian(iOmega, jin) = (helixPlusDelta.getOmega() - helix.getOmega()) / delta ;
172 jacobian(iZ0, jin) = (helixPlusDelta.getZ0() - helix.getZ0()) / delta ;
173 jacobian(iTanLambda, jin) = (helixPlusDelta.getTanLambda() - helix.getTanLambda()) / delta ;
180 const Eigen::Matrix<double, 1, 6>& positionAndMom,
181 int charge,
double Bz,
184 Eigen::Matrix<double, 5, 6>& jacobian,
194 for (
int jin = 0; jin < 6; ++jin) {
195 for (
int i = 0; i < 3; ++i) {
196 postmp[i] = positionAndMom(i);
197 momtmp[i] = positionAndMom(i + 3);
201 postmp[jin] += delta;
203 momtmp[jin - 3] += delta;
207 jacobian(iD0, jin) = (helixPlusDelta.getD0() - helix.getD0()) / delta ;
208 jacobian(iPhi0, jin) = (helixPlusDelta.getPhi0() - helix.getPhi0()) / delta ;
209 jacobian(iOmega, jin) = (helixPlusDelta.getOmega() - helix.getOmega()) / delta ;
210 jacobian(iZ0, jin) = (helixPlusDelta.getZ0() - helix.getZ0()) / delta ;
211 jacobian(iTanLambda, jin) = (helixPlusDelta.getTanLambda() - helix.getTanLambda()) / delta ;
216 inline double sqr(
double x) {
return x * x ; }
221 if (phi < -TMath::Pi()) rc += TMath::TwoPi();
222 else if (phi > TMath::Pi()) rc -= TMath::TwoPi();
229 double& flt1,
double& flt2,
230 TVector3& vertex,
bool parallel)
233 double d0_1 = helix1.getD0();
234 double phi0_1 = helix1.getPhi0();
235 double omega_1 = helix1.getOmega();
236 double z0_1 = helix1.getZ0();
237 double tandip_1 = helix1.getTanLambda();
238 double cosdip_1 = cos(atan(tandip_1)) ;
240 double d0_2 = helix2.getD0();
241 double phi0_2 = helix2.getPhi0();
242 double omega_2 = helix2.getOmega();
243 double z0_2 = helix2.getZ0();
244 double tandip_2 = helix2.getTanLambda();
245 double cosdip_2 = cos(atan(tandip_2)) ;
247 double r_1 = 1 / omega_1 ;
248 double r_2 = 1 / omega_2 ;
250 double x0_1 = - (r_1 + d0_1) * sin(phi0_1) ;
251 double y0_1 = (r_1 + d0_1) * cos(phi0_1) ;
253 double x0_2 = - (r_2 + d0_2) * sin(phi0_2) ;
254 double y0_2 = (r_2 + d0_2) * cos(phi0_2) ;
256 double deltax = x0_2 - x0_1 ;
257 double deltay = y0_2 - y0_1 ;
264 const double pi = TMath::Pi();
265 double phi = - atan2(deltax, deltay) ;
266 double phinot = phi > 0 ? phi - pi : phi + pi ;
267 phi1[0] = r_1 < 0 ? phi : phinot ;
268 phi2[0] = r_2 > 0 ? phi : phinot ;
270 double R1 = fabs(r_1) ;
271 double R2 = fabs(r_2) ;
272 double Rmin = R1 < R2 ? R1 : R2 ;
273 double Rmax = R1 > R2 ? R1 : R2 ;
274 double dX = sqrt(deltax * deltax + deltay * deltay) ;
276 if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
279 double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
283 double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
287 }
else if (dX < Rmax) {
288 if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
289 else phi1[0] = r_1 < 0 ? phi : phinot ;
293 double z1(0), z2(0) ;
297 for (
int i = 0; i < nsolutions; ++i) {
298 double dphi1 =
phidomain(phi1[i] - phi0_1) ;
299 double dphi2 =
phidomain(phi2[i] - phi0_2) ;
300 for (
int n1 = 1 - ncirc; n1 <= 1 + ncirc ; ++n1) {
301 double l1 = (dphi1 + n1 * TMath::TwoPi()) / omega_1 ;
302 double tmpz1 = (z0_1 + l1 * tandip_1) ;
303 if (n1 == 0 || fabs(tmpz1) < 100) {
304 for (
int n2 = 1 - ncirc ; n2 <= 1 + ncirc; ++n2) {
305 double l2 = (dphi2 + n2 * TMath::TwoPi()) / omega_2 ;
306 double tmpz2 = (z0_2 + l2 * tandip_2) ;
307 if (n2 == 0 || fabs(tmpz2) < 100) {
308 if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
313 flt1 = l1 / cosdip_1 ;
314 flt2 = l2 / cosdip_2 ;
322 double x1 = r_1 * sin(phi1[ibest]) + x0_1 ;
323 double y1 = -r_1 * cos(phi1[ibest]) + y0_1 ;
325 double x2 = r_2 * sin(phi2[ibest]) + x0_2 ;
326 double y2 = -r_2 * cos(phi2[ibest]) + y0_2 ;
328 vertex.SetX(0.5 * (x1 + x2));
329 vertex.SetY(0.5 * (y1 + y2));
330 vertex.SetZ(0.5 * (z1 + z2));
332 return sqrt(sqr(x2 - x1) + sqr(y2 - y1) + sqr(z2 - z1)) ;
337 const TVector3& point,
340 double d0 = helix.getD0();
341 double phi0 = helix.getPhi0();
342 double omega = helix.getOmega();
343 double z0 = helix.getZ0();
344 double tandip = helix.getTanLambda();
345 double cosdip = cos(atan(tandip)) ;
347 double r = 1 / omega ;
349 double x0 = - (r + d0) * sin(phi0) ;
350 double y0 = (r + d0) * cos(phi0) ;
352 double deltax = x0 - point.X() ;
353 double deltay = y0 - point.Y() ;
355 const double pi = TMath::Pi();
356 double phi = - atan2(deltax, deltay) ;
357 if (r < 0) phi = phi > 0 ? phi - pi : phi + pi ;
360 double x = r * sin(phi) + x0 ;
361 double y = -r * cos(phi) + y0 ;
366 for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
367 double l = (dphi + n * TMath::TwoPi()) / omega ;
368 double tmpz = (z0 + l * tandip) ;
369 if (first || fabs(tmpz - point.z()) < fabs(z - point.z())) {
375 return sqrt(sqr(x - point.x()) + sqr(y - point.y()) + sqr(z - point.z())) ;
382 const double z __attribute__((unused)),
392 const double aq = charge / alpha;
394 const double pt = std::hypot(px, py);
395 const double pt2 = pt * pt;
396 const double pt3 = pt2 * pt;
397 const double aq2 = aq * aq;
399 const double x2 = x * x;
400 const double y2 = y * y;
401 const double r = x2 + y2;
403 const double px2 = px * px;
404 const double py2 = py * py;
406 const double px0 = px - aq * y;
407 const double py0 = py + aq * x;
409 const double pt02 = px0 * px0 + py0 * py0;
410 const double pt0 = std::sqrt(pt02);
411 double sqrt13 = pt0 / pt;
414 jacobian(0, 0) = py0 / pt0;
415 jacobian(0, 1) = -px0 / pt0;
417 jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
418 (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
419 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
421 jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
422 (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
423 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
427 jacobian(1, 0) = aq * px0 / pt02;
428 jacobian(1, 1) = aq * py0 / pt02;
430 jacobian(1, 3) = -py0 / pt02;
431 jacobian(1, 4) = px0 / pt02;
438 jacobian(2, 3) = - aq * px / pt3;
439 jacobian(2, 4) = - aq * py / pt3;
443 jacobian(3, 0) = -pz * px0 / pt02;
444 jacobian(3, 1) = -pz * py0 / pt02;
446 jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
447 jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
448 jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq;
454 jacobian(4, 3) = -pz * px / pt3;
455 jacobian(4, 4) = -pz * py / pt3;
456 jacobian(4, 5) = 1. / pt;
static const double speedOfLight
[cm/ns]
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, TVector3 &position, TVector3 &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 void printVertexPar(const TVector3 &position, const TVector3 &momentum, int charge)
Print the vertex parameters.
static double phidomain(const double phi)
the domain of phi
static double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, TVector3 &vertex, bool parallel=false)
POCA between two tracks.
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.