12#include <framework/gearbox/Const.h> 
   13#include <framework/logging/Logger.h> 
   15#include <analysis/VertexFitting/TreeFitter/HelixUtils.h> 
   18#include <initializer_list> 
   25                                   ROOT::Math::XYZVector& position,
 
   26                                   ROOT::Math::XYZVector& momentum, 
int& charge)
 
 
   34                                   int charge, 
double Bz,
 
   37                                   Eigen::Matrix<double, 5, 6>& jacobian)
 
   40    helix = 
Belle2::Helix(ROOT::Math::XYZVector(positionAndMomentum(0), positionAndMomentum(1), positionAndMomentum(2)),
 
   41                          ROOT::Math::XYZVector(positionAndMomentum(3), positionAndMomentum(4), positionAndMomentum(5)),
 
   45                                 positionAndMomentum(1));
 
   47    const double alpha =  helix.
getAlpha(Bz);
 
   53    Eigen::Matrix<double, 6, 6> jacobianRot = Eigen::Matrix<double, 6, 6>::Zero(6, 6);
 
   55    const double px = positionAndMomentum(3);
 
   56    const double py = positionAndMomentum(4);
 
   57    const double pt = hypot(px, py);
 
   58    const double cosPhi0 = px / pt;
 
   59    const double sinPhi0 = py / pt;
 
   62    jacobianRot(iX, iX) = cosPhi0;
 
   63    jacobianRot(iX, iY) = sinPhi0;
 
   64    jacobianRot(iY, iX) = -sinPhi0;
 
   65    jacobianRot(iY, iY) = cosPhi0;
 
   66    jacobianRot(iZ, iZ) = 1.0;
 
   68    jacobianRot(iPx, iPx) = cosPhi0;
 
   69    jacobianRot(iPx, iPy) = sinPhi0;
 
   70    jacobianRot(iPy, iPx) = -sinPhi0;
 
   71    jacobianRot(iPy, iPy) = cosPhi0;
 
   72    jacobianRot(iPz, iPz) = 1.0;
 
   75    const double pz = positionAndMomentum(5);
 
   76    const double invPt = 1 / pt;
 
   77    const double invPtSquared = invPt * invPt;
 
   78    Eigen::Matrix<double, 5, 6> jacobianToHelixParameters = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
 
   79    jacobianToHelixParameters(iD0, iY) = -1;
 
   80    jacobianToHelixParameters(iPhi0, iX) = charge * invPt / alpha;
 
   81    jacobianToHelixParameters(iPhi0, iPy) = invPt;
 
   82    jacobianToHelixParameters(iOmega, iPx) = -charge * invPtSquared / alpha;
 
   83    jacobianToHelixParameters(iTanLambda, iPx) = - pz * invPtSquared;
 
   84    jacobianToHelixParameters(iTanLambda, iPz) = invPt;
 
   85    jacobianToHelixParameters(iZ0, iX) = - pz * invPt;
 
   86    jacobianToHelixParameters(iZ0, iZ) = 1;
 
   88    jacobian = jacobianToHelixParameters * jacobianRot;
 
 
   96      case 1     : rc = 
"d0    : " ; break ;
 
   97      case 2     : rc = 
"phi0  : " ; break ;
 
   98      case 3     : rc = 
"omega : " ; break ;
 
   99      case 4     : rc = 
"z0    : " ; break ;
 
  100      case 5     : rc = 
"tandip: " ; break ;
 
  101      case 6     : rc = 
"L     : " ; break ;
 
 
  110      case 1  : rc = 
"x    : " ; break ;
 
  111      case 2  : rc = 
"y    : " ; break ;
 
  112      case 3  : rc = 
"z    : " ; break ;
 
  113      case 4  : rc = 
"px   : " ; break ;
 
  114      case 5  : rc = 
"py   : " ; break ;
 
  115      case 6  : rc = 
"pz   : " ; break ;
 
 
  128    B2INFO(
"charge:    " << charge);
 
 
  133                                                          int charge, 
double Bz,
 
  135                                                          Eigen::Matrix<double, 5, 6>& jacobian)
 
  138    helix = 
