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