8#include <framework/dataobjects/Helix.h> 
   10#include <framework/gearbox/Const.h> 
   12#include <boost/math/special_functions/sign.hpp> 
   13#include <boost/math/special_functions/sinc.hpp> 
   14#include <boost/math/tools/precision.hpp> 
   16#include <Math/VectorUtil.h> 
   22using namespace HelixParameterIndex;
 
   34             const ROOT::Math::XYZVector& momentum,
 
   35             const short int charge,
 
 
   45             const double& tanLambda)
 
 
  116  return boost::math::sign(
getOmega());
 
 
  135  const double dr = 
getD0();
 
  136  const double deltaCylindricalR = cylindricalR;
 
  138  return absArcLength2D;
 
 
  144  double arcLength2D = 0;
 
 
  150                                          const double& nX, 
const double& nY)
 const 
  153  const double tX = nY;
 
  154  const double tY = -nX;
 
  160  const double d0 = 
getD0();
 
  164  const double deltaParallel = byX * cosPhi0 + byY * sinPhi0;
 
  165  const double deltaOrthogonal = byY * cosPhi0 - byX * sinPhi0 + d0;
 
  166  const double deltaCylindricalR = hypot(deltaOrthogonal, deltaParallel);
 
  167  const double deltaCylindricalRSquared = deltaCylindricalR * deltaCylindricalR;
 
  169  const double UOrthogonal = 1 + omega * deltaOrthogonal; 
 
  170  const double UParallel = omega * deltaParallel;
 
  173  const double A = 2 * deltaOrthogonal + omega * deltaCylindricalRSquared;
 
  175  const double tParallel = tX * cosPhi0 + tY * sinPhi0;
 
  176  const double tOrthogonal = tY * cosPhi0 - tX * sinPhi0;
 
  177  const double tCylindricalR = (tX * tX + tY * tY);
 
  179  const double c = A / 2;
 
  180  const double b = UParallel * tParallel + UOrthogonal * tOrthogonal;
 
  181  const double a = omega / 2 * tCylindricalR;
 
  183  const double discriminant = ((double)b) * b - 4 * a * c;
 
  184  const double root = sqrt(discriminant);
 
  185  const double bigSum = (b > 0) ? -b - root : -b + root;
 
  187  const double bigOffset = bigSum / 2 / a;
 
  188  const double smallOffset = 2 * c / bigSum;
 
  190  const double distance1 = hypot(byX + bigOffset   * tX, byY + bigOffset   * tY);
 
  191  const double distance2 = hypot(byX + smallOffset * tX, byY + smallOffset * tY);
 
  193  if (distance1 < distance2) {
 
 
  225  const double chi = -arcLength2D * 
getOmega();
 
  226  const double chiHalf = chi / 2.0;
 
  228  using boost::math::sinc_pi;
 
  230  const double x = arcLength2D * sinc_pi(chi);
 
  231  const double y = arcLength2D * sinc_pi(chiHalf) * sin(chiHalf) - 
getD0();
 
  237  ROOT::Math::XYZVector position(x, y, z);
 
  240  position = ROOT::Math::VectorUtil::RotateZ(position, 
getPhi0());
 
 
  251  const double chi = - omega * arcLength2D;
 
  253  const double tx = cos(chi + phi0);
 
  254  const double ty = sin(chi + phi0);
 
  255  const double tz = tanLambda;
 
  257  ROOT::Math::XYZVector tangential(tx, ty, tz);
 
 
  265  const double invNorm = 1 / norm;
 
  266  unitTangential *= invNorm;
 
  267  return unitTangential;
 
 
  285  double arcLength2D = 0;
 
  289  double chi = -arcLength2D * 
getOmega();
 
  290  double new_phi0 = 
m_phi0 + chi;
 
 
  303  TMatrixD jacobian(5, 5);
 
 
  312                                      const double expandBelowChi)
 const 
  316  jacobian.UnitMatrix();
 
  317  assert(jacobian.GetNrows() == jacobian.GetNcols());
 
  318  assert(jacobian.GetNrows() == 5 or jacobian.GetNrows() == 6);
 
  324  const double d0 = 
