318 LOG(error) <<
"Initialization not yet done. Aborting...";
326 mNTPCOccBinLength = mTPCParam->rec.tpc.occupancyMapTimeBins;
327 mNTPCOccBinLengthInv = 1.f / mNTPCOccBinLength;
330 LOG(error) <<
"No ITS dictionary available";
336 auto pattIt = patterns.begin();
337 mITSClustersArray.clear();
338 mITSClustersArray.reserve(clusITS.size());
339 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}", clusITS.size(), patterns.size());
347 std::random_device
rd;
348 std::mt19937
g(
rd());
349 std::vector<uint32_t> trackIndices;
359 int nSeeds = mSeeds.size(), lastChecked = 0;
361 mParentID.resize(nSeeds, -1);
363 int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds;
364 mTrackData.reserve(maxOutputTracks);
365 mClRes.reserve(maxOutputTracks * param::NPadRows);
366 mDetInfoRes.reserve(maxOutputTracks * param::NPadRows);
367 bool maxTracksReached =
false;
368 for (
int iSeed = 0; iSeed < nSeeds; ++iSeed) {
369 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
370 LOG(info) <<
"Maximum number of tracks per TF reached. Skipping the remaining " << nSeeds - iSeed <<
" tracks.";
373 int seedIndex = trackIndices[iSeed];
378 this->mGIDs.push_back(this->mGIDtables[seedIndex][
src]);
380 this->mTrackTimes.push_back(this->mTrackTimes[seedIndex]);
381 this->mSeeds.push_back(this->mSeeds[seedIndex]);
382 this->mParentID.push_back(seedIndex);
383 this->mTrackPVID.push_back(this->mTrackPVID[seedIndex]);
387 if (!mSingleSourcesConfigured && !mSourcesConfiguredMap[mGIDs[seedIndex].getSource()]) {
394 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF) {
395 if (!maxTracksReached) {
396 LOGP(info,
"We already have reached mMaxTracksPerTF={}, but we continue to create seeds until mAddTracksForMapPerTF={} is also reached, iSeed: {} of {} inital seeds", mMaxTracksPerTF, mAddTracksForMapPerTF, iSeed, nSeeds);
398 maxTracksReached =
true;
403 LOGP(
debug,
"interpolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
414 LOGP(
debug,
"extrapolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
418 std::vector<int> remSeeds;
419 if (mSeeds.size() > ++lastChecked) {
420 remSeeds.resize(mSeeds.size() - lastChecked);
421 std::iota(remSeeds.begin(), remSeeds.end(), lastChecked);
422 std::shuffle(remSeeds.begin(), remSeeds.end(),
g);
423 LOGP(info,
"Up to {} tracks out of {} additional seeds will be processed in random order, of which {} are stripped versions, accepted seeds: {}", mAddTracksForMapPerTF, remSeeds.size(), mSeeds.size() - nSeeds, mTrackDataCompact.size());
425 int extraChecked = 0;
426 for (
int iSeed : remSeeds) {
427 if (mAddTracksForMapPerTF > 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
428 LOGP(info,
"Maximum number {} of additional tracks per TF reached. Skipping the remaining {} tracks", mAddTracksForMapPerTF, remSeeds.size() - extraChecked);
434 LOGP(
debug,
"extra check {} of {}, seed {} interpolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
436 LOGP(
debug,
"extra check {} of {}, seed {} extrapolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
440 LOG(info) <<
"Could process " << mTrackData.size() <<
" tracks successfully. " << mRejectedResiduals <<
" residuals were rejected. " << mClRes.size() <<
" residuals were accepted.";
441 mRejectedResiduals = 0;
446 LOGP(
debug,
"Starting track interpolation for GID {}", mGIDs[iSeed].
asString());
450 std::unique_ptr<TrackDataExtended> trackDataExtended;
451 std::vector<TPCClusterResiduals> clusterResiduals;
453 const auto& gidTable = mGIDtables[iSeed];
456 if (mDumpTrackPoints) {
457 trackDataExtended = std::make_unique<TrackDataExtended>();
458 (*trackDataExtended).gid = mGIDs[iSeed];
459 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
460 (*trackDataExtended).trkITS = trkITS;
461 (*trackDataExtended).trkTPC = trkTPC;
462 auto nCl = trkITS.getNumberOfClusters();
463 auto clEntry = trkITS.getFirstClusterEntry();
464 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
465 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
466 (*trackDataExtended).clsITS.push_back(clsITS);
472 trackData.
gid = mGIDs[iSeed];
473 trackData.
par = mSeeds[iSeed];
474 auto trkWork = mSeeds[iSeed];
477 for (
auto& elem : mCache) {
478 elem.clAvailable = 0;
480 trackData.
clIdx.setFirstEntry(mClRes.size());
481 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
485 std::array<short, constants::MAXGLOBALPADROW> multBins{};
486 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
488 uint32_t clusterIndexInRow;
489 const auto& clTPC = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
491 std::array<float, 2> clTPCYZ;
492 mFastTransform->TransformIdeal(sector,
row, clTPC.getPad(), clTPC.getTime(), clTPCX, clTPCYZ[0], clTPCYZ[1], clusterTimeBinOffset);
493 mCache[
row].clSec = sector;
494 mCache[
row].clAvailable = 1;
495 mCache[
row].clY = clTPCYZ[0];
496 mCache[
row].clZ = clTPCYZ[1];
498 mCacheDEDX[
row].first = clTPC.getQtot();
499 mCacheDEDX[
row].second = clTPC.getQmax();
500 int imb =
int(clTPC.getTime() * mNTPCOccBinLengthInv);
501 if (imb < mTPCParam->occupancyMapSize) {
502 multBins[
row] = 1 + std::max(0, imb);
507 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
508 if (!mCache[iRow].clAvailable) {
511 if (!trkWork.rotate(mCache[iRow].clAngle)) {
512 LOG(
debug) <<
"Failed to rotate track during first extrapolation";
515 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
516 LOG(
debug) <<
"Failed on first extrapolation";
519 mCache[iRow].y[
ExtOut] = trkWork.getY();
520 mCache[iRow].z[
ExtOut] = trkWork.getZ();
521 mCache[iRow].sy2[
ExtOut] = trkWork.getSigmaY2();
522 mCache[iRow].szy[
ExtOut] = trkWork.getSigmaZY();
523 mCache[iRow].sz2[
ExtOut] = trkWork.getSigmaZ2();
524 mCache[iRow].snp[
ExtOut] = trkWork.getSnp();
530 LOG(
debug) <<
"TOF point available";
532 if (mDumpTrackPoints) {
533 (*trackDataExtended).clsTOF = clTOF;
534 (*trackDataExtended).matchTOF = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
536 const int clTOFSec = clTOF.getCount();
538 if (!trkWork.rotate(clTOFAlpha)) {
539 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
542 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
543 if (!clTOF.isInNominalSector()) {
546 std::array<float, 2> clTOFYZ{clTOFxyz[1], clTOFxyz[2]};
548 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
549 LOG(
debug) <<
"Failed final propagation to TOF radius";
553 if (!trkWork.update(clTOFYZ, clTOFCov)) {
554 LOG(
debug) <<
"Failed to update extrapolated ITS track with TOF cluster";
562 if (mDumpTrackPoints) {
563 (*trackDataExtended).trkTRD = trkTRD;
566 std::array<float, 2> trkltTRDYZ{};
567 std::array<float, 3> trkltTRDCov{};
575 if (!trkWork.update(trkltTRDYZ, trkltTRDCov)) {
576 LOG(
debug) <<
"Failed to update track at TRD layer " << iLayer;
582 if (mDumpTrackPoints) {
583 (*trackDataExtended).trkOuter = trkWork;
585 auto trkOuter = trkWork;
588 bool outerParamStored =
false;
589 for (
int iRow = param::NPadRows; iRow--;) {
590 if (!mCache[iRow].clAvailable) {
593 if (mProcessSeeds && !outerParamStored) {
599 trackData.
par = trkWork;
600 outerParamStored =
true;
602 if (!trkWork.rotate(mCache[iRow].clAngle)) {
603 LOG(
debug) <<
"Failed to rotate track during back propagation";
606 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
607 LOG(
debug) <<
"Failed on back propagation";
611 mCache[iRow].y[
ExtIn] = trkWork.getY();
612 mCache[iRow].z[
ExtIn] = trkWork.getZ();
613 mCache[iRow].sy2[
ExtIn] = trkWork.getSigmaY2();
614 mCache[iRow].szy[
ExtIn] = trkWork.getSigmaZY();
615 mCache[iRow].sz2[
ExtIn] = trkWork.getSigmaZ2();
616 mCache[iRow].snp[
ExtIn] = trkWork.getSnp();
620 unsigned short deltaRow = 0;
621 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
622 if (!mCache[iRow].clAvailable) {
626 float wTotY = 1.f / mCache[iRow].sy2[
ExtOut] + 1.f / mCache[iRow].sy2[
ExtIn];
627 float wTotZ = 1.f / mCache[iRow].sz2[
ExtOut] + 1.f / mCache[iRow].sz2[
ExtIn];
628 mCache[iRow].y[
Int] = (mCache[iRow].y[
ExtOut] / mCache[iRow].sy2[
ExtOut] + mCache[iRow].y[
ExtIn] / mCache[iRow].sy2[
ExtIn]) / wTotY;
629 mCache[iRow].z[
Int] = (mCache[iRow].z[
ExtOut] / mCache[iRow].sz2[
ExtOut] + mCache[iRow].z[
ExtIn] / mCache[iRow].sz2[
ExtIn]) / wTotZ;
632 mCache[iRow].snp[
Int] = (mCache[iRow].snp[
ExtOut] + mCache[iRow].snp[
ExtIn]) / 2.f;
634 const auto dY = mCache[iRow].clY - mCache[iRow].y[
Int];
635 const auto dZ = mCache[iRow].clZ - mCache[iRow].z[
Int];
636 const auto y = mCache[iRow].y[
Int];
637 const auto z = mCache[iRow].z[
Int];
638 const auto snp = mCache[iRow].snp[
Int];
639 const auto sec = mCache[iRow].clSec;
640 clusterResiduals.emplace_back(dY, dZ,
y,
z, snp, sec, deltaRow);
645 trackData.
chi2TPC = trkTPC.getChi2();
646 trackData.
chi2ITS = trkITS.getChi2();
647 trackData.
nClsTPC = trkTPC.getNClusterReferences();
648 trackData.
nClsITS = trkITS.getNumberOfClusters();
651 double t0forTOF = 0.;
652 float t0forTOFwithinBC = 0.f;
653 float t0forTOFres = 9999.f;
656 const auto& tofMatch = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
660 t0forTOFres = tofMatch.getFT0BestRes();
661 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
666 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
671 int nClValidated = 0;
673 for (
unsigned int iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
674 iRow += clusterResiduals[iCl].dRow;
675 if (
params.flagRej[iCl]) {
679 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
680 const auto dy = clusterResiduals[iCl].dy;
681 const auto dz = clusterResiduals[iCl].dz;
682 const auto y = clusterResiduals[iCl].y;
683 const auto z = clusterResiduals[iCl].z;
684 const auto sec = clusterResiduals[iCl].sec;
685 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
686 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, sec);
687 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
690 ++mRejectedResiduals;
693 trackData.
clIdx.setEntries(nClValidated);
696 for (
int ist = 0; ist < NSTACKS; ist++) {
697 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
698 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
699 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
700 prevBin = multBins[
ir];
701 if (multBins[
ir] > mltBinMax) {
702 mltBinMax = multBins[
ir];
704 if (multBins[
ir] < mltBinMin) {
705 mltBinMin = multBins[
ir];
709 if (--mltBinMin >= 0) {
711 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
712 avMlt += mTPCParam->occupancyMap[ib];
714 avMlt /= (mltBinMax - mltBinMin);
719 bool stopPropagation = !mExtDetResid;
720 if (!stopPropagation) {
726 std::array<float, 2> trkltTRDYZ{};
727 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
732 stopPropagation =
true;
736 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
737 auto dy = trkltTRDYZ[0] - trkWork.getY();
738 auto dz = trkltTRDYZ[1] - trkWork.getZ();
739 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWork.getY()) < param::MaxY) && (std::abs(trkWork.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
741 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
748 while (gidTable[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
750 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
751 if (!clTOF.isInNominalSector()) {
755 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
756 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
757 stopPropagation =
true;
760 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
761 LOG(
debug) <<
"Failed final propagation to TOF radius";
765 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
766 auto dy = clTOFxyz[1] - trkWork.getY();
767 auto dz = clTOFxyz[2] - trkWork.getZ();
770 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWork.getY()) < param::MaxY) && (std::abs(trkWork.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
771 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
774 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
776 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
777 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
784 while (!stopPropagation) {
785 auto& trkWorkITS = trkInner;
786 auto nCl = trkITS.getNumberOfClusters();
787 auto clEntry = trkITS.getFirstClusterEntry();
789 for (
int iCl = 0; iCl < nCl; iCl++) {
790 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
791 int chip = cls.getSensorID();
792 float chipX, chipAlpha;
793 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
794 if (!trkWorkITS.rotate(chipAlpha) || !propagator->PropagateToXBxByBz(trkWorkITS, chipX, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
795 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
796 stopPropagation =
true;
799 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
800 auto dy = cls.getY() - trkWorkITS.getY();
801 auto dz = cls.getZ() - trkWorkITS.getZ();
802 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
803 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
804 mDetInfoRes.emplace_back();
808 if (!stopPropagation) {
811 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
812 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
813 stopPropagation =
true;
817 float sn, cs,
alpha = trkWorkITS.getAlpha();
818 math_utils::detail::bringToPMPi(
alpha);
819 math_utils::detail::sincos<float>(
alpha, sn, cs);
820 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
821 auto dy = yv - trkWorkITS.getY();
822 auto dz = zv - trkWorkITS.getZ();
823 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && abs(xv) < param::MaxVtxX) {
824 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
825 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
827 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
830 mDetInfoRes.emplace_back().setPV(tdif);
838 mGIDsSuccess.push_back(mGIDs[iSeed]);
839 mTrackDataCompact.emplace_back(trackData.
clIdx.getFirstEntry(), trackData.
multStack, nClValidated, mGIDs[iSeed].getSource(), trackData.
nExtDetResid);
840 mTrackData.push_back(std::move(trackData));
841 if (mDumpTrackPoints) {
842 (*trackDataExtended).clIdx.setEntries(nClValidated);
843 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
844 mTrackDataExtended.push_back(std::move(*trackDataExtended));
849 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
850 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
851 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
852 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
912 LOGP(
debug,
"Starting track extrapolation for GID {}", mGIDs[iSeed].
asString());
913 const auto& gidTable = mGIDtables[iSeed];
917 std::unique_ptr<TrackDataExtended> trackDataExtended;
918 std::vector<TPCClusterResiduals> clusterResiduals;
919 trackData.
clIdx.setFirstEntry(mClRes.size());
922 if (mDumpTrackPoints) {
923 trackDataExtended = std::make_unique<TrackDataExtended>();
924 (*trackDataExtended).gid = mGIDs[iSeed];
925 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
926 (*trackDataExtended).trkITS = trkITS;
927 (*trackDataExtended).trkTPC = trkTPC;
928 auto nCl = trkITS.getNumberOfClusters();
929 auto clEntry = trkITS.getFirstClusterEntry();
930 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
931 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
932 (*trackDataExtended).clsITS.push_back(clsITS);
938 trackData.
gid = mGIDs[iSeed];
939 trackData.
par = mSeeds[iSeed];
941 auto trkWork = mSeeds[iSeed];
942 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
944 unsigned short rowPrev = 0;
945 unsigned short nMeasurements = 0;
948 std::array<short, constants::MAXGLOBALPADROW> multBins{};
949 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
951 uint32_t clusterIndexInRow;
952 const auto& cl = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
953 if (clRowPrev ==
row) {
956 }
else if (clRowPrev < constants::MAXGLOBALPADROW && clRowPrev >
row) {
958 LOGP(
debug,
"TPC track with pT={} GeV and {} clusters has cluster {} on row {} while the previous cluster was on row {}",
959 mSeeds[iSeed].getPt(), trkTPC.getNClusterReferences(), iCl,
row, clRowPrev);
965 float x = 0,
y = 0,
z = 0;
966 mFastTransform->TransformIdeal(sector,
row, cl.getPad(), cl.getTime(),
x,
y,
z, clusterTimeBinOffset);
970 if (!propagator->PropagateToXBxByBz(trkWork,
x, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
974 const auto dY =
y - trkWork.getY();
975 const auto dZ =
z - trkWork.getZ();
976 const auto ty = trkWork.getY();
977 const auto tz = trkWork.getZ();
978 const auto snp = trkWork.getSnp();
979 const auto sec = sector;
980 clusterResiduals.emplace_back(dY, dZ, ty, tz, snp, sec,
row - rowPrev);
981 mCacheDEDX[
row].first = cl.getQtot();
982 mCacheDEDX[
row].second = cl.getQmax();
984 int imb =
int(cl.getTime() * mNTPCOccBinLengthInv);
985 if (imb < mTPCParam->occupancyMapSize) {
986 multBins[
row] = 1 + std::max(0, imb);
993 LOGP(warn,
"Extrapolated ITS-TPC track and found more residuals than possible ({})", clusterResiduals.size());
997 trackData.
chi2TPC = trkTPC.getChi2();
998 trackData.
chi2ITS = trkITS.getChi2();
999 trackData.
nClsTPC = trkTPC.getNClusterReferences();
1000 trackData.
nClsITS = trkITS.getNumberOfClusters();
1001 trackData.
clIdx.setEntries(nMeasurements);
1002 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
1003 if (mDumpTrackPoints) {
1004 (*trackDataExtended).trkOuter = trkWork;
1010 int nClValidated = 0, iRow = 0;
1011 unsigned int iCl = 0;
1012 for (iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
1013 iRow += clusterResiduals[iCl].dRow;
1014 if (iRow < param::NPadRows &&
params.flagRej[iCl]) {
1017 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
1018 const auto dy = clusterResiduals[iCl].dy;
1019 const auto dz = clusterResiduals[iCl].dz;
1020 const auto y = clusterResiduals[iCl].y;
1021 const auto z = clusterResiduals[iCl].z;
1022 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
1023 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, clusterResiduals[iCl].sec);
1024 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
1027 ++mRejectedResiduals;
1030 trackData.
clIdx.setEntries(nClValidated);
1033 for (
int ist = 0; ist < NSTACKS; ist++) {
1034 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
1035 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
1036 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
1037 prevBin = multBins[
ir];
1038 if (multBins[
ir] > mltBinMax) {
1039 mltBinMax = multBins[
ir];
1041 if (multBins[
ir] < mltBinMin) {
1042 mltBinMin = multBins[
ir];
1046 if (--mltBinMin >= 0) {
1048 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
1049 avMlt += mTPCParam->occupancyMap[ib];
1051 avMlt /= (mltBinMax - mltBinMin);
1056 bool stopPropagation = !mExtDetResid;
1057 if (!stopPropagation) {
1059 int iSeedFull = mParentID[iSeed] == -1 ? iSeed : mParentID[iSeed];
1060 auto gidFull = mGIDs[iSeedFull];
1061 const auto& gidTableFull = mGIDtables[iSeedFull];
1064 trackData.
nTrkltsTRD = trkTRD.getNtracklets();
1066 std::array<float, 2> trkltTRDYZ{};
1067 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
1072 stopPropagation =
true;
1076 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1077 auto dy = trkltTRDYZ[0] - trkWork.getY();
1078 auto dz = trkltTRDYZ[1] - trkWork.getZ();
1079 const auto sec = clusterResiduals[iCl].sec;
1080 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWork.getY()) < param::MaxY) && (std::abs(trkWork.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
1082 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
1090 while (gidTableFull[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
1091 const auto& tofMatch = mRecoCont->
getTOFMatch(gidFull);
1095 float t0forTOFres = tofMatch.getFT0BestRes();
1096 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
1097 trackData.
clAvailTOF = uint16_t(t0forTOFres);
1100 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
1101 if (!clTOF.isInNominalSector()) {
1104 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
1105 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
1106 stopPropagation =
true;
1109 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1110 LOG(
debug) <<
"Failed final propagation to TOF radius";
1114 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1115 auto dy = clTOFxyz[1] - trkWork.getY();
1116 auto dz = clTOFxyz[2] - trkWork.getZ();
1117 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWork.getY()) < param::MaxY) && (std::abs(trkWork.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
1118 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
1121 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1124 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
1125 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
1132 while (!stopPropagation) {
1134 auto nCl = trkITS.getNumberOfClusters();
1135 auto clEntry = trkITS.getFirstClusterEntry();
1137 for (
int iCl = 0; iCl < nCl; iCl++) {
1138 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
1139 int chip = cls.getSensorID();
1140 float chipX, chipAlpha;
1141 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
1142 if (!trkWorkITS.rotate(chipAlpha) || !propagator->propagateToX(trkWorkITS, chipX, mBz, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1143 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
1144 stopPropagation =
true;
1147 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
1148 auto dy = cls.getY() - trkWorkITS.getY();
1149 auto dz = cls.getZ() - trkWorkITS.getZ();
1150 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
1151 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
1152 mDetInfoRes.emplace_back();
1156 if (!stopPropagation) {
1159 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
1160 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
1161 stopPropagation =
true;
1165 float sn, cs,
alpha = trkWorkITS.getAlpha();
1166 math_utils::detail::bringToPMPi(
alpha);
1167 math_utils::detail::sincos<float>(
alpha, sn, cs);
1168 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
1169 auto dy = yv - trkWorkITS.getY();
1170 auto dz = zv - trkWorkITS.getZ();
1171 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && abs(xv) < param::MaxVtxX) {
1172 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
1173 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
1175 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1178 mDetInfoRes.emplace_back().setPV(tdif);
1185 mTrackData.push_back(std::move(trackData));
1186 mGIDsSuccess.push_back(mGIDs[iSeed]);
1187 mTrackDataCompact.emplace_back(trackData.
clIdx.getFirstEntry(), trackData.
multStack, nClValidated, mGIDs[iSeed].getSource(), trackData.
nExtDetResid);
1188 if (mDumpTrackPoints) {
1189 (*trackDataExtended).clIdx.setEntries(nClValidated);
1190 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
1191 mTrackDataExtended.push_back(std::move(*trackDataExtended));
1196 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
1197 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
1198 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
1199 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
1228 std::array<float, param::NPadRows> residHelixY;
1229 std::array<float, param::NPadRows> residHelixZ;
1231 std::array<float, param::NPadRows> xLab;
1232 std::array<float, param::NPadRows> yLab;
1233 std::array<float, param::NPadRows> sPath;
1236 int secFirst = clsRes[0].sec;
1238 float snPhi = sin(phiSect);
1239 float csPhi = cos(phiSect);
1243 int nCl = clsRes.size();
1244 for (
unsigned int iP = 0; iP < nCl; ++iP) {
1245 iRow += clsRes[iP].dRow;
1246 float yTrk = clsRes[iP].y;
1248 xLab[iP] = param::RowX[iRow];
1249 if (clsRes[iP].sec != secFirst) {
1251 float cs = cos(phiSectCurrent - phiSect);
1252 float sn = sin(phiSectCurrent - phiSect);
1253 xLab[iP] = param::RowX[iRow] * cs - yTrk * sn;
1254 yLab[iP] = yTrk * cs + param::RowX[iRow] * sn;
1256 xLab[iP] = param::RowX[iRow];
1260 params.zTrk[iP] = clsRes[iP].z;
1261 params.xTrk[iP] = param::RowX[iRow];
1262 params.dy[iP] = clsRes[iP].dy;
1263 params.dz[iP] = clsRes[iP].dz;
1266 float dx = xLab[iP] - xLab[iP - 1];
1267 float dy = yLab[iP] - yLab[iP - 1];
1268 float ds2 = dx * dx + dy * dy;
1269 float ds = sqrt(ds2);
1273 if (
ds * curvature > 0.05) {
1274 ds *= (1.f + ds2 * curvature * curvature / 24.f);
1276 sPath[iP] = sPath[iP - 1] +
ds;
1279 if (fabsf(mBz) < 0.01) {
1294 float phiI = TMath::ATan2(yLab[0], xLab[0]);
1295 float phiF = TMath::ATan2(yLab[nCl - 1], xLab[nCl - 1]);
1302 float dPhi = phiF - phiI;
1303 float curvSign = -1.f;
1314 float xc = xcSec * csPhi - ycSec * snPhi;
1315 float yc = xcSec * snPhi + ycSec * csPhi;
1317 std::array<float, 2> pol1Z;
1324 float hMaxY = -1e9f;
1326 float hMaxZ = -1e9f;
1328 int secCurr = secFirst;
1330 for (
unsigned int iCl = 0; iCl < nCl; ++iCl) {
1331 iRow += clsRes[iCl].dRow;
1332 float resZ =
params.zTrk[iCl] - (pol1Z[1] + sPath[iCl] * pol1Z[0]);
1333 residHelixZ[iCl] = resZ;
1340 if (residHelixY[iCl] < hMinY) {
1341 hMinY = residHelixY[iCl];
1343 if (residHelixY[iCl] > hMaxY) {
1344 hMaxY = residHelixY[iCl];
1346 int sec = clsRes[iCl].sec;
1347 if (sec != secCurr) {
1350 snPhi = sin(phiSect);
1351 csPhi = cos(phiSect);
1352 xcSec = xc * csPhi + yc * snPhi;
1354 float cstalp = (param::RowX[iRow] - xcSec) /
r;
1355 if (fabsf(cstalp) > 1.f - sFloatEps) {
1357 cstalp = std::copysign(1.f - sFloatEps, cstalp);
1359 params.tglArr[iCl] = cstalp / sqrt((1 - cstalp) * (1 + cstalp));
1362 if (
params.qpt * mBz > 0) {
1363 params.tglArr[iCl] *= -1.f;