Belle II Software development
QualityEstimatorCircleFit.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
9#include <tracking/trackFindingVXD/trackQualityEstimators/QualityEstimatorCircleFit.h>
10#include <tracking/trackFindingVXD/utilities/CalcCurvatureSignum.h>
11
12#include <framework/logging/Logger.h>
13
14#include <TMath.h>
15#include <cmath>
16
17using namespace Belle2;
18
19double QualityEstimatorCircleFit::estimateQuality(std::vector<SpacePoint const*> const& measurements)
20{
21 if (measurements.size() < 4) {
22 if (measurements.size() == 3) return 0.2; // Arbitrary value to prevent excluding measurements with 3 hits later on.
23 else return 0;
24 }
25 // Calculates Curvature: True means clockwise, False means counterclockwise.
26 // TODO this is not an optimized approach; just to get things to work.
27 // CalcCurvature could be integrated into the looping over the hits which CircleFit does anyhow.
29 bool clockwise = *(m_results.curvatureSign) >= 0;
30
31 double stopper = 0.000000001;
32 double meanX = 0, meanY = 0, meanX2 = 0, meanY2 = 0, meanR2 = 0, meanR4 = 0, meanXR2 = 0, meanYR2 = 0, meanXY = 0; //mean values
33 double sumWeights = 0, divisor/*, weightNormalizer = 0*/; // sumWeights is sum of weights, divisor is 1/sumWeights;
34 double tuningParameter = 1.; //0.02; // this parameter is for internal tuning of the weights, 1 means no influence of parameter.
35
36 // looping over all hits and do the division afterwards
37 for (const SpacePoint* hit : measurements) {
38 double weight = 1. / (sqrt(hit->getPositionError().X() * hit->getPositionError().X() + hit->getPositionError().Y() *
39 hit->getPositionError().Y()) * tuningParameter);
40 sumWeights += weight;
41 if (std::isnan(weight) or std::isinf(weight)) {
42 B2ERROR("QualityEstimators::circleFit, chosen sigma is 'nan': " << weight << ", setting arbitrary error: "
43 << stopper << ")"); weight = stopper;
44 }
45 double x = hit->getPosition().X();
46 double y = hit->getPosition().Y();
47 double x2 = x * x;
48 double y2 = y * y;
49 double r2 = x2 + y2;
50 meanX += x * weight;
51 meanY += y * weight;
52 meanXY += x * y * weight;
53 meanX2 += x2 * weight;
54 meanY2 += y2 * weight;
55 meanXR2 += x * r2 * weight;
56 meanYR2 += y * r2 * weight;
57 meanR2 += r2 * weight;
58 meanR4 += r2 * r2 * weight;
59 }
60 divisor = 1. / sumWeights;
61 meanX *= divisor;
62 meanY *= divisor;
63 meanXY *= divisor;
64 meanY2 *= divisor;
65 meanX2 *= divisor;
66 meanXR2 *= divisor;
67 meanYR2 *= divisor;
68 meanR2 *= divisor;
69 meanR4 *= divisor;
70
71 // covariances:
72 double covXX = meanX2 - meanX * meanX;
73 double covXY = meanXY - meanX * meanY;
74 double covYY = meanY2 - meanY * meanY;
75 double covXR2 = meanXR2 - meanX * meanR2;
76 double covYR2 = meanYR2 - meanY * meanR2;
77 double covR2R2 = meanR4 - meanR2 * meanR2;
78
79 if (covR2R2 == 0) {
80 return 0; // TODO could be problematic if it is pretty near to 0
81 }
82
83 // q1, q2: helping variables, to make the code more readable
84 double q1 = covR2R2 * covXY - covXR2 * covYR2;
85 double q2 = covR2R2 * (covXX - covYY) - covXR2 * covXR2 + covYR2 * covYR2;
86
87 // physical meaning: phi value of the point of closest approach of the fitted circle to the origin
88 double pocaPhi = 0.5 * atan2(2. * q1, q2);
89
90 double sinPhi = sin(pocaPhi);
91 double cosPhi = cos(pocaPhi);
92 double kappa = (sinPhi * covXR2 - cosPhi * covYR2) / covR2R2;
93 double delta = -kappa * meanR2 + sinPhi * meanX - cosPhi * meanY;
94 double rootTerm = sqrt(1. - 4.*delta * kappa);
95 // rho = curvature in X-Y-plane = 1/radius of fitting circle, used for pT-calculation
96 double curvature = 2.*kappa / (rootTerm);
97 double pocaD = 2.*delta / (1. + rootTerm);
98
99 // Checks if the random Curvature of CircleFit corresponds to CalcCurvature and adjust the results accordingly.
100 if ((curvature < 0 && clockwise) || (curvature > 0 && !clockwise)) {
101 // this is according to eq. 23 in the paper of Karimäki
102 curvature = -curvature;
103 pocaD = -pocaD;
104 //TODO ..and swap correlation Terms V_rho_phi and V_rho_d (which are not implemented anyway)
105 }
106 double radius = 1. / curvature;
107 double absRadius = fabs(radius);
108 double pt = calcPt(absRadius);
109 m_results.pt = pt;
110 m_results.pocaD = pocaD;
111
112 // Estimating theta of the track with the theta of the innermost hit.
113 // Otherwise the track is solely a circle without theta information.
114 double innermostHitTheta = 0.;
115 double innermostHitRadiusSquared = 100000000;
116 for (const SpacePoint* hit : measurements) {
117 if (hit->getPosition().Perp2() < innermostHitRadiusSquared) {
118 innermostHitRadiusSquared = hit->getPosition().Perp2();
119 innermostHitTheta = hit->getPosition().Theta();
120 }
121 }
122 // Account for precision when checking equality of innermostHitTheta with 0
123 double pz = (innermostHitTheta <= 1e-6 ? 0 : pt / tan(innermostHitTheta));
124 // Both p and pmag are only rough estimates based and by far not accutate!
125 m_results.p = B2Vector3D(pt * cosPhi, pt * sinPhi, pz);
126 m_results.pmag = sqrt(pt * pt + pz * pz);
127
128 double chi2 = sumWeights * (1. + curvature * pocaD) * (1. + curvature * pocaD)
129 * (sinPhi * sinPhi * covXX - 2.*sinPhi * cosPhi * covXY + cosPhi * cosPhi * covYY - kappa * kappa * covR2R2);
130
131 m_results.chiSquared = chi2;
132
133 return TMath::Prob(chi2, measurements.size() - 3);
134}
135
QualityEstimationResults m_results
Result of the quality estimation This is stored as a member variable, because some values may be calc...
double calcPt(double const radius) const
Returns a value for the transverse momentum in GeV calculated from a provided radius.
virtual double estimateQuality(std::vector< SpacePoint const * > const &measurements) final
Minimal implementation of the quality estimation Calculates quality indicator in range [0,...
SpacePoint typically is build from 1 PXDCluster or 1-2 SVDClusters.
Definition: SpacePoint.h:42
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
short calcCurvatureSignum(std::vector< SpacePoint const * > const &measurements)
Calculate curvature based on triplets of measurements.
Abstract base class for different kinds of events.
std::optional< double > pt
transverse momentum estimate from the QE
std::optional< short > curvatureSign
direction of curvature as obtained by the QE
std::optional< double > pocaD
distance to the z-axis of the POCA
std::optional< double > chiSquared
chi squared value obtained by the fit of the QE
std::optional< B2Vector3D > p
momentum vector estimate from the QE
std::optional< double > pmag
momentum magnitute estimate from the QE