getD0();
 
  329  const double deltaParallel = byX * cosPhi0 + byY * sinPhi0;
 
  330  const double deltaOrthogonal = byY * cosPhi0 - byX * sinPhi0 + d0;
 
  331  const double deltaCylindricalR = hypot(deltaOrthogonal, deltaParallel);
 
  332  const double deltaCylindricalRSquared = deltaCylindricalR * deltaCylindricalR;
 
  335  const double A = 2 * deltaOrthogonal + omega * deltaCylindricalRSquared;
 
  336  const double USquared = 1 + omega * A;
 
  337  const double U = sqrt(USquared);
 
  338  const double UOrthogonal = 1 + omega * deltaOrthogonal; 
 
  339  const double UParallel = omega * deltaParallel;
 
  341  const double u = 1 + omega * d0; 
 
  352  const double new_d0 = A / (1 + U);
 
  354  jacobian(iD0, iOmega) = (deltaCylindricalR + new_d0) * (deltaCylindricalR - new_d0) / 2 / U;
 
  355  jacobian(iD0, iPhi0) = - u * deltaParallel / U;
 
  356  jacobian(iD0, iD0) =  UOrthogonal / U;
 
  361  const double dArcLength2D_dD0 = - UParallel / USquared;
 
  362  const double dArcLength2D_dPhi0 = (omega * deltaCylindricalRSquared + deltaOrthogonal - d0 * UOrthogonal) / USquared;
 
  364  jacobian(iPhi0, iD0) = - dArcLength2D_dD0 * omega;
 
  365  jacobian(iPhi0, iPhi0) = u * UOrthogonal / USquared;
 
  366  jacobian(iPhi0, iOmega) =  -deltaParallel / USquared;
 
  375  const double chi = -atan2(UParallel, UOrthogonal);
 
  376  double arcLength2D = 0;
 
  377  double dArcLength2D_dOmega = 0;
 
  379  if (fabs(chi) < std::min(expandBelowChi, M_PI / 2.0)) {
 
  382    double principleArcLength2D = deltaParallel / UOrthogonal;
 
  383    const double dPrincipleArcLength2D_dOmega = - principleArcLength2D * deltaOrthogonal / UOrthogonal;
 
  385    const double x = principleArcLength2D * omega;
 
  389    arcLength2D = principleArcLength2D * f;
 
  390    dArcLength2D_dOmega = (f + x * df_dx) * dPrincipleArcLength2D_dOmega + principleArcLength2D * df_dx * principleArcLength2D;
 
  396    arcLength2D = - chi / omega;
 
  397    dArcLength2D_dOmega = (-arcLength2D - jacobian(iPhi0, iOmega)) / omega;
 
  404  jacobian(iZ0, iD0) = tanLambda * dArcLength2D_dD0;
 
  405  jacobian(iZ0, iPhi0) = tanLambda * dArcLength2D_dPhi0;
 
  406  jacobian(iZ0, iOmega) = tanLambda * dArcLength2D_dOmega;
 
  407  jacobian(iZ0, iZ0) = 1.0; 
 
  408  jacobian(iZ0, iTanLambda) = arcLength2D;
 
  410  if (jacobian.GetNrows() == 6) {
 
  412    jacobian(iArcLength2D, iD0) = dArcLength2D_dD0;
 
  413    jacobian(iArcLength2D, iPhi0) = dArcLength2D_dPhi0;
 
  414    jacobian(iArcLength2D, iOmega) = dArcLength2D_dOmega;
 
  415    jacobian(iArcLength2D, iZ0) = 0.0;
 
  416    jacobian(iArcLength2D, iTanLambda) = 0;
 
  417    jacobian(iArcLength2D, iArcLength2D) = 1.0;
 
 
  423  return std::remainder(phi + M_PI, 2 * M_PI);
 
 
  434  double x = secantLength * 
getOmega() / 2.0;
 
 
  443  BOOST_MATH_STD_USING;
 
  445  auto const taylor_n_bound = boost::math::tools::forth_root_epsilon<double>();
 
  447  if (abs(x) >= taylor_n_bound) {
 
  460    auto const taylor_0_bound = boost::math::tools::epsilon<double>();
 
  461    if (abs(x) >= taylor_0_bound) {
 
  466      auto const taylor_2_bound = boost::math::tools::root_epsilon<double>();
 
  467      if (abs(x) >= taylor_2_bound) {
 
  469        result += x2 * x2 * (3.0 / 40.0);
 
 
  482  BOOST_MATH_STD_USING;
 
  484  auto const taylor_n_bound = boost::math::tools::forth_root_epsilon<double>();
 
  486  if (abs(x) >= taylor_n_bound) {
 
  493    auto const taylor_0_bound = boost::math::tools::epsilon<double>();
 
  494    if (abs(x) >= taylor_0_bound) {
 
  499      auto const taylor_2_bound = boost::math::tools::root_epsilon<double>();
 
  500      if (abs(x) >= taylor_2_bound) {
 
  502        result += x2 * x2 * (1.0 / 5.0);
 
 
  514  BOOST_MATH_STD_USING;
 
  516  auto const taylor_n_bound = boost::math::tools::forth_root_epsilon<double>();
 
  518  const double x2 = x * x;
 
  519  if (abs(x) >= taylor_n_bound) {
 
  520    const double chi = atan(x);
 
  521    return ((1 - chi / x) / x - chi) / (1 + x2);
 
  527    auto const taylor_0_bound = boost::math::tools::epsilon<double>();
 
  528    if (abs(x) >= taylor_0_bound) {
 
  530      result -= 2.0 * x / 3.0;
 
  532      auto const taylor_2_bound = boost::math::tools::root_epsilon<double>();
 
  533      if (abs(x) >= taylor_2_bound) {
 
  535        result += x2 * x * (4.0 / 5.0);
 
 
  551  const double d0 = 
getD0();
 
  553  const double deltaParallel = x * cosPhi0 + y * sinPhi0;
 
  554  const double deltaOrthogonal = y * cosPhi0 - x * sinPhi0 + d0;
 
  555  const double deltaCylindricalR = hypot(deltaOrthogonal, deltaParallel);
 
  556  const double deltaCylindricalRSquared = deltaCylindricalR * deltaCylindricalR;
 
  558  const double A = 2 * deltaOrthogonal + omega * deltaCylindricalRSquared;
 
  559  const double U = sqrt(1 + omega * A);
 
  560  const double UOrthogonal = 1 + omega * deltaOrthogonal; 
 
  561  const double UParallel = omega * deltaParallel;
 
  568  const double chi = -atan2(UParallel, UOrthogonal);
 
  570  if (fabs(chi) < M_PI / 8) { 
 
  572    double principleArcLength2D = deltaParallel / UOrthogonal;
 
  577    arcLength2D = -chi / omega;
 
 
  584  double secantLength = sqrt((deltaCylindricalR + dr) * (deltaCylindricalR - dr) / (1 + dr * omega));
 
 
  589                         const ROOT::Math::XYZVector& momentum,
 
  590                         const short int charge,
 
  593  assert(abs(charge) <= 1);  
 
  601  const double x = position.X();
 
  602  const double y = position.Y();
 
  603  const double z = position.Z();
 
  605  const double px = momentum.X();
 
  606  const double py = momentum.Y();
 
  607  const double pz = momentum.Z();
 
  609  const double ptinv = 1 / hypot(px, py);
 
  610  const double omega = charge * ptinv / alpha;
 
  611  const double tanLambda = ptinv * pz;
 
  612  const double phi0 = atan2(py, px);
 
 
  635           << 
"d0=" << helix.
getD0() << 
", " 
  636           << 
"phi0=" << helix.
getPhi0() << 
", " 
  637           << 
"omega=" << helix.
getOmega() << 
", " 
  638           << 
"z0=" << helix.
getZ0() << 
", " 
 
static const double speedOfLight
[cm/ns]
Double32_t m_tanLambda
Memory for the slope of the track in the z coordinate over the two dimensional arc length (dz/ds)
double getPerigeeX() const
Calculates the x coordinate of the perigee point.
double getSinPhi0() const
Getter for the cosine of the azimuth angle of travel direction at the perigee.
double getMomentumZ(const double bZ) const
Calculates the z momentum of the particle at the perigee point.
Double32_t m_omega
Memory for the curvature of the signed curvature.
double getMomentumY(const double bZ) const
Calculates the y momentum of the particle at the perigee point.
void reverse()
Reverses the direction of travel of the helix in place.
double getCosPhi0() const
Getter for the cosine of the azimuth angle of travel direction at the perigee.
double getArcLength2DAtCylindricalR(const double &cylindricalR) const
Calculates the transverse travel distance at the point the helix first reaches the given cylindrical ...
static double calcASinXDividedByX(const double &x)
Implementation of the function asin(x) / x which handles small x values smoothly.
static double reversePhi(const double &phi)
Reverses an azimuthal angle to the opposite direction.
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 ...
Double32_t m_z0
Memory for the z coordinate of the perigee.
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 getDirection() const
Getter for unit vector of momentum at the perigee position.
ROOT::Math::XYZVector getTangentialAtArcLength2D(const double &arcLength2D) const
Calculates the tangential vector to the helix curve at the given two dimensional arc length.
ROOT::Math::XYZVector getPositionAtArcLength2D(const double &arcLength2D) const
Calculates the position on the helix at the given two dimensional arc length.
Double32_t m_d0
Memory for the signed distance to the perigee.
ROOT::Math::XYZVector getUnitTangentialAtArcLength2D(const double &arcLength2D) const
Calculates the unit tangential vector to the helix curve at the given two dimensional arc length.
double getPerigeeZ() const
Calculates the z coordinate of the perigee point.
void setCartesian(const ROOT::Math::XYZVector &position, const ROOT::Math::XYZVector &momentum, const short int charge, const double bZ)
Cartesian to Perigee conversion.
double getD0() const
Getter for d0, which is the signed distance to the perigee in the r-phi plane.
ROOT::Math::XYZVector getMomentum(const double bZ) const
Getter for vector of momentum at the perigee position.
void calcArcLength2DAndDrAtXY(const double &x, const double &y, double &arcLength2D, double &dr) const
Helper method to calculate the signed two dimensional arc length and the signed distance to the circl...
double passiveMoveBy(const ROOT::Math::XYZVector &by)
Moves origin of the coordinate system (passive transformation) by the given vector.
double getArcLength2DAtNormalPlane(const double &x, const double &y, const double &nX, const double &nY) const
Calculates the arc length to reach a plane parallel to the z axes.
double getMomentumX(const double bZ) const
Calculates the x momentum of the particle at the perigee point.
double getTanLambda() const
Getter for tan lambda, which is the z over two dimensional arc length slope of the track.
TMatrixD calcPassiveMoveByJacobian(const ROOT::Math::XYZVector &by, const double expandBelowChi=M_PI/8) const
Calculate the 5x5 jacobian matrix for the transport of the helix parameters, when moving the origin o...
double getPerigeeY() const
Calculates the y coordinate of the perigee point.
double calcSecantLengthToArcLength2DFactor(const double &secantLength2D) const
Helper function to calculate the factor between the dimensional secant length and the two dimensional...
Double32_t m_phi0
Memory for the azimuth angle between the transverse momentum and the x axis, which is in [-pi,...
double calcArcLength2DAtDeltaCylindricalRAndDr(const double &deltaCylindricalR, const double &dr) const
Helper method to calculate the two dimensional arc length from the perigee to a point at cylindrical ...
double calcArcLength2DFromSecantLength(const double &secantLength2D) const
Helper function to calculate the two dimensional arc length from the length of a secant.
double getZ0() const
Getter for z0, which is the z coordinate of the perigee.
double getKappa(const double bZ) const
Getter for kappa, which is charge / transverse momentum or equivalently omega * alpha.
static double calcDerivativeOfATanXDividedByX(const double &x)
Implementation of the function d / dx (atan(x) / x) which handles small x values smoothly.
Helix()
Constructor initializing all perigee parameters to zero.
ROOT::Math::XYZVector getMomentumAtArcLength2D(const double &arcLength2D, const double &bz) const
Calculates the momentum vector at the given two dimensional arc length.
ROOT::Math::XYZVector getPerigee() const
Getter for the perigee position.
double getTransverseMomentum(const double bZ) const
Getter for the absolute value of the transverse momentum at the perigee.
double getPhi0() const
Getter for phi0, which is the azimuth angle of the transverse momentum at the perigee.
static double calcATanXDividedByX(const double &x)
Implementation of the function atan(x) / x which handles small x values smoothly.
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
Abstract base class for different kinds of events.