CbmRoot
Loading...
Searching...
No Matches
CaTrackFitter.cxx
Go to the documentation of this file.
1/* Copyright (C) 2010-2020 Frankfurt Institute for Advanced Studies, Goethe-Universitaet Frankfurt, Frankfurt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Ivan Kisel, Sergey Gorbunov, Igor Kulakov [committer], Valentina Akishina, Maksym Zyzak */
4
5#include "CaTrackFitter.h"
6
7#include "CaFramework.h"
9#include "KfTrackParam.h"
10
11#include <iostream>
12#include <vector>
13
14
15namespace cbm::algo::ca
16{
17 // -------------------------------------------------------------------------------------------------------------------
18 //
20 : fParameters(pars)
21 , fSetup(fParameters.GetActiveSetup())
22 , fField(fSetup.GetField())
23 , fDefaultMass(mass)
24 , fTrackingMode(mode)
25 {
26 }
27
28 // -------------------------------------------------------------------------------------------------------------------
29 //
31
32 // -------------------------------------------------------------------------------------------------------------------
33 //
35 {
36 // LOG(info) << " Start CA Track Fitter ";
37 int start_hit = 0; // for interation in wData.RecoHitIndices()
38
39 // static kf::FieldValue fldB0, fldB1, fldB2 _fvecalignment;
40 // static kf::FieldRegion fld _fvecalignment;
41 kf::FieldValue<fvec> fldB0, fldB1, fldB2 _fvecalignment;
43
44
45 //kf::FieldRegion<fvec> fld1 _fvecalignment;
46
47 const int nStations = fParameters.GetNstationsActive();
48 int nTracks_SIMD = fvec::size();
49
50 kf::TrackKalmanFilter<fvec> fit; // fit parameters coresponding to the current track
51 TrackParamV& tr = fit.Tr();
53
54 Track* t[fvec::size()]{nullptr};
55
56 const auto& sta = fSetup.GetActiveLayers();
57
58 // Spatial-time position of a hit vs. station and track in the portion
59 fvec x[constants::size::MaxNstations]; // Hit position along the x-axis [cm]
60 fvec y[constants::size::MaxNstations]; // Hit position along the y-axis [cm]
61 kf::MeasurementXy<fvec> mxy[constants::size::MaxNstations]; // Covariance matrix for x,y
62
63 fvec z[constants::size::MaxNstations]; // Hit position along the z-axis (precised) [cm]
64
65 fvec time[constants::size::MaxNstations]; // Hit time [ns]
66 fvec dt2[constants::size::MaxNstations]; // Hit time uncertainty [ns] squared
67
68 fvec x_first;
69 fvec y_first;
71
72 fvec time_first;
73 fvec wtime_first;
74 fvec dt2_first;
75
76 fvec x_last;
77 fvec y_last;
79
80 fvec time_last;
81 fvec wtime_last;
82 fvec dt2_last;
83
87
88 fvec y_temp;
89 fvec x_temp;
90 fvec fldZ0;
91 fvec fldZ1;
92 fvec fldZ2;
93 fvec z_start;
94 fvec z_end;
95
97
99 for (int ista = 0; ista < nStations; ista++) {
100 ZSta[ista] = sta[ista].GetZref();
101 mxy[ista].SetCov(1., 0., 1.);
102 }
103
104 unsigned short N_vTracks = wData.RecoTracks().size(); // number of tracks processed per one SSE register
105
106 for (unsigned short itrack = 0; itrack < N_vTracks; itrack += fvec::size()) {
107
108 if (N_vTracks - itrack < static_cast<unsigned short>(fvec::size())) nTracks_SIMD = N_vTracks - itrack;
109
110 for (int i = 0; i < nTracks_SIMD; i++) {
111 t[i] = &wData.RecoTrack(itrack + i);
112 }
113
114 // fill the rest of the SIMD vectors with something reasonable
115 for (uint i = nTracks_SIMD; i < fvec::size(); i++) {
116 t[i] = &wData.RecoTrack(itrack);
117 }
118
119 // get hits of current track
120 for (int ista = 0; ista < nStations; ista++) {
121 w[ista] = fmask::Zero();
122 w_time[ista] = fmask::Zero();
123 z[ista] = ZSta[ista];
124 }
125
126 //fmask isFieldPresent = fmask::Zero();
127
128 for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
129
130 int nHitsTrack = t[iVec]->fNofHits;
132
133 for (int ih = 0; ih < nHitsTrack; ih++) {
134
135 const ca::Hit& hit = input.GetHit(wData.RecoHitIndex(start_hit++));
136 const int ista = hit.Station();
137 auto [detSystemId, iStLocal] = fSetup.GetIndexMap().GlobalToLocal<EDetectorID>(ista);
138
139 //if (sta[ista].fieldStatus) { isFieldPresent[iVec] = true; }
140
141 iSta[ih] = ista;
142 w[ista][iVec] = true;
143 if (sta[ista].IsTimeMeasured()) {
144 w_time[ista][iVec] = true;
145 }
146 // subtract misalignment tolerances to get the original hit errors
147 auto misalignment = fParameters.GetConfig().GetMisalignmentTolerance(detSystemId);
148 float dX2Orig = hit.dX2() - misalignment.GetXsq();
149 float dY2Orig = hit.dY2() - misalignment.GetYsq();
150 float dXYOrig = hit.dXY();
151 if (dX2Orig < 0. || dY2Orig < 0. || fabs(dXYOrig / sqrt(dX2Orig * dY2Orig)) > 1.) { // ????
152 dX2Orig = hit.dX2();
153 dY2Orig = hit.dY2();
154 }
155 float dT2Orig = hit.dT2() - misalignment.GetTimeSq();
156 if (dT2Orig < 0.) {
157 dT2Orig = hit.dT2();
158 }
159
160 x[ista][iVec] = hit.X(); //x_temp[iVec];
161 y[ista][iVec] = hit.Y(); //y_temp[iVec];
162 time[ista][iVec] = hit.T();
163 dt2[ista][iVec] = dT2Orig;
164 if (!sta[ista].IsTimeMeasured()) {
165 dt2[ista][iVec] = 1.e4;
166 }
167 z[ista][iVec] = hit.Z(); // sta[ista].fieldSlice.GetZref()[iVec];
168 fB_temp = fField.GetFieldValue(ista, x[ista], y[ista]);
169 mxy[ista].X()[iVec] = hit.X();
170 mxy[ista].Y()[iVec] = hit.Y();
171 mxy[ista].Dx2()[iVec] = dX2Orig;
172 mxy[ista].Dy2()[iVec] = dY2Orig;
173 mxy[ista].Dxy()[iVec] = dXYOrig;
174 mxy[ista].NdfX()[iVec] = 1.;
175 mxy[ista].NdfY()[iVec] = 1.;
176
177 fB[ista].SetSimdEntry(fB_temp.GetBx()[iVec], fB_temp.GetBy()[iVec], fB_temp.GetBz()[iVec],
178 fB_temp.GetZ()[iVec], iVec);
179
180 if (ih == 0) {
181 z_start[iVec] = z[ista][iVec];
182 x_first[iVec] = x[ista][iVec];
183 y_first[iVec] = y[ista][iVec];
184 time_first[iVec] = time[ista][iVec];
185 wtime_first[iVec] = sta[ista].IsTimeMeasured() ? 1. : 0.;
186 dt2_first[iVec] = dt2[ista][iVec];
187 mxy_first.X()[iVec] = mxy[ista].X()[iVec];
188 mxy_first.Y()[iVec] = mxy[ista].Y()[iVec];
189 mxy_first.Dx2()[iVec] = mxy[ista].Dx2()[iVec];
190 mxy_first.Dy2()[iVec] = mxy[ista].Dy2()[iVec];
191 mxy_first.Dxy()[iVec] = mxy[ista].Dxy()[iVec];
192 mxy_first.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
193 mxy_first.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
194 }
195 else if (ih == nHitsTrack - 1) {
196 z_end[iVec] = z[ista][iVec];
197 x_last[iVec] = x[ista][iVec];
198 y_last[iVec] = y[ista][iVec];
199 mxy_last.X()[iVec] = mxy[ista].X()[iVec];
200 mxy_last.Y()[iVec] = mxy[ista].Y()[iVec];
201 mxy_last.Dx2()[iVec] = mxy[ista].Dx2()[iVec];
202 mxy_last.Dy2()[iVec] = mxy[ista].Dy2()[iVec];
203 mxy_last.Dxy()[iVec] = mxy[ista].Dxy()[iVec];
204 mxy_last.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
205 mxy_last.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
206 time_last[iVec] = time[ista][iVec];
207 dt2_last[iVec] = dt2[ista][iVec];
208 wtime_last[iVec] = sta[ista].IsTimeMeasured() ? 1. : 0.;
209 }
210 }
211
212 // Why a reverse loop is needed?
213 for (int ih = nHitsTrack - 1; ih >= 0; ih--) {
214 const int ista = iSta[ih];
215 By[ista][iVec] = fField.GetFieldValue(ista, 0., 0.).GetBy()[0];
216 }
217 }
218
219 fit.GuessTrack(z_end, x, y, z, time, By, w, w_time, nStations);
220
221 // FIXME: Replace with "nofield" flag
223 tr.Qp() = fvec(1. / 1.1);
224 }
225
226 // tr.Qp() = iif(isFieldPresent, tr.Qp(), fvec(1. / 0.25));
227
228 for (int iter = 0; iter < 2; iter++) { // 1.5 iterations
229
230 fit.Linearization().qp = tr.Qp();
231
232 // fit backward
233
234 int ista = nStations - 1;
235
236 time_last = iif(w_time[ista], time_last, fvec::Zero());
237 dt2_last = iif(w_time[ista], dt2_last, fvec(1.e6));
238
239 tr.ResetErrors(mxy_last.Dx2(), mxy_last.Dy2(), 0.1, 0.1, 1.0, dt2_last, 1.e-2);
240 tr.C10() = mxy_last.Dxy();
241 tr.X() = mxy_last.X();
242 tr.Y() = mxy_last.Y();
243 tr.Time() = time_last;
245 tr.InitVelocityRange(0.5);
246 tr.Ndf() = fvec(-5.) + fvec(2.);
247 tr.NdfTime() = fvec(-2.) + wtime_last;
248
249 fldZ1 = z[ista]; // sta[ista].fieldSlice.GetZref();
250 fldB1 = fField.GetFieldValue(ista, tr.X(), tr.Y());
251 fldB1.SetSimdEntries(fB[ista], w[ista]);
252
253 fldZ2 = z[ista - 2]; // sta[ista - 2].fieldSlice.GetZref();
254 fvec dz = fldZ2 - fldZ1;
255 fldB2 = fField.GetFieldValue(ista - 2, tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
256 fldB2.SetSimdEntries(fB[ista - 2], w[ista - 2]);
257
258 for (--ista; ista >= 0; ista--) {
259
260 fldZ0 = z[ista]; // sta[ista].fieldSlice.GetZref();
261 dz = (fldZ1 - fldZ0);
262 fldB0 = fField.GetFieldValue(ista, tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
263 fldB0.SetSimdEntries(fB[ista], w[ista]);
264 fld.Set(fldB0, fldB1, fldB2);
265
266 fmask initialised = (z[ista] < z_end) & (z_start <= z[ista]);
267
268 //fld1 = fld;
269
270 fit.SetMask(initialised);
271 fit.Extrapolate(z[ista], fld);
272 auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
273 fit.MultipleScattering(radThick);
275
276 fit.SetMask(initialised && w[ista]);
277 fit.FilterXY(mxy[ista]);
278 fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].IsTimeMeasured()));
279
280
281 fldB2 = fldB1;
282 fldZ2 = fldZ1;
283 fldB1 = fldB0;
284 fldZ1 = fldZ0;
285 }
286
287 // extrapolate to the PV region
288
289 kf::TrackKalmanFilter fitpv = fit;
290 {
291 fitpv.SetMask(fmask::One());
292
294 vtxInfo.SetDx2(1.e-8);
295 vtxInfo.SetDxy(0.);
296 vtxInfo.SetDy2(1.e-8);
297
300 fitpv.SetMaxExtrapolationStep(1.);
301 for (int vtxIter = 0; vtxIter < 2; vtxIter++) {
302 fitpv.Linearization().qp = fitpv.Tr().Qp();
303 fitpv.Tr() = fit.Tr();
304 fitpv.Tr().Qp() = fitpv.Linearization().qp;
305 fitpv.Extrapolate(fSetup.GetTarget().GetZ(), fldFull);
306 fitpv.FilterXY(vtxInfo);
307 }
308 }
309 else {
310 fitpv.Linearization().qp = fitpv.Tr().Qp();
311 fitpv.Extrapolate(fSetup.GetTarget().GetZ(), fld);
312 }
313 }
314
315 //fit.SetQp0(tr.Qp());
316 //fit.SetMask(fmask::One());
317 //fit.MeasureVelocityWithQp();
318 //fit.FilterVi(TrackParamV::kClightNsInv);
319
320 TrackParamV Tf = fit.Tr();
322 Tf.Qp() = fitpv.Tr().Qp();
323 }
324
325 for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
326 t[iVec]->fParFirst.Set(Tf, iVec);
327 }
328
329 for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
330 t[iVec]->fParPV.Set(fitpv.Tr(), iVec);
331 }
332
333 if (iter == 1) {
334 break;
335 } // only 1.5 iterations
336
337 // fit forward
338
339 ista = 0;
340
341 tr.ResetErrors(mxy_first.Dx2(), mxy_first.Dy2(), 0.1, 0.1, 1., dt2_first, 1.e-2);
342 tr.C10() = mxy_first.Dxy();
343
344 tr.X() = mxy_first.X();
345 tr.Y() = mxy_first.Y();
346 tr.Time() = time_first;
348 tr.InitVelocityRange(0.5);
349
350 tr.Ndf() = fvec(-5. + 2.);
351 tr.NdfTime() = fvec(-2.) + wtime_first;
352
353 fit.Linearization().qp = tr.Qp();
354
355 fldZ1 = z[ista]; // sta[ista].fieldSlice.GetZref(); // z[ista];
356 fldB1 = fField.GetFieldValue(ista, tr.X(), tr.Y());
357 fldB1.SetSimdEntries(fB[ista], w[ista]);
358
359 fldZ2 = z[ista + 2]; // sta[ista + 2].fieldSlice.GetZref(); // z[ista + 2];
360 dz = fldZ2 - fldZ1;
361 fldB2 = fField.GetFieldValue(ista + 2, tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
362 fldB2.SetSimdEntries(fB[ista + 2], w[ista + 2]);
363 //fldB2.SetZ(fldZ2);
364
365 for (++ista; ista < nStations; ista++) {
366 fldZ0 = z[ista]; // sta[ista].fieldSlice.GetZref(); // z[ista];
367 dz = (fldZ1 - fldZ0);
368 fldB0 = fField.GetFieldValue(ista, tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
369 fldB0.SetSimdEntries(fB[ista], w[ista]);
370 fld.Set(fldB0, fldB1, fldB2);
371
372 fmask initialised = (z[ista] <= z_end) & (z_start < z[ista]);
373
374 fit.SetMask(initialised);
375 fit.Extrapolate(z[ista], fld);
376 auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
377 fit.MultipleScattering(radThick);
379 fit.SetMask(initialised && w[ista]);
380 fit.FilterXY(mxy[ista]);
381 fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].IsTimeMeasured()));
382
383 fldB2 = fldB1;
384 fldZ2 = fldZ1;
385 fldB1 = fldB0;
386 fldZ1 = fldZ0;
387 }
388
389 //fit.SetQp0(tr.Qp());
390 //fit.SetMask(fmask::One());
391 //fit.MeasureVelocityWithQp();
392 //fit.FilterVi(TrackParamV::kClightNsInv);
393
394 TrackParamV Tl = fit.Tr();
396 Tl.Qp() = fitpv.Tr().Qp();
397 }
398
399 for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
400 t[iVec]->fParLast.Set(Tl, iVec);
401 }
402
403 } // iter
404 }
405 }
406} // namespace cbm::algo::ca
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.
ca::Hit class describes a generic hit for the CA tracker
Definition CaHit.h:32
fscal Z() const
Get the Z coordinate.
Definition CaHit.h:108
fscal dT2() const
Get the uncertainty of time.
Definition CaHit.h:123
fscal dXY() const
Get the X/Y covariance.
Definition CaHit.h:120
fscal dX2() const
Get the uncertainty of X coordinate.
Definition CaHit.h:114
fscal Y() const
Get the Y coordinate.
Definition CaHit.h:105
fscal T() const
Get the time.
Definition CaHit.h:111
fscal X() const
Get the X coordinate.
Definition CaHit.h:102
int Station() const
Get the station index.
Definition CaHit.h:138
fscal dY2() const
Get the uncertainty of Y coordinate.
Definition CaHit.h:117
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.
ca::TrackingMode fTrackingMode
TrackFitter(const ca::Parameters< fvec > &pars, const fscal mass, const ca::TrackingMode &mode)
Default constructor.
void FitCaTracks(const ca::InputData &input, WindowData &wData)
Fit tracks, found by the CA tracker.
const cbm::algo::kf::Field< fvec > & fField
Field instance.
const Parameters< fvec > & fParameters
Object of Framework parameters class.
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
const cbm::algo::kf::Setup< fvec > & fSetup
Setup instance.
Class representing an output track in the CA tracking algorithm.
Definition CaTrack.h:28
Container for internal data, processed on a single time window.
Track & RecoTrack(int iTrack)
Accesses reconstructed track by index.
Vector< Track > & RecoTracks()
Accesses reconstructed track container.
HitIndex_t & RecoHitIndex(int iHit)
Accesses index of hit in the input data.
kf::MeasurementXy< fvec > & TargetMeasurement()
Measurement of the target with the uncertainty.
Magnetic field region, corresponding to a hit triplet.
Magnetic flux density vector.
void SetSimdEntries(const FieldValue &other, const kf::utils::masktype< T > &mask)
Combines the current magnetic field value with another one using a mask.
void SetSimdEntry(double bx, double by, double bz, double z, size_t i)
Sets magnetic flux density components to the field function.
static EFieldType fgOriginalFieldType
Global field type.
static FieldFn_t fgOriginalField
Global variable to store the field function (x,y,z)->(Bx,By,Bz)
The class describes a 2D - measurement (x, y) in XY coordinate system.
void SetCov(DataT dx2, DataT dxy, DataT dy2)
void FilterTime(DataT t, DataT dt2, const DataTmask &m)
filter the track with the time measurement
void SetMaxExtrapolationStep(double step)
set max extrapolation step [cm]
void EnergyLossCorrection(DataT radThick, FitDirection direction)
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
void MultipleScattering(DataT radThick, DataT tx0, DataT ty0, DataT qp0)
apply multiple scattering correction to the track with the given Qp0
void SetParticleMass(DataT mass)
set particle mass for the fit
kf::TrackParam< DataT > & Tr()
void GuessTrack(const DataT &trackZ, const DataT hitX[], const DataT hitY[], const DataT hitZ[], const DataT hitT[], const DataT By[], const DataTmask hitW[], const DataTmask hitWtime[], int NHits)
fast guess of track parameterts based on its hits
void FilterXY(const kf::MeasurementXy< DataT > &m, bool skipUnmeasuredCoordinates=false)
filter the track with the XY measurement
T Qp() const
Gets charge over momentum [ec/GeV].
static fmask Zero()
static fmask One()
static constexpr size_t size()
static fvec Zero()
constexpr fscal SpeedOfLightInv
Inverse speed of light [ns/cm].
Definition CaDefs.h:96
constexpr int MaxNstations
Max number of stations, 2^6 = 64.
Definition CaDefs.h:44
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
kf::fmask fmask
Definition CaSimd.h:15
EDetectorID
Enumeration for the tracking detector subsystems in CBM-CA.
Definition CbmDefs.h:216
kf::fvec fvec
Definition CaSimd.h:13
TrackParam< fvec > TrackParamV