44 LOG(info) <<
"Start initializing TrackInterpolation";
46 LOG(error) <<
"Initialization already performed.";
51 mTPCTimeBinMUS = elParam.ZbinWidth;
60 mSourcesConfigured =
src;
61 mSourcesConfiguredMap = srcMap;
62 mSingleSourcesConfigured = (mSourcesConfigured == mSourcesConfiguredMap);
69 LOGP(info,
"Done initializing TrackInterpolation. Configured track input: {}. Track input specifically for map: {}",
75 LOGP(
debug,
"Check if input track {} is accepted", gid.
asString());
77 if (!hasOuterPoint && !mProcessITSTPConly) {
91 if (itsTrk.getChi2() / itsTrk.getNumberOfClusters() > mParams->
maxITSChi2 || tpcTrk.getChi2() / tpcTrk.getNClusterReferences() > mParams->
maxTPCChi2) {
103 if (itsTrk.getNumberOfClusters() < mParams->
minITSNCls || tpcTrk.getNClusterReferences() < mParams->
minTPCNCls) {
111 if (!prop->propagateToDCA(pv, trc, prop->getNominalBz(), 2., o2::base::PropagatorF::MatCorrType::USEMatCorrLUT, &dca)) {
145 uint32_t nTrackSeeds = 0;
146 uint32_t countSeedCandidates[4] = {0};
150 int nv = vtxRefs.size() - 1;
154 for (
int iv = 0; iv < nv; iv++) {
155 LOGP(
debug,
"processing PV {} of {}", iv, nv);
157 const auto& vtref = vtxRefs[iv];
162 for (uint32_t is = 0; is < SrcFast.size() && !usePV; is++) {
163 int src = SrcFast[is], idMin = vtref.getFirstEntryOfSource(
src), idMax = idMin + vtref.getEntriesOfSource(
src);
164 for (
int i = idMin;
i < idMax;
i++) {
177 if (!allowedSources[is]) {
180 LOGP(
debug,
"Checking source {}", is);
181 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
182 for (
int i = idMin;
i < idMax;
i++) {
183 auto vid = trackIndex[
i];
188 if (vid.isAmbiguous()) {
192 if (!mSourcesConfigured[is]) {
202 ++countSeedCandidates[mTrackTypes[vid.getSource()]];
203 LOGP(
debug,
"Checking vid {}", vid.asString());
208 mSeeds.back().setPID(mRecoCont->
getTrackParam(vidOrig).getPID(),
true);
209 mGIDs.push_back(vid);
210 mGIDtables.push_back(gidTable);
211 mTrackTimes.push_back(pv.getTimeStamp().getTimeStamp());
212 mTrackIndices[mTrackTypes[vid.getSource()]].push_back(nTrackSeeds++);
217 LOGP(info,
"Created {} seeds. {} out of {} ITS-TPC-TRD-TOF, {} out of {} ITS-TPC-TRD, {} out of {} ITS-TPC-TOF, {} out of {} ITS-TPC",
227 std::random_device
rd;
228 std::mt19937
g(
rd());
229 std::uniform_real_distribution<>
distr(0., 1.);
238 LOG(error) <<
"Initialization not yet done. Aborting...";
244 if (mDumpTrackPoints) {
246 LOG(error) <<
"No ITS dictionary available";
252 auto pattIt = patterns.begin();
253 mITSClustersArray.clear();
254 mITSClustersArray.reserve(clusITS.size());
255 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}", clusITS.size(), patterns.size());
263 std::random_device
rd;
264 std::mt19937
g(
rd());
265 std::vector<uint32_t> trackIndices;
275 int nSeeds = mSeeds.size();
276 int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds;
277 mTrackData.reserve(maxOutputTracks);
278 mClRes.reserve(maxOutputTracks * param::NPadRows);
279 bool maxTracksReached =
false;
280 for (
int iSeed = 0; iSeed < nSeeds; ++iSeed) {
281 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
282 LOG(info) <<
"Maximum number of tracks per TF reached. Skipping the remaining " << nSeeds - iSeed <<
" tracks.";
285 int seedIndex = trackIndices[iSeed];
289 if (!mSingleSourcesConfigured && !mSourcesConfiguredMap[mGIDs[seedIndex].getSource()]) {
293 mGIDs.push_back(mGIDtables[seedIndex][
src]);
295 mTrackTimes.push_back(mTrackTimes[seedIndex]);
296 mSeeds.push_back(mSeeds[seedIndex]);
299 if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF) {
300 LOG(
debug) <<
"We already have reached mMaxTracksPerTF, but we continue to create seeds until mAddTracksForMapPerTF is also reached";
309 mTrackTimes.push_back(mTrackTimes[seedIndex]);
310 mSeeds.push_back(mSeeds[seedIndex]);
314 mTrackTimes.push_back(mTrackTimes[seedIndex]);
315 mSeeds.push_back(mSeeds[seedIndex]);
321 if (mSeeds.size() > nSeeds) {
322 LOGP(info,
"Up to {} tracks out of {} additional seeds will be processed", mAddTracksForMapPerTF, mSeeds.size() - nSeeds);
324 for (
int iSeed = nSeeds; iSeed < (
int)mSeeds.size(); ++iSeed) {
325 if (!mProcessSeeds && mAddTracksForMapPerTF > 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) {
326 LOG(info) <<
"Maximum number of additional tracks per TF reached. Skipping the remaining " << mSeeds.size() - iSeed <<
" tracks.";
330 LOGP(
debug,
"Processing additional track {}", mGIDs[iSeed].
asString());
337 LOG(info) <<
"Could process " << mTrackData.size() <<
" tracks successfully. " << mRejectedResiduals <<
" residuals were rejected. " << mClRes.size() <<
" residuals were accepted.";
338 mRejectedResiduals = 0;
343 LOGP(
debug,
"Starting track interpolation for GID {}", mGIDs[iSeed].
asString());
345 std::unique_ptr<TrackDataExtended> trackDataExtended;
346 std::vector<TPCClusterResiduals> clusterResiduals;
348 const auto& gidTable = mGIDtables[iSeed];
351 if (mDumpTrackPoints) {
352 trackDataExtended = std::make_unique<TrackDataExtended>();
353 (*trackDataExtended).gid = mGIDs[iSeed];
354 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
355 (*trackDataExtended).trkITS = trkITS;
356 (*trackDataExtended).trkTPC = trkTPC;
357 auto nCl = trkITS.getNumberOfClusters();
358 auto clEntry = trkITS.getFirstClusterEntry();
359 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
360 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
361 (*trackDataExtended).clsITS.push_back(clsITS);
364 trackData.
gid = mGIDs[iSeed];
365 trackData.
par = mSeeds[iSeed];
366 auto& trkWork = mSeeds[iSeed];
368 for (
auto& elem : mCache) {
369 elem.clAvailable = 0;
371 trackData.
clIdx.setFirstEntry(mClRes.size());
372 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
375 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
377 uint32_t clusterIndexInRow;
378 const auto& clTPC = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
380 std::array<float, 2> clTPCYZ;
381 mFastTransform->TransformIdeal(sector,
row, clTPC.getPad(), clTPC.getTime(), clTPCX, clTPCYZ[0], clTPCYZ[1], clusterTimeBinOffset);
382 mCache[
row].clSec = sector;
383 mCache[
row].clAvailable = 1;
384 mCache[
row].clY = clTPCYZ[0];
385 mCache[
row].clZ = clTPCYZ[1];
390 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
391 if (!mCache[iRow].clAvailable) {
394 if (!trkWork.rotate(mCache[iRow].clAngle)) {
395 LOG(
debug) <<
"Failed to rotate track during first extrapolation";
398 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
399 LOG(
debug) <<
"Failed on first extrapolation";
402 mCache[iRow].y[
ExtOut] = trkWork.getY();
403 mCache[iRow].z[
ExtOut] = trkWork.getZ();
404 mCache[iRow].sy2[
ExtOut] = trkWork.getSigmaY2();
405 mCache[iRow].szy[
ExtOut] = trkWork.getSigmaZY();
406 mCache[iRow].sz2[
ExtOut] = trkWork.getSigmaZ2();
407 mCache[iRow].snp[
ExtOut] = trkWork.getSnp();
413 LOG(
debug) <<
"TOF point available";
415 if (mDumpTrackPoints) {
416 (*trackDataExtended).clsTOF = clTOF;
417 (*trackDataExtended).matchTOF = mRecoCont->
getTOFMatch(mGIDs[iSeed]);
419 const int clTOFSec = clTOF.getCount();
421 if (!trkWork.rotate(clTOFAlpha)) {
422 LOG(
debug) <<
"Failed to rotate into TOF cluster sector frame";
425 float clTOFX = clTOF.getX();
426 std::array<float, 2> clTOFYZ{clTOF.getY(), clTOF.getZ()};
428 if (!propagator->PropagateToXBxByBz(trkWork, clTOFX, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
429 LOG(
debug) <<
"Failed final propagation to TOF radius";
433 if (!trkWork.update(clTOFYZ, clTOFCov)) {
434 LOG(
debug) <<
"Failed to update extrapolated ITS track with TOF cluster";
442 if (mDumpTrackPoints) {
443 (*trackDataExtended).trkTRD = trkTRD;
446 int trkltIdx = trkTRD.getTrackletIndex(iLayer);
453 if (mDumpTrackPoints) {
454 (*trackDataExtended).trkltTRD.push_back(trdTrklt);
455 (*trackDataExtended).clsTRD.push_back(trdSP);
457 auto trkltDet = trdTrklt.getDetector();
461 LOG(
debug) <<
"Track could not be rotated in TRD tracklet coordinate system in layer " << iLayer;
465 if (!propagator->PropagateToXBxByBz(trkWork, trdSP.getX(), mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
466 LOG(
debug) <<
"Failed propagation to TRD layer " << iLayer;
470 const auto* pad = mGeoTRD->getPadPlane(trkltDet);
471 float tilt = tan(TMath::DegToRad() * pad->getTiltingAngle());
472 float tiltCorrUp = tilt * (trdSP.getZ() - trkWork.getZ());
473 float zPosCorrUp = trdSP.getZ() + mRecoParam.
getZCorrCoeffNRC() * trkWork.getTgl();
474 float padLength = pad->getRowSize(trdTrklt.getPadRow());
475 if (!((trkWork.getSigmaZ2() < (padLength * padLength / 12.f)) && (std::fabs(trdSP.getZ() - trkWork.getZ()) < padLength))) {
478 std::array<float, 2> trkltTRDYZ{trdSP.getY() - tiltCorrUp, zPosCorrUp};
479 std::array<float, 3> trkltTRDCov;
480 mRecoParam.
recalcTrkltCov(tilt, trkWork.getSnp(), pad->getRowSize(trdTrklt.getPadRow()), trkltTRDCov);
481 if (!trkWork.update(trkltTRDYZ, trkltTRDCov)) {
482 LOG(
debug) <<
"Failed to update track at TRD layer " << iLayer;
488 if (mDumpTrackPoints) {
489 (*trackDataExtended).trkOuter = trkWork;
493 bool outerParamStored =
false;
494 for (
int iRow = param::NPadRows; iRow--;) {
495 if (!mCache[iRow].clAvailable) {
498 if (mProcessSeeds && !outerParamStored) {
504 trackData.
par = trkWork;
505 outerParamStored =
true;
507 if (!trkWork.rotate(mCache[iRow].clAngle)) {
508 LOG(
debug) <<
"Failed to rotate track during back propagation";
511 if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
512 LOG(
debug) <<
"Failed on back propagation";
516 mCache[iRow].y[
ExtIn] = trkWork.getY();
517 mCache[iRow].z[
ExtIn] = trkWork.getZ();
518 mCache[iRow].sy2[
ExtIn] = trkWork.getSigmaY2();
519 mCache[iRow].szy[
ExtIn] = trkWork.getSigmaZY();
520 mCache[iRow].sz2[
ExtIn] = trkWork.getSigmaZ2();
521 mCache[iRow].snp[
ExtIn] = trkWork.getSnp();
525 unsigned short deltaRow = 0;
526 for (
int iRow = 0; iRow < param::NPadRows; ++iRow) {
527 if (!mCache[iRow].clAvailable) {
531 float wTotY = 1.f / mCache[iRow].sy2[
ExtOut] + 1.f / mCache[iRow].sy2[
ExtIn];
532 float wTotZ = 1.f / mCache[iRow].sz2[
ExtOut] + 1.f / mCache[iRow].sz2[
ExtIn];
533 mCache[iRow].y[
Int] = (mCache[iRow].y[
ExtOut] / mCache[iRow].sy2[
ExtOut] + mCache[iRow].y[
ExtIn] / mCache[iRow].sy2[
ExtIn]) / wTotY;
534 mCache[iRow].z[
Int] = (mCache[iRow].z[
ExtOut] / mCache[iRow].sz2[
ExtOut] + mCache[iRow].z[
ExtIn] / mCache[iRow].sz2[
ExtIn]) / wTotZ;
537 mCache[iRow].snp[
Int] = (mCache[iRow].snp[
ExtOut] + mCache[iRow].snp[
ExtIn]) / 2.f;
539 const auto dY = mCache[iRow].clY - mCache[iRow].y[
Int];
540 const auto dZ = mCache[iRow].clZ - mCache[iRow].z[
Int];
541 const auto y = mCache[iRow].y[
Int];
542 const auto z = mCache[iRow].z[
Int];
543 const auto snp = mCache[iRow].snp[
Int];
544 const auto sec = mCache[iRow].clSec;
545 clusterResiduals.emplace_back(dY, dZ,
y,
z, snp, sec, deltaRow);
550 trackData.
chi2TPC = trkTPC.getChi2();
551 trackData.
chi2ITS = trkITS.getChi2();
552 trackData.
nClsTPC = trkTPC.getNClusterReferences();
553 trackData.
nClsITS = trkITS.getNumberOfClusters();
556 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
561 int nClValidated = 0;
563 for (
unsigned int iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
564 iRow += clusterResiduals[iCl].dRow;
565 if (
params.flagRej[iCl]) {
570 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
571 const auto dy = clusterResiduals[iCl].dy;
572 const auto dz = clusterResiduals[iCl].dz;
573 const auto y = clusterResiduals[iCl].y;
574 const auto z = clusterResiduals[iCl].z;
575 const auto sec = clusterResiduals[iCl].sec;
576 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
577 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, sec);
579 ++mRejectedResiduals;
582 trackData.
clIdx.setEntries(nClValidated);
583 mTrackData.push_back(std::move(trackData));
584 if (mDumpTrackPoints) {
585 (*trackDataExtended).clIdx.setEntries(nClValidated);
586 mTrackDataExtended.push_back(std::move(*trackDataExtended));
588 mGIDsSuccess.push_back(mGIDs[iSeed]);
589 mTrackDataCompact.emplace_back(mClRes.size() - nClValidated, nClValidated, mGIDs[iSeed].getSource());
593 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
594 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
595 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
596 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
603 LOGP(
debug,
"Starting track extrapolation for GID {}", mGIDs[iSeed].
asString());
604 const auto& gidTable = mGIDtables[iSeed];
606 std::unique_ptr<TrackDataExtended> trackDataExtended;
607 std::vector<TPCClusterResiduals> clusterResiduals;
608 trackData.
clIdx.setFirstEntry(mClRes.size());
611 if (mDumpTrackPoints) {
612 trackDataExtended = std::make_unique<TrackDataExtended>();
613 (*trackDataExtended).gid = mGIDs[iSeed];
614 (*trackDataExtended).clIdx.setFirstEntry(mClRes.size());
615 (*trackDataExtended).trkITS = trkITS;
616 (*trackDataExtended).trkTPC = trkTPC;
617 auto nCl = trkITS.getNumberOfClusters();
618 auto clEntry = trkITS.getFirstClusterEntry();
619 for (
int iCl = nCl - 1; iCl >= 0; iCl--) {
620 const auto& clsITS = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
621 (*trackDataExtended).clsITS.push_back(clsITS);
624 trackData.
gid = mGIDs[iSeed];
625 trackData.
par = mSeeds[iSeed];
627 auto& trkWork = mSeeds[iSeed];
628 float clusterTimeBinOffset = mTrackTimes[iSeed] / mTPCTimeBinMUS;
630 unsigned short rowPrev = 0;
631 unsigned short nMeasurements = 0;
633 for (
int iCl = trkTPC.getNClusterReferences(); iCl--;) {
635 uint32_t clusterIndexInRow;
636 const auto& cl = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector,
row);
637 if (clRowPrev ==
row) {
640 }
else if (clRowPrev < constants::MAXGLOBALPADROW && clRowPrev >
row) {
642 LOGP(
debug,
"TPC track with pT={} GeV and {} clusters has cluster {} on row {} while the previous cluster was on row {}",
643 mSeeds[iSeed].getPt(), trkTPC.getNClusterReferences(), iCl,
row, clRowPrev);
649 float x = 0,
y = 0,
z = 0;
650 mFastTransform->TransformIdeal(sector,
row, cl.getPad(), cl.getTime(),
x,
y,
z, clusterTimeBinOffset);
654 if (!propagator->PropagateToXBxByBz(trkWork,
x, mParams->
maxSnp, mParams->
maxStep, mMatCorr)) {
658 const auto dY =
y - trkWork.getY();
659 const auto dZ =
z - trkWork.getZ();
660 const auto ty = trkWork.getY();
661 const auto tz = trkWork.getZ();
662 const auto snp = trkWork.getSnp();
663 const auto sec = sector;
665 clusterResiduals.emplace_back(dY, dZ, ty, tz, snp, sec,
row - rowPrev);
670 trackData.
chi2TPC = trkTPC.getChi2();
671 trackData.
chi2ITS = trkITS.getChi2();
672 trackData.
nClsTPC = trkTPC.getNClusterReferences();
673 trackData.
nClsITS = trkITS.getNumberOfClusters();
674 trackData.
clIdx.setEntries(nMeasurements);
675 trackData.
dEdxTPC = trkTPC.getdEdx().dEdxTotTPC;
676 if (mDumpTrackPoints) {
677 (*trackDataExtended).trkOuter = trkWork;
682 LOGP(warn,
"Extrapolated ITS-TPC track and found more reesiduals than possible ({})", clusterResiduals.size());
687 int nClValidated = 0;
689 for (
unsigned int iCl = 0; iCl < clusterResiduals.size(); ++iCl) {
690 iRow += clusterResiduals[iCl].dRow;
691 if (
params.flagRej[iCl]) {
696 const float tgPhi = clusterResiduals[iCl].snp / std::sqrt((1.f - clusterResiduals[iCl].snp) * (1.f + clusterResiduals[iCl].snp));
697 const auto dy = clusterResiduals[iCl].dy;
698 const auto dz = clusterResiduals[iCl].dz;
699 const auto y = clusterResiduals[iCl].y;
700 const auto z = clusterResiduals[iCl].z;
701 const auto sec = clusterResiduals[iCl].sec;
702 if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(
y) < param::MaxY) && (std::abs(
z) < param::MaxZ) && (std::abs(tgPhi) < param::MaxTgSlp)) {
703 mClRes.emplace_back(dy, dz, tgPhi,
y,
z, iRow, sec);
705 ++mRejectedResiduals;
708 trackData.
clIdx.setEntries(nClValidated);
709 mTrackData.push_back(std::move(trackData));
710 mGIDsSuccess.push_back(mGIDs[iSeed]);
711 mTrackDataCompact.emplace_back(mClRes.size() - nClValidated, nClValidated, mGIDs[iSeed].getSource());
712 if (mDumpTrackPoints) {
713 (*trackDataExtended).clIdx.setEntries(nClValidated);
714 mTrackDataExtended.push_back(std::move(*trackDataExtended));
719 trkDataTmp.
clIdx.setFirstEntry(mClResUnfiltered.size());
720 trkDataTmp.
clIdx.setEntries(clusterResiduals.size());
721 mTrackDataUnfiltered.push_back(std::move(trkDataTmp));
722 mClResUnfiltered.insert(mClResUnfiltered.end(), clusterResiduals.begin(), clusterResiduals.end());
728 if (clsRes.size() < mParams->
minNCl) {
730 LOG(
debug) <<
"Skipping track with too few clusters: " << clsRes.size();
736 LOG(
debug) <<
"Skipping track too far from helix approximation";
739 if (fabsf(mBz) > 0.01 && fabsf(
params.qpt) > mParams->
maxQ2Pt) {
740 LOG(
debug) <<
"Skipping track with too high q/pT: " <<
params.qpt;
751 std::array<float, param::NPadRows> residHelixY;
752 std::array<float, param::NPadRows> residHelixZ;
754 std::array<float, param::NPadRows> xLab;
755 std::array<float, param::NPadRows> yLab;
756 std::array<float, param::NPadRows> sPath;
759 int secFirst = clsRes[0].sec;
761 float snPhi = sin(phiSect);
762 float csPhi = cos(phiSect);
766 int nCl = clsRes.size();
767 for (
unsigned int iP = 0; iP < nCl; ++iP) {
768 iRow += clsRes[iP].dRow;
769 float yTrk = clsRes[iP].y;
771 xLab[iP] = param::RowX[iRow];
772 if (clsRes[iP].sec != secFirst) {
774 float cs = cos(phiSectCurrent - phiSect);
775 float sn = sin(phiSectCurrent - phiSect);
776 xLab[iP] = param::RowX[iRow] * cs - yTrk * sn;
777 yLab[iP] = yTrk * cs + param::RowX[iRow] * sn;
779 xLab[iP] = param::RowX[iRow];
783 params.zTrk[iP] = clsRes[iP].z;
784 params.xTrk[iP] = param::RowX[iRow];
785 params.dy[iP] = clsRes[iP].dy;
786 params.dz[iP] = clsRes[iP].dz;
789 float dx = xLab[iP] - xLab[iP - 1];
790 float dy = yLab[iP] - yLab[iP - 1];
791 float ds2 = dx * dx + dy * dy;
792 float ds = sqrt(ds2);
796 if (
ds * curvature > 0.05) {
797 ds *= (1.f + ds2 * curvature * curvature / 24.f);
799 sPath[iP] = sPath[iP - 1] +
ds;
802 if (fabsf(mBz) < 0.01) {
817 float phiI = TMath::ATan2(yLab[0], xLab[0]);
818 float phiF = TMath::ATan2(yLab[nCl - 1], xLab[nCl - 1]);
825 float dPhi = phiF - phiI;
826 float curvSign = -1.f;
837 float xc = xcSec * csPhi - ycSec * snPhi;
838 float yc = xcSec * snPhi + ycSec * csPhi;
840 std::array<float, 2> pol1Z;
851 int secCurr = secFirst;
853 for (
unsigned int iCl = 0; iCl < nCl; ++iCl) {
854 iRow += clsRes[iCl].dRow;
855 float resZ =
params.zTrk[iCl] - (pol1Z[1] + sPath[iCl] * pol1Z[0]);
856 residHelixZ[iCl] = resZ;
863 if (residHelixY[iCl] < hMinY) {
864 hMinY = residHelixY[iCl];
866 if (residHelixY[iCl] > hMaxY) {
867 hMaxY = residHelixY[iCl];
869 int sec = clsRes[iCl].sec;
870 if (sec != secCurr) {
873 snPhi = sin(phiSect);
874 csPhi = cos(phiSect);
875 xcSec = xc * csPhi + yc * snPhi;
877 float cstalp = (param::RowX[iRow] - xcSec) /
r;
878 if (fabsf(cstalp) > 1.f - sFloatEps) {
880 cstalp = std::copysign(1.f - sFloatEps, cstalp);
882 params.tglArr[iCl] = cstalp / sqrt((1 - cstalp) * (1 + cstalp));
885 if (
params.qpt * mBz > 0) {
886 params.tglArr[iCl] *= -1.f;
896 if (clsRes.size() < mParams->
nMALong) {
897 LOG(
debug) <<
"Skipping track with too few clusters for long moving average: " << clsRes.size();
901 if (
static_cast<float>(
params.flagRej.count()) / clsRes.size() > mParams->
maxRejFrac) {
902 LOGP(
debug,
"Skipping track with too many clusters rejected: {} out of {}",
params.flagRej.count(), clsRes.size());
906 LOG(
debug) <<
"Skipping track with too large RMS: " << rmsLong;
916 int nCl = clsRes.size();
918 int iClLast = nCl - 1;
919 int secStart = clsRes[0].sec;
922 std::array<float, param::NPadRows> yDiffLL{};
923 std::array<float, param::NPadRows> zDiffLL{};
924 std::array<float, param::NPadRows> absDevY{};
925 std::array<float, param::NPadRows> absDevZ{};
927 for (
unsigned int iCl = 0; iCl < nCl; ++iCl) {
928 if (iCl < iClLast && clsRes[iCl].sec == secStart) {
933 int nClSec = iCl - iClFirst;
934 if (iCl == iClLast) {
940 secStart = clsRes[iCl].sec;
945 for (
int iCl = nCl; iCl--;) {
946 if (fabsf(yDiffLL[iCl]) > param::sEps) {
947 absDevY[nAccY++] = fabsf(yDiffLL[iCl]);
949 if (fabsf(zDiffLL[iCl]) > param::sEps) {
950 absDevZ[nAccZ++] = fabsf(zDiffLL[iCl]);
953 if (nAccY < mParams->minNumberOfAcceptedResiduals || nAccZ < mParams->minNumberOfAcceptedResiduals) {
960 int nKeepY =
static_cast<int>(.9 * nAccY);
961 int nKeepZ =
static_cast<int>(.9 * nAccZ);
962 std::nth_element(absDevY.begin(), absDevY.begin() + nKeepY, absDevY.begin() + nAccY);
963 std::nth_element(absDevZ.begin(), absDevZ.begin() + nKeepZ, absDevZ.begin() + nAccZ);
964 float rmsYkeep = 0.f;
965 float rmsZkeep = 0.f;
966 for (
int i = nKeepY;
i--;) {
967 rmsYkeep += absDevY[
i] * absDevY[
i];
969 for (
int i = nKeepZ;
i--;) {
970 rmsZkeep += absDevZ[
i] * absDevZ[
i];
972 rmsYkeep = std::sqrt(rmsYkeep / nKeepY);
973 rmsZkeep = std::sqrt(rmsZkeep / nKeepZ);
974 if (rmsYkeep < param::sEps || rmsZkeep < param::sEps) {
975 LOG(warning) <<
"Too small RMS: " << rmsYkeep <<
"(y), " << rmsZkeep <<
"(z).";
979 float rmsYkeepI = 1.f / rmsYkeep;
980 float rmsZkeepI = 1.f / rmsZkeep;
982 std::array<float, param::NPadRows> yAcc;
983 std::array<float, param::NPadRows> yDiffLong;
984 for (
int iCl = 0; iCl < nCl; ++iCl) {
985 yDiffLL[iCl] *= rmsYkeepI;
986 zDiffLL[iCl] *= rmsZkeepI;
987 if (yDiffLL[iCl] * yDiffLL[iCl] + zDiffLL[iCl] * zDiffLL[iCl] > mParams->
maxStdDevMA) {
990 yAcc[nAcc++] =
params.dy[iCl];
997 for (
int i = 0;
i < nAcc; ++
i) {
998 average += yDiffLong[
i];
999 rms += yDiffLong[
i] * yDiffLong[
i];
1002 rmsLong = rms / nAcc - average * average;
1003 rmsLong = (rmsLong > 0) ? std::sqrt(rmsLong) : 0.f;
1008void TrackInterpolation::diffToLocLine(
const int np,
int idxOffset,
const std::array<float, param::NPadRows>&
x,
const std::array<float, param::NPadRows>&
y, std::array<float, param::NPadRows>& diffY)
const
1015 std::vector<float> sumX1vec(np + 1);
1016 std::vector<float> sumX2vec(np + 1);
1017 std::vector<float> sumY1vec(np + 1);
1018 std::vector<float> sumXYvec(np + 1);
1019 auto sumX1 = &(sumX1vec[1]);
1020 auto sumX2 = &(sumX2vec[1]);
1021 auto sumY1 = &(sumY1vec[1]);
1022 auto sumXY = &(sumXYvec[1]);
1025 for (
int iCl = 0; iCl < np; ++iCl) {
1026 int idx = iCl + idxOffset;
1027 sumX1[iCl] = sumX1[iCl - 1] +
x[idx];
1028 sumX2[iCl] = sumX2[iCl - 1] +
x[idx] *
x[idx];
1029 sumY1[iCl] = sumY1[iCl - 1] +
y[idx];
1030 sumXY[iCl] = sumXY[iCl - 1] +
x[idx] *
y[idx];
1033 for (
int iCl = 0; iCl < np; ++iCl) {
1034 int iClLeft = iCl - mParams->
nMAShort;
1035 int iClRight = iCl + mParams->
nMAShort;
1039 if (iClRight >= np) {
1042 int nPoints = iClRight - iClLeft;
1043 if (nPoints < mParams->nMAShort) {
1046 float nPointsInv = 1.f / nPoints;
1047 int iClLeftP = iClLeft - 1;
1048 int iClCurrP = iCl - 1;
1050 float sX1 = sumX1[iClRight] - sumX1[iClLeftP] - (sumX1[iCl] - sumX1[iClCurrP]);
1051 float sX2 = sumX2[iClRight] - sumX2[iClLeftP] - (sumX2[iCl] - sumX2[iClCurrP]);
1052 float sY1 = sumY1[iClRight] - sumY1[iClLeftP] - (sumY1[iCl] - sumY1[iClCurrP]);
1053 float sXY = sumXY[iClRight] - sumXY[iClLeftP] - (sumXY[iCl] - sumXY[iClCurrP]);
1054 float det = sX2 - nPointsInv * sX1 * sX1;
1055 if (fabsf(det) < 1e-12f) {
1058 float slope = (sXY - nPointsInv * sX1 * sY1) / det;
1059 float offset = nPointsInv * sY1 - nPointsInv *
slope * sX1;
1060 diffY[iCl + idxOffset] =
y[iCl + idxOffset] -
slope *
x[iCl + idxOffset] -
offset;
1067 std::vector<float> sumVec(np + 1);
1068 auto sum = &(sumVec[1]);
1069 for (
int i = 0;
i < np; ++
i) {
1072 for (
int i = 0;
i < np; ++
i) {
1082 int nPoints = iRight - iLeft;
1083 if (nPoints < mParams->nMALong) {
1087 float movingAverage = (
sum[iRight] -
sum[iLeft - 1] - (
sum[
i] -
sum[
i - 1])) / nPoints;
1088 diffMA[
i] =
y[
i] - movingAverage;
1095 mTrackDataCompact.clear();
1096 mTrackDataExtended.clear();
1098 mTrackDataUnfiltered.clear();
1099 mClResUnfiltered.clear();
1100 mGIDsSuccess.clear();
1101 for (
auto&
vec : mTrackIndices) {
1106 mTrackTimes.clear();
1114 if (
v.refVDrift != mTPCVDriftRef) {
1115 mTPCVDriftRef =
v.refVDrift;
1116 mTPCDriftTimeOffsetRef =
v.refTimeOffset;
1117 LOGP(info,
"Imposing reference VDrift={}/TDrift={} for TPC residuals extraction", mTPCVDriftRef, mTPCDriftTimeOffsetRef);
std::string asString(TDataMember const &dm, char *pointer)
Definition of the parameter class for the detector electronics.
Definition of the TrackInterpolation class.
Definition of the TrackResiduals class.
calibration data from laser track calibration
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const ParameterElectronics & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
void prepareInputTrackSample(const o2::globaltracking::RecoContainer &inp)
Prepare input track sample (not relying on CreateTracksVariadic functionality)
bool isInputTrackAccepted(const o2::dataformats::GlobalTrackID &gid, const o2::globaltracking::RecoContainer::GlobalIDSet &gidTable, const o2::dataformats::PrimaryVertex &pv) const
Check if input track passes configured cuts.
void diffToMA(const int np, const std::array< float, param::NPadRows > &y, std::array< float, param::NPadRows > &diffMA) const
For a given set of points, calculate their deviation from the moving average (build from the neighbou...
void diffToLocLine(const int np, int idxOffset, const std::array< float, param::NPadRows > &x, const std::array< float, param::NPadRows > &y, std::array< float, param::NPadRows > &diffY) const
For a given set of points, calculate the differences from each point to the fitted lines from all oth...
void extrapolateTrack(int iSeed)
@ ExtIn
extrapolation inwards of TRD/TOF track
@ Int
interpolation (mean positions of both extrapolations)
@ ExtOut
extrapolation outwards of ITS track
o2::dataformats::GlobalTrackID::Source findValidSource(const o2::dataformats::GlobalTrackID::mask_t mask, const o2::dataformats::GlobalTrackID::Source src) const
For given vertex track source which is not in mSourcesConfigured find the seeding source which is ena...
float checkResiduals(const TrackData &trk, TrackParams ¶ms, const std::vector< TPCClusterResiduals > &clsRes) const
void interpolateTrack(int iSeed)
bool compareToHelix(const TrackData &trk, TrackParams ¶ms, const std::vector< TPCClusterResiduals > &clsRes) const
void process()
Main processing function.
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
bool isTrackSelected(const o2::track::TrackParCov &trk) const
Given the defined downsampling factor tsalisThreshold check if track is selected.
void reset()
Reset cache and output vectors.
bool outlierFiltering(const TrackData &trk, TrackParams ¶ms, const std::vector< TPCClusterResiduals > &clsRes) const
void init(o2::dataformats::GlobalTrackID::mask_t src, o2::dataformats::GlobalTrackID::mask_t srcMap)
Initialize everything, set the requested track sources.
bool validateTrack(const TrackData &trk, TrackParams ¶ms, const std::vector< TPCClusterResiduals > &clsRes) const
static bool fitPoly1(int nCl, std::array< float, param::NPadRows > &x, std::array< float, param::NPadRows > &y, std::array< float, 2 > &res)
static void fitCircle(int nCl, std::array< float, param::NPadRows > &x, std::array< float, param::NPadRows > &y, float &xc, float &yc, float &r, std::array< float, param::NPadRows > &residHelixY)
static Geometry * instance()
void recalcTrkltCov(const float tilt, const float snp, const float rowSize, std::array< float, 3 > &cov) const
Recalculate tracklet covariance based on phi angle of related track.
float getZCorrCoeffNRC() const
Get tracklet z correction coefficient for track-eta based corraction.
void setBfield(float bz)
Load parameterization for given magnetic field.
GLuint GLuint GLfloat weight
GLenum const GLfloat * params
GLdouble GLdouble GLdouble z
constexpr float SectorSpanRad
constexpr float LightSpeedCm2S
constexpr double MassPionCharged
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 angle2Sector(float phi)
float sector2Angle(int sect)
constexpr int MAXGLOBALPADROW
Global TPC definitions and constants.
Enum< T >::Iterator begin(Enum< T >)
DataT sum(const Vector< DataT, N > &a)
constexpr int NLAYER
the number of layers
constexpr int NSTACK
the number of stacks per sector
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
gsl::span< const o2::trd::CalibratedTracklet > getTRDCalibratedTracklets() const
auto getITSTracksClusterRefs() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
const o2::tpc::ClusterNativeAccess & getTPCClusters() const
auto getTPCTracksClusterRefs() const
auto getPrimaryVertexMatchedTrackRefs() const
auto getITSClustersPatterns() const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
auto getTOFClusters() const
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
auto getITSTPCTRDTrack(GTrackID id) const
std::array< GTrackID, GTrackID::NSources > GlobalIDSet
auto getITSClusters() const
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
const o2::dataformats::MatchInfoTOF & getTOFMatch(GTrackID id) const
static bool downsampleTsallisCharged(float pt, float factorPt, float sqrts, float &weight, float rnd, float mass=0.13957)
float maxRejFrac
if the fraction of rejected clusters of a track is higher, the full track is invalidated
float maxDCA
DCA cut value in cm.
float maxDevHelixZ
max deviation in Z for clusters wrt helix fit
int nMALong
number of points to be used for moving average (long range)
float maxTPCChi2
cut on TPC reduced chi2
float minPtNoOuterPoint
minimum pt for ITS-TPC tracks to be considered for extrapolation
int minTRDNTrklts
min number of TRD space points
int nMAShort
number of points to be used for estimation of distance from local line (short range)
float maxDevHelixY
max deviation in Y for clusters wrt helix fit
float maxStdDevMA
max cluster std. deviation (Y^2 + Z^2) wrt moving average to accept
bool skipOutlierFiltering
if set, the outlier filtering will not be applied at all
bool ignoreNonPVContrib
flag if tracks which did not contribute to the PV should be ignored or not
int minITSNClsNoOuterPoint
min number of ITS clusters if no hit in TRD or TOF exists
int minTPCNCls
min number of TPC clusters
float tsalisThreshold
in case the sampling functions returns a value smaller than this the track is discarded (1....
float maxStep
maximum step for propagation
int minTOFTRDPVContributors
min contributors from TRD or TOF (fast detectors) to consider tracks of this PV
bool enableTrackDownsampling
flag if track sampling shall be enabled or not
float maxQ2Pt
max fitted q/pt for a track to be used for calibration
float sigYZ2TOF
for now assume cluster error for TOF equal for all clusters in both Y and Z
int minNumberOfAcceptedResiduals
min number of accepted residuals for
float maxRMSLong
maximum variance of the cluster residuals wrt moving avarage for a track to be considered
int minITSNCls
min number of ITS clusters
float maxSnp
max snp when propagating tracks
float maxITSChi2
cut on ITS reduced chi2
bool writeUnfiltered
if set, all residuals and track parameters will be aggregated and dumped additionally without outlier...
int minNCl
min number of clusters in a track to be used for calibration
int minTPCNClsNoOuterPoint
min number of TPC clusters if no hit in TRD or TOF exists
Structure filled for each track with track quality information and a vector with TPCClusterResiduals.
float chi2TRD
chi2 of TRD track
float dEdxTPC
TPC dEdx information.
unsigned short nTrkltsTRD
number of attached TRD tracklets
unsigned short clAvailTOF
whether or not track seed has a matched TOF cluster
unsigned short nClsITS
number of attached ITS clusters
o2::dataformats::RangeReference clIdx
index of first cluster residual and total number of cluster residuals of this track
float chi2TPC
chi2 of TPC track
unsigned short nClsTPC
number of attached TPC clusters
o2::dataformats::GlobalTrackID gid
global track ID for seeding track
o2::track::TrackPar par
ITS track at inner TPC radius.
float chi2ITS
chi2 of ITS track
Structure for on-the-fly re-calculated track parameters at the validation stage.
std::vector< o2::ctf::BufferType > vec
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::uniform_int_distribution< unsigned long long > distr