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);
109 for (
int sec = o2::constants::math::NSectors; sec--;) {
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();
176 mITSClustersArray[lr].clear();
177 mITSClusterSizes[lr].clear();
180 mTPCABIndexCache.clear();
181 mABWinnersIDs.clear();
182 for (
auto& clStatus : mABClusterStatus) {
185 for (
auto& abClus : mABLayerClusters) {
188 mNMatchesControl = 0;
190 for (
int sec = o2::constants::math::NSectors; sec--;) {
191 mITSSectIndexCache[sec].clear();
192 mITSTimeStart[sec].clear();
193 mTPCSectIndexCache[sec].clear();
194 mTPCTimeStart[sec].clear();
201 for (
int i = 0;
i < mNThreads;
i++) {
210 mTPCVDrift =
v.getVDrift();
211 mTPCDriftTimeOffset =
v.getTimeOffset();
226 LOG(error) <<
"Initialization was already done";
229 for (
int i = NStopWatches;
i--;) {
234 YMaxAtXMatchingRef = mParams->
XMatchingRef * 0.17632698;
239 if (!prop->getMatLUT() && mParams->
matCorr == o2::base::Propagator::MatCorrType::USEMatCorrLUT) {
240 LOG(warning) <<
"Requested material LUT is not loaded, switching to TGeo usage";
249#ifdef _ALLOW_DEBUG_TREES_
252 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(),
"recreate");
262 mABChipsBounds[lr] = geomITS->getFirstChipIndex(lr);
271 if (fair::Logger::Logging(fair::Severity::info)) {
277void MatchTPCITS::updateTimeDependentParams()
281 mFieldON = std::abs(mBz) > 0.01;
283 static bool initOnceDone =
false;
291 if (mITSROFrameLengthMUS[lr] < marginMax) {
292 marginMax = mITSROFrameLengthMUS[lr];
296 if (margin > marginMax) {
297 if (mABROFMarginMUS != marginMax) {
298 LOGP(warn,
"abROFMarginMUS={} exceeds 45% of the shortest AfterBurner layer ROF length, clamping to {}", margin, marginMax);
302 mABROFMarginMUS = margin;
306 mTPCTBinMUS = elParam.ZbinWidth;
307 mTPCTBinNS = mTPCTBinMUS * 1e3;
308 mTPCZMax = detParam.TPClength;
309 mTPCTBinMUSInv = 1. / mTPCTBinMUS;
310 assert(mITSROFrameLengthMUS[mITSClockLayer] > 0.0f);
314 mTPCmeanX0Inv = matbd.meanX2X0 / matbd.length;
316 mTPCBin2Z = mTPCTBinMUS * mTPCVDrift;
317 mZ2TPCBin = 1. / mTPCBin2Z;
318 mTPCVDriftInv = 1. / mTPCVDrift;
319 mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin;
323 mMinTPCTrackPtInv = (mFieldON && mParams->
minTPCTrackR > 0) ? 1. / std::abs(mParams->
minTPCTrackR * mBz * o2::constants::math::B2C) : 999.;
324 mMinITSTrackPtInv = (mFieldON && mParams->
minITSTrackR > 0) ? 1. / std::abs(mParams->
minITSTrackR * mBz * o2::constants::math::B2C) : 999.;
327 float scale = mLumiCTP;
329 LOGP(warning,
"Negative scale factor for TPC covariance correction, setting it to zero");
332 mCovDiagInner = trackTune.getCovInnerTotal(scale);
333 mCovDiagOuter = trackTune.getCovOuterTotal(scale);
337void MatchTPCITS::selectBestMatches()
340 mTimer[SWSelectBest].Start(
false);
341 int nValidated = 0, iter = 0;
346 int ntpc = mTPCWork.size(), nremaining = 0;
347 for (
int it = 0; it < ntpc; it++) {
348 auto& tTPC = mTPCWork[it];
349 if (isDisabledTPC(tTPC) || isValidatedTPC(tTPC)) {
353 if (validateTPCMatch(it)) {
355 if (mVDriftCalibOn && (!mFieldON || std::abs(tTPC.getQ2Pt()) < mParams->
maxVDriftTrackQ2Pt)) {
362 LOGP(info,
"iter {}: Validated {} of {} remaining matches", iter, nValidated, nremaining);
365 mNMatches += nValidated;
366 }
while (nValidated);
368 mTimer[SWSelectBest].Stop();
369 LOGP(info,
"Validated {} matches out of {} for {} TPC and {} ITS tracks in {} iterations", mNMatches, mNMatchesControl, mTPCWork.size(), mITSWork.size(), iter);
373bool MatchTPCITS::validateTPCMatch(
int iTPC)
375 auto& tTPC = mTPCWork[iTPC];
376 auto& rcTPC = mMatchRecordsTPC[tTPC.matchID];
378 auto& tITS = mITSWork[rcTPC.partnerID];
379 auto& rcITS = mMatchRecordsITS[tITS.matchID];
383 if (rcITS.partnerID == iTPC) {
384 int cloneID = tITS.getCloneShift();
386 cloneID += rcTPC.partnerID;
387 auto& tITSClone = mITSWork[cloneID];
388 if (isDisabledITS(tITSClone)) {
391 int nextITSCloneMatchID = tITSClone.matchID;
392 if (rcITS.isBetter(mMatchRecordsITS[nextITSCloneMatchID])) {
393 LOGP(
debug,
"Suppressing clone cloneID={} of winner clone {} of source ITS {}", cloneID, rcTPC.partnerID, tITS.sourceID);
394 while (nextITSCloneMatchID >
MinusOne) {
395 auto& rcITSClone = mMatchRecordsITS[nextITSCloneMatchID];
396 removeITSfromTPC(cloneID, rcITSClone.partnerID);
397 nextITSCloneMatchID = rcITSClone.nextRecID;
405 int nextTPC = rcTPC.nextRecID;
407 auto& rcTPCrem = mMatchRecordsTPC[nextTPC];
408 removeTPCfromITS(iTPC, rcTPCrem.partnerID);
409 nextTPC = rcTPCrem.nextRecID;
412 int itsWinID = rcTPC.partnerID;
415 int nextITS = rcITS.nextRecID;
417 auto& rcITSrem = mMatchRecordsITS[nextITS];
418 removeITSfromTPC(itsWinID, rcITSrem.partnerID);
419 nextITS = rcITSrem.nextRecID;
429int MatchTPCITS::getNMatchRecordsTPC(
const TrackLocTPC& tTPC)
const
434 recID = mMatchRecordsTPC[recID].nextRecID;
441int MatchTPCITS::getNMatchRecordsITS(
const TrackLocITS& tTPC)
const
446 auto& itsRecord = mMatchRecordsITS[recID];
447 recID = itsRecord.nextRecID;
457 const float SQRT12DInv = 2. / sqrt(12.);
461 const auto& tpcOrig = mTPCTracksArray[tpcID];
468 tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx);
472 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
474 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
475 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
480 if (extConstrained) {
483 terr += tpcTimeBin2MUS(tpcOrig.hasBothSidesClusters() ? mParams->
safeMarginTPCITSTimeBin : mTPCTimeEdgeTSafeMargin);
485 auto& trc = mTPCWork.emplace_back(
486 TrackLocTPC{_tr, {
t0 - terr,
t0 + terr}, extConstrained ?
t0 : tpcTimeBin2MUS(tpcOrig.getTime0()),
488 terr * (extConstrained ? mTPCExtConstrainedNSigmaInv : SQRT12DInv),
499 if (srcGID.getSource() ==
GTrackID::TPC && !trackTune.sourceLevelTPC) {
500 if (trackTune.useTPCInnerCorr) {
501 trc.updateParams(trackTune.tpcParInner);
507 if (!propagateToRefX(trc)) {
512 mTPCLblWork.emplace_back(mTPCTrkLabels[tpcID]);
520bool MatchTPCITS::prepareTPCData()
523 mTimer[SWPrepTPC].Start(
false);
524 const auto& inp = *mRecoCont;
526 mTPCTracksArray = inp.getTPCTracks();
527 mTPCTrackClusIdx = inp.getTPCTracksClusterRefs();
528 mTPCClusterIdxStruct = &inp.inputsTPCclusters->clusterIndex;
529 mTPCRefitterShMap = inp.clusterShMapTPC;
530 mTPCRefitterOccMap = inp.occupancyMapTPC;
533 mTPCTrkLabels = inp.getTPCTracksMCLabels();
536 int ntr = mTPCTracksArray.size(), ntrW = 0.7 * ntr;
538 mTPCWork.reserve(ntrW);
540 mTPCLblWork.reserve(ntrW);
542 for (
int sec = o2::constants::math::NSectors; sec--;) {
543 mTPCSectIndexCache[sec].reserve(100 + 1.2 * ntrW / o2::constants::math::NSectors);
546 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCCorrMaps, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(),
nullptr,
o2::base::Propagator::Instance());
547 mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
549 if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) {
550 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
551 int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0;
552 int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1,
int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv));
553 mTBinClOcc.resize(nTPCOccBins);
554 std::vector<float> mltHistTB(nTPCOccBins);
555 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
556 for (
int i = 0;
i < nTPCOccBins;
i++) {
557 mltHistTB[
i] = mTPCRefitter->getParam()->GetUnscaledMult(tb);
558 tb += mNTPCOccBinLength;
560 for (
int i = nTPCOccBins;
i--;) {
562 if (
i + sumBins < nTPCOccBins) {
563 sm -= mltHistTB[
i + sumBins];
568 mTBinClOcc.resize(1);
571 auto creator = [
this](
auto& trk,
GTrackID gid,
float time0,
float terr) {
572 if constexpr (isITSTrack<decltype(trk)>()) {
577 }
else if (std::abs(trk.getQ2Pt()) > mMinTPCTrackPtInv) {
582 if constexpr (isTPCTrack<decltype(trk)>()) {
584 if (!this->mSkipTPCOnly && trk.getNClusters() > 0) {
585 resAdd = this->addTPCSeed(trk, this->tpcTimeBin2MUS(time0), this->tpcTimeBin2MUS(terr), gid, (tpcIndex = gid.getIndex()));
588 if constexpr (isTPCTOFTrack<decltype(trk)>()) {
590 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
592 if constexpr (isTRDTrack<decltype(trk)>()) {
594 resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->
getTPCContributorGID(gid)));
596#ifdef _ALLOW_DEBUG_TREES_
607 int nITSROFs = mITSROFTimes.size();
609 for (
int sec = o2::constants::math::NSectors; sec--;) {
610 auto& indexCache = mTPCSectIndexCache[sec];
612 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" TPC tracks";
614 if (!indexCache.size()) {
617 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
618 auto& trcA = mTPCWork[a];
619 auto& trcB = mTPCWork[b];
620 return (trcA.tBracket.getMax() - trcB.tBracket.getMax()) < 0.;
626 float tmax = mTPCWork[indexCache.back()].tBracket.getMax();
627 if (maxTime < tmax) {
630 int nbins = 1 + (mITSTriggered ? time2ITSROFrameTrig(tmax, 0) : time2ITSROFrameCont(tmax));
631 auto& timeStart = mTPCTimeStart[sec];
632 timeStart.resize(nbins, -1);
636 for (
int itr = 0; itr < (
int)indexCache.size(); itr++) {
637 auto& trc = mTPCWork[indexCache[itr]];
638 while (itsROF < nITSROFs && !(trc.tBracket < mITSROFTimes[itsROF])) {
641 int itsROFMatch = itsROF;
642 if (itsROFMatch && timeStart[--itsROFMatch] == -1) {
643 timeStart[itsROFMatch] = itr;
646 for (
int i = 1;
i < nbins;
i++) {
647 if (timeStart[
i] == -1) {
648 timeStart[
i] = timeStart[
i - 1];
669 mInteractionMUSLUT.clear();
670 mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1);
671 mTimer[SWPrepTPC].Stop();
672 return mTPCWork.size() > 0;
676bool MatchTPCITS::prepareITSData()
678 static size_t errCount = 0;
679 constexpr size_t MaxErrors2Report = 10;
681 mTimer[SWPrepITS].Start(
false);
682 const auto& inp = *mRecoCont;
687 for (
int lr = 0; lr < nClLr; lr++) {
688 mITSClusterROFRec[lr] = inp.getITSClustersROFRecords(lr);
689 const auto clusITS = inp.getITSClusters(lr);
690 mNITSClusters += clusITS.size();
691 const auto patterns = inp.getITSClustersPatterns(lr);
692 auto pattIt = patterns.begin();
693 mITSClustersArray[lr].reserve(clusITS.size());
694#ifdef ENABLE_UPGRADES
705 mITSClusterSizes[lr].reserve(clusITS.size());
706 auto pattIt2 = patterns.begin();
707 for (
auto& clus : clusITS) {
708 auto pattID = clus.getPatternID();
710#ifdef ENABLE_UPGRADES
720#ifdef ENABLE_UPGRADES
722 npix = mIT3Dict->getNpixels(pattID, ib);
730 mITSClusterSizes[lr].push_back(std::clamp(npix, 0u, 255u));
733 mITSClsLabels[lr] = inp.getITSClustersMCLabels(lr);
736 if (!mNITSClusters) {
737 LOGP(warn,
"No ITS clusters");
743 auto& abClus = mABLayerClusters[lr];
748 const auto& rofs = mITSClusterROFRec[inp.getITSPerLayer() ? lr : 0];
749 abClus.rofTimes.reserve(rofs.size());
750 for (
const auto& rofRec : rofs) {
751 abClus.rofTimes.push_back(
getITSROFTimeBracket(rofRec.getBCData().differenceInBC(mStartIR), lr));
756 if (inp.getITSPerLayer()) {
758 mABClusterStatus[lr].resize(mITSClustersArray[lr].
size(),
MinusOne);
761 mABClusterStatus[0].resize(mITSClustersArray[0].
size(),
MinusOne);
765 mITSTracksArray = inp.getITSTracks();
766 mITSTrackClusIdx = inp.getITSTracksClusterRefs();
767 mITSTrackROFRec = inp.getITSTracksROFRecords();
769 mITSTrkLabels = inp.getITSTracksMCLabels();
771 int nROFs = mITSTrackROFRec.size();
772 mITSWork.reserve(mITSTracksArray.size());
774 for (
int sec = o2::constants::math::NSectors; sec--;) {
775 mITSTimeStart[sec].resize(nROFs, -1);
778 long maxBCs = nHBF *
long(o2::constants::lhc::LHCMaxBunches);
780 trackLTInt.setTimeNotNeeded();
781 mITSMaxROFOverhangMUS = 0.f;
784 for (
int irof = 0; irof < nROFs; irof++) {
785 const auto& rofRec = mITSTrackROFRec[irof];
786 long nBC = rofRec.getBCData().differenceInBC(mStartIR);
787 if (nBC > maxBCs || nBC < 0) {
788 if (++errCount < MaxErrors2Report) {
789 LOGP(alarm,
"ITS ROF#{} start {} is not compatible with TF 1st orbit {} or TF length of {} HBFs",
790 irof, rofRec.getBCData().asString(), mStartIR.
asString(), nHBF);
795 float tMin = tBracket.getMin(), tMax = tBracket.getMax();
796 if (!mITSTriggered) {
797 size_t irofCont = nBC / mITSROFrameLengthInBC[mITSClockLayer];
798 if (mITSTrackROFContMapping.size() <= irofCont) {
799 mITSTrackROFContMapping.resize((1 + irofCont / 128) * 128, 0);
801 mITSTrackROFContMapping[irofCont] = irof;
804 mITSROFTimes.emplace_back(tMin, tMax);
806 for (
int sec = o2::constants::math::NSectors; sec--;) {
807 mITSTimeStart[sec][irof] = mITSSectIndexCache[sec].size();
810 int trlim = rofRec.getFirstEntry() + rofRec.getNEntries();
811 for (
int it = rofRec.getFirstEntry(); it < trlim; it++) {
812 const auto& trcOrig = mITSTracksArray[it];
814 flagUsedITSClusters(trcOrig);
816 if (trcOrig.getParamOut().getX() < 1.) {
819 if (std::abs(trcOrig.getQ2Pt()) > mMinITSTrackPtInv) {
825 float tMinTrc = tMin, tMaxTrc = tMax;
826 const auto& tstamp = trcOrig.getTimeStamp();
827 if (tstamp.getTimeStampError() > 0.f) {
829 assert(tstamp.getTimeStamp() - tstamp.getTimeStampError() >= nBC + mITSTimeBiasInBC[mITSClockLayer] - 0.5f);
830 float errBC = tstamp.getTimeStampError() + trackTimeMarginBC;
831 tMinTrc = (tstamp.getTimeStamp() - errBC) * o2::constants::lhc::LHCBunchSpacingMUS;
832 tMaxTrc = (tstamp.getTimeStamp() + errBC) * o2::constants::lhc::LHCBunchSpacingMUS;
833 auto& rofEnv = mITSROFTimes.back();
834 if (tMinTrc < rofEnv.getMin()) {
835 rofEnv.setMin(tMinTrc);
837 if (tMaxTrc > rofEnv.getMax()) {
838 rofEnv.setMax(tMaxTrc);
839 if (tMaxTrc - tMax > mITSMaxROFOverhangMUS) {
840 mITSMaxROFOverhangMUS = tMaxTrc - tMax;
844 int nWorkTracks = mITSWork.size();
846 auto& trc = mITSWork.emplace_back(
TrackLocITS{trcOrig.getParamOut(), {tMinTrc, tMaxTrc}, it, irof,
MinusOne});
852 trackLTInt.clearFast();
853 if (!propagateToRefX(trc, &trackLTInt)) {
857 trc.xrho = trackLTInt.getXRho();
858 trc.dL = trackLTInt.getL();
861 mITSLblWork.emplace_back(mITSTrkLabels[it]);
866 mITSSectIndexCache[sector].push_back(nWorkTracks);
874 float trcY = trc.getY(), tgp = trc.getSnp();
875 tgp /= std::sqrt((1.f - tgp) * (1.f + tgp));
877 float dyUpDn[2] = {std::abs((YMaxAtXMatchingRef - trcY) / (tgp + Tan70)), std::abs((YMaxAtXMatchingRef + trcY) / (tgp - Tan70))};
879 int sel = dyUpDn[0] < dyUpDn[1] ? 0 : 1;
880 if (dyUpDn[sel] < mSectEdgeMargin) {
881 int sectNeib = sel == 0 ? (sector < (o2::constants::math::NSectors - 1) ? sector + 1 : 0) : (sector > 1 ? sector - 1 :
o2::constants::math::NSectors - 1);
882 addLastTrackCloneForNeighbourSector(sectNeib, &trackLTInt);
887 if (!mITSTriggered) {
888 int nr = mITSTrackROFContMapping.size();
889 for (
int i = 1;
i < nr;
i++) {
890 if (mITSTrackROFContMapping[
i] < mITSTrackROFContMapping[
i - 1]) {
891 mITSTrackROFContMapping[
i] = mITSTrackROFContMapping[
i - 1];
900 for (
int sec = o2::constants::math::NSectors; sec--;) {
901 auto& indexCache = mITSSectIndexCache[sec];
903 LOG(info) <<
"Sorting sector" << sec <<
" | " << indexCache.size() <<
" ITS tracks";
905 if (!indexCache.size()) {
908 std::sort(indexCache.begin(), indexCache.end(), [
this](
int a,
int b) {
909 auto& trackA = mITSWork[a];
910 auto& trackB = mITSWork[b];
911 if (trackA.tBracket.getMin() < trackB.tBracket.getMin()) {
913 }
else if (trackA.tBracket.getMin() > trackB.tBracket.getMin()) {
916 return trackA.getTgl() < trackB.getTgl();
920 mTimer[SWPrepITS].Stop();
922 return mNITSClusters > 0;
926bool MatchTPCITS::prepareFITData()
931 prepareInteractionTimes();
937void MatchTPCITS::doMatching(
int sec)
940 auto& cacheITS = mITSSectIndexCache[sec];
941 auto& cacheTPC = mTPCSectIndexCache[sec];
942 auto& timeStartTPC = mTPCTimeStart[sec];
943 auto& timeStartITS = mITSTimeStart[sec];
944 int nTracksTPC = cacheTPC.size(), nTracksITS = cacheITS.size();
945 if (!nTracksTPC || !nTracksITS) {
947 LOG(info) <<
"Matchng sector " << sec <<
" : N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS <<
" in sector " << sec;
953 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
957 auto minROFITS = mITSWork[cacheITS.front()].roFrame;
959 if (minROFITS >=
int(timeStartTPC.size())) {
960 LOG(info) <<
"ITS min ROFrame " << minROFITS <<
" exceeds all cached TPC track ROF eqiuvalent " << cacheTPC.size() - 1;
964 int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0;
965 int idxMinTPC = timeStartTPC[minROFITS];
970 for (
int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) {
971 auto& trefTPC = mTPCWork[cacheTPC[itpc]];
974 auto tmn = trefTPC.tBracket.getMax() - maxTDriftSafe;
977 itsROBin = mITSTriggered ? time2ITSROFrameTrig(tmn, itsROBin) : time2ITSROFrameCont(tmn - mITSMaxROFOverhangMUS);
979 if (itsROBin >=
int(timeStartITS.size())) {
982 int iits0 = timeStartITS[itsROBin];
984 for (
auto iits = iits0; iits < nTracksITS; iits++) {
985 auto& trefITS = mITSWork[cacheITS[iits]];
987 LOG(
debug) <<
"TPC bracket: " << trefTPC.tBracket.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" TPCtgl: " << trefTPC.getTgl() <<
" ITStgl: " << trefITS.getTgl();
988 if (trefTPC.tBracket < trefITS.tBracket) {
991 if (trefTPC.tBracket > trefITS.tBracket) {
996 auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mTPCVDriftInv;
997 auto timeCorr = trefTPC.getCorrectedTime(deltaT);
998 auto timeCorrErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs + mParams->
safeMarginTimeCorrErr;
999 if (mVDriftCalibOn) {
1000 timeCorrErr += vdErrT * (250. - abs(trefITS.getZ()));
1003 LOG(
debug) <<
"TPC range: " << trange.asString() <<
" ITS bracket: " << trefITS.tBracket.asString() <<
" DZ: " << (trefITS.getZ() - trefTPC.getZ()) <<
" DT: " << timeCorr;
1005 auto cmpITSBracket = trefITS.tBracket.isOutside(timeCorr);
1006 if (cmpITSBracket) {
1007 if (trefITS.tBracket.isOutside(trange)) {
1012 timeCorr = trefITS.tBracket.getMin();
1013 trange.setMin(timeCorr);
1015 timeCorr = trefITS.tBracket.getMax();
1016 trange.setMax(timeCorr);
1025 int rejFlag = compareTPCITSTracks(trefITS, trefTPC,
chi2);
1027#ifdef _ALLOW_DEBUG_TREES_
1038 if (mUseBCFilling) {
1039 auto irBracket = tBracket2IRBracket(trange);
1040 if (irBracket.isInvalid()) {
1044 if (checkInteractionCandidates && mInteractions.size()) {
1046 int tmus = trange.getMin();
1050 auto entStart = tmus <
int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[tmus] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
1051 for (
int ent = entStart; ent < (
int)mInteractions.size(); ent++) {
1052 auto cmp = mInteractions[ent].tBracket.isOutside(trange);
1066 registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc],
chi2, matchedIC);
1071 LOG(info) <<
"Match sector " << sec <<
" N tracks TPC:" << nTracksTPC <<
" ITS:" << nTracksITS
1072 <<
" N TPC tracks checked: " << nCheckTPCControl <<
" (starting from " << idxMinTPC
1073 <<
"), checks: " << nCheckITSControl <<
", matches:" << nMatchesControl;
1075 mNMatchesControl += nMatchesControl;
1079void MatchTPCITS::suppressMatchRecordITS(
int itsID,
int tpcID)
1082 auto& tITS = mITSWork[itsID];
1083 int topID =
MinusOne, recordID = tITS.matchID;
1085 if (mMatchRecordsITS[recordID].partnerID == tpcID) {
1088 tITS.matchID = mMatchRecordsITS[recordID].nextRecID;
1090 mMatchRecordsITS[topID].nextRecID = mMatchRecordsITS[recordID].nextRecID;
1095 recordID = mMatchRecordsITS[recordID].nextRecID;
1100bool MatchTPCITS::registerMatchRecordTPC(
int iITS,
int iTPC,
float chi2,
int candIC)
1104 auto& tTPC = mTPCWork[iTPC];
1106 registerMatchRecordITS(iITS, iTPC,
chi2, candIC);
1107 tTPC.
matchID = mMatchRecordsTPC.size();
1108 mMatchRecordsTPC.emplace_back(iITS,
chi2,
MinusOne, candIC);
1114 auto& nextMatchRec = mMatchRecordsTPC[nextID];
1116 if (!nextMatchRec.isBetter(
chi2, candIC)) {
1117 if (count < mParams->maxMatchCandidates) {
1120 suppressMatchRecordITS(nextMatchRec.partnerID, iTPC);
1121 registerMatchRecordITS(iITS, iTPC,
chi2, candIC);
1123 nextMatchRec.chi2 =
chi2;
1124 nextMatchRec.matchedIC = candIC;
1125 nextMatchRec.partnerID = iITS;
1130 nextID = nextMatchRec.nextRecID;
1136 if (count < mParams->maxMatchCandidates) {
1138 topID = tTPC.
matchID = mMatchRecordsTPC.size();
1140 topID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC.size();
1143 registerMatchRecordITS(iITS, iTPC,
chi2, candIC);
1144 mMatchRecordsTPC.emplace_back(iITS,
chi2, nextID, candIC);
1149 suppressMatchRecordITS(mMatchRecordsTPC[nextID].partnerID, iTPC);
1151 nextID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC[nextID].nextRecID;
1156 nextID = mMatchRecordsTPC[nextID].nextRecID;
1165void MatchTPCITS::registerMatchRecordITS(
const int iITS,
int iTPC,
float chi2,
int candIC)
1168 auto& tITS = mITSWork[iITS];
1169 int idnew = mMatchRecordsITS.size();
1170 auto& newRecord = mMatchRecordsITS.emplace_back(iTPC,
chi2,
MinusOne, candIC);
1171 if (tITS.matchID < 0) {
1172 tITS.matchID = idnew;
1177 int topID =
MinusOne, nextRecord = tITS.matchID;
1179 auto& nextMatchRec = mMatchRecordsITS[nextRecord];
1180 if (!nextMatchRec.isBetter(
chi2, candIC)) {
1181 newRecord.nextRecID = nextRecord;
1183 tITS.matchID = idnew;
1185 mMatchRecordsITS[topID].nextRecID = idnew;
1190 nextRecord = mMatchRecordsITS[nextRecord].nextRecID;
1194 mMatchRecordsITS[topID].nextRecID = idnew;
1211 if (mVDriftCalibOn) {
1213 err2Tgl += addErr * addErr;
1215 diff *= diff / err2Tgl;
1220 bool testOtherPID =
false;
1221 float itsParam[5] = {tITS.getY(), tITS.getZ(), tITS.getSnp(), tITS.getTgl(), tITS.getQ2Pt()};
1222 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1224 tPID.setPID(tTPC.getPID(),
true);
1225 if (!tPID.correctForELoss(tITS.
xrho)) {
1228 float dCurv = (tPID.getQ2Pt() - tITS.getQ2Pt()) * mBz * o2::constants::math::B2C, dLEff = tITS.
dL * mParams->
ITSStepEffFraction, dCurvL = dCurv * dLEff;
1235 testOtherPID =
true;
1277 auto tITSAlt = tITS;
1278 tITSAlt.setPID(tTPC.getPID());
1282 chi2 = getPredictedChi2NoZ(tITSAlt, tTPC);
1284 chi2 = getPredictedChi2NoZ(tITS, tTPC);
1297 int ntpc = mTPCWork.size();
1298 printf(
"\n\nPrinting all TPC -> ITS matches for %d TPC tracks\n", ntpc);
1299 for (
int i = 0;
i < ntpc;
i++) {
1300 const auto& tTPC = mTPCWork[
i];
1301 int nm = getNMatchRecordsTPC(tTPC);
1302 printf(
"*** trackTPC#%6d %6d : Ncand = %d Best = %d\n",
i, tTPC.
sourceID, nm, tTPC.
matchID);
1305 const auto& rcTPC = mMatchRecordsTPC[recID];
1306 const auto& tITS = mITSWork[rcTPC.partnerID];
1307 printf(
" * cand %2d : ITS track %6d(src:%6d) Chi2: %.2f\n",
count, rcTPC.partnerID, tITS.
sourceID, rcTPC.chi2);
1309 recID = rcTPC.nextRecID;
1318 int nits = mITSWork.size();
1319 printf(
"\n\nPrinting all ITS -> TPC matches for %d ITS tracks\n", nits);
1321 for (
int i = 0;
i < nits;
i++) {
1322 const auto& tITS = mITSWork[
i];
1323 printf(
"*** trackITS#%6d %6d : Ncand = %d Best = %d\n",
i, tITS.
sourceID, getNMatchRecordsITS(tITS), tITS.
matchID);
1326 const auto& rcITS = mMatchRecordsITS[recID];
1327 const auto& tTPC = mTPCWork[rcITS.partnerID];
1328 printf(
" * cand %2d : TPC track %6d(src:%6d) Chi2: %.2f\n",
count, rcITS.partnerID, tTPC.
sourceID, rcITS.chi2);
1330 recID = rcITS.nextRecID;
1352 covMat(0, 0) =
static_cast<double>(trITS.getSigmaY2()) +
static_cast<double>(trTPC.getSigmaY2());
1353 covMat(1, 0) =
static_cast<double>(trITS.getSigmaSnpY()) +
static_cast<double>(trTPC.getSigmaSnpY());
1354 covMat(1, 1) =
static_cast<double>(trITS.getSigmaSnp2()) +
static_cast<double>(trTPC.getSigmaSnp2());
1355 covMat(2, 0) =
static_cast<double>(trITS.getSigmaTglY()) +
static_cast<double>(trTPC.getSigmaTglY());
1356 covMat(2, 1) =
static_cast<double>(trITS.getSigmaTglSnp()) +
static_cast<double>(trTPC.getSigmaTglSnp());
1357 covMat(2, 2) =
static_cast<double>(trITS.getSigmaTgl2()) +
static_cast<double>(trTPC.getSigmaTgl2());
1358 if (mVDriftCalibOn) {
1360 covMat(2, 2) += addErr * addErr;
1362 covMat(3, 0) =
static_cast<double>(trITS.getSigma1PtY()) +
static_cast<double>(trTPC.getSigma1PtY());
1363 covMat(3, 1) =
static_cast<double>(trITS.getSigma1PtSnp()) +
static_cast<double>(trTPC.getSigma1PtSnp());
1364 covMat(3, 2) =
static_cast<double>(trITS.getSigma1PtTgl()) +
static_cast<double>(trTPC.getSigma1PtTgl());
1365 covMat(3, 3) =
static_cast<double>(trITS.getSigma1Pt2()) +
static_cast<double>(trTPC.getSigma1Pt2());
1366 if (!covMat.Invert()) {
1367 LOG(error) <<
"Cov.matrix inversion failed: " << covMat;
1368 return 2. * o2::track::HugeF;
1370 double chi2diag = 0., chi2ndiag = 0.,
1375 for (
int i = o2::track::kNParams - 1;
i--;) {
1376 chi2diag += diff[
i] * diff[
i] * covMat(
i,
i);
1377 for (
int j =
i;
j--;) {
1378 chi2ndiag += diff[
i] * diff[
j] * covMat(
i,
j);
1381 return chi2diag + 2. * chi2ndiag;
1390 mITSWork.push_back(mITSWork.back());
1391 auto& trc = mITSWork.back();
1395 mITSSectIndexCache[sector].push_back(mITSWork.size() - 1);
1397 mITSWork.back().setCloneBefore();
1399 mITSWork.back().xrho = trackLTInt->getXRho();
1400 mITSWork.back().dL = trackLTInt->getL();
1402 mITSWork[mITSWork.size() - 2].setCloneAfter();
1404 mITSLblWork.emplace_back(mITSTrkLabels[trc.sourceID]);
1407 mITSWork.pop_back();
1416 constexpr float TgHalfSector = 0.17632698f;
1417 bool refReached =
false;
1425 if (fabs(trc.getY()) < mParams->
XMatchingRef * TgHalfSector) {
1429 if (!trialsLeft--) {
1433 if (!trc.rotate(alphaNew) != 0) {
1437 return refReached && std::abs(trc.getSnp()) < MaxSnp;
1444 printf(
"\n******************** TPC-ITS matching component ********************\n");
1446 printf(
"init is not done yet\n");
1450 printf(
"MC truth: %s\n", mMCTruthON ?
"on" :
"off");
1451 printf(
"Matching reference X: %.3f\n", mParams->
XMatchingRef);
1452 printf(
"Account Z dimension: %s\n", mCompareTracksDZ ?
"on" :
"off");
1454 printf(
"Max number ITS candidates per TPC track: %d\n", mParams->
maxMatchCandidates);
1455 printf(
"Crude cut on track params: ");
1456 for (
int i = 0;
i < o2::track::kNParams;
i++) {
1461 printf(
"NSigma^2 cut on track params: ");
1462 for (
int i = 0;
i < o2::track::kNParams;
i++) {
1469#ifdef _ALLOW_DEBUG_TREES_
1471 printf(
"Output debug tree (%s) file: %s\n", mDBGFlags ?
"on" :
"off", mDebugTreeFileName.data());
1473 printf(
"Debug stream flags:\n");
1478 printf(
"* winner matches\n");
1483 printf(
"**********************************************************************\n");
1490 mTimer[SWRefit].Start(
false);
1491 matchedTracks.reserve(mNMatches + mABWinnersIDs.size());
1492 matchedTracks.resize(mNMatches);
1494 matchLabels.reserve(mNMatches + mABWinnersIDs.size());
1495 matchLabels.resize(mNMatches);
1497 if (mVDriftCalibOn) {
1498 calib.reserve(mNCalibPrelim * 1.2 + 1);
1500 std::vector<int> tpcToFit;
1501 tpcToFit.reserve(mNMatches);
1502 for (
int iTPC = 0; iTPC < (int)mTPCWork.size(); iTPC++) {
1503 const auto& tTPC = mTPCWork[iTPC];
1504 if (!isDisabledTPC(tTPC) && tTPC.
gid.testBit(0)) {
1505 tpcToFit.push_back(iTPC);
1508 LOG(
debug) <<
"Refitting winner matches";
1509 mWinnerChi2Refit.resize(mITSWork.size(), -1.f);
1510 int nToFit = (int)tpcToFit.size();
1511 unsigned int nFailedRefit{0};
1514#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) \
1515 reduction(+ : nFailedRefit)
1517 for (
int ifit = 0; ifit < nToFit; ifit++) {
1518 int iTPC = tpcToFit[ifit], iITS;
1519 const auto& tTPC = mTPCWork[iTPC];
1520 if (
refitTrackTPCITS(ifit, iTPC, iITS, matchedTracks, matchLabels, calib)) {
1521 mWinnerChi2Refit[iITS] = matchedTracks.back().getChi2Refit();
1526 LOGP(info,
"Failed {} TPC-ITS refits out of {}", nFailedRefit, nToFit);
1531 for (
int ifit = 0; ifit < nToFit; ifit++) {
1532 int itpc = tpcToFit[ifit];
1533 if (!matchedTracks[ifit].
isValid()) {
1534 while (--last > ifit && !matchedTracks[last].
isValid()) {
1537 matchedTracks[ifit] = matchedTracks[last];
1538 matchedTracks[last].invalidate();
1539 itpc = tpcToFit[last];
1541 matchLabels[ifit] = matchLabels[last];
1547 if (mDBGOut || mVDriftCalibOn) {
1553 matchedTracks.resize(mNMatches);
1555 matchLabels.resize(mNMatches);
1557 mTimer[SWRefit].Stop();
1563 const auto& tTPC = mTPCWork[iTPC];
1564 int iITS = mMatchRecordsTPC[tTPC.
matchID].partnerID;
1565 const auto& tITS = mITSWork[iITS];
1566 float minDiffFT0 = -999.,
timeC = 0.f;
1567 std::vector<float> dtimes;
1569 if (fillVDCalib || mDBGOut) {
1572 if (mInteractions.size()) {
1573 int timeC0 =
timeC - minDiffA;
1577 auto entStart = timeC0 < int(mInteractionMUSLUT.size()) ? mInteractionMUSLUT[timeC0] : (mInteractionMUSLUT.size() ? mInteractionMUSLUT.back() : 0);
1578 for (
int ent = entStart; ent < (int)mInteractions.size(); ent++) {
1579 float diff = mInteractions[ent].tBracket.mean() -
timeC;
1580 if (diff > minDiffA) {
1583 if (diff < -minDiffA) {
1586 dtimes.push_back(diff);
1588 minDiffA = std::abs(minDiffFT0);
1593 calib.emplace_back(tITS.getTgl(), tTPC.getTgl(), minDiffFT0);
1595#ifdef _ALLOW_DEBUG_TREES_
1599 itsRefPIDCorr.setX(0);
1600 if (tTPC.getPID() > tITS.getPID() && tITS.
dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1601 itsRefAltPID = mITSTracksArray[tITS.
sourceID].getParamOut();
1602 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1603 itsRefPIDCorr = itsRefAltPID;
1605 if (!itsRefPIDCorr.correctForELoss(tITS.
xrho)) {
1606 itsRefPIDCorr.setX(-10);
1608 float q2ptPID = itsRefPIDCorr.getQ2Pt();
1609 float dCurv = (q2ptPID - tITS.getQ2Pt()) * mBz * o2::constants::math::B2C, dLEff = tITS.
dL * mParams->
ITSStepEffFraction, dCurvL = dCurv * dLEff;
1610 itsRefPIDCorr = tITS;
1611 itsRefPIDCorr.setPID(tTPC.getPID(),
true);
1612 itsRefPIDCorr.setQ2Pt(q2ptPID);
1613 auto snp = tITS.getSnp() + dCurvL;
1614 if (std::abs(snp) >= 1.) {
1615 snp = std::copysign(0.99, snp);
1617 itsRefPIDCorr.setSnp(snp);
1618 itsRefPIDCorr.setY(tITS.getY() + dCurvL * dLEff * 0.5);
1622 itsRefAltPID.setX(-10);
1625 int tb = mTPCTracksArray[tTPC.
sourceID].getTime0() * mNTPCOccBinLengthInv;
1626 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
1627 (*mDBGOut) <<
"refit"
1628 <<
"tpcOrig=" << mTPCTracksArray[tTPC.
sourceID] <<
"itsOrig=" << mITSTracksArray[tITS.
sourceID] <<
"itsRef=" << tITS <<
"tpcRef=" << tTPC <<
"matchRefit=" <<
match
1629 <<
"timeCorr=" <<
timeC <<
"dTimeFT0=" << minDiffFT0 <<
"dTimes=" << dtimes
1630 <<
"itsRefAltPID=" << itsRefAltPID <<
"itsRefPIDCorr=" << itsRefPIDCorr;
1632 (*mDBGOut) <<
"refit"
1633 <<
"itsLbl=" << mITSLblWork[iITS] <<
"tpcLbl=" << mTPCLblWork[iTPC];
1635 (*mDBGOut) <<
"refit"
1636 <<
"multTPC=" << mltTPC
1637 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
1638 <<
"multITSCl=" << mNITSClusters
1639 <<
"tf=" << mTFCount <<
"\n";
1649 const float maxStep = 2.f;
1650 const auto& tTPC = mTPCWork[iTPC];
1651 const auto& tpcMatchRec = mMatchRecordsTPC[tTPC.
matchID];
1652 iITS = tpcMatchRec.partnerID;
1653 const auto& tITS = mITSWork[iITS];
1654 const auto& itsTrOrig = mITSTracksArray[tITS.
sourceID];
1655 auto& trfit = matchedTracks[slot];
1658 trfit.getParamOut().setUserField(0);
1659 trfit.setPID(tTPC.getPID(),
true);
1660 trfit.getParamOut().setPID(tTPC.getPID(),
true);
1663 if (!mCompareTracksDZ) {
1664 trfit.setZ(tITS.getZ());
1666 float deltaT = (trfit.getZ() - tTPC.getZ()) * mTPCVDriftInv;
1670 timeErr = itsTimeRes;
1693 int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters();
1697 int clEntry = itsTrOrig.getFirstClusterEntry();
1701 if (mVDriftCalibOn) {
1707 for (
int icl = 0; icl < ncl; icl++) {
1708 const auto& clus = getITSCluster(mITSTrackClusIdx[clEntry++]);
1709 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1710 if (!trfit.rotate(
alpha) ||
1714 !propagator->propagateToX(trfit,
x, propagator->getNominalBz(),
1715 MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) {
1718 chi2 += trfit.getPredictedChi2(clus);
1719 if (!trfit.update(clus)) {
1724 if (nclRefit != ncl) {
1725 LOGP(
debug,
"Refit in ITS failed after ncl={}, match between TPC track #{} and ITS track #{}", nclRefit, tTPC.
sourceID, tITS.
sourceID);
1726 LOGP(
debug,
"{:s}", trfit.asString());
1736 if (!propagator->propagateToDCA(vtxDummy.getXYZ(), trpar, propagator->getNominalBz(),
1737 maxStep, MatCorrType::USEMatCorrNONE,
nullptr, &trfit.getLTIntegralOut())) {
1738 LOG(error) <<
"LTOF integral might be incorrect";
1740 auto& tofL = trfit.getLTIntegralOut();
1741 tofL.setX2X0(-tofL.getX2X0());
1742 tofL.setXRho(-tofL.getXRho());
1745 auto& tracOut = trfit.getParamOut();
1746 if (tTPC.getPID() > tITS.getPID() && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->
minBetaGammaForPIDDiff) {
1748 tracOut = mITSTracksArray[tITS.
sourceID].getParamOut();
1749 tracOut.setPID(tTPC.getPID(),
true);
1751 LOGP(
debug,
"Failed to rotate ITSouter with imposed PID to TPC alpha {} or propagate to X={}: {:s}", tTPC.getAlpha(), mParams->
XMatchingRef, tracOut.asString());
1759 !propagator->PropagateToXBxByBz(tracOut, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1760 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1764 if (mVDriftCalibOn) {
1768 auto posStart = tracOut.getXYZGlo();
1769 auto tImposed =
timeC * mTPCTBinMUSInv;
1770 if (std::abs(tImposed - mTPCTracksArray[tTPC.
sourceID].getTime0()) > 550) {
1771 LOGP(alarm,
"Impossible imposed timebin {} for TPC track time0:{}, dBwd:{} dFwd:{} TB | ZShift:{}, TShift:{}", tImposed, mTPCTracksArray[tTPC.
sourceID].getTime0(),
1772 mTPCTracksArray[tTPC.
sourceID].getDeltaTBwd(), mTPCTracksArray[tTPC.
sourceID].getDeltaTFwd(), trfit.getZ() - tTPC.getZ(), deltaT);
1773 LOGP(info,
"Trc: {}", mTPCTracksArray[tTPC.
sourceID].asString());
1777 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(), tImposed, &chi2Out,
true,
false);
1783 auto posEnd = tracOut.getXYZGlo();
1784 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1785 tofL.addStep(lInt, tracOut.getQ2P2());
1786 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1790 if (trackTune.useTPCOuterCorr) {
1791 tracOut.updateParams(trackTune.tpcParOuter);
1797 trfit.setChi2Match(tpcMatchRec.chi2);
1798 trfit.setChi2Refit(
chi2);
1799 trfit.setTimeMUS(
timeC, timeErr);
1804 matchLabels[slot] = mTPCLblWork[iTPC];
1805 matchLabels[slot].setFakeFlag(mITSLblWork[iITS] != mTPCLblWork[iTPC]);
1816 const float maxStep = 2.f;
1817 const auto& tTPC = mTPCWork[seed.tpcWID];
1818 const auto& winLink = seed.getLink(seed.winLinkID);
1819 auto& newtr = matchedTracks.emplace_back(winLink, winLink);
1820 auto& tracOut = newtr.getParamOut();
1821 auto& tofL = newtr.getLTIntegralOut();
1824 tracOut.resetCovariance();
1826 propagator->estimateLTFast(tofL, winLink);
1828 const auto& itsClRefs = ABTrackletRefs[iITSAB];
1829 int nclRefit = 0, ncl = itsClRefs.getNClusters();
1832 for (
int icl = itsClRefs.getFirstEntry(); icl < itsClRefs.getEntriesBound(); icl++) {
1833 const auto& clus = getITSCluster(ABTrackletClusterIDs[icl]);
1834 float alpha = geom->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
1835 if (!tracOut.rotate(
alpha, refLin, propagator->getNominalBz()) ||
1839 !propagator->propagateToX(tracOut, refLin,
x, propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, &tofL)) {
1842 chi2 += tracOut.getPredictedChi2(clus);
1843 if (!tracOut.update(clus)) {
1848 if (nclRefit != ncl) {
1849 LOGP(
debug,
"AfterBurner refit in ITS failed after ncl={}, match between TPC track #{} and ITS tracklet #{}", nclRefit, tTPC.
sourceID, iITSAB);
1850 LOGP(
debug,
"{:s}", tracOut.asString());
1851 matchedTracks.pop_back();
1855 float timeC = mInteractions[seed.ICCanID].tBracket.mean();
1856 float timeErr = mInteractions[seed.ICCanID].tBracket.delta();
1860 !propagator->PropagateToXBxByBz(tracOut, refLin, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) {
1861 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed, Xtr=" << tracOut.getX() <<
" snp=" << tracOut.getSnp();
1862 matchedTracks.pop_back();
1866 auto posStart = tracOut.getXYZGlo();
1867 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, mTPCTracksArray[tTPC.
sourceID].getClusterRef(),
timeC * mTPCTBinMUSInv, &chi2Out,
true,
false);
1870 matchedTracks.pop_back();
1873 auto posEnd = tracOut.getXYZGlo();
1874 auto lInt = propagator->estimateLTIncrement(tracOut, posStart, posEnd);
1875 tofL.addStep(lInt, tracOut.getQ2P2());
1876 tofL.addX2X0(lInt * mTPCmeanX0Inv);
1879 if (trackTune.useTPCOuterCorr) {
1880 tracOut.updateParams(trackTune.tpcParOuter);
1887 newtr.setChi2Match(winLink.chi2Norm());
1888 newtr.setChi2Refit(
chi2);
1889 newtr.setTimeMUS(
timeC, timeErr);
1900 const auto& tpcTrOrig = mTPCTracksArray[trcID];
1902 trcIn = tpcTrOrig.getOuterParam();
1906 int retVal = mTPCRefitter->RefitTrackAsTrackParCov(trcIn, tpcTrOrig.getClusterRef(), timeTB, &
chi2,
false,
true);
1908 LOG(warning) <<
"Refit failed";
1909 LOG(warning) << trcIn.asString();
1915 if (!propagator->PropagateToXBxByBz(trcIn, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1916 LOG(
debug) <<
"Propagation to target X=" << xTgt <<
" failed, Xtr=" << trcIn.getX() <<
" snp=" << trcIn.getSnp() <<
" pT=" << trcIn.getPt();
1925int MatchTPCITS::prepareABSeeds()
1928 const auto& outerLr = mRGHelper.
layers.back();
1930 const float ROuter = outerLr.rRange.getMax() + 0.5f;
1933 for (
int iTPC = 0; iTPC < (
int)mTPCWork.size(); iTPC++) {
1934 auto& tTPC = mTPCWork[iTPC];
1935 if (isDisabledTPC(tTPC)) {
1941 !propagator->PropagateToXBxByBz(tTPC, xTgt, MaxSnp, 2., mUseMatCorrFlag)) {
1944 mTPCABIndexCache.push_back(iTPC);
1948 std::sort(mTPCABIndexCache.begin(), mTPCABIndexCache.end(), [
this](
int a,
int b) {
1949 auto& trcA = mTPCWork[a];
1950 auto& trcB = mTPCWork[b];
1951 return (trcA.tBracket.getMin() - trcB.tBracket.getMin()) < 0.;
1954 float maxTDriftSafe = tpcTimeBin2MUS(mNTPCBinsFullDrift + mParams->
safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin);
1955 int nIntCand = mInteractions.size(), nTPCCand = mTPCABIndexCache.size();
1957 for (
int ic = 0; ic < nIntCand; ic++) {
1958 int icFirstSeed = mTPCABSeeds.size();
1959 auto& intCand = mInteractions[ic];
1960 auto tic = intCand.tBracket.mean();
1961 for (
int it = tpcStart; it < nTPCCand; it++) {
1962 auto& trc = mTPCWork[mTPCABIndexCache[it]];
1963 auto cmp = trc.tBracket.isOutside(intCand.tBracket);
1968 if (trc.tBracket.getMin() + maxTDriftSafe < intCand.tBracket.getMin()) {
1974 float dt = trc.getSignedDT(tic - trc.time0);
1975 float dz = dt * mTPCVDrift,
z = trc.getZ() + dz;
1976 if (outerLr.zRange.isOutside(
z, std::sqrt(trc.getSigmaZ2()) + 2.)) {
1980 auto&
seed = mTPCABSeeds.emplace_back(mTPCABIndexCache[it], ic, trc);
1983 intCand.seedsRef.set(icFirstSeed, mTPCABSeeds.size() - icFirstSeed);
1985 return mTPCABIndexCache.size();
1989int MatchTPCITS::prepareInteractionTimes()
1994 const float ft0Uncertainty = 0.5e-3;
1995 const auto& clockROFTimes = mABLayerClusters[mITSClockLayer].rofTimes;
1996 int nClockROFs = clockROFTimes.size();
1998 std::array<int, NITSLayers> ptrLr{};
1999 if (mFITInfo.size() && nClockROFs) {
2001 for (
const auto& ft : mFITInfo) {
2005 auto fitTime = ft.getInteractionRecord().differenceInBCMUS(mStartIR);
2009 while (rof < nClockROFs && clockROFTimes[rof].getMax() + mABROFMarginMUS < fitTime) {
2012 if (rof >= nClockROFs) {
2015 if (
size_t(fitTime) >= mInteractionMUSLUT.size()) {
2016 mInteractionMUSLUT.resize(
size_t(fitTime) + 1, -1);
2018 if (mInteractionMUSLUT[fitTime] < 0) {
2019 mInteractionMUSLUT[fitTime] = mInteractions.size();
2021 auto& intCand = mInteractions.emplace_back(ft.getInteractionRecord(), fitTime, ft0Uncertainty, rof, o2::detectors::DetID::FT0);
2022 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2023 const auto& rofTimes = mABLayerClusters[lr].rofTimes;
2024 int nROFsLr = (
int)rofTimes.size();
2025 int&
ptr = ptrLr[lr];
2026 while (
ptr < nROFsLr && rofTimes[
ptr].getMax() + mABROFMarginMUS < fitTime) {
2029 if (ptr < nROFsLr && fitTime >= rofTimes[
ptr].getMin() - mABROFMarginMUS) {
2030 intCand.rofLr[lr] =
ptr;
2031 if (
ptr + 1 < nROFsLr && fitTime >= rofTimes[
ptr + 1].getMin() - mABROFMarginMUS) {
2032 intCand.rofNextLr |= 0x1 << lr;
2039 for (
auto&
val : mInteractionMUSLUT) {
2046 return mInteractions.size();
2050void MatchTPCITS::prepareABClusters()
2056 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2057 auto& abClus = mABLayerClusters[lr];
2058 abClus.needROF.assign(abClus.rofTimes.size(), 0);
2059 abClus.rofRefs.assign(abClus.rofTimes.size(),
ClusRange(-1, 0));
2061 for (
const auto& intCand : mInteractions) {
2062 if (!intCand.seedsRef.getEntries()) {
2065 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2066 int rof = intCand.rofLr[lr];
2070 auto& need = mABLayerClusters[lr].needROF;
2072 if ((intCand.rofNextLr >> lr) & 0x1) {
2078 int lr = 0, rof = 0,
nCl = 0, offs = 0;
2080 std::vector<ABBlock> blocks;
2081 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2082 const auto& need = mABLayerClusters[lr].needROF;
2083 for (
int rof = 0; rof < (
int)need.size(); rof++) {
2085 blocks.push_back({lr, rof});
2089 if (blocks.empty()) {
2092 int nBlocks = blocks.size();
2095#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
2097 for (
int ib = 0; ib < nBlocks; ib++) {
2098 auto& blk = blocks[ib];
2099 int slot = perLayer ? blk.lr : 0;
2100 const auto& rofRec = mITSClusterROFRec[slot][blk.rof];
2101 const auto& status = mABClusterStatus[slot];
2102 int last = rofRec.getFirstEntry() + rofRec.getNEntries(),
nCl = 0;
2104 for (
int icl = rofRec.getFirstEntry(); icl <
last; icl++) {
2110 const auto& clusArr = mITSClustersArray[0];
2111 int chipMin = mABChipsBounds[blk.lr], chipMax = mABChipsBounds[blk.lr + 1];
2112 for (
int icl = rofRec.getFirstEntry(); icl <
last; icl++) {
2113 int chip = clusArr[icl].getSensorID();
2114 if (chip >= chipMin && chip < chipMax && status[icl] !=
MinusTen) {
2122 std::array<int, NITSLayers> layerSizes{};
2123 for (
auto& blk : blocks) {
2124 blk.offs = layerSizes[blk.lr];
2125 layerSizes[blk.lr] += blk.nCl;
2127 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2128 mABLayerClusters[lr].clus.resize(layerSizes[lr]);
2132#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
2134 for (
int ib = 0; ib < nBlocks; ib++) {
2135 const auto& blk = blocks[ib];
2136 auto& abClus = mABLayerClusters[blk.lr];
2137 int slot = perLayer ? blk.lr : 0;
2138 const auto& rofRec = mITSClusterROFRec[slot][blk.rof];
2139 const auto& status = mABClusterStatus[slot];
2140 const auto& clusArr = mITSClustersArray[slot];
2141 int last = rofRec.getFirstEntry() + rofRec.getNEntries();
2142 int chipMin = mABChipsBounds[blk.lr], chipMax = mABChipsBounds[blk.lr + 1];
2145 for (
int icl = rofRec.getFirstEntry(); icl <
last; icl++) {
2146 const auto& cls = clusArr[icl];
2147 int chip = cls.getSensorID();
2148 if ((perLayer || (chip >= chipMin && chip < chipMax)) && status[icl] !=
MinusTen) {
2149 assert(chip >= chipMin && chip < chipMax);
2153 assert(nCl == blk.nCl);
2155 abClus.rofRefs[blk.rof].set(blk.offs, nCl);
2160void MatchTPCITS::updateABLayerView(
ABLayerView& view,
int lr,
int rof,
int nROFs)
const
2167 for (
int chip : view.touchedChips) {
2173 view.
data =
nullptr;
2178 const auto& abClus = mABLayerClusters[lr];
2179 const auto& ref0 = abClus.rofRefs[rof];
2180 assert(ref0.getFirstEntry() >= 0);
2182 view.
data = abClus.clus.data() + ref0.getFirstEntry();
2183 view.
nData = ref0.getEntries();
2185 const auto& ref1 = abClus.rofRefs[rof + 1];
2186 assert(ref1.getFirstEntry() >= 0);
2187 view.
merged.resize(ref0.getEntries() + ref1.getEntries());
2188 std::merge(abClus.clus.begin() + ref0.getFirstEntry(), abClus.clus.begin() + ref0.getEntriesBound(),
2189 abClus.clus.begin() + ref1.getFirstEntry(), abClus.clus.begin() + ref1.getEntriesBound(),
2195 while (icl < view.
nData) {
2196 int chip = view.
data[icl].
chip, jcl = icl + 1;
2200 int chipLoc = chip - view.
chipOffs;
2201 view.
chipRefs[chipLoc].set(icl, jcl - icl);
2211 mTimer[SWABSeeds].Start(
false);
2214 int nIntCand = mInteractions.size(), nABSeeds = mTPCABSeeds.size();
2215 LOGP(info,
"AfterBurner will check {} seeds from {} TPC tracks and {} interaction candidates with {} threads", nABSeeds, mTPCABIndexCache.size(), nIntCand, mNThreads);
2216 mTimer[SWABSeeds].Stop();
2217 if (!nIntCand || !mTPCABSeeds.size()) {
2220 mTimer[SWABMatch].Start(
false);
2221 prepareABClusters();
2226 std::vector<int> seededIC;
2227 std::vector<std::pair<int, int>> icGroups;
2228 seededIC.reserve(nIntCand);
2229 for (
int ic = 0; ic < nIntCand; ic++) {
2230 const auto& intCand = mInteractions[ic];
2231 if (!intCand.seedsRef.getEntries()) {
2234 bool anyROF =
false;
2235 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2236 if (intCand.rofLr[lr] >= 0) {
2242 for (
int is = intCand.seedsRef.getFirstEntry(); is < intCand.seedsRef.getEntriesBound(); is++) {
2243 mTPCABSeeds[is].disable();
2247 bool sameROFs =
false;
2248 if (!seededIC.empty()) {
2249 const auto& prevCand = mInteractions[seededIC.back()];
2250 sameROFs = prevCand.rofNextLr == intCand.rofNextLr;
2251 for (
int lr = lowestAB; sameROFs && lr <
NITSLayers; lr++) {
2252 sameROFs = prevCand.rofLr[lr] == intCand.rofLr[lr];
2256 icGroups.back().second = (int)seededIC.size();
2258 icGroups.emplace_back((
int)seededIC.size(), (int)seededIC.size());
2260 seededIC.push_back(ic);
2263 std::vector<ABThreadClusterViews> itsClViewsBuff(mNThreads);
2264 for (
auto& views : itsClViewsBuff) {
2265 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2266 auto& view = views.layers[lr];
2267 view.
chipOffs = mABChipsBounds[lr];
2268 view.
chipRefs.resize(mABChipsBounds[lr + 1] - mABChipsBounds[lr],
ClusRange(0, 0));
2273#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
2275 for (
int ig = 0; ig < (int)icGroups.size(); ig++) {
2277 uint8_t tid = (uint8_t)omp_get_thread_num();
2281 auto& views = itsClViewsBuff[tid];
2282 const auto& groupCand = mInteractions[seededIC[icGroups[ig].first]];
2283 for (
int lr = lowestAB; lr <
NITSLayers; lr++) {
2284 updateABLayerView(views.layers[lr], lr, groupCand.rofLr[lr], (groupCand.rofNextLr >> lr) & 0x1 ? 2 : 1);
2286 for (
int j = icGroups[ig].
first;
j <= icGroups[ig].second;
j++) {
2287 const auto& intCand = mInteractions[seededIC[
j]];
2288 LOGP(
debug,
"cand T {} Entries: {} : {} : {} | ITS clock ROF: {}", intCand.tBracket.mean(), intCand.seedsRef.getEntries(), intCand.seedsRef.getFirstEntry(), intCand.seedsRef.getEntriesBound(), intCand.rofITS);
2289 for (
int is = intCand.seedsRef.getFirstEntry(); is < intCand.seedsRef.getEntriesBound(); is++) {
2290 processABSeed(is, views, tid);
2294 mTimer[SWABMatch].Stop();
2295 mTimer[SWABWinners].Start(
false);
2302 std::vector<SID> candAB;
2303 candAB.reserve(nABSeeds);
2304 mABWinnersIDs.reserve(mTPCABIndexCache.size());
2306 for (
int i = 0;
i < nABSeeds;
i++) {
2307 auto& ABSeed = mTPCABSeeds[
i];
2308 if (ABSeed.isDisabled()) {
2311 candAB.emplace_back(SID{
i, ABSeed.getLink(ABSeed.getBestLinkID()).chi2Norm()});
2313 std::sort(candAB.begin(), candAB.end(), [](SID
a, SID
b) { return a.chi2 < b.chi2; });
2314 for (
int i = 0;
i < (int)candAB.size();
i++) {
2315 auto& ABSeed = mTPCABSeeds[candAB[
i].seedID];
2316 if (ABSeed.isDisabled()) {
2320 auto& tTPC = mTPCWork[ABSeed.tpcWID];
2326 auto bestID = ABSeed.getBestLinkID();
2327 if (ABSeed.checkLinkHasUsedClusters(bestID, mABClusterStatus)) {
2328 ABSeed.setNeedAlternative();
2332 ABSeed.validate(bestID);
2333 ABSeed.flagLinkUsedClusters(bestID, mABClusterStatus);
2334 mABWinnersIDs.push_back(tTPC.
matchID = candAB[
i].seedID);
2335 mNABRefsClus += ABSeed.getNLayers();
2339 mTimer[SWABWinners].Stop();
2340 mTimer[SWABRefit].Start(
false);
2341 refitABWinners(matchedTracks, matchLabels, ABTrackletLabels, ABTrackletClusterIDs, ABTrackletRefs, calib);
2342 mTimer[SWABRefit].Stop();
2353 ABTrackletClusterIDs.reserve(mNABRefsClus);
2354 ABTrackletRefs.reserve(mABWinnersIDs.size());
2356 ABTrackletLabels.reserve(mABWinnersIDs.size());
2358 if (matchedTracks.capacity() < mABWinnersIDs.size() + matchedTracks.size()) {
2359 LOGP(warn,
"need to expand matched tracks container from {} to {}", matchedTracks.capacity(), mABWinnersIDs.size() + matchedTracks.size());
2360 matchedTracks.reserve(mABWinnersIDs.size() + matchedTracks.size());
2362 matchLabels.reserve(mABWinnersIDs.size() + matchedTracks.size());
2366 std::map<o2::MCCompLabel, int> labelOccurence;
2367 auto accountClusterLabel = [&labelOccurence,
this](
int clID) {
2369 for (
auto lab :
labels) {
2371 labelOccurence[lab]++;
2376 for (
auto wid : mABWinnersIDs) {
2377 const auto& ABSeed = mTPCABSeeds[wid];
2378 int start = ABTrackletClusterIDs.size();
2379 int lID = ABSeed.winLinkID, ncl = 0;
2380 auto& clref = ABTrackletRefs.emplace_back(
start, ncl);
2382 const auto& winL = ABSeed.getLink(lID);
2384 ABTrackletClusterIDs.push_back(winL.clID);
2386 clref.pattern |= 0x1 << winL.layerID;
2389 accountClusterLabel(winL.clID);
2392 lID = winL.parentID;
2394 clref.setEntries(ncl);
2395 if (!
refitABTrack(ABTrackletRefs.size() - 1, ABSeed, matchedTracks, ABTrackletClusterIDs, ABTrackletRefs)) {
2396 ABTrackletRefs.pop_back();
2397 ABTrackletClusterIDs.resize(
start);
2399 labelOccurence.clear();
2415 labelOccurence.clear();
2416 ABTrackletLabels.push_back(lab);
2417 auto& lblGlo = matchLabels.emplace_back(mTPCLblWork[ABSeed.tpcWID]);
2418 lblGlo.setFakeFlag(lab != lblGlo);
2419 LOG(
debug) <<
"ABWinner ncl=" << ncl <<
" mcLBAB " << lab <<
" mcLBGlo " << lblGlo <<
" chi2=" << ABSeed.getLink(ABSeed.winLinkID).chi2Norm() <<
" pT = " << ABSeed.track.getPt();
2423 LOG(info) <<
"AfterBurner validated " << ABTrackletRefs.size() <<
" tracks";
2430 auto& ABSeed = mTPCABSeeds[sid];
2431 ABSeed.threadID = tID;
2432 ABSeed.linksEntry = mABLinksPool.
threadPool[tID].size();
2435 int nextLinkID = ABSeed.firstInLr[ilr];
2436 if (nextLinkID < 0) {
2440 const auto& seedLink = ABSeed.getLink(nextLinkID);
2441 if (seedLink.isDisabled()) {
2442 nextLinkID = seedLink.nextOnLr;
2445 int next2nextLinkID = seedLink.nextOnLr;
2446 followABSeed(seedLink, itsClViews.
layers[ilr - 1], nextLinkID, ilr - 1, ABSeed);
2447 nextLinkID = next2nextLinkID;
2451 auto candID = ABSeed.getBestLinkID();
2452 if (ABSeed.isDisabled() ||
2457 mABLinksPool.
threadPool[tID].resize(
size_t(ABSeed.linksEntry));
2475 if (!clView.
nData) {
2480 const auto& lr = mRGHelper.
layers[lrID];
2482 if (!seedC.getXatLabR(lr.rRange.getMax(), xTgt, propagator->getNominalBz(),
o2::track::DirInward) ||
2483 !propagator->propagateToX(seedC, xTgt, propagator->getNominalBz(), MaxSnp, 2., mUseMatCorrFlag)) {
2487 float zDRStep = -seedC.getTgl() * lr.rRange.delta();
2488 float errZ = std::sqrt(seedC.getSigmaZ2() + mParams->
err2ABExtraZ);
2489 if (lr.zRange.isOutside(seedC.getZ(), mParams->
nABSigmaZ * errZ + std::abs(zDRStep))) {
2492 std::vector<int> chipSelClusters;
2499 seedC.getCircleParams(propagator->getNominalBz(), trcCircle, sna, csa);
2501 seedC.getLineParams(trcLinPar, sna, csa);
2505 float phi = std::atan2(yCurr, xCurr);
2507 int nLad2Check = 0, ladIDguess = lr.getLadderID(phi), chipIDguess = lr.getChipID(seedC.getZ() + 0.5 * zDRStep);
2508 std::array<int, MaxLadderCand> lad2Check;
2509 nLad2Check = mFieldON ? findLaddersToCheckBOn(lrID, ladIDguess, trcCircle, errYFrac, lad2Check) : findLaddersToCheckBOff(lrID, ladIDguess, trcLinPar, errYFrac, lad2Check);
2511 for (
int ilad = nLad2Check; ilad--;) {
2512 int ladID = lad2Check[ilad];
2513 const auto& lad = lr.ladders[ladID];
2517 float t = 1e9, xCross, yCross;
2518 const auto& chipC = lad.chips[chipIDguess];
2520 chipC.xyEdges.circleCrossParam(trcCircle, t);
2522 chipC.xyEdges.lineCrossParam(trcLinPar, t);
2524 chipC.xyEdges.eval(t, xCross, yCross);
2525 float dx = xCross - xCurr, dy = yCross - yCurr, dst2 = dx * dx + dy * dy,
dst = sqrtf(dst2);
2527 float zCross = seedC.getZ() + seedC.getTgl() * (dst2 < 2 * (dx * xCurr + dy * yCurr) ?
dst : -
dst);
2529 for (
int ich = -1; ich < 2; ich++) {
2530 int chipID = chipIDguess + ich;
2532 if (chipID < 0 || chipID >=
static_cast<int>(lad.chips.size())) {
2535 if (lad.chips[chipID].zRange.isOutside(zCross, mParams->
nABSigmaZ * errZ)) {
2538 const auto& clRange = clView.
chipRefs[lad.chips[chipID].id - clView.
chipOffs];
2539 if (!clRange.getEntries()) {
2540 LOG(
debug) <<
"No clusters in chip range";
2544 float errYcalp = errY * (csa * chipC.csAlp + sna * chipC.snAlp);
2546 float yTrack = -xCross * chipC.snAlp + yCross * chipC.csAlp;
2547 if (!preselectChipClusters(chipSelClusters, clRange, clView, yTrack, zCross, tolerY, tolerZ)) {
2548 LOG(
debug) <<
"No compatible clusters found";
2553 if (!trcLC.rotate(chipC.alp) || !trcLC.propagateTo(chipC.xRef, propagator->getNominalBz())) {
2554 LOG(
debug) <<
" failed to rotate to alpha=" << chipC.alp <<
" or prop to X=" << chipC.xRef;
2559 for (
auto clID : chipSelClusters) {
2560 const auto& cls = getITSCluster(clID);
2561 auto chi2 = trcLC.getPredictedChi2(cls);
2565 int lnkID = registerABTrackLink(ABSeed, trcLC, clID, seedID, lrID, ladID,
chi2);
2583void MatchTPCITS::accountForOverlapsAB(
int lrSeed)
2586 LOG(warning) <<
"TODO";
2591 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2595 const auto& lr = mRGHelper.
layers[ilr];
2596 int nacc = 0, jmp = 0;
2597 if (lr.ladders[lad0].xyEdges.seenByCircle(circle, errYFrac)) {
2598 lad2Check[nacc++] = lad0;
2600 bool doUp =
true, doDn =
true;
2603 int ldID = (lad0 + jmp) % lr.nLadders;
2604 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2605 lad2Check[nacc++] = ldID;
2611 int ldID = lad0 - jmp;
2613 ldID += lr.nLadders;
2615 if (lr.ladders[ldID].xyEdges.seenByCircle(circle, errYFrac)) {
2616 lad2Check[nacc++] = ldID;
2627 std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check)
const
2631 const auto& lr = mRGHelper.
layers[ilr];
2632 int nacc = 0, jmp = 0;
2633 if (lr.ladders[lad0].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2634 lad2Check[nacc++] = lad0;
2636 bool doUp =
true, doDn =
true;
2639 int ldID = (lad0 + jmp) % lr.nLadders;
2640 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2641 lad2Check[nacc++] = ldID;
2647 int ldID = lad0 - jmp;
2649 ldID += lr.nLadders;
2651 if (lr.ladders[ldID].xyEdges.seenByLine(trcLinPar, errYFrac)) {
2652 lad2Check[nacc++] = ldID;
2679 auto& nextLink = ABSeed.
getLink(nextID);
2681 bool newIsBetter = parentID <=
MinusOne ? isBetter(
chi2, nextLink.chi2) : isBetter(ABSeed.getLink(parentID).chi2NormPredict(chi2Cl), nextLink.chi2Norm());
2683 if (count < mParams->maxABLinksOnLayer) {
2684 ABSeed.
addLink(trc, clID, parentID, nextID, lr, nc, laddID,
chi2);
2697 nextID = nextLink.nextOnLr;
2700 if (count < mParams->maxABLinksOnLayer) {
2720 auto tpcTrOrig = mTPCTracksArray[tTPC.
sourceID];
2743 float dDrift = (timeIC - tTPC.
time0) * mTPCBin2Z;
2765 LOG(fatal) <<
"ITS Alpide parameters pointer is null";
2768 constexpr float BCLenMUS = o2::constants::lhc::LHCBunchSpacingMUS;
2769 unsigned int maxNROFsPerOrbit = 0;
2772 if (mITSTriggered) {
2773 mITSROFrameLengthMUS[lr] = p->roFrameLengthTrig * 1e-3;
2774 mITSROFrameLengthInBC[lr] = std::max(1,
int(mITSROFrameLengthMUS[lr] / BCLenMUS));
2776 mITSROFrameLengthInBC[lr] = p->getROFLengthInBC(lr);
2777 mITSROFrameLengthMUS[lr] = mITSROFrameLengthInBC[lr] * BCLenMUS;
2779 mITSROFrameLengthMUSInv[lr] = 1.f / mITSROFrameLengthMUS[lr];
2780 mITSTimeResMUS[lr] = mITSROFrameLengthMUS[lr] / std::sqrt(12.f);
2781 mITSTimeBiasInBC[lr] = p->getROFBiasInBC(lr);
2782 mITSTimeBiasMUS[lr] = mITSTimeBiasInBC[lr] * BCLenMUS;
2786 unsigned int nROFsPerOrbit = o2::constants::lhc::LHCMaxBunches / mITSROFrameLengthInBC[lr];
2787 if (nROFsPerOrbit > maxNROFsPerOrbit) {
2788 maxNROFsPerOrbit = nROFsPerOrbit;
2789 mITSClockLayer = lr;
2794 rep += fmt::format(
" L{}:{}/{}", lr, mITSROFrameLengthInBC[lr], mITSTimeBiasInBC[lr]);
2796 LOGP(info,
"ITS {} readout, per-layer ROFLength/Bias in BC:{} | clock layer {}",
2797 mITSTriggered ?
"triggered" :
"continuous", rep, mITSClockLayer);
2806 if (minBC < 0 && mUseBCFilling) {
2807 if (mUseBCFilling) {
2808 mUseBCFilling =
false;
2809 LOG(warning) <<
"Disabling match validation by BunchFilling as no interacting bunches found";
2813 int bcAbove = minBC;
2814 for (
int i = o2::constants::lhc::LHCMaxBunches;
i--;) {
2818 mClosestBunchAbove[
i] = bcAbove;
2820 int bcBelow = maxBC;
2821 for (
int i = 0;
i < o2::constants::lhc::LHCMaxBunches;
i++) {
2825 mClosestBunchBelow[
i] = bcBelow;
2834 if (tbrange.
getMin() > 0) {
2839 int bc = mClosestBunchAbove[irMin.bc];
2840 if (
bc < irMin.bc) {
2844 bc = mClosestBunchBelow[irMax.bc];
2845 if (
bc > irMax.bc) {
2846 if (irMax.orbit == 0) {
2853 return {irMin, irMax};
2857void MatchTPCITS::removeTPCfromITS(
int tpcID,
int itsID)
2860 auto& tITS = mITSWork[itsID];
2861 if (isValidatedITS(tITS)) {
2866 auto& rcITS = mMatchRecordsITS[next];
2867 if (rcITS.partnerID == tpcID) {
2869 tITS.
matchID = rcITS.nextRecID;
2871 mMatchRecordsITS[topID].nextRecID = rcITS.nextRecID;
2876 next = rcITS.nextRecID;
2881void MatchTPCITS::removeITSfromTPC(
int itsID,
int tpcID)
2884 auto& tTPC = mTPCWork[tpcID];
2885 if (isValidatedTPC(tTPC)) {
2890 auto& rcTPC = mMatchRecordsTPC[next];
2891 if (rcTPC.partnerID == itsID) {
2893 tTPC.
matchID = rcTPC.nextRecID;
2895 mMatchRecordsTPC[topID].nextRecID = rcTPC.nextRecID;
2900 next = rcTPC.nextRecID;
2908 int clEntry =
track.getFirstClusterEntry();
2909 for (
int icl =
track.getNumberOfClusters(); icl--;) {
2910 const int clID = mITSTrackClusIdx[clEntry++];
2912 if (!clStatus.empty()) {
2919int MatchTPCITS::preselectChipClusters(std::vector<int>& clVecOut,
const ClusRange& clRange,
const ABLayerView& clView,
2920 float trackY,
float trackZ,
float tolerY,
float tolerZ)
const
2923 int icID = clRange.getFirstEntry();
2924 for (
int icl = clRange.getEntries(); icl--;) {
2925 const auto& cls = clView.
data[icID++];
2926 float dz = cls.
z - trackZ;
2927 LOG(
debug) <<
"cl" << icl <<
'/' << cls.id <<
" "
2928 <<
" dZ: " << dz <<
" [" << tolerZ <<
"| dY: " << trackY - cls.y <<
" [" << tolerY <<
"]";
2930 LOG(
debug) <<
"Skip the rest since " << trackZ <<
" < " << cls.z <<
"\n";
2932 }
else if (dz < -tolerZ) {
2933 LOG(
debug) <<
"Skip cluster dz=" << dz <<
" Ztr=" << trackZ <<
" zCl=" << cls.z;
2936 if (fabs(trackY - cls.y) > tolerY) {
2937 LOG(
debug) <<
"Skip cluster dy= " << trackY - cls.y <<
" Ytr=" << trackY <<
" yCl=" << cls.y;
2940 clVecOut.push_back(cls.id);
2942 return clVecOut.size();
2953 size_t sizTotShm = 0, capTotShm = 0, sizTot = 0, capTot = 0, siz = 0, cap = 0, cnt = 0, cntCap = 0;
2959 LOGP(info,
"Size SHM, matchedTracks : size {:9} cap {:9}", siz, cap);
2965 LOGP(info,
"Size SHM, ABTrackletRefs : size {:9} cap {:9}", siz, cap);
2967 siz = ABTrackletClusterIDs.size() *
sizeof(int);
2968 cap = ABTrackletClusterIDs.capacity() *
sizeof(int);
2971 LOGP(info,
"Size SHM, ABTrackletClusterIDs : size {:9} cap {:9}", siz, cap);
2977 LOGP(info,
"Size SHM, matchLabels : size {:9} cap {:9}", siz, cap);
2983 LOGP(info,
"Size SHM, ABTrackletLabels : size {:9} cap {:9}", siz, cap);
2989 LOGP(info,
"Size SHM, calib : size {:9} cap {:9}", siz, cap);
2993 for (
const auto& clusV : mITSClustersArray) {
2995 cap += clusV.capacity() *
sizeof(
ITSCluster);
2999 LOGP(info,
"Size RSS, mITSClustersArray : size {:9} cap {:9}", siz, cap);
3002 for (
const auto& abClus : mABLayerClusters) {
3003 siz += abClus.sizeInternal();
3004 cap += abClus.capInternal();
3008 LOGP(info,
"Size RSS, mABLayerClusters : size {:9} cap {:9}", siz, cap);
3010 siz = mMatchRecordsTPC.size() *
sizeof(
MatchRecord);
3011 cap = mMatchRecordsTPC.capacity() *
sizeof(
MatchRecord);
3014 LOGP(info,
"Size RSS, mMatchRecordsTPC : size {:9} cap {:9}", siz, cap);
3016 siz = mMatchRecordsITS.size() *
sizeof(
MatchRecord);
3017 cap = mMatchRecordsITS.capacity() *
sizeof(
MatchRecord);
3020 LOGP(info,
"Size RSS, mMatchRecordsITS : size {:9} cap {:9}", siz, cap);
3022 siz = mITSROFTimes.size() *
sizeof(
BracketF);
3023 cap = mITSROFTimes.capacity() *
sizeof(
BracketF);
3026 LOGP(info,
"Size RSS, mITSROFTimes : size {:9} cap {:9}", siz, cap);
3032 LOGP(info,
"Size RSS, mTPCWork : size {:9} cap {:9}", siz, cap);
3038 LOGP(info,
"Size RSS, mITSWork : size {:9} cap {:9}", siz, cap);
3040 siz = mWinnerChi2Refit.size() *
sizeof(float);
3041 cap = mWinnerChi2Refit.capacity() *
sizeof(float);
3044 LOGP(info,
"Size RSS, mWinnerChi2Refit : size {:9} cap {:9}", siz, cap);
3046 siz = mTPCABSeeds.size() *
sizeof(float);
3047 cap = mTPCABSeeds.capacity() *
sizeof(float);
3050 for (
const auto&
a : mTPCABSeeds) {
3051 siz +=
a.sizeInternal();
3052 cap +=
a.capInternal();
3053 cnt +=
a.getNLinks();
3054 cntCap +=
a.getNLinks();
3058 LOGP(info,
"Size RSS, mTPCABSeeds : size {:9} cap {:9} | internals size:{}/capacity:{} for {} elements", siz, cap, cnt, cntCap, mTPCABSeeds.size());
3060 siz = mTPCABIndexCache.size() *
sizeof(int);
3061 cap = mTPCABIndexCache.capacity() *
sizeof(int);
3064 LOGP(info,
"Size RSS, mTPCABIndexCache : size {:9} cap {:9}", siz, cap);
3066 siz = mABWinnersIDs.size() *
sizeof(int);
3067 cap = mABWinnersIDs.capacity() *
sizeof(int);
3070 LOGP(info,
"Size RSS, mABWinnersIDs : size {:9} cap {:9}", siz, cap);
3073 for (
const auto& clStatus : mABClusterStatus) {
3074 siz += clStatus.size() *
sizeof(int);
3075 cap += clStatus.capacity() *
sizeof(int);
3079 LOGP(info,
"Size RSS, mABClusterStatus : size {:9} cap {:9}", siz, cap);
3081 for (
int is = 0; is < o2::constants::math::NSectors; is++) {
3082 siz += mTPCSectIndexCache[is].size() *
sizeof(int);
3083 cap += mTPCSectIndexCache[is].capacity() *
sizeof(int);
3087 LOGP(info,
"Size RSS, mTPCSectIndexCache : size {:9} cap {:9}", siz, cap);
3089 for (
int is = 0; is < o2::constants::math::NSectors; is++) {
3090 siz += mITSSectIndexCache[is].size() *
sizeof(int);
3091 cap += mITSSectIndexCache[is].capacity() *
sizeof(int);
3095 LOGP(info,
"Size RSS, mITSSectIndexCache : size {:9} cap {:9}", siz, cap);
3097 for (
int is = 0; is < o2::constants::math::NSectors; is++) {
3098 siz += mTPCTimeStart[is].size() *
sizeof(int);
3099 cap += mTPCTimeStart[is].capacity() *
sizeof(int);
3103 LOGP(info,
"Size RSS, mTPCTimeStart : size {:9} cap {:9}", siz, cap);
3105 for (
int is = 0; is < o2::constants::math::NSectors; is++) {
3106 siz += mITSTimeStart[is].size() *
sizeof(int);
3107 cap += mITSTimeStart[is].capacity() *
sizeof(int);
3111 LOGP(info,
"Size RSS, mITSTimeStart : size {:9} cap {:9}", siz, cap);
3113 siz = mITSTrackROFContMapping.size() *
sizeof(int);
3114 cap = mITSTrackROFContMapping.capacity() *
sizeof(int);
3117 LOGP(info,
"Size RSS, ITSTrackROFContMapping: size {:9} cap {:9}", siz, cap);
3119 LOGP(info,
"TotalSizes/Capacities: SHM: {}/{} Heap: {}/{}", sizTotShm, capTotShm, sizTot, capTot);
3126 mNThreads =
n > 0 ?
n : 1;
3128 LOG(warning) <<
"Multithreading is not supported, imposing single thread";
3137#ifdef _ALLOW_DEBUG_TREES_
3153 mTimer[SWDBG].Start(
false);
3154 const auto& tpcOrig = mTPCTracksArray[tpcIndex];
3155 uint8_t clSect = 0, clRow = 0, prevRow = 0xff, padFromEdge = -1;
3158 std::array<bool, 152> shMap{};
3159 bool prevRawShared =
false;
3160 for (
int i = 0;
i < tpcOrig.getNClusterReferences();
i++) {
3161 tpcOrig.getClusterReference(mTPCTrackClusIdx,
i, clSect, clRow, clIdx);
3162 unsigned int absoluteIndex = mTPCClusterIdxStruct->
clusterOffset[clSect][clRow] + clIdx;
3164 if (!(prevRow == clRow && prevRawShared)) {
3168 prevRawShared =
true;
3171 const auto& clus = mTPCClusterIdxStruct->
clusters[clSect][clRow][clIdx];
3172 padFromEdge =
uint8_t(clus.getPad());
3173 if (padFromEdge > TPCGeometry.NPads(clRow) / 2) {
3174 padFromEdge = TPCGeometry.NPads(clRow) - 1 - padFromEdge;
3176 int tb = tpcOrig.getTime0() * mNTPCOccBinLengthInv;
3177 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
3178 (*mDBGOut) <<
"tpcOrig"
3179 <<
"tf=" << mTFCount
3180 <<
"index=" << tpcIndex
3182 <<
"chi2TPC=" << tpcOrig.getChi2()
3183 <<
"nClus=" << tpcOrig.getNClusters()
3184 <<
"nShared=" << nshared
3185 <<
"time0=" << tpcOrig.getTime0()
3187 <<
"minRow=" << clRow
3188 <<
"padFromEdge=" << padFromEdge
3189 <<
"multTPC=" << mltTPC;
3191 (*mDBGOut) <<
"tpcOrig"
3192 <<
"tpcLbl=" << mTPCTrkLabels[tpcIndex];
3194 (*mDBGOut) <<
"tpcOrig"
3196 mTimer[SWDBG].Stop();
3204 mTimer[SWDBG].Start(
false);
3206 auto& trackITS = mITSWork[itsID];
3207 auto& trackTPC = mTPCWork[tpcID];
3209 chi2 = getPredictedChi2NoZ(trackITS, trackTPC);
3211 (*mDBGOut) <<
"match"
3212 <<
"tf=" << mTFCount <<
"chi2Match=" <<
chi2 <<
"its=" << trackITS <<
"tpc=" << trackTPC <<
"tcorr=" << tCorr;
3214 (*mDBGOut) <<
"match"
3215 <<
"itsLbl=" << mITSLblWork[itsID] <<
"tpcLbl=" << mTPCLblWork[tpcID];
3217 int tb = mTPCTracksArray[trackTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
3218 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
3219 (*mDBGOut) <<
"match"
3220 <<
"rejFlag=" << rejFlag
3221 <<
"multTPC=" << mltTPC
3222 <<
"multITSTr=" << mITSTrackROFRec[trackITS.roFrame].getNEntries()
3223 <<
"multITSCl=" << mITSClusterROFRec[mRecoCont->
getITSPerLayer() ? mITSClockLayer : 0][trackITS.roFrame].getNEntries()
3226 mTimer[SWDBG].Stop();
3234 mTimer[SWDBG].Start(
false);
3236 LOG(info) <<
"Dumping debug tree for winner matches";
3237 for (
int iits = 0; iits <
int(mITSWork.size()); iits++) {
3238 auto& tITS = mITSWork[iits];
3239 if (isDisabledITS(tITS)) {
3242 auto& itsMatchRec = mMatchRecordsITS[tITS.
matchID];
3243 int itpc = itsMatchRec.partnerID;
3244 auto& tTPC = mTPCWork[itpc];
3246 (*mDBGOut) <<
"matchWin"
3247 <<
"tf=" << mTFCount <<
"chi2Match=" << itsMatchRec.chi2 <<
"chi2Refit=" << mWinnerChi2Refit[iits] <<
"its=" << tITS <<
"tpc=" << tTPC;
3250 (*mDBGOut) <<
"matchWin"
3251 <<
"itsLbl=" << mITSLblWork[iits] <<
"tpcLbl=" << mTPCLblWork[itpc];
3253 int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv;
3254 float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]);
3255 (*mDBGOut) <<
"matchWin"
3256 <<
"multTPC=" << mltTPC
3257 <<
"multITSTr=" << mITSTrackROFRec[tITS.
roFrame].getNEntries()
3258 <<
"multITSCl=" << mITSClusterROFRec[mRecoCont->
getITSPerLayer() ? mITSClockLayer : 0][tITS.
roFrame].getNEntries()
3261 mTimer[SWDBG].Stop();
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.
std::vector< o2::MCCompLabel > labels
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
@ 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)
BracketF getITSROFTimeBracket(long nBC, int lr) const
bool refitABTrack(int iITSAB, const TPCABSeed &seed, pmr::vector< o2::dataformats::TrackTPCITS > &matchedTracks, pmr::vector< int > &ABTrackletClusterIDs, pmr::vector< o2::itsmft::TrkClusRef > &ABTrackletRefs)
void setAlpideParam(const AlpParamITS *p)
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)
perform matching for provided input
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
static constexpr int NITSLayers
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
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 int statusCode int
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 int Validated
per-layer status of ITS clusters (e.g. for the AfterBurner)
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 const float const TrackSeed< NLayers > & seed
o2::track::TrackParCov int int int float int nCl
const bool const int TrackITSInternal< NLayers > & track
constexpr int clusID2Layer(int id)
constexpr int composeClusID(int lr, int idx)
constexpr int clusID2Index(int id)
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 z
Y, Z of the cluster in the tracking frame of its sensor.
int chip
global chip (sensor) ID
int nData
number of clusters in the view
int chipOffs
global ID of the 1st chip of the layer
int rofKey
1st ROF of the loaded block(s): -1: no compatible ROF, -2: nothing loaded yet
const ABClusterInfo * data
clusters of the loaded block(s), sorted in (chip, Z)
std::vector< ClusRange > chipRefs
cluster range in data for every chip of the layer
std::vector< ABClusterInfo > merged
buffer to merge 2 blocks when the candidate time is compatible with 2 ROFs
std::vector< int > touchedChips
chips with non-empty chipRefs, for fast reset
int nROFsKey
number of consecutive ROFs loaded (1 or 2)
std::array< ABLayerView, o2::its::RecoGeomHelper::getNLayers()> layers
< per-thread views of the AB clusters of all layers
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.
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 abROFMarginMUS
margin in \mus for matching interaction candidate time to ITS ROFs in the AfterBurner (clamped to bel...
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 itsTimeStampMarginBC
safety margin in BC applied to both edges of the ITS track time-stamp uncertainty interval
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...
auto getITSPerLayer() const
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
void addLink(const o2::track::TrackParCov &trc, int clID, int parentID, int nextID, int lr, int nc, int laddID, float chi2)
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"
char const *restrict const cmp