14#include "GPUParam.inc"
23#include <fairlogger/Logger.h>
40#include <Math/SMatrix.h>
41#include <Math/SVector.h>
43#include <TGeoGlobalMagField.h>
67constexpr float MatchTPCITS::Tan70, MatchTPCITS::Cos70I2, MatchTPCITS::MaxSnp, MatchTPCITS::MaxTgp;
90 LOG(fatal) <<
"init() was not done yet";
95 updateTimeDependentParams();
97 mTimer[SWTot].Start(
false);
100 if (!prepareITSData() || !prepareTPCData() || !prepareFITData()) {
103 if (mVDriftCalibOn) {
104 calib.emplace_back(mTPCVDrift, mTPCDrift.
refVDrift, mTPCDrift.
refTP);
105 calib.emplace_back(mTPCDriftTimeOffset, mTPCDrift.
refTimeOffset, -999.);
108 mTimer[SWDoMatching].Start(
false);
112 mTimer[SWDoMatching].Stop();
113 if constexpr (
false) {
114 mTimer[SWTot].Stop();
117 mTimer[SWTot].Start(
false);
122 bool fullMatchRefitDone =
false;
124 fullMatchRefitDone =
runAfterBurner(matchedTracks, matchLabels, ABTrackletLabels, ABTrackletClusterIDs, ABTrackletRefs, calib);
126 if (!fullMatchRefitDone) {
130 reportSizes(matchedTracks, ABTrackletRefs, ABTrackletClusterIDs, matchLabels, ABTrackletLabels, calib);
132#ifdef _ALLOW_DEBUG_TREES_
139 mTimer[SWTot].Stop();
150 for (
int i = 0;
i < NStopWatches;
i++) {
151 LOGF(info,
"Timing for %15s: Cpu: %.3e Real: %.3e s in %d slots of TF#%d", TimerName[
i], mTimer[
i].CpuTime(), mTimer[
i].RealTime(), mTimer[
i].Counter() - 1, mTFCount);
158#ifdef _ALLOW_DEBUG_TREES_
167 mMatchRecordsTPC.clear();
168 mMatchRecordsITS.clear();
169 mWinnerChi2Refit.clear();
172 mInteractions.clear();
173 mITSROFTimes.clear();
174 mITSTrackROFContMapping.clear();
175 mITSClustersArray.clear();
176 mITSClusterSizes.clear();
178 mTPCABIndexCache.clear();
179 mABWinnersIDs.clear();
180 mABClusterLinkIndex.clear();
181 mNMatchesControl = 0;
184 mITSSectIndexCache[sec].clear();
185 mITSTimeStart[sec].clear();
186 mTPCSectIndexCache[sec].clear();
187 mTPCTimeStart[sec].clear();
194 for (
int i = 0;
i < mNThreads;
i++) {
203 mTPCVDrift =
v.getVDrift();
204 mTPCDriftTimeOffset =
v.getTimeOffset();
219 LOG(error) <<
"Initialization was already done";
222 for (
int i = NStopWatches;
i--;) {
227 YMaxAtXMatchingRef = mParams->
XMatchingRef * 0.17632698;
232 if (!prop->getMatLUT() && mParams->
matCorr == o2::base::Propagator::MatCorrType::USEMatCorrLUT) {
233 LOG(warning) <<
"Requested material LUT is not loaded, switching to TGeo usage";
242#ifdef _ALLOW_DEBUG_TREES_
245 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(),
"recreate");
257 if (fair::Logger::Logging(fair::Severity::info)) {
263void MatchTPCITS::updateTimeDependentParams()
268 mTPCTBinMUS = elParam.ZbinWidth;
269 mTPCTBinNS = mTPCTBinMUS * 1e3;
270 mTPCZMax = detParam.TPClength;
271 mTPCTBinMUSInv = 1. / mTPCTBinMUS;
272 assert(mITSROFrameLengthMUS > 0.0f);
273 mTPCBin2Z = mTPCTBinMUS * mTPCVDrift;
274 mZ2TPCBin = 1. / mTPCBin2Z;
275 mTPCVDriftInv = 1. / mTPCVDrift;
276 mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin;
280 mFieldON = std::abs(mBz) > 0.01;
287 mTPCmeanX0Inv = matbd.meanX2X0 / matbd.length;
290 float scale = mLumiCTP;
292 LOGP(warning,
"Negative scale factor for TPC covariance correction, setting it to zero");
295 mCovDiagInner = trackTune.getCovInnerTotal(scale);
296 mCovDiagOuter = trackTune.getCovOuterTotal(scale);
300void MatchTPCITS::selectBestMatches()
303 mTimer[SWSelectBest].Start(
false);
304 int nValidated = 0, iter = 0;
309 int ntpc = mTPCWork.size(), nremaining = 0;
310 for (
int it = 0; it < ntpc; it++) {
311 auto& tTPC = mTPCWork[it];
312 if (isDisabledTPC(tTPC) || isValidatedTPC(tTPC)) {
316 if (validateTPCMatch(it)) {
318 if (mVDriftCalibOn && (!mFieldON || std::abs(tTPC.getQ2Pt()) < mParams->
maxVDriftTrackQ2Pt)) {
325 LOGP(info,
"iter {}: Validated {} of {} remaining matches", iter, nValidated, nremaining);
328 mNMatches += nValidated;
329 }
while (nValidated);
331 mTimer[SWSelectBest].Stop();
332 LOGP(info,
"Validated {} matches out of {} for {} TPC and {} ITS tracks in {} iterations", mNMatches, mNMatchesControl, mTPCWork.size(), mITSWork.size(), iter);
336bool MatchTPCITS::validateTPCMatch(
int iTPC)
338 auto& tTPC = mTPCWork[iTPC];
339 auto& rcTPC = mMatchRecordsTPC[tTPC.matchID];
341 auto& tITS = mITSWork[rcTPC.partnerID];
342 auto& rcITS = mMatchRecordsITS[tITS.matchID];
346 if (rcITS.partnerID == iTPC) {
347 int cloneID = tITS.getCloneShift();
349 cloneID += rcTPC.partnerID;
350 auto& tITSClone = mITSWork[cloneID];
351 if (isDisabledITS(tITSClone)) {
354 int nextITSCloneMatchID = tITSClone.matchID;
355 if (rcITS.isBetter(mMatchRecordsITS[nextITSCloneMatchID])) {
356 LOGP(
debug,
"Suppressing clone cloneID={} of winner clone {} of source ITS {}", cloneID, rcTPC.partnerID, tITS.sourceID);
357 while (nextITSCloneMatchID >
MinusOne) {
358 auto& rcITSClone = mMatchRecordsITS[nextITSCloneMatchID];
359 removeITSfromTPC(cloneID, rcITSClone.partnerID);
360 nextITSCloneMatchID = rcITSClone.nextRecID;
368 int nextTPC = rcTPC.nextRecID;
370 auto& rcTPCrem = mMatchRecordsTPC[nextTPC];
371 removeTPCfromITS(iTPC, rcTPCrem.partnerID);
372 nextTPC = rcTPCrem.nextRecID;
375 int itsWinID = rcTPC.partnerID;
378 int nextITS = rcITS.nextRecID;
380 auto& rcITSrem = mMatchRecordsITS[nextITS];
381 removeITSfromTPC(itsWinID, rcITSrem.partnerID);
382 nextITS = rcITSrem.nextRecID;
392int MatchTPCITS::getNMatchRecordsTPC(
const TrackLocTPC& tTPC)
const
397 recID = mMatchRecordsTPC[recID].nextRecID;
404int MatchTPCITS::getNMatchRecordsITS(
const TrackLocITS& tTPC)
const
409 auto& itsRecord = mMatchRecordsITS[recID];
410 recID = itsRecord.nextRecID;
420 const float SQRT12DInv = 2. / sqrt(12.);
424 const auto& tpcOrig = mTPCTracksArray[tpcID];
431 tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx);
435 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
437 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
438 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
443 if (extConstrained) {
446 terr += tpcTimeBin2MUS(tpcOrig.hasBothSidesClusters() ? mParams->
safeMarginTPCITSTimeBin : mTPCTimeEdgeTSafeMargin);
448 auto& trc = mTPCWork.emplace_back(
449 TrackLocTPC{_tr, {
t0 - terr,
t0 + terr}, extConstrained ?
t0 : tpcTimeBin2MUS(tpcOrig.getTime0()),
451 terr * (extConstrained ? mTPCExtConstrainedNSigmaInv : SQRT12DInv),
462 if (srcGID.getSource() ==
GTrackID::TPC && !trackTune.sourceLevelTPC) {
463 if (trackTune.useTPCInnerCorr) {
464 trc.updateParams(trackTune.tpcParInner);
470 if (!propagateToRefX(trc)) {
475 mTPCLblWork.emplace_back(mTPCTrkLabels[tpcID]);
483bool MatchTPCITS::prepareTPCData()
486 mTimer[SWPrepTPC].Start(
false);
487 const auto& inp = *mRecoCont;
489 mTPCTracksArray = inp.getTPCTracks();
490 mTPCTrackClusIdx = inp.getTPCTracksClusterRefs();
491 mTPCClusterIdxStruct = &inp.inputsTPCclusters->clusterIndex;
492 mTPCRefitterShMap = inp.clusterShMapTPC;
493 mTPCRefitterOccMap = inp.occupancyMapTPC;
496 mTPCTrkLabels = inp.getTPCTracksMCLabels();
499 int ntr = mTPCTracksArray.size(), ntrW = 0.7 * ntr;
501 mTPCWork.reserve(ntrW);
503 mTPCLblWork.reserve(ntrW);
509 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCCorrMaps, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(),
nullptr,
o2::base::Propagator::Instance());
510 mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
512 if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) {
513 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
516 mTBinClOcc.resize(nTPCOccBins);
517 std::vector<float> mltHistTB(nTPCOccBins);
518 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
519 for (
int i = 0;
i < nTPCOccBins;
i++) {
520 mltHistTB[
i] = mTPCRefitter->getParam()->GetUnscaledMult(tb);
521 tb += mNTPCOccBinLength;
523 for (
int i = nTPCOccBins;
i--;) {
525 if (
i + sumBins < nTPCOccBins) {
526 sm -= mltHistTB[
i + sumBins];
531 mTBinClOcc.resize(1);
534 auto creator = [
this](
auto& trk,
GTrackID gid,
float time0,
float terr) {
535 if constexpr (isITSTrack<decltype(trk)>()) {
540 }
else if (std::abs(trk.getQ2Pt()) > mMinTPCTrackPtInv) {
545 if constexpr (isTPCTrack<decltype(trk)>()) {
547 if (!this->mSkipTPCOnly && trk.getNClusters() > 0) {
548 resAdd = this->addTPCSeed(trk, this->tpcTimeBin2MUS(time0), this->tpcTimeBin2MUS(terr), gid, (tpcIndex = gid.getIndex()));
551 if constexpr (isTPCTOFTrack<decltype(trk)>()) {
553 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
555 if constexpr (isTRDTrack<decltype(trk)>()) {
557 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
559#ifdef _ALLOW_DEBUG_TREES_
570 int nITSROFs = mITSROFTimes.size();
573 auto& indexCache = mTPCSectIndexCache[sec];
575 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" TPC tracks";
577 if (!indexCache.size()) {
580 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
581 auto& trcA = mTPCWork[a];
582 auto& trcB = mTPCWork[b];
583 return (trcA.tBracket.getMax() - trcB.tBracket.getMax()) < 0.;
589 float tmax = mTPCWork[indexCache.back()].tBracket.getMax();
590 if (maxTime < tmax) {
593 int nbins = 1 + (mITSTriggered ? time2ITSROFrameTrig(tmax, 0) : time2ITSROFrameCont(tmax));
594 auto& timeStart = mTPCTimeStart[sec];
595 timeStart.resize(nbins, -1);
599 for (
int itr = 0; itr < (
int)indexCache.size(); itr++) {
600 auto& trc = mTPCWork[indexCache[itr]];
601 while (itsROF < nITSROFs && !(trc.tBracket < mITSROFTimes[itsROF])) {
604 int itsROFMatch = itsROF;
605 if (itsROFMatch && timeStart[--itsROFMatch] == -1) {
606 timeStart[itsROFMatch] = itr;
609 for (
int i = 1;
i < nbins;
i++) {
610 if (timeStart[
i] == -1) {
611 timeStart[
i] = timeStart[
i - 1];
632 mInteractionMUSLUT.clear();
634 mTimer[SWPrepTPC].Stop();
635 return mTPCWork.size() > 0;
639bool MatchTPCITS::prepareITSData()
641 static size_t errCount = 0;
642 constexpr size_t MaxErrors2Report = 10;
644 mTimer[SWPrepITS].Start(
false);
645 const auto& inp = *mRecoCont;
648 mITSClusterROFRec = inp.getITSClustersROFRecords();
649 const auto clusITS = inp.getITSClusters();
650 if (mITSClusterROFRec.empty() || clusITS.empty()) {
651 LOG(info) <<
"No ITS clusters";
654 const auto patterns = inp.getITSClustersPatterns();
655 auto pattIt = patterns.begin();
656 mITSClustersArray.reserve(clusITS.size());
657#ifdef ENABLE_UPGRADES
669 mITSClusterSizes.reserve(clusITS.size());
670 auto pattIt2 = patterns.begin();
671 for (
auto& clus : clusITS) {
672 auto pattID = clus.getPatternID();
674#ifdef ENABLE_UPGRADES
684#ifdef ENABLE_UPGRADES
686 npix = mIT3Dict->getNpixels(pattID, ib);
694 mITSClusterSizes.push_back(std::clamp(npix, 0u, 255u));
698 mITSClsLabels = inp.mcITSClusters.get();
702 mITSTracksArray = inp.getITSTracks();
703 mITSTrackClusIdx = inp.getITSTracksClusterRefs();
704 mITSTrackROFRec = inp.getITSTracksROFRecords();
706 mITSTrkLabels = inp.getITSTracksMCLabels();
708 int nROFs = mITSTrackROFRec.size();
709 mITSWork.reserve(mITSTracksArray.size());
712 const auto& lastClROF = mITSClusterROFRec.back();
713 int nITSClus = lastClROF.getFirstEntry() + lastClROF.getNEntries();
714 mABClusterLinkIndex.resize(nITSClus,
MinusOne);
716 mITSTimeStart[sec].resize(nROFs, -1);
721 trackLTInt.setTimeNotNeeded();
723 for (
int irof = 0; irof < nROFs; irof++) {
724 const auto& rofRec = mITSTrackROFRec[irof];
725 long nBC = rofRec.getBCData().differenceInBC(mStartIR);
726 if (nBC > maxBCs || nBC < 0) {
727 if (++errCount < MaxErrors2Report) {
728 LOGP(alarm,
"ITS ROF#{} start {} is not compatible with TF 1st orbit {} or TF length of {} HBFs",
729 irof, rofRec.getBCData().asString(), mStartIR.
asString(), nHBF);
735 if (!mITSTriggered) {
736 size_t irofCont = nBC / mITSROFrameLengthInBC;
737 if (mITSTrackROFContMapping.size() <= irofCont) {
738 mITSTrackROFContMapping.resize((1 + irofCont / 128) * 128, 0);
740 mITSTrackROFContMapping[irofCont] = irof;
743 mITSROFTimes.emplace_back(tMin, tMax);
746 mITSTimeStart[sec][irof] = mITSSectIndexCache[sec].size();
749 int trlim = rofRec.getFirstEntry() + rofRec.getNEntries();
750 for (
int it = rofRec.getFirstEntry(); it < trlim; it++) {
751 const auto& trcOrig = mITSTracksArray[it];
753 flagUsedITSClusters(trcOrig);
755 if (trcOrig.getParamOut().getX() < 1.) {
758 if (std::abs(trcOrig.getQ2Pt()) > mMinITSTrackPtInv) {
761 int nWorkTracks = mITSWork.size();
763 auto& trc = mITSWork.emplace_back(
TrackLocITS{trcOrig.getParamOut(), {tMin, tMax}, it, irof,
MinusOne});
769 trackLTInt.clearFast();
770 if (!propagateToRefX(trc, &trackLTInt)) {
774 trc.xrho = trackLTInt.getXRho();
775 trc.dL = trackLTInt.getL();
778 mITSLblWork.emplace_back(mITSTrkLabels[it]);
783 mITSSectIndexCache[sector].push_back(nWorkTracks);
791 float trcY = trc.getY(), tgp = trc.getSnp();
792 tgp /= std::sqrt((1.f - tgp) * (1.f + tgp));
794 float dyUpDn[2] = {std::abs((YMaxAtXMatchingRef - trcY) / (tgp + Tan70)), std::abs((YMaxAtXMatchingRef + trcY) / (tgp - Tan70))};
796 int sel = dyUpDn[0] < dyUpDn[1] ? 0 : 1;
797 if (dyUpDn[sel] < mSectEdgeMargin) {
799 addLastTrackCloneForNeighbourSector(sectNeib, &trackLTInt);
804 if (!mITSTriggered) {
805 int nr = mITSTrackROFContMapping.size();
806 for (
int i = 1;
i < nr;
i++) {
807 if (mITSTrackROFContMapping[
i] < mITSTrackROFContMapping[
i - 1]) {
808 mITSTrackROFContMapping[
i] = mITSTrackROFContMapping[
i - 1];
816 auto& indexCache = mITSSectIndexCache[sec];
818 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" ITS tracks";
820 if (!indexCache.size()) {
823 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
824 auto& trackA = mITSWork[a];
825 auto& trackB = mITSWork[b];
826 if (trackA.tBracket.getMin() < trackB.tBracket.getMin()) {
828 }
else if (trackA.tBracket.getMin() > trackB.tBracket.getMin()) {
831 return trackA.getTgl() < trackB.getTgl();
835 mTimer[SWPrepITS].Stop();
841bool MatchTPCITS::prepareFITData()
846 prepareInteractionTimes();
852void MatchTPCITS::doMatching(
int sec)
855 auto& cacheITS = mITSSectIndexCache[sec];
856 auto& cacheTPC = mTPCSectIndexCache[sec];
857 auto& timeStartTPC = mTPCTimeStart[sec];
858 auto& timeStartITS = mITSTimeStart[sec];
859 int nTracksTPC = cacheTPC.size(), nTracksITS = cacheITS.size();
860 if (!nTracksTPC || !nTracksITS) {
862 LOG(info) <<
"Matchng sector " << sec <<
" : N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS <<
" in sector " << sec;
868 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
872 auto minROFITS = mITSWork[cacheITS.front()].roFrame;
874 if (minROFITS >=
int(timeStartTPC.size())) {
875 LOG(info) <<
"ITS min ROFrame " << minROFITS <<
" exceeds all cached TPC track ROF eqiuvalent " << cacheTPC.size() - 1;
879 int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0;
880 int idxMinTPC = timeStartTPC[minROFITS];
885 for (
int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) {
886 auto& trefTPC = mTPCWork[cacheTPC[itpc]];
889 auto tmn = trefTPC.tBracket.getMax() - maxTDriftSafe;
890 itsROBin = mITSTriggered ? time2ITSROFrameTrig(tmn, itsROBin) : time2ITSROFrameCont(tmn);
892 if (itsROBin >=
int(timeStartITS.size())) {
895 int iits0 = timeStartITS[itsROBin];
897 for (
auto iits = iits0; iits < nTracksITS; iits++) {
898 auto& trefITS = mITSWork[cacheITS[iits]];
900 LOG(
debug) <<
"TPC bracket: " << trefTPC.tBracket.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" TPCtgl: " << trefTPC.getTgl() <<
" ITStgl: " << trefITS.getTgl();
901 if (trefTPC.tBracket < trefITS.tBracket) {
904 if (trefTPC.tBracket > trefITS.tBracket) {
909 auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mTPCVDriftInv;
910 auto timeCorr = trefTPC.getCorrectedTime(deltaT);
911 auto timeCorrErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs + mParams->
safeMarginTimeCorrErr;
912 if (mVDriftCalibOn) {
913 timeCorrErr += vdErrT * (250. - abs(trefITS.getZ()));
916 LOG(
debug) <<
"TPC range: " << trange.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" DZ: " << (trefITS.getZ() - trefTPC.getZ()) <<
" DT: " << timeCorr;
918 auto cmpITSBracket = trefITS.tBracket.isOutside(timeCorr);
920 if (trefITS.tBracket.isOutside(trange)) {
925 timeCorr = trefITS.tBracket.getMin();
926 trange.setMin(timeCorr);
928 timeCorr = trefITS.tBracket.getMax();
929 trange.setMax(timeCorr);
938 int rejFlag = compareTPCITSTracks(trefITS, trefTPC, chi2);
940#ifdef _ALLOW_DEBUG_TREES_
973 auto irBracket = tBracket2IRBracket(trange);
974 if (irBracket.isInvalid()) {
978 if (checkInteractionCandidates && mInteractions.size()) {
980 int tmus = trange.getMin();
984 auto entStart = tmus <
int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[tmus] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
985 for (
int ent = entStart; ent < (
int)mInteractions.size(); ent++) {
986 auto cmp = mInteractions[ent].tBracket.isOutside(trange);
1000 registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc], chi2, matchedIC);
1005 LOG(info) <<
"Match sector " << sec <<
" N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS
1006 <<
" N TPC tracks checked: " << nCheckTPCControl <<
" (starting from " << idxMinTPC
1007 <<
"), checks: " << nCheckITSControl <<
", matches:" << nMatchesControl;
1009 mNMatchesControl += nMatchesControl;
1013void MatchTPCITS::suppressMatchRecordITS(
int itsID,
int tpcID)
1016 auto& tITS = mITSWork[itsID];
1017 int topID =
MinusOne, recordID = tITS.matchID;
1019 if (mMatchRecordsITS[recordID].partnerID == tpcID) {
1022 tITS.matchID = mMatchRecordsITS[recordID].nextRecID;
1024 mMatchRecordsITS[topID].nextRecID = mMatchRecordsITS[recordID].nextRecID;
1029 recordID = mMatchRecordsITS[recordID].nextRecID;
1034bool MatchTPCITS::registerMatchRecordTPC(
int iITS,
int iTPC,
float chi2,
int candIC)
1038 auto& tTPC = mTPCWork[iTPC];
1040 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1041 tTPC.
matchID = mMatchRecordsTPC.size();
1042 mMatchRecordsTPC.emplace_back(iITS, chi2,
MinusOne, candIC);
1048 auto& nextMatchRec = mMatchRecordsTPC[nextID];
1050 if (!nextMatchRec.isBetter(chi2, candIC)) {
1051 if (count < mParams->maxMatchCandidates) {
1054 suppressMatchRecordITS(nextMatchRec.partnerID, iTPC);
1055 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1057 nextMatchRec.chi2 = chi2;
1058 nextMatchRec.matchedIC = candIC;
1059 nextMatchRec.partnerID = iITS;
1064 nextID = nextMatchRec.nextRecID;
1070 if (count < mParams->maxMatchCandidates) {
1072 topID = tTPC.
matchID = mMatchRecordsTPC.size();
1074 topID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC.size();
1077 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1078 mMatchRecordsTPC.emplace_back(iITS, chi2, nextID, candIC);
1083 suppressMatchRecordITS(mMatchRecordsTPC[nextID].partnerID, iTPC);
1085 nextID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC[nextID].nextRecID;
1090 nextID = mMatchRecordsTPC[nextID].nextRecID;
1099void MatchTPCITS::registerMatchRecordITS(
const int iITS,
int iTPC,
float chi2,
int candIC)
1102 auto& tITS = mITSWork[iITS];
1103 int idnew = mMatchRecordsITS.size();
1104 auto& newRecord = mMatchRecordsITS.emplace_back(iTPC, chi2,
MinusOne, candIC);
1105 if (tITS.matchID < 0) {
1106 tITS.matchID = idnew;
1111 int topID =
MinusOne, nextRecord = tITS.matchID;
1113 auto& nextMatchRec = mMatchRecordsITS[nextRecord];
1114 if (!nextMatchRec.isBetter(chi2, candIC)) {
1115 newRecord.nextRecID = nextRecord;
1117 tITS.matchID = idnew;
1119 mMatchRecordsITS[topID].nextRecID = idnew;
1124 nextRecord = mMatchRecordsITS[nextRecord].nextRecID;
1128 mMatchRecordsITS[topID].nextRecID = idnew;
1145 if (mVDriftCalibOn) {
1147 err2Tgl += addErr * addErr;
1149 diff *= diff / err2Tgl;
1154 bool testOtherPID =
false;
1155 float itsParam[5] = {tITS.getY(), tITS.getZ(), tITS.getSnp(), tITS.getTgl(), tITS.getQ2Pt()};
1156 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1158 tPID.setPID(tTPC.getPID(),
true);
1159 if (!tPID.correctForELoss(tITS.
xrho)) {
1169 testOtherPID =
true;
1211 auto tITSAlt = tITS;
1212 tITSAlt.setPID(tTPC.getPID());
1216 chi2 = getPredictedChi2NoZ(tITSAlt, tTPC);
1218 chi2 = getPredictedChi2NoZ(tITS, tTPC);
1231 int ntpc = mTPCWork.size();
1232 printf(
"\n\nPrinting all TPC -> ITS matches for %d TPC tracks\n", ntpc);
1233 for (
int i = 0;
i < ntpc;
i++) {
1234 const auto& tTPC = mTPCWork[
i];
1235 int nm = getNMatchRecordsTPC(tTPC);
1236 printf(
"*** trackTPC#%6d %6d : Ncand = %d Best = %d\n",
i, tTPC.
sourceID, nm, tTPC.
matchID);
1239 const auto& rcTPC = mMatchRecordsTPC[recID];
1240 const auto& tITS = mITSWork[rcTPC.partnerID];
1241 printf(
" * cand %2d : ITS track %6d(src:%6d) Chi2: %.2f\n",
count, rcTPC.partnerID, tITS.
sourceID, rcTPC.chi2);
1243 recID = rcTPC.nextRecID;
1252 int nits = mITSWork.size();
1253 printf(
"\n\nPrinting all ITS -> TPC matches for %d ITS tracks\n", nits);
1255 for (
int i = 0;
i < nits;
i++) {
1256 const auto& tITS = mITSWork[
i];
1257 printf(
"*** trackITS#%6d %6d : Ncand = %d Best = %d\n",
i, tITS.
sourceID, getNMatchRecordsITS(tITS), tITS.
matchID);
1260 const auto& rcITS = mMatchRecordsITS[recID];
1261 const auto& tTPC = mTPCWork[rcITS.partnerID];
1262 printf(
" * cand %2d : TPC track %6d(src:%6d) Chi2: %.2f\n",
count, rcITS.partnerID, tTPC.
sourceID, rcITS.chi2);
1264 recID = rcITS.nextRecID;
1286 covMat(0, 0) =
static_cast<double>(trITS.getSigmaY2()) +
static_cast<double>(trTPC.getSigmaY2());
1287 covMat(1, 0) =
static_cast<double>(trITS.getSigmaSnpY()) +
static_cast<double>(trTPC.getSigmaSnpY());
1288 covMat(1, 1) =
static_cast<double>(trITS.getSigmaSnp2()) +
static_cast<double>(trTPC.getSigmaSnp2());
1289 covMat(2, 0) =
static_cast<double>(trITS.getSigmaTglY()) +
static_cast<double>(trTPC.getSigmaTglY());
1290 covMat(2, 1) =
static_cast<double>(trITS.getSigmaTglSnp()) +
static_cast<double>(trTPC.getSigmaTglSnp());
1291 covMat(2, 2) =
static_cast<double>(trITS.getSigmaTgl2()) +
static_cast<double>(trTPC.getSigmaTgl2());
1292 if (mVDriftCalibOn) {
1294 covMat(2, 2) += addErr * addErr;
1296 covMat(3, 0) =
static_cast<double>(trITS.getSigma1PtY()) +
static_cast<double>(trTPC.getSigma1PtY());
1297 covMat(3, 1) =
static_cast<double>(trITS.getSigma1PtSnp()) +
static_cast<double>(trTPC.getSigma1PtSnp());
1298 covMat(3, 2) =
static_cast<double>(trITS.getSigma1PtTgl()) +
static_cast<double>(trTPC.getSigma1PtTgl());
1299 covMat(3, 3) =
static_cast<double>(trITS.getSigma1Pt2()) +
static_cast<double>(trTPC.getSigma1Pt2());
1300 if (!covMat.Invert()) {
1301 LOG(error) <<
"Cov.matrix inversion failed: " << covMat;
1304 double chi2diag = 0., chi2ndiag = 0.,
1310 chi2diag += diff[
i] * diff[
i] * covMat(
i,
i);
1311 for (
int j =
i;
j--;) {
1312 chi2ndiag += diff[
i] * diff[
j] * covMat(
i,
j);
1315 return chi2diag + 2. * chi2ndiag;
1324 mITSWork.push_back(mITSWork.back());
1325 auto& trc = mITSWork.back();
1329 mITSSectIndexCache[sector].push_back(mITSWork.size() - 1);
1331 mITSWork.back().setCloneBefore();
1333 mITSWork.back().xrho = trackLTInt->getXRho();
1334 mITSWork.back().dL = trackLTInt->getL();
1336 mITSWork[mITSWork.size() - 2].setCloneAfter();
1338 mITSLblWork.emplace_back(mITSTrkLabels[trc.sourceID]);
1341 mITSWork.pop_back();
1350 constexpr float TgHalfSector = 0.17632698f;
1351 bool refReached =
false;
1359 if (fabs(trc.getY()) < mParams->
XMatchingRef * TgHalfSector) {
1363 if (!trialsLeft--) {
1367 if (!trc.rotate(alphaNew) != 0) {
1371 return refReached && std::abs(trc.getSnp()) < MaxSnp;
1378 printf(
"\n******************** TPC-ITS matching component ********************\n");
1380 printf(
"init is not done yet\n");
1384 printf(
"MC truth: %s\n", mMCTruthON ?
"on" :
"off");
1385 printf(
"Matching reference X: %.3f\n", mParams->
XMatchingRef);
1386 printf(
"Account Z dimension: %s\n", mCompareTracksDZ ?
"on" :
"off");
1388 printf(
"Max number ITS candidates per TPC track: %d\n", mParams->
maxMatchCandidates);
1389 printf(
"Crude cut on track params: ");
1395 printf(
"NSigma^2 cut on track params: ");
1403#ifdef _ALLOW_DEBUG_TREES_
1405 printf(
"Output debug tree (%s) file: %s\n", mDBGFlags ?
"on" :
"off", mDebugTreeFileName.data());
1407 printf(
"Debug stream flags:\n");
1412 printf(
"* winner matches\n");
1417 printf(
"**********************************************************************\n");
1424 mTimer[SWRefit].Start(
false);
1425 matchedTracks.reserve(mNMatches + mABWinnersIDs.size());
1426 matchedTracks.resize(mNMatches);
1428 matchLabels.reserve(mNMatches + mABWinnersIDs.size());
1429 matchLabels.resize(mNMatches);
1431 if (mVDriftCalibOn) {
1432 calib.reserve(mNCalibPrelim * 1.2 + 1);
1434 std::vector<int> tpcToFit;
1435 tpcToFit.reserve(mNMatches);
1436 for (
int iTPC = 0; iTPC < (
int)mTPCWork.size(); iTPC++) {
1437 const auto& tTPC = mTPCWork[iTPC];
1438 if (!isDisabledTPC(tTPC) && tTPC.
gid.testBit(0)) {
1439 tpcToFit.push_back(iTPC);
1442 LOG(
debug) <<
"Refitting winner matches";
1443 mWinnerChi2Refit.resize(mITSWork.size(), -1.f);
1444 int nToFit = (
int)tpcToFit.size();
1445 unsigned int nFailedRefit{0};
1448#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) \
1449 reduction(+ : nFailedRefit)
1451 for (
int ifit = 0; ifit < nToFit; ifit++) {
1452 int iTPC = tpcToFit[ifit], iITS;
1453 const auto& tTPC = mTPCWork[iTPC];
1454 if (
refitTrackTPCITS(ifit, iTPC, iITS, matchedTracks, matchLabels, calib)) {
1455 mWinnerChi2Refit[iITS] = matchedTracks.back().getChi2Refit();
1460 LOGP(info,
"Failed {} TPC-ITS refits out of {}", nFailedRefit, nToFit);
1465 for (
int ifit = 0; ifit < nToFit; ifit++) {
1466 int itpc = tpcToFit[ifit];
1467 if (!matchedTracks[ifit].
isValid()) {
1468 while (--last > ifit && !matchedTracks[last].
isValid()) {
1471 matchedTracks[ifit] = matchedTracks[last];
1472 matchedTracks[last].invalidate();
1473 itpc = tpcToFit[last];
1475 matchLabels[ifit] = matchLabels[last];
1481 if (mDBGOut || mVDriftCalibOn) {
1487 matchedTracks.resize(mNMatches);
1489 matchLabels.resize(mNMatches);
1491 mTimer[SWRefit].Stop();
1497 const auto& tTPC = mTPCWork[iTPC];
1498 int iITS = mMatchRecordsTPC[tTPC.
matchID].partnerID;
1499 const auto& tITS = mITSWork[iITS];
1500 float minDiffFT0 = -999.,
timeC = 0.f;
1501 std::vector<float> dtimes;
1503 if (fillVDCalib || mDBGOut) {
1506 if (mInteractions.size()) {
1507 int timeC0 =
timeC - minDiffA;
1511 auto entStart = timeC0 <
int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[timeC0] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
1512 for (
int ent = entStart; ent < (
int)mInteractions.size(); ent++) {
1513 float diff = mInteractions[ent].tBracket.mean() -
timeC;
1514 if (diff > minDiffA) {
1517 if (diff < -minDiffA) {
1520 dtimes.push_back(diff);
1522 minDiffA = std::abs(minDiffFT0);
1527 calib.emplace_back(tITS.getTgl(), tTPC.getTgl(), minDiffFT0);
1529#ifdef _ALLOW_DEBUG_TREES_
1533 itsRefPIDCorr.setX(0);
1534 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1535 itsRefAltPID = mITSTracksArray[tITS.
sourceID].getParamOut();
1536 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1537 itsRefPIDCorr = itsRefAltPID;
1539 if (!itsRefPIDCorr.correctForELoss(tITS.
xrho)) {
1540 itsRefPIDCorr.setX(-10);
1542 float q2ptPID = itsRefPIDCorr.getQ2Pt();
1544 itsRefPIDCorr = tITS;
1545 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1546 itsRefPIDCorr.setQ2Pt(q2ptPID);
1547 auto snp = tITS.getSnp() + dCurvL;
1548 if (std::abs(snp) >= 1.) {
1549 snp = std::copysign(0.99, snp);
1551 itsRefPIDCorr.setSnp(snp);
1552 itsRefPIDCorr.setY(tITS.getY() + dCurvL * dLEff * 0.5);
1556 itsRefAltPID.setX(-10);
1559 int tb = mTPCTracksArray[tTPC.
sourceID].getTime0() * mNTPCOccBinLengthInv;
1560 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
1561 (*mDBGOut) <<
"refit"
1562 <<
"tpcOrig=" << mTPCTracksArray[tTPC.
sourceID] <<
"itsOrig=" << mITSTracksArray[tITS.
sourceID] <<
"itsRef=" << tITS <<
"tpcRef=" << tTPC <<
"matchRefit=" <<
match
1563 <<
"timeCorr=" <<
timeC <<
"dTimeFT0=" << minDiffFT0 <<
"dTimes=" << dtimes
1564 <<
"itsRefAltPID=" << itsRefAltPID <<
"itsRefPIDCorr=" << itsRefPIDCorr;
1566 (*mDBGOut) <<
"refit"
1567 <<
"itsLbl=" << mITSLblWork[iITS] <<
"tpcLbl=" << mTPCLblWork[iTPC];
1569 (*mDBGOut) <<
"refit"
1570 <<
"multTPC=" << mltTPC
1571 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
1572 <<
"multITSCl=" << mITSClusterROFRec[tITS.
roFrame].getNEntries()
1573 <<
"tf=" << mTFCount <<
"\n";
1583 const float maxStep = 2.f;
1584 const auto& tTPC = mTPCWork[iTPC];
1585 const auto& tpcMatchRec = mMatchRecordsTPC[tTPC.
matchID];
1586 iITS = tpcMatchRec.partnerID;
1587 const auto& tITS = mITSWork[iITS];
1588 const auto& itsTrOrig = mITSTracksArray[tITS.
sourceID];
1589 auto& trfit = matchedTracks[slot];
1592 trfit.getParamOut().setUserField(0);
1593 trfit.setPID(tTPC.getPID(),
true);
1594 trfit.getParamOut().setPID(tTPC.getPID(),
true);
1597 if (!mCompareTracksDZ) {
1598 trfit.setZ(tITS.getZ());
1600 float deltaT = (trfit.getZ() - tTPC.getZ()) * mTPCVDriftInv;
1603 timeErr = mITSTimeResMUS;
1626 int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters();
1630 int clEntry = itsTrOrig.getFirstClusterEntry();
1634 if (mVDriftCalibOn) {
1640 for (
int icl = 0; icl < ncl; icl++) {
1641 const auto& clus = mITSClustersArray[mITSTrackClusIdx[clEntry++]];
1642 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1643 if (!trfit.rotate(
alpha) ||
1647 !propagator->propagateToX(trfit,
x, propagator->getNominalBz(),
1648 MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) {
1651 chi2 += trfit.getPredictedChi2(clus);
1652 if (!trfit.update(clus)) {
1657 if (nclRefit != ncl) {
1658 LOGP(
debug,
"Refit in ITS failed after ncl={}, match between TPC track #{} and ITS track #{}", nclRefit, tTPC.
sourceID, tITS.
sourceID);
1659 LOGP(
debug,
"{:s}", trfit.asString());
1669 if (!propagator->propagateToDCA(vtxDummy.getXYZ(), trpar, propagator->getNominalBz(),
1670 maxStep, MatCorrType::USEMatCorrNONE,
nullptr, &trfit.getLTIntegralOut())) {
1671 LOG(error) <<
"LTOF integral might be incorrect";
1673 auto& tofL = trfit.getLTIntegralOut();
1674 tofL.setX2X0(-tofL.getX2X0());
1675 tofL.setXRho(-tofL.getXRho());
1678 auto& tracOut = trfit.getParamOut();
1679 if (tTPC.getPID() > tITS.getPID() && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1681 tracOut = mITSTracksArray[tITS.
sourceID].getParamOut();
1682 tracOut.setPID(tTPC.getPID(),
true);
1684 LOGP(
debug,
"Failed to rotate ITSouter with imposed PID to TPC alpha {} or propagate to X={}: {:s}", tTPC.getAlpha(), mParams->
XMatchingRef, tracOut.asString());
1692 !propagator->PropagateToXBxByBz(tracOut, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1693 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1697 if (mVDriftCalibOn) {
1701 auto posStart = tracOut.getXYZGlo();
1702 auto tImposed =
timeC * mTPCTBinMUSInv;
1703 if (std::abs(tImposed - mTPCTracksArray[tTPC.
sourceID].getTime0()) > 550) {
1704 LOGP(alarm,
"Impossible imposed timebin {} for TPC track time0:{}, dBwd:{} dFwd:{} TB | ZShift:{}, TShift:{}", tImposed, mTPCTracksArray[tTPC.
sourceID].getTime0(),
1705 mTPCTracksArray[tTPC.
sourceID].getDeltaTBwd(), mTPCTracksArray[tTPC.
sourceID].getDeltaTFwd(), trfit.getZ() - tTPC.getZ(), deltaT);
1706 LOGP(info,
"Trc: {}", mTPCTracksArray[tTPC.
sourceID].asString());
1710 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(), tImposed, &chi2Out,
true,
false);
1716 auto posEnd = tracOut.getXYZGlo();
1717 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1718 tofL.addStep(lInt, tracOut.getQ2P2());
1719 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1723 if (trackTune.useTPCOuterCorr) {
1724 tracOut.updateParams(trackTune.tpcParOuter);
1730 trfit.setChi2Match(tpcMatchRec.chi2);
1731 trfit.setChi2Refit(chi2);
1732 trfit.setTimeMUS(
timeC, timeErr);
1737 matchLabels[slot] = mTPCLblWork[iTPC];
1738 matchLabels[slot].setFakeFlag(mITSLblWork[iITS] != mTPCLblWork[iTPC]);
1749 const float maxStep = 2.f;
1750 const auto& tTPC = mTPCWork[seed.
tpcWID];
1752 auto& newtr = matchedTracks.emplace_back(winLink, winLink);
1753 auto& tracOut = newtr.getParamOut();
1754 auto& tofL = newtr.getLTIntegralOut();
1757 tracOut.resetCovariance();
1759 propagator->estimateLTFast(tofL, winLink);
1761 const auto& itsClRefs = ABTrackletRefs[iITSAB];
1762 int nclRefit = 0, ncl = itsClRefs.getNClusters();
1765 for (
int icl = itsClRefs.getFirstEntry(); icl < itsClRefs.getEntriesBound(); icl++) {
1766 const auto& clus = mITSClustersArray[ABTrackletClusterIDs[icl]];
1767 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1768 if (!tracOut.rotate(
alpha, refLin, propagator->getNominalBz()) ||
1772 !propagator->propagateToX(tracOut, refLin,
x, propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, &tofL)) {
1775 chi2 += tracOut.getPredictedChi2(clus);
1776 if (!tracOut.update(clus)) {
1781 if (nclRefit != ncl) {
1782 LOGP(
debug,
"AfterBurner refit in ITS failed after ncl={}, match between TPC track #{} and ITS tracklet #{}", nclRefit, tTPC.
sourceID, iITSAB);
1783 LOGP(
debug,
"{:s}", tracOut.asString());
1784 matchedTracks.pop_back();
1788 float timeC = mInteractions[seed.
ICCanID].tBracket.mean();
1789 float timeErr = mInteractions[seed.
ICCanID].tBracket.delta();
1793 !propagator->PropagateToXBxByBz(tracOut, refLin, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1794 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1795 matchedTracks.pop_back();
1799 auto posStart = tracOut.getXYZGlo();
1800 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(),
timeC * mTPCTBinMUSInv, &chi2Out,
true,
false);
1803 matchedTracks.pop_back();
1806 auto posEnd = tracOut.getXYZGlo();
1807 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1808 tofL.addStep(lInt, tracOut.getQ2P2());
1809 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1812 if (trackTune.useTPCOuterCorr) {
1813 tracOut.updateParams(trackTune.tpcParOuter);
1820 newtr.setChi2Match(winLink.chi2Norm());
1821 newtr.setChi2Refit(chi2);
1822 newtr.setTimeMUS(
timeC, timeErr);
1830bool MatchTPCITS::refitTPCInward(
o2::track::TrackParCov& trcIn,
float& chi2,
float xTgt,
int trcID,
float timeTB)
const
1833 const auto& tpcTrOrig = mTPCTracksArray[trcID];
1835 trcIn = tpcTrOrig.getOuterParam();
1839 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(trcIn, tpcTrOrig.getClusterRef(), timeTB, &chi2,
false,
true);
1841 LOG(warning) <<
"Refit failed";
1842 LOG(warning) << trcIn.asString();
1848 if (!propagator->PropagateToXBxByBz(trcIn, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1849 LOG(
debug) <<
"Propagation to target X=" << xTgt <<
" failed, Xtr=" << trcIn.getX() <<
" snp=" << trcIn.getSnp() <<
" pT=" << trcIn.getPt();
1858int MatchTPCITS::prepareABSeeds()
1861 const auto& outerLr = mRGHelper.
layers.back();
1863 const float ROuter = outerLr.rRange.getMax() + 0.5f;
1866 for (
int iTPC = 0; iTPC < (
int)mTPCWork.size(); iTPC++) {
1867 auto& tTPC = mTPCWork[iTPC];
1868 if (isDisabledTPC(tTPC)) {
1874 !
propagator->PropagateToXBxByBz(tTPC, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1877 mTPCABIndexCache.push_back(iTPC);
1881 std::sort(mTPCABIndexCache.begin(), mTPCABIndexCache.end(), [
this](
int a,
int b) {
1882 auto& trcA = mTPCWork[a];
1883 auto& trcB = mTPCWork[b];
1884 return (trcA.tBracket.getMin() - trcB.tBracket.getMin()) < 0.;
1887 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
1888 int nIntCand = mInteractions.size(), nTPCCand = mTPCABIndexCache.size();
1890 for (
int ic = 0; ic < nIntCand; ic++) {
1891 int icFirstSeed = mTPCABSeeds.size();
1892 auto& intCand = mInteractions[ic];
1893 auto tic = intCand.tBracket.mean();
1894 for (
int it = tpcStart; it < nTPCCand; it++) {
1895 auto& trc = mTPCWork[mTPCABIndexCache[it]];
1896 auto cmp = trc.tBracket.isOutside(intCand.tBracket);
1901 if (trc.tBracket.getMin() + maxTDriftSafe < intCand.tBracket.getMin()) {
1907 float dt = trc.getSignedDT(tic - trc.time0);
1908 float dz = dt * mTPCVDrift,
z = trc.getZ() + dz;
1909 if (outerLr.zRange.isOutside(
z, std::sqrt(trc.getSigmaZ2()) + 2.)) {
1913 auto& seed = mTPCABSeeds.emplace_back(mTPCABIndexCache[it], ic, trc);
1916 intCand.seedsRef.set(icFirstSeed, mTPCABSeeds.size() - icFirstSeed);
1918 return mTPCABIndexCache.size();
1922int MatchTPCITS::prepareInteractionTimes()
1925 const float ft0Uncertainty = 0.5e-3;
1926 int nITSROFs = mITSROFTimes.size();
1927 if (mFITInfo.size()) {
1929 for (
const auto& ft : mFITInfo) {
1933 auto fitTime = ft.getInteractionRecord().differenceInBCMUS(mStartIR);
1937 if (
size_t(fitTime) >= mInteractionMUSLUT.size()) {
1938 mInteractionMUSLUT.resize(
size_t(fitTime) + 1, -1);
1940 if (mInteractionMUSLUT[fitTime] < 0) {
1941 mInteractionMUSLUT[fitTime] = mInteractions.size();
1943 for (; rof < nITSROFs; rof++) {
1944 if (mITSROFTimes[rof] < fitTime) {
1949 if (rof >= nITSROFs) {
1956 for (
auto&
val : mInteractionMUSLUT) {
1963 return mInteractions.size();
1970 mTimer[SWABSeeds].Start(
false);
1973 int nIntCand = mInteractions.size(), nABSeeds = mTPCABSeeds.size();
1974 LOGP(info,
"AfterBurner will check {} seeds from {} TPC tracks and {} interaction candidates with {} threads", nABSeeds, mTPCABIndexCache.size(), nIntCand, mNThreads);
1975 mTimer[SWABSeeds].Stop();
1976 if (!nIntCand || !mTPCABSeeds.size()) {
1979 mTimer[SWABMatch].Start(
false);
1981 std::vector<ITSChipClustersRefs> itsChipClRefsBuff(mNThreads);
1982#ifdef ENABLE_UPGRADES
1985 std::generate(itsChipClRefsBuff.begin(), itsChipClRefsBuff.end(), []() {
1986 return ITSChipClustersRefs(o2::its::GeometryTGeo::Instance()->getNumberOfChips());
1991#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
1993 for (
int ic = 0; ic < nIntCand; ic++) {
1994 const auto& intCand = mInteractions[ic];
1995 LOGP(
debug,
"cand T {} Entries: {} : {} : {} | ITS ROF: {}", intCand.tBracket.mean(), intCand.seedsRef.getEntries(), intCand.seedsRef.getFirstEntry(), intCand.seedsRef.getEntriesBound(), intCand.rofITS);
1996 if (!intCand.seedsRef.getEntries()) {
2000 uint8_t tid = (uint8_t)omp_get_thread_num();
2004 fillClustersForAfterBurner(intCand.rofITS, 1, itsChipClRefsBuff[tid]);
2005 for (
int is = intCand.seedsRef.getFirstEntry(); is < intCand.seedsRef.getEntriesBound(); is++) {
2006 processABSeed(is, itsChipClRefsBuff[tid], tid);
2009 mTimer[SWABMatch].Stop();
2010 mTimer[SWABWinners].Start(
false);
2017 std::vector<SID> candAB;
2018 candAB.reserve(nABSeeds);
2019 mABWinnersIDs.reserve(mTPCABIndexCache.size());
2021 for (
int i = 0;
i < nABSeeds;
i++) {
2022 auto& ABSeed = mTPCABSeeds[
i];
2023 if (ABSeed.isDisabled()) {
2026 candAB.emplace_back(SID{
i, ABSeed.getLink(ABSeed.getBestLinkID()).chi2Norm()});
2028 std::sort(candAB.begin(), candAB.end(), [](SID
a, SID
b) { return a.chi2 < b.chi2; });
2029 for (
int i = 0;
i < (
int)candAB.size();
i++) {
2030 auto& ABSeed = mTPCABSeeds[candAB[
i].seedID];
2031 if (ABSeed.isDisabled()) {
2035 auto& tTPC = mTPCWork[ABSeed.tpcWID];
2041 auto bestID = ABSeed.getBestLinkID();
2042 if (ABSeed.checkLinkHasUsedClusters(bestID, mABClusterLinkIndex)) {
2043 ABSeed.setNeedAlternative();
2047 ABSeed.validate(bestID);
2048 ABSeed.flagLinkUsedClusters(bestID, mABClusterLinkIndex);
2049 mABWinnersIDs.push_back(tTPC.
matchID = candAB[
i].seedID);
2050 mNABRefsClus += ABSeed.getNLayers();
2054 mTimer[SWABWinners].Stop();
2055 mTimer[SWABRefit].Start(
false);
2056 refitABWinners(matchedTracks, matchLabels, ABTrackletLabels, ABTrackletClusterIDs, ABTrackletRefs, calib);
2057 mTimer[SWABRefit].Stop();
2068 ABTrackletClusterIDs.reserve(mNABRefsClus);
2069 ABTrackletRefs.reserve(mABWinnersIDs.size());
2071 ABTrackletLabels.reserve(mABWinnersIDs.size());
2073 if (matchedTracks.capacity() < mABWinnersIDs.size() + matchedTracks.size()) {
2074 LOGP(warn,
"need to expand matched tracks container from {} to {}", matchedTracks.capacity(), mABWinnersIDs.size() + matchedTracks.size());
2075 matchedTracks.reserve(mABWinnersIDs.size() + matchedTracks.size());
2077 matchLabels.reserve(mABWinnersIDs.size() + matchedTracks.size());
2081 std::map<o2::MCCompLabel, int> labelOccurence;
2082 auto accountClusterLabel = [&labelOccurence, itsClLabs = mITSClsLabels](
int clID) {
2083 auto labels = itsClLabs->getLabels(clID);
2084 for (
auto lab :
labels) {
2086 labelOccurence[lab]++;
2091 for (
auto wid : mABWinnersIDs) {
2092 const auto& ABSeed = mTPCABSeeds[wid];
2093 int start = ABTrackletClusterIDs.size();
2094 int lID = ABSeed.winLinkID, ncl = 0;
2095 auto& clref = ABTrackletRefs.emplace_back(
start, ncl);
2097 const auto& winL = ABSeed.getLink(lID);
2099 ABTrackletClusterIDs.push_back(winL.clID);
2101 clref.pattern |= 0x1 << winL.layerID;
2102 clref.setClusterSize(winL.layerID, mITSClusterSizes[winL.clID]);
2104 accountClusterLabel(winL.clID);
2107 lID = winL.parentID;
2109 clref.setEntries(ncl);
2110 if (!
refitABTrack(ABTrackletRefs.size() - 1, ABSeed, matchedTracks, ABTrackletClusterIDs, ABTrackletRefs)) {
2111 ABTrackletRefs.pop_back();
2112 ABTrackletClusterIDs.resize(
start);
2114 labelOccurence.clear();
2130 labelOccurence.clear();
2131 ABTrackletLabels.push_back(lab);
2132 auto& lblGlo = matchLabels.emplace_back(mTPCLblWork[ABSeed.tpcWID]);
2133 lblGlo.setFakeFlag(lab != lblGlo);
2134 LOG(
debug) <<
"ABWinner ncl=" << ncl <<
" mcLBAB " << lab <<
" mcLBGlo " << lblGlo <<
" chi2=" << ABSeed.getLink(ABSeed.winLinkID).chi2Norm() <<
" pT = " << ABSeed.track.getPt();
2138 LOG(info) <<
"AfterBurner validated " << ABTrackletRefs.size() <<
" tracks";
2142void MatchTPCITS::processABSeed(
int sid,
const ITSChipClustersRefs& itsChipClRefs, uint8_t tID)
2145 auto& ABSeed = mTPCABSeeds[sid];
2146 ABSeed.threadID = tID;
2147 ABSeed.linksEntry = mABLinksPool.
threadPool[tID].size();
2150 int nextLinkID = ABSeed.firstInLr[ilr];
2151 if (nextLinkID < 0) {
2155 const auto& seedLink = ABSeed.getLink(nextLinkID);
2156 if (seedLink.isDisabled()) {
2157 nextLinkID = seedLink.nextOnLr;
2160 int next2nextLinkID = seedLink.nextOnLr;
2161 followABSeed(seedLink, itsChipClRefs, nextLinkID, ilr - 1, ABSeed);
2162 nextLinkID = next2nextLinkID;
2166 auto candID = ABSeed.getBestLinkID();
2167 if (ABSeed.isDisabled() ||
2172 mABLinksPool.
threadPool[tID].resize(
size_t(ABSeed.linksEntry));
2193 const auto& lr = mRGHelper.
layers[lrID];
2196 !
propagator->propagateToX(seedC, xTgt,
propagator->getNominalBz(), MaxSnp, 2., mUseMatCorrFlag)) {
2200 float zDRStep = -seedC.getTgl() * lr.rRange.delta();
2201 float errZ = std::sqrt(seedC.getSigmaZ2() + mParams->
err2ABExtraZ);
2202 if (lr.zRange.isOutside(seedC.getZ(), mParams->
nABSigmaZ * errZ + std::abs(zDRStep))) {
2205 std::vector<int> chipSelClusters;
2212 seedC.getCircleParams(
propagator->getNominalBz(), trcCircle, sna, csa);
2214 seedC.getLineParams(trcLinPar, sna, csa);
2218 float phi = std::atan2(yCurr, xCurr);
2220 int nLad2Check = 0, ladIDguess = lr.getLadderID(phi), chipIDguess = lr.getChipID(seedC.getZ() + 0.5 * zDRStep);
2221 std::array<int, MaxLadderCand> lad2Check;
2222 nLad2Check = mFieldON ? findLaddersToCheckBOn(lrID, ladIDguess, trcCircle, errYFrac, lad2Check) : findLaddersToCheckBOff(lrID, ladIDguess, trcLinPar, errYFrac, lad2Check);
2224 for (
int ilad = nLad2Check; ilad--;) {
2225 int ladID = lad2Check[ilad];
2226 const auto& lad = lr.ladders[ladID];
2230 float t = 1e9, xCross, yCross;
2231 const auto& chipC = lad.chips[chipIDguess];
2233 chipC.xyEdges.circleCrossParam(trcCircle, t);
2235 chipC.xyEdges.lineCrossParam(trcLinPar, t);
2237 chipC.xyEdges.eval(t, xCross, yCross);
2238 float dx = xCross - xCurr, dy = yCross - yCurr, dst2 = dx * dx + dy * dy,
dst = sqrtf(dst2);
2240 float zCross = seedC.getZ() + seedC.getTgl() * (dst2 < 2 * (dx * xCurr + dy * yCurr) ?
dst : -
dst);
2242 for (
int ich = -1; ich < 2; ich++) {
2243 int chipID = chipIDguess + ich;
2245 if (chipID < 0 || chipID >=
static_cast<int>(lad.chips.size())) {
2248 if (lad.chips[chipID].zRange.isOutside(zCross, mParams->
nABSigmaZ * errZ)) {
2251 const auto& clRange = itsChipClRefs.
chipRefs[lad.chips[chipID].id];
2252 if (!clRange.getEntries()) {
2253 LOG(
debug) <<
"No clusters in chip range";
2257 float errYcalp = errY * (csa * chipC.csAlp + sna * chipC.snAlp);
2259 float yTrack = -xCross * chipC.snAlp + yCross * chipC.csAlp;
2260 if (!preselectChipClusters(chipSelClusters, clRange, itsChipClRefs, yTrack, zCross, tolerY, tolerZ)) {
2261 LOG(
debug) <<
"No compatible clusters found";
2266 if (!trcLC.rotate(chipC.alp) || !trcLC.propagateTo(chipC.xRef,
propagator->getNominalBz())) {
2267 LOG(
debug) <<
" failed to rotate to alpha=" << chipC.alp <<
" or prop to X=" << chipC.xRef;
2272 for (
auto clID : chipSelClusters) {
2273 const auto& cls = mITSClustersArray[clID];
2274 auto chi2 = trcLC.getPredictedChi2(cls);
2278 int lnkID = registerABTrackLink(ABSeed, trcLC, clID, seedID, lrID, ladID, chi2);
2296void MatchTPCITS::accountForOverlapsAB(
int lrSeed)
2299 LOG(warning) <<
"TODO";
2304 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2308 const auto& lr = mRGHelper.
layers[ilr];
2309 int nacc = 0, jmp = 0;
2310 if (lr.ladders[lad0].xyEdges.seenByCircle(circle, errYFrac)) {
2311 lad2Check[nacc++] = lad0;
2313 bool doUp =
true, doDn =
true;
2316 int ldID = (lad0 + jmp) % lr.nLadders;
2317 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2318 lad2Check[nacc++] = ldID;
2324 int ldID = lad0 - jmp;
2326 ldID += lr.nLadders;
2328 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2329 lad2Check[nacc++] = ldID;
2340 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2344 const auto& lr = mRGHelper.
layers[ilr];
2345 int nacc = 0, jmp = 0;
2346 if (lr.ladders[lad0].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2347 lad2Check[nacc++] = lad0;
2349 bool doUp =
true, doDn =
true;
2352 int ldID = (lad0 + jmp) % lr.nLadders;
2353 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2354 lad2Check[nacc++] = ldID;
2360 int ldID = lad0 - jmp;
2362 ldID += lr.nLadders;
2364 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2365 lad2Check[nacc++] = ldID;
2392 auto& nextLink = ABSeed.
getLink(nextID);
2394 bool newIsBetter = parentID <=
MinusOne ? isBetter(chi2, nextLink.chi2) : isBetter(ABSeed.getLink(parentID).chi2NormPredict(chi2Cl), nextLink.chi2Norm());
2396 if (count < mParams->maxABLinksOnLayer) {
2397 ABSeed.
addLink(trc, clID, parentID, nextID, lr, nc, laddID, chi2);
2410 nextID = nextLink.nextOnLr;
2413 if (count < mParams->maxABLinksOnLayer) {
2433 auto tpcTrOrig = mTPCTracksArray[tTPC.
sourceID];
2456 float dDrift = (timeIC - tTPC.
time0) * mTPCBin2Z;
2473void MatchTPCITS::fillClustersForAfterBurner(
int rofStart,
int nROFs,
ITSChipClustersRefs& itsChipClRefs)
2478 int first = mITSClusterROFRec[rofStart].getFirstEntry(),
last =
first;
2479 for (
int ir = nROFs;
ir--;) {
2480 last += mITSClusterROFRec[rofStart +
ir].getNEntries();
2482 itsChipClRefs.
clear();
2483 auto& idxSort = itsChipClRefs.
clusterID;
2484 for (
int icl =
first; icl <
last; icl++) {
2485 if (mABClusterLinkIndex[icl] !=
MinusTen) {
2486 idxSort.push_back(icl);
2490 const auto& clusArr = mITSClustersArray;
2491 std::sort(idxSort.begin(), idxSort.end(), [&clusArr](
int i,
int j) {
2492 const auto &clI = clusArr[i], &clJ = clusArr[j];
2493 if (clI.getSensorID() < clJ.getSensorID()) {
2496 if (clI.getSensorID() == clJ.getSensorID()) {
2497 return clI.getZ() < clJ.getZ();
2502 int ncl = idxSort.size();
2503 int lastSens = -1, nClInSens = 0;
2505 for (
int icl = 0; icl <
ncl; icl++) {
2506 const auto& clus = mITSClustersArray[idxSort[icl]];
2507 int sens = clus.getSensorID();
2508 if (sens != lastSens) {
2510 chipClRefs->setEntries(nClInSens);
2513 chipClRefs = &itsChipClRefs.
chipRefs[(lastSens = sens)];
2514 chipClRefs->setFirstEntry(icl);
2519 chipClRefs->setEntries(nClInSens);
2526 mITSTimeBiasInBC =
n;
2533 mITSROFrameLengthMUS = fums;
2534 mITSTimeResMUS = mITSROFrameLengthMUS / std::sqrt(12.f);
2535 mITSROFrameLengthMUSInv = 1. / mITSROFrameLengthMUS;
2542 mITSROFrameLengthInBC = nbc;
2544 mITSTimeResMUS = mITSROFrameLengthMUS / std::sqrt(12.f);
2545 mITSROFrameLengthMUSInv = 1. / mITSROFrameLengthMUS;
2554 if (minBC < 0 && mUseBCFilling) {
2555 if (mUseBCFilling) {
2556 mUseBCFilling =
false;
2557 LOG(warning) <<
"Disabling match validation by BunchFilling as no interacting bunches found";
2561 int bcAbove = minBC;
2566 mClosestBunchAbove[
i] = bcAbove;
2568 int bcBelow = maxBC;
2573 mClosestBunchBelow[
i] = bcBelow;
2582 if (tbrange.
getMin() > 0) {
2587 int bc = mClosestBunchAbove[irMin.bc];
2588 if (
bc < irMin.bc) {
2592 bc = mClosestBunchBelow[irMax.bc];
2593 if (
bc > irMax.bc) {
2594 if (irMax.orbit == 0) {
2601 return {irMin, irMax};
2605void MatchTPCITS::removeTPCfromITS(
int tpcID,
int itsID)
2608 auto& tITS = mITSWork[itsID];
2609 if (isValidatedITS(tITS)) {
2614 auto& rcITS = mMatchRecordsITS[next];
2615 if (rcITS.partnerID == tpcID) {
2617 tITS.
matchID = rcITS.nextRecID;
2619 mMatchRecordsITS[topID].nextRecID = rcITS.nextRecID;
2624 next = rcITS.nextRecID;
2629void MatchTPCITS::removeITSfromTPC(
int itsID,
int tpcID)
2632 auto& tTPC = mTPCWork[tpcID];
2633 if (isValidatedTPC(tTPC)) {
2638 auto& rcTPC = mMatchRecordsTPC[next];
2639 if (rcTPC.partnerID == itsID) {
2641 tTPC.
matchID = rcTPC.nextRecID;
2643 mMatchRecordsTPC[topID].nextRecID = rcTPC.nextRecID;
2648 next = rcTPC.nextRecID;
2657 for (
int icl = track.getNumberOfClusters(); icl--;) {
2658 mABClusterLinkIndex[mITSTrackClusIdx[clEntry++]] =
MinusTen;
2663int MatchTPCITS::preselectChipClusters(std::vector<int>& clVecOut,
const ClusRange& clRange,
const ITSChipClustersRefs& itsChipClRefs,
2664 float trackY,
float trackZ,
float tolerY,
float tolerZ)
const
2667 int icID = clRange.getFirstEntry();
2668 for (
int icl = clRange.getEntries(); icl--;) {
2669 int clID = itsChipClRefs.
clusterID[icID++];
2670 const auto& cls = mITSClustersArray[clID];
2671 float dz = cls.getZ() - trackZ;
2672 LOG(
debug) <<
"cl" << icl <<
'/' << clID <<
" "
2673 <<
" dZ: " << dz <<
" [" << tolerZ <<
"| dY: " << trackY - cls.getY() <<
" [" << tolerY <<
"]";
2675 float clsZ = cls.getZ();
2676 LOG(
debug) <<
"Skip the rest since " << trackZ <<
" < " << clsZ <<
"\n";
2678 }
else if (dz < -tolerZ) {
2679 LOG(
debug) <<
"Skip cluster dz=" << dz <<
" Ztr=" << trackZ <<
" zCl=" << cls.getZ();
2682 if (fabs(trackY - cls.getY()) > tolerY) {
2683 LOG(
debug) <<
"Skip cluster dy= " << trackY - cls.getY() <<
" Ytr=" << trackY <<
" yCl=" << cls.getY();
2686 clVecOut.push_back(clID);
2688 return clVecOut.size();
2699 size_t sizTotShm = 0, capTotShm = 0, sizTot = 0, capTot = 0, siz = 0, cap = 0, cnt = 0, cntCap = 0;
2705 LOGP(info,
"Size SHM, matchedTracks : size {:9} cap {:9}", siz, cap);
2711 LOGP(info,
"Size SHM, ABTrackletRefs : size {:9} cap {:9}", siz, cap);
2713 siz = ABTrackletClusterIDs.size() *
sizeof(
int);
2714 cap = ABTrackletClusterIDs.capacity() *
sizeof(
int);
2717 LOGP(info,
"Size SHM, ABTrackletClusterIDs : size {:9} cap {:9}", siz, cap);
2723 LOGP(info,
"Size SHM, matchLabels : size {:9} cap {:9}", siz, cap);
2729 LOGP(info,
"Size SHM, ABTrackletLabels : size {:9} cap {:9}", siz, cap);
2735 LOGP(info,
"Size SHM, calib : size {:9} cap {:9}", siz, cap);
2738 siz = mITSClustersArray.size() *
sizeof(
ITSCluster);
2739 cap = mITSClustersArray.capacity() *
sizeof(
ITSCluster);
2742 LOGP(info,
"Size RSS, mITSClustersArray : size {:9} cap {:9}", siz, cap);
2744 siz = mMatchRecordsTPC.size() *
sizeof(
MatchRecord);
2745 cap = mMatchRecordsTPC.capacity() *
sizeof(
MatchRecord);
2748 LOGP(info,
"Size RSS, mMatchRecordsTPC : size {:9} cap {:9}", siz, cap);
2750 siz = mMatchRecordsITS.size() *
sizeof(
MatchRecord);
2751 cap = mMatchRecordsITS.capacity() *
sizeof(
MatchRecord);
2754 LOGP(info,
"Size RSS, mMatchRecordsITS : size {:9} cap {:9}", siz, cap);
2756 siz = mITSROFTimes.size() *
sizeof(
BracketF);
2757 cap = mITSROFTimes.capacity() *
sizeof(
BracketF);
2760 LOGP(info,
"Size RSS, mITSROFTimes : size {:9} cap {:9}", siz, cap);
2766 LOGP(info,
"Size RSS, mTPCWork : size {:9} cap {:9}", siz, cap);
2772 LOGP(info,
"Size RSS, mITSWork : size {:9} cap {:9}", siz, cap);
2774 siz = mWinnerChi2Refit.size() *
sizeof(float);
2775 cap = mWinnerChi2Refit.capacity() *
sizeof(float);
2778 LOGP(info,
"Size RSS, mWinnerChi2Refit : size {:9} cap {:9}", siz, cap);
2780 siz = mTPCABSeeds.size() *
sizeof(float);
2781 cap = mTPCABSeeds.capacity() *
sizeof(float);
2784 for (
const auto&
a : mTPCABSeeds) {
2785 siz +=
a.sizeInternal();
2786 cap +=
a.capInternal();
2787 cnt +=
a.getNLinks();
2788 cntCap +=
a.getNLinks();
2792 LOGP(info,
"Size RSS, mTPCABSeeds : size {:9} cap {:9} | internals size:{}/capacity:{} for {} elements", siz, cap, cnt, cntCap, mTPCABSeeds.size());
2794 siz = mTPCABIndexCache.size() *
sizeof(
int);
2795 cap = mTPCABIndexCache.capacity() *
sizeof(
int);
2798 LOGP(info,
"Size RSS, mTPCABIndexCache : size {:9} cap {:9}", siz, cap);
2800 siz = mABWinnersIDs.size() *
sizeof(
int);
2801 cap = mABWinnersIDs.capacity() *
sizeof(
int);
2804 LOGP(info,
"Size RSS, mABWinnersIDs : size {:9} cap {:9}", siz, cap);
2806 siz = mABClusterLinkIndex.size() *
sizeof(
int);
2807 cap = mABClusterLinkIndex.capacity() *
sizeof(
int);
2810 LOGP(info,
"Size RSS, mABClusterLinkIndex : size {:9} cap {:9}", siz, cap);
2813 siz += mTPCSectIndexCache[is].size() *
sizeof(
int);
2814 cap += mTPCSectIndexCache[is].capacity() *
sizeof(
int);
2818 LOGP(info,
"Size RSS, mTPCSectIndexCache : size {:9} cap {:9}", siz, cap);
2821 siz += mITSSectIndexCache[is].size() *
sizeof(
int);
2822 cap += mITSSectIndexCache[is].capacity() *
sizeof(
int);
2826 LOGP(info,
"Size RSS, mITSSectIndexCache : size {:9} cap {:9}", siz, cap);
2829 siz += mTPCTimeStart[is].size() *
sizeof(
int);
2830 cap += mTPCTimeStart[is].capacity() *
sizeof(
int);
2834 LOGP(info,
"Size RSS, mTPCTimeStart : size {:9} cap {:9}", siz, cap);
2837 siz += mITSTimeStart[is].size() *
sizeof(
int);
2838 cap += mITSTimeStart[is].capacity() *
sizeof(
int);
2842 LOGP(info,
"Size RSS, mITSTimeStart : size {:9} cap {:9}", siz, cap);
2844 siz = mITSTrackROFContMapping.size() *
sizeof(
int);
2845 cap = mITSTrackROFContMapping.capacity() *
sizeof(
int);
2848 LOGP(info,
"Size RSS, ITSTrackROFContMapping: size {:9} cap {:9}", siz, cap);
2850 LOGP(info,
"TotalSizes/Capacities: SHM: {}/{} Heap: {}/{}", sizTotShm, capTotShm, sizTot, capTot);
2857 mNThreads =
n > 0 ?
n : 1;
2859 LOG(warning) <<
"Multithreading is not supported, imposing single thread";
2868#ifdef _ALLOW_DEBUG_TREES_
2884 mTimer[SWDBG].Start(
false);
2885 const auto& tpcOrig = mTPCTracksArray[tpcIndex];
2886 uint8_t clSect = 0, clRow = 0, prevRow = 0xff, padFromEdge = -1;
2889 std::array<bool, 152> shMap{};
2890 bool prevRawShared =
false;
2891 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
2892 tpcOrig.getClusterReference(mTPCTrackClusIdx,
i, clSect, clRow, clIdx);
2893 unsigned int absoluteIndex = mTPCClusterIdxStruct->
clusterOffset[clSect][clRow] + clIdx;
2895 if (!(prevRow == clRow && prevRawShared)) {
2899 prevRawShared =
true;
2902 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
2903 padFromEdge =
uint8_t(clus.getPad());
2904 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
2905 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
2907 int tb = tpcOrig.getTime0() * mNTPCOccBinLengthInv;
2908 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2909 (*mDBGOut) <<
"tpcOrig"
2910 <<
"tf=" << mTFCount
2911 <<
"index=" << tpcIndex
2913 <<
"chi2TPC=" << tpcOrig.getChi2()
2914 <<
"nClus=" << tpcOrig.getNClusters()
2915 <<
"nShared=" << nshared
2916 <<
"time0=" << tpcOrig.getTime0()
2918 <<
"minRow=" << clRow
2919 <<
"padFromEdge=" << padFromEdge
2920 <<
"multTPC=" << mltTPC;
2922 (*mDBGOut) <<
"tpcOrig"
2923 <<
"tpcLbl=" << mTPCTrkLabels[tpcIndex];
2925 (*mDBGOut) <<
"tpcOrig"
2927 mTimer[SWDBG].Stop();
2935 mTimer[SWDBG].Start(
false);
2937 auto& trackITS = mITSWork[itsID];
2938 auto& trackTPC = mTPCWork[tpcID];
2940 chi2 = getPredictedChi2NoZ(trackITS, trackTPC);
2942 (*mDBGOut) <<
"match"
2943 <<
"tf=" << mTFCount <<
"chi2Match=" << chi2 <<
"its=" << trackITS <<
"tpc=" << trackTPC <<
"tcorr=" << tCorr;
2945 (*mDBGOut) <<
"match"
2946 <<
"itsLbl=" << mITSLblWork[itsID] <<
"tpcLbl=" << mTPCLblWork[tpcID];
2948 int tb = mTPCTracksArray[trackTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
2949 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2950 (*mDBGOut) <<
"match"
2951 <<
"rejFlag=" << rejFlag
2952 <<
"multTPC=" << mltTPC
2953 <<
"multITSTr=" << mITSTrackROFRec[trackITS.roFrame].getNEntries()
2954 <<
"multITSCl=" << mITSClusterROFRec[trackITS.roFrame].getNEntries()
2957 mTimer[SWDBG].Stop();
2965 mTimer[SWDBG].Start(
false);
2967 LOG(info) <<
"Dumping debug tree for winner matches";
2968 for (
int iits = 0; iits <
int(mITSWork.size()); iits++) {
2969 auto& tITS = mITSWork[iits];
2970 if (isDisabledITS(tITS)) {
2973 auto& itsMatchRec = mMatchRecordsITS[tITS.
matchID];
2974 int itpc = itsMatchRec.partnerID;
2975 auto& tTPC = mTPCWork[itpc];
2977 (*mDBGOut) <<
"matchWin"
2978 <<
"tf=" << mTFCount <<
"chi2Match=" << itsMatchRec.chi2 <<
"chi2Refit=" << mWinnerChi2Refit[iits] <<
"its=" << tITS <<
"tpc=" << tTPC;
2981 (*mDBGOut) <<
"matchWin"
2982 <<
"itsLbl=" << mITSLblWork[iits] <<
"tpcLbl=" << mTPCLblWork[itpc];
2984 int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
2985 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2986 (*mDBGOut) <<
"matchWin"
2987 <<
"multTPC=" << mltTPC
2988 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
2989 <<
"multITSCl=" << mITSClusterROFRec[tITS.
roFrame].getNEntries()
2992 mTimer[SWDBG].Stop();
std::vector< std::string > labels
General auxilliary methods.
Definition of the GeometryManager class.
Helper for geometry and GRP related CCDB requests.
Some ALICE geometry constants of common interest.
constexpr int p1()
constexpr to accelerate the coordinates changing
Definition of the GeometryTGeo class.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the fast magnetic field parametrization MagFieldFast.
Definition of the MagF class.
Class to perform TPC ITS matching.
Definition of the Names Generator class.
Definition of the parameter class for the detector.
Definition of the parameter class for the detector electronics.
Header to collect physics constants.
Wrapper container for different reconstructed object types.
Configurable params for tracks ad hoc tuning.
Helper class to obtain TPC clusters / digits / labels from DPL.
int getLastFilledBC(int dir=-1) const
bool testBC(int bcID, int dir=-1) const
int getFirstFilledBC(int dir=-1) const
void setFakeFlag(bool v=true)
static int getNHBFPerTF()
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
static const MatchTPCITSParams & Instance()
o2::math_utils::Bracket< float > BracketF
void setUseMatCorrFlag(MatCorrType f)
void fillCalibDebug(int ifit, int iTPC, const o2::dataformats::TrackTPCITS &match, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
o2::BaseCluster< float > ITSCluster
void reportTiming()
clear results of previous event reco
void setITSROFrameLengthMUS(float fums)
set ITS ROFrame duration in BC (continuous mode only)
@ MatchTreeAccOnly
fill the matching candidates tree only once the cut is passed
@ TPCOrigTree
original TPC tracks with some aux info
@ MatchTreeAll
produce matching candidates tree for all candidates
@ WinnerMatchesTree
separate debug tree for winner matches
void clear()
set Bunch filling and init helpers for validation by BCs
void refitWinners(pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
void refitABWinners(pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::MCCompLabel > &ABTrackletLabels, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
bool refitABTrack(int iITSAB, const TPCABSeed &seed, pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs)
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
o2::dataformats::RangeReference< int, int > ClusRange
bool isDebugFlag(UInt_t flags) const
get debug trees flags
void printCandidatesITS() const
void setTPCCorrMaps(const o2::gpu::TPCFastTransformPOD *maph, float lumi)
print settings
bool runAfterBurner(pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::MCCompLabel > &ABTrackletLabels, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
void reportSizes(pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::MCCompLabel > &ABTrackletLabels, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
void printCandidatesTPC() const
void fillTPCITSmatchTree(int itsID, int tpcID, int rejFlag, float chi2=-1., float tCorr=0.)
bool refitTrackTPCITS(int slot, int iTPC, int &iITS, pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
static constexpr int MaxUpDnLadders
void run(const o2::globaltracking::RecoContainer &inp, pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::MCCompLabel > &matchLabels, pmr::vector< o2::MCCompLabel > &ABTrackletLabels, pmr::vector< o2::dataformats::Triplet< float, float, float > > &calib)
void setBunchFilling(const o2::BunchFilling &bf)
void dumpTPCOrig(bool acc, int tpcIndex)
void setDebugFlag(UInt_t flag, bool on=true)
set the name of output debug file
void setITSROFrameLengthInBC(int nbc)
void setITSTimeBiasInBC(int n)
static constexpr int NITSLayers
perform matching for provided input
UInt_t getDebugFlags() const
set or unset debug stream flag
void setNThreads(int n)
perform all initializations
static GeometryTGeo * Instance()
void fillMatrixCache(int mask) override
int getFirstClusterEntry() const
void acquirePattern(iterator &pattIt)
int getNPixels() const
Returns the number of fired pixels.
static constexpr unsigned short InvalidPatternID
int getNpixels(int n) const
Returns the number of fired pixels of the n_th element.
bool isGroup(int n) const
Returns true if the element corresponds to a group of rare topologies.
Relation isOutside(const Bracket< T > &t) const
bool match(const std::vector< std::string > &queries, const char *pattern)
GLfloat GLfloat GLfloat alpha
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * label
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t
constexpr float XTPCOuterRef
reference radius to propagate outer TPC track
constexpr float XTPCInnerRef
reference radius at which TPC provides the tracks
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCOrbitMUS
constexpr double LHCBunchSpacingNS
constexpr int Validated
flags to tell the status of TPC-ITS tracks comparison
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const o2::its3::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const itsmft::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
int int int float float float int const float const TrackingFrameInfo *const const float const o2::base::Propagator * propagator
if(!okForPhiMin(phi0, phi1))
float angle2Alpha(float phi)
int angle2Sector(float phi)
std::tuple< float, float > rotateZ(float xL, float yL, float snAlp, float csAlp)
float sector2Angle(int sect)
std::vector< T, fair::mq::pmr::polymorphic_allocator< T > > vector
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
bool isValid(std::string alias)
std::string asString() const
bool isSelected(const RecPoints &rp) const
float chi2
chi2 after update
uint8_t nDaughters
number of daughter links on lower layers
int8_t nContLayers
number of contributing layers
int nextOnLr
ID of the next (in quality) link on the same layer.
std::array< ClusRange, o2::its::RecoGeomHelper::getNChips()> chipRefs
std::vector< int > clusterID
o2::math_utils::Bracketf_t tBracket
std::vector< std::deque< ABTrackLink > > threadPool
bool runAfterBurner
run afterburner for TPCtrack-ITScluster matching
float nABSigmaZ
nSigma cut on afterburner track-cluster Z distance
float err2ABExtraZ
extra "systematic" error on Z
float tpcTimeICMatchingNSigma
nsigma for matching TPC corrected time and InteractionCandidate from FT0
float XMatchingRef
reference radius to propagate tracks for matching
float crudeNSigma2Cut[o2::track::kNParams]
float tfEdgeTimeToleranceMUS
corrected TPC time allowed to go out from the TF time edges by this amount
float maxVDriftUncertainty
max assumed VDrift relative uncertainty, used only in VDrift calibration mode
float globalTimeBiasMUS
global time shift to apply to assigned time, brute force way to eliminate bias wrt FIT
int requireToReachLayerAB
AB tracks should reach at least this layer from above.
int maxMatchCandidates
max allowed matching candidates per TPC track
float minTPCTrackR
cut on minimal TPC tracks radius to consider for matching, 666*pt_gev*B_kgaus/5
float minBetaGammaForPIDDiff
float safeMarginTPCITSTimeBin
safety margin (in TPC time bins) for ITS-TPC tracks time (in TPC time bins!) comparison
TimeOutliersPolicy ITSTimeOutliersPolicy
int minTPCClusters
minimum number of clusters to consider
ValidateMatchByFIT validateMatchByFIT
when comparing ITS-TPC matches, prefer those which have time of Interaction Candidate
int lowestLayerAB
lowest layer to reach in AfterBurner
float tpcExtConstrainedNSigma
nsigma to apply to externally (TRD,TOF) time-constrained TPC tracks time error
float maxVDritTimeOffset
max possible TDrift offset to calibrate
o2::base::Propagator::MatCorrType matCorr
int minContributingLayersAB
AB tracks must have at least this amount on contributing layers.
float crudeAbsDiffCut[o2::track::kNParams]
float cutMatchingChi2
cut on matching chi2
float safeMarginTimeCorrErr
safety marging (in \mus) for TPC track time corrected by ITS constraint
float cutABTrack2ClChi2
cut on AfterBurner track-cluster chi2
float maxVDriftTrackQ2Pt
use only tracks below this q/pt (with field only)
float nABSigmaY
nSigma cut on afterburner track-cluster Y distance
int verbosity
verbosit level
float minITSTrackR
cut on minimal ITS tracks radius to consider for matching, 666*pt_gev*B_kgaus/5
float err2ABExtraY
extra "systematic" error on Y
float globalTimeExtraErrorMUS
extra error to add to global time estimate
float safeMarginTPCTimeEdge
safety margin in cm when estimating TPC track tMin and tMax from assigned time0 and its track Z posit...
o2::InteractionRecord startIR
void createTracksVariadic(T creator, GTrackID::mask_t srcSel=GTrackID::getSourcesMask("all")) const
GTrackID getTPCContributorGID(GTrackID source) const
auto getFT0RecPoints() const
std::array< int, o2::its::RecoGeomHelper::getNLayers()> firstInLr
entry of 1st (best) hypothesis on each layer
int winLinkID
ID of the validated link.
void addLink(const o2::track::TrackParCov &trc, int clID, int parentID, int nextID, int lr, int nc, int laddID, float chi2)
int ICCanID
interaction candidate ID (they are sorted in increasing time)
ABTrackLink & getLink(int i)
static LinksPoolMT * gLinksPool
pool of links per thread
int8_t lowestLayer
lowest layer reached
int roFrame
ITS readout frame assigned to this track.
o2::math_utils::Bracketf_t tBracket
bracketing time in \mus
float dL
distance integrated during propagation to reference X (as pion)
int matchID
entry (non if MinusOne) of its matchCand struct in the mMatchesITS
float xrho
x*rho seen during propagation to reference X (as pion)
int sourceID
track origin id
float time0
nominal time in \mus since start of TF (time0 for bare TPC tracks, constrained time for TRD/TOF const...
int sourceID
TPC track origin in.
int matchID
entry (non if MinusOne) of its matchTPC struct in the mMatchesTPC
float getCorrectedTime(float dt) const
float timeErr
time sigma (makes sense for constrained tracks only)
o2::dataformats::GlobalTrackID gid
std::array< RecoLayer, o2::itsmft::ChipMappingITS::NLayers > layers
void init(int minLayer=0, int maxLayer=getNLayers())
static constexpr float ladderWidthInv()
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float refTP
reference temperature / pressure for which refVDrift was extracted
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
char const *restrict const cmp