CbmRoot
Loading...
Searching...
No Matches
CaTripletConstructor.cxx
Go to the documentation of this file.
1/* Copyright (C) 2010-2021 Frankfurt Institute for Advanced Studies, Goethe-Universität Frankfurt, Frankfurt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Igor Kulakov [committer], Maksym Zyzak, Valentina Akishina */
4
6
7#include "CaDefines.h"
8#include "CaFramework.h"
9#include "CaGridArea.h"
10
11#include <algorithm>
12#include <iostream>
13// #include "CaToolsDebugger.h"
15#include "KfTrackKalmanFilter.h"
16#include "KfTrackParam.h"
17
18// using cbm::ca::tools::Debugger;
19
20namespace cbm::algo::ca
21{
23 const ca::TrackingMode& mode)
24 : fParameters(pars)
25 , fSetup(fParameters.GetActiveSetup())
26 , frWData(wData)
27 , fDefaultMass(mass)
28 , fTrackingMode(mode)
29 {
30 // FIXME: SZh 24.08.2022
31 // This approach is suitable only for a case, when all the stations inside a magnetic field come right before
32 // all the stations outside of the field!
33 fNfieldStations = std::lower_bound(fParameters.GetStations().cbegin(),
34 fParameters.GetStations().cbegin() + fParameters.GetNstationsActive(),
35 0, // we are looking for the first zero element
36 [](const ca::Station<fvec>& s, int edge) { return bool(s.fieldStatus) > edge; })
37 - fParameters.GetStations().cbegin();
38
39 fIsTargetField = !frWData.TargB().IsZero();
40 }
41
42
43 bool TripletConstructor::InitStations(int istal, int istam, int istar)
44 {
45 fIstaL = istal;
46 fIstaM = istam;
47 fIstaR = istar;
48
49 if (fIstaM >= fParameters.GetNstationsActive()) {
50 return false;
51 }
52 fStaL = &fParameters.GetStation(fIstaL);
53 fStaM = &fParameters.GetStation(fIstaM);
54 fStaR = &fParameters.GetStation(fIstaR);
55
56 { // two stations for approximating the field between the target and the left hit
57 const int sta1 = (fNfieldStations <= 1) ? 1 : std::clamp(fIstaL, 1, fNfieldStations - 1);
58 const int sta0 = sta1 / 2; // station between fIstaL and the target
59
60 assert(0 <= sta0 && sta0 < sta1 && sta1 < fParameters.GetNstationsActive());
61 fFld0Sta[0] = &fParameters.GetStation(sta0);
62 fFld0Sta[1] = &fParameters.GetStation(sta1);
63 }
64
65 { // three stations for approximating the field between the left and the right hit
66
67 int sta0 = fIstaL;
68 int sta1 = fIstaM;
69 int sta2 = fIstaM + 1;
70 if (sta2 >= fParameters.GetNstationsActive()) {
71 sta2 = fIstaM;
72 sta1 = fIstaM - 1;
73 sta0 = (sta1 <= 0) ? 0 : std::clamp(sta0, 0, sta1 - 1);
74 }
75 if (fParameters.GetNstationsActive() >= 3) {
76 assert(0 <= sta0 && sta0 < sta1 && sta1 < sta2 && sta2 < fParameters.GetNstationsActive());
77 }
78
79 fFld1Sta[0] = &fParameters.GetStation(sta0);
80 fFld1Sta[1] = &fParameters.GetStation(sta1);
81 fFld1Sta[2] = &fParameters.GetStation(sta2);
82 }
83 return true;
84 }
85
86
87 void TripletConstructor::CreateTripletsForHit(Vector<ca::Triplet>& tripletsOut, int istal, int istam, int istar,
88 ca::HitIndex_t iHitL)
89 {
90 if (!InitStations(istal, istam, istar)) {
91 tripletsOut.clear();
92 return;
93 }
94
98
99 fIhitL = iHitL;
100 const auto& hitl = frWData.Hit(fIhitL);
101
102 // fit a straight line through the target and the left hit.
103 TrackParamV& T = fit.Tr();
104 {
107 //kf::FieldValue<fvec> lB, mB, cB, rB _fvecalignment; currently not used
108 //kf::FieldValue<fvec> l_B_global, centB_global _fvecalignment; currently not used
109
110 // get the magnetic field along the track.
111 // (suppose track is straight line with origin in the target)
112 {
113 const fvec dzli = 1.f / (hitl.Z() - fParameters.GetTargetPositionZ());
114
115 T.X() = hitl.X();
116 T.Y() = hitl.Y();
117 T.Z() = hitl.Z();
118 T.Tx() = (hitl.X() - fParameters.GetTargetPositionX()) * dzli;
119 T.Ty() = (hitl.Y() - fParameters.GetTargetPositionY()) * dzli;
120 T.Qp() = fvec(0.);
121 T.Time() = hitl.T();
123
124 const fvec maxSlopePV = frWData.CurrentIteration()->GetMaxSlopePV();
125 const fvec maxQp = frWData.CurrentIteration()->GetMaxQp();
126 const fvec txErr2 = maxSlopePV * maxSlopePV / fvec(9.);
127 const fvec qpErr2 = maxQp * maxQp / fvec(9.);
128
129 T.ResetErrors(1., 1., txErr2, txErr2, qpErr2, (fStaL->timeInfo ? hitl.dT2() : 1.e6), 1.e10);
130 T.InitVelocityRange(1. / frWData.CurrentIteration()->GetMaxQp());
131
132 T.C00() = hitl.dX2();
133 T.C10() = hitl.dXY();
134 T.C11() = hitl.dY2();
135 T.Ndf() = (frWData.CurrentIteration()->GetPrimaryFlag()) ? fvec(2.) : fvec(0.);
136 T.NdfTime() = (fStaL->timeInfo ? 0 : -1);
137 }
138
139 // NDF = number of track parameters (6: x, y, tx, ty, qp, time)
140 // - number of measured parameters (3: x, y, time) on station or (2: x, y) on target
141
142 // field made by the left hit, the target and the station istac in-between.
143 // is used for extrapolation to the target and to the middle hit
145 {
146 kf::FieldValue<fvec> B0 = fFld0Sta[0]->fieldSlice.GetFieldValueForLine(T);
147 kf::FieldValue<fvec> B1 = fFld0Sta[1]->fieldSlice.GetFieldValueForLine(T);
148 fld0.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B0, fFld0Sta[0]->fZ, B1, fFld0Sta[1]->fZ);
149 }
150
151 { // field, made by the left hit, the middle station and the right station
152 // Will be used for extrapolation to the right hit
153 kf::FieldValue<fvec> B0 = fFld1Sta[0]->fieldSlice.GetFieldValueForLine(T);
154 kf::FieldValue<fvec> B1 = fFld1Sta[1]->fieldSlice.GetFieldValueForLine(T);
155 kf::FieldValue<fvec> B2 = fFld1Sta[2]->fieldSlice.GetFieldValueForLine(T);
156 fFldL.Set(B0, fFld1Sta[0]->fZ, B1, fFld1Sta[1]->fZ, B2, fFld1Sta[2]->fZ);
157 }
158
159 // add the target constraint
160 fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fld0);
161 fit.MultipleScattering(fSetup.GetMaterial(fIstaL).GetThicknessX0(T.GetX(), T.GetY()));
162
163 // extrapolate to the middle hit
164 fit.ExtrapolateLine(fStaM->fZ, fFldL);
165 }
166
168 auto FindDoubletHits = [&]() {
169 const bool matchMc = fParameters.DevIsMatchDoubletsViaMc();
170 const int iMC = matchMc ? ca::Framework::GetMcTrackIdForWindowHit(fIhitL) : -1;
171 fDoubletData.second.clear();
172 if (iMC < 0 && matchMc) {
173 return;
174 }
176 fParameters.GetMaxDoubletsPerSinglet());
177 };
178
179 FindDoubletHits();
180 FindDoublets(fit);
181
182 //D.Smith 28.8.24: Moving this upward (before doublet finding) changes QA output slightly
183 if (fIstaR >= fParameters.GetNstationsActive()) {
184 tripletsOut.clear();
185 return;
186 }
187
189 FindTriplets();
190 SelectTriplets(tripletsOut);
191 }
192
193
195 {
196 // ---- Add the middle hits to parameters estimation ----
198 Vector<ca::HitIndex_t>& hitsM = fDoubletData.second;
199
200 tracks.clear();
201 tracks.reserve(hitsM.size());
202
203 const bool isMomentumFitted = (fIsTargetField || (fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0));
204
205 const TrackParamV Tr = fit.Tr(); // copy contents of fit
206
207 auto it2 = hitsM.begin();
208 for (auto it = hitsM.begin(); it != hitsM.end(); it++) {
209
210 const ca::HitIndex_t indM = *it;
211 const ca::Hit& hitm = frWData.Hit(indM);
212
213 if (frWData.IsHitSuppressed(indM)) {
214 continue;
215 }
216
217 TrackParamV& T2 = fit.Tr();
218 T2 = Tr;
219 fit.SetQp0(fvec(0.f));
220
221 fvec z_2 = hitm.Z();
222 kf::MeasurementXy<fvec> m_2(hitm.X(), hitm.Y(), hitm.dX2(), hitm.dY2(), hitm.dXY(), fvec::One(), fvec::One());
223 fvec t_2 = hitm.T();
224 fvec dt2_2 = hitm.dT2();
225
226 // add the middle hit
227 fit.ExtrapolateLineNoField(z_2);
228 fit.FilterXY(m_2);
229 fit.FilterTime(t_2, dt2_2, fmask(fStaM->timeInfo));
230 fit.SetQp0(isMomentumFitted ? fit.Tr().GetQp() : frWData.CurrentIteration()->GetMaxQp());
231 fit.MultipleScattering(fSetup.GetMaterial(fIstaM).GetThicknessX0(T2.GetX(), T2.Y()));
232 fit.SetQp0(fit.Tr().Qp());
233
234 // check if there are other hits close to the doublet on the same station
235 if (ca::kMcbm != fTrackingMode) {
236 // TODO: SG: adjust cuts, put them to parameters
237
238 const fscal tx = T2.Tx()[0];
239 const fscal ty = T2.Ty()[0];
240 const fscal tt = T2.Vi()[0] * sqrt(1. + tx * tx + ty * ty); // dt/dl * dl/dz
241
242 for (auto itClone = it + 1; itClone != hitsM.end(); itClone++) {
243
244 const int indClone = *itClone;
245 const ca::Hit& hitClone = frWData.Hit(indClone);
246
247 const fscal dz = hitClone.Z() - T2.Z()[0];
248
249 if ((fStaM->timeInfo) && (T2.NdfTime()[0] >= 0)) {
250 const fscal dt = T2.Time()[0] + tt * dz - hitClone.T();
251 if (!(fabs(dt) <= 3.5 * sqrt(T2.C55()[0]) + hitClone.RangeT())) {
252 continue;
253 }
254 }
255
256 const fscal dx = T2.GetX()[0] + tx * dz - hitClone.X();
257 if (!(fabs(dx) <= 3.5 * sqrt(T2.C00()[0]) + hitClone.RangeX())) {
258 continue;
259 }
260
261 const fscal dy = T2.Y()[0] + ty * dz - hitClone.Y();
262 if (!(fabs(dy) <= 3.5 * sqrt(T2.C11()[0]) + hitClone.RangeY())) {
263 continue;
264 }
265
266 if (fParameters.DevIsSuppressOverlapHitsViaMc()) {
269 || (iMC != ca::Framework::GetMcTrackIdForWindowHit(indClone))) {
270 continue;
271 }
272 }
273
274 frWData.SuppressHit(indClone);
275 }
276 }
277
278 tracks.push_back(T2);
279 *it2 = indM;
280 it2++;
281 } // it
282 hitsM.shrink(std::distance(hitsM.begin(), it2));
283 }
284
285
287 {
288 //auto& [tracks_2, hitsM_2] = doublets; TO DO: Reactivate when MacOS compiler bug is fixed.
289 Vector<TrackParamV>& tracks_2 = fDoubletData.first;
290 Vector<ca::HitIndex_t>& hitsM_2 = fDoubletData.second;
291
292 Vector<ca::HitIndex_t>& hitsM_3 = std::get<1>(fTripletData);
293 Vector<ca::HitIndex_t>& hitsR_3 = std::get<2>(fTripletData);
294
299 fit.SetQp0(fvec(0.));
300
301 {
302 const int maxTriplets = hitsM_2.size() * fParameters.GetMaxTripletPerDoublets();
303 hitsM_3.clear();
304 hitsR_3.clear();
305 hitsM_3.reserve(maxTriplets);
306 hitsR_3.reserve(maxTriplets);
307 }
308 // ---- Add the middle hits to parameters estimation. Propagate to right station. ----
309
310 const double maxSlope = frWData.CurrentIteration()->GetMaxSlope();
311 const double tripletChi2Cut = frWData.CurrentIteration()->GetTripletChi2Cut();
312 for (unsigned int i2 = 0; i2 < hitsM_2.size(); i2++) {
313
314 fit.SetTrack(tracks_2[i2]);
315 TrackParamV& T2 = fit.Tr();
316
317 // extrapolate to the right hit station
318 fit.Extrapolate(fStaR->fZ, fFldL);
319
320 if constexpr (fDebugDublets) {
321 ca::HitIndex_t iwhit[2] = {fIhitL, hitsM_2[i2]};
322 ca::HitIndex_t ihit[2] = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id()};
323
324 const int ih0 = ihit[0];
325 const int ih1 = ihit[1];
326 const ca::Hit& h0 = frWData.Hit(iwhit[0]);
327 const ca::Hit& h1 = frWData.Hit(iwhit[1]);
328
329 LOG(info) << "\n====== Extrapolated Doublet : "
330 << " iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
331 << fIstaM << "/" << ih1 << " " << fIstaR << "/?} xyz: {" << h0.X() << " " << h0.Y() << " " << h0.Z()
332 << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "} chi2 " << T2.GetChiSq()[0] << " ndf "
333 << T2.Ndf()[0] << " chi2time " << T2.ChiSqTime()[0] << " ndfTime " << T2.NdfTime()[0];
334 LOG(info) << " extr. track: " << T2.ToString(0);
335 }
336
337 // ---- Find the triplets(right hit). Reformat data in the portion of triplets. ----
338 int iMC = -1;
339
340 auto rejectDoublet = [&]() -> bool {
341 if (ca::TrackingMode::kSts == fTrackingMode && (T2.C44()[0] < 0)) {
342 return true;
343 }
344 if (T2.C00()[0] < 0 || T2.C11()[0] < 0 || T2.C22()[0] < 0 || T2.C33()[0] < 0 || T2.C55()[0] < 0) {
345 return true;
346 }
347 if (fabs(T2.Tx()[0]) > maxSlope) {
348 return true;
349 }
350 if (fabs(T2.Ty()[0]) > maxSlope) {
351 return true;
352 }
353 if (fParameters.DevIsMatchTripletsViaMc()) {
354 int indM = hitsM_2[i2];
356 if (iMC < 0 || iMC != ca::Framework::GetMcTrackIdForWindowHit(indM)) {
357 return true;
358 }
359 }
360 return false;
361 };
362 const bool isDoubletGood = !rejectDoublet();
363
364 if constexpr (fDebugDublets) {
365 if (isDoubletGood) {
366 LOG(info) << " extrapolated doublet accepted";
367 }
368 else {
369 LOG(info) << " extrapolated doublet rejected";
370 LOG(info) << "======== end of extrapolated doublet ==== \n";
371 }
372 }
373
374 if (!isDoubletGood) {
375 continue;
376 }
377
378 Vector<ca::HitIndex_t> collectedHits;
379 CollectHits(collectedHits, fit, fIstaR, tripletChi2Cut, iMC, fParameters.GetMaxTripletPerDoublets());
380
381 if (collectedHits.size() >= fParameters.GetMaxTripletPerDoublets()) {
382 // FU, 28.08.2024, Comment the following log lines since it spams the output
383 // of our tests and finally results in crashes on run4
384 // LOG(debug) << "Ca: GetMaxTripletPerDoublets==" << fParameters.GetMaxTripletPerDoublets()
385 // << " reached in findTripletsStep0()";
386 // reject already created triplets for this doublet
387 collectedHits.clear();
388 }
389 if constexpr (fDebugDublets) {
390 LOG(info) << " collected " << collectedHits.size() << " hits on the right station ";
391 }
392 for (ca::HitIndex_t& irh : collectedHits) {
393 if constexpr (fDebugDublets) {
394 const ca::Hit& h = frWData.Hit(irh);
395 ca::HitIndex_t ihit = h.Id();
396 LOG(info) << " hit " << ihit << " " << h.ToString();
397 }
398 if (frWData.IsHitSuppressed(irh)) {
399 if constexpr (fDebugDublets) {
400 LOG(info) << " the hit is suppressed";
401 }
402 continue;
403 }
404 // pack the triplet
405 hitsM_3.push_back(hitsM_2[i2]);
406 hitsR_3.push_back(irh);
407 } // search area
408 if constexpr (fDebugDublets) {
409 LOG(info) << "======== end of extrapolated doublet ==== \n";
410 }
411 } // i2
412 }
413
415 {
416 constexpr int nIterations = 2;
417
419 Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
420 Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
421 assert(hitsM.size() == hitsR.size());
422
423 tracks.clear();
424 tracks.reserve(hitsM.size());
425
427 if constexpr (fDebugTriplets) {
428 //cbm::ca::tools::Debugger::Instance().AddNtuple(
429 // "triplets", "ev:iter:i0:x0:y0:z0:i1:x1:y1:z1:i2:x2:y2:z2:mc:sta:p:vx:vy:vz:chi2:ndf:chi2time:ndfTime");
430 }
431
433 fit.SetMask(fmask::One());
435
436 // prepare data
437 const int NHits = 3; // triplets
438 const int ista[NHits] = {fIstaL, fIstaM, fIstaR};
439
440 const ca::Station<fvec> sta[NHits] = {fParameters.GetStation(ista[0]), fParameters.GetStation(ista[1]),
441 fParameters.GetStation(ista[2])};
442
443 const bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
444 const fvec ndfTrackModel = 4 + (isMomentumFitted ? 1 : 0); // straight line or track with momentum
445
446 for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
447
448 // prepare data
449 const ca::HitIndex_t iwhit[NHits] = {fIhitL, hitsM[i3], hitsR[i3]};
450
451 const ca::HitIndex_t ihit[NHits] = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id(),
452 frWData.Hit(iwhit[2]).Id()};
453
454 if (fParameters.DevIsMatchTripletsViaMc()) {
455 int mc1 = ca::Framework::GetMcTrackIdForCaHit(ihit[0]);
456 int mc2 = ca::Framework::GetMcTrackIdForCaHit(ihit[1]);
457 int mc3 = ca::Framework::GetMcTrackIdForCaHit(ihit[2]);
458 if ((mc1 != mc2) || (mc1 != mc3)) {
459 // D.S.: Added to preserve the ordering when switching from index-based
460 // access to push_back(). Discuss with SZ.
461 tracks.push_back(TrackParamV());
462 continue;
463 }
464 }
465
466 fscal x[NHits], y[NHits], z[NHits], t[NHits];
467 fscal dt2[NHits];
468 kf::MeasurementXy<fvec> mxy[NHits];
469
470 for (int ih = 0; ih < NHits; ++ih) {
471 const ca::Hit& hit = frWData.Hit(iwhit[ih]);
472 mxy[ih] = kf::MeasurementXy<fvec>(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
473
474 x[ih] = hit.X();
475 y[ih] = hit.Y();
476 z[ih] = hit.Z();
477 t[ih] = hit.T();
478 dt2[ih] = hit.dT2();
479 };
480
481 // find the field along the track
482
486
487 fvec tx[3] = {(x[1] - x[0]) / (z[1] - z[0]), (x[2] - x[0]) / (z[2] - z[0]), (x[2] - x[1]) / (z[2] - z[1])};
488 fvec ty[3] = {(y[1] - y[0]) / (z[1] - z[0]), (y[2] - y[0]) / (z[2] - z[0]), (y[2] - y[1]) / (z[2] - z[1])};
489
490 for (int ih = 0; ih < NHits; ++ih) {
491 fvec dz = (sta[ih].fZ - z[ih]);
492 B[ih] = sta[ih].fieldSlice.GetFieldValue(x[ih] + tx[ih] * dz, y[ih] + ty[ih] * dz);
493 };
494
495 fld.Set(B[0], sta[0].fZ, B[1], sta[1].fZ, B[2], sta[2].fZ);
496 fldTarget.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B[0], sta[0].fZ, B[1], sta[1].fZ);
497
498 TrackParamV& T = fit.Tr();
499
500 // initial parameters
501 {
502 fvec dz01 = 1. / (z[1] - z[0]);
503 T.Tx() = (x[1] - x[0]) * dz01;
504 T.Ty() = (y[1] - y[0]) * dz01;
505 T.Qp() = 0.;
506 T.Vi() = 0.;
507 }
508
509 // repeat several times in order to improve the precision
510 for (int iiter = 0; iiter < nIterations; ++iiter) {
511
512 auto fitTrack = [&](int startIdx, int endIdx, int step, kf::FitDirection direction) {
513 const fvec maxQp = frWData.CurrentIteration()->GetMaxQp();
514 fit.SetQp0(T.Qp());
515 fit.Qp0()(fit.Qp0() > maxQp) = maxQp;
516 fit.Qp0()(fit.Qp0() < -maxQp) = -maxQp;
517
518 int ih0 = startIdx;
519 T.X() = x[ih0];
520 T.Y() = y[ih0];
521 T.Z() = z[ih0];
522 T.Time() = t[ih0];
523 T.Qp() = 0.;
524 T.Vi() = 0.;
525
526 T.ResetErrors(1., 1., 1., 1., 100., (sta[ih0].timeInfo ? dt2[ih0] : 1.e6), 1.e2);
527 T.C00() = mxy[ih0].Dx2();
528 T.C10() = mxy[ih0].Dxy();
529 T.C11() = mxy[ih0].Dy2();
530
531 T.Ndf() = -ndfTrackModel + 2;
532 T.NdfTime() = sta[ih0].timeInfo ? 0 : -1;
533
534 if (startIdx == 0) { //only for the forward fit
535 fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fldTarget);
536 }
537
538 for (int ih = startIdx + step; ih != endIdx; ih += step) {
539 fit.Extrapolate(z[ih], fld);
540 auto radThick = fSetup.GetMaterial(ista[ih]).GetThicknessX0(T.X(), T.Y());
541 fit.MultipleScattering(radThick);
542 fit.EnergyLossCorrection(radThick, direction);
543 fit.FilterXY(mxy[ih]);
544 fit.FilterTime(t[ih], dt2[ih], fmask(sta[ih].timeInfo));
545 }
546 };
547
548 // Fit downstream
549 fitTrack(0, NHits, 1, kf::FitDirection::kDownstream);
550
551 if (iiter == nIterations - 1) break;
552
553 // Fit upstream
554 fitTrack(NHits - 1, -1, -1, kf::FitDirection::kUpstream);
555 } // for iiter
556
557 tracks.push_back(T);
558
559 if constexpr (fDebugTriplets) {
560 int ih0 = ihit[0];
561 int ih1 = ihit[1];
562 int ih2 = ihit[2];
566
567 if (1 || (mc1 >= 0) && (mc1 == mc2) && (mc1 == mc3)) {
568 const ca::Hit& h0 = frWData.Hit(iwhit[0]);
569 const ca::Hit& h1 = frWData.Hit(iwhit[1]);
570 const ca::Hit& h2 = frWData.Hit(iwhit[2]);
571 //const CbmL1MCTrack& mctr = CbmL1::Instance()->GetMcTracks()[mc1];
572 LOG(info) << "== fitted triplet: "
573 << " iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
574 << fIstaM << "/" << ih1 << " " << fIstaR << "/" << ih2 << "} xyz: {" << h0.X() << " " << h0.Y()
575 << " " << h0.Z() << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "}, {" << h2.X() << ", "
576 << h2.Y() << ", " << h2.Z() << "} chi2 " << T.GetChiSq()[0] << " ndf " << T.Ndf()[0] << " chi2time "
577 << T.ChiSqTime()[0] << " ndfTime " << T.NdfTime()[0];
578 /*
579 cbm::ca::tools::Debugger::Instance().FillNtuple(
580 "triplets", mctr.iEvent, frAlgo.fCurrentIterationIndex, ih0, h0.X(), h0.Y(), h0.Z(), ih1, h1.X(), h1.Y(),
581 h1.Z(), ih2, h2.X(), h2.Y(), h2.Z(), mc1, fIstaL, mctr.p, mctr.x, mctr.y, mctr.z, (fscal) T.GetChiSq()[0],
582 (fscal) T.Ndf()[0], (fscal) T.ChiSqTime()[0], (fscal) T.NdfTime()[0]);
583 */
584 }
585 }
586 } //i3
587 } // FindTriplets
588
589
591 {
594
596 Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
597 Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
598
599 bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
600
601 tripletsOut.clear();
602 tripletsOut.reserve(hitsM.size());
603
604 for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
605
606 TrackParamV& T3 = tracks[i3];
607
608 // TODO: SG: normalize chi2, separate cuts on time and space
609
610 const fscal chi2 = T3.GetChiSq()[0] + T3.GetChiSqTime()[0];
611
612 const ca::HitIndex_t ihitl = fIhitL;
613 const ca::HitIndex_t ihitm = hitsM[i3];
614 const ca::HitIndex_t ihitr = hitsR[i3];
615
619
622 continue;
623 }
624 }
625 // assert(std::isfinite(chi2) && chi2 > 0);
626
627 if (!std::isfinite(chi2) || chi2 < 0) {
628 continue;
629 }
630 //if (!T3.IsEntryConsistent(true, 0)) { continue; }
631
632 fscal qp = T3.Qp()[0];
633 fscal Cqp = T3.C44()[0];
634
635 // TODO: SG: a magic correction that comes from the legacy code
636 // removing it leads to a higher ghost ratio
637 Cqp += 0.001;
638
639 tripletsOut.emplace_back(ihitl, ihitm, ihitr, fIstaL, fIstaM, fIstaR, 0, 0, 0, chi2, qp, Cqp, T3.Tx()[0],
640 T3.C22()[0], T3.Ty()[0], T3.C33()[0], isMomentumFitted);
641 }
642 }
643
644
646 const int iSta, const double chi2Cut, const int iMC, const int maxNhits)
647 {
649 collectedHits.clear();
650 collectedHits.reserve(maxNhits);
651
652 const ca::Station<fvec>& sta = fParameters.GetStation(iSta);
653
654 TrackParamV& T = fit.Tr();
655 //LOG(info) << T.chi2[0] ;
656 T.ChiSq() = 0.;
657
658 // if make it bigger the found hits will be rejected later because of the chi2 cut.
659 const fvec Pick_m22 = (fvec(chi2Cut) - T.GetChiSq());
660 const fscal timeError2 = T.C55()[0];
661 const fscal time = T.Time()[0];
662
663 const auto& grid = frWData.Grid(iSta);
664 const fvec maxDZ = frWData.CurrentIteration()->GetMaxDZ();
665 ca::GridArea area(grid, T.X()[0], T.Y()[0],
666 (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0],
667 (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0]);
668 if constexpr (fDebugCollectHits) {
669 LOG(info) << "search area: " << T.X()[0] << " " << T.Y()[0] << " "
670 << (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0] << " "
671 << (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0];
672 }
673 if (fParameters.DevIsIgnoreHitSearchAreas()) {
675 }
676
677 // loop over station hits (index incremented in condition)
678 for (ca::HitIndex_t ih = 0; area.GetNextObjectId(ih) && ((int) collectedHits.size() < maxNhits);) {
679
680 if (frWData.IsHitSuppressed(ih)) {
681 continue;
682 }
683
684 const ca::Hit& hit = frWData.Hit(ih);
685 if constexpr (fDebugCollectHits) {
686 LOG(info) << "hit in the search area: " << hit.ToString();
687 LOG(info) << " check the hit.. ";
688 }
689
690 if (iMC >= 0) { // match via MC
692 if constexpr (fDebugCollectHits) {
693 LOG(info) << " hit mc does not match";
694 }
695 continue;
696 }
697 }
698
699 // check time-boundaries
700
701 //TODO: move hardcoded cuts to parameters
702 if ((sta.timeInfo) && (T.NdfTime()[0] >= 0)) {
703 if (fabs(time - hit.T()) > 1.4 * (3.5 * sqrt(timeError2) + hit.RangeT())) {
704 if constexpr (fDebugCollectHits) {
705 LOG(info) << " hit time does not match";
706 }
707 continue;
708 }
709 // if (fabs(time - hit.T()) > 30) continue;
710 }
711
712 // - check whether hit belong to the window ( track position +\- errors ) -
713 const fscal z = hit.Z();
714
715 // check y-boundaries
716 const auto [y, C11] = fit.ExtrapolateLineYdY2(z);
717 const fscal dy_est = sqrt(Pick_m22[0] * C11[0]) + hit.RangeY();
718 const fscal dY = hit.Y() - y[0];
719
720 if (fabs(dY) > dy_est) {
721 if constexpr (fDebugCollectHits) {
722 LOG(info) << " hit Y does not match";
723 }
724 continue;
725 }
726
727 // check x-boundaries
728 const auto [x, C00] = fit.ExtrapolateLineXdX2(z);
729 const fscal dx_est = sqrt(Pick_m22[0] * C00[0]) + hit.RangeX();
730 const fscal dX = hit.X() - x[0];
731
732 if (fabs(dX) > dx_est) {
733 if constexpr (fDebugCollectHits) {
734 LOG(info) << " hit X does not match";
735 }
736 continue;
737 }
738
739 // check chi2
740 kf::MeasurementXy<fvec> mxy(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
741
742 const fvec C10 = fit.ExtrapolateLineDxy(z);
743 const auto [chi2x, chi2u] = kf::TrackKalmanFilter<fvec>::GetChi2XChi2U(mxy, x, y, C00, C10, C11);
744
745 // TODO: adjust the cut, cut on chi2x & chi2u separately
747 if (chi2x[0] > chi2Cut) {
748 if constexpr (fDebugCollectHits) {
749 LOG(info) << " hit chi2X is too large";
750 }
751 continue;
752 }
753 if (chi2u[0] > chi2Cut) {
754 if constexpr (fDebugCollectHits) {
755 LOG(info) << " hit chi2U is too large";
756 }
757 continue;
758 }
759 }
760 if constexpr (fDebugCollectHits) {
761 LOG(info) << " hit passed all the checks";
762 }
763 collectedHits.push_back(ih);
764
765 } // loop over the hits in the area
766 }
767} // namespace cbm::algo::ca
TClonesArray * tracks
Macros for the CA tracking algorithm.
#define CBMCA_DEBUG_ASSERT(v)
Definition CaDefines.h:40
Triplet constructor for the CA tracker.
friend fvec sqrt(const fvec &a)
Track fit utilities for the CA tracking based on the Kalman filter.
Data class with information on a STS local track.
static int GetMcTrackIdForCaHit(int iHit)
Gets number of stations before the pipe (MVD stations in CBM)
static int GetMcTrackIdForWindowHit(int iGridHit)
Get mc track ID for a hit (debug tool)
Class for accessing objects in the 2D area that are stored in ca::Grid.
Definition CaGridArea.h:17
bool GetNextObjectId(ca::HitIndex_t &objectId)
look up the next object id in the requested area
Definition CaGridArea.h:92
void DoLoopOverEntireGrid()
debug mode: loop over the entire GetEntries() vector ignoring the search area
Definition CaGridArea.h:103
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 RangeX() const
Get the +/- range of uncertainty of X coordinate.
Definition CaHit.h:126
fscal dT2() const
Get the uncertainty of time.
Definition CaHit.h:123
std::string ToString() const
Simple string representation of the hit class.
Definition CaHit.cxx:17
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 RangeY() const
Get the +/- range of uncertainty of Y coordinate.
Definition CaHit.h:129
fscal RangeT() const
Get the +/- range of uncertainty of time.
Definition CaHit.h:132
fscal T() const
Get the time.
Definition CaHit.h:111
fscal X() const
Get the X coordinate.
Definition CaHit.h:102
HitIndex_t Id() const
Get the hit id.
Definition CaHit.h:135
fscal dY2() const
Get the uncertainty of Y coordinate.
Definition CaHit.h:117
float GetTripletChi2Cut() const
Gets triplet chi2 upper cut.
float GetMaxSlope() const
Gets max slope (tx\ty) in 3D hit position of a triplet.
Definition CaIteration.h:82
bool GetElectronFlag() const
flag check: electrons/positrons - true, heavy charged - false
Definition CaIteration.h:64
float GetDoubletChi2Cut() const
Gets doublet chi2 upper cut.
Definition CaIteration.h:61
float GetTripletFinalChi2Cut() const
Gets triplet chi2 upper cut.
bool GetTrackFromTripletsFlag() const
float GetMaxQp() const
Gets max considered q/p for tracks.
Definition CaIteration.h:79
float GetMaxDZ() const
Gets correction for accounting overlaping and iff z.
Definition CaIteration.h:76
const std::string & GetName() const
Gets the name of the iteration.
Definition CaIteration.h:94
float GetMaxSlopePV() const
Gets max slope (tx\ty) in primary vertex.
Definition CaIteration.h:85
A container for all external parameters of the CA tracking algorithm.
DataT fZ
z position of station [cm]
Definition CaStation.h:29
int timeInfo
flag: if time information can be used
Definition CaStation.h:25
kf::FieldSlice< DataT > fieldSlice
Magnetic field near the station.
Definition CaStation.h:33
const cbm::algo::kf::Setup< fvec > & fSetup
Reference to the setup.
const Parameters< fvec > & fParameters
Object of Framework parameters class.
void SelectTriplets(Vector< ca::Triplet > &tripletsOut)
Select good triplets.
void CreateTripletsForHit(Vector< ca::Triplet > &tripletsOut, int istal, int istam, int istar, ca::HitIndex_t ihl)
---— FUNCTIONAL PART ---—
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
void CollectHits(Vector< ca::HitIndex_t > &collectedHits, kf::TrackKalmanFilter< fvec > &fit, const int iSta, const double chi2Cut, const int iMC, const int maxNhits)
const ca::Station< fvec > * fFld0Sta[2]
const ca::Station< fvec > * fFld1Sta[3]
bool InitStations(int istal, int istam, int istar)
void FindDoublets(kf::TrackKalmanFilter< fvec > &fit)
Find the doublets. Reformat data in the portion of doublets.
TripletConstructor(const ca::Parameters< fvec > &pars, WindowData &wData, const fscal mass, const ca::TrackingMode &mode)
---— Constructors and destructor ---—
void FindTriplets()
Find triplets on station.
const ca::Station< fvec > * fStaR
right station
ca::HitIndex_t fIhitL
index of the left hit in fAlgo->fWindowHits
const ca::Station< fvec > * fStaL
left station
const ca::Station< fvec > * fStaM
mid station
bool fIsTargetField
is the magnetic field present at the target
void shrink(std::size_t count)
Reduces the vector to a given size.
Definition CaVector.h:150
void push_back(Tinput value)
Pushes back a value to the vector.
Definition CaVector.h:176
void reserve(std::size_t count)
Reserves a new size for the vector.
Definition CaVector.h:162
void emplace_back(Tinput &&... value)
Creates a parameter in the end of the vector.
Definition CaVector.h:196
Container for internal data, processed on a single time window.
HitIndex_t & HitStartIndexOnStation(int iStation)
Index of the first hit on the station.
ca::Grid & Grid(int iStation)
Gets grid for station index.
void SuppressHit(int iHit)
Set hit suppression flag.
const Iteration * CurrentIteration() const
Accesses current iteration.
kf::FieldValue< fvec > & TargB()
Accesses magnetic field in starting point (target or first station)
uint8_t IsHitSuppressed(int iHit) const
Gets hit suppression flag.
kf::MeasurementXy< fvec > & TargetMeasurement()
Measurement of the target with the uncertainty.
ca::Hit & Hit(int iHit)
Gets hit by index.
Magnetic field region, corresponding to a hit triplet.
void Set(const FieldValue< T > &b0, const T &z0, const FieldValue< T > &b1, const T &z1, const FieldValue< T > &b2, const T &z2)
Interpolates the field by three nodal points with the second order polynomial.
constexpr FieldValue< T > GetFieldValue(const T &x, const T &y) const
Gets field value at a point on the transverse plane.
Magnetic flux density vector.
void Set(const I &bx, const I &by, const I &bz)
Constructor from components.
The class describes a 2D - measurement (x, y) in XY coordinate system.
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
void FilterWithTargetAtLine(DataT targZ, const kf::MeasurementXy< DataT > &targXYInfo, const kf::FieldRegion< DataT > &F)
add target measuremet to the track using linearisation at a straight line
std::pair< DataT, DataT > ExtrapolateLineYdY2(DataT z_out) const
static std::tuple< DataT, DataT > GetChi2XChi2U(kf::MeasurementXy< DataT > m, DataT x, DataT y, DataT C00, DataT C10, DataT C11)
git two chi^2 components of the track fit to measurement
void FilterXY(const kf::MeasurementXy< DataT > &m, bool skipUnmeasuredCoordinates=false)
filter the track with the XY measurement
void ExtrapolateLineNoField(DataT z_out)
extrapolate the track to the given Z assuming no magnetic field
kf::TrackParam< DataT > & Tr()
void MultipleScattering(DataT radThick, DataT tx0, DataT ty0, DataT qp0)
apply multiple scattering correction to the track with the given Qp0
void EnergyLossCorrection(DataT radThick, FitDirection direction)
DataT ExtrapolateLineDxy(DataT z_out) const
std::pair< DataT, DataT > ExtrapolateLineXdX2(DataT z_out) const
void FilterTime(DataT t, DataT dt2, const DataTmask &m)
filter the track with the time measurement
void SetParticleMass(DataT mass)
set particle mass for the fit
void SetTrack(const kf::TrackParam< T > &t)
void ExtrapolateLine(DataT z_out, const kf::FieldRegion< DataT > &F)
extrapolate the track to the given Z using linearization at the straight line
T C00() const
Individual getters for covariance matrix elements.
T Ndf() const
Gets NDF of track fit model.
T Vi() const
Gets inverse velocity [ns/cm].
T NdfTime() const
Gets NDF of time measurements.
T ChiSq() const
Gets Chi-square of track fit model.
T Tx() const
Gets slope along x-axis.
T ChiSqTime() const
Gets Chi-square of time measurements.
T GetQp() const
Gets charge over momentum [ec/GeV].
T Y() const
Gets y position [cm].
T GetChiSqTime() const
Gets Chi-square of time measurements.
T Qp() const
Gets charge over momentum [ec/GeV].
T Z() const
Gets z position [cm].
T Time() const
Gets time [ns].
T GetChiSq() const
Gets Chi-square of track fit model.
T Ty() const
Gets slope along y-axis.
std::string ToString(int i=-1) const
Prints parameters to a string.
T GetX() const
Gets x position [cm].
static fmask One()
static fvec One()
constexpr fscal ElectronMass
Electron mass [GeV/c2].
Definition CaDefs.h:86
constexpr fscal SpeedOfLightInv
Inverse speed of light [ns/cm].
Definition CaDefs.h:89
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
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