CbmRoot
Loading...
Searching...
No Matches
CbmKfTrackFitter.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergey Gorbunov [committer] */
4
5#include "CbmKfTrackFitter.h"
6
7#include "CbmGlobalTrack.h"
9#include "CbmMuchPixelHit.h"
10#include "CbmMuchTrack.h"
12#include "CbmMvdHit.h"
14#include "CbmStsAddress.h"
15#include "CbmStsHit.h"
16#include "CbmStsSetup.h"
17#include "CbmStsTrack.h"
19#include "CbmTofHit.h"
20#include "CbmTofTrack.h"
22#include "CbmTrdHit.h"
23#include "CbmTrdTrack.h"
25#include "FairRootManager.h"
26#include "KFParticleDatabase.h"
27#include "KfDefs.h"
28#include "KfTrackKalmanFilter.h"
29#include "KfTrackParam.h"
30#include "TClonesArray.h"
31#include "TDatabasePDG.h"
32
33using std::vector;
34using namespace std;
35using namespace cbm::algo;
36
38{
39 // sort the nodes in z
40 std::sort(fNodes.begin(), fNodes.end(), [](const TrajectoryNode& a, const TrajectoryNode& b) { return a.fZ < b.fZ; });
41}
42
43
45
47
49{
50 if (fIsInitialized) {
51 return;
52 }
53
54 FairRootManager* ioman = FairRootManager::Instance();
55
56 if (!ioman) {
57 LOG(fatal) << "CbmKfTrackFitter: no FairRootManager";
58 }
59
60 // TODO: better check if all the interfaces are properly initialized
63 LOG(fatal) << "CbmTrackingDetectorInterface instance was not found. Please, add it as a task to your "
64 "reco macro right before the KF and L1 tasks:\n"
65 << "\033[1;30mrun->AddTask(new CbmTrackingDetectorInterfaceInit());\033[0m";
66 }
67
68 // Get hits
69
70 fInputMvdHits = dynamic_cast<TClonesArray*>(ioman->GetObject("MvdHit"));
71 fInputStsHits = dynamic_cast<TClonesArray*>(ioman->GetObject("StsHit"));
72 fInputTrdHits = dynamic_cast<TClonesArray*>(ioman->GetObject("TrdHit"));
73 fInputMuchHits = dynamic_cast<TClonesArray*>(ioman->GetObject("MuchHit"));
74 fInputTofHits = dynamic_cast<TClonesArray*>(ioman->GetObject("TofHit"));
75
76 // Get global tracks
77 fInputGlobalTracks = dynamic_cast<TClonesArray*>(ioman->GetObject("GlobalTrack"));
78
79 // Get detector tracks
80 fInputStsTracks = dynamic_cast<TClonesArray*>(ioman->GetObject("StsTrack"));
81 fInputMuchTracks = dynamic_cast<TClonesArray*>(ioman->GetObject("MuchTrack"));
82 fInputTrdTracks = dynamic_cast<TClonesArray*>(ioman->GetObject("TrdTrack"));
83 fInputTofTracks = dynamic_cast<TClonesArray*>(ioman->GetObject("TofTrack"));
84
86
87 fIsInitialized = true;
88}
89
91{
92 TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(pdg);
93 if (!particlePDG) {
94 LOG(fatal) << "CbmKfTrackFitter: particle PDG " << pdg << " is not in the data base, please set the mass manually";
95 return;
96 }
97 fMass = particlePDG->Mass();
98 fIsElectron = (abs(pdg) == 11);
99}
100
102{
103 assert(mass >= 0.);
104 fMass = mass;
105}
106
107
108void CbmKfTrackFitter::SetElectronFlag(bool isElectron) { fIsElectron = isElectron; }
109
110
112{
113 Init();
114 if (!fIsInitialized) {
115 return false;
116 }
117
118 if (!fInputStsTracks) {
119 LOG(error) << "CbmKfTrackFitter: Sts track array not found!";
120 return false;
121 }
122 if (stsTrackIndex >= fInputStsTracks->GetEntriesFast()) {
123 LOG(error) << "CbmKfTrackFitter: Sts track index " << stsTrackIndex << " is out of range!";
124 return false;
125 }
126 auto* stsTrack = dynamic_cast<const CbmStsTrack*>(fInputStsTracks->At(stsTrackIndex));
127 if (!stsTrack) {
128 LOG(error) << "CbmKfTrackFitter: Sts track is null!";
129 return false;
130 }
131
132 CbmGlobalTrack globalTrack;
133 globalTrack.SetStsTrackIndex(stsTrackIndex);
134 globalTrack.SetParamFirst(*dynamic_cast<const FairTrackParam*>(stsTrack->GetParamFirst()));
135
136 return CreateGlobalTrack(kfTrack, globalTrack);
137}
138
139
141{
142 Init();
143 if (!fIsInitialized) {
144 return false;
145 }
146
147 if (!fInputGlobalTracks) {
148 LOG(error) << "CbmKfTrackFitter: Global track array not found!";
149 return false;
150 }
151
152 if (globalTrackIndex >= fInputGlobalTracks->GetEntriesFast()) {
153 LOG(error) << "CbmKfTrackFitter: Global track index " << globalTrackIndex << " is out of range!";
154 return false;
155 }
156
157 auto* globalTrack = dynamic_cast<const CbmGlobalTrack*>(fInputGlobalTracks->At(globalTrackIndex));
158 if (!globalTrack) {
159 LOG(error) << "CbmKfTrackFitter: Global track is null!";
160 return false;
161 }
162
163 return CreateGlobalTrack(kfTrack, *globalTrack);
164}
165
166
168{
169 kfTrack = {};
170 Init();
171 if (!fIsInitialized) {
172 return false;
173 }
174
176
177 {
178 t.fNodes.resize(fKfSetup->GetNofLayers());
179 for (int i = 0; i < fKfSetup->GetNofLayers(); i++) {
181 n = {};
182 n.fMaterialLayer = i;
183 n.fZ = fKfSetup->GetMaterial(i).GetZref();
184 n.fRadThick = 0.;
185 n.fIsRadThickFixed = false;
186 n.fIsFitted = false;
187 n.fIsXySet = false;
188 n.fIsTimeSet = false;
190 n.fHitAddress = -1;
191 n.fHitIndex = -1;
192 }
193 }
194
195 // lambda to set the node from the pixel hit
196 auto setNode = [&](const CbmPixelHit& h, int stIdx, int hitIdx,
198 int iLayer = fKfSetup->GetIndexMap().LocalToGlobal(detId, stIdx);
199 if (iLayer < 0) {
200 return nullptr;
201 }
202 assert(iLayer >= 0 && iLayer < fKfSetup->GetNofLayers());
204 n.fZ = h.GetZ();
205 n.fMxy.SetX(h.GetX());
206 n.fMxy.SetY(h.GetY());
207 n.fMxy.SetDx2(h.GetDx() * h.GetDx());
208 n.fMxy.SetDy2(h.GetDy() * h.GetDy());
209 n.fMxy.SetDxy(h.GetDxy());
210 n.fMxy.SetNdfX(1);
211 n.fMxy.SetNdfY(1);
212 n.fIsXySet = true;
213 n.fMt.SetT(h.GetTime());
214 n.fMt.SetDt2(h.GetTimeError() * h.GetTimeError());
215 n.fMt.SetNdfT(1);
216 n.fIsTimeSet = (detId != ca::EDetectorID::kMvd);
217 n.fRadThick = 0.;
218 n.fIsRadThickFixed = false;
220 n.fHitAddress = h.GetAddress();
221 n.fHitIndex = hitIdx;
222 return &n;
223 };
224
225 // Read MVD & STS hits
226
227 if (globalTrack.GetStsTrackIndex() >= 0) {
228
229 int stsTrackIndex = globalTrack.GetStsTrackIndex();
230
231 if (!fInputStsTracks) {
232 LOG(error) << "CbmKfTrackFitter: Sts track array not found!";
233 return false;
234 }
235 if (stsTrackIndex >= fInputStsTracks->GetEntriesFast()) {
236 LOG(error) << "CbmKfTrackFitter: Sts track index " << stsTrackIndex << " is out of range!";
237 return false;
238 }
239 auto* stsTrack = dynamic_cast<const CbmStsTrack*>(fInputStsTracks->At(stsTrackIndex));
240 if (!stsTrack) {
241 LOG(error) << "CbmKfTrackFitter: Sts track is null!";
242 return false;
243 }
244
245 // Read MVD hits
246
247 int nMvdHits = stsTrack->GetNofMvdHits();
248 if (nMvdHits > 0) {
249 if (!fInputMvdHits) {
250 LOG(error) << "CbmKfTrackFitter: Mvd hit array not found!";
251 return false;
252 }
254 LOG(error) << "CbmKfTrackFitter: Mvd tracking interface not found!";
255 return false;
256 }
257 for (int ih = 0; ih < nMvdHits; ih++) {
258 int hitIndex = stsTrack->GetMvdHitIndex(ih);
259 if (hitIndex >= fInputMvdHits->GetEntriesFast()) {
260 LOG(error) << "CbmKfTrackFitter: Mvd hit index " << hitIndex << " is out of range!";
261 return false;
262 }
263 const auto& hit = *dynamic_cast<const CbmMvdHit*>(fInputMvdHits->At(hitIndex));
264 setNode(hit, CbmMvdTrackingInterface::Instance()->GetTrackingStationIndex(&hit), hitIndex,
265 ca::EDetectorID::kMvd);
266 }
267 }
268
269 // Read STS hits
270
271 int nStsHits = stsTrack->GetNofStsHits();
272 if (nStsHits > 0) {
273 if (!fInputStsHits) {
274 LOG(error) << "CbmKfTrackFitter: Sts hit array not found!";
275 return false;
276 }
278 LOG(error) << "CbmKfTrackFitter: Sts tracking interface not found!";
279 return false;
280 }
281 for (int ih = 0; ih < nStsHits; ih++) {
282 int hitIndex = stsTrack->GetStsHitIndex(ih);
283 if (hitIndex >= fInputStsHits->GetEntriesFast()) {
284 LOG(error) << "CbmKfTrackFitter: Sts hit index " << hitIndex << " is out of range!";
285 return false;
286 }
287 const auto& hit = *dynamic_cast<const CbmStsHit*>(fInputStsHits->At(hitIndex));
288 setNode(hit, CbmStsTrackingInterface::Instance()->GetTrackingStationIndex(&hit), hitIndex,
289 ca::EDetectorID::kSts);
290 }
291 }
292 } // MVD & STS hits
293
294
295 // Read Much hits
296
297 if (globalTrack.GetMuchTrackIndex() >= 0) {
298 int muchTrackIndex = globalTrack.GetMuchTrackIndex();
299 if (!fInputMuchTracks) {
300 LOG(error) << "CbmKfTrackFitter: Much track array not found!";
301 return false;
302 }
303 if (muchTrackIndex >= fInputMuchTracks->GetEntriesFast()) {
304 LOG(error) << "CbmKfTrackFitter: Much track index " << muchTrackIndex << " is out of range!";
305 return false;
306 }
307 auto* track = dynamic_cast<const CbmMuchTrack*>(fInputMuchTracks->At(muchTrackIndex));
308 if (!track) {
309 LOG(error) << "CbmKfTrackFitter: Much track is null!";
310 return false;
311 }
312 int nHits = track->GetNofHits();
313 if (nHits > 0) {
314 if (!fInputMuchHits) {
315 LOG(error) << "CbmKfTrackFitter: Much hit array not found!";
316 return false;
317 }
319 LOG(error) << "CbmKfTrackFitter: Much tracking interface not found!";
320 return false;
321 }
322 for (int ih = 0; ih < nHits; ih++) {
323 int hitIndex = track->GetHitIndex(ih);
324 if (hitIndex >= fInputMuchHits->GetEntriesFast()) {
325 LOG(error) << "CbmKfTrackFitter: Much hit index " << hitIndex << " is out of range!";
326 return false;
327 }
328 const auto& hit = *dynamic_cast<const CbmMuchPixelHit*>(fInputMuchHits->At(hitIndex));
329 setNode(hit, CbmMuchTrackingInterface::Instance()->GetTrackingStationIndex(&hit), hitIndex,
330 ca::EDetectorID::kMuch);
331 }
332 }
333 }
334
335 // Read TRD hits
336
337 if (globalTrack.GetTrdTrackIndex() >= 0) {
338 int trdTrackIndex = globalTrack.GetTrdTrackIndex();
339 if (!fInputTrdTracks) {
340 LOG(error) << "CbmKfTrackFitter: Trd track array not found!";
341 return false;
342 }
343 if (trdTrackIndex >= fInputTrdTracks->GetEntriesFast()) {
344 LOG(error) << "CbmKfTrackFitter: Trd track index " << trdTrackIndex << " is out of range!";
345 return false;
346 }
347 auto* track = dynamic_cast<const CbmTrdTrack*>(fInputTrdTracks->At(trdTrackIndex));
348 if (!track) {
349 LOG(error) << "CbmKfTrackFitter: Trd track is null!";
350 return false;
351 }
352 int nHits = track->GetNofHits();
353 if (nHits > 0) {
354 if (!fInputTrdHits) {
355 LOG(error) << "CbmKfTrackFitter: Trd hit array not found!";
356 return false;
357 }
359 LOG(error) << "CbmKfTrackFitter: Trd tracking interface not found!";
360 return false;
361 }
362 for (int ih = 0; ih < nHits; ih++) {
363 int hitIndex = track->GetHitIndex(ih);
364 if (hitIndex >= fInputTrdHits->GetEntriesFast()) {
365 LOG(error) << "CbmKfTrackFitter: Trd hit index " << hitIndex << " is out of range!";
366 return false;
367 }
368 const auto& hit = *dynamic_cast<const CbmTrdHit*>(fInputTrdHits->At(hitIndex));
369
370 auto* node = setNode(hit, CbmTrdTrackingInterface::Instance()->GetTrackingStationIndex(&hit), hitIndex,
371 ca::EDetectorID::kTrd);
372 if (node != nullptr && hit.GetClassType() == 1) {
373 node->fHitSystemId = ECbmModuleId::kTrd2d;
374 }
375 }
376 }
377 }
378
379
380 // Read TOF hits
381
382 if (globalTrack.GetTofTrackIndex() >= 0) {
383 int tofTrackIndex = globalTrack.GetTofTrackIndex();
384 if (!fInputTofTracks) {
385 LOG(error) << "CbmKfTrackFitter: Trd track array not found!";
386 return false;
387 }
388 if (tofTrackIndex >= fInputTofTracks->GetEntriesFast()) {
389 LOG(error) << "CbmKfTrackFitter: Trd track index " << tofTrackIndex << " is out of range!";
390 return false;
391 }
392 auto* track = dynamic_cast<const CbmTofTrack*>(fInputTofTracks->At(tofTrackIndex));
393 if (!track) {
394 LOG(error) << "CbmKfTrackFitter: Tof track is null!";
395 return false;
396 }
397
398 int nHits = track->GetNofHits();
399 if (nHits > 0) {
400 if (!fInputTofHits) {
401 LOG(error) << "CbmKfTrackFitter: Tof hit array not found!";
402 return false;
403 }
405 LOG(error) << "CbmKfTrackFitter: Tof tracking interface not found!";
406 return false;
407 }
408 for (int ih = 0; ih < nHits; ih++) {
409 int hitIndex = track->GetHitIndex(ih);
410 if (hitIndex >= fInputTofHits->GetEntriesFast()) {
411 LOG(error) << "CbmKfTrackFitter: Tof hit index " << hitIndex << " is out of range!";
412 return false;
413 }
414 const auto& hit = *dynamic_cast<const CbmTofHit*>(fInputTofHits->At(hitIndex));
415 setNode(hit, CbmTofTrackingInterface::Instance()->GetTrackingStationIndex(&hit), hitIndex,
416 ca::EDetectorID::kTof);
417 }
418 }
419 }
420
421 t.OrderNodesInZ();
422
423 kfTrack = t;
424 return true;
425
426 // return CreateTrack(kfTrack, *globalTrack.GetParamFirst(), mvdHits, stsHits, muchHits, trdHits, tofHits);
427}
428
429
431{
432 // a special routine to filter the first measurement.
433 // the measurement errors are simply copied to the track covariance matrix
434
435 assert(n.fIsXySet);
436
437 const auto& mxy = n.fMxy;
438 const auto& mt = n.fMt;
439
440 auto& tr = fFit.Tr();
441
442 if (fabs(tr.GetZ() - n.fZ) > 1.e-10) {
443 LOG(fatal) << "CbmKfTrackFitter: Z mismatch: fitted track " << tr.GetZ() << " != node " << n.fZ;
444 }
445
446 tr.ResetErrors(mxy.Dx2(), mxy.Dy2(), 100., 100., 10., 1.e4, 1.e2);
447 tr.SetC10(mxy.Dxy());
448 tr.SetX(mxy.X());
449 tr.SetY(mxy.Y());
450 tr.SetZ(n.fZ);
451
452 if (fSkipUnmeasuredCoordinates) { // TODO: take C10 correlation into account
453 if (mxy.NdfX() == 0) {
454 tr.SetX(n.fParamDn.GetX());
455 tr.SetC00(1.e4);
456 }
457 if (mxy.NdfY() == 0) {
458 tr.SetY(n.fParamDn.GetY());
459 tr.SetC11(1.e4);
460 tr.SetC10(0.);
461 }
462 }
463
464 tr.SetChiSq(0.);
465 tr.SetChiSqTime(0.);
466 tr.SetNdf(-5. + mxy.NdfX() + mxy.NdfY());
467 if (n.fIsTimeSet) {
468 tr.SetTime(mt.T());
469 tr.SetC55(mt.Dt2());
470 tr.SetNdfTime(-2 + 1);
471 }
472 else {
473 tr.SetNdfTime(-2);
474 }
476 tr.InitVelocityRange(0.5);
477}
478
479
481 kf::FitDirection direction)
482{
483 // add material effects
484 if (n.fMaterialLayer < 0) {
485 return;
486 }
487
488 double tx = 0.5 * (l.fParamDn.GetTx() + l.fParamUp.GetTx());
489 double ty = 0.5 * (l.fParamDn.GetTy() + l.fParamUp.GetTy());
490 double msQp = 0.5 * (l.fParamDn.GetQp() + l.fParamUp.GetQp());
491
492 if (fIsQpForMsFixed) {
493 msQp = fDefaultQpForMs;
494 }
495
496 // calculate the radiation thickness from the current track
497 if (!n.fIsRadThickFixed) {
498 const kf::MaterialMap& map = fKfSetup->GetMaterial(n.fMaterialLayer);
499 n.fRadThick = map.GetThicknessX0(l.fParamDn.GetX(), l.fParamDn.GetY());
500 }
501
502 fFit.MultipleScattering(n.fRadThick, tx, ty, msQp);
503
504 if (!fIsQpForMsFixed) {
505 if (direction == kf::FitDirection::kDownstream) {
507 }
508 else {
510 }
511 fFit.EnergyLossCorrection(n.fRadThick, direction);
512 }
513}
514
515
517{
518 // (re)fit the track
519 if (fVerbosityLevel > 0) {
520 std::cout << "FitTrajectory ... " << std::endl;
521 }
522 bool ok = true;
523
524 // ensure that the fitter is initialized
525 Init();
526
527 int nNodes = t.fNodes.size();
528
529 if (nNodes <= 0) {
530 LOG(warning) << "CbmKfTrackFitter: no nodes found!";
531 return false;
532 }
533
534 int firstHitNode = -1;
535 int lastHitNode = -1;
536 bool isOrdered = true;
537
538 { // find the first and the last hit nodes. Check if the nodes are ordered in Z
539 double zOld = -1.e10;
540 for (int i = 0; i < nNodes; i++) {
541 const auto& n = t.fNodes[i];
542 if (n.fIsXySet) {
543 if (firstHitNode < 0) {
544 firstHitNode = i;
545 }
546 lastHitNode = i;
547 }
548 if (n.fZ < zOld) {
549 isOrdered = false;
550 }
551 zOld = n.fZ;
552 }
553 }
554
555 if (firstHitNode < 0 || lastHitNode < 0) {
556 LOG(warning) << "CbmKfTrackFitter: no hit nodes found!";
557 return false;
558 }
559
560 if (!isOrdered) {
561 LOG(warning) << "CbmKfTrackFitter: track nodes are not ordered in Z!";
562 }
563
565
566 // kf::GlobalField::fgOriginalFieldType = kf::EFieldType::Null;
567
569
570 std::vector<LinearizationAtNode> linearization(nNodes);
571
572 if (t.fIsFitted) { // take the linearization from the previously fitted trajectory
573 for (int i = firstHitNode; i <= lastHitNode; i++) {
574 if (!t.fNodes[i].fIsFitted) {
575 LOG(fatal) << "CbmKfTrackFitter: node " << i << " in the measured region is not fitted";
576 }
577 linearization[i].fParamDn = t.fNodes[i].fParamDn;
578 linearization[i].fParamUp = t.fNodes[i].fParamUp;
579 }
580 }
581 else { // first approximation with straight line segments connecting the nodes
582 for (int i1 = firstHitNode, i2 = firstHitNode + 1; i2 <= lastHitNode; i2++) {
583 auto& n1 = t.fNodes[i1];
584 auto& n2 = t.fNodes[i2];
585 if (!n2.fIsXySet) {
586 continue;
587 }
588 double dz = n2.fZ - n1.fZ;
589 double dzi = (fabs(dz) > 1.e-4) ? 1. / dz : 0.;
590 double tx = (n2.fMxy.X() - n1.fMxy.X()) * dzi;
591 double ty = (n2.fMxy.Y() - n1.fMxy.Y()) * dzi;
592 for (int i = i1; i <= i2; i++) { // fill the nodes inbetween
593 auto& n = t.fNodes[i];
594 auto& l = linearization[i];
595 double x = n1.fMxy.X() + tx * (n.fZ - n1.fZ);
596 double y = n1.fMxy.Y() + ty * (n.fZ - n1.fZ);
597 if (i < i2
598 || i == lastHitNode) { // downstream parameters for i2 will be set later, except for the last hit node
599 l.fParamDn.SetX(x);
600 l.fParamDn.SetY(y);
601 l.fParamDn.SetZ(n.fZ);
602 l.fParamDn.SetTx(tx);
603 l.fParamDn.SetTy(ty);
604 l.fParamDn.SetQp(0.);
605 l.fParamDn.SetTime(0.);
607 }
608 if (i > i1 || i == firstHitNode) { // upstream parameters for i1 are already set, except for the first hit node
609 l.fParamUp.SetX(x);
610 l.fParamUp.SetY(y);
611 l.fParamUp.SetZ(n.fZ);
612 l.fParamUp.SetTx(tx);
613 l.fParamUp.SetTy(ty);
614 l.fParamUp.SetQp(0.);
615 l.fParamUp.SetTime(0.);
617 }
618 }
619 i1 = i2;
620 }
621 }
622
623 t.fIsFitted = false;
624 for (auto& n : t.fNodes) {
625 n.fIsFitted = false;
626 }
627
628 auto printNode = [&](std::string str, int node) {
629 if (fVerbosityLevel > 0) {
630 LOG(info) << str << ": node " << node << " chi2 " << fFit.Tr().GetChiSq() << " x " << fFit.Tr().GetX() << " y "
631 << fFit.Tr().GetY() << " z " << fFit.Tr().GetZ() << " tx " << fFit.Tr().GetTx() << " ty "
632 << fFit.Tr().GetTy();
633 }
634 };
635
636
637 { // fit downstream up to the last measurement
638
639 { // initialisation at the first measurement
640 TrajectoryNode& n = t.fNodes[firstHitNode];
641 assert(n.fIsXySet);
642 fFit.SetTrack(linearization[firstHitNode].fParamDn);
644 printNode("fit downstream", firstHitNode);
645 }
646
647 for (int iNode = firstHitNode + 1; iNode <= lastHitNode; iNode++) {
648
649 TrajectoryNode& n = t.fNodes[iNode];
650
651 // transport the partially fitted track to the current node
652 fFit.SetQp0(linearization[iNode - 1].fParamDn.GetQp());
653 fFit.Extrapolate(n.fZ, field);
654
655 // measure the track at the current node
656 if (n.fIsXySet) {
658 }
659 if (n.fIsTimeSet) {
661 }
662 printNode("fit downstream", iNode);
663
664 // store the partially fitted track before the scattering
665 n.fParamUp = fFit.Tr();
666
667 // add material effects
668 AddMaterialEffects(n, linearization[iNode], kf::FitDirection::kDownstream);
669
670 // store the partially fitted track after the scattering
671 n.fParamDn = fFit.Tr();
672 }
673 }
674
675 // store the chi2 for debugging purposes
676 double dnChi2 = fFit.Tr().GetChiSq();
677
678 { // fit upstream with the Kalman Filter smoothing
679
680 { // initialisation at the last measurement
681 TrajectoryNode& n = t.fNodes[lastHitNode];
682 assert(n.fIsXySet);
683 n.fIsFitted = true;
684 fFit.SetTrack(linearization[lastHitNode].fParamUp);
686 printNode("fit upstream", lastHitNode);
687 }
688
689 for (int iNode = lastHitNode - 1; ok && (iNode > firstHitNode); iNode--) {
690
691 TrajectoryNode& n = t.fNodes[iNode];
692
693 // transport the partially fitted track to the current node
694 fFit.SetQp0(linearization[iNode + 1].fParamUp.GetQp());
695 fFit.Extrapolate(n.fZ, field);
696
697 // combine partially fitted downstream and upstream tracks
698 ok = ok && Smooth(n.fParamDn, fFit.Tr());
699
700 AddMaterialEffects(n, linearization[iNode], kf::FitDirection::kUpstream);
701
702 // combine partially fitted downstream and upstream tracks
703 ok = ok && Smooth(n.fParamUp, fFit.Tr());
704
705 n.fIsFitted = true;
706
707 // measure the track at the current node
708 if (n.fIsXySet) {
710 }
711 if (n.fIsTimeSet) {
713 }
714 printNode("fit upstream", iNode);
715 }
716
717 if (!ok) {
718 return false;
719 }
720
721 if (ok) {
722 int iNode = firstHitNode;
723
724 TrajectoryNode& n = t.fNodes[iNode];
725
726 // transport the partially fitted track to the current node
727 fFit.SetQp0(linearization[iNode + 1].fParamUp.GetQp());
728 fFit.Extrapolate(n.fZ, field);
729
730 // measure the track at the current node
731 if (n.fIsXySet) {
733 }
734 if (n.fIsTimeSet) {
736 }
737 printNode("fit upstream", iNode);
738 n.fParamDn = fFit.Tr();
739
740 AddMaterialEffects(n, linearization[iNode], kf::FitDirection::kUpstream);
741
742 n.fParamUp = fFit.Tr();
743
744 n.fIsFitted = true;
745 }
746 }
747
748 if (ok) { // propagate downstream
749 fFit.SetTrack(t.fNodes[lastHitNode].fParamDn);
750 for (int i = lastHitNode + 1; i < nNodes; i++) {
751 auto& n = t.fNodes[i];
752 fFit.Extrapolate(n.fZ, field);
753 n.fParamDn = fFit.Tr();
755 l.fParamDn = fFit.Tr();
756 l.fParamUp = fFit.Tr();
757 AddMaterialEffects(n, l, kf::FitDirection::kDownstream);
758 n.fParamUp = fFit.Tr();
759 n.fIsFitted = true;
760 }
761 }
762
763 if (ok) { // propagate upstream
764 fFit.SetTrack(t.fNodes[firstHitNode].fParamUp);
765 for (int i = firstHitNode - 1; i >= 0; i--) {
766 auto& n = t.fNodes[i];
767 fFit.Extrapolate(n.fZ, field);
768 n.fParamUp = fFit.Tr();
770 l.fParamDn = fFit.Tr();
771 l.fParamUp = fFit.Tr();
772 AddMaterialEffects(n, l, kf::FitDirection::kUpstream);
773 n.fParamDn = fFit.Tr();
774 n.fIsFitted = true;
775 }
776 }
777
778 assert(ok);
779
780 if (!fDoSmooth) {
781 double upChi2 = fFit.Tr().GetChiSq();
782 if (fabs(upChi2 - dnChi2) > 1.e-1) {
783 //if (upChi2 > dnChi2 + 1.e-2) {
784 LOG(debug) << "CbmKfTrackFitter: " << fDebugInfo << ": chi2 mismatch: dn " << dnChi2 << " != up " << upChi2
785 << " first node " << firstHitNode << " last node " << lastHitNode << " of " << nNodes;
786 //if (fVerbosityLevel > 0) {
787 //exit(1);
788 //}
789 }
790 }
791 // distribute the final chi2, ndf to all nodes
792
793 const auto& tt = fFit.Tr();
794 for (int iNode = 0; iNode < nNodes; iNode++) {
795 TrajectoryNode& n = t.fNodes[iNode];
796 n.fParamDn.SetNdf(tt.GetNdf());
797 n.fParamDn.SetNdfTime(tt.GetNdfTime());
798 n.fParamDn.SetChiSq(tt.GetChiSq());
799 n.fParamDn.SetChiSqTime(tt.GetChiSqTime());
800 n.fParamUp.SetNdf(tt.GetNdf());
801 n.fParamUp.SetNdfTime(tt.GetNdfTime());
802 n.fParamUp.SetChiSq(tt.GetChiSq());
803 n.fParamUp.SetChiSqTime(tt.GetChiSqTime());
804 }
805
806 return ok;
807}
808
810{
811 // TODO: move to the CaTrackFit class
812
813 constexpr int nPar = kf::TrackParamV::kNtrackParam;
814 constexpr int nCov = kf::TrackParamV::kNcovParam;
815
816 double r[nPar] = {t1.X(), t1.Y(), t1.Tx(), t1.Ty(), t1.Qp(), t1.Time(), t1.Vi()};
817 double m[nPar] = {t2.X(), t2.Y(), t2.Tx(), t2.Ty(), t2.Qp(), t2.Time(), t2.Vi()};
818
819 double S[nCov], S1[nCov], Tmp[nCov];
820 for (int i = 0; i < nCov; i++) {
821 S[i] = (t1.GetCovMatrix()[i] + t2.GetCovMatrix()[i]);
822 }
823
824 int nullty = 0;
825 int ifault = 0;
826 cbm::algo::kf::utils::math::SymInv(S, nPar, S1, Tmp, &nullty, &ifault);
827
828 if ((0 != ifault) || (0 != nullty)) {
829 return false;
830 }
831
832 double dzeta[nPar];
833
834 for (int i = 0; i < nPar; i++) {
835 dzeta[i] = m[i] - r[i];
836 }
837
838 double C[nPar][nPar];
839 double Si[nPar][nPar];
840 for (int i = 0, k = 0; i < nPar; i++) {
841 for (int j = 0; j <= i; j++, k++) {
842 C[i][j] = t1.GetCovMatrix()[k];
843 Si[i][j] = S1[k];
844 C[j][i] = C[i][j];
845 Si[j][i] = Si[i][j];
846 }
847 }
848
849 // K = C * S^{-1}
850 double K[nPar][nPar];
851 for (int i = 0; i < nPar; i++) {
852 for (int j = 0; j < nPar; j++) {
853 K[i][j] = 0.;
854 for (int k = 0; k < nPar; k++) {
855 K[i][j] += C[i][k] * Si[k][j];
856 }
857 }
858 }
859
860 for (int i = 0, k = 0; i < nPar; i++) {
861 for (int j = 0; j <= i; j++, k++) {
862 double kc = 0.; // K*C[i][j]
863 for (int l = 0; l < nPar; l++) {
864 kc += K[i][l] * C[l][j];
865 }
866 t1.CovMatrix()[k] = t1.CovMatrix()[k] - kc;
867 }
868 }
869
870 for (int i = 0; i < nPar; i++) {
871 double kd = 0.;
872 for (int j = 0; j < nPar; j++) {
873 kd += K[i][j] * dzeta[j];
874 }
875 r[i] += kd;
876 }
877 t1.X() = r[0];
878 t1.Y() = r[1];
879 t1.Tx() = r[2];
880 t1.Ty() = r[3];
881 t1.Qp() = r[4];
882 t1.Time() = r[5];
883 t1.Vi() = r[6];
884
885 double chi2 = 0.;
886 double chi2Time = 0.;
887 for (int i = 0; i < nPar; i++) {
888 double SiDzeta = 0.;
889 for (int j = 0; j < nPar; j++) {
890 SiDzeta += Si[i][j] * dzeta[j];
891 }
892 if (i < 5) {
893 chi2 += dzeta[i] * SiDzeta;
894 }
895 else {
896 chi2Time += dzeta[i] * SiDzeta;
897 }
898 }
899 t1.SetChiSq(chi2 + t1.GetChiSq() + t2.GetChiSq());
900 t1.SetChiSqTime(chi2Time + t1.GetChiSqTime() + t2.GetChiSqTime());
901 t1.SetNdf(5 + t1.GetNdf() + t2.GetNdf());
902 t1.SetNdfTime(2 + t1.GetNdfTime() + t2.GetNdfTime());
903 return true;
904}
@ kNotExist
If not found.
@ kTrd2d
TRD-FASP Detector (FIXME)
Int_t nStsHits
Class for pixel hits in MUCH detector.
Data class for a reconstructed hit in the STS.
Data class for STS tracks.
Class for hits in TRD detector.
Common constant definitions for the Kalman Filter library.
Track fit utilities for the CA tracking based on the Kalman filter.
Generates beam ions for transport simulation.
int32_t GetStsTrackIndex() const
int32_t GetTofTrackIndex() const
int32_t GetMuchTrackIndex() const
void SetParamFirst(const FairTrackParam *parFirst)
int32_t GetTrdTrackIndex() const
void SetStsTrackIndex(int32_t iSts)
TClonesArray * fInputTofTracks
TClonesArray * fInputMuchTracks
cbm::algo::kf::TrackKalmanFilter< double > fFit
void SetElectronFlag(bool isElectron)
set electron flag (bremmstrallung will be applied)
TClonesArray * fInputMvdHits
bool CreateMvdStsTrack(Trajectory &kfTrack, int stsTrackIndex)
set the input data arrays
bool CreateGlobalTrack(Trajectory &kfTrack, int globalTrackIndex)
void SetMassHypothesis(double mass)
set particle mass
void FilterFirstMeasurement(const TrajectoryNode &n)
TClonesArray * fInputStsHits
bool FitTrajectory(CbmKfTrackFitter::Trajectory &t)
fit the track
bool Smooth(cbm::algo::kf::TrackParamD &t1, const cbm::algo::kf::TrackParamD &t2)
TClonesArray * fInputTrdHits
TClonesArray * fInputStsTracks
TClonesArray * fInputMuchHits
void AddMaterialEffects(TrajectoryNode &n, const LinearizationAtNode &l, cbm::algo::kf::FitDirection direction)
TClonesArray * fInputGlobalTracks
TClonesArray * fInputTofHits
std::shared_ptr< const cbm::algo::kf::Setup< double > > fKfSetup
TClonesArray * fInputTrdTracks
void SetParticleHypothesis(int pid)
set particle hypothesis (mass and electron flag) via particle PDG
static CbmMuchTrackingInterface * Instance()
Gets pointer to the instance of the CbmMuchTrackingInterface.
static CbmMvdTrackingInterface * Instance()
Gets pointer to the instance of the CbmMvdTrackingInterface.
data class for a reconstructed 3-d hit in the STS
Definition CbmStsHit.h:35
int32_t GetNofMvdHits() const
Definition CbmStsTrack.h:87
static CbmStsTrackingInterface * Instance()
Gets pointer to the instance of the CbmStsTrackingInterface class.
static CbmTofTrackingInterface * Instance()
Gets pointer to the instance of the CbmTofTrackingInterface.
virtual int32_t GetNofHits() const
Definition CbmTrack.h:58
data class for a reconstructed Energy-4D measurement in the TRD
Definition CbmTrdHit.h:40
static CbmTrdTrackingInterface * Instance()
Gets pointer to the instance of the CbmTrdTrackingInterface.
Magnetic field region, corresponding to a hit triplet.
static EFieldType fgOriginalFieldType
Global field type.
static FieldFn_t fgOriginalField
Global variable to store the fielf funciton (x,y,z)->(Bx,By,Bz)
A map of station thickness in units of radiation length (X0) to the specific point in XY plane.
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
void FilterXY(const kf::MeasurementXy< DataT > &m, bool skipUnmeasuredCoordinates=false)
filter the track with the XY measurement
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)
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 SetChiSqTime(T v)
Sets Chi-square of time measurements.
T Vi() const
Gets inverse velocity [ns/cm].
const CovMatrix_t & GetCovMatrix() const
Gets covariance matrix.
T GetTy() const
Gets slope along y-axis.
T GetZ() const
Gets z position [cm].
void ResetErrors(T c00, T c11, T c22, T c33, T c44, T c55, T c66)
Resets variances of track parameters and chi2, ndf values.
T Tx() const
Gets slope along x-axis.
void SetChiSq(T v)
Sets Chi-square of track fit model.
T X() const
Gets x position [cm].
T GetTx() const
Gets slope along x-axis.
void SetNdf(T v)
Sets NDF of track fit model.
T GetNdfTime() const
Gets NDF 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 GetNdf() const
Gets NDF of track fit model.
T Time() const
Gets time [ns].
T GetY() const
Gets y position [cm].
void SetNdfTime(T v)
Sets NDF of time measurements.
CovMatrix_t & CovMatrix()
Reference to covariance matrix.
T GetChiSq() const
Gets Chi-square of track fit model.
T Ty() const
Gets slope along y-axis.
T GetX() const
Gets x position [cm].
std::shared_ptr< const cbm::algo::kf::Setup< double > > GetSharedGeoSetup()
Gets a shared pointer to the geometry setup.
static TrackingSetupBuilder * Instance()
Instance access.
EDetectorID
Enumeration for the tracking detector subsystems in CBM-CA.
Definition CbmDefs.h:176
ECbmModuleId ToCbmModuleId(EDetectorID detID)
Conversion map from EDetectorID to ECbmModuleId.
Definition CbmDefs.cxx:108
constexpr auto SpeedOfLightInv
Inverse speed of light [ns/cm].
Definition KfDefs.h:107
void SymInv(const double a[], const int n, double c[], double w[], int *nullty, int *ifault)
Definition KfUtils.cxx:212
Hash for CbmL1LinkKey.
cbm::algo::kf::TrackParamD fParamUp
fitted track parameters upstream the node
cbm::algo::kf::TrackParamD fParamDn
fitted track parameters downstream the node
cbm::algo::kf::TrackParamD fParamUp
fitted track parameters upstream the node
double fZ
Z coordinate of the node.
bool fIsFitted
true if the track parameters at the node are fitted
cbm::algo::kf::MeasurementXy< double > fMxy
== Hit information ( if present )
int fHitIndex
hit index in the detector hit array
int fHitAddress
detector ID of the hit
ECbmModuleId fHitSystemId
== External references
cbm::algo::kf::TrackParamD fParamDn
fitted track parameters downstream the node
bool fIsRadThickFixed
true if the radiation thickness is fixed to the fRadThick value
cbm::algo::kf::MeasurementTime< double > fMt
time measurement at fZ
int fMaterialLayer
== Material information (if present)
bool fIsTimeSet
true if the time measurement is set
A trajectory to be fitted.
std::vector< TrajectoryNode > fNodes
nodes on the trajectory
bool fIsFitted
true if the trajectory is fitted