Belle2::Helix(ROOT::Math::XYZVector(positionAndMom(0), positionAndMom(1), positionAndMom(2)),
 
  139                          ROOT::Math::XYZVector(positionAndMom(3), positionAndMom(4), positionAndMom(5)),
 
  147    ROOT::Math::XYZVector postmp;
 
  148    ROOT::Math::XYZVector momtmp;
 
  150    for (
int jin = 0; jin < 6; ++jin) {
 
  151      postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
 
  152      momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
 
  153      if (jin == 0) postmp.SetX(postmp.X() + delta);
 
  154      if (jin == 1) postmp.SetY(postmp.Y() + delta);
 
  155      if (jin == 2) postmp.SetZ(postmp.Z() + delta);
 
  156      if (jin == 3) momtmp.SetX(momtmp.X() + delta);
 
  157      if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
 
  158      if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
 
  161      jacobian(iD0, jin)        = (helixPlusDelta.
getD0()        - helix.
getD0())        / delta ;
 
  162      jacobian(iPhi0, jin)      = (helixPlusDelta.
getPhi0()      - helix.
getPhi0())      / delta ;
 
  163      jacobian(iOmega, jin)     = (helixPlusDelta.
getOmega()     - helix.
getOmega())     / delta ;
 
  164      jacobian(iZ0, jin)        = (helixPlusDelta.
getZ0()        - helix.
getZ0())        / delta ;
 
 
  172    const Eigen::Matrix<double, 1, 6>& positionAndMom,
 
  173    int charge, 
double Bz,
 
  175    Eigen::Matrix<double, 5, 6>& jacobian,
 
  182    ROOT::Math::XYZVector postmp;
 
  183    ROOT::Math::XYZVector momtmp;
 
  185    for (
int jin = 0; jin < 6; ++jin) {
 
  186      postmp.SetCoordinates(positionAndMom(0), positionAndMom(1), positionAndMom(2));
 
  187      momtmp.SetCoordinates(positionAndMom(3), positionAndMom(4), positionAndMom(5));
 
  188      if (jin == 0) postmp.SetX(postmp.X() + delta);
 
  189      if (jin == 1) postmp.SetY(postmp.Y() + delta);
 
  190      if (jin == 2) postmp.SetZ(postmp.Z() + delta);
 
  191      if (jin == 3) momtmp.SetX(momtmp.X() + delta);
 
  192      if (jin == 4) momtmp.SetY(momtmp.Y() + delta);
 
  193      if (jin == 5) momtmp.SetZ(momtmp.Z() + delta);
 
  196      jacobian(iD0, jin)        = (helixPlusDelta.
getD0()        - helix.
getD0())        / delta ;
 
  197      jacobian(iPhi0, jin)      = (helixPlusDelta.
getPhi0()      - helix.
getPhi0())      / delta ;
 
  198      jacobian(iOmega, jin)     = (helixPlusDelta.
getOmega()     - helix.
getOmega())     / delta ;
 
  199      jacobian(iZ0, jin)        = (helixPlusDelta.
getZ0()        - helix.
getZ0())        / delta ;
 
 
  205  inline double sqr(
double x) { 
return x * x ; }
 
  210    if (phi < -TMath::Pi())  rc += TMath::TwoPi();
 
  211    else if (phi >  TMath::Pi())  rc -= TMath::TwoPi();
 
 
  218                               double& flt1, 
double& flt2,
 
  219                               ROOT::Math::XYZVector& vertex, 
bool parallel)
 
  222    const double d0_1     = helix1.
getD0();
 
  223    const double phi0_1   = helix1.
getPhi0();
 
  224    const double omega_1  = helix1.
getOmega();
 
  226    const double d0_2     = helix2.
getD0();
 
  227    const double phi0_2   = helix2.
getPhi0();
 
  228    const double omega_2  = helix2.
getOmega();
 
  231    const double r_1 = 1 / omega_1 ;
 
  232    const double r_2 = 1 / omega_2 ;
 
  236    const double x0_1 = (r_1 + d0_1) * sin(phi0_1) ;
 
  237    const double y0_1 = -(r_1 + d0_1) * cos(phi0_1) ;
 
  239    const double x0_2 = (r_2 + d0_2) * sin(phi0_2) ;
 
  240    const double y0_2 = -(r_2 + d0_2) * cos(phi0_2) ;
 
  243    const double deltax = x0_2 - x0_1 ;
 
  244    const double deltay = y0_2 - y0_1 ;
 
  252    const double phi    = - atan2(deltax, deltay) ;
 
  253    const double phinot = phi > 0 ?  phi - TMath::Pi() : phi + TMath::Pi() ;
 
  254    phi1[0] = r_1 < 0 ? phi : phinot ;
 
  255    phi2[0] = r_2 > 0 ? phi : phinot ;
 
  258    const double R1 = fabs(r_1) ;
 
  259    const double R2 = fabs(r_2) ;
 
  260    const double Rmin = R1 < R2 ? R1 : R2 ;
 
  261    const double Rmax = R1 > R2 ? R1 : R2 ;
 
  262    const double dX = hypot(deltax, deltay) ;
 
  264    if (!parallel && dX + Rmin > Rmax && dX < R1 + R2) {
 
  269      const double ddphi1 = acos((dX * dX - R2 * R2 + R1 * R1) / (2.*dX * R1)) ;
 
  273      const double ddphi2 = acos((dX * dX - R1 * R1 + R2 * R2) / (2.*dX * R2)) ;
 
  277    } 
else if (dX < Rmax) {
 
  279      if (R1 > R2) phi2[0] = r_2 < 0 ? phi : phinot ;
 
  280      else         phi1[0] = r_1 < 0 ? phi : phinot ;
 
  286    double x1[2], y1[2], x2[2], y2[2];
 
  287    for (
int i = 0; i < nsolutions; i++) {
 
  288      x1[i] =  r_1 * sin(phi1[i]) + x0_1 ;
 
  289      y1[i] = -r_1 * cos(phi1[i]) + y0_1 ;
 
  290      x2[i] =  r_2 * sin(phi2[i]) + x0_2 ;
 
  291      y2[i] = -r_2 * cos(phi2[i]) + y0_2 ;
 
  298    const int nturnsmax = 10; 
 
  301    for (
int i = 0; i < nsolutions; ++i) {
 
  306      std::vector<double> z1s;
 
  307      for (
int n1 = 0; n1 <= nturnsmax; ++n1) {
 
  310        for (
int sn1 : {n1, -n1}) {
 
  312          if (sn1 == 0 || (-82 <= tmpz1 && tmpz1 <= 158)) {
 
  314            z1s.push_back(tmpz1);
 
  326      for (
int n2 = 0; n2 <= nturnsmax; ++n2) {
 
  329        for (
int sn2 : {n2, -n2}) {
 
  331          if (sn2 == 0 || (-82 <= tmpz2 && tmpz2 <= 158)) {
 
  335            const auto i1best = std::min_element(
 
  336            z1s.cbegin(), z1s.cend(), [&tmpz2](
const double & z1a, 
const double & z1b) {
 
  337              return fabs(z1a - tmpz2) < fabs(z1b - tmpz2);
 
  339            const double tmpz1 = *i1best;
 
  341            if (first || fabs(tmpz1 - tmpz2) < fabs(z1 - z2)) {
 
  359    vertex.SetX(0.5 * (x1[ibest] + x2[ibest]));
 
  360    vertex.SetY(0.5 * (y1[ibest] + y2[ibest]));
 
  361    vertex.SetZ(0.5 * (z1 + z2));
 
  363    return std::hypot(x2[ibest] - x1[ibest], y2[ibest] - y1[ibest], z2 - z1);
 
 
  368                               const ROOT::Math::XYZVector& point,
 
  371    const double d0     = helix.
getD0();
 
  372    const double phi0   = helix.
getPhi0();
 
  373    const double omega  = helix.
getOmega();
 
  374    const double z0     = helix.
getZ0();
 
  376    const double cosdip = cos(atan(tandip))  ; 
 
  378    const double r = 1 / omega ;
 
  380    const double x0 = - (r + d0) * sin(phi0) ;
 
  381    const double y0 = (r + d0) * cos(phi0) ;
 
  383    const double deltax = x0 - point.X() ;
 
  384    const double deltay = y0 - point.Y() ;
 
  386    const double pi = TMath::Pi();
 
  387    double phi = - atan2(deltax, deltay) ;
 
  388    if (r < 0) phi = phi > 0 ?  phi - pi : phi + pi ;
 
  391    const double x =  r * sin(phi) + x0 ;
 
  392    const double y = -r * cos(phi) + y0 ;
 
  396    const double dphi = 
phidomain(phi - phi0) ;
 
  397    for (
int n = 1 - ncirc; n <= 1 + ncirc ; ++n) {
 
  398      const double l = (dphi + n * TMath::TwoPi()) / omega ;
 
  399      const double tmpz = (z0 + l * tandip) ;
 
  400      if (first || fabs(tmpz - point.Z()) < fabs(z - point.Z())) {
 
  406    return sqrt(sqr(x - point.X()) + sqr(y - point.Y()) + sqr(z - point.Z())) ;
 
 
  412                                                        const double z __attribute__((unused)),
 
  422    const double aq = charge / alpha;
 
  424    const double pt = std::hypot(px, py);
 
  425    const double pt2 = pt * pt;
 
  426    const double pt3 = pt2 * pt;
 
  427    const double aq2 = aq * aq;
 
  429    const double x2 = x * x;
 
  430    const double y2 = y * y;
 
  431    const double r  = x2 + y2;
 
  433    const double px2 = px * px;
 
  434    const double py2 = py * py;
 
  436    const double px0 = px - aq * y;
 
  437    const double py0 = py + aq * x;
 
  439    const double pt02 = px0 * px0 + py0 * py0;
 
  440    const double pt0 = std::sqrt(pt02);
 
  441    double sqrt13 = pt0 / pt;
 
  444    jacobian(0, 0) = py0 / pt0;
 
  445    jacobian(0, 1) = -px0 / pt0;
 
  447    jacobian(0, 3) = (-(y * (aq2 * r + 2 * aq * py * x + 2 * py2 * (1 + sqrt13))) - px * (2 * py * x * (1 + sqrt13) + aq * (y2 *
 
  448                      (-1 + sqrt13) + x2 * (1 + sqrt13)))) /
 
  449                     (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
 
  451    jacobian(0, 4) = (2 * px2 * x * (1 + sqrt13) + 2 * px * y * (py - aq * x + py * sqrt13) + aq * (aq * r * x - py * (x2 *
 
  452                      (-1 + sqrt13) + y2 * (1 + sqrt13)))) /
 
  453                     (pt2 * pt0 * (1 + sqrt13) * (1 + sqrt13));
 
  457    jacobian(1, 0) = aq * px0 / pt02;
 
  458    jacobian(1, 1) = aq * py0 / pt02;
 
  460    jacobian(1, 3) = -py0 / pt02;
 
  461    jacobian(1, 4) = px0 / pt02;
 
  468    jacobian(2, 3) = - aq * px / pt3;
 
  469    jacobian(2, 4) = - aq * py / pt3;
 
  473    jacobian(3, 0) = -pz * px0 / pt02;
 
  474    jacobian(3, 1) = -pz * py0 / pt02;
 
  476    jacobian(3, 3) = (pz * (px2 * x - py * (aq * r + py * x) + 2 * px * py * y)) / (pt2 * pt02);
 
  477    jacobian(3, 4) = (pz * (px * (aq * r + 2 * py * x) - px2 * y + py2 * y)) / (pt2 * pt02);
 
  478    jacobian(3, 5) = std::atan2(-(aq * (px * x + py * y)), (px2 + py * py0 - aq * px * y)) / aq; 
 
  484    jacobian(4, 3) = -pz * px / pt3;
 
  485    jacobian(4, 4) = -pz * py / pt3;
 
  486    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 double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, ROOT::Math::XYZVector &vertex, bool parallel=false)
POCA between two tracks.
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.