CbmRoot
Loading...
Searching...
No Matches
KfVertexFitter.cxx
Go to the documentation of this file.
1/* Copyright (C) 2007-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergey Gorbunov [committer] */
4
5
10
11#include "KfVertexFitter.h"
12
14#include "KfFieldRegion.h"
15#include "KfSetup.h"
16#include "KfTrackKalmanFilter.h"
17
18using namespace cbm::algo::kf;
19
20template<DoFitTime FlagFitTime>
22{
23 if (!fKfSetup) {
24 LOG(fatal) << "VertexFitter: KfSetup is not set!";
25 }
26 const auto& target = fKfSetup->GetTarget();
27 VertexD v;
28 v.SetX(target.GetX());
29 v.SetY(target.GetY());
30 v.SetZ(target.GetZ());
31 v.SetTime(0.);
32 v.ResetErrors(target.GetR() * target.GetR() / 3.5 / 3.5, target.GetR() * target.GetR() / 3.5 / 3.5,
33 target.GetDz() * target.GetDz() / 3.5 / 3.5, 1.e5);
34 return v;
35}
36
37template<DoFitTime FlagFitTime>
38template<typename T>
39std::tuple<VertexD, std::vector<char>>
41 const std::vector<const TrackParam<T>*>& linearizations,
42 const VertexD& vtxGuess) const
43{
44 if (!fKfSetup) {
45 LOG(fatal) << "VertexFitter: KfSetup is not set!";
46 }
47
48 if (tracks.size() != linearizations.size()) {
49 LOG(fatal) << "VertexFitter: number of tracks and number of linearizations do not match!";
50 }
51
52 for (unsigned int itr = 0; itr < tracks.size(); ++itr) {
53 const auto trk = tracks[itr];
54 const auto lin = linearizations[itr];
55 if (!trk || !lin) {
56 LOG(fatal) << "VertexFitter: null track or linearization pointer!";
57 }
58 if (!(fabs(trk->GetZ() - lin->GetZ()) < 1.e-10)) {
59 LOG(fatal) << "VertexFitter: track and linearization z positions do not match!";
60 }
61 }
62
63 std::vector<char> usedTracks(tracks.size(), 0);
64
65 const auto& target = fKfSetup->GetTarget();
66
69
70 trackFitter.SetMaxExtrapolationStep(1.0); // [cm]
71
72 // Vertex state vector and the covariance matrix
73
74 VertexD vtx = vtxGuess;
75 auto& r = vtx.Parameters();
76 auto& C = vtx.CovMatrix();
77
78 // Iteratively fit the vertex
79 for (int iteration = 0; iteration < fNofIterations; ++iteration) {
80
81 // Store the vertex from the previous iteration
82
83 auto vtx0 = vtx;
84 const auto& r0 = vtx0.Parameters();
85 const auto& C0 = vtx0.CovMatrix();
86
87 // Initialize the vertex covariance matrix, Chi^2 & NDF
88
89 vtx.ResetErrors(1.e1, 1.e1, 1.e1, 1.e1);
90 std::fill(usedTracks.begin(), usedTracks.end(), 0);
91
93 vtx.SetZ(target.GetZ());
94 C(Tag22) = target.GetDz() * target.GetDz() / 3.5 / 3.5;
95 }
97 vtx.SetX(fBeamX);
98 vtx.SetY(fBeamY);
101 }
102
103 // Loop over tracks to update the vertex with each track information
104
105 //LOG(info) << "\n\n===========================";
106 //LOG(info) << "VertexFitter: iteration " << iteration;
107
108 for (unsigned int itr = 0; itr < tracks.size(); ++itr) {
109 //LOG(info) << "VertexFitter: processing track " << itr;
110 //LOG(info) << vtx.ToString();
111 // Transport track to the vertex z position
112 trackFitter.SetTrack(*tracks[itr]);
113 trackFitter.SetLinearization(*linearizations[itr]);
114 trackFitter.Extrapolate(vtx0.GetZ(), field);
115
116 const auto& tr = trackFitter.Tr();
117 const auto& lin = trackFitter.Linearization();
118
119 //LOG(info) << tr.ToString();
120
121 std::array<T, 6> m{tr.X(), tr.Y(), tr.Tx(), tr.Ty(), tr.Qp(), tr.Time()};
122 const auto& V = tr.GetCovMatrix();
123
124 // Check the track deviation from the vtx0 estimate. The covariance matrix of the vtxGuess must be set when using this option.
125 if (fRmsCut > 0.) {
126 double zeta[2] = {r0[0] - m[0], r0[1] - m[1]};
127 double S[3] = {(C0(Tag11) + V[2]), -(C0(Tag10) + V[1]), (C0(Tag00) + V[0])};
128 double s = S[2] * S[0] - S[1] * S[1];
129 double chi2 = zeta[0] * zeta[0] * S[0] + 2 * zeta[0] * zeta[1] * S[1] + zeta[1] * zeta[1] * S[2];
130 if (chi2 > s * fRmsCut * fRmsCut) {
131 continue;
132 }
133 }
134
135 // Fit the track linearization to the r0 vertex. The covmatrix is taken from the track.
136
137 double a = 0, b = 0; // slopes at the vertex
138 {
139 std::array<T, 6> ml{lin.x, lin.y, lin.tx, lin.ty, lin.qp, lin.time};
140 double zeta[2] = {r0[0] - ml[0], r0[1] - ml[1]};
141
142 double s = V[0] * V[2] - V[1] * V[1];
143 if (s < 1.E-20) {
144 LOG(warning) << "VertexFitter: track covariance matrix is singular, skipping track!";
145 continue;
146 }
147 a = m[2] + ((V[3] * V[2] - V[4] * V[1]) * zeta[0] + (-V[3] * V[1] + V[4] * V[0]) * zeta[1]) / s;
148 b = m[3] + ((V[6] * V[2] - V[7] * V[1]) * zeta[0] + (-V[6] * V[1] + V[7] * V[0]) * zeta[1]) / s;
149 }
150
151 //LOG(info) << "VertexFitter: track slopes at vertex a=" << a << " b=" << b;
152
153 // Update the vertex (r,C) with the track estimate (m,V) :
154
155 // Matrix of the linearized measurement
156 // H = { 1, 0, -a }
157 // { 0, 1, -b }
158
159 // ( 1 0 )
160 // Ht = ( 0 1 )
161 // (-a -b )
162
163 // Residual (measured - estimated) zeta = m - H*r
164
165 double zeta[2] = {m[0] + a * (r[2] - r0[2]) - r[0], // propagate track from vtx0 to vtx using slopes a, b at vtx0
166 m[1] + b * (r[2] - r0[2]) - r[1]};
167
168 // CHt = CH'
169
170 double CHt[3][2] = {{C(Tag00) - a * C(Tag20), C(Tag10) - b * C(Tag20)},
171 {C(Tag10) - a * C(Tag21), C(Tag11) - b * C(Tag21)},
172 {C(Tag20) - a * C(Tag22), C(Tag21) - b * C(Tag22)}};
173
174 // HCHt = H*C*H', low-triangular storage
175
176 double HCHt[3] = {CHt[0][0] - a * CHt[2][0], //
177 CHt[1][0] - b * CHt[2][0], CHt[1][1] - b * CHt[2][1]};
178
179 // S = (H*C*H' + V ), low-triangular storage
180
181 double S[3] = {V[0] + HCHt[0], //
182 V[1] + HCHt[1], V[2] + HCHt[2]};
183
184 // Invert S: S -> S^{-1}
185 {
186 double det = S[0] * S[2] - S[1] * S[1];
187 if (det < 1.E-20) {
188 LOG(warn) << "VertexFitter: S matrix is singular, skipping track!";
189 LOG(warn) << " S00=" << S[0] << " S11=" << S[2] << " S01=" << S[1];
190 LOG(warn) << " V00=" << V[0] << " V11=" << V[2] << " V01=" << V[1];
191 LOG(warn) << " a = " << a << " b=" << b;
192 LOG(warn) << vtx.ToString();
193 continue;
194 }
195 double S0 = S[0];
196 S[0] = S[2] / det;
197 S[1] = -S[1] / det;
198 S[2] = S0 / det;
199 }
200
201 vtx.NofTracks()++;
202 usedTracks[itr] = 1;
203
204 // Calculate Chi^2
205 if (vtx.NofTracks() > 2) {
206 vtx.ChiSq() += zeta[0] * zeta[0] * S[0] + 2 * zeta[0] * zeta[1] * S[1] + zeta[1] * zeta[1] * S[2];
207 }
208 vtx.Ndf() += 2;
209
210 // Kalman gain K = CH'*S
211
212 double K[3][2];
213
214 for (int i = 0; i < 3; ++i) {
215 K[i][0] = CHt[i][0] * S[0] + CHt[i][1] * S[1];
216 K[i][1] = CHt[i][0] * S[1] + CHt[i][1] * S[2];
217 }
218
219 // New estimation of the vertex position r += K*zeta
220
221 for (int i = 0; i < 3; ++i) {
222 r[i] += K[i][0] * zeta[0] + K[i][1] * zeta[1];
223 }
224
225 // New covariance matrix C -= K*(CH')'
226
227 C(Tag00) -= K[0][0] * CHt[0][0] + K[0][1] * CHt[0][1];
228
229 C(Tag10) -= K[1][0] * CHt[0][0] + K[1][1] * CHt[0][1];
230 C(Tag11) -= K[1][0] * CHt[1][0] + K[1][1] * CHt[1][1];
231
232 C(Tag20) -= K[2][0] * CHt[0][0] + K[2][1] * CHt[0][1];
233 C(Tag21) -= K[2][0] * CHt[1][0] + K[2][1] * CHt[1][1];
234 C(Tag22) -= K[2][0] * CHt[2][0] + K[2][1] * CHt[2][1];
235
236 if constexpr (FlagFitTime == DoFitTime::Y) { // fit the time separately in a simple way
237
238 double dt = m[5] - vtx.Time(); // time residual
239 double s = V[15] + C(Tag33);
240 if (s > 1.E-10) {
241 vtx.ChiSqTime() += dt * dt / s;
242 vtx.NdfTime() += 1;
243 double Kt = C(Tag33) / s;
244 vtx.Time() += Kt * dt;
245 C(Tag33) -= Kt * C(Tag33);
246 }
247 }
248
249 } // end loop over tracks
250
251 if (vtx.GetNofTracks() < 2) {
252 if (iteration > 0) {
253 LOG(warn) << "VertexFitter: only " << vtx.GetNofTracks() << " tracks contributed to the vertex in the "
254 << iteration << " iteration, vertex fit failed.";
255 }
256 break;
257 }
258 } // end of vertex fitting iterations
259
260 return std::make_tuple(vtx, usedTracks);
261}
262
263template<DoFitTime FlagFitTime>
265{
266 // instantiations of FitVertex method
267 FitVertex<double>(std::vector<const TrackParam<double>*>(), std::vector<const TrackParam<double>*>(), VertexD{});
268 FitVertex<float>(std::vector<const TrackParam<float>*>(), std::vector<const TrackParam<float>*>(), VertexD{});
269}
270
271// Template instantiations
272
TClonesArray * tracks
Magnetic flux density interpolation along the track vs. z-coordinate (header)
Setup representation for the Kalman-filter framework (header)
fscal v[fmask::Size]
Definition KfSimdPseudo.h:4
Track fit utilities for the CA tracking based on the Kalman filter.
header file for the kf::VertexFitter class
Some class C.
Magnetic field region, corresponding to a hit triplet.
static EFieldType fgOriginalFieldType
Global field type.
static FieldFn_t fgOriginalField
Global variable to store the field function (x,y,z)->(Bx,By,Bz)
void SetMaxExtrapolationStep(double step)
set max extrapolation step [cm]
void SetLinearization(const Linearization_t &lin)
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
kf::TrackParam< DataT > & Tr()
void SetTrack(const kf::TrackParam< T > &t)
TrackParam classes of different types.
The class implements vertex fitting with Kalman filter.
double fBeamX
Width of beamline constraint in X [cm].
double fBeamSigmaY
Sigma of beamline constraint in Y [cm].
VertexD GetGuessFromTheTarget() const
bool fConstrainToTargetZ
Flag to constrain vertex to target.
double fBeamY
Width of beamline constraint in Y [cm].
std::tuple< VertexD, std::vector< char > > FitVertex(const std::vector< const TrackParam< T > * > &tracks, const std::vector< const TrackParam< T > * > &linearizations, const VertexD &vtxGuess) const
Fit vertex from the given tracks.
std::shared_ptr< const Setup< double > > fKfSetup
Kalman Filter setup.
void dummy()
template instantiation dummy function
double fBeamSigmaX
Sigma of beamline constraint in X [cm].
double fRmsCut
Cut in standard deviation for track to be included in vertex fit.
int fNofIterations
N of iterations for vertex fitting.
bool fConstrainToBeamXY
Flag to constrain vertex to beamline.
std::string ToString() const
Prints parameters to a string.
Definition KfVertex.cxx:22
void SetZ(T v)
z position [cm]
Definition KfVertex.h:98
CovMatrix_t & CovMatrix()
get covariance matrix
Definition KfVertex.h:89
int32_t Ndf() const
nof degrees of freedom
Definition KfVertex.h:59
void ResetErrors(T c00, T c11, T c22, T c33)
nof tracks used
Definition KfVertex.h:171
int32_t GetNofTracks() const
Definition KfVertex.h:72
void SetX(T v)
x position [cm]
Definition KfVertex.h:96
int32_t NofTracks() const
Definition KfVertex.h:62
T Time() const
t position [cm]
Definition KfVertex.h:57
T ChiSqTime() const
chi2 time
Definition KfVertex.h:60
void SetY(T v)
y position [cm]
Definition KfVertex.h:97
Parameters_t & Parameters()
nof tracks used
Definition KfVertex.h:88
int32_t NdfTime() const
nof degrees of freedom time
Definition KfVertex.h:61
T ChiSq() const
chi2
Definition KfVertex.h:58
static constexpr Tag< 2, 2 > Tag22
Tag for (2,2) element.
Definition KfDefs.h:51
static constexpr Tag< 1, 1 > Tag11
Tag for (1,1) element.
Definition KfDefs.h:41
@ Y
Fit the time component.
Definition KfDefs.h:134
static constexpr Tag< 1, 0 > Tag10
Tag for (1,0) element.
Definition KfDefs.h:40
static constexpr Tag< 2, 1 > Tag21
Tag for (2,1) element.
Definition KfDefs.h:50
static constexpr Tag< 3, 3 > Tag33
Tag for (3,3) element.
Definition KfDefs.h:61
static constexpr Tag< 2, 0 > Tag20
Tag for (2,0) element.
Definition KfDefs.h:49
static constexpr Tag< 0, 0 > Tag00
Tag for (0,0) element.
Definition KfDefs.h:31
Vertex< double > VertexD
Definition KfVertex.h:166