Belle II Software  release-06-02-00
test_HelixJacobian.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 
10 #include <Eigen/Core>
11 #include <gtest/gtest.h>
12 
13 #include <framework/gearbox/Const.h>
14 
15 #include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
16 #include <framework/geometry/BFieldManager.h>
17 #include <framework/gearbox/Unit.h>
18 
19 namespace {
20 
22  class TreeFitterHelixJacobianTest : public ::testing::Test {
23 
24  };
25 
27  TEST_F(TreeFitterHelixJacobianTest, Helix)
28  {
29  const double eps = 1E-6;
30  //random start values to ensure x and p vector are not orthogonal/parallel
31  const double px = 0.123214;
32  const double py = 1.543;
33  const double pz = -2.876;
34  const double x = 3.765346;
35  const double y = -2.56756;
36  const double z = 1.678;
37 
38  const int charge = -1;
39  const double bfield = Belle2::BFieldManager::getField(TVector3(0, 0, 0)).Z() / Belle2::Unit::T;
40  const double alpha = 1.0 / (bfield * Belle2::Const::speedOfLight) * 1E4;
41  const double aq = charge / alpha;
42 
43  Belle2::Helix helix = Belle2::Helix(TVector3(x, y, z), TVector3(px, py, pz), charge, bfield);
44 
45  const double pt = std::sqrt(px * px + py * py);
46  const double omega = aq / pt;
47 
48  const double phi = atan(py / px);
49  const double cosPhi = std::cos(phi);
50  const double sinPhi = std::sin(phi);
51 
52  const double para = -x * cosPhi - y * sinPhi;
53  const double ortho = -y * cosPhi + x * sinPhi;
54  const double R2 = para * para + ortho * ortho;
55  const double A = 2 * ortho + omega * R2;
56  const double U = std::sqrt(1 + omega * A);
57  const double d0 = A / (1 + U);
58  const double l = 1 / omega * atan((omega * para) / (1 + omega * ortho));
59  const double phi0 = phi + atan((omega * para) / (1 + omega * ortho));
60  const double tanLambda = pz / pt;
61  const double z0 = z + tanLambda * l;
62 
63  std::vector<double> h = {d0, phi0, omega, z0, tanLambda};
64  std::vector<double> h_framework = {helix.getD0(), helix.getPhi0(), helix.getOmega(), helix.getZ0(), helix.getTanLambda()};
65  for (int row = 0; row < 5; ++row) {
66  double res = h[row] - h_framework[row];
67  EXPECT_TRUE(res < eps) << "row " << row << " num - ana " << res << " framework " << h_framework[row] << " mine " << h[row];
68  }
69  }
70 
72  TEST_F(TreeFitterHelixJacobianTest, Parameters)
73  {
74  const double delta = 1e-6;
75  const double eps = 1e-5;
76 
77  Eigen::Matrix<double, 5, 6> jacobian_numerical = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
78  Eigen::Matrix<double, 5, 6> jacobian_analytical = Eigen::Matrix<double, 5, 6>::Zero(5, 6);
79 
80  TVector3 postmp;
81  TVector3 momtmp;
82 
83  //random start values to ensure x and p vector are not orthogonal/parallel
84  const double px = 0.523214;
85  const double py = -1.543;
86  const double pz = -2.876;
87  const double x = -3.765346;
88  const double y = -2.56756;
89  const double z = 5.678;
90 
91  const Eigen::Matrix<double, 1, 6> positionAndMom_ = (Eigen::Matrix<double, 1, 6>() << x, y, z, px, py, pz).finished();
92  const int charge = -1;
93  const double bfield = Belle2::BFieldManager::getField(TVector3(0, 0, 0)).Z() / Belle2::Unit::T;
94 
95  Belle2::Helix helix = Belle2::Helix(TVector3(x, y, z), TVector3(px, py, pz), charge, bfield);
96 
97  for (int jin = 0; jin < 6; ++jin) {
98  for (int i = 0; i < 3; ++i) {
99  postmp[i] = positionAndMom_(i);
100  momtmp[i] = positionAndMom_(i + 3);
101  }
102  if (jin < 3) {
103  postmp[jin] += delta;
104  } else {
105  momtmp[jin - 3] += delta;
106  }
107 
108  Belle2::Helix helixPlusDelta(postmp, momtmp, charge, bfield);
109 
110  jacobian_numerical(0, jin) = (helixPlusDelta.getD0() - helix.getD0()) / delta;
111  jacobian_numerical(1, jin) = (helixPlusDelta.getPhi0() - helix.getPhi0()) / delta;
112  jacobian_numerical(2, jin) = (helixPlusDelta.getOmega() - helix.getOmega()) / delta;
113  jacobian_numerical(3, jin) = (helixPlusDelta.getZ0() - helix.getZ0()) / delta;
114  jacobian_numerical(4, jin) = (helixPlusDelta.getTanLambda() - helix.getTanLambda()) / delta;
115  }
116 
117  TreeFitter::HelixUtils::getJacobianToCartesianFrameworkHelix(jacobian_analytical, x, y, z, px, py, pz, bfield, charge);
118 
119  for (int row = 0; row < 5; ++row) {
120  for (int col = 0; col < 6; ++col) {
121  const double num = jacobian_numerical(row, col);
122  const double ana = jacobian_analytical(row, col);
123  const double res = std::abs(num - ana);
124  EXPECT_TRUE(res < eps) << "row " << row << " col " << col << " num - ana " << res << " num " << num << " ana " << ana;
125  }
126  }
127  }
128 
129 }
Helix parameter class.
Definition: Helix.h:48
static const double speedOfLight
[cm/ns]
Definition: Const.h:575
static const double T
[tesla]
Definition: Unit.h:120
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.
Definition: HelixUtils.cc:379
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
Definition: globalLabel.cc:72
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Definition: EvtPDLUtil.cc:44