24#include "TMatrixDSym.h"
25#include "TDecompChol.h"
33#include "TStopwatch.h"
40#include <fairlogger/Logger.h>
53 mSmoothPol2[
VoxX] =
true;
54 mSmoothPol2[
VoxF] =
true;
58 mIsInitialized =
true;
65 LOG(info) <<
"Initialization complete";
72 LOG(error) <<
"Binning already initialized, not changing y/x binning";
77 LOGP(info,
"Empty binning provided, will use default uniform y/x binning with {} bins", mNY2XBins);
79 }
else if (
binning.size() == 1) {
82 LOGP(info,
"Setting uniform binning for y/x with {} bins",
bins - 1);
86 const int nBins =
binning.size() - 1;
87 if (std::abs(
binning[0] + 1.f) > param::sEps || std::abs(
binning[nBins] - 1.f) > param::sEps) {
88 LOG(error) <<
"Provided binning for y/x not in range -1 to 1: " <<
binning[0] <<
" - " <<
binning[nBins] <<
". Not changing y/x binning";
92 LOGP(info,
"Setting custom binning for y/x with {} bins", nBins);
94 mUniformBins[
VoxF] =
false;
97 mY2XBinsCenter.clear();
98 for (
int iBin = 0; iBin < nBins; ++iBin) {
100 mY2XBinsDI.push_back(.5f / mY2XBinsDH[iBin]);
101 mY2XBinsCenter.push_back(
binning[iBin] + mY2XBinsDH[iBin]);
102 LOGF(info,
"Bin %i: center (%.3f), half bin width (%.3f)", iBin, mY2XBinsCenter.back(), mY2XBinsDH.back());
109 if (mIsInitialized) {
110 LOG(error) <<
"Binning already initialized, not changing z/x binning";
115 LOGP(info,
"Empty binning provided, will use default uniform z/x binning with {} bins", mNZ2XBins);
117 }
else if (
binning.size() == 1) {
120 LOGP(info,
"Setting uniform binning for z/x with {} bins",
bins);
124 int nBins =
binning.size() - 1;
125 if (std::abs(
binning[0]) > param::sEps || std::abs(
binning[nBins] - 1.f) > param::sEps) {
126 LOG(error) <<
"Provided binning for z/x not in range 0 to 1: " <<
binning[0] <<
" - " <<
binning[nBins] <<
". Not changing z/x binning";
130 LOGP(info,
"Setting custom binning for z/x with {} bins", nBins);
132 mUniformBins[
VoxZ] =
false;
135 mZ2XBinsCenter.clear();
137 LOGP(info,
"Using maxZ2X {} for setZ2XBinning", maxZ2X);
138 for (
int iBin = 0; iBin < nBins; ++iBin) {
139 mZ2XBinsDH.push_back(.5f * (
binning[iBin + 1] -
binning[iBin]) * maxZ2X);
140 mZ2XBinsDI.push_back(.5f / mZ2XBinsDH[iBin]);
141 mZ2XBinsCenter.push_back(
binning[iBin] * maxZ2X + mZ2XBinsDH[iBin]);
142 LOGF(info,
"Bin %i: center (%.3f), half bin width (%.3f)", iBin, mZ2XBinsCenter.back(), mZ2XBinsDH.back());
152 if (mNXBins > 0 && mNXBins < param::NPadRows) {
154 LOGF(info,
"X-binning is uniform with %i bins from %.2f to %.2f", mNXBins, param::MinX, param::MaxX);
155 mDXI = mNXBins / (param::MaxX - param::MinX);
157 mUniformBins[
VoxX] =
true;
160 LOGF(info,
"X-binning is per pad-row");
161 mNXBins = param::NPadRows;
162 mUniformBins[
VoxX] =
false;
163 mDX = param::RowDX[0];
168 mMaxY2X.resize(mNXBins);
169 mDY2XI.resize(mNXBins);
170 mDY2X.resize(mNXBins);
172 for (
int ix = 0; ix < mNXBins; ++ix) {
175 mDY2XI[ix] = mNY2XBins / (2.f * mMaxY2X[ix]);
176 mDY2X[ix] = 1.f / mDY2XI[ix];
178 if (mUniformBins[
VoxF]) {
179 LOGF(info,
"Y/X-binning is uniform with %i bins from -MaxY2X to +MaxY2X (values depend on X-bin)", mNY2XBins);
180 for (
int ip = 0; ip < mNY2XBins; ++ip) {
181 mY2XBinsDH.push_back(1.f / mNY2XBins);
182 mY2XBinsDI.push_back(.5f / mY2XBinsDH[ip]);
183 mY2XBinsCenter.push_back(-1.f + (ip + 0.5f) * 2.f * mY2XBinsDH[ip]);
184 LOGF(info,
"Bin %i: center (%.3f), half bin width (%.3f)", ip, mY2XBinsCenter.back(), mY2XBinsDH.back());
189 mDZ2XI = mNZ2XBins / mMaxZ2X;
190 mDZ2X = 1.0f / mDZ2XI;
191 if (mUniformBins[
VoxZ]) {
192 LOGF(info,
"Z/X-binning is uniform with %i bins from 0 to %f", mNZ2XBins, mMaxZ2X);
193 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
194 mZ2XBinsDH.push_back(.5f * mDZ2X);
195 mZ2XBinsDI.push_back(mDZ2XI);
196 mZ2XBinsCenter.push_back((iz + 0.5f) * mDZ2X);
197 LOGF(info,
"Bin %i: center (%.3f), half bin width (%.3f)", iz, mZ2XBinsCenter.back(), mZ2XBinsDH.back());
201 mNVoxPerSector = mNY2XBins * mNZ2XBins * mNXBins;
202 LOGF(info,
"Each TPC sector is divided into %i voxels", mNVoxPerSector);
208 if (mInitResultsContainer.test(iSec)) {
211 mInitResultsContainer.set(iSec);
212 mVoxelResults[iSec].resize(mNVoxPerSector);
213 for (
int ix = 0; ix < mNXBins; ++ix) {
214 for (
int ip = 0; ip < mNY2XBins; ++ip) {
215 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
217 VoxRes& resVox = mVoxelResults[iSec][binGlb];
225 LOG(
debug) <<
"initialized the container for the main results";
232 mXBinsIgnore[iSec].reset();
233 std::fill(mVoxelResults[iSec].
begin(), mVoxelResults[iSec].
end(),
VoxRes());
234 std::fill(mValidFracXBins[iSec].
begin(), mValidFracXBins[iSec].
end(), 0);
242 if (
x < param::RowX[param::NRowsAccumulated[0] - 1] + param::RowDX[0]) {
244 ix = (
x - (param::RowX[0] - .5f * param::RowDX[0])) / param::RowDX[0];
249 }
else if (
x >= param::RowX[param::NRowsAccumulated[param::NROCTypes - 2]] - .5f * param::RowDX[param::NROCTypes - 1]) {
251 ix = (
x - (param::RowX[param::NRowsAccumulated[param::NROCTypes - 2]] - .5f * param::RowDX[param::NROCTypes - 1])) / param::RowDX[param::NROCTypes - 1] + param::NRowsAccumulated[param::NROCTypes - 2];
252 if (ix >= param::NPadRows) {
256 }
else if (
x > param::RowX[param::NRowsAccumulated[0]] - .5f * param::RowDX[1] &&
x < param::RowX[param::NRowsAccumulated[1] - 1] + .5f * param::RowDX[1]) {
258 ix = (
x - (param::RowX[param::NRowsAccumulated[0]] - .5f * param::RowDX[1])) / param::RowDX[1] + param::NRowsAccumulated[0];
259 }
else if (
x > param::RowX[param::NRowsAccumulated[1]] - .5f * param::RowDX[2] &&
x < param::RowX[param::NRowsAccumulated[2] - 1] + .5f * param::RowDX[2]) {
261 ix = (
x - (param::RowX[param::NRowsAccumulated[1]] - .5f * param::RowDX[2])) / param::RowDX[2] + param::NRowsAccumulated[1];
272 if (std::abs(
z /
x) > mMaxZ2X) {
281 if (bx < 0 || bx >= mNXBins) {
286 if (bp < 0 || bp >= mNY2XBins) {
299 mKernelType = kernel;
301 mKernelScaleEdge[
VoxX] = scX;
302 mKernelScaleEdge[
VoxF] = scP;
303 mKernelScaleEdge[
VoxZ] = scZ;
305 mKernelWInv[
VoxX] = (bwX > 0) ? 1. / bwX : 1.;
306 mKernelWInv[
VoxF] = (bwP > 0) ? 1. / bwP : 1.;
307 mKernelWInv[
VoxZ] = (bwZ > 0) ? 1. / bwZ : 1.;
311 mStepKern[
VoxX] =
static_cast<int>(nearbyint(bwX + 0.5));
312 mStepKern[
VoxF] =
static_cast<int>(nearbyint(bwP + 0.5));
313 mStepKern[
VoxZ] =
static_cast<int>(nearbyint(bwZ + 0.5));
316 mStepKern[
VoxX] =
static_cast<int>(nearbyint(bwX * 5. + 0.5));
317 mStepKern[
VoxF] =
static_cast<int>(nearbyint(bwP * 5. + 0.5));
318 mStepKern[
VoxZ] =
static_cast<int>(nearbyint(bwZ * 5. + 0.5));
320 LOG(error) <<
"given kernel type is not defined";
323 if (mStepKern[
i] < 1) {
338 std::vector<VoxRes>& secDataTmp = mVoxelResults[iSec];
339 for (
int iVox = 0; iVox < mNVoxPerSector; ++iVox) {
340 secDataTmp[iVox].stat[
VoxX] = statsIn[iVox].meanPos[
VoxX];
341 secDataTmp[iVox].stat[
VoxF] = statsIn[iVox].meanPos[
VoxF];
342 secDataTmp[iVox].stat[
VoxZ] = statsIn[iVox].meanPos[
VoxZ];
343 secDataTmp[iVox].stat[
VoxDim] = statsIn[iVox].nEntries;
350 std::vector<VoxRes>& secDataTmp = mVoxelResults[iSec];
351 for (
int iVox = 0; iVox < mNVoxPerSector; ++iVox) {
352 const auto& voxStat = mVoxStatsIn[iVox];
353 VoxRes& resVox = secDataTmp[iVox];
354 for (
int iDim =
VoxDim; iDim--;) {
355 const auto sumStat = (resVox.
stat[
VoxDim] + voxStat.nEntries);
359 double norm = 1. / sumStat;
360 resVox.
stat[iDim] = (resVox.
stat[iDim] * resVox.
stat[
VoxDim] + voxStat.meanPos[iDim] * voxStat.nEntries) * norm;
369 LOGP(info,
"Processing {} voxel residuals for sector {}", mLocalResidualsIn.size(), iSec);
372 float effT0corr = (iSec <
SECTORSPERSIDE) ? mEffT0Corr : -1. * mEffT0Corr;
373 std::vector<size_t> binData;
374 for (
const auto&
res : mLocalResidualsIn) {
378 std::vector<size_t> binIndices(binData.size());
381 std::vector<VoxRes>& secData = mVoxelResults[iSec];
384 std::vector<float> dyVec;
385 std::vector<float> dzVec;
386 std::vector<float> tgVec;
391 size_t currVoxBin = -1;
392 unsigned int nPointsInVox = 0;
393 unsigned int nProcessed = 0;
394 while (nProcessed < binData.size()) {
396 int idx = binIndices[nProcessed];
397 if (currVoxBin != binData[idx]) {
399 VoxRes& resVox = secData[currVoxBin];
402 currVoxBin = binData[idx];
408 dyVec.push_back(mLocalResidualsIn[idx].dy * param::MaxResid / 0x7fff);
409 dzVec.push_back(mLocalResidualsIn[idx].dz * param::MaxResid / 0x7fff -
410 mEffVdriftCorr * secData[currVoxBin].stat[
VoxZ] * secData[currVoxBin].stat[
VoxX] -
412 tgVec.push_back(mLocalResidualsIn[idx].tgSlp * param::MaxTgSlp / 0x7fff);
419 VoxRes& resVox = secData[currVoxBin];
422 LOG(info) <<
"extracted residuals for sector " << iSec;
425 LOG(info) <<
"number of validated X rows: " << nRowsOK;
427 LOG(warning) <<
"sector " << iSec <<
": all X-bins disabled, abandon smoothing";
439 while (nProcessed < binData.size()) {
440 int idx = binIndices[nProcessed];
441 if (currVoxBin != binData[idx]) {
443 VoxRes& resVox = secData[currVoxBin];
448 currVoxBin = binData[idx];
453 dyVec.push_back(mLocalResidualsIn[idx].dy * param::MaxResid / 0x7fff);
454 tgVec.push_back(mLocalResidualsIn[idx].tgSlp * param::MaxTgSlp / 0x7fff);
460 VoxRes& resVox = secData[currVoxBin];
466 for (
int ix = 0; ix < mNXBins; ++ix) {
470 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
471 for (
int ip = 0; ip < mNY2XBins; ++ip) {
473 VoxRes& resVox = secData[voxBin];
478 LOG(info) <<
"Done processing residuals for sector " << iSec;
485 int nPoints = dy.size();
486 if (nPoints < mParams->minEntriesPerVoxel) {
492 std::array<float, 7> zResults;
494 std::vector<size_t>
indices(dz.size());
500 std::array<float, 2>
res{0.f};
501 std::array<float, 3> err{0.f};
504 LOG(
debug) <<
"failed robust linear fit, sigMAD = " << sigMAD;
507 float corrErr = err[0] * err[2];
508 corrErr = corrErr > 0 ? err[1] / std::sqrt(corrErr) : -999;
512 resVox.
D[
ResZ] = zResults[1];
513 resVox.
E[
ResX] = std::sqrt(err[2]);
514 resVox.
E[
ResY] = std::sqrt(err[0]);
515 resVox.
E[
ResZ] = zResults[4];
522 std::array<float, 7> yResults;
523 std::vector<size_t> indicesY(dy.size());
529 resVox.
D[
ResY] = yResults[1];
530 resVox.
D[
ResZ] = zResults[1];
532 resVox.
E[
ResY] = yResults[4];
533 resVox.
E[
ResZ] = zResults[4];
539 LOGF(
debug,
"D[0]=%.2f, D[1]=%.2f, D[2]=%.2f, E[0]=%.2f, E[1]=%.2f, E[2]=%.2f, EXYCorr=%.4f, dYSigMAD=%.3f, dZSigLTM=%.3f",
549 size_t nPoints = tg.size();
550 LOG(
debug) <<
"processing voxel dispersions for vox " <<
getGlbVoxBin(resVox.
bvox) <<
" with " << nPoints <<
" points";
554 for (
size_t i = nPoints;
i--;) {
558 resVox.
E[
ResD] = resVox.
D[
ResD] / sqrt(2.f * nPoints);
569 mXBinsIgnore[iSec].reset();
570 std::vector<VoxRes>& secData = mVoxelResults[iSec];
572 int cntMaskedFit = 0;
573 int cntMaskedSigma = 0;
576 for (
int ix = 0; ix < mNXBins; ++ix) {
578 for (
int ip = 0; ip < mNY2XBins; ++ip) {
579 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
581 VoxRes& resVox = secData[binGlb];
609 mValidFracXBins[iSec][ix] =
static_cast<float>(cntValid) / (mNY2XBins * mNZ2XBins);
610 LOGP(
debug,
"Sector {}: xBin {} has {} % of voxels valid. Total masked due to fit: {} ,and sigma: {}",
611 iSec, ix, mValidFracXBins[iSec][ix] * 100., cntMaskedFit, cntMaskedSigma);
617 std::array<short, param::NPadRows> badStart;
618 std::array<short, param::NPadRows> badEnd;
619 bool prevBad =
false;
620 float fracBadRows = 0.f;
621 for (
int ix = 0; ix < mNXBins; ++ix) {
623 LOG(
debug) <<
"row " << ix <<
" is bad";
626 badEnd[nBadReg] = ix;
628 badStart[nBadReg] = ix;
629 badEnd[nBadReg] = ix;
642 fracBadRows /= mNXBins;
644 LOG(warning) <<
"sector " << iSec <<
": Fraction of bad X-bins: " << fracBadRows <<
" -> masking whole sector";
645 mXBinsIgnore[iSec].set();
647 for (
int iBad = 0; iBad < nBadReg; ++iBad) {
648 LOG(
debug) <<
"masking bad region " << iBad;
649 short badInReg = badEnd[iBad] - badStart[iBad] + 1;
650 short badInNextReg = iBad < (nBadReg - 1) ? badEnd[iBad] - badStart[iBad] + 1 : 0;
653 for (
int i = 0;
i < badInReg; ++
i) {
654 LOG(
debug) <<
"disabling too large patch in bad region " << iBad <<
", badStart(" << badStart[iBad] <<
"), i(" <<
i <<
")";
655 mXBinsIgnore[iSec].set(badStart[iBad] +
i);
660 for (
int i = badEnd[iBad] + 1;
i < badStart[iBad + 1]; ++
i) {
661 LOG(
debug) <<
"disabling too small good patch before bad region " << iBad + 1 <<
", badStart(" << badEnd[iBad] <<
"), badEnd(" << badStart[iBad + 1] <<
")";
662 mXBinsIgnore[iSec].set(
i);
669 for (
int i = 0;
i < badStart[0]; ++
i) {
670 LOG(
debug) <<
"disabling too small first good patch badStart(0), badEnd(" << badStart[0] <<
")";
671 mXBinsIgnore[iSec].set(
i);
674 if (mXBinsIgnore[iSec].
test(badStart[nBadReg - 1]) && (mNXBins - badEnd[nBadReg - 1] - 1) < mParams->
minGoodXBinsToCover) {
676 for (
int i = badEnd[nBadReg - 1] + 1;
i < mNXBins; ++
i) {
677 LOG(
debug) <<
"disabling too small last good patch badStart(" << badEnd[nBadReg - 1] <<
"), badEnd(" << mNXBins <<
")";
678 mXBinsIgnore[iSec].set(
i);
684 int nMaskedRows = mXBinsIgnore[iSec].count();
685 LOGP(info,
"Sector {}: out of {} voxels {} are masked. {} (low stat), {} (invalid fit) and {} (raw distrib sigma)",
686 iSec, mNVoxPerSector, cntMasked, cntLowStat, cntMaskedFit, cntMaskedSigma);
688 return mNXBins - nMaskedRows;
693 std::vector<VoxRes>& secData = mVoxelResults[iSec];
694 for (
int ix = 0; ix < mNXBins; ++ix) {
698 for (
int ip = 0; ip < mNY2XBins; ++ip) {
699 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
701 VoxRes& resVox = secData[voxBin];
702 resVox.
flags &= ~SmoothDone;
705 mNSmoothingFailedBins[iSec]++;
713 for (
int ix = 0; ix < mNXBins; ++ix) {
717 for (
int ip = 0; ip < mNY2XBins; ++ip) {
718 for (
int iz = 0; iz < mNZ2XBins; ++iz) {
720 VoxRes& resVox = secData[voxBin];
726 if (mDoAdhocCorrectionZ2X) {
735 if (mAdhocScalingX[iSec >= 18] != 0) {
736 const float aDX = resVox.
DS[
ResX] * mAdhocScalingX[iSec >= 18];
737 resVox.
D[
ResX] += aDX;
741 resVox.
D[
ResZ] += aDX * z2x;
742 resVox.
DS[
ResZ] += aDX * z2x;
754 std::array<int, VoxDim> minPointsDir{0};
755 const float kTrialStep = 0.5;
756 std::array<bool, ResDim> doDim{
false};
758 doDim[
i] = (whichDim & (0x1 <<
i)) > 0;
764 int matSize = sSmtLinDim;
767 if (mSmoothPol2[
i]) {
775 std::vector<VoxRes>& secData = mVoxelResults[iSec];
777 VoxRes& voxCenter = secData[binCenter];
778 LOG(
debug) <<
"getting smooth estimate around voxel " << binCenter;
782 std::array<std::array<double, sMaxSmtDim*(sMaxSmtDim + 1) / 2>,
ResDim> cmat;
783 int maxNeighb = 10 * 10 * 10;
784 std::vector<VoxRes*> currVox;
785 currVox.reserve(maxNeighb);
786 std::vector<float> currCache;
787 currCache.reserve(maxNeighb *
VoxHDim);
789 std::array<int, VoxDim> maxTrials;
790 maxTrials[
VoxZ] = mNZ2XBins / 2;
791 maxTrials[
VoxF] = mNY2XBins / 2;
794 std::array<int, VoxDim> trial{0};
797 std::fill(mLastSmoothingRes.begin(), mLastSmoothingRes.end(), 0);
798 memset(&cmat[0][0], 0,
sizeof(cmat));
802 float stepX = mStepKern[
VoxX] * (1. + kTrialStep * trial[
VoxX]);
803 float stepF = mStepKern[
VoxF] * (1. + kTrialStep * trial[
VoxF]);
804 float stepZ = mStepKern[
VoxZ] * (1. + kTrialStep * trial[
VoxZ]);
808 stepX += kTrialStep * mStepKern[
VoxX];
809 stepF += kTrialStep * mStepKern[
VoxF];
810 stepZ += kTrialStep * mStepKern[
VoxZ];
814 float kWXI =
getDXI(ix0) * mKernelWInv[
VoxX] * mStepKern[
VoxX] / stepX;
815 float kWFI =
getDY2XI(ix0, ip0) * mKernelWInv[
VoxF] * mStepKern[
VoxF] / stepF;
817 int iStepX =
static_cast<int>(nearbyint(stepX + 0.5));
818 int iStepF =
static_cast<int>(nearbyint(stepF + 0.5));
819 int iStepZ =
static_cast<int>(nearbyint(stepZ + 0.5));
820 int ixMin = ix0 - iStepX;
821 int ixMax = ix0 + iStepX;
824 ixMax = std::min(
static_cast<int>(nearbyint(ix0 + stepX * mKernelScaleEdge[
VoxX])), mNXBins - 1);
825 kWXI /= mKernelScaleEdge[
VoxX];
827 if (ixMax >= mNXBins) {
829 ixMin = std::max(
static_cast<int>(nearbyint(ix0 - stepX * mKernelScaleEdge[
VoxX])), 0);
830 kWXI /= mKernelScaleEdge[
VoxX];
833 int ipMin = ip0 - iStepF;
834 int ipMax = ip0 + iStepF;
837 ipMax = std::min(
static_cast<int>(nearbyint(ip0 + stepF * mKernelScaleEdge[
VoxF])), mNY2XBins - 1);
838 kWFI /= mKernelScaleEdge[
VoxF];
840 if (ipMax >= mNY2XBins) {
841 ipMax = mNY2XBins - 1;
842 ipMin = std::max(
static_cast<int>(nearbyint(ip0 - stepF * mKernelScaleEdge[
VoxF])), 0);
843 kWFI /= mKernelScaleEdge[
VoxF];
846 int izMin = iz0 - iStepZ;
847 int izMax = iz0 + iStepZ;
850 izMax = std::min(
static_cast<int>(nearbyint(iz0 + stepZ * mKernelScaleEdge[
VoxZ])), mNZ2XBins - 1);
851 kWZI /= mKernelScaleEdge[
VoxZ];
853 if (izMax >= mNZ2XBins) {
854 izMax = mNZ2XBins - 1;
855 izMin = std::max(
static_cast<int>(nearbyint(iz0 - stepZ * mKernelScaleEdge[
VoxZ])), 0);
856 kWZI /= mKernelScaleEdge[
VoxZ];
859 std::vector<unsigned short> nOccX(ixMax - ixMin + 1, 0);
860 std::vector<unsigned short> nOccF(ipMax - ipMin + 1, 0);
861 std::vector<unsigned short> nOccZ(izMax - izMin + 1, 0);
863 int nbCheck = (ixMax - ixMin + 1) * (ipMax - ipMin + 1) * (izMax - izMin + 1);
864 if (nbCheck >= maxNeighb) {
865 maxNeighb = nbCheck + 100;
866 currCache.reserve(maxNeighb *
VoxHDim);
867 currVox.reserve(maxNeighb);
869 std::array<double, 3> u2Vec;
872 for (
int ix = ixMin; ix <= ixMax; ++ix) {
873 for (
int ip = ipMin; ip <= ipMax; ++ip) {
874 for (
int iz = izMin; iz <= izMax; ++iz) {
876 VoxRes& voxNb = secData[binNb];
887 float dxw = dx * kWXI;
888 float dfw = df * kWFI;
889 float dzw = dz * kWZI;
890 u2Vec[0] = dxw * dxw;
891 u2Vec[1] = dfw * dfw;
892 u2Vec[2] = dzw * dzw;
894 if (kernelWeight < 1e-6) {
901 currVox[nbOK] = &voxNb;
912 std::array<int, VoxDim> nPoints{0};
913 for (
int i = ixMax - ixMin + 1;
i--;) {
918 for (
int i = ipMax - ipMin + 1;
i--;) {
923 for (
int i = izMax - izMin + 1;
i--;) {
928 bool enoughPoints =
true;
929 std::array<bool, VoxDim> incrDone{
false};
931 if (nPoints[
i] < minPointsDir[
i]) {
933 enoughPoints =
false;
934 if (trial[
i] < maxTrials[
i] && !incrDone[
i]) {
938 }
else if (trial[
i] == maxTrials[
i]) {
941 if (
i !=
j && trial[
j] < maxTrials[
j] && !incrDone[
j]) {
951 if (!(incrDone[
VoxX] || incrDone[
VoxF] || incrDone[
VoxZ])) {
952 LOG(error) << fmt::format(
"trial limit reached, skipping this voxel: incrDone[VoxX] {}, incrDone[VoxF] {}, incrDone[VoxZ] {}", incrDone[
VoxX], incrDone[
VoxF], incrDone[
VoxZ]);
955 LOG(
debug) <<
"sector " << iSec <<
": increasing filter bandwidth around voxel " << binCenter;
963 for (
int iNb = 0; iNb < nbOK; ++iNb) {
968 double dxi2 = dxi * dxi;
969 double dfi2 = dfi * dfi;
970 double dzi2 = dzi * dzi;
971 const VoxRes* voxNb = currVox[iNb];
972 for (
int iDim = 0; iDim <
ResDim; ++iDim) {
976 double vi = voxNb->
D[iDim];
978 if (mUseErrInSmoothing && std::abs(voxNb->
E[iDim]) > 1e-6) {
980 wi /= (voxNb->
E[iDim] * voxNb->
E[iDim]);
982 std::array<double, sMaxSmtDim*(sMaxSmtDim + 1) / 2>& cmatD = cmat[iDim];
983 double* rhsD = &mLastSmoothingRes[iDim * sMaxSmtDim];
984 unsigned short iMat = 0;
985 unsigned short iRhs = 0;
988 rhsD[iRhs++] += wi * vi;
990 cmatD[iMat++] += wi * dxi;
991 cmatD[iMat++] += wi * dxi2;
992 rhsD[iRhs++] += wi * dxi * vi;
994 cmatD[iMat++] += wi * dfi;
995 cmatD[iMat++] += wi * dxi * dfi;
996 cmatD[iMat++] += wi * dfi2;
997 rhsD[iRhs++] += wi * dfi * vi;
999 cmatD[iMat++] += wi * dzi;
1000 cmatD[iMat++] += wi * dxi * dzi;
1001 cmatD[iMat++] += wi * dfi * dzi;
1002 cmatD[iMat++] += wi * dzi2;
1003 rhsD[iRhs++] += wi * dzi * vi;
1006 if (mSmoothPol2[
VoxX]) {
1007 cmatD[iMat++] += wi * dxi2;
1008 cmatD[iMat++] += wi * dxi * dxi2;
1009 cmatD[iMat++] += wi * dfi * dxi2;
1010 cmatD[iMat++] += wi * dzi * dxi2;
1011 cmatD[iMat++] += wi * dxi2 * dxi2;
1012 rhsD[iRhs++] += wi * dxi2 * vi;
1014 if (mSmoothPol2[
VoxF]) {
1015 cmatD[iMat++] += wi * dfi2;
1016 cmatD[iMat++] += wi * dxi * dfi2;
1017 cmatD[iMat++] += wi * dfi * dfi2;
1018 cmatD[iMat++] += wi * dzi * dfi2;
1019 cmatD[iMat++] += wi * dxi2 * dfi2;
1020 cmatD[iMat++] += wi * dfi2 * dfi2;
1021 rhsD[iRhs++] += wi * dfi2 * vi;
1023 if (mSmoothPol2[
VoxZ]) {
1024 cmatD[iMat++] += wi * dzi2;
1025 cmatD[iMat++] += wi * dxi * dzi2;
1026 cmatD[iMat++] += wi * dfi * dzi2;
1027 cmatD[iMat++] += wi * dzi * dzi2;
1028 cmatD[iMat++] += wi * dxi2 * dzi2;
1029 cmatD[iMat++] += wi * dfi2 * dzi2;
1030 cmatD[iMat++] += wi * dzi2 * dzi2;
1031 rhsD[iRhs++] += wi * dzi2 * vi;
1040 TMatrixDSym matrix(matSize);
1041 TDecompChol chol(matSize);
1042 TVectorD rhsVec(matSize);
1043 for (
int iDim = 0; iDim <
ResDim; ++iDim) {
1048 std::array<double, sMaxSmtDim*(sMaxSmtDim + 1) / 2>& cmatD = cmat[iDim];
1049 double* rhsD = &mLastSmoothingRes[iDim * sMaxSmtDim];
1054 matrix(++
row, 0) = cmatD[++iMat];
1055 matrix(++
row, 0) = cmatD[++iMat];
1056 matrix(
row, 1) = cmatD[++iMat];
1057 matrix(0,
row) = matrix(
row, 0);
1058 matrix(++
row, 0) = cmatD[++iMat];
1059 matrix(
row, 1) = cmatD[++iMat];
1060 matrix(
row, 2) = cmatD[++iMat];
1061 matrix(0,
row) = matrix(
row, 0);
1062 matrix(1,
row) = matrix(
row, 1);
1063 matrix(++
row, 0) = cmatD[++iMat];
1064 matrix(
row, 1) = cmatD[++iMat];
1065 matrix(
row, 2) = cmatD[++iMat];
1066 matrix(
row, 3) = cmatD[++iMat];
1067 matrix(0,
row) = matrix(
row, 0);
1068 matrix(1,
row) = matrix(
row, 1);
1069 matrix(2,
row) = matrix(
row, 2);
1071 if (mSmoothPol2[
VoxX]) {
1072 const int colLim = (++
row) + 1;
1073 for (
int iCol = 0; iCol < colLim; ++iCol) {
1074 matrix(
row, iCol) = cmatD[++iMat];
1075 matrix(iCol,
row) = matrix(
row, iCol);
1078 if (mSmoothPol2[
VoxF]) {
1079 const int colLim = (++
row) + 1;
1080 for (
int iCol = 0; iCol < colLim; ++iCol) {
1081 matrix(
row, iCol) = cmatD[++iMat];
1082 matrix(iCol,
row) = matrix(
row, iCol);
1085 if (mSmoothPol2[
VoxZ]) {
1086 const int colLim = (++
row) + 1;
1087 for (
int iCol = 0; iCol < colLim; ++iCol) {
1088 matrix(
row, iCol) = cmatD[++iMat];
1089 matrix(iCol,
row) = matrix(
row, iCol);
1092 rhsVec.SetElements(rhsD);
1093 chol.SetMatrix(matrix);
1095 fitRes = chol.Solve(rhsVec);
1100 LOG(error) <<
"solution for smoothing failed, trying to increase filter bandwidth";
1103 res[iDim] = rhsVec[0];
1116 for (
size_t i = u2vec.size();
i--;) {
1120 w *= 3. / 4. * (1. - u2vec[
i]);
1124 for (
size_t i = u2vec.size();
i--;) {
1141 if (
x.size() !=
y.size()) {
1142 LOG(error) <<
"x and y must not have different sizes for fitPoly1Robust (" <<
x.size() <<
" != " <<
y.size() <<
")";
1144 size_t nPoints =
x.size();
1149 std::array<float, 7> yResults;
1150 std::vector<size_t> indY(nPoints);
1159 int nPointsUsed = std::lrint(yResults[0]);
1160 int vecOffset = std::lrint(yResults[5]);
1163 medFit(nPointsUsed, vecOffset,
x,
y,
a,
b, err);
1165 std::vector<float> ycm(nPoints);
1166 for (
size_t i = nPoints;
i-- > 0;) {
1167 ycm[
i] =
y[
i] - (
a +
b *
x[
i]);
1169 std::vector<size_t>
indices(nPoints);
1176 float sigMAD =
getMAD2Sigma({ycm.begin() + vecOffset, ycm.begin() + vecOffset + nPointsUsed});
1182 nPointsUsed = std::lrint(yResults[0]);
1183 vecOffset = std::lrint(yResults[5]);
1184 medFit(nPointsUsed, vecOffset,
x,
y,
a,
b, err);
1195 float aa,
bb, chi2 = 0.f;
1198 err[0] = err[1] = err[2] = 999.f;
1202 float sx = 0.f, sxx = 0.f, sy = 0.f, sxy = 0.f;
1209 float del = nPoints * sxx - sx * sx;
1210 float delI = 1. / del;
1211 aa = (sxx * sy - sx * sxy) * delI;
1212 bb = (nPoints * sxy - sx * sy) * delI;
1213 err[0] = sxx * delI;
1215 err[2] = nPoints * delI;
1218 float tmp =
y[
j] - (aa +
bb *
x[
j]);
1221 float sigb = std::sqrt(chi2 * delI);
1225 float b2 =
bb + std::copysign(3.f * sigb, f1);
1227 if (std::abs(f1 - f2) < sFloatEps) {
1232 while (f1 * f2 > 0.f) {
1233 bb = b2 + 1.6f * (b2 - b1);
1240 while (std::abs(b2 - b1) > sigb) {
1241 bb = b1 + .5f * (b2 - b1);
1242 if (
bb == b1 ||
bb == b2) {
1246 if (
f * f1 >= .0f) {
1263 std::vector<float> vecTmp(nPoints);
1265 for (
int j = nPoints;
j-- > 0;) {
1268 int nPointsHalf = nPoints / 2;
1270 for (
int i = 1;
i < nPoints;
i++) {
1271 float v = vecTmp[
i];
1274 if (vecTmp[
j] >
v) {
1275 vecTmp[
j + 1] = vecTmp[
j];
1282 aa = (nPoints & 0x1) ? vecTmp[nPointsHalf] : .5f * (vecTmp[nPointsHalf - 1] + vecTmp[nPointsHalf]);
1284 std::vector<float>::iterator nth = vecTmp.begin() + vecTmp.size() / 2;
1285 if (nPoints & 0x1) {
1286 std::nth_element(vecTmp.begin(), nth, vecTmp.end());
1289 std::nth_element(vecTmp.begin(), nth - 1, vecTmp.end());
1290 std::nth_element(nth, nth, vecTmp.end());
1291 aa = 0.5 * (*(nth - 1) + *(nth));
1295 for (
int j = nPoints;
j-- > 0;) {
1300 if (std::abs(d) > sFloatEps) {
1328 mid = (l +
ir) >> 1;
1377 int nPoints =
data.size();
1384 std::vector<float>::iterator nth =
data.begin() +
data.size() / 2;
1385 if (nPoints & 0x1) {
1386 std::nth_element(
data.begin(), nth,
data.end());
1387 medianOfData = *nth;
1389 std::nth_element(
data.begin(), nth - 1,
data.end());
1390 std::nth_element(nth, nth,
data.end());
1391 medianOfData = .5f * (*(nth - 1) + (*nth));
1400 float medianOfAbsDeviations;
1401 if (nPoints & 0x1) {
1402 std::nth_element(
data.begin(), nth,
data.end());
1403 medianOfAbsDeviations = *nth;
1405 std::nth_element(
data.begin(), nth - 1,
data.end());
1406 std::nth_element(nth, nth,
data.end());
1407 medianOfAbsDeviations = .5f * (*(nth - 1) + (*nth));
1411 return k * medianOfAbsDeviations;
1418 double xMean = 0., yMean = 0.;
1419 int ncl =
params.points.size();
1420 for (
const auto& pnt :
params.points) {
1427 double su2 = 0., sv2 = 0., suv = 0., su3 = 0., sv3 = 0., su2v = 0., suv2 = 0.;
1428 for (
const auto& pnt :
params.points) {
1429 double ui = pnt.xLab - xMean;
1430 double vi = pnt.yLab - yMean;
1431 double ui2 = ui * ui;
1432 double vi2 = vi * vi;
1441 double rhsU = .5f * (su3 + suv2);
1442 double rhsV = .5f * (sv3 + su2v);
1443 double det = su2 * sv2 - suv * suv;
1444 double uc = (rhsU * sv2 - rhsV * suv) / det;
1445 double vc = (su2 * rhsV - suv * rhsU) / det;
1446 double r2 = uc * uc + vc * vc + (su2 + sv2) / ncl;
1447 params.xcLab = uc + xMean;
1448 params.ycLab = vc + yMean;
1451 for (
auto& pnt :
params.points) {
1452 double dx = pnt.xLab -
params.xcLab;
1453 double dxr = r2 - dx * dx;
1454 double ys = dxr > 0 ? sqrt(dxr) : 0.f;
1455 double dy = pnt.yLab -
params.ycLab;
1456 double dysp = dy - ys;
1457 double dysm = dy + ys;
1458 pnt.residHelixY = std::abs(dysp) < std::abs(dysm) ? dysp : dysm;
1462void 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)
1469 for (
int i = nCl;
i--;) {
1476 float su2 = 0.f, sv2 = 0.f, suv = 0.f, su3 = 0.f, sv3 = 0.f, su2v = 0.f, suv2 = 0.f;
1477 for (
int i = nCl;
i--;) {
1478 float ui =
x[
i] - xMean;
1479 float vi =
y[
i] - yMean;
1480 float ui2 = ui * ui;
1481 float vi2 = vi * vi;
1490 float rhsU = .5f * (su3 + suv2);
1491 float rhsV = .5f * (sv3 + su2v);
1492 float det = su2 * sv2 - suv * suv;
1493 float uc = (rhsU * sv2 - rhsV * suv) / det;
1494 float vc = (su2 * rhsV - suv * rhsU) / det;
1495 float r2 = uc * uc + vc * vc + (su2 + sv2) / nCl;
1500 for (
int i = nCl;
i--;) {
1501 float dx =
x[
i] - xc;
1502 float dxr = r2 - dx * dx;
1503 float ys = dxr > 0 ? sqrt(dxr) : 0.f;
1504 float dy =
y[
i] - yc;
1505 float dysp = dy - ys;
1506 float dysm = dy + ys;
1507 residHelixY[
i] = std::abs(dysp) < std::abs(dysm) ? dysp : dysm;
1518 int ncl =
params.points.size();
1523 double sumX = 0., sumY = 0., sumXY = 0., sumX2 = 0., nInv = 1. / ncl;
1524 for (
const auto& pnt :
params.points) {
1527 sumXY += pnt.sPath * pnt.zTrk;
1528 sumX2 += pnt.sPath * pnt.sPath;
1530 auto det = sumX2 - nInv * sumX * sumX;
1531 if (std::abs(det) < 1e-12) {
1534 params.tgl = (sumXY - nInv * sumX * sumY) / det;
1549 float sumX = 0.f, sumY = 0.f, sumXY = 0.f, sumX2 = 0.f, nInv = 1.f / nCl;
1550 for (
int i = nCl;
i--;) {
1553 sumXY +=
x[
i] *
y[
i];
1554 sumX2 +=
x[
i] *
x[
i];
1556 float det = sumX2 - nInv * sumX * sumX;
1557 if (std::abs(det) < 1e-12f) {
1560 res[0] = (sumXY - nInv * sumX * sumY) / det;
1561 res[1] = nInv * sumY - nInv *
res[0] * sumX;
1574 LOG(warn) <<
"For the tree aliases to work you must initialize the binning before calling createOutputFile()";
1576 mFileOut = std::make_unique<TFile>(
filename,
"recreate");
1577 mTreeOut = std::make_unique<TTree>(
"voxResTree",
"Voxel results and statistics");
1578 mTreeOut->SetAlias(
"z2xBin",
"bvox[0]");
1579 mTreeOut->SetAlias(
"y2xBin",
"bvox[1]");
1580 mTreeOut->SetAlias(
"xBin",
"bvox[2]");
1581 mTreeOut->SetAlias(
"z2xAV",
"stat[0]");
1582 mTreeOut->SetAlias(
"y2xAV",
"stat[1]");
1583 mTreeOut->SetAlias(
"xAV",
"stat[2]");
1584 mTreeOut->SetAlias(
"fsector",
"bsec+0.5+9.*(y2xAV)/pi");
1585 mTreeOut->SetAlias(
"phi",
"(bsec%18+0.5+9.*(stat[1])/pi)/9*pi");
1586 mTreeOut->SetAlias(
"r",
"stat[2]");
1587 mTreeOut->SetAlias(
"z",
"z2xAV*xAV");
1588 mTreeOut->SetAlias(
"dX",
"D[0]");
1589 mTreeOut->SetAlias(
"dY",
"D[1]");
1590 mTreeOut->SetAlias(
"dZ",
"D[2]");
1591 mTreeOut->SetAlias(
"dXS",
"DS[0]");
1592 mTreeOut->SetAlias(
"dYS",
"DS[1]");
1593 mTreeOut->SetAlias(
"dZS",
"DS[2]");
1594 mTreeOut->SetAlias(
"dXE",
"E[0]");
1595 mTreeOut->SetAlias(
"dYE",
"E[1]");
1596 mTreeOut->SetAlias(
"dZE",
"E[2]");
1598 mTreeOut->SetAlias(
"entries",
"stat[3]");
1599 mTreeOut->SetAlias(
"fitOK", Form(
"(flags & %u) == %u",
DistDone,
DistDone));
1600 mTreeOut->SetAlias(
"dispOK", Form(
"(flags & %u) == %u",
DispDone,
DispDone));
1602 mTreeOut->SetAlias(
"masked", Form(
"(flags & %u) == %u",
Masked,
Masked));
1603 mTreeOut->Branch(
"voxRes", &mVoxelResultsOutPtr);
1618 printf(
"Dumping results for sector %i. Don't forget the call to closeOutputFile() in the end...\n", iSec);
1619 for (
int i = 0;
i < mNVoxPerSector; ++
i) {
1620 mVoxelResultsOut = mVoxelResults[iSec][
i];
1628 static float mres = 0, mvir = 0, mres0 = 0, mvir0 = 0;
1629 static ProcInfo_t procInfo;
1630 static TStopwatch
sw;
1631 const Long_t kMB = 1024;
1632 gSystem->GetProcInfo(&procInfo);
1633 mres = float(procInfo.fMemResident) / kMB;
1634 mvir = float(procInfo.fMemVirtual) / kMB;
1636 printf(
"RSS: %.3f(%.3f) VMEM: %.3f(%.3f) MB | CpuTime:%.3f RealTime:%.3f s\n",
1637 mres, mres - mres0, mvir, mvir - mvir0,
sw.CpuTime(),
sw.RealTime());
1646 mInitResultsContainer.reset();
bounded_vector< float > bins
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)
Definition of the TrackResiduals class.
static const SpacePointsCalibConfParam & Instance()
std::vector< LocalResid > & getLocalResVec()
float getDZ2XI(int iz=0) const
void setKernelType(KernelType kernel=KernelType::Epanechnikov, float bwX=2.1f, float bwP=2.1f, float bwZ=1.7f, float scX=1.f, float scP=1.f, float scZ=1.f)
bool getSmoothEstimate(int iSec, float x, float p, float z, std::array< float, ResDim > &res, int whichDim=0)
int getXBinExact(float x) const
void setY2XBinning(const std::vector< float > &binning)
void dumpResults(int iSec)
void processSectorResiduals(Int_t iSec)
static bool fitPoly1(int nCl, std::array< float, param::NPadRows > &x, std::array< float, param::NPadRows > &y, std::array< float, 2 > &res)
size_t getGlbVoxBin(int ix, int ip, int iz) const
void setStats(const std::vector< TrackResiduals::VoxStats > &statsIn, int iSec)
Set the voxel statistics directly from outside.
void closeOutputFile()
Closes the file with the debug output.
void clear()
clear member to be able to process new sector or new input files
void fillStats(int iSec)
Fill statistics from TTree.
void printMem() const
Prints the current memory usage.
void setZ2XBinning(const std::vector< float > &binning)
void initResultsContainer(int iSec)
int getNVoxelsPerSector() const
Get the total number of voxels per TPC sector (mNXBins * mNY2XBins * mNZ2XBins)
int getRowID(float x) const
@ VoxDim
dimensionality of the voxels
void createOutputFile(const char *filename="debugVoxRes.root")
Creates a file for the debug output.
float getDY2XI(int ix, int iy=0) const
@ DispDone
voxel dispersions have been processed
@ DistDone
voxel residuals have been processed
@ SmoothDone
voxel has been smoothed
void findVoxel(float x, float y2x, float z2x, int &ix, int &ip, int &iz) const
float roFunc(int nPoints, int offset, const std::vector< float > &x, const std::vector< float > &y, float b, float &aa) const
void medFit(int nPoints, int offset, const std::vector< float > &x, const std::vector< float > &y, float &a, float &b, std::array< float, 3 > &err) const
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)
float getDXI(int ix) const
float fitPoly1Robust(std::vector< float > &x, std::vector< float > &y, std::array< float, 2 > &res, std::array< float, 3 > &err, float cutLTM) const
int getY2XBinExact(float y2x, int ix) const
bool findVoxelBin(int secID, float x, float y, float z, std::array< unsigned char, VoxDim > &bvox) const
Calculates the bin indices for given x, y, z in sector coordinates.
bool getXBinIgnored(int iSec, int bin) const
void initBinning()
Initializes the binning in X, Y/X and Z.
float getMAD2Sigma(std::vector< float > data) const
@ ResD
index for dispersions
void reset()
Resets all (also intermediate) results.
int getZ2XBinExact(float z2x) const
double getKernelWeight(std::array< double, 3 > u2vec) const
void processVoxelDispersions(std::vector< float > &tg, std::vector< float > &dy, VoxRes &resVox)
void init(bool doBinning=true)
float selectKthMin(const int k, std::vector< float > &data) const
void setNY2XBins(int nBins)
void setNZ2XBins(int nBins)
int validateVoxels(int iSec)
void processVoxelResiduals(std::vector< float > &dy, std::vector< float > &dz, std::vector< float > &tg, VoxRes &resVox)
GLboolean GLboolean GLboolean b
GLenum const GLfloat * params
GLsizei GLenum const void * indices
GLboolean GLboolean GLboolean GLboolean a
GLubyte GLubyte GLubyte GLubyte w
GLdouble GLdouble GLdouble z
void Reorder(std::vector< T > &data, const std::vector< size_t > &index)
bool LTMUnbinnedSig(const std::vector< T > &data, std::vector< size_t > &index, std::array< float, 7 > ¶ms, float fracKeepMin, float sigTgt, bool sorted=false)
void SortData(std::vector< T > const &values, std::vector< size_t > &index)
bool LTMUnbinned(const std::vector< T > &data, std::vector< size_t > &index, std::array< float, 7 > ¶ms, float fracKeep)
Global TPC definitions and constants.
constexpr double SECPHIWIDTH
constexpr unsigned char SECTORSPERSIDE
Enum< T >::Iterator begin(Enum< T >)
constexpr unsigned char SIDES
DataT sum(const Vector< DataT, N > &a)
FIXME: do not use data model tables.
float minFracLTM
minimum fraction of points to keep when trimming data to fit expected sigma
float maxFitErrX2
maximum fit error for X2
float minValidVoxFracDrift
if more than this fraction of bins are bad for one pad row the whole pad row is declared bad
float maxGaussStdDev
maximum number of sigmas to be considered for gaussian kernel smoothing
int minEntriesPerVoxel
minimum number of points in voxel for processing
float LTMCut
fraction op points to keep when trimming input data
int maxBadXBinsToCover
a lower number of consecutive bad X bins will not be declared bad
float maxFitErrY2
maximum fit error for Y2
float maxSigY
maximum sigma for y of the voxel
float maxFitCorrXY
maximum fit correlation for x and y
float maxSigZ
maximum sigma for z of the voxel
int minGoodXBinsToCover
minimum number of consecutive good bins, otherwise bins are declared bad
float maxFracBadRowsPerSector
maximum fraction of bad rows before whole sector is masked
bool isBfieldZero
for B=0 we set the radial distortions to zero and don't fit dy vs tgSlp
Structure which gets filled with the results for each voxel.
std::array< unsigned char, VoxDim > bvox
voxel identifier: VoxZ, VoxF, VoxX
std::array< float, ResDim > E
their errors
float dYSigMAD
MAD estimator of dY sigma (dispersion after slope removal)
std::array< float, ResDim > D
values of extracted distortions
float dZSigLTM
Z sigma from unbinned LTM estimator.
unsigned char flags
status flag
std::array< float, ResDim > DS
smoothed residual
unsigned char bsec
sector ID (0-35)
float EXYCorr
correlation between extracted X and Y
std::array< float, VoxHDim > stat
statistics: averages of each voxel dimension + entries
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)