320 LOG(error) <<
"Initialization not yet done. Aborting...";
328 mNTPCOccBinLength = mTPCParam->rec.tpc.occupancyMapTimeBins;
329 mNTPCOccBinLengthInv = 1.f / mNTPCOccBinLength;
332 LOG(error) <<
"No ITS dictionary available";
338 auto pattIt = patterns.begin();
339 mITSClustersArray.clear();
340 mITSClustersArray.reserve(clusITS.size());
341 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}", clusITS.size(), patterns.size());
349 std::random_device
rd;
350 std::mt19937
g(
rd());
351 std::vector<uint32_t> trackIndices;
361 int nSeeds = mSeeds.size(), lastChecked = 0;
363 mParentID.resize(nSeeds, -1);
365 int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds;
366 mTrackData.reserve(maxOutputTracks);
367 mClRes.reserve(maxOutputTracks * param::NPadRows);
368 mDetInfoRes.reserve(maxOutputTracks * param::NPadRows);
369 bool maxTracksReached =
false;
370 for (
int iSeed = 0; iSeed < nSeeds; ++iSeed) {
371 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
372 LOG(info) <<
"Maximum number of tracks per TF reached. Skipping the remaining " << nSeeds - iSeed <<
" tracks.";
375 int seedIndex = trackIndices[iSeed];
380 this->mGIDs.push_back(this->mGIDtables[seedIndex][
src]);
382 this->mTrackTimes.push_back(this->mTrackTimes[seedIndex]);
383 this->mSeeds.push_back(this->mSeeds[seedIndex]);
384 this->mParentID.push_back(seedIndex);
385 this->mTrackPVID.push_back(this->mTrackPVID[seedIndex]);
389 if (!mSingleSourcesConfigured && !mSourcesConfiguredMap[mGIDs[seedIndex].getSource()]) {
396 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF) {
397 if (!maxTracksReached) {
398 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);
400 maxTracksReached =
true;
405 LOGP(
debug,
"interpolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
416 LOGP(
debug,
"extrapolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
420 std::vector<int> remSeeds;
421 if (mSeeds.size() > ++lastChecked) {
422 remSeeds.resize(mSeeds.size() - lastChecked);
423 std::iota(remSeeds.begin(), remSeeds.end(), lastChecked);
424 std::shuffle(remSeeds.begin(), remSeeds.end(),
g);
425 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());
427 int extraChecked = 0;
428 for (
int iSeed : remSeeds) {
429 if (mAddTracksForMapPerTF > 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
430 LOGP(info,
"Maximum number {} of additional tracks per TF reached. Skipping the remaining {} tracks", mAddTracksForMapPerTF, remSeeds.size() - extraChecked);
436 LOGP(
debug,
"extra check {} of {}, seed {} interpolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
438 LOGP(
debug,
"extra check {} of {}, seed {} extrapolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
442 LOG(info) <<
"Could process " << mTrackData.size() <<
" tracks successfully. " << mRejectedResiduals <<
" residuals were rejected. " << mClRes.size() <<
" residuals were accepted.";
443 mRejectedResiduals = 0;
448 LOGP(
debug,
"Starting track interpolation for GID {}", mGIDs[iSeed].
asString());
452 std::unique_ptr<TrackDataExtended> trackDataExtended;
453 std::vector<TPCClusterResiduals> clusterResiduals;
455 const auto& gidTable = mGIDtables[iSeed];
458 if (mDumpTrackPoints) {
459 trackDataExtended = std::make_unique<TrackDataExtended>();
460 (*trackDataExtended).gid = mGIDs[iSeed];
461 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
462 (*trackDataExtended).trkITS = trkITS;
463 (*trackDataExtended).trkTPC = trkTPC;
464 auto nCl = trkITS.getNumberOfClusters();
465 auto clEntry = trkITS.getFirstClusterEntry();
466 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
467 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
468 (*trackDataExtended).clsITS.push_back(clsITS);
474 trackData.
gid = mGIDs[iSeed];
475 trackData.
par = mSeeds[iSeed];
476 auto trkWork = mSeeds[iSeed];
479 for (
auto& elem : mCache) {
480 elem.clAvailable = 0;
482 trackData.
clIdx.setFirstEntry(mClRes.size());
483 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
487 std::array<short, constants::MAXGLOBALPADROW> multBins{};
488 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
490 uint32_t clusterIndexInRow;
491 const auto& clTPC = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
493 std::array<float, 2> clTPCYZ;
494 mFastTransform->TransformIdeal(sector,
row, clTPC.getPad(), clTPC.getTime(), clTPCX, clTPCYZ[0], clTPCYZ[1], clusterTimeBinOffset);
495 mCache[
row].clSec = sector;
496 mCache[
row].clAvailable = 1;
497 mCache[
row].clY = clTPCYZ[0];
498 mCache[
row].clZ = clTPCYZ[1];
500 mCacheDEDX[
row].first = clTPC.getQtot();
501 mCacheDEDX[
row].second = clTPC.getQmax();
502 int imb =
int(clTPC.getTime() * mNTPCOccBinLengthInv);
503 if (imb < mTPCParam->occupancyMapSize) {
504 multBins[
row] = 1 + std::max(0, imb);
509 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
510 if (!mCache[iRow].clAvailable) {
513 if (!trkWork.rotate(mCache[iRow].clAngle)) {
514 LOG(
debug) <<
"Failed to rotate track during first extrapolation";
517 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
518 LOG(
debug) <<
"Failed on first extrapolation";
521 mCache[iRow].y[
ExtOut] = trkWork.getY();
522 mCache[iRow].z[
ExtOut] = trkWork.getZ();
523 mCache[iRow].sy2[
ExtOut] = trkWork.getSigmaY2();
524 mCache[iRow].szy[
ExtOut] = trkWork.getSigmaZY();
525 mCache[iRow].sz2[
ExtOut] = trkWork.getSigmaZ2();
526 mCache[iRow].snp[
ExtOut] = trkWork.getSnp();
532 LOG(
debug) <<
"TOF point available";
534 if (mDumpTrackPoints) {
535 (*trackDataExtended).clsTOF = clTOF;
536 (*trackDataExtended).matchTOF = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
538 const int clTOFSec = clTOF.getCount();
540 if (!trkWork.rotate(clTOFAlpha)) {
541 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
544 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
545 if (!clTOF.isInNominalSector()) {
548 std::array<float, 2> clTOFYZ{clTOFxyz[1], clTOFxyz[2]};
550 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
551 LOG(
debug) <<
"Failed final propagation to TOF radius";
555 if (!trkWork.update(clTOFYZ, clTOFCov)) {
556 LOG(
debug) <<
"Failed to update extrapolated ITS track with TOF cluster";
564 if (mDumpTrackPoints) {
565 (*trackDataExtended).trkTRD = trkTRD;
568 std::array<float, 2> trkltTRDYZ{};
569 std::array<float, 3> trkltTRDCov{};
577 if (!trkWork.update(trkltTRDYZ, trkltTRDCov)) {
578 LOG(
debug) <<
"Failed to update track at TRD layer " << iLayer;
584 if (mDumpTrackPoints) {
585 (*trackDataExtended).trkOuter = trkWork;
587 auto trkOuter = trkWork;
590 bool outerParamStored =
false;
591 for (
int iRow = param::NPadRows; iRow--;) {
592 if (!mCache[iRow].clAvailable) {
595 if (mProcessSeeds && !outerParamStored) {
601 trackData.
par = trkWork;
602 outerParamStored =
true;
604 if (!trkWork.rotate(mCache[iRow].clAngle)) {
605 LOG(
debug) <<
"Failed to rotate track during back propagation";
608 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
609 LOG(
debug) <<
"Failed on back propagation";
613 mCache[iRow].y[
ExtIn] = trkWork.getY();
614 mCache[iRow].z[
ExtIn] = trkWork.getZ();
615 mCache[iRow].sy2[
ExtIn] = trkWork.getSigmaY2();
616 mCache[iRow].szy[
ExtIn] = trkWork.getSigmaZY();
617 mCache[iRow].sz2[
ExtIn] = trkWork.getSigmaZ2();
618 mCache[iRow].snp[
ExtIn] = trkWork.getSnp();
622 unsigned short deltaRow = 0;
623 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
624 if (!mCache[iRow].clAvailable) {
628 float wTotY = 1.f / mCache[iRow].sy2[
ExtOut] + 1.f / mCache[iRow].sy2[
ExtIn];
629 float wTotZ = 1.f / mCache[iRow].sz2[
ExtOut] + 1.f / mCache[iRow].sz2[
ExtIn];
630 mCache[iRow].y[
Int] = (mCache[iRow].y[
ExtOut] / mCache[iRow].sy2[
ExtOut] + mCache[iRow].y[
ExtIn] / mCache[iRow].sy2[
ExtIn]) / wTotY;
631 mCache[iRow].z[
Int] = (mCache[iRow].z[
ExtOut] / mCache[iRow].sz2[
ExtOut] + mCache[iRow].z[
ExtIn] / mCache[iRow].sz2[
ExtIn]) / wTotZ;
634 mCache[iRow].snp[
Int] = (mCache[iRow].snp[
ExtOut] + mCache[iRow].snp[
ExtIn]) / 2.f;
636 const auto dY = mCache[iRow].clY - mCache[iRow].y[
Int];
637 const auto dZ = mCache[iRow].clZ - mCache[iRow].z[
Int];
638 const auto y = mCache[iRow].y[
Int];
639 const auto z = mCache[iRow].z[
Int];
640 const auto snp = mCache[iRow].snp[
Int];
641 const auto sec = mCache[iRow].clSec;
642 clusterResiduals.emplace_back(dY, dZ,
y,
z, snp, sec, deltaRow);
647 trackData.
chi2TPC = trkTPC.getChi2();
648 trackData.
chi2ITS = trkITS.getChi2();
649 trackData.
nClsTPC = trkTPC.getNClusterReferences();
650 trackData.
nClsITS = trkITS.getNumberOfClusters();
653 double t0forTOF = 0.;
654 float t0forTOFwithinBC = 0.f;
655 float t0forTOFres = 9999.f;
658 const auto& tofMatch = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
662 t0forTOFres = tofMatch.getFT0BestRes();
663 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
668 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
673 int nClValidated = 0;
675 for (
unsigned int iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
676 iRow += clusterResiduals[iCl].dRow;
677 if (
params.flagRej[iCl]) {
681 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
682 const auto dy = clusterResiduals[iCl].dy;
683 const auto dz = clusterResiduals[iCl].dz;
684 const auto y = clusterResiduals[iCl].y;
685 const auto z = clusterResiduals[iCl].z;
686 const auto sec = clusterResiduals[iCl].sec;
687 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)) {
688 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, sec);
689 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
692 ++mRejectedResiduals;
695 trackData.
clIdx.setEntries(nClValidated);
698 for (
int ist = 0; ist < NSTACKS; ist++) {
699 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
700 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
701 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
702 prevBin = multBins[
ir];
703 if (multBins[
ir] > mltBinMax) {
704 mltBinMax = multBins[
ir];
706 if (multBins[
ir] < mltBinMin) {
707 mltBinMin = multBins[
ir];
711 if (--mltBinMin >= 0) {
713 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
714 avMlt += mTPCParam->occupancyMap[ib];
716 avMlt /= (mltBinMax - mltBinMin);
721 bool stopPropagation = !mExtDetResid;
722 if (!stopPropagation) {
728 std::array<float, 2> trkltTRDYZ{};
729 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
734 stopPropagation =
true;
738 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
739 auto dy = trkltTRDYZ[0] - trkWork.getY();
740 auto dz = trkltTRDYZ[1] - trkWork.getZ();
741 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)) {
743 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
750 while (gidTable[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
752 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
753 if (!clTOF.isInNominalSector()) {
757 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
758 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
759 stopPropagation =
true;
762 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
763 LOG(
debug) <<
"Failed final propagation to TOF radius";
767 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
768 auto dy = clTOFxyz[1] - trkWork.getY();
769 auto dz = clTOFxyz[2] - trkWork.getZ();
772 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)) {
773 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
776 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
778 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
779 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
786 while (!stopPropagation) {
787 auto& trkWorkITS = trkInner;
788 auto nCl = trkITS.getNumberOfClusters();
789 auto clEntry = trkITS.getFirstClusterEntry();
791 for (
int iCl = 0; iCl < nCl; iCl++) {
792 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
793 int chip = cls.getSensorID();
794 float chipX, chipAlpha;
795 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
796 if (!trkWorkITS.rotate(chipAlpha) || !propagator->PropagateToXBxByBz(trkWorkITS, chipX, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
797 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
798 stopPropagation =
true;
801 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
802 auto dy = cls.getY() - trkWorkITS.getY();
803 auto dz = cls.getZ() - trkWorkITS.getZ();
804 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)) {
805 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
806 mDetInfoRes.emplace_back();
810 if (!stopPropagation) {
813 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
814 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
815 stopPropagation =
true;
819 float sn, cs,
alpha = trkWorkITS.getAlpha();
820 math_utils::detail::bringToPMPi(
alpha);
821 math_utils::detail::sincos<float>(
alpha, sn, cs);
822 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
823 auto dy = yv - trkWorkITS.getY();
824 auto dz = zv - trkWorkITS.getZ();
825 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) {
826 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
827 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
829 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
832 mDetInfoRes.emplace_back().setPV(tdif);
840 mGIDsSuccess.push_back(mGIDs[iSeed]);
841 mTrackDataCompact.emplace_back(trackData.
clIdx.getFirstEntry(), trackData.
multStack, nClValidated, mGIDs[iSeed].getSource(), trackData.
nExtDetResid);
842 mTrackData.push_back(std::move(trackData));
843 if (mDumpTrackPoints) {
844 (*trackDataExtended).clIdx.setEntries(nClValidated);
845 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
846 mTrackDataExtended.push_back(std::move(*trackDataExtended));
851 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
852 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
853 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
854 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
914 LOGP(
debug,
"Starting track extrapolation for GID {}", mGIDs[iSeed].
asString());
915 const auto& gidTable = mGIDtables[iSeed];
919 std::unique_ptr<TrackDataExtended> trackDataExtended;
920 std::vector<TPCClusterResiduals> clusterResiduals;
921 trackData.
clIdx.setFirstEntry(mClRes.size());
924 if (mDumpTrackPoints) {
925 trackDataExtended = std::make_unique<TrackDataExtended>();
926 (*trackDataExtended).gid = mGIDs[iSeed];
927 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
928 (*trackDataExtended).trkITS = trkITS;
929 (*trackDataExtended).trkTPC = trkTPC;
930 auto nCl = trkITS.getNumberOfClusters();
931 auto clEntry = trkITS.getFirstClusterEntry();
932 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
933 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
934 (*trackDataExtended).clsITS.push_back(clsITS);
940 trackData.
gid = mGIDs[iSeed];
941 trackData.
par = mSeeds[iSeed];
943 auto trkWork = mSeeds[iSeed];
944 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
946 unsigned short rowPrev = 0;
947 unsigned short nMeasurements = 0;
950 std::array<short, constants::MAXGLOBALPADROW> multBins{};
951 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
953 uint32_t clusterIndexInRow;
954 const auto& cl = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
955 if (clRowPrev ==
row) {
958 }
else if (clRowPrev < constants::MAXGLOBALPADROW && clRowPrev >
row) {
960 LOGP(
debug,
"TPC track with pT={} GeV and {} clusters has cluster {} on row {} while the previous cluster was on row {}",
961 mSeeds[iSeed].getPt(), trkTPC.getNClusterReferences(), iCl,
row, clRowPrev);
967 float x = 0,
y = 0,
z = 0;
968 mFastTransform->TransformIdeal(sector,
row, cl.getPad(), cl.getTime(),
x,
y,
z, clusterTimeBinOffset);
972 if (!propagator->PropagateToXBxByBz(trkWork,
x, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
976 const auto dY =
y - trkWork.getY();
977 const auto dZ =
z - trkWork.getZ();
978 const auto ty = trkWork.getY();
979 const auto tz = trkWork.getZ();
980 const auto snp = trkWork.getSnp();
981 const auto sec = sector;
982 clusterResiduals.emplace_back(dY, dZ, ty, tz, snp, sec,
row - rowPrev);
983 mCacheDEDX[
row].first = cl.getQtot();
984 mCacheDEDX[
row].second = cl.getQmax();
986 int imb =
int(cl.getTime() * mNTPCOccBinLengthInv);
987 if (imb < mTPCParam->occupancyMapSize) {
988 multBins[
row] = 1 + std::max(0, imb);
995 LOGP(warn,
"Extrapolated ITS-TPC track and found more residuals than possible ({})", clusterResiduals.size());
999 trackData.
chi2TPC = trkTPC.getChi2();
1000 trackData.
chi2ITS = trkITS.getChi2();
1001 trackData.
nClsTPC = trkTPC.getNClusterReferences();
1002 trackData.
nClsITS = trkITS.getNumberOfClusters();
1003 trackData.
clIdx.setEntries(nMeasurements);
1004 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
1005 if (mDumpTrackPoints) {
1006 (*trackDataExtended).trkOuter = trkWork;
1012 int nClValidated = 0, iRow = 0;
1013 unsigned int iCl = 0;
1014 for (iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
1015 iRow += clusterResiduals[iCl].dRow;
1016 if (iRow < param::NPadRows &&
params.flagRej[iCl]) {
1019 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
1020 const auto dy = clusterResiduals[iCl].dy;
1021 const auto dz = clusterResiduals[iCl].dz;
1022 const auto y = clusterResiduals[iCl].y;
1023 const auto z = clusterResiduals[iCl].z;
1024 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)) {
1025 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, clusterResiduals[iCl].sec);
1026 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
1029 ++mRejectedResiduals;
1032 trackData.
clIdx.setEntries(nClValidated);
1035 for (
int ist = 0; ist < NSTACKS; ist++) {
1036 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
1037 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
1038 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
1039 prevBin = multBins[
ir];
1040 if (multBins[
ir] > mltBinMax) {
1041 mltBinMax = multBins[
ir];
1043 if (multBins[
ir] < mltBinMin) {
1044 mltBinMin = multBins[
ir];
1048 if (--mltBinMin >= 0) {
1050 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
1051 avMlt += mTPCParam->occupancyMap[ib];
1053 avMlt /= (mltBinMax - mltBinMin);
1058 bool stopPropagation = !mExtDetResid;
1059 if (!stopPropagation) {
1061 int iSeedFull = mParentID[iSeed] == -1 ? iSeed : mParentID[iSeed];
1062 auto gidFull = mGIDs[iSeedFull];
1063 const auto& gidTableFull = mGIDtables[iSeedFull];
1066 trackData.
nTrkltsTRD = trkTRD.getNtracklets();
1068 std::array<float, 2> trkltTRDYZ{};
1069 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
1074 stopPropagation =
true;
1078 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1079 auto dy = trkltTRDYZ[0] - trkWork.getY();
1080 auto dz = trkltTRDYZ[1] - trkWork.getZ();
1081 const auto sec = clusterResiduals[iCl].sec;
1082 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)) {
1084 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
1092 while (gidTableFull[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
1093 const auto& tofMatch = mRecoCont->
getTOFMatch(gidFull);
1097 float t0forTOFres = tofMatch.getFT0BestRes();
1098 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
1099 trackData.
clAvailTOF = uint16_t(t0forTOFres);
1102 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
1103 if (!clTOF.isInNominalSector()) {
1106 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
1107 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
1108 stopPropagation =
true;
1111 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1112 LOG(
debug) <<
"Failed final propagation to TOF radius";
1116 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1117 auto dy = clTOFxyz[1] - trkWork.getY();
1118 auto dz = clTOFxyz[2] - trkWork.getZ();
1119 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)) {
1120 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
1123 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1126 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
1127 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
1134 while (!stopPropagation) {
1136 auto nCl = trkITS.getNumberOfClusters();
1137 auto clEntry = trkITS.getFirstClusterEntry();
1139 for (
int iCl = 0; iCl < nCl; iCl++) {
1140 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
1141 int chip = cls.getSensorID();
1142 float chipX, chipAlpha;
1143 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
1144 if (!trkWorkITS.rotate(chipAlpha) || !propagator->propagateToX(trkWorkITS, chipX, mBz, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1145 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
1146 stopPropagation =
true;
1149 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
1150 auto dy = cls.getY() - trkWorkITS.getY();
1151 auto dz = cls.getZ() - trkWorkITS.getZ();
1152 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)) {
1153 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
1154 mDetInfoRes.emplace_back();
1158 if (!stopPropagation) {
1161 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
1162 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
1163 stopPropagation =
true;
1167 float sn, cs,
alpha = trkWorkITS.getAlpha();
1168 math_utils::detail::bringToPMPi(
alpha);
1169 math_utils::detail::sincos<float>(
alpha, sn, cs);
1170 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
1171 auto dy = yv - trkWorkITS.getY();
1172 auto dz = zv - trkWorkITS.getZ();
1173 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) {
1174 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
1175 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
1177 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1180 mDetInfoRes.emplace_back().setPV(tdif);
1187 mTrackData.push_back(std::move(trackData));
1188 mGIDsSuccess.push_back(mGIDs[iSeed]);
1189 mTrackDataCompact.emplace_back(trackData.
clIdx.getFirstEntry(), trackData.
multStack, nClValidated, mGIDs[iSeed].getSource(), trackData.
nExtDetResid);
1190 if (mDumpTrackPoints) {
1191 (*trackDataExtended).clIdx.setEntries(nClValidated);
1192 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
1193 mTrackDataExtended.push_back(std::move(*trackDataExtended));
1198 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
1199 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
1200 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
1201 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
1230 std::array<float, param::NPadRows> residHelixY;
1231 std::array<float, param::NPadRows> residHelixZ;
1233 std::array<float, param::NPadRows> xLab;
1234 std::array<float, param::NPadRows> yLab;
1235 std::array<float, param::NPadRows> sPath;
1238 int secFirst = clsRes[0].sec;
1240 float snPhi = sin(phiSect);
1241 float csPhi = cos(phiSect);
1245 int nCl = clsRes.size();
1246 for (
unsigned int iP = 0; iP < nCl; ++iP) {
1247 iRow += clsRes[iP].dRow;
1248 float yTrk = clsRes[iP].y;
1250 xLab[iP] = param::RowX[iRow];
1251 if (clsRes[iP].sec != secFirst) {
1253 float cs = cos(phiSectCurrent - phiSect);
1254 float sn = sin(phiSectCurrent - phiSect);
1255 xLab[iP] = param::RowX[iRow] * cs - yTrk * sn;
1256 yLab[iP] = yTrk * cs + param::RowX[iRow] * sn;
1258 xLab[iP] = param::RowX[iRow];
1262 params.zTrk[iP] = clsRes[iP].z;
1263 params.xTrk[iP] = param::RowX[iRow];
1264 params.dy[iP] = clsRes[iP].dy;
1265 params.dz[iP] = clsRes[iP].dz;
1268 float dx = xLab[iP] - xLab[iP - 1];
1269 float dy = yLab[iP] - yLab[iP - 1];
1270 float ds2 = dx * dx + dy * dy;
1271 float ds = sqrt(ds2);
1275 if (
ds * curvature > 0.05) {
1276 ds *= (1.f + ds2 * curvature * curvature / 24.f);
1278 sPath[iP] = sPath[iP - 1] +
ds;
1281 if (fabsf(mBz) < 0.01) {
1296 float phiI = TMath::ATan2(yLab[0], xLab[0]);
1297 float phiF = TMath::ATan2(yLab[nCl - 1], xLab[nCl - 1]);
1304 float dPhi = phiF - phiI;
1305 float curvSign = -1.f;
1316 float xc = xcSec * csPhi - ycSec * snPhi;
1317 float yc = xcSec * snPhi + ycSec * csPhi;
1319 std::array<float, 2> pol1Z;
1326 float hMaxY = -1e9f;
1328 float hMaxZ = -1e9f;
1330 int secCurr = secFirst;
1332 for (
unsigned int iCl = 0; iCl < nCl; ++iCl) {
1333 iRow += clsRes[iCl].dRow;
1334 float resZ =
params.zTrk[iCl] - (pol1Z[1] + sPath[iCl] * pol1Z[0]);
1335 residHelixZ[iCl] = resZ;
1342 if (residHelixY[iCl] < hMinY) {
1343 hMinY = residHelixY[iCl];
1345 if (residHelixY[iCl] > hMaxY) {
1346 hMaxY = residHelixY[iCl];
1348 int sec = clsRes[iCl].sec;
1349 if (sec != secCurr) {
1352 snPhi = sin(phiSect);
1353 csPhi = cos(phiSect);
1354 xcSec = xc * csPhi + yc * snPhi;
1356 float cstalp = (param::RowX[iRow] - xcSec) /
r;
1357 if (fabsf(cstalp) > 1.f - sFloatEps) {
1359 cstalp = std::copysign(1.f - sFloatEps, cstalp);
1361 params.tglArr[iCl] = cstalp / sqrt((1 - cstalp) * (1 + cstalp));
1364 if (
params.qpt * mBz > 0) {
1365 params.tglArr[iCl] *= -1.f;