Belle II Software development
Helix.cc
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#include <tracking/trackingUtilities/geometry/Helix.h>
9
10#include <tracking/trackingUtilities/geometry/HelixParameters.h>
11#include <tracking/trackingUtilities/geometry/PerigeeCircle.h>
12#include <tracking/trackingUtilities/geometry/PerigeeParameters.h>
13#include <tracking/trackingUtilities/geometry/SZLine.h>
14#include <tracking/trackingUtilities/geometry/SZParameters.h>
15
16#include <tracking/trackingUtilities/geometry/VectorUtil.h>
17
18#include <Math/Vector3D.h>
19
20#include <boost/math/tools/minima.hpp>
21
22#include <utility>
23#include <algorithm>
24#include <limits>
25#include <ostream>
26#include <cstdint>
27
28using namespace Belle2;
29using namespace TrackingUtilities;
30
31double Helix::arcLength2DToClosest(const ROOT::Math::XYZVector& point, bool firstPeriod) const
32{
33 // The point may happen to lie in the center of the helix.
34 double loc_d0 = circleXY().distance(VectorUtil::getXYVector(point));
35 double denominator = 1 + curvatureXY() * loc_d0;
36 if (denominator == 0) {
37 // When this happens we can optimise the z distance for the closest point
38 double arcLength2D = (point.z() - z0()) / tanLambda();
39 if (not std::isfinite(arcLength2D)) {
40 return 0.0;
41 } else {
42 return arcLength2D;
43 }
44 }
45
46 // First approximation optimising the xy distance.
47 double arcLength2D = circleXY().arcLengthTo(VectorUtil::getXYVector(point));
48 // In case the helix is a flat circle with no extend into z this is the actual solution
49 if (tanLambda() == 0) {
50 return arcLength2D;
51 }
52
53 double deltaZ = point.z() - szLine().map(arcLength2D);
54 if (not firstPeriod) {
55 if (fabs(deltaZ) > zPeriod() / 2) {
56 double newDeltaZ = std::remainder(deltaZ, zPeriod());
57 double nPeriodShift = (deltaZ - newDeltaZ) / zPeriod();
58 arcLength2D += nPeriodShift * perimeterXY();
59 deltaZ = newDeltaZ;
60 }
61 }
62
63 using boost::math::tools::brent_find_minima;
64
65 auto distance3D = [this, &point](const double & s) -> double {
66 ROOT::Math::XYZVector pos = atArcLength2D(s);
67 return VectorUtil::Distance(pos, point);
68 };
69
70 double searchWidth = std::fmin(perimeterXY(), 2 * deltaZ / tanLambda());
71
72 double lowerS = arcLength2D - searchWidth;
73 double upperS = arcLength2D + searchWidth;
74
75 int bits = std::numeric_limits<double>::digits;
76 size_t nMaxIter = 100;
77
78 std::pair<double, double> sBounds = brent_find_minima(distance3D, lowerS, upperS, bits, nMaxIter);
79
80 // Stopped before iterations were exhausted?
81 // bool converged = nMaxIter > 0;
82
83 double firstDistance = distance3D(sBounds.first);
84 double secondDistance = distance3D(sBounds.second);
85 if (firstDistance < secondDistance) {
86 return sBounds.first;
87 } else {
88 return sBounds.second;
89 }
90}
91
92HelixJacobian Helix::passiveMoveByJacobian(const ROOT::Math::XYZVector& by) const
93{
94 // Fills the upper left 3x3 corner.
95 PerigeeJacobian perigeeJacobian = circleXY().passiveMoveByJacobian(VectorUtil::getXYVector(by));
96 SZJacobian szJacobian = SZUtil::identity();
97 HelixJacobian jacobian = HelixUtil::stackBlocks(perigeeJacobian, szJacobian);
98
99 double curv = curvatureXY();
100 double tanL = tanLambda();
101 double sArc = circleXY().arcLengthTo(VectorUtil::getXYVector(by));
102
103 using namespace NHelixParameterIndices;
104 jacobian(c_Z0, c_Curv) = tanL * (jacobian(c_Phi0, c_Curv) - sArc) / curv;
105 jacobian(c_Z0, c_Phi0) = tanL * (jacobian(c_Phi0, c_Phi0) - 1.) / curv;
106 jacobian(c_Z0, c_I) = tanL * jacobian(c_Phi0, c_I) / curv;
107 jacobian(c_Z0, c_TanL) = sArc;
108
109 return jacobian;
110}
111
112std::ostream& TrackingUtilities::operator<<(std::ostream& output, const Helix& helix)
113{
114 return output << "Helix("
115 << "curv=" << helix.curvatureXY() << ","
116 << "phi0=" << helix.phi0() << ","
117 << "impact=" << helix.impactXY() << ","
118 << "tanL=" << helix.tanLambda() << ","
119 << "z0=" << helix.z0() << ")";
120}
double curv(void) const
Return curvature of helix.
Definition Helix.h:420
Extension of the generalized circle also caching the perigee coordinates.
Definition Helix.h:30
double z0() const
Getter for z coordinate at the perigee point of the helix.
Definition Helix.h:257
double phi0() const
Getter for the azimuth angle of the direction of flight at the perigee.
Definition Helix.h:307
double perimeterXY() const
Getter for the perimeter of the circle in the xy projection.
Definition Helix.h:276
double impactXY() const
Getter for the signed distance to the z axes at the perigee point.
Definition Helix.h:214
double tanLambda() const
Getter for the proportinality factor from arc length in xy space to z.
Definition Helix.h:245
double curvatureXY() const
Getter for the signed curvature in the xy projection.
Definition Helix.h:208
double zPeriod() const
Getter for the distance in z at which the two points on the helix coincide in the xy projection.
Definition Helix.h:264
HelixJacobian passiveMoveByJacobian(const ROOT::Math::XYZVector &by) const
Computes the Jacobi matrix for a move of the coordinate system by the given vector.
Definition Helix.cc:92
double arcLength2DToClosest(const ROOT::Math::XYZVector &point, bool firstPeriod=true) const
Calculates the perpendicular travel distance at which the helix has the closest approach to the given...
Definition Helix.cc:31
const PerigeeCircle & circleXY() const
Getter for the projection into xy space.
Definition Helix.h:326
ROOT::Math::XYZVector atArcLength2D(double s) const
Calculates the point, which lies at the give perpendicular travel distance (counted from the perigee)
Definition Helix.h:176
const SZLine & szLine() const
Getter for the projection into xy space.
Definition Helix.h:332
Namespace to hide the contained enum constants.
Abstract base class for different kinds of events.
static HelixUtil::CovarianceMatrix stackBlocks(const PerigeeUtil::CovarianceMatrix &perigeeCov, const SZUtil::CovarianceMatrix &szCov)
Combine covariance matrices from the xy space and the sz space in their respective blocks.