CbmRoot
Loading...
Searching...
No Matches
CaCloneMerger.cxx
Go to the documentation of this file.
1/* Copyright (C) 2010-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko, Maksym Zyzak [committer]*/
4
9
10#include "CaCloneMerger.h"
11
12#include "CaFramework.h"
13#include "CaParameters.h"
14#include "CaTrack.h"
15#include "CaVector.h"
16#include "KfTrackKalmanFilter.h"
17
18#include <iostream>
19
20// FIXME: Refactor code, maybe use an external linear algebra package (e.g., boost::qvm)
21
22namespace cbm::algo::ca
23{
24 // -------------------------------------------------------------------------------------------------------------------
25 //
27 : fParameters(pars)
28 , fSetup(fParameters.GetActiveSetup())
29 , fField(fSetup.GetField())
30 , fDefaultMass(mass)
31 {
32 }
33
34 // -------------------------------------------------------------------------------------------------------------------
35 //
37
38 // -------------------------------------------------------------------------------------------------------------------
39 //
40 void CloneMerger::Exec(const ca::InputData& input, WindowData& wData)
41 {
42 Vector<Track>& extTracks = wData.RecoTracks();
43 Vector<ca::HitIndex_t>& extRecoHits = wData.RecoHitIndices();
44
50 Vector<fscal>& trackChi2 = fTrackChi2;
51 Vector<char>& isStored = fTrackIsStored;
52 Vector<char>& isDownstreamNeighbour = fTrackIsDownstreamNeighbour;
53
54 int nTracks = extTracks.size();
55
56 assert(nTracks < std::numeric_limits<unsigned short>::max());
57
58 constexpr unsigned short kNoNeighbour = std::numeric_limits<unsigned short>::max();
59
60 fTracksNew.clear();
61 fTracksNew.reserve(nTracks);
62 fRecoHitsNew.clear();
63 fRecoHitsNew.reserve(extRecoHits.size());
64
65 firstStation.reset(nTracks);
66 lastStation.reset(nTracks);
67 firstHit.reset(nTracks);
68 lastHit.reset(nTracks);
69 isStored.reset(nTracks);
70 trackChi2.reset(nTracks);
71 neighbour.reset(nTracks);
72 isDownstreamNeighbour.reset(nTracks);
73
74 ca::HitIndex_t start_hit = 0;
75
76 for (int iTr = 0; iTr < nTracks; iTr++) {
77 firstHit[iTr] = start_hit;
78 firstStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
79 start_hit += extTracks[iTr].fNofHits - 1;
80 lastHit[iTr] = start_hit;
81 lastStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
82 start_hit++;
83
84 isStored[iTr] = false;
85 neighbour[iTr] = kNoNeighbour;
86 trackChi2[iTr] = 100000.;
87 isDownstreamNeighbour[iTr] = false;
88 }
89
92 fitB.SetMask(fmask::One());
93 fitB.Linearization().qp = fvec(0.);
94
97 fitF.SetMask(fmask::One());
98 fitF.Linearization().qp = fvec(0.);
99
100 TrackParamV& Tb = fitB.Tr();
101 TrackParamV& Tf = fitF.Tr();
104
105 // Max length for merging
106 unsigned char maxLengthForMerge = static_cast<unsigned char>(fParameters.GetNstationsActive() - 3);
107
108 for (int iTr = 0; iTr < nTracks; iTr++) {
109 if (extTracks[iTr].fNofHits > maxLengthForMerge) continue;
110 for (int jTr = 0; jTr < nTracks; jTr++) {
111 if (extTracks[jTr].fNofHits > maxLengthForMerge) continue;
112 if (iTr == jTr) continue;
113 if (firstStation[iTr] <= lastStation[jTr]) continue;
114
115 unsigned short stab = firstStation[iTr];
116
117 Tb.Set(extTracks[iTr].fParFirst);
118 fitB.Linearization().qp = Tb.Qp();
119
120 unsigned short staf = lastStation[jTr];
121
122 Tf.Set(extTracks[jTr].fParLast);
123 fitF.Linearization().qp = Tf.Qp();
124
125 if (Tf.NdfTime()[0] >= 0. && Tb.NdfTime()[0] >= 0.) {
126 if (fabs(Tf.GetTime()[0] - Tb.GetTime()[0]) > 3 * sqrt(Tf.C55()[0] + Tb.C55()[0])) continue;
127 }
128
129 unsigned short stam;
130
131 fBf = fField.GetFieldValue(staf, Tf.X(), Tf.Y());
132 fBb = fField.GetFieldValue(stab, Tb.X(), Tb.Y());
133
134 unsigned short dist = firstStation[iTr] - lastStation[jTr];
135
136 if (dist > 1)
137 stam = staf + 1;
138 else
139 stam = staf - 1;
140
141 fvec zm = fSetup.GetActiveLayer(stam).GetZref();
142 fvec xm = fvec(0.5) * (Tf.GetX() + Tf.Tx() * (zm - Tf.Z()) + Tb.GetX() + Tb.Tx() * (zm - Tb.Z()));
143 fvec ym = fvec(0.5) * (Tf.Y() + Tf.Ty() * (zm - Tf.Z()) + Tb.Y() + Tb.Ty() * (zm - Tb.Z()));
144 fBm = fField.GetFieldValue(stam, xm, ym);
145 fld.Set(fBb, fBm, fBf);
146
147 fvec zMiddle = fvec(0.5) * (Tb.Z() + Tf.Z());
148
149 fitF.Extrapolate(zMiddle, fld);
150 fitB.Extrapolate(zMiddle, fld);
151
152 fvec Chi2Tracks(0.);
153 FilterTracks(&(Tf.X()), &(Tf.C00()), &(Tb.X()), &(Tb.C00()), nullptr, nullptr, &Chi2Tracks);
154 if (Chi2Tracks[0] > 50) continue;
155
156 if (Chi2Tracks[0] < trackChi2[iTr] || Chi2Tracks[0] < trackChi2[jTr]) {
157 if (neighbour[iTr] < kNoNeighbour) {
158 neighbour[neighbour[iTr]] = kNoNeighbour;
159 trackChi2[neighbour[iTr]] = 100000.;
160 isDownstreamNeighbour[neighbour[iTr]] = false;
161 }
162 if (neighbour[jTr] < kNoNeighbour) {
163 neighbour[neighbour[jTr]] = kNoNeighbour;
164 trackChi2[neighbour[jTr]] = 100000.;
165 isDownstreamNeighbour[neighbour[jTr]] = false;
166 }
167 neighbour[iTr] = jTr;
168 neighbour[jTr] = iTr;
169 trackChi2[iTr] = Chi2Tracks[0];
170 trackChi2[jTr] = Chi2Tracks[0];
171 isDownstreamNeighbour[iTr] = true;
172 isDownstreamNeighbour[jTr] = false;
173 }
174 }
175 }
176
177 for (int iTr = 0; iTr < nTracks; iTr++) {
178 if (isStored[iTr]) continue;
179
180 fTracksNew.push_back(extTracks[iTr]);
181 if (!isDownstreamNeighbour[iTr]) {
182 for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
183 fRecoHitsNew.push_back(extRecoHits[HI]);
184 }
185 }
186
187 if (neighbour[iTr] < kNoNeighbour) {
188 isStored[neighbour[iTr]] = true;
189 fTracksNew.back().fNofHits += extTracks[neighbour[iTr]].fNofHits;
190 for (ca::HitIndex_t HI = firstHit[neighbour[iTr]]; HI <= lastHit[neighbour[iTr]]; HI++)
191 fRecoHitsNew.push_back(extRecoHits[HI]);
192 }
193
194 if (isDownstreamNeighbour[iTr]) {
195 for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
196 fRecoHitsNew.push_back(extRecoHits[HI]);
197 }
198 }
199 }
200
201 // Save the merging results into external vectors
202 extTracks = std::move(fTracksNew);
203 extRecoHits = std::move(fRecoHitsNew);
204 }
205
206 // -------------------------------------------------------------------------------------------------------------------
207 //
208 void CloneMerger::FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5],
209 fvec W[15], fvec* chi2)
210 {
211 fvec S[15];
212 for (int i = 0; i < 15; i++) {
213 if (W) W[i] = C[i];
214 S[i] = C[i] + V[i];
215 }
216
218
219 fvec dzeta[5];
220
221 for (int i = 0; i < 5; i++)
222 dzeta[i] = m[i] - r[i];
223
224 if (W && R) {
225 for (int i = 0; i < 5; i++)
226 R[i] = r[i];
227
228 fvec K[5][5];
229 MultiplySS(C, S, K);
230
231 fvec KC[15];
232 MultiplyMS(K, C, KC);
233 for (int i = 0; i < 15; i++)
234 W[i] -= KC[i];
235
236 fvec kd;
237 for (int i = 0; i < 5; i++) {
238 kd = 0.f;
239 for (int j = 0; j < 5; j++)
240 kd += K[i][j] * dzeta[j];
241 R[i] += kd;
242 }
243 }
244 if (chi2) {
245 fvec S_dzeta[5];
246 MultiplySR(S, dzeta, S_dzeta);
247 *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3]
248 + dzeta[4] * S_dzeta[4];
249 }
250 }
251
252 // -------------------------------------------------------------------------------------------------------------------
253 //
255 {
256 fvec d[5], uud, u[5][5];
257 for (int i = 0; i < 5; i++) {
258 d[i] = 0.f;
259 for (int j = 0; j < 5; j++)
260 u[i][j] = 0.f;
261 }
262
263 for (int i = 0; i < 5; i++) {
264 uud = 0.f;
265 for (int j = 0; j < i; j++)
266 uud += u[j][i] * u[j][i] * d[j];
267 uud = a[i * (i + 3) / 2] - uud;
268
269 fvec smallval(1.e-12);
270 uud = iif(uud >= smallval, uud, smallval);
271
272 d[i] = uud / kf::utils::fabs(uud);
273 u[i][i] = sqrt(kf::utils::fabs(uud));
274
275 for (int j = i + 1; j < 5; j++) {
276 uud = 0.f;
277 for (int k = 0; k < i; k++)
278 uud += u[k][i] * u[k][j] * d[k];
279 uud = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud;
280 u[i][j] = d[i] / u[i][i] * uud;
281 }
282 }
283
284 fvec u1[5];
285
286 for (int i = 0; i < 5; i++) {
287 u1[i] = u[i][i];
288 u[i][i] = 1.f / u[i][i];
289 }
290 for (int i = 0; i < 4; i++) {
291 u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1];
292 }
293 for (int i = 0; i < 3; i++) {
294 u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2];
295 }
296 for (int i = 0; i < 2; i++) {
297 u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3];
298 u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]);
299 }
300 u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4];
301 u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]);
302 u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2]));
303
304 for (int i = 0; i < 5; i++)
305 a[i + 10] = u[i][4] * d[4] * u[4][4];
306 for (int i = 0; i < 4; i++)
307 a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4];
308 for (int i = 0; i < 3; i++)
309 a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4];
310 for (int i = 0; i < 2; i++)
311 a[i + 1] =
312 u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4];
313 a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3]
314 + u[0][4] * u[0][4] * d[4];
315 }
316
317 // -------------------------------------------------------------------------------------------------------------------
318 //
319 void CloneMerger::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
320 {
321 K[0] = C[0][0] * V[0] + C[0][1] * V[1] + C[0][2] * V[3] + C[0][3] * V[6] + C[0][4] * V[10];
322
323 K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10];
324 K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11];
325
326 K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10];
327 K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11];
328 K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12];
329
330 K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10];
331 K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11];
332 K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12];
333 K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13];
334
335 K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10];
336 K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11];
337 K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12];
338 K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13];
339 K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14];
340 }
341
342 // -------------------------------------------------------------------------------------------------------------------
343 //
344 void CloneMerger::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5])
345 {
346 r_out[0] = r_in[0] * C[0] + r_in[1] * C[1] + r_in[2] * C[3] + r_in[3] * C[6] + r_in[4] * C[10];
347 r_out[1] = r_in[0] * C[1] + r_in[1] * C[2] + r_in[2] * C[4] + r_in[3] * C[7] + r_in[4] * C[11];
348 r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12];
349 r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13];
350 r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14];
351 }
352
353 // -------------------------------------------------------------------------------------------------------------------
354 //
355 void CloneMerger::MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5])
356 {
357 K[0][0] = C[0] * V[0] + C[1] * V[1] + C[3] * V[3] + C[6] * V[6] + C[10] * V[10];
358 K[0][1] = C[0] * V[1] + C[1] * V[2] + C[3] * V[4] + C[6] * V[7] + C[10] * V[11];
359 K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12];
360 K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13];
361 K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14];
362
363 K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10];
364 K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11];
365 K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12];
366 K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13];
367 K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14];
368
369 K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10];
370 K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11];
371 K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12];
372 K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13];
373 K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14];
374
375 K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10];
376 K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11];
377 K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12];
378 K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13];
379 K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14];
380
381 K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10];
382 K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11];
383 K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12];
384 K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13];
385 K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14];
386 }
387} // namespace cbm::algo::ca
source file for the ca::Track class
friend fvec sqrt(const fvec &a)
friend fvec iif(fmask a, fvec b, fvec c)
Track fit utilities for the CA tracking based on the Kalman filter.
Some class C.
Vector< unsigned short > fTrackLastStation
Last station of a track.
static void MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5])
Vector< char > fTrackIsDownstreamNeighbour
Flag: is the track a downstream neighbour of another track.
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
CloneMerger(const ca::Parameters< fvec > &pars, const fscal mass)
Default constructor.
Vector< Track > fTracksNew
vector of tracks after the merge
const Parameters< fvec > & fParameters
Reference to the Framework parameters class.
Vector< unsigned short > fTrackNeighbour
Index (TODO:??) of a track that can be merge with the given track.
Vector< ca::HitIndex_t > fRecoHitsNew
vector of track hits after the merge
static void MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
const kf::Field< fvec > & fField
Reference to the magnetic field representation.
void Exec(const ca::InputData &input, WindowData &wData)
Registers.
static void MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5])
Vector< char > fTrackIsStored
Flag: is the given track already stored to the output.
Vector< unsigned short > fTrackFirstStation
First station of a track.
Vector< fscal > fTrackChi2
Chi2 value of the track merging procedure.
Vector< ca::HitIndex_t > fTrackFirstHit
Index of the first hit of a track.
static void FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], fvec W[15], fvec *chi2)
Vector< ca::HitIndex_t > fTrackLastHit
Index of the last hit of a track.
static void InvertCholesky(fvec a[15])
const kf::Setup< fvec > & fSetup
Active setup.
int Station() const
Get the station index.
Definition CaHit.h:138
const Hit & GetHit(HitIndex_t index) const
Gets reference to hit by its index.
Definition CaInputData.h:55
A container for all external parameters of the CA tracking algorithm.
void reset(std::size_t count, Tinput... value)
Clears vector and resizes it to the selected size with selected values.
Definition CaVector.h:135
Container for internal data, processed on a single time window.
Vector< Track > & RecoTracks()
Accesses reconstructed track container.
Vector< HitIndex_t > & RecoHitIndices()
Accesses indices of hits, used by reconstructed tracks.
Magnetic field region, corresponding to a hit triplet.
Magnetic flux density vector.
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
void SetParticleMass(DataT mass)
set particle mass for the fit
kf::TrackParam< DataT > & Tr()
static fmask One()
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
class cbm::algo::ca::WindowData _fvecalignment
kf::fscal fscal
Definition CaSimd.h:14
unsigned int HitIndex_t
Index of ca::Hit.
Definition CaHit.h:27
kf::fvec fvec
Definition CaSimd.h:13
fvec fabs(const fvec &v)
Definition KfUtils.h:30
TrackParam< fvec > TrackParamV