337 LOG(error) <<
"Initialization not yet done. Aborting...";
346 mNTPCOccBinLength = mTPCParam->rec.tpc.occupancyMapTimeBins;
347 mNTPCOccBinLengthInv = 1.f / mNTPCOccBinLength;
350 LOG(error) <<
"No ITS dictionary available";
355 mITSClustersArray.
init(nLr);
356 for (
int lr = 0; lr < nLr; lr++) {
360 auto pattIt = patterns.begin();
361 mITSClustersArray.
getClusters().reserve(mITSClustersArray.
size() + clusITS.size());
362 LOGP(info,
"We have {} ITS clusters and the number of patterns is {} on the layer slot {}", clusITS.size(), patterns.size(), lr);
372 std::random_device
rd;
373 std::mt19937
g(
rd());
374 std::vector<uint32_t> trackIndices;
383 int nSeeds = mSeeds.size(), lastChecked = 0;
385 mParentID.resize(nSeeds, -1);
387 int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds;
388 mTrackData.reserve(maxOutputTracks);
389 mClRes.reserve(maxOutputTracks * param::NPadRows);
390 mDetInfoRes.reserve(maxOutputTracks * param::NPadRows);
391 bool maxTracksReached =
false;
392 for (
int iSeed = 0; iSeed < nSeeds; ++iSeed) {
393 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
394 LOG(info) <<
"Maximum number of tracks per TF reached. Skipping the remaining " << nSeeds - iSeed <<
" tracks.";
397 int seedIndex = trackIndices[iSeed];
402 this->mGIDs.push_back(this->mGIDtables[seedIndex][
src]);
404 this->mTrackTimes.push_back(this->mTrackTimes[seedIndex]);
405 this->mSeeds.push_back(this->mSeeds[seedIndex]);
406 this->mParentID.push_back(seedIndex);
407 this->mTrackPVID.push_back(this->mTrackPVID[seedIndex]);
411 if (!mSingleSourcesConfigured && !mSourcesConfiguredMap[mGIDs[seedIndex].getSource()]) {
418 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF) {
419 if (!maxTracksReached) {
420 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);
422 maxTracksReached =
true;
425 if (mGIDs[seedIndex].includesDet(DetID::TRD) || mGIDs[seedIndex].includesDet(DetID::TOF)) {
427 LOGP(
debug,
"interpolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
429 if (mGIDs[seedIndex].includesDet(DetID::TRD) && mGIDs[seedIndex].includesDet(DetID::TOF) && !partsAdded[
GTrackID::ITSTPCTRD]) {
438 LOGP(
debug,
"extrapolateTrack {} {}, accepted: {}", iSeed,
GTrackID::getSourceName(mGIDs[seedIndex].getSource()), mTrackDataCompact.size());
442 std::vector<int> remSeeds;
443 if (mSeeds.size() > ++lastChecked) {
444 remSeeds.resize(mSeeds.size() - lastChecked);
445 std::iota(remSeeds.begin(), remSeeds.end(), lastChecked);
446 std::shuffle(remSeeds.begin(), remSeeds.end(),
g);
447 LOGP(info,
"Up to {} tracks out of {} additional seeds will be processed in random order, of which {} are stripped versions, accepted seeds: {}",
448 mAddTracksForMapPerTF > 0 ? mAddTracksForMapPerTF : remSeeds.size(),
449 remSeeds.size(), mSeeds.size() - nSeeds, mTrackDataCompact.size());
451 int extraChecked = 0;
452 for (
int iSeed : remSeeds) {
453 if (mAddTracksForMapPerTF > 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
454 LOGP(info,
"Maximum number {} of additional tracks per TF reached. Skipping the remaining {} tracks", mAddTracksForMapPerTF, remSeeds.size() - extraChecked);
458 if (mGIDs[iSeed].includesDet(DetID::TRD) || mGIDs[iSeed].includesDet(DetID::TOF)) {
460 LOGP(
debug,
"extra check {} of {}, seed {} interpolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
462 LOGP(
debug,
"extra check {} of {}, seed {} extrapolateTrack {}, used: {}", extraChecked, remSeeds.size(), iSeed,
GTrackID::getSourceName(mGIDs[iSeed].getSource()), mTrackDataCompact.size());
466 LOGP(info,
"Could process {} tracks successfully ({} rejected in refits, {} in propagation, {} as loopers), {} residuals were rejected, {} accepted",
467 mTrackData.size(), mNRejRefit, mNRejProp, mNRejLoop, mRejectedResiduals, mClRes.size());
469 LOGP(info,
"keepClustersOnPropFail: {} tracks kept after a propagation failure, {} position-only TPC clusters stored", mNPosOnlyTracks, mNPosOnlyClusters);
472 mNPosOnlyClusters = 0;
473 mRejectedResiduals = 0;
490 LOGP(
debug,
"Starting track interpolation for GID {}", mGIDs[iSeed].
asString());
494 std::unique_ptr<TrackDataExtended> trackDataExtended;
495 std::vector<TPCClusterResiduals> clusterResiduals;
497 const auto& gidTable = mGIDtables[iSeed];
500 if (mDumpTrackPoints) {
501 trackDataExtended = std::make_unique<TrackDataExtended>();
502 (*trackDataExtended).gid = mGIDs[iSeed];
503 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
504 (*trackDataExtended).trkITS = trkITS;
505 (*trackDataExtended).trkTPC = trkTPC;
506 auto nCl = trkITS.getNumberOfClusters();
507 auto clEntry = trkITS.getFirstClusterEntry();
508 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
509 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
510 (*trackDataExtended).clsITS.push_back(clsITS);
517 trackData.
gid = mGIDs[iSeed];
518 trackData.
par = mSeeds[iSeed];
519 auto trkWork = mSeeds[iSeed];
522 for (
auto& elem : mCache) {
523 elem.clAvailable = 0;
525 trackData.
clIdx.setFirstEntry(mClRes.size());
526 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
529 std::array<std::pair<uint16_t, uint16_t>, constants::MAXGLOBALPADROW> mCacheDEDX{};
530 std::array<short, constants::MAXGLOBALPADROW> multBins{};
533 bool allLost =
false;
534 std::array<bool, constants::MAXGLOBALPADROW> refOut{}, refIn{};
535 std::vector<PositionOnlyCluster> posOnly;
536 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
538 uint32_t clusterIndexInRow;
539 trkTPC.getClusterReference(mTPCTrackClusIdx, iCl, sector,
row, clusterIndexInRow);
540 unsigned int absoluteIndex = mTPCClusterIdxStruct->
clusterOffset[sector][
row] + clusterIndexInRow;
541 const auto& clTPC = mTPCClusterIdxStruct->
clustersLinear[absoluteIndex];
543 std::array<float, 2> clTPCYZ;
544 mFastTransform->TransformIdeal(sector,
row, clTPC.getPad(), clTPC.getTime(), clTPCX, clTPCYZ[0], clTPCYZ[1], clusterTimeBinOffset);
545 mCache[
row].clSec = sector;
546 mCache[
row].clAvailable = 1;
547 mCache[
row].clY = clTPCYZ[0];
548 mCache[
row].clZ = clTPCYZ[1];
550 mCache[
row].clFlags = clTPC.getFlags();
554 mCacheDEDX[
row].first = std::min<uint16_t>(clTPC.getQtot(), UINT16_MAX);
555 mCacheDEDX[
row].second = clTPC.getQmax();
556 int imb = int(clTPC.getTime() * mNTPCOccBinLengthInv);
557 if (imb < mTPCParam->occupancyMapSize) {
558 multBins[
row] = 1 + std::max(0, imb);
563 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
564 if (!mCache[iRow].clAvailable) {
567 if (!trkWork.rotate(mCache[iRow].clAngle) || !propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
568 LOG(
debug) <<
"Failed on first extrapolation";
577 mCache[iRow].y[
ExtOut] = trkWork.getY();
578 mCache[iRow].z[
ExtOut] = trkWork.getZ();
579 mCache[iRow].sy2[
ExtOut] = trkWork.getSigmaY2();
580 mCache[iRow].szy[
ExtOut] = trkWork.getSigmaZY();
581 mCache[iRow].sz2[
ExtOut] = trkWork.getSigmaZ2();
582 mCache[iRow].snp[
ExtOut] = trkWork.getSnp();
588 LOG(
debug) <<
"TOF point available";
590 if (mDumpTrackPoints) {
591 (*trackDataExtended).clsTOF = clTOF;
592 (*trackDataExtended).matchTOF = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
594 const int clTOFSec = clTOF.getCount();
596 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
597 if (!clTOF.isInNominalSector()) {
600 std::array<float, 2> clTOFYZ{clTOFxyz[1], clTOFxyz[2]};
603 if (!trkWork.rotate(clTOFAlpha) || !propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr) || !trkWork.update(clTOFYZ, clTOFCov)) {
604 LOG(
debug) <<
"Failed to rotate/propagate/update the extrapolated ITS track at the TOF cluster";
615 if (mDumpTrackPoints) {
616 (*trackDataExtended).trkTRD = trkTRD;
618 for (
int iLayer = o2::trd::constants::NLAYER - 1; iLayer >= 0; --iLayer) {
619 std::array<float, 2> trkltTRDYZ{};
620 std::array<float, 3> trkltTRDCov{};
625 if (
res < -1 || !trkWork.update(trkltTRDYZ, trkltTRDCov)) {
626 LOG(
debug) <<
"Failed to reach or update the track at TRD layer " << iLayer;
639 if (mDumpTrackPoints) {
640 (*trackDataExtended).trkOuter = trkWork;
642 auto trkOuter = trkWork;
645 bool outerParamStored =
false;
646 for (
int iRow = param::NPadRows; !allLost && iRow--;) {
647 if (!mCache[iRow].clAvailable) {
650 if (mProcessSeeds && !outerParamStored) {
656 trackData.
par = trkWork;
657 outerParamStored =
true;
659 if (!trkWork.rotate(mCache[iRow].clAngle) || !propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
660 LOG(
debug) <<
"Failed on back propagation";
668 mCache[iRow].y[
ExtIn] = trkWork.getY();
669 mCache[iRow].z[
ExtIn] = trkWork.getZ();
670 mCache[iRow].sy2[
ExtIn] = trkWork.getSigmaY2();
671 mCache[iRow].szy[
ExtIn] = trkWork.getSigmaZY();
672 mCache[iRow].sz2[
ExtIn] = trkWork.getSigmaZ2();
673 mCache[iRow].snp[
ExtIn] = trkWork.getSnp();
677 unsigned short deltaRow = 0;
678 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
679 if (!mCache[iRow].clAvailable) {
683 if (!refOut[iRow] || !refIn[iRow]) {
684 posOnly.push_back({mCache[iRow].clY, mCache[iRow].clZ, mCache[iRow].clSec, (
unsigned char)iRow, mCache[iRow].clFlags});
688 float wTotY = 1.f / mCache[iRow].sy2[
ExtOut] + 1.f / mCache[iRow].sy2[
ExtIn];
689 float wTotZ = 1.f / mCache[iRow].sz2[
ExtOut] + 1.f / mCache[iRow].sz2[
ExtIn];
690 mCache[iRow].y[
Int] = (mCache[iRow].y[
ExtOut] / mCache[iRow].sy2[
ExtOut] + mCache[iRow].y[
ExtIn] / mCache[iRow].sy2[
ExtIn]) / wTotY;
691 mCache[iRow].z[
Int] = (mCache[iRow].z[
ExtOut] / mCache[iRow].sz2[
ExtOut] + mCache[iRow].z[
ExtIn] / mCache[iRow].sz2[
ExtIn]) / wTotZ;
694 mCache[iRow].snp[
Int] = (mCache[iRow].snp[
ExtOut] + mCache[iRow].snp[
ExtIn]) / 2.f;
696 const auto dY = mCache[iRow].clY - mCache[iRow].y[
Int];
697 const auto dZ = mCache[iRow].clZ - mCache[iRow].z[
Int];
698 const auto y = mCache[iRow].y[
Int];
699 const auto z = mCache[iRow].z[
Int];
700 const auto snp = mCache[iRow].snp[
Int];
701 const auto sec = mCache[iRow].clSec;
702 clusterResiduals.emplace_back(dY, dZ,
y,
z, snp, sec, deltaRow, mCache[iRow].clFlags);
707 trackData.
chi2TPC = trkTPC.getChi2();
708 trackData.
chi2ITS = trkITS.getChi2();
709 trackData.
nClsTPC = trkTPC.getNClusterReferences();
710 trackData.
nClsITS = trkITS.getNumberOfClusters();
713 double t0forTOF = 0.;
714 float t0forTOFwithinBC = 0.f;
715 float t0forTOFres = 9999.f;
718 const auto& tofMatch = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
722 t0forTOFres = tofMatch.getFT0BestRes();
723 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
728 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
730 mTrackValidation.
clear();
736 int nClValidated = 0;
740 auto flushPosOnly = [&](
int rowLimit) {
741 for (; iPosOnly < posOnly.size() && posOnly[iPosOnly].row < rowLimit; ++iPosOnly) {
742 const auto& pc = posOnly[iPosOnly];
743 if (std::abs(pc.y) < param::MaxY && std::abs(pc.z) < param::MaxZ) {
744 mClRes.emplace_back(0.f, 0.f, 0.f, pc.y, pc.z, pc.row, pc.sec, pc.flags,
false);
746 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[pc.row].first, mCacheDEDX[pc.row].second);
750 ++mRejectedResiduals;
754 for (
unsigned int iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
755 iRow += clusterResiduals[iCl].dRow;
757 const auto rej = trackData.
filterFlag < 0 ? false : mTrackValidation.
points[iCl].flagRej;
761 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
762 const auto dy = clusterResiduals[iCl].dy;
763 const auto dz = clusterResiduals[iCl].dz;
764 const auto y = clusterResiduals[iCl].y;
765 const auto z = clusterResiduals[iCl].z;
766 const auto sec = clusterResiduals[iCl].sec;
767 const short flags = clusterResiduals[iCl].flags;
769 const bool tgPhiOK = (std::abs(tgPhi) < param::MaxTgSlp) || mParams->
clampTgSlp;
770 const float tgPhiStore = std::clamp(tgPhi, -param::MaxTgSlp, param::MaxTgSlp);
771 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && tgPhiOK) {
772 mClRes.emplace_back(dy, dz, tgPhiStore,
y,
z, iRow, sec,
flags, rej);
773 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
776 ++mRejectedResiduals;
779 flushPosOnly(constants::MAXGLOBALPADROW);
780 if (!posOnly.empty()) {
783 trackData.
clIdx.setEntries(nClValidated);
786 for (
int ist = 0; ist < NSTACKS; ist++) {
787 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
788 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
789 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
790 prevBin = multBins[
ir];
791 if (multBins[
ir] > mltBinMax) {
792 mltBinMax = multBins[
ir];
794 if (multBins[
ir] < mltBinMin) {
795 mltBinMin = multBins[
ir];
799 if (--mltBinMin >= 0) {
801 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
802 avMlt += mTPCParam->occupancyMap[ib];
804 avMlt /= (mltBinMax - mltBinMin);
809 bool stopPropagation = !mExtDetResid;
811 if (!stopPropagation) {
817 for (
int iLayer = 0; iLayer < o2::trd::constants::NLAYER; iLayer++) {
818 std::array<float, 2> trkltTRDYZ{};
819 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
824 stopPropagation =
true;
828 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
829 auto dy = trkltTRDYZ[0] - trkWork.getY();
830 auto dz = trkltTRDYZ[1] - trkWork.getZ();
831 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)) {
833 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
840 while (!allLost && gidTable[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
842 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
843 if (!clTOF.isInNominalSector()) {
847 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
848 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
849 stopPropagation =
true;
852 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
853 LOG(
debug) <<
"Failed final propagation to TOF radius";
857 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
858 auto dy = clTOFxyz[1] - trkWork.getY();
859 auto dz = clTOFxyz[2] - trkWork.getZ();
862 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)) {
863 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
866 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
868 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
869 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
876 while (!stopPropagation) {
877 auto& trkWorkITS = trkInner;
878 auto nCl = trkITS.getNumberOfClusters();
879 auto clEntry = trkITS.getFirstClusterEntry();
881 for (
int iCl = 0; iCl < nCl; iCl++) {
882 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
883 int chip = cls.getSensorID();
884 float chipX, chipAlpha;
885 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
886 if (!trkWorkITS.rotate(chipAlpha) || !propagator->PropagateToXBxByBz(trkWorkITS, chipX, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
887 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
888 stopPropagation =
true;
891 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
892 auto dy = cls.getY() - trkWorkITS.getY();
893 auto dz = cls.getZ() - trkWorkITS.getZ();
894 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)) {
895 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
896 mDetInfoRes.emplace_back();
900 if (!stopPropagation) {
903 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
904 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
905 stopPropagation =
true;
909 float sn, cs,
alpha = trkWorkITS.getAlpha();
910 math_utils::detail::bringToPMPi(
alpha);
911 math_utils::detail::sincos<float>(
alpha, sn, cs);
912 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
913 auto dy = yv - trkWorkITS.getY();
914 auto dz = zv - trkWorkITS.getZ();
915 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(xv) < param::MaxVtxX) {
916 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
917 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
919 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
922 mDetInfoRes.emplace_back().setPV(tdif);
930 mGIDsSuccess.push_back(mGIDs[iSeed]);
931 mTRDGIDsSuccess.push_back(gidTRDUsed);
933 mTrackData.push_back(std::move(trackData));
935 if (mDumpTrackPoints) {
936 (*trackDataExtended).clIdx.setEntries(nClValidated);
937 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
938 (*trackDataExtended).filterFlag = trackData.
filterFlag;
939 mTrackDataExtended.push_back(std::move(*trackDataExtended));
943 (*mDBGOut) <<
"valdata" <<
"params=" << mTrackValidation <<
"trackData=" << (stored ? mTrackData.back() : trackData) <<
"\n";
1003 LOGP(
debug,
"Starting track extrapolation for GID {}", mGIDs[iSeed].
asString());
1004 const auto& gidTable = mGIDtables[iSeed];
1008 std::unique_ptr<TrackDataExtended> trackDataExtended;
1009 std::vector<TPCClusterResiduals> clusterResiduals;
1010 trackData.
clIdx.setFirstEntry(mClRes.size());
1013 if (mDumpTrackPoints) {
1014 trackDataExtended = std::make_unique<TrackDataExtended>();
1015 (*trackDataExtended).gid = mGIDs[iSeed];
1016 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
1017 (*trackDataExtended).trkITS = trkITS;
1018 (*trackDataExtended).trkTPC = trkTPC;
1019 auto nCl = trkITS.getNumberOfClusters();
1020 auto clEntry = trkITS.getFirstClusterEntry();
1021 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
1022 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
1023 (*trackDataExtended).clsITS.push_back(clsITS);
1030 trackData.
gid = mGIDs[iSeed];
1031 trackData.
par = mSeeds[iSeed];
1033 auto trkWork = mSeeds[iSeed];
1034 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
1036 unsigned short rowPrev = 0;
1037 unsigned short nMeasurements = 0;
1038 uint8_t clRowPrev = constants::MAXGLOBALPADROW;
1039 std::array<std::pair<uint16_t, uint16_t>, constants::MAXGLOBALPADROW> mCacheDEDX{};
1040 std::array<short, constants::MAXGLOBALPADROW> multBins{};
1041 bool refLost =
false;
1042 std::vector<PositionOnlyCluster> posOnly;
1043 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
1044 uint8_t sector,
row;
1045 uint32_t clusterIndexInRow;
1046 trkTPC.getClusterReference(mTPCTrackClusIdx, iCl, sector,
row, clusterIndexInRow);
1047 unsigned int absoluteIndex = mTPCClusterIdxStruct->
clusterOffset[sector][
row] + clusterIndexInRow;
1048 const auto& cl = mTPCClusterIdxStruct->
clustersLinear[absoluteIndex];
1049 if (clRowPrev ==
row) {
1052 }
else if (clRowPrev < constants::MAXGLOBALPADROW && clRowPrev >
row) {
1054 LOGP(
debug,
"TPC track with pT={} GeV and {} clusters has cluster {} on row {} while the previous cluster was on row {}",
1055 mSeeds[iSeed].getPt(), trkTPC.getNClusterReferences(), iCl,
row, clRowPrev);
1062 float x = 0,
y = 0,
z = 0;
1063 mFastTransform->TransformIdeal(sector,
row, cl.getPad(), cl.getTime(),
x,
y,
z, clusterTimeBinOffset);
1064 unsigned char flags = cl.getFlags();
1075 mCacheDEDX[
row].first = cl.getQtot();
1076 mCacheDEDX[
row].second = cl.getQmax();
1078 posOnly.push_back({
y,
z, sector,
row,
flags});
1080 const auto dY =
y - trkWork.getY();
1081 const auto dZ =
z - trkWork.getZ();
1082 const auto ty = trkWork.getY();
1083 const auto tz = trkWork.getZ();
1084 const auto snp = trkWork.getSnp();
1085 const auto sec = sector;
1086 clusterResiduals.emplace_back(dY, dZ, ty, tz, snp, sec,
row - rowPrev,
flags);
1089 int imb = int(cl.getTime() * mNTPCOccBinLengthInv);
1090 if (imb < mTPCParam->occupancyMapSize) {
1091 multBins[
row] = 1 + std::max(0, imb);
1096 mTrackValidation.
clear();
1097 if (clusterResiduals.size() > constants::MAXGLOBALPADROW) {
1098 LOGP(warn,
"Extrapolated ITS-TPC track and found more residuals than possible ({})", clusterResiduals.size());
1103 trackData.
chi2TPC = trkTPC.getChi2();
1104 trackData.
chi2ITS = trkITS.getChi2();
1105 trackData.
nClsTPC = trkTPC.getNClusterReferences();
1106 trackData.
nClsITS = trkITS.getNumberOfClusters();
1107 trackData.
clIdx.setEntries(nMeasurements);
1108 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
1109 if (mDumpTrackPoints) {
1110 (*trackDataExtended).trkOuter = trkWork;
1113 bool stored =
false;
1117 int nClValidated = 0, iRow = 0;
1118 unsigned int iCl = 0;
1120 size_t iPosOnly = 0;
1121 auto flushPosOnly = [&](
int rowLimit) {
1122 for (; iPosOnly < posOnly.size() && posOnly[iPosOnly].row < rowLimit; ++iPosOnly) {
1123 const auto& pc = posOnly[iPosOnly];
1124 if (std::abs(pc.y) < param::MaxY && std::abs(pc.z) < param::MaxZ) {
1125 mClRes.emplace_back(0.f, 0.f, 0.f, pc.y, pc.z, pc.row, pc.sec, pc.flags,
false);
1127 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[pc.row].first, mCacheDEDX[pc.row].second);
1129 ++mNPosOnlyClusters;
1131 ++mRejectedResiduals;
1135 for (iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
1136 iRow += clusterResiduals[iCl].dRow;
1138 if (iRow >= param::NPadRows) {
1141 const auto rej = trackData.
filterFlag < 0 ? false : mTrackValidation.
points[iCl].flagRej;
1145 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
1146 const auto dy = clusterResiduals[iCl].dy;
1147 const auto dz = clusterResiduals[iCl].dz;
1148 const auto y = clusterResiduals[iCl].y;
1149 const auto z = clusterResiduals[iCl].z;
1150 const short flags = clusterResiduals[iCl].flags;
1152 const bool tgPhiOK = (std::abs(tgPhi) < param::MaxTgSlp) || mParams->
clampTgSlp;
1153 const float tgPhiStore = std::clamp(tgPhi, -param::MaxTgSlp, param::MaxTgSlp);
1154 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && tgPhiOK) {
1155 mClRes.emplace_back(dy, dz, tgPhiStore,
y,
z, iRow, clusterResiduals[iCl].sec,
flags, rej);
1156 mDetInfoRes.emplace_back().setTPC(mCacheDEDX[iRow].
first, mCacheDEDX[iRow].second);
1159 ++mRejectedResiduals;
1162 flushPosOnly(constants::MAXGLOBALPADROW);
1163 if (!posOnly.empty()) {
1166 trackData.
clIdx.setEntries(nClValidated);
1169 for (
int ist = 0; ist < NSTACKS; ist++) {
1170 int mltBinMin = 0x7ffff, mltBinMax = -1, prevBin = -1;
1171 for (
int ir = STACKROWS[ist];
ir < STACKROWS[ist + 1];
ir++) {
1172 if (multBins[
ir] != prevBin && multBins[
ir] > 0) {
1173 prevBin = multBins[
ir];
1174 if (multBins[
ir] > mltBinMax) {
1175 mltBinMax = multBins[
ir];
1177 if (multBins[
ir] < mltBinMin) {
1178 mltBinMin = multBins[
ir];
1182 if (--mltBinMin >= 0) {
1184 for (
int ib = mltBinMin; ib < mltBinMax; ib++) {
1185 avMlt += mTPCParam->occupancyMap[ib];
1187 avMlt /= (mltBinMax - mltBinMin);
1192 bool stopPropagation = !mExtDetResid;
1194 if (!stopPropagation) {
1196 int iSeedFull = mParentID[iSeed] == -1 ? iSeed : mParentID[iSeed];
1197 auto gidFull = mGIDs[iSeedFull];
1198 const auto& gidTableFull = mGIDtables[iSeedFull];
1202 trackData.
nTrkltsTRD = trkTRD.getNtracklets();
1203 trackData.
chi2TRD = trkTRD.getChi2();
1204 for (
int iLayer = 0; iLayer < o2::trd::constants::NLAYER; iLayer++) {
1205 std::array<float, 2> trkltTRDYZ{};
1206 int res =
processTRDLayer(trkTRD, iLayer, trkWork, &trkltTRDYZ,
nullptr, &trackData, &trkl64, &trklCalib);
1211 stopPropagation =
true;
1215 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1216 auto dy = trkltTRDYZ[0] - trkWork.getY();
1217 auto dz = trkltTRDYZ[1] - trkWork.getZ();
1218 const auto sec = clusterResiduals[iCl].sec;
1219 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)) {
1221 mDetInfoRes.emplace_back().setTRD(trkl64.getQ0(), trkl64.getQ1(), trkl64.getQ2(), trklCalib.getDy());
1229 while (!refLost && gidTableFull[
GTrackID::TOF].isIndexSet() && !stopPropagation) {
1230 const auto& tofMatch = mRecoCont->
getTOFMatch(gidFull);
1234 float t0forTOFres = tofMatch.getFT0BestRes();
1235 trackData.
deltaTOF = tofMatch.getSignal() - t0forTOF - tofMatch.getLTIntegralOut().getTOF(trkTPC.getPID().getID());
1236 trackData.
clAvailTOF = uint16_t(t0forTOFres);
1239 float clTOFxyz[3] = {clTOF.getX(), clTOF.getY(), clTOF.getZ()};
1240 if (!clTOF.isInNominalSector()) {
1243 if (trkWork.getAlpha() != clTOFAlpha && !trkWork.rotate(clTOFAlpha)) {
1244 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
1245 stopPropagation =
true;
1248 if (!propagator->PropagateToXBxByBz(trkWork, clTOFxyz[0], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1249 LOG(
debug) <<
"Failed final propagation to TOF radius";
1253 float tgPhi = trkWork.getSnp() / std::sqrt((1.f - trkWork.getSnp()) * (1.f + trkWork.getSnp()));
1254 auto dy = clTOFxyz[1] - trkWork.getY();
1255 auto dz = clTOFxyz[2] - trkWork.getZ();
1256 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)) {
1257 mClRes.emplace_back(dy, dz, tgPhi, trkWork.getY(), trkWork.getZ(), 170, clTOF.getCount(), clTOF.getPadInSector());
1260 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1263 float tdif =
static_cast<float>(clTOF.getTime() - t0forTOF);
1264 mDetInfoRes.emplace_back().setTOF(tdif * 1e-6);
1271 while (!stopPropagation) {
1273 auto nCl = trkITS.getNumberOfClusters();
1274 auto clEntry = trkITS.getFirstClusterEntry();
1276 for (
int iCl = 0; iCl < nCl; iCl++) {
1277 const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
1278 int chip = cls.getSensorID();
1279 float chipX, chipAlpha;
1280 geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
1281 if (!trkWorkITS.rotate(chipAlpha) || !propagator->propagateToX(trkWorkITS, chipX, mBz, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
1282 LOGP(
debug,
"Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
1283 stopPropagation =
true;
1286 float tgPhi = trkWorkITS.getSnp() / std::sqrt((1.f - trkWorkITS.getSnp()) * (1.f + trkWorkITS.getSnp()));
1287 auto dy = cls.getY() - trkWorkITS.getY();
1288 auto dz = cls.getZ() - trkWorkITS.getZ();
1289 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)) {
1290 mClRes.emplace_back(dy, dz, tgPhi, trkWorkITS.getY(), trkWorkITS.getZ(), 180 + geom->getLayer(cls.getSensorID()), -1, cls.getSensorID());
1291 mDetInfoRes.emplace_back();
1295 if (!stopPropagation) {
1298 if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->
maxStep, mMatCorr)) {
1299 LOGP(
debug,
"Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
1300 stopPropagation =
true;
1304 float sn, cs,
alpha = trkWorkITS.getAlpha();
1305 math_utils::detail::bringToPMPi(
alpha);
1306 math_utils::detail::sincos<float>(
alpha, sn, cs);
1307 float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
1308 auto dy = yv - trkWorkITS.getY();
1309 auto dz = zv - trkWorkITS.getZ();
1310 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(xv) < param::MaxVtxX) {
1311 short compXV =
static_cast<short>(xv * 0x7fff / param::MaxVtxX);
1312 mClRes.emplace_back(dy, dz,
alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
1314 LOGP(fatal,
"ITS-TPC seed index is not set for TOF track");
1317 mDetInfoRes.emplace_back().setPV(tdif);
1324 mTrackData.push_back(std::move(trackData));
1326 mGIDsSuccess.push_back(mGIDs[iSeed]);
1327 mTRDGIDsSuccess.push_back(gidTRDUsed);
1329 if (mDumpTrackPoints) {
1330 (*trackDataExtended).clIdx.setEntries(nClValidated);
1331 (*trackDataExtended).nExtDetResid = trackData.
nExtDetResid;
1332 (*trackDataExtended).filterFlag = trackData.
filterFlag;
1333 mTrackDataExtended.push_back(std::move(*trackDataExtended));
1337 (*mDBGOut) <<
"valdata" <<
"params=" << mTrackValidation <<
"trackData=" << (stored ? mTrackData.back() : trackData) <<
"\n";