22#include <TGeoGlobalMagField.h>
38constexpr double TrackFinderOriginal::SDefaultChamberZ[10];
39constexpr double TrackFinderOriginal::SChamberThicknessInX0[10];
49 mTrackFitter.
setChamberResolution(trackerParam.chamberResolutionX, trackerParam.chamberResolutionY);
53 mChamberResolutionX2 = trackerParam.chamberResolutionX * trackerParam.chamberResolutionX;
54 mChamberResolutionY2 = trackerParam.chamberResolutionY * trackerParam.chamberResolutionY;
55 mBendingVertexDispersion2 = trackerParam.bendingVertexDispersion * trackerParam.bendingVertexDispersion;
56 mMaxChi2ForTracking = 2. * trackerParam.sigmaCutForTracking * trackerParam.sigmaCutForTracking;
57 mMaxChi2ForImprovement = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement;
61 double inverseBendingP = (SMinBendingMomentum > 0.) ? 1. / SMinBendingMomentum : 1.;
62 param.setInverseBendingMomentum(inverseBendingP);
63 for (
int iCh = 0; iCh < 10; ++iCh) {
72 mTrackFitter.
initField(l3Current, dipoleCurrent);
80 print(
"\n------------------ Start the original track finder ------------------");
81 for (
auto& clustersInCh : mClusters) {
87 for (
const auto& cluster :
clusters) {
88 mClusters[cluster.getChamberId()].emplace_back(&cluster);
97 print(
"\n--> Step 1: find track candidates\n");
98 auto tStart = std::chrono::high_resolution_clock::now();
99 findTrackCandidates();
100 auto tEnd = std::chrono::high_resolution_clock::now();
101 mTimeFindCandidates += tEnd - tStart;
103 tStart = std::chrono::high_resolution_clock::now();
104 findMoreTrackCandidates();
105 tEnd = std::chrono::high_resolution_clock::now();
106 mTimeFindMoreCandidates += tEnd - tStart;
108 mNCandidates += mTracks.size();
111 if (mTracks.empty()) {
116 print(
"\n--> Step 2: Follow track candidates\n");
117 tStart = std::chrono::high_resolution_clock::now();
118 followTracks(mTracks.begin(), mTracks.end(), 2);
119 tEnd = std::chrono::high_resolution_clock::now();
120 mTimeFollowTracks += tEnd - tStart;
122 }
catch (exception
const& e) {
123 LOG(warning) << e.what() <<
" --> abort";
129 auto tStart = std::chrono::high_resolution_clock::now();
130 if (completeTracks()) {
132 removeDuplicateTracks();
134 auto tEnd = std::chrono::high_resolution_clock::now();
135 mTimeCompleteTracks += tEnd - tStart;
136 print(
"Currently ", mTracks.size(),
" candidates");
140 tStart = std::chrono::high_resolution_clock::now();
142 tEnd = std::chrono::high_resolution_clock::now();
143 mTimeImproveTracks += tEnd - tStart;
144 print(
"Currently ", mTracks.size(),
" candidates");
148 tStart = std::chrono::high_resolution_clock::now();
149 removeConnectedTracks(3, 4);
150 removeConnectedTracks(2, 2);
151 tEnd = std::chrono::high_resolution_clock::now();
152 mTimeCleanTracks += tEnd - tStart;
156 tStart = std::chrono::high_resolution_clock::now();
159 tEnd = std::chrono::high_resolution_clock::now();
160 mTimeRefineTracks += tEnd - tStart;
170void TrackFinderOriginal::findTrackCandidates()
175 for (
int iSt = 4; iSt >= 3; --iSt) {
178 auto itTrack = findTrackCandidates(2 * iSt, 2 * iSt + 1);
180 for (; itTrack != mTracks.end();) {
183 auto itNewTrack = followTrackInStation(itTrack, 7 - iSt);
184 print(
"new candidates starting at position #", getTrackIndex(itNewTrack));
190 print(
"Removing original candidate now at position #", getTrackIndex(itTrack));
191 printTrackParam(itTrack->first());
192 itTrack = mTracks.erase(itTrack);
196 print(
"Currently ", mTracks.size(),
" candidates");
201 removeDuplicateTracks();
204 print(
"Refitting tracks");
205 auto itTrack(mTracks.begin());
206 while (itTrack != mTracks.end()) {
210 mTrackFitter.
fit(*itTrack,
false);
213 if (!isAcceptable(itTrack->first())) {
214 print(
"Removing candidate at position #", getTrackIndex(itTrack));
215 itTrack = mTracks.erase(itTrack);
219 }
catch (exception
const&) {
220 print(
"Removing candidate at position #", getTrackIndex(itTrack));
221 itTrack = mTracks.erase(itTrack);
225 print(
"Currently ", mTracks.size(),
" candidates");
230void TrackFinderOriginal::findMoreTrackCandidates()
237 auto itCurrentTrack = mTracks.empty() ? mTracks.end() : std::prev(mTracks.end());
239 for (
int iCh1 = 6; iCh1 <= 7; ++iCh1) {
241 for (
int iCh2 = 8; iCh2 <= 9; ++iCh2) {
244 auto itTrack = findTrackCandidates(iCh1, iCh2,
true);
246 for (; itTrack != mTracks.end();) {
249 auto itNewTrack = followLinearTrackInChamber(itTrack, 17 - iCh2);
250 print(
"new candidates starting at position #", getTrackIndex(itNewTrack));
253 if (itNewTrack == mTracks.end()) {
254 itNewTrack = itTrack;
257 print(
"Removing original candidate now at position #", getTrackIndex(itTrack));
258 printTrackParam(itTrack->first());
259 itTrack = mTracks.erase(itTrack);
262 for (; itNewTrack != itTrack;) {
265 auto itNewNewTrack = followLinearTrackInChamber(itNewTrack, 13 - iCh1);
266 print(
"new candidates starting at position #", getTrackIndex(itNewNewTrack));
269 if (itNewNewTrack == mTracks.end()) {
272 print(
"Removing original candidate now at position #", getTrackIndex(itNewTrack));
273 printTrackParam(itTrack->first());
274 itNewTrack = mTracks.erase(itNewTrack);
279 print(
"Currently ", mTracks.size(),
" candidates");
283 print(
"Refitting tracks");
284 itCurrentTrack = (itCurrentTrack == mTracks.end()) ? mTracks.begin() : ++itCurrentTrack;
285 while (itCurrentTrack != mTracks.end()) {
289 mTrackFitter.
fit(*itCurrentTrack,
false);
292 if (!isAcceptable(itCurrentTrack->first())) {
293 print(
"Removing candidate at position #", getTrackIndex(itCurrentTrack));
294 itCurrentTrack = mTracks.erase(itCurrentTrack);
298 }
catch (exception
const&) {
299 print(
"Removing candidate at position #", getTrackIndex(itCurrentTrack));
300 itCurrentTrack = mTracks.erase(itCurrentTrack);
304 print(
"Currently ", mTracks.size(),
" candidates");
309std::list<Track>::iterator TrackFinderOriginal::findTrackCandidates(
int ch1,
int ch2,
bool skipUsedPairs)
316 print(
"Looking for candidates between chamber ", ch1,
" and ", ch2);
321 double impactMCS2(0.);
322 for (
int iCh = 0; iCh <= ch1; ++iCh) {
323 impactMCS2 += SDefaultChamberZ[iCh] * SDefaultChamberZ[iCh] * mMaxMCSAngle2[iCh];
327 auto itTrack = mTracks.empty() ? mTracks.end() : std::prev(mTracks.end());
329 for (
const auto cluster1 : mClusters.at(ch1)) {
331 double z1 = cluster1->getZ();
333 for (
const auto cluster2 : mClusters.at(ch2)) {
336 if (skipUsedPairs && areUsed(*cluster1, *cluster2)) {
340 double z2 = cluster2->getZ();
344 double nonBendingSlope = (cluster1->getX() - cluster2->getX()) / dZ;
345 double nonBendingImpactParam = TMath::Abs(cluster1->getX() - cluster1->getZ() * nonBendingSlope);
346 double nonBendingImpactParamErr = TMath::Sqrt((z1 * z1 * mChamberResolutionX2 + z2 * z2 * mChamberResolutionX2) / dZ / dZ + impactMCS2);
347 if ((nonBendingImpactParam - trackerParam.sigmaCutForTracking * nonBendingImpactParamErr) > (3. * trackerParam.nonBendingVertexDispersion)) {
351 double bendingSlope = (cluster1->getY() - cluster2->getY()) / dZ;
354 double bendingImpactParam = cluster1->getY() - cluster1->getZ() * bendingSlope;
355 double bendingImpactParamErr2 = (
z1 *
z1 * mChamberResolutionY2 +
z2 *
z2 * mChamberResolutionY2) / dZ / dZ + impactMCS2;
357 double bendingMomentumErr = TMath::Sqrt((mBendingVertexDispersion2 + bendingImpactParamErr2) / bendingImpactParam / bendingImpactParam + 0.01) * bendingMomentum;
358 if ((bendingMomentum + 3. * bendingMomentumErr) < SMinBendingMomentum) {
363 double bendingImpactParam = TMath::Abs(cluster1->getY() - cluster1->getZ() * bendingSlope);
364 double bendingImpactParamErr = TMath::Sqrt((z1 * z1 * mChamberResolutionY2 + z2 * z2 * mChamberResolutionY2) / dZ / dZ + impactMCS2);
365 if ((bendingImpactParam - trackerParam.sigmaCutForTracking * bendingImpactParamErr) > (3. * trackerParam.bendingVertexDispersion)) {
371 createTrack(*cluster1, *cluster2);
375 print(
"Currently ", mTracks.size(),
" candidates");
377 return (itTrack == mTracks.end()) ? mTracks.begin() : ++itTrack;
381bool TrackFinderOriginal::areUsed(
const Cluster& cl1,
const Cluster& cl2)
385 for (
const auto& track : mTracks) {
387 bool cl1Used(
false), cl2Used(
false);
389 for (
auto itParam = track.rbegin(); itParam != track.rend(); ++itParam) {
391 if (itParam->getClusterPtr() == &cl1) {
393 }
else if (itParam->getClusterPtr() == &cl2) {
397 if (cl1Used && cl2Used) {
407void TrackFinderOriginal::createTrack(
const Cluster& cl1,
const Cluster& cl2)
415 throw length_error(
string(
"Too many track candidates (") + mTracks.size() +
")");
418 print(
"Creating a new candidate");
421 mTracks.emplace_back();
422 TrackParam& param2 = mTracks.back().createParamAtCluster(cl2);
423 TrackParam& param1 = mTracks.back().createParamAtCluster(cl1);
426 double dZ = cl1.getZ() - cl2.getZ();
427 double nonBendingSlope = (cl1.getX() - cl2.getX()) / dZ;
428 double bendingSlope = (cl1.getY() - cl2.getY()) / dZ;
429 double bendingImpact = cl1.getY() - cl1.getZ() * bendingSlope;
433 param1.setNonBendingCoor(cl1.getX());
434 param1.setNonBendingSlope(nonBendingSlope);
435 param1.setBendingCoor(cl1.getY());
436 param1.setBendingSlope(bendingSlope);
437 param1.setInverseBendingMomentum(inverseBendingMomentum);
440 param2.setNonBendingCoor(cl2.getX());
441 param2.setNonBendingSlope(nonBendingSlope);
442 param2.setBendingCoor(cl2.getY());
443 param2.setBendingSlope(bendingSlope);
444 param2.setInverseBendingMomentum(inverseBendingMomentum);
447 TMatrixD paramCov(5, 5);
450 double cl1Ex2 = mChamberResolutionX2;
451 double cl2Ex2 = mChamberResolutionX2;
452 paramCov(0, 0) = cl1Ex2;
453 paramCov(0, 1) = cl1Ex2 / dZ;
454 paramCov(1, 0) = paramCov(0, 1);
455 paramCov(1, 1) = (cl1Ex2 + cl2Ex2) / dZ / dZ;
457 double cl1Ey2 = mChamberResolutionY2;
458 double cl2Ey2 = mChamberResolutionY2;
459 paramCov(2, 2) = cl1Ey2;
460 paramCov(2, 3) = cl1Ey2 / dZ;
461 paramCov(3, 2) = paramCov(2, 3);
462 paramCov(3, 3) = (cl1Ey2 + cl2Ey2) / dZ / dZ;
465 paramCov(4, 4) = ((mBendingVertexDispersion2 +
466 (cl1.getZ() * cl1.getZ() * cl2Ey2 + cl2.getZ() * cl2.getZ() * cl1Ey2) / dZ / dZ) /
467 bendingImpact / bendingImpact +
469 inverseBendingMomentum * inverseBendingMomentum;
470 paramCov(2, 4) = -cl2.getZ() * cl1Ey2 * inverseBendingMomentum / bendingImpact / dZ;
471 paramCov(4, 2) = paramCov(2, 4);
472 paramCov(3, 4) = -(cl1.getZ() * cl2Ey2 + cl2.getZ() * cl1Ey2) * inverseBendingMomentum / bendingImpact / dZ / dZ;
473 paramCov(4, 3) = paramCov(3, 4);
475 paramCov(4, 4) = inverseBendingMomentum * inverseBendingMomentum;
477 param1.setCovariances(paramCov);
481 paramCov(0, 0) = cl2Ex2;
482 paramCov(0, 1) = -cl2Ex2 / dZ;
483 paramCov(1, 0) = paramCov(0, 1);
485 paramCov(2, 2) = cl2Ey2;
486 paramCov(2, 3) = -cl2Ey2 / dZ;
487 paramCov(3, 2) = paramCov(2, 3);
490 paramCov(2, 4) = cl1.getZ() * cl2Ey2 * inverseBendingMomentum / bendingImpact / dZ;
491 paramCov(4, 2) = paramCov(2, 4);
493 param2.setCovariances(paramCov);
495 printTrackParam(param1);
499std::list<Track>::iterator TrackFinderOriginal::addTrack(
const std::list<Track>::iterator&
pos,
const Track& track)
505 throw length_error(
string(
"Too many track candidates (") + mTracks.size() +
")");
507 return mTracks.emplace(
pos, track);
511bool TrackFinderOriginal::isAcceptable(
const TrackParam&
param)
const
516 const TMatrixD& paramCov =
param.getCovariances();
521 double impactMCS2(0.);
524 for (
int iCh = 0; iCh <=
chamber; ++iCh) {
529 for (Int_t iCh = 0; iCh <=
chamber; ++iCh) {
530 impactMCS2 += SDefaultChamberZ[iCh] * SDefaultChamberZ[iCh] * mMaxMCSAngle2[iCh];
535 double nonBendingImpactParam = TMath::Abs(
param.getNonBendingCoor() -
z *
param.getNonBendingSlope());
536 double nonBendingImpactParamErr = TMath::Sqrt(paramCov(0, 0) +
z *
z * paramCov(1, 1) - 2. *
z * paramCov(0, 1) + impactMCS2);
537 if ((nonBendingImpactParam - trackerParam.sigmaCutForTracking * nonBendingImpactParamErr) > (3. * trackerParam.nonBendingVertexDispersion)) {
543 double bendingMomentum = TMath::Abs(1. /
param.getInverseBendingMomentum());
544 double bendingMomentumErr = TMath::Sqrt(paramCov(4, 4)) * bendingMomentum * bendingMomentum;
545 if (chamber < 6 && (bendingMomentum + trackerParam.sigmaCutForTracking * bendingMomentumErr) < SMinBendingMomentum) {
547 }
else if ((bendingMomentum + 3. * bendingMomentumErr) < SMinBendingMomentum) {
552 double bendingImpactParam = TMath::Abs(
param.getBendingCoor() -
z *
param.getBendingSlope());
553 double bendingImpactParamErr = TMath::Sqrt(paramCov(2, 2) +
z *
z * paramCov(3, 3) - 2. *
z * paramCov(2, 3) + impactMCS2);
554 if ((bendingImpactParam - trackerParam.sigmaCutForTracking * bendingImpactParamErr) > (3. * trackerParam.bendingVertexDispersion)) {
563void TrackFinderOriginal::removeDuplicateTracks()
568 print(
"Remove duplicated tracks");
570 for (
auto itTrack1 = mTracks.begin(); itTrack1 != mTracks.end();) {
572 int nClusters1 = itTrack1->getNClusters();
573 bool track1Removed(
false);
575 for (
auto itTrack2 = std::next(itTrack1); itTrack2 != mTracks.end();) {
577 int nClusters2 = itTrack2->getNClusters();
578 int nClustersInCommon = itTrack2->getNClustersInCommon(*itTrack1);
580 if (nClustersInCommon == nClusters2) {
581 print(
"Removing candidate at position #", getTrackIndex(itTrack2));
582 itTrack2 = mTracks.erase(itTrack2);
583 }
else if (nClustersInCommon == nClusters1) {
584 print(
"Removing candidate at position #", getTrackIndex(itTrack1));
585 itTrack1 = mTracks.erase(itTrack1);
586 track1Removed =
true;
593 if (!track1Removed) {
598 print(
"Currently ", mTracks.size(),
" candidates");
602void TrackFinderOriginal::removeConnectedTracks(
int stMin,
int stMax)
608 print(
"Remove connected tracks in stations [", stMin,
", ", stMax,
"]");
611 for (
auto itTrack1 = mTracks.begin(); itTrack1 != mTracks.end(); ++itTrack1) {
612 for (
auto itTrack2 = std::next(itTrack1); itTrack2 != mTracks.end(); ++itTrack2) {
613 if (itTrack2->getNClustersInCommon(*itTrack1, stMin, stMax) > 0) {
614 if (itTrack2->isBetter(*itTrack1)) {
615 itTrack1->connected();
617 itTrack2->connected();
624 for (
auto itTrack = mTracks.begin(); itTrack != mTracks.end();) {
625 if (itTrack->isConnected()) {
626 print(
"Removing candidate at position #", getTrackIndex(itTrack));
627 itTrack = mTracks.erase(itTrack);
633 print(
"Currently ", mTracks.size(),
" candidates");
637void TrackFinderOriginal::followTracks(
const std::list<Track>::iterator& itTrackBegin,
638 const std::list<Track>::iterator& itTrackEnd,
int nextStation)
645 print(
"Follow track candidates #", getTrackIndex(itTrackBegin),
" to #", getTrackIndex(std::prev(itTrackEnd)),
" in station ", nextStation);
647 for (
auto itTrack = itTrackBegin; itTrack != itTrackEnd;) {
650 auto itNewTrack = followTrackInStation(itTrack, nextStation);
653 if (itNewTrack == mTracks.end()) {
657 print(
"Duplicate original candidate");
658 itTrack = addTrack(itTrack, *itTrack);
662 itNewTrack = recoverTrack(itTrack, nextStation);
665 print(
"Removing original candidate or its copy at position #", getTrackIndex(itTrack));
666 printTrackParam(itTrack->first());
667 itTrack = mTracks.erase(itTrack);
671 if (itNewTrack == mTracks.end()) {
672 itNewTrack = itTrack;
680 print(
"Removing original candidate now at position #", getTrackIndex(itTrack));
681 printTrackParam(itTrack->first());
682 itTrack = mTracks.erase(itTrack);
685 print(
"Currently ", mTracks.size(),
" candidates");
689 if (itNewTrack != mTracks.end() && nextStation != 0) {
690 followTracks(itNewTrack, itTrack, nextStation - 1);
696std::list<Track>::iterator TrackFinderOriginal::followTrackInStation(
const std::list<Track>::iterator& itTrack,
int nextStation)
703 print(
"Follow track candidate #", getTrackIndex(itTrack),
" in station ", nextStation);
704 printTrackParam(itTrack->first());
706 auto itNewTrack(itTrack);
707 TrackParam extrapTrackParamAtCluster1{};
708 TrackParam extrapTrackParamAtCluster2{};
709 TrackParam extrapTrackParam{};
715 if (nextStation == 4) {
716 ch1 = 2 * nextStation + 1;
717 ch2 = 2 * nextStation;
719 ch1 = 2 * nextStation;
720 ch2 = 2 * nextStation + 1;
724 TrackParam extrapTrackParamAtCh = (nextStation == 4) ? itTrack->last() : itTrack->first();
727 int currentChamber(extrapTrackParamAtCh.getClusterPtr()->getChamberId());
732 extrapTrackParamAtCh.resetPropagator();
736 while (ch1 < ch2 && currentChamber > ch2 + 1) {
740 return mTracks.end();
747 return mTracks.end();
751 std::vector<bool> clusterCh1Used(mClusters.at(ch1).size(),
false);
754 for (
const auto clusterCh2 : mClusters.at(ch2)) {
757 if (!tryOneClusterFast(extrapTrackParamAtCh, *clusterCh2)) {
762 if (tryOneCluster(extrapTrackParamAtCh, *clusterCh2, extrapTrackParamAtCluster2,
769 extrapTrackParamAtCluster2.setExtrapParameters(extrapTrackParamAtCluster2.getParameters());
770 extrapTrackParamAtCluster2.setExtrapCovariances(extrapTrackParamAtCluster2.getCovariances());
776 }
catch (exception
const&) {
781 if (!isAcceptable(extrapTrackParamAtCluster2)) {
786 extrapTrackParam = extrapTrackParamAtCluster2;
791 extrapTrackParam.resetPropagator();
795 bool foundSecondCluster(
false);
800 for (
const auto clusterCh1 : mClusters.at(ch1)) {
805 if (!tryOneClusterFast(extrapTrackParam, *clusterCh1)) {
810 if (tryOneCluster(extrapTrackParam, *clusterCh1, extrapTrackParamAtCluster1,
817 extrapTrackParamAtCluster1.setExtrapParameters(extrapTrackParamAtCluster1.getParameters());
818 extrapTrackParamAtCluster1.setExtrapCovariances(extrapTrackParamAtCluster1.getCovariances());
824 }
catch (exception
const&) {
829 if (!isAcceptable(extrapTrackParamAtCluster1)) {
834 print(
"Duplicate the candidate");
835 itNewTrack = addTrack(itNewTrack, *itTrack);
836 updateTrack(*itNewTrack, extrapTrackParamAtCluster1, extrapTrackParamAtCluster2);
839 clusterCh1Used[iCluster1] =
true;
840 foundSecondCluster =
true;
845 if (!foundSecondCluster) {
846 print(
"Duplicate the candidate");
847 itNewTrack = addTrack(itNewTrack, *itTrack);
848 updateTrack(*itNewTrack, extrapTrackParamAtCluster2);
857 return (itNewTrack == itTrack) ? mTracks.end() : itNewTrack;
862 for (
const auto clusterCh1 : mClusters.at(ch1)) {
865 if (clusterCh1Used[iCluster1]) {
870 if (!tryOneClusterFast(extrapTrackParamAtCh, *clusterCh1)) {
875 if (tryOneCluster(extrapTrackParamAtCh, *clusterCh1, extrapTrackParamAtCluster1,
882 extrapTrackParamAtCluster1.setExtrapParameters(extrapTrackParamAtCluster1.getParameters());
883 extrapTrackParamAtCluster1.setExtrapCovariances(extrapTrackParamAtCluster1.getCovariances());
889 }
catch (exception
const&) {
894 if (!isAcceptable(extrapTrackParamAtCluster1)) {
899 print(
"Duplicate the candidate");
900 itNewTrack = addTrack(itNewTrack, *itTrack);
901 updateTrack(*itNewTrack, extrapTrackParamAtCluster1);
904 return (itNewTrack == itTrack) ? mTracks.end() : itNewTrack;
908std::list<Track>::iterator TrackFinderOriginal::followLinearTrackInChamber(
const std::list<Track>::iterator& itTrack,
int nextChamber)
916 print(
"Follow track candidate #", getTrackIndex(itTrack),
" in chamber ", nextChamber);
917 printTrackParam(itTrack->first());
919 auto itNewTrack(itTrack);
920 TrackParam extrapTrackParamAtCluster{};
923 TrackParam trackParam = (nextChamber > 7) ? itTrack->last() : itTrack->first();
929 for (
const auto cluster : mClusters.at(nextChamber)) {
932 if (!tryOneClusterFast(trackParam, *cluster)) {
937 extrapTrackParamAtCluster = trackParam;
941 if (tryOneCluster(extrapTrackParamAtCluster, *cluster, extrapTrackParamAtCluster,
false) >= mMaxChi2ForTracking) {
946 print(
"Duplicate the candidate");
947 itNewTrack = addTrack(itNewTrack, *itTrack);
948 updateTrack(*itNewTrack, extrapTrackParamAtCluster);
951 return (itNewTrack == itTrack) ? mTracks.end() : itNewTrack;
955bool TrackFinderOriginal::tryOneClusterFast(
const TrackParam&
param,
const Cluster& cluster)
962 ++mNCallTryOneClusterFast;
964 double dZ = cluster.getZ() -
param.getZ();
965 double dX = cluster.getX() - (
param.getNonBendingCoor() +
param.getNonBendingSlope() * dZ);
966 double dY = cluster.getY() - (
param.getBendingCoor() +
param.getBendingSlope() * dZ);
967 const TMatrixD& paramCov =
param.getCovariances();
968 double errX2 = paramCov(0, 0) + dZ * dZ * paramCov(1, 1) + 2. * dZ * paramCov(0, 1) + mChamberResolutionX2;
969 double errY2 = paramCov(2, 2) + dZ * dZ * paramCov(3, 3) + 2. * dZ * paramCov(2, 3) + mChamberResolutionY2;
971 double dXmax =
TrackerParam::Instance().sigmaCutForTracking * TMath::Sqrt(2. * errX2) + SMaxNonBendingDistanceToTrack;
972 double dYmax =
TrackerParam::Instance().sigmaCutForTracking * TMath::Sqrt(2. * errY2) + SMaxBendingDistanceToTrack;
974 if (TMath::Abs(dX) > dXmax || TMath::Abs(dY) > dYmax) {
981double TrackFinderOriginal::tryOneCluster(
const TrackParam&
param,
const Cluster& cluster, TrackParam& paramAtCluster,
982 bool updatePropagator)
989 ++mNCallTryOneCluster;
992 paramAtCluster =
param;
993 paramAtCluster.setClusterPtr(&cluster);
999 double dX = cluster.getX() - paramAtCluster.getNonBendingCoor();
1000 double dY = cluster.getY() - paramAtCluster.getBendingCoor();
1003 const TMatrixD& paramCov = paramAtCluster.getCovariances();
1004 double sigmaX2 = paramCov(0, 0) + mChamberResolutionX2;
1005 double sigmaY2 = paramCov(2, 2) + mChamberResolutionY2;
1006 double covXY = paramCov(0, 2);
1007 double det = sigmaX2 * sigmaY2 - covXY * covXY;
1013 return (dX * dX * sigmaY2 + dY * dY * sigmaX2 - 2. * dX * dY * covXY) / det;
1017void TrackFinderOriginal::updateTrack(Track& track, TrackParam& trackParamAtCluster)
1023 trackParamAtCluster.setRemovable(
false);
1025 trackParamAtCluster.setRemovable(
true);
1029 trackParamAtCluster.setLocalChi2(0.);
1032 track.addParamAtCluster(trackParamAtCluster);
1036void TrackFinderOriginal::updateTrack(Track& track, TrackParam& trackParamAtCluster1, TrackParam& trackParamAtCluster2)
1042 trackParamAtCluster1.setRemovable(
true);
1043 trackParamAtCluster2.setRemovable(
true);
1046 const Cluster* cluster1(trackParamAtCluster1.getClusterPtr());
1047 double deltaX = trackParamAtCluster1.getNonBendingCoor() - cluster1->getX();
1048 double deltaY = trackParamAtCluster1.getBendingCoor() - cluster1->getY();
1049 double localChi2 = deltaX * deltaX / mChamberResolutionX2 + deltaY * deltaY / mChamberResolutionY2;
1050 trackParamAtCluster1.setLocalChi2(localChi2);
1053 const Cluster* cluster2(trackParamAtCluster2.getClusterPtr());
1054 TrackParam extrapTrackParamAtCluster2(trackParamAtCluster1);
1056 deltaX = extrapTrackParamAtCluster2.getNonBendingCoor() - cluster2->getX();
1057 deltaY = extrapTrackParamAtCluster2.getBendingCoor() - cluster2->getY();
1058 localChi2 = deltaX * deltaX / mChamberResolutionX2 + deltaY * deltaY / mChamberResolutionY2;
1059 trackParamAtCluster2.setLocalChi2(localChi2);
1062 track.addParamAtCluster(trackParamAtCluster2);
1063 track.addParamAtCluster(trackParamAtCluster1);
1067std::list<Track>::iterator TrackFinderOriginal::recoverTrack(std::list<Track>::iterator& itTrack,
int nextStation)
1075 if (nextStation > 1) {
1076 return mTracks.end();
1079 print(
"Try to recover the track candidate #", getTrackIndex(itTrack),
" in station ", nextStation);
1082 auto itWorstParam = itTrack->end();
1083 double worstLocalChi2(-1.);
1084 for (
auto itParam = itTrack->begin(); itParam != itTrack->end(); ++itParam) {
1087 if (itParam->getClusterPtr()->getChamberId() / 2 != nextStation + 1) {
1092 if (!itParam->isRemovable()) {
1093 return mTracks.end();
1098 itParam->setRemovable(
false);
1102 if (itParam->getLocalChi2() > worstLocalChi2) {
1103 worstLocalChi2 = itParam->getLocalChi2();
1104 itWorstParam = itParam;
1109 if (itWorstParam == itTrack->end()) {
1110 return mTracks.end();
1114 itTrack->removeParamAtCluster(itWorstParam);
1118 auto itParam = std::next(itTrack->begin());
1119 auto ritParam = std::make_reverse_iterator(++itParam);
1120 mTrackFitter.
fit(*itTrack,
false,
false, &ritParam);
1121 }
catch (exception
const&) {
1122 return mTracks.end();
1125 if (!isAcceptable(itTrack->first())) {
1126 return mTracks.end();
1130 return followTrackInStation(itTrack, nextStation);
1134bool TrackFinderOriginal::completeTracks()
1142 print(
"Complete tracks");
1144 bool completionOccurred(
false);
1145 TrackParam paramAtCluster{};
1146 TrackParam bestParamAtCluster{};
1148 for (
auto itTrack = mTracks.begin(); itTrack != mTracks.end();) {
1150 bool trackCompleted(
false);
1152 for (
auto itParam = itTrack->begin(), itPrevParam = itTrack->begin(); itParam != itTrack->end();) {
1155 auto itNextParam = std::next(itParam);
1158 TrackParam*
param = (itNextParam == itTrack->end()) ? &*itPrevParam : &*itParam;
1161 int deId = itParam->getClusterPtr()->getDEId();
1162 double bestChi2AtCluster = mTrackFitter.
getMaxChi2();
1163 for (
const auto cluster : mClusters.at(itParam->getClusterPtr()->getChamberId())) {
1166 if (cluster->getDEId() == deId) {
1171 if (!tryOneClusterFast(*itParam, *cluster)) {
1176 if (tryOneCluster(*
param, *cluster, paramAtCluster,
false) >= mMaxChi2ForTracking) {
1183 }
catch (exception
const&) {
1188 if (paramAtCluster.getTrackChi2() < bestChi2AtCluster) {
1189 bestChi2AtCluster = paramAtCluster.getTrackChi2();
1190 bestParamAtCluster = paramAtCluster;
1195 if (bestChi2AtCluster < mTrackFitter.
getMaxChi2()) {
1196 itParam->setRemovable(
true);
1197 bestParamAtCluster.setRemovable(
true);
1198 itTrack->addParamAtCluster(bestParamAtCluster);
1199 trackCompleted = kTRUE;
1200 completionOccurred = kTRUE;
1203 itPrevParam = itParam;
1204 itParam = itNextParam;
1208 if (trackCompleted) {
1210 mTrackFitter.
fit(*itTrack,
false);
1211 print(
"Candidate at position #", getTrackIndex(itTrack),
" completed");
1213 }
catch (exception
const&) {
1214 print(
"Removing candidate at position #", getTrackIndex(itTrack));
1215 itTrack = mTracks.erase(itTrack);
1222 return completionOccurred;
1226void TrackFinderOriginal::improveTracks()
1233 print(
"Improve tracks");
1237 LOG(error) <<
"Smoother disabled --> tracks cannot be improved";
1241 for (
auto itTrack = mTracks.begin(); itTrack != mTracks.end();) {
1243 bool removeTrack(
false);
1246 auto itStartingParam = std::prev(itTrack->rend());
1252 mTrackFitter.
fit(*itTrack,
true,
false, (itStartingParam == itTrack->rbegin()) ?
nullptr : &itStartingParam);
1253 }
catch (exception
const&) {
1259 itTrack->tagRemovableClusters(requestedStationMask(),
false);
1262 double worstLocalChi2(-1.);
1263 auto itWorstParam(itTrack->end());
1264 for (
auto itParam = itTrack->begin(); itParam != itTrack->end(); ++itParam) {
1265 if (itParam->getLocalChi2() > worstLocalChi2) {
1266 worstLocalChi2 = itParam->getLocalChi2();
1267 itWorstParam = itParam;
1272 if (worstLocalChi2 < mMaxChi2ForImprovement) {
1277 if (!itWorstParam->isRemovable()) {
1283 auto itNextParam = itTrack->removeParamAtCluster(itWorstParam);
1287 itStartingParam = itTrack->rbegin();
1288 auto itNextToNextParam = (itNextParam == itTrack->end()) ? itNextParam :
std::next(itNextParam);
1289 while (itNextToNextParam != itTrack->end()) {
1290 if (itNextToNextParam->getClusterPtr()->getChamberId() != itNextParam->getClusterPtr()->getChamberId()) {
1291 itStartingParam = std::make_reverse_iterator(++itNextParam);
1294 ++itNextToNextParam;
1300 print(
"Removing candidate at position #", getTrackIndex(itTrack));
1301 itTrack = mTracks.erase(itTrack);
1303 print(
"Candidate at position #", getTrackIndex(itTrack),
" is improved");
1310void TrackFinderOriginal::refineTracks()
1314 print(
"Refine tracks");
1316 for (
auto itTrack = mTracks.begin(); itTrack != mTracks.end();) {
1318 mTrackFitter.
fit(*itTrack,
false);
1320 }
catch (exception
const&) {
1321 print(
"Removing candidate at position #", getTrackIndex(itTrack));
1322 itTrack = mTracks.erase(itTrack);
1332void TrackFinderOriginal::finalize()
1336 print(
"Finalize tracks");
1340 LOG(error) <<
"Smoother disabled --> tracks cannot be finalized";
1344 for (
auto& track : mTracks) {
1345 for (
auto&
param : track) {
1346 param.setParameters(
param.getSmoothParameters());
1347 param.setCovariances(
param.getSmoothCovariances());
1353uint8_t TrackFinderOriginal::requestedStationMask()
const
1360 for (
int i = 0;
i < 5; ++
i) {
1370int TrackFinderOriginal::getTrackIndex(
const std::list<Track>::iterator& itCurrentTrack)
const
1377 if (mDebugLevel < 1) {
1381 if (itCurrentTrack == mTracks.end()) {
1386 for (
auto itTrack = mTracks.begin(); itTrack != itCurrentTrack; ++itTrack) {
1387 if (itTrack == mTracks.end()) {
1397void TrackFinderOriginal::printTracks()
const
1400 if (mDebugLevel > 1) {
1401 for (
const auto& track : mTracks) {
1408void TrackFinderOriginal::printTrackParam(
const TrackParam& trackParam)
const
1411 if (mDebugLevel > 1) {
1417template <
class... Args>
1418void TrackFinderOriginal::print(Args... args)
const
1421 if (mDebugLevel > 0) {
1422 (
cout << ... << args) <<
"\n";
1430 LOG(info) <<
"number of candidates tracked = " << mNCandidates;
1432 LOG(info) <<
"number of times tryOneClusterFast() is called = " << mNCallTryOneClusterFast;
1433 LOG(info) <<
"number of times tryOneCluster() is called = " << mNCallTryOneCluster;
1440 LOG(info) <<
"findTrackCandidates duration = " << mTimeFindCandidates.count() <<
" s";
1441 LOG(info) <<
"findMoreTrackCandidates duration = " << mTimeFindMoreCandidates.count() <<
" s";
1442 LOG(info) <<
"followTracks duration = " << mTimeFollowTracks.count() <<
" s";
1443 LOG(info) <<
"completeTracks duration = " << mTimeCompleteTracks.count() <<
" s";
1444 LOG(info) <<
"improveTracks duration = " << mTimeImproveTracks.count() <<
" s";
1445 LOG(info) <<
"removeConnectedTracks duration = " << mTimeCleanTracks.count() <<
" s";
1446 LOG(info) <<
"refineTracks duration = " << mTimeRefineTracks.count() <<
" s";
definition of the MCH processing errors
Configurable parameters for MCH tracking.
Definition of the MagF class.
Definition of a class to reconstruct tracks with the original algorithm.
static const TrackerParam & Instance()
HMPID cluster implementation.
void add(ErrorType errorType, uint32_t id0, uint32_t id1, uint64_t n=1)
void initField(float l3Current, float dipoleCurrent)
const std::list< Track > & findTracks(gsl::span< const Cluster > clusters)
void setChamberResolution(double ex, double ey)
void useChamberResolution()
Use the chamber resolution instead of cluster resolution during the fit.
void initField(float l3Current, float dipoleCurrent)
void useClusterResolution()
Use the own resolution of each cluster during the fit (default)
void setBendingVertexDispersion(double ey)
Set the vertex dispersion in y direction used for the track covariance seed.
bool isSmootherEnabled()
Return the smoother enable/disable flag.
void smoothTracks(bool smooth)
Enable/disable the smoother (and the saving of related parameters)
static constexpr double getMaxChi2()
Return the maximum chi2 above which the track can be considered as abnormal.
void fit(Track &track, bool smooth=true, bool finalize=true, std::list< TrackParam >::reverse_iterator *itStartingParam=nullptr, bool skipLocalChi2Calculation=false)
void runKalmanFilter(TrackParam &trackParam)
track parameters for internal use
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t
float float float float float z2
float float float float z1
std::optional< Chamber > chamber(int chamberId)
@ Tracking_TooManyCandidates
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters