MyMarlinTPC  170316
SimpleHelixTrackModel.cc
Go to the documentation of this file.
2 
3 #include <iostream>
4 #include <string>
5 #include <cmath>
6 
7 #include "marlin/Global.h"
8 #include <gear/BField.h>
9 #include <gearimpl/Vector3D.h>
10 
11 #include "EVENT/LCIO.h"
12 
13 #include "EVENT/TrackerHit.h"
14 
15 #include "TMath.h"
16 
17 using namespace std;
18 using namespace gear;
19 
20 namespace marlintpc {
21 
23 
34 TMatrixD localHelixAnalyticalJacobian(double ds, double qbyp, Vector3D& t1, Vector3D& t2, Vector3D& bc) {
35  TMatrixD ajac(5, 5);
36  ajac.UnitMatrix();
37  const double qp = -bc.r(); // -|B*c|
38  const double q = qp * qbyp; // Q
39  if (q == 0.) {
40  // line
41  ajac[3][2] = ds * sqrt(t1[0] * t1[0] + t1[1] * t1[1]);
42  ;
43  ajac[4][1] = ds;
44  } else {
45  // helix
46  // at start
47  const double cosl1 = sqrt(t1[0] * t1[0] + t1[1] * t1[1]);
48  // at end
49  const double cosl2 = sqrt(t2[0] * t2[0] + t2[1] * t2[1]);
50  const double cosl2Inv = 1. / cosl2;
51  // magnetic field direction
52  Vector3D hn(bc.unit());
53  // (signed) momentum
54  const double pav = 1.0 / qbyp;
55  //
56  const double theta = q * ds;
57  const double sint = sin(theta);
58  const double cost = cos(theta);
59  const double gamma = hn.dot(t2); // H*T
60  Vector3D an1 = hn.cross(t1); // HxT0
61  Vector3D an2 = hn.cross(t2); // HxT
62  // U0, V0
63  const double au1 = 1. / t1.trans();
64  Vector3D u1(-au1 * t1[1], au1 * t1[0], 0.);
65  Vector3D v1(-t1[2] * u1[1], t1[2] * u1[0], t1[0] * u1[1] - t1[1] * u1[0]);
66  // U, V
67  const double au2 = 1. / t2.trans();
68  Vector3D u2(-au2 * t2[1], au2 * t2[0], 0.);
69  Vector3D v2(-t2[2] * u2[1], t2[2] * u2[0], t2[0] * u2[1] - t2[1] * u2[0]);
70  //
71  const double anv = -hn.dot(u2); // N*V=-H*U
72  const double anu = hn.dot(v2); // N*U= H*V
73  const double omcost = 1. - cost;
74  const double tmsint = theta - sint;
75  // M0-M
76  Vector3D dx(-(gamma * tmsint * hn[0] + sint * t1[0] + omcost * an1[0]) / q,
77  -(gamma * tmsint * hn[1] + sint * t1[1] + omcost * an1[1]) / q,
78  -(gamma * tmsint * hn[2] + sint * t1[2] + omcost * an1[2]) / q);
79  // HxU0
80  Vector3D hu1 = hn.cross(u1);
81  // HxV0
82  Vector3D hv1 = hn.cross(v1);
83  // some dot products
84  const double u1u2 = u1.dot(u2), u1v2 = u1.dot(v2), v1u2 = v1.dot(u2), v1v2 = v1.dot(v2);
85  const double hu1u2 = hu1.dot(u2), hu1v2 = hu1.dot(v2), hv1u2 = hv1.dot(u2), hv1v2 = hv1.dot(v2);
86  const double hnu1 = hn.dot(u1), hnv1 = hn.dot(v1), hnu2 = hn.dot(u2), hnv2 = hn.dot(v2);
87  const double t2u1 = t2.dot(u1), t2v1 = t2.dot(v1);
88  const double t2dx = t2.dot(dx), u2dx = u2.dot(dx), v2dx = v2.dot(dx);
89  const double an2u1 = an2.dot(u1), an2v1 = an2.dot(v1);
90  // jacobian
91  // 1/P
92  ajac[0][0] = 1.;
93  // Lambda
94  ajac[1][0] = -qp * anv * t2dx;
95  ajac[1][1] = cost * v1v2 + sint * hv1v2 + omcost * hnv1 * hnv2 + anv * (-sint * t2v1 + omcost * an2v1 - gamma * tmsint * hnv1);
96  ajac[1][2] = cosl1
97  * (cost * u1v2 + sint * hu1v2 + omcost * hnu1 * hnv2 + anv * (-sint * t2u1 + omcost * an2u1 - gamma * tmsint * hnu1));
98  ajac[1][3] = -q * anv * t2u1;
99  ajac[1][4] = -q * anv * t2v1;
100  // Phi
101  ajac[2][0] = -qp * anu * t2dx * cosl2Inv;
102  ajac[2][1] = cosl2Inv
103  * (cost * v1u2 + sint * hv1u2 + omcost * hnv1 * hnu2 + anu * (-sint * t2v1 + omcost * an2v1 - gamma * tmsint * hnv1));
104  ajac[2][2] = cosl2Inv * cosl1
105  * (cost * u1u2 + sint * hu1u2 + omcost * hnu1 * hnu2 + anu * (-sint * t2u1 + omcost * an2u1 - gamma * tmsint * hnu1));
106  ajac[2][3] = -q * anu * t2u1 * cosl2Inv;
107  ajac[2][4] = -q * anu * t2v1 * cosl2Inv;
108  // Xt
109  ajac[3][0] = pav * u2dx;
110  ajac[3][1] = (sint * v1u2 + omcost * hv1u2 + tmsint * hnu2 * hnv1) / q;
111  ajac[3][2] = (sint * u1u2 + omcost * hu1u2 + tmsint * hnu2 * hnu1) * cosl1 / q;
112  ajac[3][3] = u1u2;
113  ajac[3][4] = v1u2;
114  // Yt
115  ajac[4][0] = pav * v2dx;
116  ajac[4][1] = (sint * v1v2 + omcost * hv1v2 + tmsint * hnv2 * hnv1) / q;
117  ajac[4][2] = (sint * u1v2 + omcost * hu1v2 + tmsint * hnv2 * hnu1) * cosl1 / q;
118  ajac[4][3] = u1v2;
119  ajac[4][4] = v1v2;
120  }
121  return ajac;
122 }
123 
125 simpleHelix::simpleHelix(const double rinv, const double phi0, const double dca, const double dzds, const double z0,
126  const double* refPoint, const double Bzc) :
127  _xref(refPoint[0]), _yref(refPoint[1]), _zref(refPoint[2]), _bzc(Bzc), _rinv(rinv), _phi0(phi0), _dca(dca), _dzds(dzds), _z0(
128  z0), _xRelCenter(-(1. - _dca * _rinv) * sin(_phi0)), _yRelCenter((1. - _dca * _rinv) * cos(_phi0)), _eps(1.0e-6) {
129 }
130 
132 simpleHelix::simpleHelix(const double* parameters, const double* refPoint, const double Bzc) :
133  _xref(refPoint[0]), _yref(refPoint[1]), _zref(refPoint[2]), _bzc(Bzc), _rinv(parameters[0]), _phi0(parameters[1]), _dca(
134  parameters[2]), _dzds(parameters[3]), _z0(parameters[4]), _xRelCenter(-(1. - _dca * _rinv) * sin(_phi0)), _yRelCenter(
135  (1. - _dca * _rinv) * cos(_phi0)), _eps(1.0e-6) {
136 }
137 
139 void simpleHelix::dump() const {
140  std::cout << " simpleHelix " << _rinv << ", " << _phi0 << ", " << _dca << ", " << _dzds << ", " << _z0 << std::endl;
141  std::cout << " rel. center " << _xRelCenter << ", " << _yRelCenter << std::endl;
142  std::cout << " ref. point " << _xref << ", " << _yref << ", " << _zref << std::endl;
143 }
144 
146 
153 double simpleHelix::getArcLengthXY(const double* position) const {
154  const double xLoc = position[0] - _xref;
155  const double yLoc = position[1] - _yref;
156  // line (approximation)
157  if ((xLoc * xLoc + yLoc * yLoc) * _rinv * _rinv < _eps * _eps) return cos(_phi0) * xLoc + sin(_phi0) * yLoc;
158  // helix
159  const double dx = xLoc * _rinv - _xRelCenter;
160  const double dy = yLoc * _rinv - _yRelCenter;
161  double dphi = atan2(dx, -dy) - _phi0;
162  if (abs(dphi) > M_PI) dphi -= (dphi > 0.) ? 2.0 * M_PI : -2.0 * M_PI;
163  return dphi / _rinv;
164 }
165 
167 void simpleHelix::getZSDirection(double* direction) const {
168  const double tanl = _dzds;
169  const double cosl = 1. / sqrt(1. + tanl * tanl);
170  direction[0] = cosl;
171  direction[1] = cosl * tanl;
172 }
173 
175 
179 void simpleHelix::getPosAtArcLength(const double sArc, double* position) const {
180  if (abs(_rinv * sArc) <= _eps) {
181  // line (approximation)
182  position[0] = _xref + _dca * sin(_phi0) + sArc * cos(_phi0);
183  position[1] = _yref - _dca * cos(_phi0) + sArc * sin(_phi0);
184  } else {
185  // helix
186  const double phi = _phi0 + sArc * _rinv;
187  position[0] = _xref + (_xRelCenter + sin(phi)) / _rinv;
188  position[1] = _yref + (_yRelCenter - cos(phi)) / _rinv;
189  }
190  position[2] = _zref + _z0 + sArc * _dzds;
191 }
192 
194 
207 bool simpleHelix::getExpectedPlanePos(const double* point, const double measPhi, double& xyPos, double& zPos, double& sArc,
208  double& phi, double& lambda) const {
209  const double xLoc = point[0] - _xref;
210  const double yLoc = point[1] - _yref;
211  const double zLoc = point[2] - _zref;
212  if ((xLoc * xLoc + yLoc * yLoc) * _rinv * _rinv < _eps * _eps) {
213  // line (approximation)
214  if (measPhi == _phi0) return false;
215  // intersection exists
216  const double cosb = sin(measPhi - _phi0);
217  const double sinb = cos(measPhi - _phi0);
218  sArc = (sin(measPhi) * xLoc - cos(measPhi) * yLoc - _dca * sinb) / cosb;
219  xyPos = (sin(_phi0) * xLoc - cos(_phi0) * yLoc - _dca) / cosb;
220  phi = _phi0;
221  } else {
222  // helix
223  const double dx = _xRelCenter - xLoc * _rinv;
224  const double dy = _yRelCenter - yLoc * _rinv;
225  const double ex = cos(measPhi);
226  const double ey = sin(measPhi);
227  const double A = ex * dx + ey * dy;
228  const double B = dx * dx + dy * dy - 1.0;
229  // C = ex * dy - ey * dx
230  if (A * A < B) return false;
231  // intersection exists
232  const double cosb = A * sqrt(1.0 - B / (A * A));
233  // sinb = C
234  xyPos = (A - cosb) / _rinv;
235  const double dxSec = (xLoc + ex * xyPos) * _rinv - _xRelCenter;
236  const double dySec = (yLoc + ey * xyPos) * _rinv - _yRelCenter;
237  phi = atan2(dxSec, -dySec);
238  double dphi = phi - _phi0;
239  if (abs(dphi) > M_PI) dphi -= dphi > 0. ? 2.0 * M_PI : -2.0 * M_PI;
240  sArc = dphi / _rinv;
241  }
242  zPos = _z0 + sArc * _dzds - zLoc;
243  lambda = atan(_dzds);
244  return true;
245 }
246 
248 
255 TMatrixD simpleHelix::analyticalHelixJacobian(const double phi1, const double ds) const {
256  // magnetic field * c (in Z direction)
257  Vector3D bFieldc(0., 0., _bzc);
258  // track direction vectors T0, T
259  const double cosl = 1. / sqrt(1. + _dzds * _dzds);
260  const double sinl = cosl * _dzds;
261  const double phi2 = phi1 + ds * cosl * _rinv;
262  Vector3D dir1(cosl * cos(phi1), cosl * sin(phi1), sinl);
263  Vector3D dir2(cosl * cos(phi2), cosl * sin(phi2), sinl);
264  // q/p
265  const double qbyp = (_rinv != 0.) ? -cosl * _rinv / _bzc : 0.;
266  return localHelixAnalyticalJacobian(ds, qbyp, dir1, dir2, bFieldc);
267 }
268 
270 
277 TMatrixD simpleHelix::simplifiedHelixJacobian(const double phi1, const double ds) const {
278  const double cosl = 1. / sqrt(1. + _dzds * _dzds);
279  TMatrixD ajac(5, 5);
280  ajac.UnitMatrix();
281  ajac[2][0] = -_bzc * ds;
282  ajac[3][0] = -0.5 * _bzc * ds * ds * cosl;
283  ajac[3][2] = ds * cosl;
284  ajac[4][1] = ds;
285  return ajac;
286 }
287 
289 
295  // define local curvilinear coordinate system
296  // U = Z x T / |Z x T|, V = T x U
297  const double cosPhi = cos(_phi0);
298  const double sinPhi = sin(_phi0);
299  const double tanLambda = _dzds;
300  const double cosLambda = 1. / sqrt(1. + tanLambda * tanLambda);
301  const double sinLambda = cosLambda * _dzds;
302  Vector3D T(cosPhi * cosLambda, sinPhi * cosLambda, sinLambda);
303  Vector3D U(-sinPhi, cosPhi, 0.);
304  Vector3D V(-cosPhi * sinLambda, -sinPhi * sinLambda, cosLambda);
305  // helper vectors for local (perigee) system
306  // J = -U , K = Z, I = J x K
307  Vector3D J(sinPhi, -cosPhi, 0.);
308  Vector3D K(0., 0., 1.);
309  Vector3D I = J.cross(K);
310  // set the right variables for helix parametrisation by wittek/strandlie
311  // H is direction of magnetic field, N is H x T/a, a = |H x T|
312  Vector3D H(0., 0., 1.); // magnetic field direction
313  Vector3D aN = H.cross(T); // a*N
314  // formal helpers for later evaluation of jacobian transformation from curvilinear track parameters to perigee frame
315  const double ui = U.dot(I), anv = aN.dot(V), ti = T.dot(I);
316  const double vi = V.dot(I), anu = aN.dot(U), vk = V.dot(K);
317 
318  TMatrixD cl2perjacobian(5, 5);
319  cl2perjacobian.UnitMatrix();
320  // differences to unit matrix:
321  const double Q = _rinv * cosLambda; // -Bz*q/p
322  cl2perjacobian[0][0] = -_bzc / cosLambda;
323  cl2perjacobian[0][1] = Q * tanLambda / cosLambda;
324  cl2perjacobian[0][3] = -Q * Q * tanLambda * ui * anv / cosLambda / ti;
325  cl2perjacobian[0][4] = -Q * Q * tanLambda * vi * anv / cosLambda / ti;
326  cl2perjacobian[1][1] = -1.;
327  cl2perjacobian[1][3] = Q * ui * anv / ti;
328  cl2perjacobian[1][4] = Q * vi * anv / ti;
329  cl2perjacobian[2][3] = -Q * ui * anu / cosLambda / ti;
330  cl2perjacobian[2][4] = -Q * vi * anu / cosLambda / ti;
331  cl2perjacobian[3][3] = vk / ti;
332  cl2perjacobian[4][4] = -1. / ti;
333 
334  return cl2perjacobian;
335 }
336 
338 
346  TMatrixD per2ILDjacobian(5, 5);
347  per2ILDjacobian.UnitMatrix();
348  // differences to unit matrix:
349  per2ILDjacobian[0][0] = -1.;
350  per2ILDjacobian[1][1] = -(1. + _dzds * _dzds);
351  per2ILDjacobian[3][3] = -1.;
352 
353  return per2ILDjacobian;
354 }
355 
357 
365  TMatrixD per2LCIOjacobian(5, 5);
366  // differences to zero matrix:
367  per2LCIOjacobian[0][3] = -1.;
368  per2LCIOjacobian[1][2] = 1.;
369  per2LCIOjacobian[2][0] = -1.;
370  per2LCIOjacobian[3][4] = 1.;
371  per2LCIOjacobian[4][1] = -(1. + _dzds * _dzds);
372 
373  return per2LCIOjacobian;
374 }
375 
377 
385  TMatrixD hlx2LCIOjacobian(5, 5);
386  // differences to zero matrix:
387  hlx2LCIOjacobian[0][2] = -1.;
388  hlx2LCIOjacobian[1][1] = 1.;
389  hlx2LCIOjacobian[2][0] = -1.;
390  hlx2LCIOjacobian[3][4] = 1.;
391  hlx2LCIOjacobian[4][3] = 1.;
392 
393  return hlx2LCIOjacobian;
394 }
395 
397 
403 void simpleHelix::moveTo(const double newRefX, const double newRefY, const double newRefZ, double* newPar) {
404  const double dx = _xref - newRefX;
405  const double dy = _yref - newRefY;
406  const double dz = _zref - newRefZ;
407  newPar[0] = _rinv;
408  newPar[1] = _phi0;
409  newPar[2] = _dca;
410  newPar[3] = _dzds;
411  newPar[4] = _z0 + dz;
412 
413  const double cosphi = cos(_phi0);
414  const double sinphi = sin(_phi0);
415  const double u = 1. - _rinv * _dca;
416  const double dp = dx * sinphi - dy * cosphi + _dca;
417  const double dl = dx * cosphi + dy * sinphi;
418  const double sa = 2. * dp - _rinv * (dp * dp + dl * dl);
419  const double sb = -_rinv * dx + u * sinphi;
420  const double sc = _rinv * dy + u * cosphi;
421  const double sd = sqrt(1. - _rinv * sa);
422  // transformed parameters
423  if ((dx * dx + dy * dy) * _rinv * _rinv < _eps * _eps) {
424  newPar[2] = dp;
425  newPar[4] -= dl * _dzds;
426  } else {
427  newPar[1] = atan2(sb, sc);
428  newPar[2] = sa / (1. + sd);
429  double dphi = newPar[1] - _phi0;
430  if (abs(dphi) > M_PI) dphi -= (dphi > 0.) ? 2.0 * M_PI : -2.0 * M_PI;
431  newPar[4] += dphi / _rinv * _dzds;
432  }
433 }
434 
436 
444 void simpleHelix::getStateAt(const double posX, const double posY, const double posZ, TMatrixDSym& refCov, TVectorD& newPar,
445  TMatrixDSym& newCov) {
446  const double dx = _xref - posX;
447  const double dy = _yref - posY;
448  const double dz = _zref - posZ;
449 
450  const double cosphi = cos(_phi0);
451  const double sinphi = sin(_phi0);
452  const double u = 1. - _rinv * _dca;
453  const double dp = dx * sinphi - dy * cosphi + _dca;
454  const double dl = dx * cosphi + dy * sinphi;
455  const double sa = 2. * dp - _rinv * (dp * dp + dl * dl);
456  const double sb = -_rinv * dx + u * sinphi;
457  const double sc = _rinv * dy + u * cosphi;
458  const double sd = sqrt(1. - _rinv * sa);
459  // transformed parameters
460  double sArc;
461  if ((dx * dx + dy * dy) * _rinv * _rinv < _eps * _eps) {
462  newPar[0] = _phi0;
463  newPar[1] = dp;
464  newPar[2] = _dzds;
465  sArc = -dl;
466  newPar[3] = _z0 + sArc * _dzds + dz;
467  } else {
468  newPar[0] = _rinv;
469  newPar[1] = atan2(sb, sc);
470  newPar[2] = sa / (1. + sd);
471  newPar[3] = _dzds;
472  double dphi = newPar[1] - _phi0;
473  if (abs(dphi) > M_PI) dphi -= (dphi > 0.) ? 2.0 * M_PI : -2.0 * M_PI;
474  sArc = dphi / _rinv;
475  newPar[4] = _z0 + sArc * _dzds + dz;
476  }
477  // define jacobian
478  int nPar = (_rinv == 0.) ? 4 : 5;
479  TMatrixD aJac(nPar, nPar);
480  aJac.UnitMatrix();
481  if ((dx * dx + dy * dy) * _rinv * _rinv < _eps * _eps) {
482  aJac[1][0] = -sArc;
483  aJac[3][2] = sArc;
484  } else {
485  const double fc = 1. / (sb * sb + sc * sc);
486  const double fl = 0.5 * sa / (sd * (1. + sd) * (1. + sd));
487  const double fm = -_rinv * fl + 1. / (sd * (1. + sd));
488  aJac[1][0] = -fc * dl;
489  aJac[1][1] = fc * u * (1. - _rinv * dp);
490  aJac[1][2] = -fc * _rinv * _rinv * dl;
491  aJac[2][0] = -fm * (dp * dp + dl * dl) + fl * sa;
492  aJac[2][1] = 2. * fm * u * dl;
493  aJac[2][2] = 2. * fm * (1. - _rinv * dp);
494  aJac[4][0] = _dzds * (aJac[1][0] - sArc) / _rinv;
495  aJac[4][1] = _dzds * (aJac[1][1] - 1.) / _rinv;
496  aJac[4][2] = _dzds * aJac[1][2] / _rinv;
497  aJac[4][3] = sArc;
498  }
499  // transformed covariance
500  newCov = refCov;
501  newCov.Similarity(aJac);
502 }
503 
505 
510 localHelix::localHelix(const double* parameters, const double* refPoint, const double bScale) :
511  _bfac(bScale * 0.0002998), _offset(3), _rotation(3, 3), _rotInv(3, 3) {
512  // track direction at PCA
513  const double cosPhi = cos(parameters[1]);
514  const double sinPhi = sin(parameters[1]);
515  const double cosLambda = 1. / sqrt(1. + parameters[3] * parameters[3]);
516  _trackDir = cosLambda * Vector3D(cosPhi, sinPhi, parameters[3]);
517  // position at PCA
518  double pca[] = { refPoint[0] + sinPhi * parameters[2], refPoint[1] - cosPhi * parameters[2], refPoint[2] + parameters[4] };
519  _offset = TVectorD(3, pca);
520  // Bfield at PCA
521  _bFieldc = getBFieldc(pca);
522  // Q/P (= const)
523  _qbyp = (_bFieldc.z() != 0.) ? -cosLambda * parameters[0] / _bFieldc.z() : 0.;
524  // local parameters
525  calcLocal();
526 }
527 
529 
533  // calculate rotation
534  Vector3D h = (_bFieldc.r() != 0.) ? _bFieldc.unit() : Vector3D(0., 0., 1.); // in field (or Z) direction
535  Vector3D t = _trackDir; // in track direction
536  Vector3D n = h.cross(t).unit(); // in bending plane perpendicular to track direction
537  Vector3D p = n.cross(h); // in bending plane parallel to track direction
538  // local system is (p,n,h)
539  for (int i = 0; i < 3; ++i) {
540  _rotation[0][i] = p[i];
541  _rotation[1][i] = n[i];
542  _rotation[2][i] = h[i];
543  _localRef[i] = 0.;
544  }
545  _rotInv = _rotation;
546  _rotInv.Invert();
547  // calculate local track parameters
548  const double gamma = h.dot(t);
549  const double alpha = sqrt(1. - gamma * gamma);
550  _cosLambda = alpha;
551  _localPar[0] = _qbyp * _bFieldc.r() / (-alpha); // rho
552  _localPar[1] = 0.; // phi0
553  _localPar[2] = 0.; // rho
554  _localPar[3] = gamma / alpha; // dzds
555  _localPar[4] = 0.; // z0
556 }
557 
559 
563  // local direction
564  TVectorD localDir(3);
565  localDir[0] = cos(_localPar[1]) * _cosLambda;
566  localDir[1] = sin(_localPar[1]) * _cosLambda;
567  localDir[2] = _localPar[3] * _cosLambda;
568  // global direction
569  TVectorD globalDir(_rotInv * localDir);
570  for (int i = 0; i < 3; ++i)
571  _trackDir[i] = globalDir[i];
572  // global offset
573  _offset += _rotInv * TVectorD(3, _localRef);
574 }
575 
577 void localHelix::dump() const {
578  cout << " localHelix, Q/P = " << _qbyp << endl;
579  cout << " Bfield*c " << _bFieldc.x() << ", " << _bFieldc.y() << ", " << _bFieldc.z() << endl;
580  cout << " direction " << _trackDir.x() << ", " << _trackDir.y() << ", " << _trackDir.z() << endl;
581  cout << " offset " << _offset[0] << ", " << _offset[1] << ", " << _offset[2] << ", " << endl;
582  cout << " rotation " << endl;
583  _rotation.Print();
584 }
585 
587 
595 TMatrixD localHelix::propagateTo(const double* point, const double mstep) {
596  TMatrixD aJac(5, 5);
597  if (_qbyp == 0.) {
598  // line
599  // current helix
600  simpleHelix startHelix(_localPar, _localRef, _bFieldc.r());
601  // position relative to offset
602  double relPos[] = { point[0] - _offset[0], point[1] - _offset[1], point[2] - _offset[2] };
603  // 3D arc length to point
604  double deltaW = startHelix.getArcLengthXY(relPos) / _cosLambda;
605  aJac = startHelix.analyticalHelixJacobian(0., deltaW);
606  // adjust offset
607  for (int i = 0; i < 3; ++i)
608  _offset[i] += deltaW * _trackDir[i];
609  } else {
610  //helix
611  const double maxStep = abs(mstep);
612  aJac.UnitMatrix();
613  double sArc, newPos[3], step;
614  TVectorD localPos(3);
615  do {
616  // current helix, (global) track direction, field
617  simpleHelix startHelix(_localPar, _localRef, _bFieldc.r());
618  Vector3D tStart = _trackDir;
619  Vector3D bStart = _bFieldc;
620  // arc length to point
621  localPos = _rotation * (TVectorD(3, point) - _offset);
622  sArc = startHelix.getArcLengthXY(localPos.GetMatrixArray());
623  // step size in 3D, limited to _maxStep
624  step = abs(sArc / _cosLambda) > maxStep ? (sArc > 0. ? maxStep : -maxStep) : sArc / _cosLambda;
625  // new position (on helix) after 'step' for new magnetic field
626  startHelix.getPosAtArcLength(step * _cosLambda, newPos);
627  TVectorD newGlobalPos(_rotInv * TVectorD(3, newPos) + _offset);
628  // new field
629  Vector3D newBc = getBFieldc(newGlobalPos.GetMatrixArray());
630  // average field
631  _bFieldc = 0.5 * (_bFieldc + newBc);
632  // adjust local parameters
633  calcLocal();
634  // propgate using helix with average field
635  simpleHelix avgHelix(_localPar, _localRef, _bFieldc.r());
636  // redo arc length to point
637  localPos = _rotation * (TVectorD(3, point) - _offset);
638  sArc = startHelix.getArcLengthXY(localPos.GetMatrixArray());
639  step = abs(sArc / _cosLambda) > maxStep ? (sArc > 0. ? maxStep : -maxStep) : sArc / _cosLambda;
640  // new position (on helix) after 'step' as new reference point
641  startHelix.getPosAtArcLength(step * _cosLambda, _localRef);
642  // adjust track parameters at new (reference) position
643  _localPar[1] += step * _localPar[0];
644  // adjust global parameters
645  calcGlobal();
646  // update jacobian
647  aJac = localHelixAnalyticalJacobian(step, _qbyp, tStart, _trackDir, bStart) * aJac;
648  // new field
649  _bFieldc = newBc;
650  // adjust local parameters
651  calcLocal();
652  } while (abs(sArc / _cosLambda) > maxStep);
653  }
654  return aJac;
655 }
656 
658 
664  double globalPar[5];
665  // calculate global track parameters
666  const double cosLambda = sqrt(1. - _trackDir[2] * _trackDir[2]);
667  globalPar[0] = _qbyp * _bFieldc.z() / (-cosLambda); // rho
668  globalPar[1] = atan2(_trackDir[1], _trackDir[0]); // phi0
669  globalPar[2] = 0.; // dca
670  globalPar[3] = _trackDir[2] / cosLambda; // dzds = tanLambda
671  globalPar[4] = 0.; // z0
672  return simpleHelix(globalPar, _offset.GetMatrixArray(), _bFieldc.z());
673 }
674 
676 
680 Vector3D localHelix::getBFieldc(const double* pos) const {
681  Vector3D bfield = marlin::Global::GEAR->getBField().at(Vector3D(pos));
682  return _bfac * bfield;
683 }
684 
686 
691 simpleFitXY::simpleFitXY(bool flag, double xr, double yr) :
692  _curved(flag), _npar((flag) ? 3 : 2), _xRef(xr), _yRef(yr), _parameters(_npar), _covariance(_npar) {
693  _numPoints = 0;
694  _sx = _sy = _sxx = _sxy = _syy = _sw = 0.;
695  _sr = _sxr = _syr = _srr = 0.;
696 }
697 
699 
704 void simpleFitXY::addPoint(double x, double y, double w) {
705  _numPoints++;
706  double xl = x - _xRef;
707  double yl = y - _yRef;
708  _sw += w;
709  _sx += w * xl;
710  _sy += w * yl;
711  _sxx += w * xl * xl;
712  _sxy += w * xl * yl;
713  _syy += w * yl * yl;
714  if (_curved) {
715  double r2 = xl * xl + yl * yl;
716  _sr += w * r2;
717  _sxr += w * r2 * xl;
718  _syr += w * r2 * yl;
719  _srr += w * r2 * r2;
720  }
721 }
722 
724 
727 void simpleFitXY::addTrack(EVENT::Track const * seedTrack) {
728  EVENT::TrackerHitVec inputHitVec = seedTrack->getTrackerHits();
729  for (unsigned int iHit = 0; iHit < inputHitVec.size(); iHit++) {
730  this->simpleFitXY::addPoint(inputHitVec[iHit]->getPosition()[0], inputHitVec[iHit]->getPosition()[1], 1);
731  }
732 
733 }
734 
736 
741 int simpleFitXY::fit(double& Chi2, int& nPoints) {
742  // averages
743  double ax = _sx / _sw;
744  double ay = _sy / _sw;
745  double ar = _sr / _sw;
746  double axx = _sxx / _sw;
747  double ayy = _syy / _sw;
748  double axy = _sxy / _sw;
749  double axr = _sxr / _sw;
750  double ayr = _syr / _sw;
751  double arr = _srr / _sw;
752  // variances
753  double cxx = axx - ax * ax;
754  double cyy = ayy - ay * ay;
755  double cxy = axy - ax * ay;
756  double cxr = axr - ax * ar;
757  double cyr = ayr - ay * ar;
758  double crr = arr - ar * ar;
759 
760  double q1, q2;
761  if (_curved) {
762  q1 = crr * cxy - cxr * cyr;
763  q2 = crr * (cxx - cyy) - cxr * cxr + cyr * cyr;
764  } else {
765  q1 = cxy;
766  q2 = cxx - cyy;
767  }
768  double phi = 0.5 * atan2(2. * q1, q2);
769  double sinphi = sin(phi);
770  double cosphi = cos(phi);
771  // compare phi with initial track direction
772  if (cosphi * (ax + _xRef) + sinphi * (ay + _yRef) < 0.) {
773  // reverse direction
774  phi -= (phi > 0.) ? M_PI : -M_PI;
775  cosphi = -cosphi;
776  sinphi = -sinphi;
777  }
778  if (_curved) {
779  double kappa = (sinphi * cxr - cosphi * cyr) / crr;
780  double delta = -kappa * ar + sinphi * ax - cosphi * ay;
781  // track parameters
782  double rho = -2. * kappa / sqrt(1. - 4. * delta * kappa);
783  double d = 2. * delta / (1. + sqrt(1. - 4. * delta * kappa));
784  _parameters[0] = rho;
785  _parameters[1] = phi;
786  _parameters[2] = d;
787  // chi2
788  double u = 1. - rho * d;
789  Chi2 = _sw * u * u * (sinphi * sinphi * cxx - 2. * sinphi * cosphi * cxy + cosphi * cosphi * cyy - kappa * kappa * crr);
790  //cout << " xyfit " << Chi2 << " " << _numPoints << " " <<_npar << ": " << rho << " " << phi << " " << d << endl;
791  // calculate covariance matrix
792  double sa = sinphi * _sx - cosphi * _sy;
793  double sb = cosphi * _sx + sinphi * _sy;
794  double sc = (sinphi * sinphi - cosphi * cosphi) * _sxy + sinphi * cosphi * (_sxx - _syy);
795  double sd = sinphi * _sxr - cosphi * _syr;
796  double saa = sinphi * sinphi * _sxx - 2. * sinphi * cosphi * _sxy + cosphi * cosphi * _syy;
797  _covariance[0][0] = 0.25 * _srr - d * (sd - d * (saa + 0.5 * _sr - d * (sa - 0.25 * d * _sw)));
798  _covariance[0][1] = u * (0.5 * (cosphi * _sxr + sinphi * _syr) - d * (sc - 0.5 * d * sb));
799  _covariance[1][0] = _covariance[0][1];
800  _covariance[1][1] = u * u * (cosphi * cosphi * _sxx + 2. * cosphi * sinphi * _sxy + sinphi * sinphi * _syy);
801  _covariance[0][2] = rho * (-0.5 * sd + d * saa) - 0.5 * u * _sr + 0.5 * d * ((3 * u - 1.) * sa - u * d * _sw);
802  _covariance[2][0] = _covariance[0][2];
803  _covariance[1][2] = -u * (rho * sc + u * sb);
804  _covariance[2][1] = _covariance[1][2];
805  _covariance[2][2] = rho * (rho * saa + 2 * u * sa) + u * u * _sw;
806  } else {
807  // track parameters
808  double d = sinphi * ax - cosphi * ay;
809  _parameters[0] = phi;
810  _parameters[1] = d;
811  // chi2
812  Chi2 = _sw * (sinphi * sinphi * cxx - 2. * sinphi * cosphi * cxy + cosphi * cosphi * cyy);
813  //cout << " xyfit " << chi2 << " " << _numPoints-_npar << ": " << phi << " " << d << endl;
814  // calculate covariance matrix
815  _covariance[0][0] = cosphi * cosphi * _sxx + 2. * cosphi * sinphi * _sxy + sinphi * sinphi * _syy;
816  _covariance[0][1] = -(cosphi * _sx + sinphi * _sy);
817  _covariance[1][0] = _covariance[0][1];
818  _covariance[1][1] = _sw;
819  }
820  _covariance.Invert();
821  nPoints = _numPoints;
822  return _npar;
823 }
824 
826 
829 TVectorD simpleFitXY::getPar() const {
830  return _parameters;
831 }
832 
834 
837 TMatrixDSym simpleFitXY::getCov() const {
838  return _covariance;
839 }
840 
844  _numPoints = 0;
845  _sx = _sy = _sxx = _sxy = _syy = _sw = 0.;
846 }
847 
849 
854 void simpleFitZS::addPoint(double x, double y, double w) {
855  _numPoints++;
856  // x is S, y is Z
857  _sw += w;
858  _sx += w * x;
859  _sy += w * y;
860  _sxx += w * x * x;
861  _sxy += w * x * y;
862  _syy += w * y * y;
863 }
864 
866 
871 int simpleFitZS::fit(double& Chi2, int& nPoints) {
872  // linear equation system A*x = b
873  //cout << " zsfit " << endl;
874  TVectorD bVec(2);
875  bVec[0] = _sxy;
876  bVec[1] = _sy;
877  TMatrixDSym aMat(2);
878  aMat[0][0] = _sxx;
879  aMat[0][1] = aMat[1][0] = _sx;
880  aMat[1][1] = _sw;
881  // solve
882  aMat.Invert();
883  _parameters = aMat * bVec;
884  _covariance = aMat;
885  // chi2
886  Chi2 = _parameters[0] * _parameters[0] * _sxx + _parameters[1] * _parameters[1] * _sw + _syy
887  + 2. * _parameters[0] * _parameters[1] * _sx - 2. * _parameters[0] * _sxy - 2. * _parameters[1] * _sy;
888  //cout << " zsfit " << Chi2 << " " << _numPoints-_npar << ": " << _parameters[0] << " " << _parameters[1] << endl;
889  nPoints = _numPoints;
890  return _npar;
891 }
892 
894 
897 TVectorD simpleFitZS::getPar() const {
898  return _parameters;
899 }
900 
902 
905 TMatrixDSym simpleFitZS::getCov() const {
906  return _covariance;
907 }
908 
909 } // close namespace brackets
void calcLocal()
Calculate local parameters.
int fit(double &, int &)
Perform fit.
double _sxx
weighted sum(x*x)
double _sx
weighted sum(x)
double _sy
weighted sum(z)
TMatrixD localHelixAnalyticalJacobian(double ds, double qbyp, Vector3D &t1, Vector3D &t2, Vector3D &bc)
Get analytical helix propagator (in constant magnetic field)
gear::Vector3D _bFieldc
B-field.
double _srr
weighted sum(r*r*r*r)
simpleHelix getSimpleHelix() const
Get simple helix.
const double _z0
Z position at distance of closest approach.
simpleHelix(const double, const double, const double, const double, const double, const double *, const double)
Constructor.
TMatrixD analyticalHelixJacobian(const double, const double) const
Get analytical helix propagator (in constant solenoidal magnetic field)
TMatrixD propagateTo(const double *, const double)
Propagate stepwise (close) to point.
void moveTo(const double, const double, const double, double *)
Change reference point.
const double _eps
cut off for straight line approximation (|relevent scale / R| < _eps)
void dump() const
Dump helix.
TMatrixD _rotation
rotation to local system
double _localRef[3]
local reference point
TMatrixD _rotInv
rotation from local system
double _syy
weighted sum(z*z)
double _syr
weighted sum(y*r*r)
TMatrixD perigeeToLCIOJacobian() const
Get transformation from helix to LCIO track parameters (at reference point)
double _localPar[5]
local helix parameter
void dump() const
Dump helix.
gear::Vector3D _trackDir
(global) track direction
double _sy
weighted sum(y)
TMatrixDSym getCov() const
Get covariance matrix.
int _numPoints
number of points (hits) used
void getPosAtArcLength(const double, double *) const
Get position (on helix) at arc length.
const double _phi0
flight direction at point of closest approach (in XY)
const double _yRef
Y of reference point.
const double _yref
Y of reference point.
double _qbyp
Q/P = const !
bool getExpectedPlanePos(const double *, const double, double &, double &, double &, double &, double &) const
Get expected position (and direction) in plane.
void calcGlobal()
Calculate global parameters.
double _sxy
weighted sum(s*z)
void addPoint(double, double, double)
Add point.
const double _xref
X of reference point.
simpleFitZS()
Constructor for simple fit in ZS.
TVectorD _parameters
parameter vector
double _syy
weighted sum(y*y)
const double _yRelCenter
XY circle parameter: Y position of center / R.
void getStateAt(const double, const double, const double, TMatrixDSym &, TVectorD &, TMatrixDSym &)
Get state (parameters, covariance matrix) at point.
TMatrixD simplifiedHelixJacobian(const double, const double) const
Get simplified helix propagator (in constant solenoidal magnetic field)
gear::Vector3D getBFieldc(const double *) const
Get magnetic field (*c).
void getZSDirection(double *) const
Get ZS direction (cosLambda, sinLambda).
double _cosLambda
(local) cos(lambda)
int fit(double &, int &)
Perform fit.
double _sr
weighted sum(r*r)
double _sx
weighted sum(s)
const double _dca
distance of closest approach in (XY)
const double _xRelCenter
XY circle parameter: X position of center / R.
double _sxx
weighted sum(s*s)
TMatrixD curvilinearToPerigeeJacobian() const
Get transformation from curivilinear to perigee track parameters (at reference point) ...
TVectorD _parameters
parameter vector
void addTrack(EVENT::Track const *)
add a complete Track.
localHelix(const double *, const double *, const double)
Constructor.
const bool _curved
flag for curved (circle) track
TMatrixDSym _covariance
covariance matrix
const int _npar
number of track parameters (3: circle, 2: line)
TMatrixD perigeeToILDJacobian() const
Get transformation from perigee to L3/ILD track parameters (at reference point)
const double _xRef
X of reference point.
TVectorD getPar() const
Get parameters vector.
void addPoint(double, double, double)
Add point.
double _sw
sum of weights
double _sxr
weighted sum(x*r*r)
const double _bzc
Z component of magnetic field (*c)
double _bfac
c * scaling factor (0/1) for magnetic field
TMatrixDSym getCov() const
Get covariance matrix.
const int _npar
number of track parameters (2)
TVectorD _offset
offset of local system
double getArcLengthXY(const double *) const
Get (2D) arc length for given point.
TMatrixDSym _covariance
covariance matrix
TMatrixD helixToLCIOJacobian() const
Get transformation from helix to LCIO track parameters (at reference point)
TVectorD getPar() const
Get parameters vector.
int _numPoints
number of points (hits) used
simpleFitXY(bool, double, double)
Constructor for simple fit in XY.
double _sxy
weighted sum(x*y)
const double _zref
Z of reference point.
double _sw
sum of weights