14 #include <framework/gearbox/Const.h>
15 #include <framework/logging/Logger.h>
18 #include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
20 namespace TreeFitter {
25 TVector3& momentum,
int& charge)
27 position = helix.getPositionAtArcLength2D(L);
28 momentum = helix.getMomentumAtArcLength2D(L, Bz);
29 charge = helix.getChargeSign();
33 int charge,
double Bz,
36 Eigen::Matrix<double, 5, 6>& jacobian)
40 TVector3 position(positionAndMomentum(0),
41 positionAndMomentum(1),
42 positionAndMomentum(2));
43 TVector3 momentum(positionAndMomentum(3),
44 positionAndMomentum(4),
45 positionAndMomentum(5));
48 L = helix.getArcLength2DAtXY(positionAndMomentum(0),
49 positionAndMomentum(1));
51 const double alpha = helix.getAlpha(Bz);
57 Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
59 const double px = positionAndMomentum(3);
60 const double py = positionAndMomentum(4);
61 const double pt = hypot(px, py);
62 const double cosPhi0 = px / pt;
63 const double sinPhi0 = py / pt;
66 jacobianRot(iX, iX) = cosPhi0;
67 jacobianRot(iX, iY) = sinPhi0;
68 jacobianRot(iY, iX) = -sinPhi0;
69 jacobianRot(iY, iY) = cosPhi0;
70 jacobianRot(iZ, iZ) = 1.0;
72 jacobianRot(iPx, iPx) = cosPhi0;
73 jacobianRot(iPx, iPy) = sinPhi0;
74 jacobianRot(iPy, iPx) = -sinPhi0;
75 jacobianRot(iPy, iPy) = cosPhi0;
76 jacobianRot(iPz, iPz) = 1.0;
79 const double pz = positionAndMomentum(5);
80 const double invPt = 1 / pt;
81 const double invPtSquared = invPt * invPt;
82 Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
83 jacobianToHelixParameters(iD0, iY) = -1;
84 jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
85 jacobianToHelixParameters(iPhi0, iPy) = invPt;
86 jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
87 jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
88 jacobianToHelixParameters(iTanLambda, iPz) = invPt;
89 jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
90 jacobianToHelixParameters(iZ0, iZ) = 1;
92 jacobian = jacobianToHelixParameters * jacobianRot;
100 case 1 : rc =
"d0 : " ; break ;
101 case 2 : rc =
"phi0 : " ; break ;
102 case 3 : rc =
"omega : " ; break ;
103 case 4 : rc =
"z0 : " ; break ;
104 case 5 : rc =
"tandip: " ; break ;
105 case 6 : rc =
"L : " ; break ;
114 case 1 : rc =
"x : " ; break ;
115 case 2 : rc =
"y : " ; break ;
116 case 3 : rc =
"z : " ; break ;
117 case 4 : rc =
"px : " ; break ;
118 case 5 : rc =
"py : " ; break ;
119 case 6 : rc =
"pz : " ; break ;
126 for (
int i = 0; i < 3; ++i)
128 for (
int i = 0; i < 3; ++i)
130 B2INFO(
"charge: " << charge);
135 int charge,
double Bz,
138 Eigen::Matrix<double, 5, 6>& jacobian)
141 TVector3 position(positionAndMom(0),
145 TVector3 momentum(positionAndMom(3),
159 for (
int jin = 0; jin < 6; ++jin) {
160 for (
int i = 0; i < 3; ++i) {
161 postmp[i] = positionAndMom(i);
162 momtmp[i] = positionAndMom(i + 3);
165 postmp[jin] += delta;
167 momtmp[jin - 3] += delta;
171 jacobian(iD0, jin) = (helixPlusDelta.getD0() - helix.getD0()) / delta ;
172 jacobian(iPhi0, jin) = (helixPlusDelta.getPhi0() - helix.getPhi0()) / delta ;
173 jacobian(iOmega, jin) = (helixPlusDelta.getOmega() - helix.getOmega()) / delta ;
174 jacobian(iZ0, jin) = (helixPlusDelta.getZ0() - helix.getZ0()) / delta ;
175 jacobian(iTanLambda, jin) = (helixPlusDelta.getTanLambda() - helix.getTanLambda()) / delta ;
182 const Eigen::Matrix<double, 1, 6>& positionAndMom,
183 int charge,
double Bz,
186 Eigen::Matrix<double, 5, 6>& jacobian,
196 for (
int jin = 0; jin < 6; ++jin) {
197 for (
int i = 0; i < 3; ++i) {
198 postmp[i] = positionAndMom(i);
199 momtmp[i] = positionAndMom(i + 3);
203 postmp[jin] += delta;
205 momtmp[jin - 3] += delta;
209 jacobian(iD0, jin) = (helixPlusDelta.getD0() - helix.getD0()) / delta ;
210 jacobian(iPhi0, jin) = (helixPlusDelta.getPhi0() - helix.getPhi0()) / delta ;
211 jacobian(iOmega, jin) = (helixPlusDelta.getOmega() - helix.getOmega()) / delta ;
212 jacobian(iZ0, jin) = (helixPlusDelta.getZ0() - helix.getZ0()) / delta ;
213 jacobian(iTanLambda, jin) = (helixPlusDelta.getTanLambda() - helix.getTanLambda()) / delta ;
218 inline double sqr(
double x) {
return x * x ; }
223 if (phi < -TMath::Pi()) rc += TMath::TwoPi();
224 else if (phi > TMath::Pi()) rc -= TMath::TwoPi();
231 double& flt1,
double& flt2,
232 TVector3& vertex,
bool parallel)
235 double d0_1 = helix1.getD0();
236 double phi0_1 = helix1.getPhi0();
237 double omega_1 = helix1.getOmega();
238 double z0_1 = helix1.getZ0();
239 double tandip_1 = helix1.getTanLambda();
240 double cosdip_1 = cos(atan(tandip_1)) ;
242 double d0_2 = helix2.getD0();
243 double phi0_2 = helix2.getPhi0();
244 double omega_2 = helix2.getOmega();
245 double z0_2 = helix2.getZ0();
246 double tandip_2 = helix2.getTanLambda();
247 double cosdip_2 = cos(atan(tandip_2)) ;
249 double r_1 = 1 / omega_1 ;
250 double r_2 = 1 / omega_2 ;
252 double x0_1 = - (r_1 + d0_1) * sin(phi0_1) ;
253 double y0_1 = (r_1 + d0_1) * cos(phi0_1) ;
255 double x0_2 = - (r_2 + d0_2) * sin(phi0_2) ;
256 double y0_2 = (r_2 + d0_2) * cos(phi0_2) ;
258 double deltax = x0_2 - x0_1 ;
259 double deltay = y0_2 - y0_1 ;
266 const double pi = TMath::Pi();
267 double phi = - atan2(deltax, deltay) ;
268 double phinot = phi > 0 ? phi - pi : phi + pi ;
269 phi1[0] = r_1 < 0 ? phi : phinot ;
270 phi2[0] = r_2 > 0 ? phi : phinot ;
272 double R1 = fabs(r_1) ;
273 double R2 = fabs(r_2) ;
274 double Rmin = R1 < R2 ? R1 : R2 ;
275 double Rmax = R1 > R2 ? R1 : R2 ;
276 double dX = sqrt(deltax * deltax + deltay * deltay) ;
278 if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
281 double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
285 double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
289 }
else if (dX < Rmax) {
290 if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
291 else phi1[0] = r_1 < 0 ? phi : phinot ;
295 double z1(0), z2(0) ;
299 for (
int i = 0; i < nsolutions; ++i) {
300 double dphi1 =
phidomain(phi1[i] - phi0_1) ;
301 double dphi2 =
phidomain(phi2[i] - phi0_2) ;
302 for (
int n1 = 1 - ncirc; n1 <= 1 + ncirc ; ++n1) {
303 double l1 = (dphi1 + n1 * TMath::TwoPi()) / omega_1 ;
304 double tmpz1 = (z0_1 + l1 * tandip_1) ;
305 if (n1 == 0 || fabs(tmpz1) < 100) {
306 for (
int n2 = 1 - ncirc ; n2 <= 1 + ncirc; ++n2) {
307 double l2 = (dphi2 + n2 * TMath::TwoPi()) / omega_2 ;
308 double tmpz2 = (z0_2 + l2 * tandip_2) ;
309 if (n2 == 0 || fabs(tmpz2) < 100) {
310 if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
315 flt1 = l1 / cosdip_1 ;
316 flt2 = l2 / cosdip_2 ;
324 double x1 = r_1 * sin(phi1[ibest]) + x0_1 ;
325 double y1 = -r_1 * cos(phi1[ibest]) + y0_1 ;
327 double x2 = r_2 * sin(phi2[ibest]) + x0_2 ;
328 double y2 = -r_2 * cos(phi2[ibest]) + y0_2 ;
330 vertex.SetX(0.5 * (x1 + x2));
331 vertex.SetY(0.5 * (y1 + y2));
332 vertex.SetZ(0.5 * (z1 + z2));
334 return sqrt(sqr(x2 - x1) + sqr(y2 - y1) + sqr(z2 - z1)) ;
339 const TVector3& point,
342 double d0 = helix.getD0();
343 double phi0 = helix.getPhi0();
344 double omega = helix.getOmega();
345 double z0 = helix.getZ0();
346 double tandip = helix.getTanLambda();
347 double cosdip = cos(atan(tandip)) ;
349 double r = 1 / omega ;
351 double x0 = - (r + d0) * sin(phi0) ;
352 double y0 = (r + d0) * cos(phi0) ;
354 double deltax = x0 - point.X() ;
355 double deltay = y0 - point.Y() ;
357 const double pi = TMath::Pi();
358 double phi = - atan2(deltax, deltay) ;
359 if (r < 0) phi = phi > 0 ? phi - pi : phi + pi ;
362 double x = r * sin(phi) + x0 ;
363 double y = -r * cos(phi) + y0 ;
368 for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
369 double l = (dphi + n * TMath::TwoPi()) / omega ;
370 double tmpz = (z0 + l * tandip) ;
371 if (first || fabs(tmpz - point.z()) < fabs(z - point.z())) {
377 return sqrt(sqr(x - point.x()) + sqr(y - point.y()) + sqr(z - point.z())) ;
384 const double z __attribute__((unused)),
394 const double aq = charge / alpha;
396 const double pt = std::hypot(px, py);
397 const double pt2 = pt * pt;
398 const double pt3 = pt2 * pt;
399 const double aq2 = aq * aq;
401 const double x2 = x * x;
402 const double y2 = y * y;
403 const double r = x2 + y2;
405 const double px2 = px * px;
406 const double py2 = py * py;
408 const double px0 = px - aq * y;
409 const double py0 = py + aq * x;
411 const double pt02 = px0 * px0 + py0 * py0;
412 const double pt0 = std::sqrt(pt02);
413 double sqrt13 = pt0 / pt;
416 jacobian(0, 0) = py0 / pt0;
417 jacobian(0, 1) = -px0 / pt0;
419 jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
420 (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
421 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
423 jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
424 (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
425 (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
429 jacobian(1, 0) = aq * px0 / pt02;
430 jacobian(1, 1) = aq * py0 / pt02;
432 jacobian(1, 3) = -py0 / pt02;
433 jacobian(1, 4) = px0 / pt02;
440 jacobian(2, 3) = - aq * px / pt3;
441 jacobian(2, 4) = - aq * py / pt3;
445 jacobian(3, 0) = -pz * px0 / pt02;
446 jacobian(3, 1) = -pz * py0 / pt02;
448 jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
449 jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
450 jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq;
456 jacobian(4, 3) = -pz * px / pt3;
457 jacobian(4, 4) = -pz * py / pt3;
458 jacobian(4, 5) = 1. / pt;