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();
210 mTPCCorrMapsHelper = maph;
218 LOG(error) <<
"Initialization was already done";
221 for (
int i = NStopWatches;
i--;) {
226 YMaxAtXMatchingRef = mParams->
XMatchingRef * 0.17632698;
231 if (!prop->getMatLUT() && mParams->
matCorr == o2::base::Propagator::MatCorrType::USEMatCorrLUT) {
232 LOG(warning) <<
"Requested material LUT is not loaded, switching to TGeo usage";
241#ifdef _ALLOW_DEBUG_TREES_
244 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(),
"recreate");
256 if (fair::Logger::Logging(fair::Severity::info)) {
262void MatchTPCITS::updateTimeDependentParams()
267 mTPCTBinMUS = elParam.ZbinWidth;
268 mTPCTBinNS = mTPCTBinMUS * 1e3;
269 mTPCZMax = detParam.TPClength;
270 mTPCTBinMUSInv = 1. / mTPCTBinMUS;
271 assert(mITSROFrameLengthMUS > 0.0f);
272 mTPCBin2Z = mTPCTBinMUS * mTPCVDrift;
273 mZ2TPCBin = 1. / mTPCBin2Z;
274 mTPCVDriftInv = 1. / mTPCVDrift;
275 mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin;
279 mFieldON = std::abs(mBz) > 0.01;
286 mTPCmeanX0Inv = matbd.meanX2X0 / matbd.length;
289 float scale = mTPCCorrMapsHelper->getInstLumiCTP();
293 mCovDiagInner = trackTune.getCovInnerTotal(scale);
294 mCovDiagOuter = trackTune.getCovOuterTotal(scale);
298void MatchTPCITS::selectBestMatches()
301 mTimer[SWSelectBest].Start(
false);
302 int nValidated = 0, iter = 0;
307 int ntpc = mTPCWork.size(), nremaining = 0;
308 for (
int it = 0; it < ntpc; it++) {
309 auto& tTPC = mTPCWork[it];
310 if (isDisabledTPC(tTPC) || isValidatedTPC(tTPC)) {
314 if (validateTPCMatch(it)) {
316 if (mVDriftCalibOn && (!mFieldON || std::abs(tTPC.getQ2Pt()) < mParams->
maxVDriftTrackQ2Pt)) {
323 LOGP(info,
"iter {}: Validated {} of {} remaining matches", iter, nValidated, nremaining);
326 mNMatches += nValidated;
327 }
while (nValidated);
329 mTimer[SWSelectBest].Stop();
330 LOGP(info,
"Validated {} matches out of {} for {} TPC and {} ITS tracks in {} iterations", mNMatches, mNMatchesControl, mTPCWork.size(), mITSWork.size(), iter);
334bool MatchTPCITS::validateTPCMatch(
int iTPC)
336 auto& tTPC = mTPCWork[iTPC];
337 auto& rcTPC = mMatchRecordsTPC[tTPC.matchID];
339 auto& tITS = mITSWork[rcTPC.partnerID];
340 auto& rcITS = mMatchRecordsITS[tITS.matchID];
344 if (rcITS.partnerID == iTPC) {
345 int cloneID = tITS.getCloneShift();
347 cloneID += rcTPC.partnerID;
348 auto& tITSClone = mITSWork[cloneID];
349 if (isDisabledITS(tITSClone)) {
352 int nextITSCloneMatchID = tITSClone.matchID;
353 if (rcITS.isBetter(mMatchRecordsITS[nextITSCloneMatchID])) {
354 LOGP(
debug,
"Suppressing clone cloneID={} of winner clone {} of source ITS {}", cloneID, rcTPC.partnerID, tITS.sourceID);
355 while (nextITSCloneMatchID >
MinusOne) {
356 auto& rcITSClone = mMatchRecordsITS[nextITSCloneMatchID];
357 removeITSfromTPC(cloneID, rcITSClone.partnerID);
358 nextITSCloneMatchID = rcITSClone.nextRecID;
366 int nextTPC = rcTPC.nextRecID;
368 auto& rcTPCrem = mMatchRecordsTPC[nextTPC];
369 removeTPCfromITS(iTPC, rcTPCrem.partnerID);
370 nextTPC = rcTPCrem.nextRecID;
373 int itsWinID = rcTPC.partnerID;
376 int nextITS = rcITS.nextRecID;
378 auto& rcITSrem = mMatchRecordsITS[nextITS];
379 removeITSfromTPC(itsWinID, rcITSrem.partnerID);
380 nextITS = rcITSrem.nextRecID;
390int MatchTPCITS::getNMatchRecordsTPC(
const TrackLocTPC& tTPC)
const
395 recID = mMatchRecordsTPC[recID].nextRecID;
402int MatchTPCITS::getNMatchRecordsITS(
const TrackLocITS& tTPC)
const
407 auto& itsRecord = mMatchRecordsITS[recID];
408 recID = itsRecord.nextRecID;
418 const float SQRT12DInv = 2. / sqrt(12.);
422 const auto& tpcOrig = mTPCTracksArray[tpcID];
429 tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx);
433 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
435 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
436 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
441 if (extConstrained) {
444 terr += tpcTimeBin2MUS(tpcOrig.hasBothSidesClusters() ? mParams->
safeMarginTPCITSTimeBin : mTPCTimeEdgeTSafeMargin);
446 auto& trc = mTPCWork.emplace_back(
447 TrackLocTPC{_tr, {
t0 - terr,
t0 + terr}, extConstrained ?
t0 : tpcTimeBin2MUS(tpcOrig.getTime0()),
449 terr * (extConstrained ? mTPCExtConstrainedNSigmaInv : SQRT12DInv),
460 if (srcGID.getSource() ==
GTrackID::TPC && !trackTune.sourceLevelTPC) {
461 if (trackTune.useTPCInnerCorr) {
462 trc.updateParams(trackTune.tpcParInner);
468 if (!propagateToRefX(trc)) {
473 mTPCLblWork.emplace_back(mTPCTrkLabels[tpcID]);
481bool MatchTPCITS::prepareTPCData()
484 mTimer[SWPrepTPC].Start(
false);
485 const auto& inp = *mRecoCont;
487 mTPCTracksArray = inp.getTPCTracks();
488 mTPCTrackClusIdx = inp.getTPCTracksClusterRefs();
489 mTPCClusterIdxStruct = &inp.inputsTPCclusters->clusterIndex;
490 mTPCRefitterShMap = inp.clusterShMapTPC;
491 mTPCRefitterOccMap = inp.occupancyMapTPC;
494 mTPCTrkLabels = inp.getTPCTracksMCLabels();
497 int ntr = mTPCTracksArray.size(), ntrW = 0.7 * ntr;
499 mTPCWork.reserve(ntrW);
501 mTPCLblWork.reserve(ntrW);
507 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(),
nullptr,
o2::base::Propagator::Instance());
508 mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
510 if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) {
511 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
514 mTBinClOcc.resize(nTPCOccBins);
515 std::vector<float> mltHistTB(nTPCOccBins);
516 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
517 for (
int i = 0;
i < nTPCOccBins;
i++) {
518 mltHistTB[
i] = mTPCRefitter->getParam()->GetUnscaledMult(tb);
519 tb += mNTPCOccBinLength;
521 for (
int i = nTPCOccBins;
i--;) {
523 if (
i + sumBins < nTPCOccBins) {
524 sm -= mltHistTB[
i + sumBins];
529 mTBinClOcc.resize(1);
532 auto creator = [
this](
auto& trk,
GTrackID gid,
float time0,
float terr) {
533 if constexpr (isITSTrack<decltype(trk)>()) {
538 }
else if (std::abs(trk.getQ2Pt()) > mMinTPCTrackPtInv) {
543 if constexpr (isTPCTrack<decltype(trk)>()) {
545 if (!this->mSkipTPCOnly && trk.getNClusters() > 0) {
546 resAdd = this->addTPCSeed(trk, this->tpcTimeBin2MUS(time0), this->tpcTimeBin2MUS(terr), gid, (tpcIndex = gid.getIndex()));
549 if constexpr (isTPCTOFTrack<decltype(trk)>()) {
551 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
553 if constexpr (isTRDTrack<decltype(trk)>()) {
555 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
557#ifdef _ALLOW_DEBUG_TREES_
568 int nITSROFs = mITSROFTimes.size();
571 auto& indexCache = mTPCSectIndexCache[sec];
573 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" TPC tracks";
575 if (!indexCache.size()) {
578 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
579 auto& trcA = mTPCWork[a];
580 auto& trcB = mTPCWork[b];
581 return (trcA.tBracket.getMax() - trcB.tBracket.getMax()) < 0.;
587 float tmax = mTPCWork[indexCache.back()].tBracket.getMax();
588 if (maxTime < tmax) {
591 int nbins = 1 + (mITSTriggered ? time2ITSROFrameTrig(tmax, 0) : time2ITSROFrameCont(tmax));
592 auto& timeStart = mTPCTimeStart[sec];
593 timeStart.resize(nbins, -1);
597 for (
int itr = 0; itr < (
int)indexCache.size(); itr++) {
598 auto& trc = mTPCWork[indexCache[itr]];
599 while (itsROF < nITSROFs && !(trc.tBracket < mITSROFTimes[itsROF])) {
602 int itsROFMatch = itsROF;
603 if (itsROFMatch && timeStart[--itsROFMatch] == -1) {
604 timeStart[itsROFMatch] = itr;
607 for (
int i = 1;
i < nbins;
i++) {
608 if (timeStart[
i] == -1) {
609 timeStart[
i] = timeStart[
i - 1];
630 mInteractionMUSLUT.clear();
632 mTimer[SWPrepTPC].Stop();
633 return mTPCWork.size() > 0;
637bool MatchTPCITS::prepareITSData()
639 static size_t errCount = 0;
640 constexpr size_t MaxErrors2Report = 10;
642 mTimer[SWPrepITS].Start(
false);
643 const auto& inp = *mRecoCont;
646 mITSClusterROFRec = inp.getITSClustersROFRecords();
647 const auto clusITS = inp.getITSClusters();
648 if (mITSClusterROFRec.empty() || clusITS.empty()) {
649 LOG(info) <<
"No ITS clusters";
652 const auto patterns = inp.getITSClustersPatterns();
653 auto pattIt = patterns.begin();
654 mITSClustersArray.reserve(clusITS.size());
655#ifdef ENABLE_UPGRADES
667 mITSClusterSizes.reserve(clusITS.size());
668 auto pattIt2 = patterns.begin();
669 for (
auto& clus : clusITS) {
670 auto pattID = clus.getPatternID();
672#ifdef ENABLE_UPGRADES
682#ifdef ENABLE_UPGRADES
684 npix = mIT3Dict->getNpixels(pattID, ib);
692 mITSClusterSizes.push_back(std::clamp(npix, 0u, 255u));
696 mITSClsLabels = inp.mcITSClusters.get();
700 mITSTracksArray = inp.getITSTracks();
701 mITSTrackClusIdx = inp.getITSTracksClusterRefs();
702 mITSTrackROFRec = inp.getITSTracksROFRecords();
704 mITSTrkLabels = inp.getITSTracksMCLabels();
706 int nROFs = mITSTrackROFRec.size();
707 mITSWork.reserve(mITSTracksArray.size());
710 const auto& lastClROF = mITSClusterROFRec[nROFs - 1];
711 int nITSClus = lastClROF.getFirstEntry() + lastClROF.getNEntries();
712 mABClusterLinkIndex.resize(nITSClus,
MinusOne);
714 mITSTimeStart[sec].resize(nROFs, -1);
719 trackLTInt.setTimeNotNeeded();
721 for (
int irof = 0; irof < nROFs; irof++) {
722 const auto& rofRec = mITSTrackROFRec[irof];
723 long nBC = rofRec.getBCData().differenceInBC(mStartIR);
724 if (nBC > maxBCs || nBC < 0) {
725 if (++errCount < MaxErrors2Report) {
726 LOGP(alarm,
"ITS ROF#{} start {} is not compatible with TF 1st orbit {} or TF length of {} HBFs",
727 irof, rofRec.getBCData().asString(), mStartIR.
asString(), nHBF);
733 if (!mITSTriggered) {
734 size_t irofCont = nBC / mITSROFrameLengthInBC;
735 if (mITSTrackROFContMapping.size() <= irofCont) {
736 mITSTrackROFContMapping.resize((1 + irofCont / 128) * 128, 0);
738 mITSTrackROFContMapping[irofCont] = irof;
741 mITSROFTimes.emplace_back(tMin, tMax);
744 mITSTimeStart[sec][irof] = mITSSectIndexCache[sec].size();
747 int trlim = rofRec.getFirstEntry() + rofRec.getNEntries();
748 for (
int it = rofRec.getFirstEntry(); it < trlim; it++) {
749 const auto& trcOrig = mITSTracksArray[it];
751 flagUsedITSClusters(trcOrig);
753 if (trcOrig.getParamOut().getX() < 1.) {
756 if (std::abs(trcOrig.getQ2Pt()) > mMinITSTrackPtInv) {
759 int nWorkTracks = mITSWork.size();
761 auto& trc = mITSWork.emplace_back(
TrackLocITS{trcOrig.getParamOut(), {tMin, tMax}, it, irof,
MinusOne});
767 trackLTInt.clearFast();
768 if (!propagateToRefX(trc, &trackLTInt)) {
772 trc.xrho = trackLTInt.getXRho();
773 trc.dL = trackLTInt.getL();
776 mITSLblWork.emplace_back(mITSTrkLabels[it]);
781 mITSSectIndexCache[sector].push_back(nWorkTracks);
789 float trcY = trc.getY(), tgp = trc.getSnp();
790 tgp /= std::sqrt((1.f - tgp) * (1.f + tgp));
792 float dyUpDn[2] = {std::abs((YMaxAtXMatchingRef - trcY) / (tgp + Tan70)), std::abs((YMaxAtXMatchingRef + trcY) / (tgp - Tan70))};
794 int sel = dyUpDn[0] < dyUpDn[1] ? 0 : 1;
795 if (dyUpDn[sel] < mSectEdgeMargin) {
797 addLastTrackCloneForNeighbourSector(sectNeib, &trackLTInt);
802 if (!mITSTriggered) {
803 int nr = mITSTrackROFContMapping.size();
804 for (
int i = 1;
i < nr;
i++) {
805 if (mITSTrackROFContMapping[
i] < mITSTrackROFContMapping[
i - 1]) {
806 mITSTrackROFContMapping[
i] = mITSTrackROFContMapping[
i - 1];
814 auto& indexCache = mITSSectIndexCache[sec];
816 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" ITS tracks";
818 if (!indexCache.size()) {
821 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
822 auto& trackA = mITSWork[a];
823 auto& trackB = mITSWork[b];
824 if (trackA.tBracket.getMin() < trackB.tBracket.getMin()) {
826 }
else if (trackA.tBracket.getMin() > trackB.tBracket.getMin()) {
829 return trackA.getTgl() < trackB.getTgl();
833 mTimer[SWPrepITS].Stop();
839bool MatchTPCITS::prepareFITData()
844 prepareInteractionTimes();
850void MatchTPCITS::doMatching(
int sec)
853 auto& cacheITS = mITSSectIndexCache[sec];
854 auto& cacheTPC = mTPCSectIndexCache[sec];
855 auto& timeStartTPC = mTPCTimeStart[sec];
856 auto& timeStartITS = mITSTimeStart[sec];
857 int nTracksTPC = cacheTPC.size(), nTracksITS = cacheITS.size();
858 if (!nTracksTPC || !nTracksITS) {
860 LOG(info) <<
"Matchng sector " << sec <<
" : N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS <<
" in sector " << sec;
866 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
870 auto minROFITS = mITSWork[cacheITS.front()].roFrame;
872 if (minROFITS >=
int(timeStartTPC.size())) {
873 LOG(info) <<
"ITS min ROFrame " << minROFITS <<
" exceeds all cached TPC track ROF eqiuvalent " << cacheTPC.size() - 1;
877 int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0;
878 int idxMinTPC = timeStartTPC[minROFITS];
883 for (
int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) {
884 auto& trefTPC = mTPCWork[cacheTPC[itpc]];
887 auto tmn = trefTPC.tBracket.getMax() - maxTDriftSafe;
888 itsROBin = mITSTriggered ? time2ITSROFrameTrig(tmn, itsROBin) : time2ITSROFrameCont(tmn);
890 if (itsROBin >=
int(timeStartITS.size())) {
893 int iits0 = timeStartITS[itsROBin];
895 for (
auto iits = iits0; iits < nTracksITS; iits++) {
896 auto& trefITS = mITSWork[cacheITS[iits]];
898 LOG(
debug) <<
"TPC bracket: " << trefTPC.tBracket.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" TPCtgl: " << trefTPC.getTgl() <<
" ITStgl: " << trefITS.getTgl();
899 if (trefTPC.tBracket < trefITS.tBracket) {
902 if (trefTPC.tBracket > trefITS.tBracket) {
907 auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mTPCVDriftInv;
908 auto timeCorr = trefTPC.getCorrectedTime(deltaT);
909 auto timeCorrErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs + mParams->
safeMarginTimeCorrErr;
910 if (mVDriftCalibOn) {
911 timeCorrErr += vdErrT * (250. - abs(trefITS.getZ()));
914 LOG(
debug) <<
"TPC range: " << trange.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" DZ: " << (trefITS.getZ() - trefTPC.getZ()) <<
" DT: " << timeCorr;
916 auto cmpITSBracket = trefITS.tBracket.isOutside(timeCorr);
918 if (trefITS.tBracket.isOutside(trange)) {
923 timeCorr = trefITS.tBracket.getMin();
924 trange.setMin(timeCorr);
926 timeCorr = trefITS.tBracket.getMax();
927 trange.setMax(timeCorr);
936 int rejFlag = compareTPCITSTracks(trefITS, trefTPC, chi2);
938#ifdef _ALLOW_DEBUG_TREES_
971 auto irBracket = tBracket2IRBracket(trange);
972 if (irBracket.isInvalid()) {
976 if (checkInteractionCandidates && mInteractions.size()) {
978 int tmus = trange.getMin();
982 auto entStart = tmus <
int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[tmus] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
983 for (
int ent = entStart; ent < (
int)mInteractions.size(); ent++) {
984 auto cmp = mInteractions[ent].tBracket.isOutside(trange);
998 registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc], chi2, matchedIC);
1003 LOG(info) <<
"Match sector " << sec <<
" N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS
1004 <<
" N TPC tracks checked: " << nCheckTPCControl <<
" (starting from " << idxMinTPC
1005 <<
"), checks: " << nCheckITSControl <<
", matches:" << nMatchesControl;
1007 mNMatchesControl += nMatchesControl;
1011void MatchTPCITS::suppressMatchRecordITS(
int itsID,
int tpcID)
1014 auto& tITS = mITSWork[itsID];
1015 int topID =
MinusOne, recordID = tITS.matchID;
1017 if (mMatchRecordsITS[recordID].partnerID == tpcID) {
1020 tITS.matchID = mMatchRecordsITS[recordID].nextRecID;
1022 mMatchRecordsITS[topID].nextRecID = mMatchRecordsITS[recordID].nextRecID;
1027 recordID = mMatchRecordsITS[recordID].nextRecID;
1032bool MatchTPCITS::registerMatchRecordTPC(
int iITS,
int iTPC,
float chi2,
int candIC)
1036 auto& tTPC = mTPCWork[iTPC];
1038 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1039 tTPC.
matchID = mMatchRecordsTPC.size();
1040 mMatchRecordsTPC.emplace_back(iITS, chi2,
MinusOne, candIC);
1046 auto& nextMatchRec = mMatchRecordsTPC[nextID];
1048 if (!nextMatchRec.isBetter(chi2, candIC)) {
1049 if (count < mParams->maxMatchCandidates) {
1052 suppressMatchRecordITS(nextMatchRec.partnerID, iTPC);
1053 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1055 nextMatchRec.chi2 = chi2;
1056 nextMatchRec.matchedIC = candIC;
1057 nextMatchRec.partnerID = iITS;
1062 nextID = nextMatchRec.nextRecID;
1068 if (count < mParams->maxMatchCandidates) {
1070 topID = tTPC.
matchID = mMatchRecordsTPC.size();
1072 topID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC.size();
1075 registerMatchRecordITS(iITS, iTPC, chi2, candIC);
1076 mMatchRecordsTPC.emplace_back(iITS, chi2, nextID, candIC);
1081 suppressMatchRecordITS(mMatchRecordsTPC[nextID].partnerID, iTPC);
1083 nextID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC[nextID].nextRecID;
1088 nextID = mMatchRecordsTPC[nextID].nextRecID;
1097void MatchTPCITS::registerMatchRecordITS(
const int iITS,
int iTPC,
float chi2,
int candIC)
1100 auto& tITS = mITSWork[iITS];
1101 int idnew = mMatchRecordsITS.size();
1102 auto& newRecord = mMatchRecordsITS.emplace_back(iTPC, chi2,
MinusOne, candIC);
1103 if (tITS.matchID < 0) {
1104 tITS.matchID = idnew;
1109 int topID =
MinusOne, nextRecord = tITS.matchID;
1111 auto& nextMatchRec = mMatchRecordsITS[nextRecord];
1112 if (!nextMatchRec.isBetter(chi2, candIC)) {
1113 newRecord.nextRecID = nextRecord;
1115 tITS.matchID = idnew;
1117 mMatchRecordsITS[topID].nextRecID = idnew;
1122 nextRecord = mMatchRecordsITS[nextRecord].nextRecID;
1126 mMatchRecordsITS[topID].nextRecID = idnew;
1143 if (mVDriftCalibOn) {
1145 err2Tgl += addErr * addErr;
1147 diff *= diff / err2Tgl;
1152 bool testOtherPID =
false;
1153 float itsParam[5] = {tITS.getY(), tITS.getZ(), tITS.getSnp(), tITS.getTgl(), tITS.getQ2Pt()};
1154 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1156 tPID.setPID(tTPC.getPID(),
true);
1157 if (!tPID.correctForELoss(tITS.
xrho)) {
1167 testOtherPID =
true;
1209 auto tITSAlt = tITS;
1210 tITSAlt.setPID(tTPC.getPID());
1214 chi2 = getPredictedChi2NoZ(tITSAlt, tTPC);
1216 chi2 = getPredictedChi2NoZ(tITS, tTPC);
1229 int ntpc = mTPCWork.size();
1230 printf(
"\n\nPrinting all TPC -> ITS matches for %d TPC tracks\n", ntpc);
1231 for (
int i = 0;
i < ntpc;
i++) {
1232 const auto& tTPC = mTPCWork[
i];
1233 int nm = getNMatchRecordsTPC(tTPC);
1234 printf(
"*** trackTPC#%6d %6d : Ncand = %d Best = %d\n",
i, tTPC.
sourceID, nm, tTPC.
matchID);
1237 const auto& rcTPC = mMatchRecordsTPC[recID];
1238 const auto& tITS = mITSWork[rcTPC.partnerID];
1239 printf(
" * cand %2d : ITS track %6d(src:%6d) Chi2: %.2f\n",
count, rcTPC.partnerID, tITS.
sourceID, rcTPC.chi2);
1241 recID = rcTPC.nextRecID;
1250 int nits = mITSWork.size();
1251 printf(
"\n\nPrinting all ITS -> TPC matches for %d ITS tracks\n", nits);
1253 for (
int i = 0;
i < nits;
i++) {
1254 const auto& tITS = mITSWork[
i];
1255 printf(
"*** trackITS#%6d %6d : Ncand = %d Best = %d\n",
i, tITS.
sourceID, getNMatchRecordsITS(tITS), tITS.
matchID);
1258 const auto& rcITS = mMatchRecordsITS[recID];
1259 const auto& tTPC = mTPCWork[rcITS.partnerID];
1260 printf(
" * cand %2d : TPC track %6d(src:%6d) Chi2: %.2f\n",
count, rcITS.partnerID, tTPC.
sourceID, rcITS.chi2);
1262 recID = rcITS.nextRecID;
1284 covMat(0, 0) =
static_cast<double>(trITS.getSigmaY2()) +
static_cast<double>(trTPC.getSigmaY2());
1285 covMat(1, 0) =
static_cast<double>(trITS.getSigmaSnpY()) +
static_cast<double>(trTPC.getSigmaSnpY());
1286 covMat(1, 1) =
static_cast<double>(trITS.getSigmaSnp2()) +
static_cast<double>(trTPC.getSigmaSnp2());
1287 covMat(2, 0) =
static_cast<double>(trITS.getSigmaTglY()) +
static_cast<double>(trTPC.getSigmaTglY());
1288 covMat(2, 1) =
static_cast<double>(trITS.getSigmaTglSnp()) +
static_cast<double>(trTPC.getSigmaTglSnp());
1289 covMat(2, 2) =
static_cast<double>(trITS.getSigmaTgl2()) +
static_cast<double>(trTPC.getSigmaTgl2());
1290 if (mVDriftCalibOn) {
1292 covMat(2, 2) += addErr * addErr;
1294 covMat(3, 0) =
static_cast<double>(trITS.getSigma1PtY()) +
static_cast<double>(trTPC.getSigma1PtY());
1295 covMat(3, 1) =
static_cast<double>(trITS.getSigma1PtSnp()) +
static_cast<double>(trTPC.getSigma1PtSnp());
1296 covMat(3, 2) =
static_cast<double>(trITS.getSigma1PtTgl()) +
static_cast<double>(trTPC.getSigma1PtTgl());
1297 covMat(3, 3) =
static_cast<double>(trITS.getSigma1Pt2()) +
static_cast<double>(trTPC.getSigma1Pt2());
1298 if (!covMat.Invert()) {
1299 LOG(error) <<
"Cov.matrix inversion failed: " << covMat;
1302 double chi2diag = 0., chi2ndiag = 0.,
1308 chi2diag += diff[
i] * diff[
i] * covMat(
i,
i);
1309 for (
int j =
i;
j--;) {
1310 chi2ndiag += diff[
i] * diff[
j] * covMat(
i,
j);
1313 return chi2diag + 2. * chi2ndiag;
1322 mITSWork.push_back(mITSWork.back());
1323 auto& trc = mITSWork.back();
1327 mITSSectIndexCache[sector].push_back(mITSWork.size() - 1);
1329 mITSWork.back().setCloneBefore();
1331 mITSWork.back().xrho = trackLTInt->getXRho();
1332 mITSWork.back().dL = trackLTInt->getL();
1334 mITSWork[mITSWork.size() - 2].setCloneAfter();
1336 mITSLblWork.emplace_back(mITSTrkLabels[trc.sourceID]);
1339 mITSWork.pop_back();
1348 constexpr float TgHalfSector = 0.17632698f;
1349 bool refReached =
false;
1357 if (fabs(trc.getY()) < mParams->
XMatchingRef * TgHalfSector) {
1361 if (!trialsLeft--) {
1365 if (!trc.rotate(alphaNew) != 0) {
1369 return refReached && std::abs(trc.getSnp()) < MaxSnp;
1376 printf(
"\n******************** TPC-ITS matching component ********************\n");
1378 printf(
"init is not done yet\n");
1382 printf(
"MC truth: %s\n", mMCTruthON ?
"on" :
"off");
1383 printf(
"Matching reference X: %.3f\n", mParams->
XMatchingRef);
1384 printf(
"Account Z dimension: %s\n", mCompareTracksDZ ?
"on" :
"off");
1386 printf(
"Max number ITS candidates per TPC track: %d\n", mParams->
maxMatchCandidates);
1387 printf(
"Crude cut on track params: ");
1393 printf(
"NSigma^2 cut on track params: ");
1401#ifdef _ALLOW_DEBUG_TREES_
1403 printf(
"Output debug tree (%s) file: %s\n", mDBGFlags ?
"on" :
"off", mDebugTreeFileName.data());
1405 printf(
"Debug stream flags:\n");
1410 printf(
"* winner matches\n");
1415 printf(
"**********************************************************************\n");
1422 mTimer[SWRefit].Start(
false);
1423 matchedTracks.reserve(mNMatches + mABWinnersIDs.size());
1424 matchedTracks.resize(mNMatches);
1426 matchLabels.reserve(mNMatches + mABWinnersIDs.size());
1427 matchLabels.resize(mNMatches);
1429 if (mVDriftCalibOn) {
1430 calib.reserve(mNCalibPrelim * 1.2 + 1);
1432 std::vector<int> tpcToFit;
1433 tpcToFit.reserve(mNMatches);
1434 for (
int iTPC = 0; iTPC < (
int)mTPCWork.size(); iTPC++) {
1435 const auto& tTPC = mTPCWork[iTPC];
1436 if (!isDisabledTPC(tTPC) && tTPC.
gid.testBit(0)) {
1437 tpcToFit.push_back(iTPC);
1440 LOG(
debug) <<
"Refitting winner matches";
1441 mWinnerChi2Refit.resize(mITSWork.size(), -1.f);
1442 int nToFit = (
int)tpcToFit.size();
1443 unsigned int nFailedRefit{0};
1446#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) \
1447 reduction(+ : nFailedRefit)
1449 for (
int ifit = 0; ifit < nToFit; ifit++) {
1450 int iTPC = tpcToFit[ifit], iITS;
1451 const auto& tTPC = mTPCWork[iTPC];
1452 if (
refitTrackTPCITS(ifit, iTPC, iITS, matchedTracks, matchLabels, calib)) {
1453 mWinnerChi2Refit[iITS] = matchedTracks.back().getChi2Refit();
1458 LOGP(info,
"Failed {} TPC-ITS refits out of {}", nFailedRefit, nToFit);
1463 for (
int ifit = 0; ifit < nToFit; ifit++) {
1464 int itpc = tpcToFit[ifit];
1465 if (!matchedTracks[ifit].
isValid()) {
1466 while (--last > ifit && !matchedTracks[last].
isValid()) {
1469 matchedTracks[ifit] = matchedTracks[last];
1470 matchedTracks[last].invalidate();
1471 itpc = tpcToFit[last];
1473 matchLabels[ifit] = matchLabels[last];
1479 if (mDBGOut || mVDriftCalibOn) {
1485 matchedTracks.resize(mNMatches);
1487 matchLabels.resize(mNMatches);
1489 mTimer[SWRefit].Stop();
1495 const auto& tTPC = mTPCWork[iTPC];
1496 int iITS = mMatchRecordsTPC[tTPC.
matchID].partnerID;
1497 const auto& tITS = mITSWork[iITS];
1498 float minDiffFT0 = -999.,
timeC = 0.f;
1499 std::vector<float> dtimes;
1501 if (fillVDCalib || mDBGOut) {
1504 if (mInteractions.size()) {
1505 int timeC0 =
timeC - minDiffA;
1509 auto entStart = timeC0 <
int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[timeC0] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
1510 for (
int ent = entStart; ent < (
int)mInteractions.size(); ent++) {
1511 float diff = mInteractions[ent].tBracket.mean() -
timeC;
1512 if (diff > minDiffA) {
1515 if (diff < -minDiffA) {
1518 dtimes.push_back(diff);
1520 minDiffA = std::abs(minDiffFT0);
1525 calib.emplace_back(tITS.getTgl(), tTPC.getTgl(), minDiffFT0);
1527#ifdef _ALLOW_DEBUG_TREES_
1531 itsRefPIDCorr.setX(0);
1532 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1533 itsRefAltPID = mITSTracksArray[tITS.
sourceID].getParamOut();
1534 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1535 itsRefPIDCorr = itsRefAltPID;
1537 if (!itsRefPIDCorr.correctForELoss(tITS.
xrho)) {
1538 itsRefPIDCorr.setX(-10);
1540 float q2ptPID = itsRefPIDCorr.getQ2Pt();
1542 itsRefPIDCorr = tITS;
1543 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1544 itsRefPIDCorr.setQ2Pt(q2ptPID);
1545 auto snp = tITS.getSnp() + dCurvL;
1546 if (std::abs(snp) >= 1.) {
1547 snp = std::copysign(0.99, snp);
1549 itsRefPIDCorr.setSnp(snp);
1550 itsRefPIDCorr.setY(tITS.getY() + dCurvL * dLEff * 0.5);
1554 itsRefAltPID.setX(-10);
1557 int tb = mTPCTracksArray[tTPC.
sourceID].getTime0() * mNTPCOccBinLengthInv;
1558 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
1559 (*mDBGOut) <<
"refit"
1560 <<
"tpcOrig=" << mTPCTracksArray[tTPC.
sourceID] <<
"itsOrig=" << mITSTracksArray[tITS.
sourceID] <<
"itsRef=" << tITS <<
"tpcRef=" << tTPC <<
"matchRefit=" <<
match
1561 <<
"timeCorr=" <<
timeC <<
"dTimeFT0=" << minDiffFT0 <<
"dTimes=" << dtimes
1562 <<
"itsRefAltPID=" << itsRefAltPID <<
"itsRefPIDCorr=" << itsRefPIDCorr;
1564 (*mDBGOut) <<
"refit"
1565 <<
"itsLbl=" << mITSLblWork[iITS] <<
"tpcLbl=" << mTPCLblWork[iTPC];
1567 (*mDBGOut) <<
"refit"
1568 <<
"multTPC=" << mltTPC
1569 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
1570 <<
"multITSCl=" << mITSClusterROFRec[tITS.
roFrame].getNEntries()
1571 <<
"tf=" << mTFCount <<
"\n";
1581 const float maxStep = 2.f;
1582 const auto& tTPC = mTPCWork[iTPC];
1583 const auto& tpcMatchRec = mMatchRecordsTPC[tTPC.
matchID];
1584 iITS = tpcMatchRec.partnerID;
1585 const auto& tITS = mITSWork[iITS];
1586 const auto& itsTrOrig = mITSTracksArray[tITS.
sourceID];
1587 auto& trfit = matchedTracks[slot];
1590 trfit.getParamOut().setUserField(0);
1591 trfit.setPID(tTPC.getPID(),
true);
1592 trfit.getParamOut().setPID(tTPC.getPID(),
true);
1595 if (!mCompareTracksDZ) {
1596 trfit.setZ(tITS.getZ());
1598 float deltaT = (trfit.getZ() - tTPC.getZ()) * mTPCVDriftInv;
1601 timeErr = mITSTimeResMUS;
1624 int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters();
1628 int clEntry = itsTrOrig.getFirstClusterEntry();
1632 if (mVDriftCalibOn) {
1638 for (
int icl = 0; icl < ncl; icl++) {
1639 const auto& clus = mITSClustersArray[mITSTrackClusIdx[clEntry++]];
1640 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1641 if (!trfit.rotate(
alpha) ||
1645 !propagator->propagateToX(trfit,
x, propagator->getNominalBz(),
1646 MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) {
1649 chi2 += trfit.getPredictedChi2(clus);
1650 if (!trfit.update(clus)) {
1655 if (nclRefit != ncl) {
1656 LOGP(
debug,
"Refit in ITS failed after ncl={}, match between TPC track #{} and ITS track #{}", nclRefit, tTPC.
sourceID, tITS.
sourceID);
1657 LOGP(
debug,
"{:s}", trfit.asString());
1667 if (!propagator->propagateToDCA(vtxDummy.getXYZ(), trpar, propagator->getNominalBz(),
1668 maxStep, MatCorrType::USEMatCorrNONE,
nullptr, &trfit.getLTIntegralOut())) {
1669 LOG(error) <<
"LTOF integral might be incorrect";
1671 auto& tofL = trfit.getLTIntegralOut();
1672 tofL.setX2X0(-tofL.getX2X0());
1673 tofL.setXRho(-tofL.getXRho());
1676 auto& tracOut = trfit.getParamOut();
1677 if (tTPC.getPID() > tITS.getPID() && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1679 tracOut = mITSTracksArray[tITS.
sourceID].getParamOut();
1680 tracOut.setPID(tTPC.getPID(),
true);
1682 LOGP(
debug,
"Failed to rotate ITSouter with imposed PID to TPC alpha {} or propagate to X={}: {:s}", tTPC.getAlpha(), mParams->
XMatchingRef, tracOut.asString());
1690 !propagator->PropagateToXBxByBz(tracOut, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1691 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1695 if (mVDriftCalibOn) {
1699 auto posStart = tracOut.getXYZGlo();
1700 auto tImposed =
timeC * mTPCTBinMUSInv;
1701 if (std::abs(tImposed - mTPCTracksArray[tTPC.
sourceID].getTime0()) > 550) {
1702 LOGP(alarm,
"Impossible imposed timebin {} for TPC track time0:{}, dBwd:{} dFwd:{} TB | ZShift:{}, TShift:{}", tImposed, mTPCTracksArray[tTPC.
sourceID].getTime0(),
1703 mTPCTracksArray[tTPC.
sourceID].getDeltaTBwd(), mTPCTracksArray[tTPC.
sourceID].getDeltaTFwd(), trfit.getZ() - tTPC.getZ(), deltaT);
1704 LOGP(info,
"Trc: {}", mTPCTracksArray[tTPC.
sourceID].asString());
1708 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(), tImposed, &chi2Out,
true,
false);
1714 auto posEnd = tracOut.getXYZGlo();
1715 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1716 tofL.addStep(lInt, tracOut.getQ2P2());
1717 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1721 if (trackTune.useTPCOuterCorr) {
1722 tracOut.updateParams(trackTune.tpcParOuter);
1728 trfit.setChi2Match(tpcMatchRec.chi2);
1729 trfit.setChi2Refit(chi2);
1730 trfit.setTimeMUS(
timeC, timeErr);
1735 matchLabels[slot] = mTPCLblWork[iTPC];
1736 matchLabels[slot].setFakeFlag(mITSLblWork[iITS] != mTPCLblWork[iTPC]);
1747 const float maxStep = 2.f;
1748 const auto& tTPC = mTPCWork[seed.
tpcWID];
1750 auto& newtr = matchedTracks.emplace_back(winLink, winLink);
1751 auto& tracOut = newtr.getParamOut();
1752 auto& tofL = newtr.getLTIntegralOut();
1755 tracOut.resetCovariance();
1757 propagator->estimateLTFast(tofL, winLink);
1759 const auto& itsClRefs = ABTrackletRefs[iITSAB];
1760 int nclRefit = 0, ncl = itsClRefs.getNClusters();
1763 for (
int icl = itsClRefs.getFirstEntry(); icl < itsClRefs.getEntriesBound(); icl++) {
1764 const auto& clus = mITSClustersArray[ABTrackletClusterIDs[icl]];
1765 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1766 if (!tracOut.rotate(
alpha, refLin, propagator->getNominalBz()) ||
1770 !propagator->propagateToX(tracOut, refLin,
x, propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, &tofL)) {
1773 chi2 += tracOut.getPredictedChi2(clus);
1774 if (!tracOut.update(clus)) {
1779 if (nclRefit != ncl) {
1780 LOGP(
debug,
"AfterBurner refit in ITS failed after ncl={}, match between TPC track #{} and ITS tracklet #{}", nclRefit, tTPC.
sourceID, iITSAB);
1781 LOGP(
debug,
"{:s}", tracOut.asString());
1782 matchedTracks.pop_back();
1786 float timeC = mInteractions[seed.
ICCanID].tBracket.mean();
1787 float timeErr = mInteractions[seed.
ICCanID].tBracket.delta();
1791 !propagator->PropagateToXBxByBz(tracOut, refLin, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1792 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1793 matchedTracks.pop_back();
1797 auto posStart = tracOut.getXYZGlo();
1798 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(),
timeC * mTPCTBinMUSInv, &chi2Out,
true,
false);
1801 matchedTracks.pop_back();
1804 auto posEnd = tracOut.getXYZGlo();
1805 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1806 tofL.addStep(lInt, tracOut.getQ2P2());
1807 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1810 if (trackTune.useTPCOuterCorr) {
1811 tracOut.updateParams(trackTune.tpcParOuter);
1818 newtr.setChi2Match(winLink.chi2Norm());
1819 newtr.setChi2Refit(chi2);
1820 newtr.setTimeMUS(
timeC, timeErr);
1828bool MatchTPCITS::refitTPCInward(
o2::track::TrackParCov& trcIn,
float& chi2,
float xTgt,
int trcID,
float timeTB)
const
1831 const auto& tpcTrOrig = mTPCTracksArray[trcID];
1833 trcIn = tpcTrOrig.getOuterParam();
1837 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(trcIn, tpcTrOrig.getClusterRef(), timeTB, &chi2,
false,
true);
1839 LOG(warning) <<
"Refit failed";
1840 LOG(warning) << trcIn.asString();
1846 if (!propagator->PropagateToXBxByBz(trcIn, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1847 LOG(
debug) <<
"Propagation to target X=" << xTgt <<
" failed, Xtr=" << trcIn.getX() <<
" snp=" << trcIn.getSnp() <<
" pT=" << trcIn.getPt();
1856int MatchTPCITS::prepareABSeeds()
1859 const auto& outerLr = mRGHelper.
layers.back();
1861 const float ROuter = outerLr.rRange.getMax() + 0.5f;
1864 for (
int iTPC = 0; iTPC < (
int)mTPCWork.size(); iTPC++) {
1865 auto& tTPC = mTPCWork[iTPC];
1866 if (isDisabledTPC(tTPC)) {
1872 !propagator->PropagateToXBxByBz(tTPC, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1875 mTPCABIndexCache.push_back(iTPC);
1879 std::sort(mTPCABIndexCache.begin(), mTPCABIndexCache.end(), [
this](
int a,
int b) {
1880 auto& trcA = mTPCWork[a];
1881 auto& trcB = mTPCWork[b];
1882 return (trcA.tBracket.getMin() - trcB.tBracket.getMin()) < 0.;
1885 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
1886 int nIntCand = mInteractions.size(), nTPCCand = mTPCABIndexCache.size();
1888 for (
int ic = 0; ic < nIntCand; ic++) {
1889 int icFirstSeed = mTPCABSeeds.size();
1890 auto& intCand = mInteractions[ic];
1891 auto tic = intCand.tBracket.mean();
1892 for (
int it = tpcStart; it < nTPCCand; it++) {
1893 auto& trc = mTPCWork[mTPCABIndexCache[it]];
1894 auto cmp = trc.tBracket.isOutside(intCand.tBracket);
1899 if (trc.tBracket.getMin() + maxTDriftSafe < intCand.tBracket.getMin()) {
1905 float dt = trc.getSignedDT(tic - trc.time0);
1906 float dz = dt * mTPCVDrift,
z = trc.getZ() + dz;
1907 if (outerLr.zRange.isOutside(
z, std::sqrt(trc.getSigmaZ2()) + 2.)) {
1911 auto& seed = mTPCABSeeds.emplace_back(mTPCABIndexCache[it], ic, trc);
1914 intCand.seedsRef.set(icFirstSeed, mTPCABSeeds.size() - icFirstSeed);
1916 return mTPCABIndexCache.size();
1920int MatchTPCITS::prepareInteractionTimes()
1923 const float ft0Uncertainty = 0.5e-3;
1924 int nITSROFs = mITSROFTimes.size();
1925 if (mFITInfo.size()) {
1927 for (
const auto& ft : mFITInfo) {
1931 auto fitTime = ft.getInteractionRecord().differenceInBCMUS(mStartIR);
1935 if (
size_t(fitTime) >= mInteractionMUSLUT.size()) {
1936 mInteractionMUSLUT.resize(
size_t(fitTime) + 1, -1);
1938 if (mInteractionMUSLUT[fitTime] < 0) {
1939 mInteractionMUSLUT[fitTime] = mInteractions.size();
1941 for (; rof < nITSROFs; rof++) {
1942 if (mITSROFTimes[rof] < fitTime) {
1947 if (rof >= nITSROFs) {
1954 for (
auto&
val : mInteractionMUSLUT) {
1961 return mInteractions.size();
1968 mTimer[SWABSeeds].Start(
false);
1971 int nIntCand = mInteractions.size(), nABSeeds = mTPCABSeeds.size();
1972 LOGP(info,
"AfterBurner will check {} seeds from {} TPC tracks and {} interaction candidates with {} threads", nABSeeds, mTPCABIndexCache.size(), nIntCand, mNThreads);
1973 mTimer[SWABSeeds].Stop();
1974 if (!nIntCand || !mTPCABSeeds.size()) {
1977 mTimer[SWABMatch].Start(
false);
1979 std::vector<ITSChipClustersRefs> itsChipClRefsBuff(mNThreads);
1980#ifdef ENABLE_UPGRADES
1983 std::generate(itsChipClRefsBuff.begin(), itsChipClRefsBuff.end(), []() {
1984 return ITSChipClustersRefs(o2::its::GeometryTGeo::Instance()->getNumberOfChips());
1989#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
1991 for (
int ic = 0; ic < nIntCand; ic++) {
1992 const auto& intCand = mInteractions[ic];
1993 LOGP(
debug,
"cand T {} Entries: {} : {} : {} | ITS ROF: {}", intCand.tBracket.mean(), intCand.seedsRef.getEntries(), intCand.seedsRef.getFirstEntry(), intCand.seedsRef.getEntriesBound(), intCand.rofITS);
1994 if (!intCand.seedsRef.getEntries()) {
1998 uint8_t tid = (uint8_t)omp_get_thread_num();
2002 fillClustersForAfterBurner(intCand.rofITS, 1, itsChipClRefsBuff[tid]);
2003 for (
int is = intCand.seedsRef.getFirstEntry(); is < intCand.seedsRef.getEntriesBound(); is++) {
2004 processABSeed(is, itsChipClRefsBuff[tid], tid);
2007 mTimer[SWABMatch].Stop();
2008 mTimer[SWABWinners].Start(
false);
2015 std::vector<SID> candAB;
2016 candAB.reserve(nABSeeds);
2017 mABWinnersIDs.reserve(mTPCABIndexCache.size());
2019 for (
int i = 0;
i < nABSeeds;
i++) {
2020 auto& ABSeed = mTPCABSeeds[
i];
2021 if (ABSeed.isDisabled()) {
2024 candAB.emplace_back(SID{
i, ABSeed.getLink(ABSeed.getBestLinkID()).chi2Norm()});
2026 std::sort(candAB.begin(), candAB.end(), [](SID
a, SID
b) { return a.chi2 < b.chi2; });
2027 for (
int i = 0;
i < (
int)candAB.size();
i++) {
2028 auto& ABSeed = mTPCABSeeds[candAB[
i].seedID];
2029 if (ABSeed.isDisabled()) {
2033 auto& tTPC = mTPCWork[ABSeed.tpcWID];
2039 auto bestID = ABSeed.getBestLinkID();
2040 if (ABSeed.checkLinkHasUsedClusters(bestID, mABClusterLinkIndex)) {
2041 ABSeed.setNeedAlternative();
2045 ABSeed.validate(bestID);
2046 ABSeed.flagLinkUsedClusters(bestID, mABClusterLinkIndex);
2047 mABWinnersIDs.push_back(tTPC.
matchID = candAB[
i].seedID);
2048 mNABRefsClus += ABSeed.getNLayers();
2052 mTimer[SWABWinners].Stop();
2053 mTimer[SWABRefit].Start(
false);
2054 refitABWinners(matchedTracks, matchLabels, ABTrackletLabels, ABTrackletClusterIDs, ABTrackletRefs, calib);
2055 mTimer[SWABRefit].Stop();
2066 ABTrackletClusterIDs.reserve(mNABRefsClus);
2067 ABTrackletRefs.reserve(mABWinnersIDs.size());
2069 ABTrackletLabels.reserve(mABWinnersIDs.size());
2071 if (matchedTracks.capacity() < mABWinnersIDs.size() + matchedTracks.size()) {
2072 LOGP(warn,
"need to expand matched tracks container from {} to {}", matchedTracks.capacity(), mABWinnersIDs.size() + matchedTracks.size());
2073 matchedTracks.reserve(mABWinnersIDs.size() + matchedTracks.size());
2075 matchLabels.reserve(mABWinnersIDs.size() + matchedTracks.size());
2079 std::map<o2::MCCompLabel, int> labelOccurence;
2080 auto accountClusterLabel = [&labelOccurence, itsClLabs = mITSClsLabels](
int clID) {
2081 auto labels = itsClLabs->getLabels(clID);
2082 for (
auto lab :
labels) {
2084 labelOccurence[lab]++;
2089 for (
auto wid : mABWinnersIDs) {
2090 const auto& ABSeed = mTPCABSeeds[wid];
2091 int start = ABTrackletClusterIDs.size();
2092 int lID = ABSeed.winLinkID, ncl = 0;
2093 auto& clref = ABTrackletRefs.emplace_back(
start, ncl);
2095 const auto& winL = ABSeed.getLink(lID);
2097 ABTrackletClusterIDs.push_back(winL.clID);
2099 clref.pattern |= 0x1 << winL.layerID;
2100 clref.setClusterSize(winL.layerID, mITSClusterSizes[winL.clID]);
2102 accountClusterLabel(winL.clID);
2105 lID = winL.parentID;
2107 clref.setEntries(ncl);
2108 if (!
refitABTrack(ABTrackletRefs.size() - 1, ABSeed, matchedTracks, ABTrackletClusterIDs, ABTrackletRefs)) {
2109 ABTrackletRefs.pop_back();
2110 ABTrackletClusterIDs.resize(
start);
2112 labelOccurence.clear();
2128 labelOccurence.clear();
2129 ABTrackletLabels.push_back(lab);
2130 auto& lblGlo = matchLabels.emplace_back(mTPCLblWork[ABSeed.tpcWID]);
2131 lblGlo.setFakeFlag(lab != lblGlo);
2132 LOG(
debug) <<
"ABWinner ncl=" << ncl <<
" mcLBAB " << lab <<
" mcLBGlo " << lblGlo <<
" chi2=" << ABSeed.getLink(ABSeed.winLinkID).chi2Norm() <<
" pT = " << ABSeed.track.getPt();
2136 LOG(info) <<
"AfterBurner validated " << ABTrackletRefs.size() <<
" tracks";
2140void MatchTPCITS::processABSeed(
int sid,
const ITSChipClustersRefs& itsChipClRefs, uint8_t tID)
2143 auto& ABSeed = mTPCABSeeds[sid];
2144 ABSeed.threadID = tID;
2145 ABSeed.linksEntry = mABLinksPool.
threadPool[tID].size();
2148 int nextLinkID = ABSeed.firstInLr[ilr];
2149 if (nextLinkID < 0) {
2153 const auto& seedLink = ABSeed.getLink(nextLinkID);
2154 if (seedLink.isDisabled()) {
2155 nextLinkID = seedLink.nextOnLr;
2158 int next2nextLinkID = seedLink.nextOnLr;
2159 followABSeed(seedLink, itsChipClRefs, nextLinkID, ilr - 1, ABSeed);
2160 nextLinkID = next2nextLinkID;
2164 auto candID = ABSeed.getBestLinkID();
2165 if (ABSeed.isDisabled() ||
2170 mABLinksPool.
threadPool[tID].resize(
size_t(ABSeed.linksEntry));
2191 const auto& lr = mRGHelper.
layers[lrID];
2193 if (!seedC.getXatLabR(lr.rRange.getMax(), xTgt, propagator->getNominalBz(),
o2::track::DirInward) ||
2194 !propagator->propagateToX(seedC, xTgt, propagator->getNominalBz(), MaxSnp, 2., mUseMatCorrFlag)) {
2198 float zDRStep = -seedC.getTgl() * lr.rRange.delta();
2199 float errZ = std::sqrt(seedC.getSigmaZ2() + mParams->
err2ABExtraZ);
2200 if (lr.zRange.isOutside(seedC.getZ(), mParams->
nABSigmaZ * errZ + std::abs(zDRStep))) {
2203 std::vector<int> chipSelClusters;
2210 seedC.getCircleParams(propagator->getNominalBz(), trcCircle, sna, csa);
2212 seedC.getLineParams(trcLinPar, sna, csa);
2216 float phi = std::atan2(yCurr, xCurr);
2218 int nLad2Check = 0, ladIDguess = lr.getLadderID(phi), chipIDguess = lr.getChipID(seedC.getZ() + 0.5 * zDRStep);
2219 std::array<int, MaxLadderCand> lad2Check;
2220 nLad2Check = mFieldON ? findLaddersToCheckBOn(lrID, ladIDguess, trcCircle, errYFrac, lad2Check) : findLaddersToCheckBOff(lrID, ladIDguess, trcLinPar, errYFrac, lad2Check);
2222 for (
int ilad = nLad2Check; ilad--;) {
2223 int ladID = lad2Check[ilad];
2224 const auto& lad = lr.ladders[ladID];
2228 float t = 1e9, xCross, yCross;
2229 const auto& chipC = lad.chips[chipIDguess];
2231 chipC.xyEdges.circleCrossParam(trcCircle, t);
2233 chipC.xyEdges.lineCrossParam(trcLinPar, t);
2235 chipC.xyEdges.eval(t, xCross, yCross);
2236 float dx = xCross - xCurr, dy = yCross - yCurr, dst2 = dx * dx + dy * dy,
dst = sqrtf(dst2);
2238 float zCross = seedC.getZ() + seedC.getTgl() * (dst2 < 2 * (dx * xCurr + dy * yCurr) ?
dst : -
dst);
2240 for (
int ich = -1; ich < 2; ich++) {
2241 int chipID = chipIDguess + ich;
2243 if (chipID < 0 || chipID >=
static_cast<int>(lad.chips.size())) {
2246 if (lad.chips[chipID].zRange.isOutside(zCross, mParams->
nABSigmaZ * errZ)) {
2249 const auto& clRange = itsChipClRefs.
chipRefs[lad.chips[chipID].id];
2250 if (!clRange.getEntries()) {
2251 LOG(
debug) <<
"No clusters in chip range";
2255 float errYcalp = errY * (csa * chipC.csAlp + sna * chipC.snAlp);
2257 float yTrack = -xCross * chipC.snAlp + yCross * chipC.csAlp;
2258 if (!preselectChipClusters(chipSelClusters, clRange, itsChipClRefs, yTrack, zCross, tolerY, tolerZ)) {
2259 LOG(
debug) <<
"No compatible clusters found";
2264 if (!trcLC.rotate(chipC.alp) || !trcLC.propagateTo(chipC.xRef, propagator->getNominalBz())) {
2265 LOG(
debug) <<
" failed to rotate to alpha=" << chipC.alp <<
" or prop to X=" << chipC.xRef;
2270 for (
auto clID : chipSelClusters) {
2271 const auto& cls = mITSClustersArray[clID];
2272 auto chi2 = trcLC.getPredictedChi2(cls);
2276 int lnkID = registerABTrackLink(ABSeed, trcLC, clID, seedID, lrID, ladID, chi2);
2278 auto& link = ABSeed.
getLink(lnkID);
2294void MatchTPCITS::accountForOverlapsAB(
int lrSeed)
2297 LOG(warning) <<
"TODO";
2302 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2306 const auto& lr = mRGHelper.
layers[ilr];
2307 int nacc = 0, jmp = 0;
2308 if (lr.ladders[lad0].xyEdges.seenByCircle(circle, errYFrac)) {
2309 lad2Check[nacc++] = lad0;
2311 bool doUp =
true, doDn =
true;
2314 int ldID = (lad0 + jmp) % lr.nLadders;
2315 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2316 lad2Check[nacc++] = ldID;
2322 int ldID = lad0 - jmp;
2324 ldID += lr.nLadders;
2326 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2327 lad2Check[nacc++] = ldID;
2338 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2342 const auto& lr = mRGHelper.
layers[ilr];
2343 int nacc = 0, jmp = 0;
2344 if (lr.ladders[lad0].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2345 lad2Check[nacc++] = lad0;
2347 bool doUp =
true, doDn =
true;
2350 int ldID = (lad0 + jmp) % lr.nLadders;
2351 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2352 lad2Check[nacc++] = ldID;
2358 int ldID = lad0 - jmp;
2360 ldID += lr.nLadders;
2362 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2363 lad2Check[nacc++] = ldID;
2390 auto& nextLink = ABSeed.
getLink(nextID);
2392 bool newIsBetter = parentID <=
MinusOne ? isBetter(chi2, nextLink.chi2) : isBetter(ABSeed.getLink(parentID).chi2NormPredict(chi2Cl), nextLink.chi2Norm());
2394 if (count < mParams->maxABLinksOnLayer) {
2395 ABSeed.
addLink(trc, clID, parentID, nextID, lr, nc, laddID, chi2);
2408 nextID = nextLink.nextOnLr;
2411 if (count < mParams->maxABLinksOnLayer) {
2431 auto tpcTrOrig = mTPCTracksArray[tTPC.
sourceID];
2454 float dDrift = (timeIC - tTPC.
time0) * mTPCBin2Z;
2471void MatchTPCITS::fillClustersForAfterBurner(
int rofStart,
int nROFs,
ITSChipClustersRefs& itsChipClRefs)
2476 int first = mITSClusterROFRec[rofStart].getFirstEntry(),
last =
first;
2477 for (
int ir = nROFs;
ir--;) {
2478 last += mITSClusterROFRec[rofStart +
ir].getNEntries();
2480 itsChipClRefs.
clear();
2481 auto& idxSort = itsChipClRefs.
clusterID;
2482 for (
int icl =
first; icl <
last; icl++) {
2483 if (mABClusterLinkIndex[icl] !=
MinusTen) {
2484 idxSort.push_back(icl);
2488 const auto& clusArr = mITSClustersArray;
2489 std::sort(idxSort.begin(), idxSort.end(), [&clusArr](
int i,
int j) {
2490 const auto &clI = clusArr[i], &clJ = clusArr[j];
2491 if (clI.getSensorID() < clJ.getSensorID()) {
2494 if (clI.getSensorID() == clJ.getSensorID()) {
2495 return clI.getZ() < clJ.getZ();
2500 int ncl = idxSort.size();
2501 int lastSens = -1, nClInSens = 0;
2503 for (
int icl = 0; icl < ncl; icl++) {
2504 const auto& clus = mITSClustersArray[idxSort[icl]];
2505 int sens = clus.getSensorID();
2506 if (sens != lastSens) {
2508 chipClRefs->setEntries(nClInSens);
2511 chipClRefs = &itsChipClRefs.
chipRefs[(lastSens = sens)];
2512 chipClRefs->setFirstEntry(icl);
2517 chipClRefs->setEntries(nClInSens);
2524 mITSTimeBiasInBC =
n;
2531 mITSROFrameLengthMUS = fums;
2532 mITSTimeResMUS = mITSROFrameLengthMUS / std::sqrt(12.f);
2533 mITSROFrameLengthMUSInv = 1. / mITSROFrameLengthMUS;
2540 mITSROFrameLengthInBC = nbc;
2542 mITSTimeResMUS = mITSROFrameLengthMUS / std::sqrt(12.f);
2543 mITSROFrameLengthMUSInv = 1. / mITSROFrameLengthMUS;
2552 if (minBC < 0 && mUseBCFilling) {
2553 if (mUseBCFilling) {
2554 mUseBCFilling =
false;
2555 LOG(warning) <<
"Disabling match validation by BunchFilling as no interacting bunches found";
2559 int bcAbove = minBC;
2564 mClosestBunchAbove[
i] = bcAbove;
2566 int bcBelow = maxBC;
2571 mClosestBunchBelow[
i] = bcBelow;
2580 if (tbrange.
getMin() > 0) {
2585 int bc = mClosestBunchAbove[irMin.bc];
2586 if (
bc < irMin.bc) {
2590 bc = mClosestBunchBelow[irMax.bc];
2591 if (
bc > irMax.bc) {
2592 if (irMax.orbit == 0) {
2599 return {irMin, irMax};
2603void MatchTPCITS::removeTPCfromITS(
int tpcID,
int itsID)
2606 auto& tITS = mITSWork[itsID];
2607 if (isValidatedITS(tITS)) {
2612 auto& rcITS = mMatchRecordsITS[next];
2613 if (rcITS.partnerID == tpcID) {
2615 tITS.
matchID = rcITS.nextRecID;
2617 mMatchRecordsITS[topID].nextRecID = rcITS.nextRecID;
2622 next = rcITS.nextRecID;
2627void MatchTPCITS::removeITSfromTPC(
int itsID,
int tpcID)
2630 auto& tTPC = mTPCWork[tpcID];
2631 if (isValidatedTPC(tTPC)) {
2636 auto& rcTPC = mMatchRecordsTPC[next];
2637 if (rcTPC.partnerID == itsID) {
2639 tTPC.
matchID = rcTPC.nextRecID;
2641 mMatchRecordsTPC[topID].nextRecID = rcTPC.nextRecID;
2646 next = rcTPC.nextRecID;
2655 for (
int icl = track.getNumberOfClusters(); icl--;) {
2656 mABClusterLinkIndex[mITSTrackClusIdx[clEntry++]] =
MinusTen;
2661int MatchTPCITS::preselectChipClusters(std::vector<int>& clVecOut,
const ClusRange& clRange,
const ITSChipClustersRefs& itsChipClRefs,
2662 float trackY,
float trackZ,
float tolerY,
float tolerZ)
const
2665 int icID = clRange.getFirstEntry();
2666 for (
int icl = clRange.getEntries(); icl--;) {
2667 int clID = itsChipClRefs.
clusterID[icID++];
2668 const auto& cls = mITSClustersArray[clID];
2669 float dz = cls.getZ() - trackZ;
2670 LOG(
debug) <<
"cl" << icl <<
'/' << clID <<
" "
2671 <<
" dZ: " << dz <<
" [" << tolerZ <<
"| dY: " << trackY - cls.getY() <<
" [" << tolerY <<
"]";
2673 float clsZ = cls.getZ();
2674 LOG(
debug) <<
"Skip the rest since " << trackZ <<
" < " << clsZ <<
"\n";
2676 }
else if (dz < -tolerZ) {
2677 LOG(
debug) <<
"Skip cluster dz=" << dz <<
" Ztr=" << trackZ <<
" zCl=" << cls.getZ();
2680 if (fabs(trackY - cls.getY()) > tolerY) {
2681 LOG(
debug) <<
"Skip cluster dy= " << trackY - cls.getY() <<
" Ytr=" << trackY <<
" yCl=" << cls.getY();
2684 clVecOut.push_back(clID);
2686 return clVecOut.size();
2697 size_t sizTotShm = 0, capTotShm = 0, sizTot = 0, capTot = 0, siz = 0, cap = 0, cnt = 0, cntCap = 0;
2703 LOGP(info,
"Size SHM, matchedTracks : size {:9} cap {:9}", siz, cap);
2709 LOGP(info,
"Size SHM, ABTrackletRefs : size {:9} cap {:9}", siz, cap);
2711 siz = ABTrackletClusterIDs.size() *
sizeof(
int);
2712 cap = ABTrackletClusterIDs.capacity() *
sizeof(
int);
2715 LOGP(info,
"Size SHM, ABTrackletClusterIDs : size {:9} cap {:9}", siz, cap);
2721 LOGP(info,
"Size SHM, matchLabels : size {:9} cap {:9}", siz, cap);
2727 LOGP(info,
"Size SHM, ABTrackletLabels : size {:9} cap {:9}", siz, cap);
2733 LOGP(info,
"Size SHM, calib : size {:9} cap {:9}", siz, cap);
2736 siz = mITSClustersArray.size() *
sizeof(
ITSCluster);
2737 cap = mITSClustersArray.capacity() *
sizeof(
ITSCluster);
2740 LOGP(info,
"Size RSS, mITSClustersArray : size {:9} cap {:9}", siz, cap);
2742 siz = mMatchRecordsTPC.size() *
sizeof(
MatchRecord);
2743 cap = mMatchRecordsTPC.capacity() *
sizeof(
MatchRecord);
2746 LOGP(info,
"Size RSS, mMatchRecordsTPC : size {:9} cap {:9}", siz, cap);
2748 siz = mMatchRecordsITS.size() *
sizeof(
MatchRecord);
2749 cap = mMatchRecordsITS.capacity() *
sizeof(
MatchRecord);
2752 LOGP(info,
"Size RSS, mMatchRecordsITS : size {:9} cap {:9}", siz, cap);
2754 siz = mITSROFTimes.size() *
sizeof(
BracketF);
2755 cap = mITSROFTimes.capacity() *
sizeof(
BracketF);
2758 LOGP(info,
"Size RSS, mITSROFTimes : size {:9} cap {:9}", siz, cap);
2764 LOGP(info,
"Size RSS, mTPCWork : size {:9} cap {:9}", siz, cap);
2770 LOGP(info,
"Size RSS, mITSWork : size {:9} cap {:9}", siz, cap);
2772 siz = mWinnerChi2Refit.size() *
sizeof(float);
2773 cap = mWinnerChi2Refit.capacity() *
sizeof(float);
2776 LOGP(info,
"Size RSS, mWinnerChi2Refit : size {:9} cap {:9}", siz, cap);
2778 siz = mTPCABSeeds.size() *
sizeof(float);
2779 cap = mTPCABSeeds.capacity() *
sizeof(float);
2782 for (
const auto&
a : mTPCABSeeds) {
2783 siz +=
a.sizeInternal();
2784 cap +=
a.capInternal();
2785 cnt +=
a.getNLinks();
2786 cntCap +=
a.getNLinks();
2790 LOGP(info,
"Size RSS, mTPCABSeeds : size {:9} cap {:9} | internals size:{}/capacity:{} for {} elements", siz, cap, cnt, cntCap, mTPCABSeeds.size());
2792 siz = mTPCABIndexCache.size() *
sizeof(
int);
2793 cap = mTPCABIndexCache.capacity() *
sizeof(
int);
2796 LOGP(info,
"Size RSS, mTPCABIndexCache : size {:9} cap {:9}", siz, cap);
2798 siz = mABWinnersIDs.size() *
sizeof(
int);
2799 cap = mABWinnersIDs.capacity() *
sizeof(
int);
2802 LOGP(info,
"Size RSS, mABWinnersIDs : size {:9} cap {:9}", siz, cap);
2804 siz = mABClusterLinkIndex.size() *
sizeof(
int);
2805 cap = mABClusterLinkIndex.capacity() *
sizeof(
int);
2808 LOGP(info,
"Size RSS, mABClusterLinkIndex : size {:9} cap {:9}", siz, cap);
2811 siz += mTPCSectIndexCache[is].size() *
sizeof(
int);
2812 cap += mTPCSectIndexCache[is].capacity() *
sizeof(
int);
2816 LOGP(info,
"Size RSS, mTPCSectIndexCache : size {:9} cap {:9}", siz, cap);
2819 siz += mITSSectIndexCache[is].size() *
sizeof(
int);
2820 cap += mITSSectIndexCache[is].capacity() *
sizeof(
int);
2824 LOGP(info,
"Size RSS, mITSSectIndexCache : size {:9} cap {:9}", siz, cap);
2827 siz += mTPCTimeStart[is].size() *
sizeof(
int);
2828 cap += mTPCTimeStart[is].capacity() *
sizeof(
int);
2832 LOGP(info,
"Size RSS, mTPCTimeStart : size {:9} cap {:9}", siz, cap);
2835 siz += mITSTimeStart[is].size() *
sizeof(
int);
2836 cap += mITSTimeStart[is].capacity() *
sizeof(
int);
2840 LOGP(info,
"Size RSS, mITSTimeStart : size {:9} cap {:9}", siz, cap);
2842 siz = mITSTrackROFContMapping.size() *
sizeof(
int);
2843 cap = mITSTrackROFContMapping.capacity() *
sizeof(
int);
2846 LOGP(info,
"Size RSS, ITSTrackROFContMapping: size {:9} cap {:9}", siz, cap);
2848 LOGP(info,
"TotalSizes/Capacities: SHM: {}/{} Heap: {}/{}", sizTotShm, capTotShm, sizTot, capTot);
2855 mNThreads =
n > 0 ?
n : 1;
2857 LOG(warning) <<
"Multithreading is not supported, imposing single thread";
2866#ifdef _ALLOW_DEBUG_TREES_
2882 mTimer[SWDBG].Start(
false);
2883 const auto& tpcOrig = mTPCTracksArray[tpcIndex];
2884 uint8_t clSect = 0, clRow = 0, prevRow = 0xff, padFromEdge = -1;
2887 std::array<bool, 152> shMap{};
2888 bool prevRawShared =
false;
2889 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
2890 tpcOrig.getClusterReference(mTPCTrackClusIdx,
i, clSect, clRow, clIdx);
2891 unsigned int absoluteIndex = mTPCClusterIdxStruct->
clusterOffset[clSect][clRow] + clIdx;
2893 if (!(prevRow == clRow && prevRawShared)) {
2897 prevRawShared =
true;
2900 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
2901 padFromEdge =
uint8_t(clus.getPad());
2902 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
2903 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
2905 int tb = tpcOrig.getTime0() * mNTPCOccBinLengthInv;
2906 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2907 (*mDBGOut) <<
"tpcOrig"
2908 <<
"tf=" << mTFCount
2909 <<
"index=" << tpcIndex
2911 <<
"chi2TPC=" << tpcOrig.getChi2()
2912 <<
"nClus=" << tpcOrig.getNClusters()
2913 <<
"nShared=" << nshared
2914 <<
"time0=" << tpcOrig.getTime0()
2916 <<
"minRow=" << clRow
2917 <<
"padFromEdge=" << padFromEdge
2918 <<
"multTPC=" << mltTPC;
2920 (*mDBGOut) <<
"tpcOrig"
2921 <<
"tpcLbl=" << mTPCTrkLabels[tpcIndex];
2923 (*mDBGOut) <<
"tpcOrig"
2925 mTimer[SWDBG].Stop();
2933 mTimer[SWDBG].Start(
false);
2935 auto& trackITS = mITSWork[itsID];
2936 auto& trackTPC = mTPCWork[tpcID];
2938 chi2 = getPredictedChi2NoZ(trackITS, trackTPC);
2940 (*mDBGOut) <<
"match"
2941 <<
"tf=" << mTFCount <<
"chi2Match=" << chi2 <<
"its=" << trackITS <<
"tpc=" << trackTPC <<
"tcorr=" << tCorr;
2943 (*mDBGOut) <<
"match"
2944 <<
"itsLbl=" << mITSLblWork[itsID] <<
"tpcLbl=" << mTPCLblWork[tpcID];
2946 int tb = mTPCTracksArray[trackTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
2947 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2948 (*mDBGOut) <<
"match"
2949 <<
"rejFlag=" << rejFlag
2950 <<
"multTPC=" << mltTPC
2951 <<
"multITSTr=" << mITSTrackROFRec[trackITS.roFrame].getNEntries()
2952 <<
"multITSCl=" << mITSClusterROFRec[trackITS.roFrame].getNEntries()
2955 mTimer[SWDBG].Stop();
2963 mTimer[SWDBG].Start(
false);
2965 LOG(info) <<
"Dumping debug tree for winner matches";
2966 for (
int iits = 0; iits <
int(mITSWork.size()); iits++) {
2967 auto& tITS = mITSWork[iits];
2968 if (isDisabledITS(tITS)) {
2971 auto& itsMatchRec = mMatchRecordsITS[tITS.
matchID];
2972 int itpc = itsMatchRec.partnerID;
2973 auto& tTPC = mTPCWork[itpc];
2975 (*mDBGOut) <<
"matchWin"
2976 <<
"tf=" << mTFCount <<
"chi2Match=" << itsMatchRec.chi2 <<
"chi2Refit=" << mWinnerChi2Refit[iits] <<
"its=" << tITS <<
"tpc=" << tTPC;
2979 (*mDBGOut) <<
"matchWin"
2980 <<
"itsLbl=" << mITSLblWork[iits] <<
"tpcLbl=" << mTPCLblWork[itpc];
2982 int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
2983 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
2984 (*mDBGOut) <<
"matchWin"
2985 <<
"multTPC=" << mltTPC
2986 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
2987 <<
"multITSCl=" << mITSClusterROFRec[tITS.
roFrame].getNEntries()
2990 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
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 setTPCCorrMaps(o2::gpu::CorrectionMapsHelper *maph)
print settings
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 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
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