From 9ed9b14ad0efd3c4a11df399d199aa38f6c8c93d Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Fri, 15 Mar 2024 15:59:14 +0000 Subject: [PATCH 01/26] TPC Splines: fix initialization of the track residuals in the test macro --- .../macro/TPCFastTransformInit.C | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 6b3756aca3b73..b13d031d6d10d 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -21,19 +21,24 @@ /// root -l TPCFastTransformInit.C'("debugVoxRes.root")' /// +#include "Algorithm/RangeTokenizer.h" + #if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include #include "TFile.h" #include "TSystem.h" #include "TTree.h" #include "TNtuple.h" #include "Riostream.h" +#include "Algorithm/RangeTokenizer.h" +#include "Framework/Logger.h" #include "GPU/TPCFastTransform.h" #include "SpacePoints/TrackResiduals.h" #include "TPCReconstruction/TPCFastTransformHelperO2.h" #include "TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h" - #endif using namespace o2::tpc; @@ -54,6 +59,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", corr->Draw("cx:y:z","iRoc==0&&iRow==10","") grid->Draw("cx:y:z","iRoc==0&&iRow==10","same") vox->Draw("vx:y:z","iRoc==0&&iRow==10","same") + points->Draw("px:y:z","iRoc==0&&iRow==10","same") */ if (gSystem->AccessPathName(fileName)) { @@ -75,15 +81,42 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", return; } + auto userInfo = voxResTree->GetUserInfo(); + + if (!userInfo->FindObject("y2xBinning") || !userInfo->FindObject("z2xBinning")) { + std::cout << "'y2xBinning' or 'z2xBinning' not found in UserInfo, but required to get the correct binning" << std::endl; + return; + } + + userInfo->Print(); + + // required for the binning that was used o2::tpc::TrackResiduals trackResiduals; - trackResiduals.init(); // also initializes the default binning which was used + auto y2xBins = o2::RangeTokenizer::tokenize(userInfo->FindObject("y2xBinning")->GetTitle()); + auto z2xBins = o2::RangeTokenizer::tokenize(userInfo->FindObject("z2xBinning")->GetTitle()); + trackResiduals.setY2XBinning(y2xBins); + trackResiduals.setZ2XBinning(z2xBins); + trackResiduals.init(); + + std::cout << "y2xBins: " << y2xBins.size() << " z2xBins: " << z2xBins.size() << std::endl; + for (auto y2x : y2xBins) { + std::cout << "y2x: " << y2x << std::endl; + } + + std::cout << std::endl; + + for (auto z2x : z2xBins) { + std::cout << "z2x: " << z2x << std::endl; + } std::cout << "create fast transformation ... " << std::endl; auto* helper = o2::tpc::TPCFastTransformHelperO2::instance(); o2::tpc::TPCFastSpaceChargeCorrectionHelper* corrHelper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); + corrHelper->setNthreadsToMaximum(); + auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, useSmoothed, invertSigns); std::unique_ptr fastTransform( @@ -162,6 +195,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", branch->SetAddress(&v); branch->SetAutoDelete(kTRUE); + int iRocLast = -1; + int iRowLast = -1; + for (int32_t iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { voxResTree->GetEntry(iVox); @@ -180,6 +216,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", int32_t iRoc = (int32_t)v->bsec; int32_t iRow = (int32_t)xBin; + iRocLast = iRoc; + iRowLast = iRow; + double x = trackResiduals.getX(xBin); // radius of the pad row double y2x = trackResiduals.getY2X( From b64531c0f11d7260d30077f74c65ba8b8741c6af Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Fri, 15 Mar 2024 16:02:00 +0000 Subject: [PATCH 02/26] TPC Splines: fix propagation of the track residual data to the TPC row edges --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 389 +++++++++++++----- 1 file changed, 279 insertions(+), 110 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index e2960c73e4d50..9910e2206ca11 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -118,6 +118,8 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas // calculate correction map: dx,du,dv = ( origTransform() -> x,u,v) - fastTransformNominal:x,u,v // for the future: switch TOF correction off for a while + TStopwatch watch; + if (!mIsInitialized) { initGeometry(); } @@ -176,6 +178,10 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas } // slice + watch.Stop(); + + LOGP(info, "Space charge correction tooks: {}s", watch.RealTime()); + initInverse(correction, 0); } @@ -380,20 +386,14 @@ std::unique_ptr TPCFastSpaceChargeCorrect { // create o2::gpu::TPCFastSpaceChargeCorrection from o2::tpc::TrackResiduals::VoxRes voxel tree - LOG(info) << "fast space charge correction helper: create correction using " << mNthreads << " threads"; + LOG(info) << "fast space charge correction helper: create correction from track residuals using " << mNthreads << " threads"; + + TStopwatch watch1, watch2; std::unique_ptr correctionPtr(new o2::gpu::TPCFastSpaceChargeCorrection); o2::gpu::TPCFastSpaceChargeCorrection& correction = *correctionPtr; - // o2::tpc::TrackResiduals::VoxRes* v = nullptr; - // voxResTree->SetBranchAddress("voxRes", &v); - - o2::tpc::TrackResiduals::VoxRes* v = nullptr; - TBranch* branch = voxResTree->GetBranch("voxRes"); - branch->SetAddress(&v); - branch->SetAutoDelete(kTRUE); - auto* helper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); @@ -417,9 +417,11 @@ std::unique_ptr TPCFastSpaceChargeCorrect // std::cout << "n knots Y: " << nKnotsY << std::endl; // std::cout << "n knots Z: " << nKnotsZ << std::endl; + const int nRows = geo.getNumberOfRows(); + const int nROCs = geo.getNumberOfSlices(); + { // create the correction object - const int nRows = geo.getNumberOfRows(); const int nCorrectionScenarios = 1; correction.startConstruction(geo, nCorrectionScenarios); @@ -451,131 +453,298 @@ std::unique_ptr TPCFastSpaceChargeCorrect LOG(info) << "fast space charge correction helper: fill data points from track residuals"; - for (int iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { - - voxResTree->GetEntry(iVox); - auto xBin = - v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) - auto y2xBin = - v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 - auto z2xBin = - v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - - int iRoc = (int)v->bsec; - int iRow = (int)xBin; + // o2::tpc::TrackResiduals::VoxRes* v = nullptr; + // voxResTree->SetBranchAddress("voxRes", &v); - // x,y,z of the voxel in local TPC coordinates + o2::tpc::TrackResiduals::VoxRes* v = nullptr; + TBranch* branch = voxResTree->GetBranch("voxRes"); + branch->SetAddress(&v); + branch->SetAutoDelete(kTRUE); - double x = trackResiduals.getX(xBin); // radius of the pad row - double y2x = trackResiduals.getY2X( - xBin, y2xBin); // y/x coordinate of the bin ~-0.15 ... 0.15 - double z2x = - trackResiduals.getZ2X(z2xBin); // z/x coordinate of the bin 0.1 .. 0.9 - double y = x * y2x; - double z = x * z2x; + // find the first and the last voxel for each ROC + // we assume the data is sorted by ROC, othwerwise it will be read nROCs times - if (iRoc >= geo.getNumberOfSlicesA()) { - z = -z; - // y = -y; - } + std::vector vROCdataFirst(nROCs, -1); + std::vector vROCdataLast(nROCs, -2); - { - float sx, sy, sz; - trackResiduals.getVoxelCoordinates(iRoc, xBin, y2xBin, z2xBin, sx, sy, sz); - sy *= x; - sz *= x; - if (fabs(sx - x) + fabs(sy - y) + fabs(sz - z) > 1.e-4) { - std::cout << "wrong coordinates: " << x << " " << y << " " << z << " / " << sx << " " << sy << " " << sz << std::endl; + { + int iRocLast = -1; + bool isSorted = true; + for (int iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { + voxResTree->GetEntry(iVox); + int iRoc = (int)v->bsec; + // ensure the data is in the expacted order + if (iRoc < iRocLast) { + isSorted = false; + } + iRocLast = iRoc; + if (iRoc < 0 || iRoc >= nROCs) { + LOG(fatal) << "ROC number " << iRoc << " is out of range"; } + if (vROCdataFirst[iRoc] < 0) { + vROCdataFirst[iRoc] = iVox; + } + vROCdataLast[iRoc] = iVox; } - - // skip empty voxels - float voxEntries = v->stat[o2::tpc::TrackResiduals::VoxV]; - if (voxEntries < 1.) { // no statistics - continue; + if (!isSorted) { + LOG(warning) << "Data is not sorted by ROC as expected"; } + } - // double statX = v->stat[o2::tpc::TrackResiduals::VoxX]; // weight - // double statY = v->stat[o2::tpc::TrackResiduals::VoxF]; // weight - // double statZ = v->stat[o2::tpc::TrackResiduals::VoxZ]; // weight - - // double dx = 1. / trackResiduals.getDXI(xBin); - double dy = x / trackResiduals.getDY2XI(xBin, y2xBin); - double dz = x * trackResiduals.getDZ2X(z2xBin); - - double correctionX = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; - double correctionY = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; - double correctionZ = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; - if (invertSigns) { - correctionX *= -1.; - correctionY *= -1.; - correctionZ *= -1.; - } - // add one point per voxel + // read the data ROC by ROC - // map.addCorrectionPoint(iRoc, iRow, y, z, correctionX, correctionY, - // correctionZ); + // data in the tree is not sorted by row + // first find which data belong to which row - // add several points per voxel, - // extend values of the edge voxels to the edges of the TPC row - // + struct VoxelData { + int mNentries{0}; // number of entries + float mCx, mCy, mCz; // corrections to the local coordinates + }; - double yFirst = y - dy / 2.; - double yLast = y + dy / 2.; + std::vector vRocData[nRows]; + for (int ir = 0; ir < nRows; ir++) { + vRocData[ir].resize(nY2Xbins * nZ2Xbins); + } - if (y2xBin == 0) { // extend value of the first Y bin to the row edge - float u, v; - if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); - } else { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + struct Voxel { + float mY, mZ; // not-distorted local coordinates + float mDy, mDz; // bin size + int mSmoothingStep{100}; // is the voxel data original or smoothed at this step + }; + + std::vector vRowVoxels(nY2Xbins * nZ2Xbins); + + for (int iRoc = 0; iRoc < nROCs; iRoc++) { + + for (int ir = 0; ir < nRows; ir++) { + for (int iv = 0; iv < nY2Xbins * nZ2Xbins; iv++) { + vRocData[ir][iv].mNentries = 0; } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yFirst = py; } - if (y2xBin == trackResiduals.getNY2XBins() - 1) { // extend value of the last Y bin to the row edge - float u, v; - if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); - } else { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + for (int iVox = vROCdataFirst[iRoc]; iVox <= vROCdataLast[iRoc]; iVox++) { + voxResTree->GetEntry(iVox); + if ((int)v->bsec != iRoc) { + LOG(fatal) << "ROC number " << v->bsec << " is not equal to " << iRoc; + continue; + } + int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) + if (iRow < 0 || iRow >= nRows) { + LOG(fatal) << "Row number " << iRow << " is out of range"; } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yLast = py; + int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 + int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 + auto& vox = vRocData[iRow][iy * nZ2Xbins + iz]; + vox.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; + vox.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; + vox.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; + vox.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; } - double z0 = 0.; - if (iRoc < geo.getNumberOfSlicesA()) { - z0 = geo.getTPCzLengthA(); - } else { - z0 = -geo.getTPCzLengthC(); - } + // now process the data row-by-row + + for (int iRow = 0; iRow < nRows; iRow++) { + + // LOG(info) << "Processing ROC " << iRoc << " row " << iRow; + + // complete the voxel data + { + int xBin = iRow; + double x = trackResiduals.getX(xBin); // radius of the pad row + bool isDataFound = false; + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + // y/x coordinate of the bin ~-0.15 ... 0.15 + double y2x = trackResiduals.getY2X(xBin, iy); + // z/x coordinate of the bin 0.1 .. 0.9 + double z2x = trackResiduals.getZ2X(iz); + vox.mY = x * y2x; + vox.mZ = x * z2x; + vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); + vox.mDz = x * trackResiduals.getDZ2X(iz); + if (iRoc >= geo.getNumberOfSlicesA()) { + vox.mZ = -vox.mZ; + } + if (data.mNentries < 1) { // no data + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + vox.mSmoothingStep = 100; + } else { // voxel contains data + if (invertSigns) { + data.mCx *= -1.; + data.mCy *= -1.; + data.mCz *= -1.; + } + vox.mSmoothingStep = 0; // original data + isDataFound = true; + } + } + } - double yStep = (yLast - yFirst) / 2; + if (!isDataFound) { // fill everything with 0 + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + vRowVoxels[iy * nZ2Xbins + iz].mSmoothingStep = 0; + } + } + } + } // complete the voxel data + + // repare the voxel data: fill empty voxels + + int nRepairs = 0; + + for (int ismooth = 1; ismooth <= 2; ismooth++) { + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep <= ismooth) { // already filled + continue; + } + nRepairs++; + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + double w = 0.; + bool filled = false; + auto update = [&](int iy1, int iz1) { + auto& data1 = vRocData[iRow][iy1 * nZ2Xbins + iz1]; + auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; + if (vox1.mSmoothingStep >= ismooth) { + return false; + } + double w1 = 1. / (abs(iy - iy1) + abs(iz - iz1) + 1); + data.mCx += w1 * data1.mCx; + data.mCy += w1 * data1.mCy; + data.mCz += w1 * data1.mCz; + w += w1; + filled = true; + return true; + }; + + for (int iy1 = iy - 1; iy1 >= 0 && !update(iy1, iz); iy1--) { + } + for (int iy1 = iy + 1; iy1 < nY2Xbins && !update(iy1, iz); iy1++) { + } + for (int iz1 = iz - 1; iz1 >= 0 && !update(iy, iz1); iz1--) { + } + for (int iz1 = iz + 1; iz1 < nZ2Xbins && !update(iy, iz1); iz1++) { + } - for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { + if (filled) { + data.mCx /= w; + data.mCy /= w; + data.mCz /= w; + vox.mSmoothingStep = ismooth; + } + } // iz + } // iy + } // ismooth - for (double pz = z - dz / 2.; pz <= z + dz / 2. + 1.e-4; pz += dz / 2.) { - map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, - correctionZ); + if (nRepairs > 0) { + LOG(info) << "ROC " << iRoc << " row " << iRow << ": " << nRepairs << " voxel repairs for " << nY2Xbins * nZ2Xbins << " voxels"; } - if (z2xBin == trackResiduals.getNZ2XBins() - 1) { - // extend value of the first Z bin to the readout, linear decrease of all values to 0. - int nZsteps = 3; - for (int is = 0; is < nZsteps; is++) { - double pz = z + (z0 - z) * (is + 1.) / nZsteps; - double s = (nZsteps - 1. - is) / nZsteps; - map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, - s * correctionY, s * correctionZ); + // feed the row data to the helper + + double yMin = 0., yMax = 0.; + + { + float u, v; + if (iRoc < geo.getNumberOfSlicesA()) { + geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + } else { + geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); } + float py, pz; + geo.convUVtoLocal(iRoc, u, v, py, pz); + yMin = py; } - } - } + { + float u, v; + if (iRoc < geo.getNumberOfSlicesA()) { + geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + } else { + geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + } + float py, pz; + geo.convUVtoLocal(iRoc, u, v, py, pz); + yMax = py; + } + + double zEdge = 0.; + if (iRoc < geo.getNumberOfSlicesA()) { + zEdge = geo.getTPCzLengthA(); + } else { + zEdge = -geo.getTPCzLengthC(); + } + + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared"; + } + + double y = vox.mY; + double z = vox.mZ; + double dy = vox.mDy; + double dz = vox.mDz; + double correctionX = data.mCx; + double correctionY = data.mCy; + double correctionZ = data.mCz; + + double yFirst = y - dy / 2.; + double yLast = y + dy / 2.; + + if (iy == 0) { // extend value of the first Y bin to the row edge + yFirst = yMin; + } + + if (iy == nY2Xbins - 1) { // extend value of the last Y bin to the row edge + yLast = yMax; + } + + double yStep = (yLast - yFirst) / 2; + + for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { + + for (double pz = z - dz / 2.; pz <= z + dz / 2. + 1.e-4; pz += dz / 2.) { + map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, + correctionZ); + } + + if (iz == nZ2Xbins - 1) { + // extend value of the first Z bin to the readout, linear decrease of all values to 0. + int nZsteps = 3; + for (int is = 0; is < nZsteps; is++) { + double pz = z + (zEdge - z) * (is + 1.) / nZsteps; + double s = (nZsteps - 1. - is) / nZsteps; + map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, + s * correctionY, s * correctionZ); + } + } + } + } // iz + } // iy + + } // iRow + + } // iRoc + + LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch1.RealTime()); + + LOG(info) << "fast space charge correction helper: create space charge from the map of data points.."; + helper->fillSpaceChargeCorrectionFromMap(correction); + + LOGP(info, "Creation from track residuals tooks in total: {}s", watch2.RealTime()); + return std::move(correctionPtr); } @@ -814,7 +983,7 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector Date: Mon, 15 Apr 2024 14:41:19 +0000 Subject: [PATCH 03/26] TPC Splines: non-uniform grid that corresponds to the track residual voxels --- .../include/SpacePoints/TrackResiduals.h | 19 +- .../TPCFastSpaceChargeCorrectionHelper.cxx | 530 ++++++++++-------- .../TPCFastSpaceChargeCorrection.cxx | 181 +++--- .../TPCFastSpaceChargeCorrection.h | 64 +-- .../TPCFastTransformGeo.h | 9 + .../macro/TPCFastTransformInit.C | 203 +++++-- 6 files changed, 619 insertions(+), 387 deletions(-) diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h index e4d0a3a053728..ab871dc3bd3d0 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h @@ -318,9 +318,14 @@ class TrackResiduals void getVoxelCoordinates(int isec, int ix, int ip, int iz, float& x, float& p, float& z) const; /// Calculates the x-coordinate for given x bin. - /// \param i Bin index + /// \param ix Bin index in x /// \return Coordinate in X - float getX(int i) const; + float getX(int ix) const; + + /// Calculates the max y/x-coordinate for given x bin taking the dead zone into account. + /// \param ix Bin index in x + /// \return Max coordinate in Y/X + float getMaxY2X(int ix) const; /// Calculates the y/x-coordinate. /// \param ix Bin index in X @@ -552,9 +557,15 @@ inline float TrackResiduals::getDXI(int ix) const } //_____________________________________________________ -inline float TrackResiduals::getX(int i) const +inline float TrackResiduals::getX(int ix) const +{ + return mUniformBins[VoxX] ? param::MinX + (ix + 0.5) * mDX : param::RowX[ix]; +} + +//_____________________________________________________ +inline float TrackResiduals::getMaxY2X(int ix) const { - return mUniformBins[VoxX] ? param::MinX + (i + 0.5) * mDX : param::RowX[i]; + return mMaxY2X[ix]; } //_____________________________________________________ diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 9910e2206ca11..861cacbe00012 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -29,6 +29,8 @@ #include #include #include "TStopwatch.h" +#include "TTreeReader.h" +#include "TTreeReaderValue.h" using namespace o2::gpu; @@ -154,7 +156,7 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas pointCorr[3 * i + 1] = du; pointCorr[3 * i + 2] = dv; } - helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getNumberOfKnots() - 1, 0., spline.getGridX2().getNumberOfKnots() - 1, &pointSU[0], + helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointSU[0], &pointSV[0], &pointCorr[0], nDataPoints); } else { for (int i = 0; i < spline.getNumberOfParameters(); i++) { @@ -388,7 +390,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect LOG(info) << "fast space charge correction helper: create correction from track residuals using " << mNthreads << " threads"; - TStopwatch watch1, watch2; + TStopwatch watch, watch1; std::unique_ptr correctionPtr(new o2::gpu::TPCFastSpaceChargeCorrection); @@ -403,17 +405,90 @@ std::unique_ptr TPCFastSpaceChargeCorrect int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); - int nKnotsY = nY2Xbins / 2; - int nKnotsZ = nZ2Xbins / 2; + std::vector yBinsInt; + { + std::vector yBins; + yBins.reserve(nY2Xbins); + for (int i = 0, j = nY2Xbins - 1; i <= j; i += 2, j -= 2) { + if (i == j) { + yBins.push_back(trackResiduals.getY2X(0, i)); + } else if (i + 1 == j) { + yBins.push_back(trackResiduals.getY2X(0, i)); + } else { + yBins.push_back(trackResiduals.getY2X(0, i)); + yBins.push_back(trackResiduals.getY2X(0, j)); + } + } + std::sort(yBins.begin(), yBins.end()); + double dy = yBins[1] - yBins[0]; + for (int i = 1; i < yBins.size(); i++) { + if (yBins[i] - yBins[i - 1] < dy) { + dy = yBins[i] - yBins[i - 1]; + } + } + yBinsInt.reserve(yBins.size()); + // spline knots must be positioned on the grid with integer internal coordinate + // take the knot position accuracy of 0.1*dy + dy = dy / 10.; + double y0 = yBins[0]; + double y1 = yBins[yBins.size() - 1]; + for (auto& y : yBins) { + y -= y0; + int iy = int(y / dy + 0.5); + yBinsInt.push_back(iy); + double yold = y / (y1 - y0) * 2 - 1.; + y = iy * dy; + y = y / (y1 - y0) * 2 - 1.; + LOG(info) << "convert y bin: " << yold << " -> " << y << " -> " << iy; + } + } + + std::vector zBinsInt; + { + std::vector zBins; + zBins.reserve(nZ2Xbins); + for (int i = 0; i < nZ2Xbins; i += 2) { + zBins.push_back(-trackResiduals.getZ2X(i)); + } + std::sort(zBins.begin(), zBins.end()); + double dz = zBins[1] - zBins[0]; + for (int i = 1; i < zBins.size(); i++) { + if (zBins[i] - zBins[i - 1] < dz) { + dz = zBins[i] - zBins[i - 1]; + } + } + zBinsInt.reserve(zBins.size()); + // spline knots must be positioned on the grid with an integer internal coordinate + // lets copy the knot positions with the accuracy of 0.1*dz + dz = dz / 10.; + double z0 = zBins[0]; + double z1 = zBins[zBins.size() - 1]; + for (auto& z : zBins) { + z -= z0; + int iz = int(z / dz + 0.5); + zBinsInt.push_back(iz); + double zold = z / (z1 - z0); + z = iz * dz; + z = z / (z1 - z0); + LOG(info) << "convert z bin: " << zold << " -> " << z << " -> " << iz; + } + } - if (nKnotsY < 2) { - nKnotsY = 2; + if (yBinsInt.size() < 2) { + yBinsInt.clear(); + yBinsInt.push_back(0); + yBinsInt.push_back(1); } - if (nKnotsZ < 2) { - nKnotsZ = 2; + if (zBinsInt.size() < 2) { + zBinsInt.clear(); + zBinsInt.push_back(0); + zBinsInt.push_back(1); } + int nKnotsY = yBinsInt.size(); + int nKnotsZ = zBinsInt.size(); + // std::cout << "n knots Y: " << nKnotsY << std::endl; // std::cout << "n knots Z: " << nKnotsZ << std::endl; @@ -432,64 +507,42 @@ std::unique_ptr TPCFastSpaceChargeCorrect } { // init spline scenario TPCFastSpaceChargeCorrection::SplineType spline; - spline.recreate(nKnotsY, nKnotsZ); + spline.recreate(nKnotsY, &yBinsInt[0], nKnotsZ, &zBinsInt[0]); correction.setSplineScenario(0, spline); } correction.finishConstruction(); } // .. create the correction object - // set the grid borders in Z to Z/X==1 + // set the grid borders for (int iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { - auto rowInfo = geo.getRowInfo(iRow); - o2::gpu::TPCFastSpaceChargeCorrection::SliceRowInfo& info = correction.getSliceRowInfo(iRoc, iRow); - double len = geo.getTPCzLength(iRoc); - info.gridV0 = len - rowInfo.x; - if (info.gridV0 < 0.) { - info.gridV0 = 0.; - } + const auto& rowInfo = geo.getRowInfo(iRow); + auto& info = correction.getSliceRowInfo(iRoc, iRow); + const auto& spline = correction.getSpline(iRoc, iRow); + double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); + double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); + double zMin = rowInfo.x * trackResiduals.getZ2X(0); + double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); + double uMin = yMin; + double uMax = yMax; + double vMin = geo.getTPCzLength(iRoc) - zMax; + double vMax = geo.getTPCzLength(iRoc) - zMin; + // std::cout << " uMin: " << uMin << " uMax: " << yuMax << " zMin: " << vMin << " zMax: " << vMax << std::endl; + info.gridU0 = uMin; + info.scaleUtoGrid = spline.getGridX1().getUmax() / (uMax - uMin); + info.gridV0 = vMin; + info.scaleVtoGrid = spline.getGridX2().getUmax() / (vMax - vMin); } } - LOG(info) << "fast space charge correction helper: fill data points from track residuals"; - - // o2::tpc::TrackResiduals::VoxRes* v = nullptr; - // voxResTree->SetBranchAddress("voxRes", &v); + LOG(info) << "fast space charge correction helper: preparation took " << watch1.RealTime() << "s"; - o2::tpc::TrackResiduals::VoxRes* v = nullptr; - TBranch* branch = voxResTree->GetBranch("voxRes"); - branch->SetAddress(&v); - branch->SetAutoDelete(kTRUE); + LOG(info) << "fast space charge correction helper: fill data points from track residuals.. "; - // find the first and the last voxel for each ROC - // we assume the data is sorted by ROC, othwerwise it will be read nROCs times + TStopwatch watch3; - std::vector vROCdataFirst(nROCs, -1); - std::vector vROCdataLast(nROCs, -2); - - { - int iRocLast = -1; - bool isSorted = true; - for (int iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { - voxResTree->GetEntry(iVox); - int iRoc = (int)v->bsec; - // ensure the data is in the expacted order - if (iRoc < iRocLast) { - isSorted = false; - } - iRocLast = iRoc; - if (iRoc < 0 || iRoc >= nROCs) { - LOG(fatal) << "ROC number " << iRoc << " is out of range"; - } - if (vROCdataFirst[iRoc] < 0) { - vROCdataFirst[iRoc] = iVox; - } - vROCdataLast[iRoc] = iVox; - } - if (!isSorted) { - LOG(warning) << "Data is not sorted by ROC as expected"; - } - } + // TTreeProcessorMT treeProcessor(*voxResTree); // multi-threaded tree processor + // treeProcessor.Init(voxResTree); // read the data ROC by ROC @@ -506,14 +559,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect vRocData[ir].resize(nY2Xbins * nZ2Xbins); } - struct Voxel { - float mY, mZ; // not-distorted local coordinates - float mDy, mDz; // bin size - int mSmoothingStep{100}; // is the voxel data original or smoothed at this step - }; - - std::vector vRowVoxels(nY2Xbins * nZ2Xbins); - for (int iRoc = 0; iRoc < nROCs; iRoc++) { for (int ir = 0; ir < nRows; ir++) { @@ -522,10 +567,17 @@ std::unique_ptr TPCFastSpaceChargeCorrect } } - for (int iVox = vROCdataFirst[iRoc]; iVox <= vROCdataLast[iRoc]; iVox++) { - voxResTree->GetEntry(iVox); + const int rocDataStart = iRoc * trackResiduals.getNVoxelsPerSector(); + const int rocDataEnd = rocDataStart + trackResiduals.getNVoxelsPerSector(); + + TTreeReader reader(voxResTree); + reader.SetEntriesRange(rocDataStart, rocDataEnd); + TTreeReaderValue v(reader, "voxRes"); + for (int iVox = rocDataStart; iVox < rocDataEnd; iVox++) { + reader.Next(); + // voxResTree->GetEntry(iVox); if ((int)v->bsec != iRoc) { - LOG(fatal) << "ROC number " << v->bsec << " is not equal to " << iRoc; + LOG(fatal) << "Error reading voxels: voxel ROC number " << v->bsec << " is not equal to the expected " << iRoc; continue; } int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) @@ -543,207 +595,237 @@ std::unique_ptr TPCFastSpaceChargeCorrect // now process the data row-by-row - for (int iRow = 0; iRow < nRows; iRow++) { + auto myThread = [&](int iThread, int nTreads) { + struct Voxel { + float mY, mZ; // not-distorted local coordinates + float mDy, mDz; // bin size + int mSmoothingStep{100}; // is the voxel data original or smoothed at this step + }; - // LOG(info) << "Processing ROC " << iRoc << " row " << iRow; + std::vector vRowVoxels(nY2Xbins * nZ2Xbins); - // complete the voxel data - { - int xBin = iRow; - double x = trackResiduals.getX(xBin); // radius of the pad row - bool isDataFound = false; - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - // y/x coordinate of the bin ~-0.15 ... 0.15 - double y2x = trackResiduals.getY2X(xBin, iy); - // z/x coordinate of the bin 0.1 .. 0.9 - double z2x = trackResiduals.getZ2X(iz); - vox.mY = x * y2x; - vox.mZ = x * z2x; - vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); - vox.mDz = x * trackResiduals.getDZ2X(iz); - if (iRoc >= geo.getNumberOfSlicesA()) { - vox.mZ = -vox.mZ; - } - if (data.mNentries < 1) { // no data - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - vox.mSmoothingStep = 100; - } else { // voxel contains data - if (invertSigns) { - data.mCx *= -1.; - data.mCy *= -1.; - data.mCz *= -1.; + for (int iRow = iThread; iRow < nRows; iRow += nTreads) { + // LOG(info) << "Processing ROC " << iRoc << " row " << iRow; + + // complete the voxel data + + { + int xBin = iRow; + double x = trackResiduals.getX(xBin); // radius of the pad row + bool isDataFound = false; + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + // y/x coordinate of the bin ~-0.15 ... 0.15 + double y2x = trackResiduals.getY2X(xBin, iy); + // z/x coordinate of the bin 0.1 .. 0.9 + double z2x = trackResiduals.getZ2X(iz); + vox.mY = x * y2x; + vox.mZ = x * z2x; + vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); + vox.mDz = x * trackResiduals.getDZ2X(iz); + if (iRoc >= geo.getNumberOfSlicesA()) { + vox.mZ = -vox.mZ; + } + if (data.mNentries < 1) { // no data + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + vox.mSmoothingStep = 100; + } else { // voxel contains data + if (invertSigns) { + data.mCx *= -1.; + data.mCy *= -1.; + data.mCz *= -1.; + } + vox.mSmoothingStep = 0; // original data + isDataFound = true; } - vox.mSmoothingStep = 0; // original data - isDataFound = true; } } - } - if (!isDataFound) { // fill everything with 0 - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - vRowVoxels[iy * nZ2Xbins + iz].mSmoothingStep = 0; + if (!isDataFound) { // fill everything with 0 + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + vRowVoxels[iy * nZ2Xbins + iz].mSmoothingStep = 0; + } } } - } - } // complete the voxel data + } // complete the voxel data - // repare the voxel data: fill empty voxels + // repare the voxel data: fill empty voxels - int nRepairs = 0; + int nRepairs = 0; - for (int ismooth = 1; ismooth <= 2; ismooth++) { - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - if (vox.mSmoothingStep <= ismooth) { // already filled - continue; - } - nRepairs++; - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - double w = 0.; - bool filled = false; - auto update = [&](int iy1, int iz1) { - auto& data1 = vRocData[iRow][iy1 * nZ2Xbins + iz1]; - auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; - if (vox1.mSmoothingStep >= ismooth) { - return false; + for (int ismooth = 1; ismooth <= 2; ismooth++) { + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep <= ismooth) { // already filled + continue; + } + nRepairs++; + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + double w = 0.; + bool filled = false; + auto update = [&](int iy1, int iz1) { + auto& data1 = vRocData[iRow][iy1 * nZ2Xbins + iz1]; + auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; + if (vox1.mSmoothingStep >= ismooth) { + return false; + } + double w1 = 1. / (abs(iy - iy1) + abs(iz - iz1) + 1); + data.mCx += w1 * data1.mCx; + data.mCy += w1 * data1.mCy; + data.mCz += w1 * data1.mCz; + w += w1; + filled = true; + return true; + }; + + for (int iy1 = iy - 1; iy1 >= 0 && !update(iy1, iz); iy1--) { + } + for (int iy1 = iy + 1; iy1 < nY2Xbins && !update(iy1, iz); iy1++) { + } + for (int iz1 = iz - 1; iz1 >= 0 && !update(iy, iz1); iz1--) { + } + for (int iz1 = iz + 1; iz1 < nZ2Xbins && !update(iy, iz1); iz1++) { } - double w1 = 1. / (abs(iy - iy1) + abs(iz - iz1) + 1); - data.mCx += w1 * data1.mCx; - data.mCy += w1 * data1.mCy; - data.mCz += w1 * data1.mCz; - w += w1; - filled = true; - return true; - }; - - for (int iy1 = iy - 1; iy1 >= 0 && !update(iy1, iz); iy1--) { - } - for (int iy1 = iy + 1; iy1 < nY2Xbins && !update(iy1, iz); iy1++) { - } - for (int iz1 = iz - 1; iz1 >= 0 && !update(iy, iz1); iz1--) { - } - for (int iz1 = iz + 1; iz1 < nZ2Xbins && !update(iy, iz1); iz1++) { - } - if (filled) { - data.mCx /= w; - data.mCy /= w; - data.mCz /= w; - vox.mSmoothingStep = ismooth; - } - } // iz - } // iy - } // ismooth + if (filled) { + data.mCx /= w; + data.mCy /= w; + data.mCz /= w; + vox.mSmoothingStep = ismooth; + } + } // iz + } // iy + } // ismooth - if (nRepairs > 0) { - LOG(info) << "ROC " << iRoc << " row " << iRow << ": " << nRepairs << " voxel repairs for " << nY2Xbins * nZ2Xbins << " voxels"; - } + if (nRepairs > 0) { + LOG(debug) << "ROC " << iRoc << " row " << iRow << ": " << nRepairs << " voxel repairs for " << nY2Xbins * nZ2Xbins << " voxels"; + } - // feed the row data to the helper + // feed the row data to the helper - double yMin = 0., yMax = 0.; + double yMin = 0., yMax = 0.; - { - float u, v; - if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); - } else { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + { + float u, v; + if (iRoc < geo.getNumberOfSlicesA()) { + geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + } else { + geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + } + float py, pz; + geo.convUVtoLocal(iRoc, u, v, py, pz); + yMin = py; } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yMin = py; - } - { - float u, v; + { + float u, v; + if (iRoc < geo.getNumberOfSlicesA()) { + geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + } else { + geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + } + float py, pz; + geo.convUVtoLocal(iRoc, u, v, py, pz); + yMax = py; + } + + double zEdge = 0.; if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + zEdge = geo.getTPCzLengthA(); } else { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + zEdge = -geo.getTPCzLengthC(); } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yMax = py; - } - - double zEdge = 0.; - if (iRoc < geo.getNumberOfSlicesA()) { - zEdge = geo.getTPCzLengthA(); - } else { - zEdge = -geo.getTPCzLengthC(); - } - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - if (vox.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared"; - } + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared"; + } - double y = vox.mY; - double z = vox.mZ; - double dy = vox.mDy; - double dz = vox.mDz; - double correctionX = data.mCx; - double correctionY = data.mCy; - double correctionZ = data.mCz; + double y = vox.mY; + double z = vox.mZ; + double dy = vox.mDy; + double dz = vox.mDz; + double correctionX = data.mCx; + double correctionY = data.mCy; + double correctionZ = data.mCz; - double yFirst = y - dy / 2.; - double yLast = y + dy / 2.; + double yFirst = y - dy / 2.; + double yLast = y + dy / 2.; - if (iy == 0) { // extend value of the first Y bin to the row edge - yFirst = yMin; - } + if (iy == 0) { // extend value of the first Y bin to the row edge + yFirst = yMin; + } - if (iy == nY2Xbins - 1) { // extend value of the last Y bin to the row edge - yLast = yMax; - } + if (iy == nY2Xbins - 1) { // extend value of the last Y bin to the row edge + yLast = yMax; + } - double yStep = (yLast - yFirst) / 2; + double yStep = (yLast - yFirst) / 2; - for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { + for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { - for (double pz = z - dz / 2.; pz <= z + dz / 2. + 1.e-4; pz += dz / 2.) { - map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, - correctionZ); - } + for (double pz = z - dz / 2.; pz <= z + dz / 2. + 1.e-4; pz += dz / 2.) { + map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, + correctionZ); + } - if (iz == nZ2Xbins - 1) { - // extend value of the first Z bin to the readout, linear decrease of all values to 0. - int nZsteps = 3; - for (int is = 0; is < nZsteps; is++) { - double pz = z + (zEdge - z) * (is + 1.) / nZsteps; - double s = (nZsteps - 1. - is) / nZsteps; - map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, - s * correctionY, s * correctionZ); + if (iz == nZ2Xbins - 1) { + // extend value of the first Z bin to the readout, linear decrease of all values to 0. + int nZsteps = 3; + for (int is = 0; is < nZsteps; is++) { + double pz = z + (zEdge - z) * (is + 1.) / nZsteps; + double s = (nZsteps - 1. - is) / nZsteps; + map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, + s * correctionY, s * correctionZ); + } } } - } - } // iz - } // iy + } // iz + } // iy + + } // iRow + }; // myThread + + // run n threads + + int nThreads = mNthreads; + // nThreads = 1; + + std::vector threads(nThreads); + + for (int i = 0; i < nThreads; i++) { + threads[i] = std::thread(myThread, i, nThreads); + } - } // iRow + // wait for the threads to finish + for (auto& th : threads) { + th.join(); + } } // iRoc - LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch1.RealTime()); + LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch3.RealTime()); LOG(info) << "fast space charge correction helper: create space charge from the map of data points.."; + TStopwatch watch4; + helper->fillSpaceChargeCorrectionFromMap(correction); - LOGP(info, "Creation from track residuals tooks in total: {}s", watch2.RealTime()); + LOG(info) << "fast space charge correction helper: creation from the data map took " << watch4.RealTime() << "s"; + + LOGP(info, "Creation from track residuals tooks in total: {}s", watch.RealTime()); return std::move(correctionPtr); } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 5a7dffd2a753b..35c6e43daa43b 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -29,12 +29,9 @@ ClassImp(TPCFastSpaceChargeCorrection); TPCFastSpaceChargeCorrection::TPCFastSpaceChargeCorrection() : FlatObject(), - mConstructionRowInfos(nullptr), mConstructionScenarios(nullptr), mNumberOfScenarios(0), mScenarioPtr(nullptr), - mRowInfoPtr(nullptr), - mSliceRowInfoPtr(nullptr), mTimeStamp(-1), mSplineData{nullptr, nullptr, nullptr}, mSliceDataSizeBytes{0, 0, 0} @@ -52,21 +49,16 @@ void TPCFastSpaceChargeCorrection::releaseConstructionMemory() { // release temporary arrays #if !defined(GPUCA_GPUCODE) - delete[] mConstructionRowInfos; delete[] mConstructionScenarios; #endif - mConstructionRowInfos = nullptr; mConstructionScenarios = nullptr; } void TPCFastSpaceChargeCorrection::destroy() { releaseConstructionMemory(); - mConstructionRowInfos = nullptr; mConstructionScenarios = nullptr; mNumberOfScenarios = 0; - mRowInfoPtr = nullptr; - mSliceRowInfoPtr = nullptr; mScenarioPtr = nullptr; mTimeStamp = -1; for (int32_t is = 0; is < 3; is++) { @@ -78,8 +70,6 @@ void TPCFastSpaceChargeCorrection::destroy() void TPCFastSpaceChargeCorrection::relocateBufferPointers(const char* oldBuffer, char* newBuffer) { - mRowInfoPtr = FlatObject::relocatePointer(oldBuffer, newBuffer, mRowInfoPtr); - mSliceRowInfoPtr = FlatObject::relocatePointer(oldBuffer, newBuffer, mSliceRowInfoPtr); mScenarioPtr = FlatObject::relocatePointer(oldBuffer, newBuffer, mScenarioPtr); for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -119,13 +109,21 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mSliceDataSizeBytes[2] = obj.mSliceDataSizeBytes[2]; // variable-size data - mRowInfoPtr = obj.mRowInfoPtr; - mSliceRowInfoPtr = obj.mSliceRowInfoPtr; mScenarioPtr = obj.mScenarioPtr; mSplineData[0] = obj.mSplineData[0]; mSplineData[1] = obj.mSplineData[1]; mSplineData[2] = obj.mSplineData[2]; + mClassVersion = obj.mClassVersion; + + for (int i = 0; i < TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + mRowInfos[i] = obj.mRowInfos[i]; + } + + for (int i = 0; i < TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + mSliceRowInfos[i] = obj.mSliceRowInfos[i]; + } + relocateBufferPointers(oldFlatBufferPtr, mFlatBufferPtr); } @@ -140,19 +138,43 @@ void TPCFastSpaceChargeCorrection::moveBufferTo(char* newFlatBufferPtr) void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBufferPtr) { - /// Sets the actual location of the external flat buffer after it has been moved (i.e. to another maschine) + /// Sets the actual location of the external flat buffer after it has been moved (e.g. to another maschine) + + struct RowInfoVersion3 { + int splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC slice + }; + + struct RowActiveAreaVersion3 { + float maxDriftLengthCheb[5]{0.f}; + float vMax{0.f}; + float cuMin{0.f}; + float cuMax{0.f}; + float cvMax{0.f}; + }; + + struct SliceRowInfoVersion3 { + float gridV0{0.f}; ///< V coordinate of the V-grid start + float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U + float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V + float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate + float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate + RowActiveAreaVersion3 activeArea; + }; FlatObject::setActualBufferAddress(actualFlatBufferPtr); size_t rowsOffset = 0; - size_t rowsSize = sizeof(RowInfo) * mGeo.getNumberOfRows(); - - mRowInfoPtr = reinterpret_cast(mFlatBufferPtr + rowsOffset); + size_t rowsSize = 0; + if (mClassVersion == 3) { + rowsSize = sizeof(RowInfoVersion3) * mGeo.getNumberOfRows(); + } size_t sliceRowsOffset = rowsOffset + rowsSize; - size_t sliceRowsSize = sizeof(SliceRowInfo) * mGeo.getNumberOfRows() * mGeo.getNumberOfSlices(); - - mSliceRowInfoPtr = reinterpret_cast(mFlatBufferPtr + sliceRowsOffset); + size_t sliceRowsSize = 0; + if (mClassVersion == 3) { // copy old-format slicerow data from the buffer to the arrays + sliceRowsSize = sizeof(SliceRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfSlices(); + } size_t scOffset = alignSize(sliceRowsOffset + sliceRowsSize, SplineType::getClassAlignmentBytes()); size_t scSize = sizeof(SplineType) * mNumberOfScenarios; @@ -173,6 +195,53 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sliceDataOffset); bufferSize = sliceDataOffset + mSliceDataSizeBytes[is] * mGeo.getNumberOfSlices(); } + + if (mClassVersion == 3) { // copy old-format slicerow data from the buffer to the arrays + + auto* rowInfosOld = reinterpret_cast(mFlatBufferPtr + rowsOffset); + for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + RowInfoVersion3& infoOld = rowInfosOld[i]; + RowInfo& info = mRowInfos[i]; + info.splineScenarioID = infoOld.splineScenarioID; + for (int is = 0; is < 3; is++) { + info.dataOffsetBytes[is] = infoOld.dataOffsetBytes[is]; + } + } + + for (int is = 0; is < mNumberOfScenarios; is++) { + auto& spline = mScenarioPtr[is]; + spline.setXrange(0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax()); + } + + auto* sliceRowInfosOld = reinterpret_cast(mFlatBufferPtr + sliceRowsOffset); + + for (int slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { + for (int row = 0; row < mGeo.getNumberOfRows(); row++) { + SliceRowInfoVersion3& infoOld = sliceRowInfosOld[mGeo.getNumberOfRows() * slice + row]; + SliceRowInfo& info = getSliceRowInfo(slice, row); + const auto& spline = getSpline(slice, row); + info.gridU0 = mGeo.getRowInfo(row).u0; + info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); + + info.gridV0 = infoOld.gridV0; + info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength(slice) + 3. - info.gridV0); + + info.gridCorrU0 = infoOld.gridCorrU0; + info.scaleCorrUtoGrid = infoOld.scaleCorrUtoGrid; + + info.gridCorrV0 = infoOld.gridCorrV0; + info.scaleCorrVtoGrid = infoOld.scaleCorrVtoGrid; + + info.activeArea.vMax = infoOld.activeArea.vMax; + info.activeArea.cuMin = infoOld.activeArea.cuMin; + info.activeArea.cuMax = infoOld.activeArea.cuMax; + info.activeArea.cvMax = infoOld.activeArea.cvMax; + for (int i = 0; i < 5; i++) { + info.activeArea.maxDriftLengthCheb[i] = infoOld.activeArea.maxDriftLengthCheb[i]; + } + } + } + } } void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBufferPtr) @@ -187,10 +256,7 @@ void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBuffer char* oldBuffer = mFlatBufferPtr; char* newBuffer = futureFlatBufferPtr; - mRowInfoPtr = relocatePointer(oldBuffer, newBuffer, mRowInfoPtr); - mSliceRowInfoPtr = relocatePointer(oldBuffer, newBuffer, mSliceRowInfoPtr); - - for (int32_t i = 0; i < mNumberOfScenarios; i++) { + for (int i = 0; i < mNumberOfScenarios; i++) { SplineType& sp = mScenarioPtr[i]; char* newSplineBuf = relocatePointer(oldBuffer, newBuffer, sp.getFlatBufferPtr()); sp.setFutureBufferAddress(newSplineBuf); @@ -210,10 +276,10 @@ void TPCFastSpaceChargeCorrection::print() const LOG(info) << " mNumberOfScenarios = " << mNumberOfScenarios; LOG(info) << " mTimeStamp = " << mTimeStamp; LOG(info) << " mSliceDataSizeBytes = " << mSliceDataSizeBytes[0] << " " << mSliceDataSizeBytes[1] << " " << mSliceDataSizeBytes[2]; - if (mRowInfoPtr) { + { LOG(info) << " TPC rows: "; - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - RowInfo& r = mRowInfoPtr[i]; + for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + const RowInfo& r = mRowInfos[i]; LOG(info) << " tpc row " << i << ": splineScenarioID = " << r.splineScenarioID << " dataOffsetBytes = " << r.dataOffsetBytes; } } @@ -223,7 +289,7 @@ void TPCFastSpaceChargeCorrection::print() const mScenarioPtr[i].print(); } } - if (mRowInfoPtr && mScenarioPtr && mSliceRowInfoPtr) { + if (mScenarioPtr) { LOG(info) << " Spline Data: "; for (int32_t is = 0; is < mGeo.getNumberOfSlices(); is++) { for (int32_t ir = 0; ir < mGeo.getNumberOfRows(); ir++) { @@ -260,15 +326,13 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& releaseConstructionMemory(); #if !defined(GPUCA_GPUCODE) - mConstructionRowInfos = new RowInfo[mGeo.getNumberOfRows()]; mConstructionScenarios = new SplineType[mNumberOfScenarios]; #endif - assert(mConstructionRowInfos != nullptr); assert(mConstructionScenarios != nullptr); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - mConstructionRowInfos[i].splineScenarioID = -1; + for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + mRowInfos[i].splineScenarioID = -1; } for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -277,13 +341,12 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& mTimeStamp = -1; - mRowInfoPtr = nullptr; - mSliceRowInfoPtr = nullptr; mScenarioPtr = nullptr; for (int32_t s = 0; s < 3; s++) { mSplineData[s] = nullptr; mSliceDataSizeBytes[s] = 0; } + mClassVersion = 4; } void TPCFastSpaceChargeCorrection::setRowScenarioID(int32_t iRow, int32_t iScenario) @@ -292,7 +355,7 @@ void TPCFastSpaceChargeCorrection::setRowScenarioID(int32_t iRow, int32_t iScena assert(mConstructionMask & ConstructionState::InProgress); assert(iRow >= 0 && iRow < mGeo.getNumberOfRows() && iScenario >= 0 && iScenario < mNumberOfScenarios); - RowInfo& row = mConstructionRowInfos[iRow]; + RowInfo& row = mRowInfos[iRow]; row.splineScenarioID = iScenario; for (int32_t s = 0; s < 3; s++) { row.dataOffsetBytes[s] = 0; @@ -315,8 +378,8 @@ void TPCFastSpaceChargeCorrection::finishConstruction() assert(mConstructionMask & ConstructionState::InProgress); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - assert(mConstructionRowInfos[i].splineScenarioID >= 0); + for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + assert(mRowInfos[i].splineScenarioID >= 0); } for (int32_t i = 0; i < mNumberOfScenarios; i++) { assert(mConstructionScenarios[i].isConstructed()); @@ -324,13 +387,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() // organize memory for the flat buffer and caculate its size - size_t rowsOffset = 0; - size_t rowsSize = sizeof(RowInfo) * mGeo.getNumberOfRows(); - - size_t sliceRowsOffset = rowsSize; - size_t sliceRowsSize = sizeof(SliceRowInfo) * mGeo.getNumberOfRows() * mGeo.getNumberOfSlices(); - - size_t scOffset = alignSize(sliceRowsOffset + sliceRowsSize, SplineType::getClassAlignmentBytes()); + size_t scOffset = 0; size_t scSize = sizeof(SplineType) * mNumberOfScenarios; size_t scBufferOffsets[mNumberOfScenarios]; @@ -347,8 +404,8 @@ void TPCFastSpaceChargeCorrection::finishConstruction() for (int32_t is = 0; is < 3; is++) { sliceDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); mSliceDataSizeBytes[is] = 0; - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - RowInfo& row = mConstructionRowInfos[i]; + for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + RowInfo& row = mRowInfos[i]; SplineType& spline = mConstructionScenarios[row.splineScenarioID]; row.dataOffsetBytes[is] = alignSize(mSliceDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); mSliceDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); @@ -359,20 +416,6 @@ void TPCFastSpaceChargeCorrection::finishConstruction() FlatObject::finishConstruction(bufferSize); - mRowInfoPtr = reinterpret_cast(mFlatBufferPtr + rowsOffset); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - mRowInfoPtr[i] = mConstructionRowInfos[i]; - } - - mSliceRowInfoPtr = reinterpret_cast(mFlatBufferPtr + sliceRowsOffset); - for (int32_t s = 0; s < mGeo.getNumberOfSlices(); s++) { - for (int32_t r = 0; r < mGeo.getNumberOfRows(); r++) { - mSliceRowInfoPtr[s * mGeo.getNumberOfRows() + r].gridCorrU0 = 0.; - mSliceRowInfoPtr[s * mGeo.getNumberOfRows() + r].scaleCorrUtoGrid = 0.; - mSliceRowInfoPtr[s * mGeo.getNumberOfRows() + r].scaleCorrVtoGrid = 0.; - } - } - mScenarioPtr = reinterpret_cast(mFlatBufferPtr + scOffset); for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -417,20 +460,28 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() } SliceRowInfo& info = getSliceRowInfo(slice, row); + + info.gridU0 = mGeo.getRowInfo(row).u0; + info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); + + info.gridV0 = 0.f; + info.scaleVtoGrid = spline.getGridX2().getUmax() / vLength; + + info.gridCorrU0 = info.gridU0; + info.gridCorrV0 = info.gridV0; + info.scaleCorrUtoGrid = info.scaleUtoGrid; + info.scaleCorrVtoGrid = info.scaleVtoGrid; + RowActiveArea& area = info.activeArea; for (int32_t i = 1; i < 5; i++) { area.maxDriftLengthCheb[i] = 0; } area.maxDriftLengthCheb[0] = vLength; - area.cuMin = mGeo.convPadToU(row, 0.f); + area.cuMin = info.gridCorrU0; area.cuMax = -area.cuMin; area.vMax = vLength; area.cvMax = vLength; - info.gridV0 = 0.f; - info.gridCorrU0 = area.cuMin; - info.gridCorrV0 = info.gridV0; - info.scaleCorrUtoGrid = spline.getGridX1().getUmax() / (area.cuMax - area.cuMin); - info.scaleCorrVtoGrid = spline.getGridX2().getUmax() / area.cvMax; + } // row } // slice } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 9589ecbfc1fc4..b29d65b98458a 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -58,13 +58,16 @@ class TPCFastSpaceChargeCorrection : public FlatObject }; struct SliceRowInfo { + float gridU0{0.f}; //< U coordinate of the U-grid start + float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate float gridV0{0.f}; ///< V coordinate of the V-grid start + float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U - float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate + float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate RowActiveArea activeArea; - ClassDefNV(SliceRowInfo, 1); + ClassDefNV(SliceRowInfo, 2); }; struct SliceInfo { @@ -199,7 +202,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() float getInterpolationSafetyMargin() const { return fInterpolationSafetyMargin; } /// Gives TPC row info - GPUd() const RowInfo& getRowInfo(int32_t row) const { return mRowInfoPtr[row]; } + GPUd() const RowInfo& getRowInfo(int row) const { return mRowInfos[row]; } /// Gives TPC slice info GPUd() const SliceInfo& getSliceInfo(int32_t slice) const @@ -216,13 +219,13 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Gives TPC slice & row info GPUd() const SliceRowInfo& getSliceRowInfo(int32_t slice, int32_t row) const { - return mSliceRowInfoPtr[mGeo.getNumberOfRows() * slice + row]; + return mSliceRowInfos[mGeo.getMaxNumberOfRows() * slice + row]; } /// Gives TPC slice & row info GPUd() SliceRowInfo& getSliceRowInfo(int32_t slice, int32_t row) { - return mSliceRowInfoPtr[mGeo.getNumberOfRows() * slice + row]; + return mSliceRowInfos[mGeo.getMaxNumberOfRows() * slice + row]; } #if !defined(GPUCA_GPUCODE) @@ -244,7 +247,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// _______________ Construction control _______________________________________________ - RowInfo* mConstructionRowInfos = nullptr; //! (transient!!) Temporary container of the row infos during construction SplineType* mConstructionScenarios = nullptr; //! (transient!!) Temporary container for spline scenarios /// _______________ Geometry _______________________________________________ @@ -255,9 +257,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject SliceInfo mSliceInfo[TPCFastTransformGeo::getNumberOfSlices()]; ///< SliceInfo array - SplineType* mScenarioPtr; //! (transient!!) pointer to spline scenarios - RowInfo* mRowInfoPtr; //! (transient!!) pointer to RowInfo array inside the mFlatBufferPtr buffer - SliceRowInfo* mSliceRowInfoPtr; //! (transient!!) pointer to SliceRowInfo array inside the mFlatBufferPtr + SplineType* mScenarioPtr; //! (transient!!) pointer to spline scenarios /// _______________ Calibration data _______________________________________________ @@ -269,7 +269,16 @@ class TPCFastSpaceChargeCorrection : public FlatObject float fInterpolationSafetyMargin{0.1f}; // 10% area around the TPC row. Outside of this area the interpolation returns the boundary values. - ClassDefNV(TPCFastSpaceChargeCorrection, 3); + /// Class version. It is used to read older versions from disc. + /// The default version 3 is the one before this field was introduced. + /// The actual version must be set in startConstruction(). + int mClassVersion{3}; + + RowInfo mRowInfos[TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RowInfo array + + SliceRowInfo mSliceRowInfos[TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< SliceRowInfo array + + ClassDefNV(TPCFastSpaceChargeCorrection, 4); }; /// ==================================================== @@ -279,28 +288,28 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t slice, int32_t row) const { /// Gives const pointer to spline - const RowInfo& rowInfo = mRowInfoPtr[row]; + const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t slice, int32_t row) { /// Gives pointer to spline - const RowInfo& rowInfo = mRowInfoPtr[row]; + const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t slice, int32_t row, int32_t iSpline) { /// Gives pointer to spline data - const RowInfo& rowInfo = mRowInfoPtr[row]; + const RowInfo& rowInfo = mRowInfos[row]; return reinterpret_cast(mSplineData[iSpline] + mSliceDataSizeBytes[iSpline] * slice + rowInfo.dataOffsetBytes[iSpline]); } GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t slice, int32_t row, int32_t iSpline) const { /// Gives pointer to spline data - const RowInfo& rowInfo = mRowInfoPtr[row]; + const RowInfo& rowInfo = mRowInfos[row]; return reinterpret_cast(mSplineData[iSpline] + mSliceDataSizeBytes[iSpline] * slice + rowInfo.dataOffsetBytes[iSpline]); } @@ -356,35 +365,18 @@ GPUdi() void TPCFastSpaceChargeCorrection::schrinkCorrectedUV(int32_t slice, int GPUdi() void TPCFastSpaceChargeCorrection::convUVtoGrid(int32_t slice, int32_t row, float u, float v, float& gu, float& gv) const { - // TODO optimise !!! - gu = 0.f; - gv = 0.f; - schrinkUV(slice, row, u, v); - const SliceRowInfo& info = getSliceRowInfo(slice, row); - const SplineType& spline = getSpline(slice, row); - - float su0 = 0.f, sv0 = 0.f; - mGeo.convUVtoScaledUV(slice, row, u, info.gridV0, su0, sv0); - mGeo.convUVtoScaledUV(slice, row, u, v, gu, gv); - - gv = (gv - sv0) / (1.f - sv0); - gu *= spline.getGridX1().getUmax(); - gv *= spline.getGridX2().getUmax(); + gu = (u - info.gridU0) * info.scaleUtoGrid; + gv = (v - info.gridV0) * info.scaleVtoGrid; } GPUdi() void TPCFastSpaceChargeCorrection::convGridToUV(int32_t slice, int32_t row, float gridU, float gridV, float& u, float& v) const { - // TODO optimise - /// convert u,v to internal grid coordinates - float su0 = 0.f, sv0 = 0.f; + /// convert internal grid coordinates to u,v const SliceRowInfo& info = getSliceRowInfo(slice, row); - const SplineType& spline = getSpline(slice, row); - mGeo.convUVtoScaledUV(slice, row, 0.f, info.gridV0, su0, sv0); - float su = gridU / spline.getGridX1().getUmax(); - float sv = sv0 + gridV / spline.getGridX2().getUmax() * (1.f - sv0); - mGeo.convScaledUVtoUV(slice, row, su, sv, u, v); + u = info.gridU0 + gridU / info.scaleUtoGrid; + v = info.gridV0 + gridV / info.scaleVtoGrid; } GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t slice, int32_t row, float corrU, float corrV, float& gridU, float& gridV) const diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index 5eddada1e9acc..d20331ba6ab0f 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -50,6 +50,12 @@ class TPCFastTransformGeo float scaleUtoSU; ///< scale for su (scaled u ) coordinate float scaleSUtoU; ///< scale for u coordinate + /// get U min + GPUd() float getUmin() const { return u0; } + + /// get U max + GPUd() float getUmax() const { return -u0; } + /// get width in U GPUd() float getUwidth() const { return -2.f * u0; } ClassDefNV(RowInfo, 1); @@ -110,6 +116,9 @@ class TPCFastTransformGeo /// Gives number of TPC rows GPUd() int32_t getNumberOfRows() const { return mNumberOfRows; } + /// Gives number of TPC rows + GPUd() static constexpr int getMaxNumberOfRows() { return MaxNumberOfRows; } + /// Gives slice info GPUd() const SliceInfo& getSliceInfo(int32_t slice) const; diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index b13d031d6d10d..bf3e14d552715 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -59,6 +59,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", corr->Draw("cx:y:z","iRoc==0&&iRow==10","") grid->Draw("cx:y:z","iRoc==0&&iRow==10","same") vox->Draw("vx:y:z","iRoc==0&&iRow==10","same") + corrvox->Draw("cx:y:z","iRoc==0&&iRow==10","same") points->Draw("px:y:z","iRoc==0&&iRow==10","same") */ @@ -98,17 +99,36 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", trackResiduals.setZ2XBinning(z2xBins); trackResiduals.init(); - std::cout << "y2xBins: " << y2xBins.size() << " z2xBins: " << z2xBins.size() << std::endl; + { + std::cout << "input track residuals: " << std::endl; + std::cout << "voxel tree y2xBins: " << y2xBins.size() << std::endl; - for (auto y2x : y2xBins) { - std::cout << "y2x: " << y2x << std::endl; - } + for (auto y2x : y2xBins) { + std::cout << " y2x: " << y2x << std::endl; + } + std::cout << std::endl; + + int nY2Xbins = trackResiduals.getNY2XBins(); + + std::cout << " TrackResiduals y2x bins: " << nY2Xbins << std::endl; + for (int i = 0; i < nY2Xbins; i++) { + std::cout << "scaled getY2X(bin) : " << trackResiduals.getY2X(0, i) / trackResiduals.getMaxY2X(0) << std::endl; + } + + std::cout << "voxel tree z2xBins: " << z2xBins.size() << std::endl; - std::cout << std::endl; + for (auto z2x : z2xBins) { + std::cout << "z2x: " << z2x << std::endl; + } + std::cout << std::endl; - for (auto z2x : z2xBins) { - std::cout << "z2x: " << z2x << std::endl; + int nZ2Xbins = trackResiduals.getNZ2XBins(); + std::cout << " TrackResiduals z2x bins: " << nZ2Xbins << std::endl; + for (int i = 0; i < nZ2Xbins; i++) { + std::cout << "getZ2X(bin) : " << trackResiduals.getZ2X(i) << std::endl; + } } + std::cout << "create fast transformation ... " << std::endl; auto* helper = o2::tpc::TPCFastTransformHelperO2::instance(); @@ -122,16 +142,47 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", std::unique_ptr fastTransform( helper->create(0, *corrPtr)); - o2::gpu::TPCFastSpaceChargeCorrection& corr = fastTransform->getCorrection(); - std::cout << "... create fast transformation completed " << std::endl; if (*outFileName) { fastTransform->writeToFile(outFileName, "ccdb_object"); } + if (1) { // read transformation from the file + + // const char* fileName = "master/out.root"; + + const char* fileName = outFileName; + + std::cout << "load corrections from file " << fileName << std::endl; + + fastTransform->cloneFromObject(*TPCFastTransform::loadFromFile(fileName, "ccdb_object"), nullptr); + + o2::gpu::TPCFastSpaceChargeCorrection& corr = fastTransform->getCorrection(); + + if (0) { + std::cout << "check the loaded correction ..." << std::endl; + + const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); + + // for (int iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { + for (int iRoc = 0; iRoc < 1; iRoc++) { + for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { + auto& info = corr.getSliceRowInfo(iRoc, iRow); + std::cout << "roc " << iRoc << " row " << iRow + << " gridV0 " << info.gridV0 << " gridCorrU0 " << info.gridCorrU0 << " gridCorrV0 " << info.gridCorrV0 + << " scaleCorrUtoGrid " << info.scaleCorrUtoGrid << " scaleCorrVtoGrid " << info.scaleCorrVtoGrid + << " gridU0 " << info.gridU0 << " scaleUtoGrid " << info.scaleUtoGrid << " scaleVtoGrid " << info.scaleVtoGrid + << std::endl; + } + } + } + } + std::cout << "verify the results ..." << std::endl; + o2::gpu::TPCFastSpaceChargeCorrection& corr = fastTransform->getCorrection(); + // the difference double maxDiff[3] = {0., 0., 0.}; @@ -158,12 +209,21 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // ntuple with the input data: voxel corrections debugFile->cd(); TNtuple* debugVox = - new TNtuple("vox", "vox", "iRoc:iRow:x:y:z:vx:vy:vz:cx:cy:cz"); + new TNtuple("vox", "vox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz"); debugVox->SetMarkerStyle(8); debugVox->SetMarkerSize(0.8); debugVox->SetMarkerColor(kBlue); + // duplicate of debugVox + debugFile->cd(); + TNtuple* debugCorrVox = + new TNtuple("corrvox", "corrvox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz"); + + debugCorrVox->SetMarkerStyle(8); + debugCorrVox->SetMarkerSize(0.8); + debugCorrVox->SetMarkerColor(kMagenta); + // ntuple with spline grid points debugFile->cd(); TNtuple* debugGrid = new TNtuple("grid", "grid", "iRoc:iRow:x:y:z:cx:cy:cz"); @@ -244,13 +304,6 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", correctionZ *= -1.; } - // TODO: skip empty voxels? - if (voxEntries < 1.) { // no statistics - // std::cout << "Empty Voxel!!! corrections: " << correctionX << " " - // << correctionY << " " << correctionZ << std::endl; - // continue; - } - float u, v, cx, cu, cv, cy, cz; geo.convLocalToUV(iRoc, y, z, u, v); corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); @@ -258,19 +311,24 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", cy -= y; cz -= z; double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; - for (int32_t i = 0; i < 3; i++) { - if (fabs(maxDiff[i]) < fabs(d[i])) { - maxDiff[i] = d[i]; - maxDiffRoc[i] = iRoc; - maxDiffRow[i] = iRow; - std::cout << " roc " << iRoc << " row " << iRow << " xyz " << i - << " diff " << d[i] << std::endl; + if (voxEntries >= 1.) { + for (int i = 0; i < 3; i++) { + if (fabs(maxDiff[i]) < fabs(d[i])) { + maxDiff[i] = d[i]; + maxDiffRoc[i] = iRoc; + maxDiffRow[i] = iRow; + std::cout << " roc " << iRoc << " row " << iRow << " xyz " << i + << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; + } + sumDiff[i] += d[i] * d[i]; } - sumDiff[i] += d[i] * d[i]; + nDiff++; } - nDiff++; - debugVox->Fill(iRoc, iRow, x, y, z, correctionX, correctionY, correctionZ, + + debugVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, cx, cy, cz); + debugCorrVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, + cx, cy, cz); } std::cout << "create debug ntuples ..." << std::endl; @@ -282,43 +340,71 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", double x = geo.getRowInfo(iRow).x; + // the spline grid + + const auto& gridU = corr.getSpline(iRoc, iRow).getGridX1(); + const auto& gridV = corr.getSpline(iRoc, iRow).getGridX2(); + if (iRoc == 0 && iRow == 0) { + std::cout << "spline scenario " << corr.getRowInfo(iRow).splineScenarioID << std::endl; + std::cout << "spline grid U: u = " << 0 << ".." << gridU.getUmax() << ", x = " << gridU.getXmin() << ".." << gridU.getXmax() << std::endl; + std::cout << "spline grid V: u = " << 0 << ".." << gridV.getUmax() << ", x = " << gridV.getXmin() << ".." << gridV.getXmax() << std::endl; + } + // the correction + { + std::vector p[2], g[2]; - for (double su = 0.; su <= 1.0001; su += 0.01) { - for (double sv = 0.; sv <= 1.0001; sv += 0.1) { + p[0].push_back(geo.getRowInfo(iRow).getUmin()); + for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { float u, v; - geo.convScaledUVtoUV(iRoc, iRow, su, sv, u, v); - float y, z; - geo.convUVtoLocal(iRoc, u, v, y, z); - float cx, cu, cv; - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - float cy, cz; - geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); - cy -= y; - cz -= z; - debugCorr->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + corr.convGridToUV(iRoc, iRow, gridU.getKnot(iu).getU(), 0., u, v); + g[0].push_back(u); + p[0].push_back(u); } - } - - // the spline grid + p[0].push_back(geo.getRowInfo(iRow).getUmax()); - const auto& gridU = corr.getSpline(iRoc, iRow).getGridX1(); - const auto& gridV = corr.getSpline(iRoc, iRow).getGridX2(); - for (int32_t iu = 0; iu < gridU.getNumberOfKnots(); iu++) { - double su = gridU.convUtoX(gridU.getKnot(iu).getU()); - for (int32_t iv = 0; iv < gridV.getNumberOfKnots(); iv++) { - double sv = gridV.convUtoX(gridV.getKnot(iv).getU()); + p[1].push_back(0.); + for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { float u, v; - corr.convGridToUV(iRoc, iRow, iu, iv, u, v); - float y, z; - geo.convUVtoLocal(iRoc, u, v, y, z); - float cx, cu, cv; - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - float cy, cz; - geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); - cy -= y; - cz -= z; - debugGrid->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + corr.convGridToUV(iRoc, iRow, 0., gridV.getKnot(iv).getU(), u, v); + g[1].push_back(v); + p[1].push_back(v); + } + p[1].push_back(geo.getTPCzLength(iRoc)); + + for (int iuv = 0; iuv < 2; iuv++) { + int n = p[iuv].size(); + for (unsigned int i = 0; i < n - 1; i++) { + double d = (p[iuv][i + 1] - p[iuv][i]) / 10.; + for (int ii = 1; ii < 10; ii++) { + p[iuv].push_back(p[iuv][i] + d * ii); + } + } + std::sort(p[iuv].begin(), p[iuv].end()); + } + + for (int iter = 0; iter < 2; iter++) { + std::vector& pu = ((iter == 0) ? g[0] : p[0]); + std::vector& pv = ((iter == 0) ? g[1] : p[1]); + for (unsigned int iu = 0; iu < pu.size(); iu++) { + for (unsigned int iv = 0; iv < pv.size(); iv++) { + float u = pu[iu]; + float v = pv[iv]; + float x, y, z; + geo.convUVtoLocal(iRoc, u, v, y, z); + float cx, cu, cv; + corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); + float cy, cz; + geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); + cy -= y; + cz -= z; + if (iter == 0) { + debugGrid->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + } else { + debugCorr->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + } + } + } } } @@ -372,6 +458,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", debugFile->cd(); debugCorr->Write(); debugVox->Write(); + debugCorrVox->Write(); debugGrid->Write(); debugPoints->Write(); debugFile->Close(); From a0503b1c0646cf5534eb354b6fb8c8e784f35ddc Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 18 Apr 2024 00:30:38 +0000 Subject: [PATCH 04/26] TPC Splines: multithreaded reading of the residual tree --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 73 +++++++++---------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 861cacbe00012..ce0954120281f 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -31,6 +31,7 @@ #include "TStopwatch.h" #include "TTreeReader.h" #include "TTreeReaderValue.h" +#include "ROOT/TTreeProcessorMT.hxx" using namespace o2::gpu; @@ -541,9 +542,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect TStopwatch watch3; - // TTreeProcessorMT treeProcessor(*voxResTree); // multi-threaded tree processor - // treeProcessor.Init(voxResTree); - // read the data ROC by ROC // data in the tree is not sorted by row @@ -554,44 +552,40 @@ std::unique_ptr TPCFastSpaceChargeCorrect float mCx, mCy, mCz; // corrections to the local coordinates }; - std::vector vRocData[nRows]; - for (int ir = 0; ir < nRows; ir++) { + std::vector vRocData[nRows * nROCs]; + for (int ir = 0; ir < nRows * nROCs; ir++) { vRocData[ir].resize(nY2Xbins * nZ2Xbins); } - for (int iRoc = 0; iRoc < nROCs; iRoc++) { + { // read data from the tree to vRocData - for (int ir = 0; ir < nRows; ir++) { - for (int iv = 0; iv < nY2Xbins * nZ2Xbins; iv++) { - vRocData[ir][iv].mNentries = 0; - } - } + ROOT::TTreeProcessorMT processor(*voxResTree, mNthreads); - const int rocDataStart = iRoc * trackResiduals.getNVoxelsPerSector(); - const int rocDataEnd = rocDataStart + trackResiduals.getNVoxelsPerSector(); - - TTreeReader reader(voxResTree); - reader.SetEntriesRange(rocDataStart, rocDataEnd); - TTreeReaderValue v(reader, "voxRes"); - for (int iVox = rocDataStart; iVox < rocDataEnd; iVox++) { - reader.Next(); - // voxResTree->GetEntry(iVox); - if ((int)v->bsec != iRoc) { - LOG(fatal) << "Error reading voxels: voxel ROC number " << v->bsec << " is not equal to the expected " << iRoc; - continue; - } - int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) - if (iRow < 0 || iRow >= nRows) { - LOG(fatal) << "Row number " << iRow << " is out of range"; + auto myThread = [&](TTreeReader& readerSubRange) { + TTreeReaderValue v(readerSubRange, "voxRes"); + while (readerSubRange.Next()) { + int iRoc = (int)v->bsec; + if (iRoc < 0 || iRoc >= nROCs) { + LOG(fatal) << "Error reading voxels: voxel ROC number " << iRoc << " is out of range"; + continue; + } + int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) + if (iRow < 0 || iRow >= nRows) { + LOG(fatal) << "Row number " << iRow << " is out of range"; + } + int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 + int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 + auto& vox = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; + vox.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; + vox.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; + vox.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; + vox.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; } - int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 - int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - auto& vox = vRocData[iRow][iy * nZ2Xbins + iz]; - vox.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; - vox.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; - vox.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; - vox.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; - } + }; + processor.Process(myThread); + } + + for (int iRoc = 0; iRoc < nROCs; iRoc++) { // now process the data row-by-row @@ -615,7 +609,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect bool isDataFound = false; for (int iy = 0; iy < nY2Xbins; iy++) { for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; // y/x coordinate of the bin ~-0.15 ... 0.15 double y2x = trackResiduals.getY2X(xBin, iy); @@ -661,7 +655,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect for (int ismooth = 1; ismooth <= 2; ismooth++) { for (int iy = 0; iy < nY2Xbins; iy++) { for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; if (vox.mSmoothingStep <= ismooth) { // already filled continue; @@ -673,7 +667,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect double w = 0.; bool filled = false; auto update = [&](int iy1, int iz1) { - auto& data1 = vRocData[iRow][iy1 * nZ2Xbins + iz1]; + auto& data1 = vRocData[iRoc * nRows + iRow][iy1 * nZ2Xbins + iz1]; auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; if (vox1.mSmoothingStep >= ismooth) { return false; @@ -746,7 +740,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect for (int iy = 0; iy < nY2Xbins; iy++) { for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRow][iy * nZ2Xbins + iz]; + auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; if (vox.mSmoothingStep > 2) { LOG(fatal) << "empty voxel is not repared"; @@ -812,7 +806,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect for (auto& th : threads) { th.join(); } - } // iRoc LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch3.RealTime()); From db4a13a3b3285a4b1247936c4a892857e6ce2edb Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 20 Jun 2024 15:15:41 +0000 Subject: [PATCH 05/26] TPC Splines: add limits for SP correction values per TPC row --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 18 +++- .../TPCFastSpaceChargeCorrection.h | 96 ++++++++++++++----- .../macro/TPCFastTransformInit.C | 15 +-- 3 files changed, 96 insertions(+), 33 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index ce0954120281f..e71340a555227 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -144,6 +144,9 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas float* splineParameters = correction.getSplineData(slice, row); const std::vector& data = mCorrectionMap.getPoints(slice, row); int nDataPoints = data.size(); + auto& info = correction.getSliceRowInfo(slice, row); + info.resetMaxValues(); + info.resetMaxValuesInv(); if (nDataPoints >= 4) { std::vector pointSU(nDataPoints); std::vector pointSV(nDataPoints); @@ -156,6 +159,8 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas pointCorr[3 * i + 0] = dx; pointCorr[3 * i + 1] = du; pointCorr[3 * i + 2] = dv; + info.updateMaxValues(2. * dx, 2. * du, 2. * dv); + info.updateMaxValuesInv(-2. * dx, -2. * du, -2. * dv); } helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointSU[0], &pointSV[0], &pointCorr[0], nDataPoints); @@ -767,9 +772,20 @@ std::unique_ptr TPCFastSpaceChargeCorrect double yStep = (yLast - yFirst) / 2; + double zFirst = z - dz / 2.; + double zLast = z + dz / 2.; + double zStep = (zLast - zFirst) / 2.; + + if (0) { // no smoothing + yFirst = y; + yLast = y; + zFirst = z; + zLast = z; + } + for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { - for (double pz = z - dz / 2.; pz <= z + dz / 2. + 1.e-4; pz += dz / 2.) { + for (double pz = zFirst; pz <= zLast + zStep / 2.; pz += zStep) { map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, correctionZ); } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index b29d65b98458a..3fdc9b32e640c 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -58,15 +58,64 @@ class TPCFastSpaceChargeCorrection : public FlatObject }; struct SliceRowInfo { - float gridU0{0.f}; //< U coordinate of the U-grid start - float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate - float gridV0{0.f}; ///< V coordinate of the V-grid start - float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate - float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U - float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate - float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V - float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate + float gridU0{0.f}; //< U coordinate of the U-grid start + float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate + float gridV0{0.f}; ///< V coordinate of the V-grid start + float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate + float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U + float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate + float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V + float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate + float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV + float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV + float maxInvCorr[3]{10.f, 10.f, 10.f}; ///< max inverse correction for dX, dU, dV + float minInvCorr[3]{-10.f, -10.f, -10.f}; ///< min inverse correction for dX, dU, dV RowActiveArea activeArea; + + void resetMaxValues() + { + maxCorr[0] = 1.f; + minCorr[0] = -1.f; + maxCorr[1] = 1.f; + minCorr[1] = -1.f; + maxCorr[2] = 1.f; + minCorr[2] = -1.f; + } + + void updateMaxValues(float dx, float du, float dv) + { + maxCorr[0] = GPUCommonMath::Max(maxCorr[0], dx); + minCorr[0] = GPUCommonMath::Min(minCorr[0], dx); + + maxCorr[1] = GPUCommonMath::Max(maxCorr[1], du); + minCorr[1] = GPUCommonMath::Min(minCorr[1], du); + + maxCorr[2] = GPUCommonMath::Max(maxCorr[2], dv); + minCorr[2] = GPUCommonMath::Min(minCorr[2], dv); + } + + void resetMaxValuesInv() + { + maxInvCorr[0] = 1.f; + minInvCorr[0] = -1.f; + maxInvCorr[1] = 1.f; + minInvCorr[1] = -1.f; + maxInvCorr[2] = 1.f; + minInvCorr[2] = -1.f; + } + + void updateMaxValuesInv(float dx, float du, float dv) + { + maxInvCorr[0] = GPUCommonMath::Max(maxInvCorr[0], dx); + minInvCorr[0] = GPUCommonMath::Min(minInvCorr[0], dx); + + maxInvCorr[1] = GPUCommonMath::Max(maxInvCorr[1], du); + minInvCorr[1] = GPUCommonMath::Min(minInvCorr[1], du); + + maxInvCorr[2] = GPUCommonMath::Max(maxInvCorr[2], dv); + minInvCorr[2] = GPUCommonMath::Min(minInvCorr[2], dv); + } + ClassDefNV(SliceRowInfo, 2); }; @@ -397,12 +446,10 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t slice, int32 convUVtoGrid(slice, row, u, v, gridU, gridV); float dxuv[3]; spline.interpolateU(splineData, gridU, gridV, dxuv); - if (CAMath::Abs(dxuv[0]) > 100 || CAMath::Abs(dxuv[1]) > 100 || CAMath::Abs(dxuv[2]) > 100) { - dxuv[0] = dxuv[1] = dxuv[2] = 0; - } - dx = dxuv[0]; - du = dxuv[1]; - dv = dxuv[2]; + const auto& info = getSliceRowInfo(slice, row); + dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], dxuv[0])); + du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], dxuv[1])); + dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], dxuv[2])); return 0; } @@ -414,12 +461,10 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t slice, in convUVtoGrid(slice, row, u, v, gridU, gridV); float dxuv[3]; spline.interpolateUold(splineData, gridU, gridV, dxuv); - if (CAMath::Abs(dxuv[0]) > 100 || CAMath::Abs(dxuv[1]) > 100 || CAMath::Abs(dxuv[2]) > 100) { - dxuv[0] = dxuv[1] = dxuv[2] = 0; - } - dx = dxuv[0]; - du = dxuv[1]; - dv = dxuv[2]; + const auto& info = getSliceRowInfo(slice, row); + dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], dxuv[0])); + du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], dxuv[1])); + dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], dxuv[2])); return 0; } @@ -433,9 +478,8 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( const float* splineData = getSplineData(slice, row, 1); float dx = 0; spline.interpolateU(splineData, gridU, gridV, &dx); - if (CAMath::Abs(dx) > 100) { - dx = 0; - } + const auto& info = getSliceRowInfo(slice, row); + dx = GPUCommonMath::Max(info.minInvCorr[0], GPUCommonMath::Min(info.maxInvCorr[0], dx)); x = mGeo.getRowInfo(row).x + dx; } @@ -450,9 +494,9 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( float duv[2]; spline.interpolateU(splineData, gridU, gridV, duv); - if (CAMath::Abs(duv[0]) > 100 || CAMath::Abs(duv[1]) > 100) { - duv[0] = duv[1] = 0; - } + const auto& info = getSliceRowInfo(slice, row); + duv[0] = GPUCommonMath::Max(info.minInvCorr[1], GPUCommonMath::Min(info.maxInvCorr[1], duv[0])); + duv[1] = GPUCommonMath::Max(info.minInvCorr[2], GPUCommonMath::Min(info.maxInvCorr[2], duv[1])); nomU = corrU - duv[0]; nomV = corrV - duv[1]; } diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index bf3e14d552715..6134f33bcc423 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -21,8 +21,6 @@ /// root -l TPCFastTransformInit.C'("debugVoxRes.root")' /// -#include "Algorithm/RangeTokenizer.h" - #if !defined(__CLING__) || defined(__ROOTCLING__) #include @@ -41,6 +39,8 @@ #include "TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h" #endif +#include "Algorithm/RangeTokenizer.h" + using namespace o2::tpc; using namespace o2::gpu; @@ -99,8 +99,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", trackResiduals.setZ2XBinning(z2xBins); trackResiduals.init(); - { - std::cout << "input track residuals: " << std::endl; + { // debug output + + std::cout << " ===== input track residuals ==== " << std::endl; std::cout << "voxel tree y2xBins: " << y2xBins.size() << std::endl; for (auto y2x : y2xBins) { @@ -127,6 +128,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", for (int i = 0; i < nZ2Xbins; i++) { std::cout << "getZ2X(bin) : " << trackResiduals.getZ2X(i) << std::endl; } + std::cout << " ==================================== " << std::endl; } std::cout << "create fast transformation ... " << std::endl; @@ -310,6 +312,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); cy -= y; cz -= z; + double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; if (voxEntries >= 1.) { for (int i = 0; i < 3; i++) { @@ -317,8 +320,8 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", maxDiff[i] = d[i]; maxDiffRoc[i] = iRoc; maxDiffRow[i] = iRow; - std::cout << " roc " << iRoc << " row " << iRow << " xyz " << i - << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; + // std::cout << " roc " << iRoc << " row " << iRow << " xyz " << i + // << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; } sumDiff[i] += d[i] * d[i]; } From 8846402e1e11e05f996d1dd3659eff7082281129 Mon Sep 17 00:00:00 2001 From: sgorbunov Date: Fri, 5 Jul 2024 00:09:05 +0200 Subject: [PATCH 06/26] TPC Splines: disable smoothing --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 106 ++++++++++-------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index e71340a555227..acaf9c474e275 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -411,10 +411,14 @@ std::unique_ptr TPCFastSpaceChargeCorrect int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); + double marginY2X = trackResiduals.getY2X(0, 2) - trackResiduals.getY2X(0, 0); + double marginZ2X = trackResiduals.getZ2X(1) - trackResiduals.getZ2X(0); + std::vector yBinsInt; { std::vector yBins; - yBins.reserve(nY2Xbins); + yBins.reserve(nY2Xbins + 2); + yBins.push_back(trackResiduals.getY2X(0, 0) - marginY2X); for (int i = 0, j = nY2Xbins - 1; i <= j; i += 2, j -= 2) { if (i == j) { yBins.push_back(trackResiduals.getY2X(0, i)); @@ -425,6 +429,8 @@ std::unique_ptr TPCFastSpaceChargeCorrect yBins.push_back(trackResiduals.getY2X(0, j)); } } + yBins.push_back(trackResiduals.getY2X(0, nY2Xbins - 1) + marginY2X); + std::sort(yBins.begin(), yBins.end()); double dy = yBins[1] - yBins[0]; for (int i = 1; i < yBins.size(); i++) { @@ -452,10 +458,13 @@ std::unique_ptr TPCFastSpaceChargeCorrect std::vector zBinsInt; { std::vector zBins; - zBins.reserve(nZ2Xbins); + zBins.reserve(nZ2Xbins + 2); + zBins.push_back(-(trackResiduals.getZ2X(0) - marginZ2X)); for (int i = 0; i < nZ2Xbins; i += 2) { zBins.push_back(-trackResiduals.getZ2X(i)); } + zBins.push_back(-(trackResiduals.getZ2X(nZ2Xbins - 1) + 2. * marginZ2X)); + std::sort(zBins.begin(), zBins.end()); double dz = zBins[1] - zBins[0]; for (int i = 1; i < zBins.size(); i++) { @@ -465,7 +474,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect } zBinsInt.reserve(zBins.size()); // spline knots must be positioned on the grid with an integer internal coordinate - // lets copy the knot positions with the accuracy of 0.1*dz + // lets copy the knot positions with the accuracy of 0.01*dz dz = dz / 10.; double z0 = zBins[0]; double z1 = zBins[zBins.size() - 1]; @@ -525,10 +534,10 @@ std::unique_ptr TPCFastSpaceChargeCorrect const auto& rowInfo = geo.getRowInfo(iRow); auto& info = correction.getSliceRowInfo(iRoc, iRow); const auto& spline = correction.getSpline(iRoc, iRow); - double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); - double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); - double zMin = rowInfo.x * trackResiduals.getZ2X(0); - double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); + double yMin = rowInfo.x * (trackResiduals.getY2X(iRow, 0) - marginY2X); + double yMax = rowInfo.x * (trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1) + marginY2X); + double zMin = rowInfo.x * (trackResiduals.getZ2X(0) - marginZ2X); + double zMax = rowInfo.x * (trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1) + 2. * marginZ2X); double uMin = yMin; double uMax = yMax; double vMin = geo.getTPCzLength(iRoc) - zMax; @@ -585,6 +594,12 @@ std::unique_ptr TPCFastSpaceChargeCorrect vox.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; vox.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; vox.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; + if (0 && vox.mNentries < 1) { + vox.mCx = 0.; + vox.mCy = 0.; + vox.mCz = 0.; + vox.mNentries = 1; + } } }; processor.Process(myThread); @@ -711,29 +726,27 @@ std::unique_ptr TPCFastSpaceChargeCorrect // feed the row data to the helper - double yMin = 0., yMax = 0.; + double yMin = 0., yMax = 0., zMin = 0.; + + auto& info = correction.getSliceRowInfo(iRoc, iRow); + const auto& spline = correction.getSpline(iRoc, iRow); { - float u, v; - if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); - } else { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); - } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yMin = py; - } - { - float u, v; + float u0, u1, v0, v1; + correction.convGridToUV(iRoc, iRow, 0., 0., u0, v0); + correction.convGridToUV(iRoc, iRow, + spline.getGridX1().getUmax(), spline.getGridX2().getUmax(), u1, v1); + float y0, y1, z0, z1; + geo.convUVtoLocal(iRoc, u0, v0, y0, z0); + geo.convUVtoLocal(iRoc, u1, v1, y1, z1); if (iRoc < geo.getNumberOfSlicesA()) { - geo.convScaledUVtoUV(iRoc, iRow, 1., 0., u, v); + yMin = y0; + yMax = y1; } else { - geo.convScaledUVtoUV(iRoc, iRow, 0., 0., u, v); + yMin = y1; + yMax = y0; } - float py, pz; - geo.convUVtoLocal(iRoc, u, v, py, pz); - yMax = py; + zMin = z1; } double zEdge = 0.; @@ -759,28 +772,22 @@ std::unique_ptr TPCFastSpaceChargeCorrect double correctionY = data.mCy; double correctionZ = data.mCz; - double yFirst = y - dy / 2.; - double yLast = y + dy / 2.; + double yStep = dy / 2.; + double zStep = dz / 2.; + + double yFirst = y; + double yLast = y; + double zFirst = z; + double zLast = z; if (iy == 0) { // extend value of the first Y bin to the row edge yFirst = yMin; + yStep = (yLast - yFirst) / 2.; } if (iy == nY2Xbins - 1) { // extend value of the last Y bin to the row edge yLast = yMax; - } - - double yStep = (yLast - yFirst) / 2; - - double zFirst = z - dz / 2.; - double zLast = z + dz / 2.; - double zStep = (zLast - zFirst) / 2.; - - if (0) { // no smoothing - yFirst = y; - yLast = y; - zFirst = z; - zLast = z; + yStep = (yLast - yFirst) / 2.; } for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { @@ -790,9 +797,19 @@ std::unique_ptr TPCFastSpaceChargeCorrect correctionZ); } + if (iz == 0) { // extend value of the first Z bin to Z=0. + int nZsteps = 2; + for (int is = 0; is < nZsteps; is++) { + double pz = z + (zMin - z) * (is + 1.) / nZsteps; + double s = 1.; //(nZsteps - 1. - is) / nZsteps; + map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, + s * correctionY, s * correctionZ); + } + } + if (iz == nZ2Xbins - 1) { - // extend value of the first Z bin to the readout, linear decrease of all values to 0. - int nZsteps = 3; + // extend value of the last Z bin to the readout, linear decrease of all values to 0. + int nZsteps = 2; for (int is = 0; is < nZsteps; is++) { double pz = z + (zEdge - z) * (is + 1.) / nZsteps; double s = (nZsteps - 1. - is) / nZsteps; @@ -803,9 +820,8 @@ std::unique_ptr TPCFastSpaceChargeCorrect } } // iz } // iy - - } // iRow - }; // myThread + } // iRow + }; // myThread // run n threads From 34ca0f2905f142e316267ec04d20f0d216fe8f91 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 18 Jul 2024 20:27:35 +0200 Subject: [PATCH 07/26] TPC Splines: smooth to linear edges, crop at grid borders, use mean position of residuals --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 302 ++++++++---------- GPU/TPCFastTransformation/Spline1DSpec.h | 20 +- .../TPCFastSpaceChargeCorrection.cxx | 28 +- .../TPCFastSpaceChargeCorrection.h | 31 +- .../macro/TPCFastTransformInit.C | 44 +-- 5 files changed, 207 insertions(+), 218 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index acaf9c474e275..82a23dfa5242a 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -159,8 +159,8 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas pointCorr[3 * i + 0] = dx; pointCorr[3 * i + 1] = du; pointCorr[3 * i + 2] = dv; - info.updateMaxValues(2. * dx, 2. * du, 2. * dv); - info.updateMaxValuesInv(-2. * dx, -2. * du, -2. * dv); + info.updateMaxValues(20. * dx, 20. * du, 20. * dv); + info.updateMaxValuesInv(-20. * dx, -20. * du, -20. * dv); } helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointSU[0], &pointSV[0], &pointCorr[0], nDataPoints); @@ -411,95 +411,69 @@ std::unique_ptr TPCFastSpaceChargeCorrect int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); - double marginY2X = trackResiduals.getY2X(0, 2) - trackResiduals.getY2X(0, 0); - double marginZ2X = trackResiduals.getZ2X(1) - trackResiduals.getZ2X(0); + std::vector uvBinsDouble[2]; - std::vector yBinsInt; - { - std::vector yBins; - yBins.reserve(nY2Xbins + 2); - yBins.push_back(trackResiduals.getY2X(0, 0) - marginY2X); - for (int i = 0, j = nY2Xbins - 1; i <= j; i += 2, j -= 2) { - if (i == j) { - yBins.push_back(trackResiduals.getY2X(0, i)); - } else if (i + 1 == j) { - yBins.push_back(trackResiduals.getY2X(0, i)); - } else { - yBins.push_back(trackResiduals.getY2X(0, i)); - yBins.push_back(trackResiduals.getY2X(0, j)); - } + uvBinsDouble[0].reserve(nY2Xbins); + uvBinsDouble[1].reserve(nZ2Xbins); + + for (int i = 0, j = nY2Xbins - 1; i <= j; i += 2, j -= 2) { + uvBinsDouble[0].push_back(trackResiduals.getY2X(0, i)); + if (j >= i + 1) { + uvBinsDouble[0].push_back(trackResiduals.getY2X(0, j)); } - yBins.push_back(trackResiduals.getY2X(0, nY2Xbins - 1) + marginY2X); + } - std::sort(yBins.begin(), yBins.end()); - double dy = yBins[1] - yBins[0]; - for (int i = 1; i < yBins.size(); i++) { - if (yBins[i] - yBins[i - 1] < dy) { - dy = yBins[i] - yBins[i - 1]; + for (int i = 0, j = nZ2Xbins - 1; i <= j; i += 2, j -= 2) { + uvBinsDouble[1].push_back(-trackResiduals.getZ2X(i)); + if (j >= i + 1) { + uvBinsDouble[1].push_back(-trackResiduals.getZ2X(j)); + } + } + + std::vector uvBinsInt[2]; + + for (int iuv = 0; iuv < 2; iuv++) { + auto& bins = uvBinsDouble[iuv]; + std::sort(bins.begin(), bins.end()); + + auto& binsInt = uvBinsInt[iuv]; + binsInt.reserve(bins.size()); + + double dy = bins[1] - bins[0]; + for (int i = 2; i < bins.size(); i++) { + double dd = bins[i] - bins[i - 1]; + if (dd < dy) { + dy = dd; } } - yBinsInt.reserve(yBins.size()); // spline knots must be positioned on the grid with integer internal coordinate // take the knot position accuracy of 0.1*dy dy = dy / 10.; - double y0 = yBins[0]; - double y1 = yBins[yBins.size() - 1]; - for (auto& y : yBins) { + double y0 = bins[0]; + double y1 = bins[bins.size() - 1]; + for (auto& y : bins) { y -= y0; int iy = int(y / dy + 0.5); - yBinsInt.push_back(iy); + binsInt.push_back(iy); double yold = y / (y1 - y0) * 2 - 1.; y = iy * dy; y = y / (y1 - y0) * 2 - 1.; - LOG(info) << "convert y bin: " << yold << " -> " << y << " -> " << iy; - } - } - - std::vector zBinsInt; - { - std::vector zBins; - zBins.reserve(nZ2Xbins + 2); - zBins.push_back(-(trackResiduals.getZ2X(0) - marginZ2X)); - for (int i = 0; i < nZ2Xbins; i += 2) { - zBins.push_back(-trackResiduals.getZ2X(i)); - } - zBins.push_back(-(trackResiduals.getZ2X(nZ2Xbins - 1) + 2. * marginZ2X)); - - std::sort(zBins.begin(), zBins.end()); - double dz = zBins[1] - zBins[0]; - for (int i = 1; i < zBins.size(); i++) { - if (zBins[i] - zBins[i - 1] < dz) { - dz = zBins[i] - zBins[i - 1]; + if (iuv == 0) { + LOG(info) << "convert y bin: " << yold << " -> " << y << " -> " << iy; + } else { + LOG(info) << "convert z bin: " << yold << " -> " << y << " -> " << iy; } } - zBinsInt.reserve(zBins.size()); - // spline knots must be positioned on the grid with an integer internal coordinate - // lets copy the knot positions with the accuracy of 0.01*dz - dz = dz / 10.; - double z0 = zBins[0]; - double z1 = zBins[zBins.size() - 1]; - for (auto& z : zBins) { - z -= z0; - int iz = int(z / dz + 0.5); - zBinsInt.push_back(iz); - double zold = z / (z1 - z0); - z = iz * dz; - z = z / (z1 - z0); - LOG(info) << "convert z bin: " << zold << " -> " << z << " -> " << iz; - } - } - if (yBinsInt.size() < 2) { - yBinsInt.clear(); - yBinsInt.push_back(0); - yBinsInt.push_back(1); + if (binsInt.size() < 2) { + binsInt.clear(); + binsInt.push_back(0); + binsInt.push_back(1); + } } - if (zBinsInt.size() < 2) { - zBinsInt.clear(); - zBinsInt.push_back(0); - zBinsInt.push_back(1); - } + auto& yBinsInt = uvBinsInt[0]; + auto& zBinsInt = uvBinsInt[1]; int nKnotsY = yBinsInt.size(); int nKnotsZ = zBinsInt.size(); @@ -534,10 +508,10 @@ std::unique_ptr TPCFastSpaceChargeCorrect const auto& rowInfo = geo.getRowInfo(iRow); auto& info = correction.getSliceRowInfo(iRoc, iRow); const auto& spline = correction.getSpline(iRoc, iRow); - double yMin = rowInfo.x * (trackResiduals.getY2X(iRow, 0) - marginY2X); - double yMax = rowInfo.x * (trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1) + marginY2X); - double zMin = rowInfo.x * (trackResiduals.getZ2X(0) - marginZ2X); - double zMax = rowInfo.x * (trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1) + 2. * marginZ2X); + double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); + double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); + double zMin = rowInfo.x * trackResiduals.getZ2X(0); + double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); double uMin = yMin; double uMax = yMax; double vMin = geo.getTPCzLength(iRoc) - zMax; @@ -563,6 +537,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect struct VoxelData { int mNentries{0}; // number of entries + float mX, mY, mZ; // mean position in the local coordinates float mCx, mCy, mCz; // corrections to the local coordinates }; @@ -589,16 +564,19 @@ std::unique_ptr TPCFastSpaceChargeCorrect } int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - auto& vox = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; - vox.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; - vox.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; - vox.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; - vox.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; - if (0 && vox.mNentries < 1) { - vox.mCx = 0.; - vox.mCy = 0.; - vox.mCz = 0.; - vox.mNentries = 1; + auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; + data.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; + data.mX = v->stat[o2::tpc::TrackResiduals::VoxX]; + data.mY = v->stat[o2::tpc::TrackResiduals::VoxF]; + data.mZ = v->stat[o2::tpc::TrackResiduals::VoxZ]; + data.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; + data.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; + data.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; + if (0 && data.mNentries < 1) { + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + data.mNentries = 1; } } }; @@ -642,10 +620,27 @@ std::unique_ptr TPCFastSpaceChargeCorrect if (iRoc >= geo.getNumberOfSlicesA()) { vox.mZ = -vox.mZ; } + data.mY *= x; + data.mZ *= x; + /* + if ( fabs(x - data.mX) > 0.01 || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { + std::cout + << " roc " << iRoc << " row " << iRow + << " voxel x " << x << " y " << vox.mY << " z " << vox.mZ + << " data x " << data.mX << " y " << data.mY << " z " << data.mZ + << std::endl; + } + */ + if (1) { // always use voxel center instead of the mean position + data.mY = vox.mY; + data.mZ = vox.mZ; + } if (data.mNentries < 1) { // no data data.mCx = 0.; data.mCy = 0.; data.mCz = 0.; + data.mY = vox.mY; + data.mZ = vox.mZ; vox.mSmoothingStep = 100; } else { // voxel contains data if (invertSigns) { @@ -726,102 +721,59 @@ std::unique_ptr TPCFastSpaceChargeCorrect // feed the row data to the helper - double yMin = 0., yMax = 0., zMin = 0.; - auto& info = correction.getSliceRowInfo(iRoc, iRow); const auto& spline = correction.getSpline(iRoc, iRow); - { - float u0, u1, v0, v1; - correction.convGridToUV(iRoc, iRow, 0., 0., u0, v0); - correction.convGridToUV(iRoc, iRow, - spline.getGridX1().getUmax(), spline.getGridX2().getUmax(), u1, v1); - float y0, y1, z0, z1; - geo.convUVtoLocal(iRoc, u0, v0, y0, z0); - geo.convUVtoLocal(iRoc, u1, v1, y1, z1); - if (iRoc < geo.getNumberOfSlicesA()) { - yMin = y0; - yMax = y1; - } else { - yMin = y1; - yMax = y0; + auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nSteps) { + auto& data1 = vRocData[iRoc * nRows + iRow][iy1 * nZ2Xbins + iz1]; + auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; + auto& data2 = vRocData[iRoc * nRows + iRow][iy2 * nZ2Xbins + iz2]; + auto& vox2 = vRowVoxels[iy2 * nZ2Xbins + iz2]; + if (vox1.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared: y " << iy1 << " z " << iz1; } - zMin = z1; - } - - double zEdge = 0.; - if (iRoc < geo.getNumberOfSlicesA()) { - zEdge = geo.getTPCzLengthA(); - } else { - zEdge = -geo.getTPCzLengthC(); - } + if (vox2.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared: y " << iy2 << " z " << iz2; + } + double y1 = vox1.mY; + double z1 = vox1.mZ; + double cx1 = data1.mCx; + double cy1 = data1.mCy; + double cz1 = data1.mCz; + double y2 = vox2.mY; + double z2 = vox2.mZ; + double cx2 = data2.mCx; + double cy2 = data2.mCy; + double cz2 = data2.mCz; + + for (int is = 0; is < nSteps; is++) { + double s2 = is / (double)nSteps; + double s1 = 1. - s2; + double y = s1 * y1 + s2 * y2; + double z = s1 * z1 + s2 * z2; + double cx = s1 * cx1 + s2 * cx2; + double cy = s1 * cy1 + s2 * cy2; + double cz = s1 * cz1 + s2 * cz2; + map.addCorrectionPoint(iRoc, iRow, y, z, cx, cy, cz); + } + }; for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - if (vox.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared"; - } - - double y = vox.mY; - double z = vox.mZ; - double dy = vox.mDy; - double dz = vox.mDz; - double correctionX = data.mCx; - double correctionY = data.mCy; - double correctionZ = data.mCz; - - double yStep = dy / 2.; - double zStep = dz / 2.; - - double yFirst = y; - double yLast = y; - double zFirst = z; - double zLast = z; - - if (iy == 0) { // extend value of the first Y bin to the row edge - yFirst = yMin; - yStep = (yLast - yFirst) / 2.; - } - - if (iy == nY2Xbins - 1) { // extend value of the last Y bin to the row edge - yLast = yMax; - yStep = (yLast - yFirst) / 2.; - } - - for (double py = yFirst; py <= yLast + yStep / 2.; py += yStep) { - - for (double pz = zFirst; pz <= zLast + zStep / 2.; pz += zStep) { - map.addCorrectionPoint(iRoc, iRow, py, pz, correctionX, correctionY, - correctionZ); - } + for (int iz = 0; iz < nZ2Xbins - 1; iz++) { + addEdge(iy, iz, iy, iz + 1, 3); + } + addEdge(iy, nZ2Xbins - 1, iy, nZ2Xbins - 1, 1); + } - if (iz == 0) { // extend value of the first Z bin to Z=0. - int nZsteps = 2; - for (int is = 0; is < nZsteps; is++) { - double pz = z + (zMin - z) * (is + 1.) / nZsteps; - double s = 1.; //(nZsteps - 1. - is) / nZsteps; - map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, - s * correctionY, s * correctionZ); - } - } + for (int iz = 0; iz < nZ2Xbins; iz++) { + for (int iy = 0; iy < nY2Xbins - 1; iy++) { + addEdge(iy, iz, iy + 1, iz, 3); + } + addEdge(nY2Xbins - 1, iz, nY2Xbins - 1, iz, 1); + } // iy - if (iz == nZ2Xbins - 1) { - // extend value of the last Z bin to the readout, linear decrease of all values to 0. - int nZsteps = 2; - for (int is = 0; is < nZsteps; is++) { - double pz = z + (zEdge - z) * (is + 1.) / nZsteps; - double s = (nZsteps - 1. - is) / nZsteps; - map.addCorrectionPoint(iRoc, iRow, py, pz, s * correctionX, - s * correctionY, s * correctionZ); - } - } - } - } // iz - } // iy - } // iRow - }; // myThread + } // iRow + }; // myThread // run n threads diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index 6462f291d1136..dc59e77e308a1 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -313,6 +313,14 @@ class Spline1DSpec : public Spline1DContainer { const auto nYdimTmp = SplineUtil::getNdim(inpYdim); const auto nYdim = nYdimTmp.get(); + + if (u < (DataT)0) { + u = (DataT)0; + } + if (u > (DataT)TBase::getUmax()) { + u = (DataT)TBase::getUmax(); + } + T uu = T(u - knotL.u); T li = T(knotL.Li); T v = uu * li; // scaled u @@ -337,11 +345,19 @@ class Spline1DSpec : public Spline1DContainer } template - GPUd() static void getUderivatives(const Knot& knotL, DataT u, - T& dSl, T& dDl, T& dSr, T& dDr) + GPUd() void getUderivatives(const Knot& knotL, DataT u, + T& dSl, T& dDl, T& dSr, T& dDr) const { /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] /// over the spline values Sl, Sr and the slopes Dl, Dr + + if (u < (DataT)0) { + u = (DataT)0; + } + if (u > (DataT)TBase::getUmax()) { + u = (DataT)TBase::getUmax(); + } + u = u - knotL.u; T v = u * T(knotL.Li); // scaled u T vm1 = v - 1.; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 35c6e43daa43b..eb69983cf87ce 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -116,11 +116,11 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mClassVersion = obj.mClassVersion; - for (int i = 0; i < TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + for (int32_t i = 0; i < TPCFastTransformGeo::getMaxNumberOfRows(); i++) { mRowInfos[i] = obj.mRowInfos[i]; } - for (int i = 0; i < TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { mSliceRowInfos[i] = obj.mSliceRowInfos[i]; } @@ -141,7 +141,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer /// Sets the actual location of the external flat buffer after it has been moved (e.g. to another maschine) struct RowInfoVersion3 { - int splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) + int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC slice }; @@ -199,24 +199,24 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer if (mClassVersion == 3) { // copy old-format slicerow data from the buffer to the arrays auto* rowInfosOld = reinterpret_cast(mFlatBufferPtr + rowsOffset); - for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { RowInfoVersion3& infoOld = rowInfosOld[i]; RowInfo& info = mRowInfos[i]; info.splineScenarioID = infoOld.splineScenarioID; - for (int is = 0; is < 3; is++) { + for (int32_t is = 0; is < 3; is++) { info.dataOffsetBytes[is] = infoOld.dataOffsetBytes[is]; } } - for (int is = 0; is < mNumberOfScenarios; is++) { + for (int32_t is = 0; is < mNumberOfScenarios; is++) { auto& spline = mScenarioPtr[is]; spline.setXrange(0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax()); } auto* sliceRowInfosOld = reinterpret_cast(mFlatBufferPtr + sliceRowsOffset); - for (int slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { - for (int row = 0; row < mGeo.getNumberOfRows(); row++) { + for (int32_t slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { + for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { SliceRowInfoVersion3& infoOld = sliceRowInfosOld[mGeo.getNumberOfRows() * slice + row]; SliceRowInfo& info = getSliceRowInfo(slice, row); const auto& spline = getSpline(slice, row); @@ -236,7 +236,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer info.activeArea.cuMin = infoOld.activeArea.cuMin; info.activeArea.cuMax = infoOld.activeArea.cuMax; info.activeArea.cvMax = infoOld.activeArea.cvMax; - for (int i = 0; i < 5; i++) { + for (int32_t i = 0; i < 5; i++) { info.activeArea.maxDriftLengthCheb[i] = infoOld.activeArea.maxDriftLengthCheb[i]; } } @@ -256,7 +256,7 @@ void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBuffer char* oldBuffer = mFlatBufferPtr; char* newBuffer = futureFlatBufferPtr; - for (int i = 0; i < mNumberOfScenarios; i++) { + for (int32_t i = 0; i < mNumberOfScenarios; i++) { SplineType& sp = mScenarioPtr[i]; char* newSplineBuf = relocatePointer(oldBuffer, newBuffer, sp.getFlatBufferPtr()); sp.setFutureBufferAddress(newSplineBuf); @@ -278,7 +278,7 @@ void TPCFastSpaceChargeCorrection::print() const LOG(info) << " mSliceDataSizeBytes = " << mSliceDataSizeBytes[0] << " " << mSliceDataSizeBytes[1] << " " << mSliceDataSizeBytes[2]; { LOG(info) << " TPC rows: "; - for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { const RowInfo& r = mRowInfos[i]; LOG(info) << " tpc row " << i << ": splineScenarioID = " << r.splineScenarioID << " dataOffsetBytes = " << r.dataOffsetBytes; } @@ -331,7 +331,7 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& assert(mConstructionScenarios != nullptr); - for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { mRowInfos[i].splineScenarioID = -1; } @@ -378,7 +378,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() assert(mConstructionMask & ConstructionState::InProgress); - for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { assert(mRowInfos[i].splineScenarioID >= 0); } for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -404,7 +404,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() for (int32_t is = 0; is < 3; is++) { sliceDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); mSliceDataSizeBytes[is] = 0; - for (int i = 0; i < mGeo.getNumberOfRows(); i++) { + for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { RowInfo& row = mRowInfos[i]; SplineType& spline = mConstructionScenarios[row.splineScenarioID]; row.dataOffsetBytes[is] = alignSize(mSliceDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 3fdc9b32e640c..e69983fab9175 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -251,7 +251,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() float getInterpolationSafetyMargin() const { return fInterpolationSafetyMargin; } /// Gives TPC row info - GPUd() const RowInfo& getRowInfo(int row) const { return mRowInfos[row]; } + GPUd() const RowInfo& getRowInfo(int32_t row) const { return mRowInfos[row]; } /// Gives TPC slice info GPUd() const SliceInfo& getSliceInfo(int32_t slice) const @@ -321,7 +321,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Class version. It is used to read older versions from disc. /// The default version 3 is the one before this field was introduced. /// The actual version must be set in startConstruction(). - int mClassVersion{3}; + int32_t mClassVersion{3}; RowInfo mRowInfos[TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RowInfo array @@ -447,9 +447,17 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t slice, int32 float dxuv[3]; spline.interpolateU(splineData, gridU, gridV, dxuv); const auto& info = getSliceRowInfo(slice, row); - dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], dxuv[0])); - du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], dxuv[1])); - dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], dxuv[2])); + float s = v / info.gridV0; + if (s < 0.) { + s = 0.; + } + if (s > 1.) { + s = 1.; + } + + dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], s * dxuv[0])); + du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], s * dxuv[1])); + dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], s * dxuv[2])); return 0; } @@ -462,9 +470,16 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t slice, in float dxuv[3]; spline.interpolateUold(splineData, gridU, gridV, dxuv); const auto& info = getSliceRowInfo(slice, row); - dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], dxuv[0])); - du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], dxuv[1])); - dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], dxuv[2])); + float s = v / info.gridV0; + if (s < 0.) { + s = 0.; + } + if (s > 1.) { + s = 1.; + } + dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], s * dxuv[0])); + du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], s * dxuv[1])); + dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], s * dxuv[2])); return 0; } diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 6134f33bcc423..c4b0680f2edd4 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -109,10 +109,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", } std::cout << std::endl; - int nY2Xbins = trackResiduals.getNY2XBins(); + int32_t nY2Xbins = trackResiduals.getNY2XBins(); std::cout << " TrackResiduals y2x bins: " << nY2Xbins << std::endl; - for (int i = 0; i < nY2Xbins; i++) { + for (int32_t i = 0; i < nY2Xbins; i++) { std::cout << "scaled getY2X(bin) : " << trackResiduals.getY2X(0, i) / trackResiduals.getMaxY2X(0) << std::endl; } @@ -123,9 +123,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", } std::cout << std::endl; - int nZ2Xbins = trackResiduals.getNZ2XBins(); + int32_t nZ2Xbins = trackResiduals.getNZ2XBins(); std::cout << " TrackResiduals z2x bins: " << nZ2Xbins << std::endl; - for (int i = 0; i < nZ2Xbins; i++) { + for (int32_t i = 0; i < nZ2Xbins; i++) { std::cout << "getZ2X(bin) : " << trackResiduals.getZ2X(i) << std::endl; } std::cout << " ==================================== " << std::endl; @@ -138,6 +138,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", o2::tpc::TPCFastSpaceChargeCorrectionHelper* corrHelper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); corrHelper->setNthreadsToMaximum(); + // corrHelper->setNthreads(1); auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, useSmoothed, invertSigns); @@ -167,9 +168,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); - // for (int iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { - for (int iRoc = 0; iRoc < 1; iRoc++) { - for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { + // for (int32_t iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { + for (int32_t iRoc = 0; iRoc < 1; iRoc++) { + for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { auto& info = corr.getSliceRowInfo(iRoc, iRow); std::cout << "roc " << iRoc << " row " << iRow << " gridV0 " << info.gridV0 << " gridCorrU0 " << info.gridCorrU0 << " gridCorrV0 " << info.gridCorrV0 @@ -257,8 +258,8 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", branch->SetAddress(&v); branch->SetAutoDelete(kTRUE); - int iRocLast = -1; - int iRowLast = -1; + int32_t iRocLast = -1; + int32_t iRowLast = -1; for (int32_t iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { @@ -306,6 +307,11 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", correctionZ *= -1.; } + if (voxEntries > 0.) { // use mean statistical positions instead of the bin centers: + y = x * v->stat[o2::tpc::TrackResiduals::VoxF]; + z = x * v->stat[o2::tpc::TrackResiduals::VoxZ]; + } + float u, v, cx, cu, cv, cy, cz; geo.convLocalToUV(iRoc, y, z, u, v); corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); @@ -315,7 +321,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; if (voxEntries >= 1.) { - for (int i = 0; i < 3; i++) { + for (int32_t i = 0; i < 3; i++) { if (fabs(maxDiff[i]) < fabs(d[i])) { maxDiff[i] = d[i]; maxDiffRoc[i] = iRoc; @@ -358,7 +364,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", std::vector p[2], g[2]; p[0].push_back(geo.getRowInfo(iRow).getUmin()); - for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { + for (int32_t iu = 0; iu < gridU.getNumberOfKnots(); iu++) { float u, v; corr.convGridToUV(iRoc, iRow, gridU.getKnot(iu).getU(), 0., u, v); g[0].push_back(u); @@ -367,7 +373,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", p[0].push_back(geo.getRowInfo(iRow).getUmax()); p[1].push_back(0.); - for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { + for (int32_t iv = 0; iv < gridV.getNumberOfKnots(); iv++) { float u, v; corr.convGridToUV(iRoc, iRow, 0., gridV.getKnot(iv).getU(), u, v); g[1].push_back(v); @@ -375,22 +381,22 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", } p[1].push_back(geo.getTPCzLength(iRoc)); - for (int iuv = 0; iuv < 2; iuv++) { - int n = p[iuv].size(); - for (unsigned int i = 0; i < n - 1; i++) { + for (int32_t iuv = 0; iuv < 2; iuv++) { + int32_t n = p[iuv].size(); + for (int32_t i = 0; i < n - 1; i++) { double d = (p[iuv][i + 1] - p[iuv][i]) / 10.; - for (int ii = 1; ii < 10; ii++) { + for (int32_t ii = 1; ii < 10; ii++) { p[iuv].push_back(p[iuv][i] + d * ii); } } std::sort(p[iuv].begin(), p[iuv].end()); } - for (int iter = 0; iter < 2; iter++) { + for (int32_t iter = 0; iter < 2; iter++) { std::vector& pu = ((iter == 0) ? g[0] : p[0]); std::vector& pv = ((iter == 0) ? g[1] : p[1]); - for (unsigned int iu = 0; iu < pu.size(); iu++) { - for (unsigned int iv = 0; iv < pv.size(); iv++) { + for (uint32_t iu = 0; iu < pu.size(); iu++) { + for (uint32_t iv = 0; iv < pv.size(); iv++) { float u = pu[iu]; float v = pv[iv]; float x, y, z; From f2274774397bfe73fddaf2214bd7e8b70e8fe611 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 16 Jan 2025 21:06:18 +0000 Subject: [PATCH 08/26] TPC Splines: fix the inverse correction --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 100 ++++++++++-------- .../TPCFastSpaceChargeCorrection.cxx | 70 +++++++----- .../TPCFastSpaceChargeCorrection.h | 45 ++++---- .../macro/TPCFastTransformInit.C | 88 +++++++++------ 4 files changed, 179 insertions(+), 124 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 82a23dfa5242a..3696df5343ad3 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -146,7 +146,6 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas int nDataPoints = data.size(); auto& info = correction.getSliceRowInfo(slice, row); info.resetMaxValues(); - info.resetMaxValuesInv(); if (nDataPoints >= 4) { std::vector pointSU(nDataPoints); std::vector pointSV(nDataPoints); @@ -160,7 +159,6 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas pointCorr[3 * i + 1] = du; pointCorr[3 * i + 2] = dv; info.updateMaxValues(20. * dx, 20. * du, 20. * dv); - info.updateMaxValuesInv(-20. * dx, -20. * du, -20. * dv); } helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointSU[0], &pointSV[0], &pointCorr[0], nDataPoints); @@ -908,46 +906,60 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector helper; std::vector splineParameters; - ChebyshevFit1D chebFitterX, chebFitterU, chebFitterV; for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(slice, row); helper.setSpline(spline, 10, 10); - std::vector dataPointCU, dataPointCV, dataPointF; - - float u0, u1, v0, v1; - mGeo.convScaledUVtoUV(slice, row, 0., 0., u0, v0); - mGeo.convScaledUVtoUV(slice, row, 1., 1., u1, v1); double x = mGeo.getRowInfo(row).x; - int nPointsU = (spline.getGridX1().getNumberOfKnots() - 1) * 10; - int nPointsV = (spline.getGridX2().getNumberOfKnots() - 1) * 10; - - double stepU = (u1 - u0) / (nPointsU - 1); - double stepV = (v1 - v0) / (nPointsV - 1); + auto& sliceRowInfo = correction.getSliceRowInfo(slice, row); - if (prn) { - LOG(info) << "u0 " << u0 << " u1 " << u1 << " v0 " << v0 << " v1 " << v1; + std::vector gridU; + { + const auto& grid = spline.getGridX1(); + for (int i = 0; i < grid.getNumberOfKnots(); i++) { + if (i == grid.getNumberOfKnots() - 1) { + gridU.push_back(grid.getKnot(i).u); + break; + } + for (double s = 1.; s > 0.; s -= 0.1) { + gridU.push_back(s * grid.getKnot(i).u + (1. - s) * grid.getKnot(i + 1).u); + } + } + } + std::vector gridV; + { + const auto& grid = spline.getGridX2(); + for (int i = 0; i < grid.getNumberOfKnots(); i++) { + if (i == grid.getNumberOfKnots() - 1) { + gridV.push_back(grid.getKnot(i).u); + break; + } + for (double s = 1.; s > 0.; s -= 0.1) { + gridV.push_back(s * grid.getKnot(i).u + (1. - s) * grid.getKnot(i + 1).u); + } + } } - TPCFastSpaceChargeCorrection::RowActiveArea& area = correction.getSliceRowInfo(slice, row).activeArea; + + std::vector dataPointCU, dataPointCV, dataPointF; + dataPointCU.reserve(gridU.size() * gridV.size()); + dataPointCV.reserve(gridU.size() * gridV.size()); + dataPointF.reserve(gridU.size() * gridV.size()); + + TPCFastSpaceChargeCorrection::RowActiveArea& area = sliceRowInfo.activeArea; area.cuMin = 1.e10; area.cuMax = -1.e10; + double cvMin = 1.e10; - /* - v1 = area.vMax; - stepV = (v1 - v0) / (nPointsU - 1); - if (stepV < 1.f) { - stepV = 1.f; - } - */ + for (int iu = 0; iu < gridU.size(); iu++) { + for (int iv = 0; iv < gridV.size(); iv++) { + float u, v; + correction.convGridToUV(slice, row, gridU[iu], gridV[iv], u, v); - for (double u = u0; u < u1 + stepU; u += stepU) { - for (double v = v0; v < v1 + stepV; v += stepV) { float dx, du, dv; correction.getCorrection(slice, row, u, v, dx, du, dv); dx *= scaling[0]; @@ -976,39 +988,41 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector +#include #include #include "Spline2DHelper.h" #endif @@ -514,15 +515,41 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfSlicesA() / 2) + 1.; tpcR2max = tpcR2max * tpcR2max; - double maxDtpc[3] = {0, 0, 0}; - double maxD = 0; + struct MaxValue { + double V{0.}; + int Roc{-1}; + int Row{-1}; + + void update(double v, int roc, int row) + { + if (fabs(v) > fabs(V)) { + V = v; + Roc = roc; + Row = row; + } + } + void update(const MaxValue& other) + { + update(other.V, other.Roc, other.Row); + } + + std::string toString() + { + std::stringstream ss; + ss << V << "(" << Roc << "," << Row << ")"; + return ss.str(); + } + }; + + MaxValue maxDtpc[3]; + MaxValue maxD; for (int32_t slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { if (prn) { LOG(info) << "check inverse transform for slice " << slice; } - double vLength = (slice < mGeo.getNumberOfSlicesA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); - double maxDslice[3] = {0, 0, 0}; + double vLength = mGeo.getTPCzLength(slice); + MaxValue maxDslice[3]; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { float u0, u1, v0, v1; mGeo.convScaledUVtoUV(slice, row, 0., 0., u0, v0); @@ -530,9 +557,12 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) double x = mGeo.getRowInfo(row).x; double stepU = (u1 - u0) / 100.; double stepV = (v1 - v0) / 100.; - double maxDrow[3] = {0, 0, 0}; + MaxValue maxDrow[3]; for (double u = u0; u < u1; u += stepU) { for (double v = v0; v < v1; v += stepV) { + if (v < getSliceRowInfo(slice, row).gridV0) { + continue; + } float dx, du, dv; getCorrection(slice, row, u, v, dx, du, dv); double cx = x + dx; @@ -545,11 +575,9 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) float nx, nu, nv; getCorrectionInvCorrectedX(slice, row, cu, cv, nx); getCorrectionInvUV(slice, row, cu, cv, nu, nv); - double d[3] = {nx - cx, nu - u, nv - v}; + double d[3] = {(cx - nx) - dx, (cu - nu) - du, (cv - nv) - dv}; for (int32_t i = 0; i < 3; i++) { - if (fabs(d[i]) > fabs(maxDrow[i])) { - maxDrow[i] = d[i]; - } + maxDrow[i].update(d[i], slice, row); } if (0 && prn && fabs(d[0]) + fabs(d[1]) + fabs(d[2]) > 0.1) { @@ -560,32 +588,26 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) } } } - if (0 && prn) { + if (1 && prn) { LOG(info) << "slice " << slice << " row " << row - << " dx " << maxDrow[0] << " du " << maxDrow[1] << " dv " << maxDrow[2]; + << " dx " << maxDrow[0].V << " du " << maxDrow[1].V << " dv " << maxDrow[2].V; } for (int32_t i = 0; i < 3; i++) { - if (fabs(maxDslice[i]) < fabs(maxDrow[i])) { - maxDslice[i] = maxDrow[i]; - } - if (fabs(maxDtpc[i]) < fabs(maxDrow[i])) { - maxDtpc[i] = maxDrow[i]; - } - if (fabs(maxD) < fabs(maxDrow[i])) { - maxD = maxDrow[i]; - } + maxDslice[i].update(maxDrow[i]); + maxDtpc[i].update(maxDrow[i]); + maxD.update(maxDrow[i]); } } if (prn) { - LOG(info) << "inverse correction: slice " << slice - << " dx " << maxDslice[0] << " du " << maxDslice[1] << " dv " << maxDslice[2]; + LOG(info) << "inverse correction: slice " << slice << ". Max deviations: " + << " dx " << maxDslice[0].toString() << " du " << maxDslice[1].toString() << " dv " << maxDslice[2].toString(); } } // slice LOG(info) << "Test inverse TPC correction. max deviations: " - << " dx " << maxDtpc[0] << " du " << maxDtpc[1] << " dv " << maxDtpc[2] << " cm"; + << " dx " << maxDtpc[0].toString() << " du " << maxDtpc[1].toString() << " dv " << maxDtpc[2].toString() << " cm"; - return maxD; + return maxD.V; } #endif // GPUCA_GPUCODE diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index e69983fab9175..2d2940054023e 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -68,8 +68,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV - float maxInvCorr[3]{10.f, 10.f, 10.f}; ///< max inverse correction for dX, dU, dV - float minInvCorr[3]{-10.f, -10.f, -10.f}; ///< min inverse correction for dX, dU, dV RowActiveArea activeArea; void resetMaxValues() @@ -94,28 +92,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject minCorr[2] = GPUCommonMath::Min(minCorr[2], dv); } - void resetMaxValuesInv() - { - maxInvCorr[0] = 1.f; - minInvCorr[0] = -1.f; - maxInvCorr[1] = 1.f; - minInvCorr[1] = -1.f; - maxInvCorr[2] = 1.f; - minInvCorr[2] = -1.f; - } - - void updateMaxValuesInv(float dx, float du, float dv) - { - maxInvCorr[0] = GPUCommonMath::Max(maxInvCorr[0], dx); - minInvCorr[0] = GPUCommonMath::Min(minInvCorr[0], dx); - - maxInvCorr[1] = GPUCommonMath::Max(maxInvCorr[1], du); - minInvCorr[1] = GPUCommonMath::Min(minInvCorr[1], du); - - maxInvCorr[2] = GPUCommonMath::Max(maxInvCorr[2], dv); - minInvCorr[2] = GPUCommonMath::Min(minInvCorr[2], dv); - } - ClassDefNV(SliceRowInfo, 2); }; @@ -494,7 +470,15 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( float dx = 0; spline.interpolateU(splineData, gridU, gridV, &dx); const auto& info = getSliceRowInfo(slice, row); - dx = GPUCommonMath::Max(info.minInvCorr[0], GPUCommonMath::Min(info.maxInvCorr[0], dx)); + + float s = corrV / info.gridCorrV0; + if (s < 0.) { + s = 0.; + } + if (s > 1.) { + s = 1.; + } + dx = GPUCommonMath::Clamp(s * dx, info.minCorr[0], info.maxCorr[0]); x = mGeo.getRowInfo(row).x + dx; } @@ -510,8 +494,15 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( float duv[2]; spline.interpolateU(splineData, gridU, gridV, duv); const auto& info = getSliceRowInfo(slice, row); - duv[0] = GPUCommonMath::Max(info.minInvCorr[1], GPUCommonMath::Min(info.maxInvCorr[1], duv[0])); - duv[1] = GPUCommonMath::Max(info.minInvCorr[2], GPUCommonMath::Min(info.maxInvCorr[2], duv[1])); + float s = corrV / info.gridCorrV0; + if (s < 0.) { + s = 0.; + } + if (s > 1.) { + s = 1.; + } + duv[0] = GPUCommonMath::Clamp(s * duv[0], info.minCorr[1], info.maxCorr[1]); + duv[1] = GPUCommonMath::Clamp(s * duv[1], info.minCorr[2], info.maxCorr[2]); nomU = corrU - duv[0]; nomV = corrV - duv[1]; } diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index c4b0680f2edd4..7e889d5a9e7db 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -202,41 +202,44 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", TFile* debugFile = new TFile("transformDebug.root", "RECREATE"); debugFile->cd(); - // ntuple with created TPC corrections - TNtuple* debugCorr = new TNtuple("corr", "corr", "iRoc:iRow:x:y:z:cx:cy:cz"); + // debug ntuple with created TPC corrections + // + // measured x,y,z; corrections cx,cy,cz from the measured to the real x,y,z; + // inverse corrections ix,iy,iz at the real position (x+cx,y+cy,z+cz) + // ideally, ix = cx, iy = cy, iz = cz + TNtuple* debugCorr = new TNtuple("corr", "corr", "iRoc:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); debugCorr->SetMarkerStyle(8); debugCorr->SetMarkerSize(0.1); debugCorr->SetMarkerColor(kBlack); - // ntuple with the input data: voxel corrections + // ntuple with the input data: voxels and corrections debugFile->cd(); TNtuple* debugVox = - new TNtuple("vox", "vox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz"); + new TNtuple("vox", "vox", "iRoc:iRow:n:x:y:z:vx:vy:vz"); debugVox->SetMarkerStyle(8); debugVox->SetMarkerSize(0.8); debugVox->SetMarkerColor(kBlue); - // duplicate of debugVox + // duplicate of debugVox + the spline data at voxels in a different color debugFile->cd(); TNtuple* debugCorrVox = - new TNtuple("corrvox", "corrvox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz"); + new TNtuple("corrvox", "corrvox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz"); debugCorrVox->SetMarkerStyle(8); debugCorrVox->SetMarkerSize(0.8); debugCorrVox->SetMarkerColor(kMagenta); - // ntuple with spline grid points + // corrections at the spline grid points debugFile->cd(); - TNtuple* debugGrid = new TNtuple("grid", "grid", "iRoc:iRow:x:y:z:cx:cy:cz"); + TNtuple* debugGrid = new TNtuple("grid", "grid", "iRoc:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); debugGrid->SetMarkerStyle(8); debugGrid->SetMarkerSize(1.2); debugGrid->SetMarkerColor(kBlack); - // ntuple with data points created from voxels (with data smearing and - // extension to the edges) + // ntuple with data points created from voxels (with the data smearing, extension to the edges etc.) debugFile->cd(); TNtuple* debugPoints = new TNtuple("points", "points", "iRoc:iRow:x:y:z:px:py:pz:cx:cy:cz"); @@ -253,6 +256,34 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); + auto getAllCorrections = [&](int iRoc, int iRow, float u, float v, float& x, float& y, float& z, float& cx, float& cy, float& cz, float& ix, float& iy, float& iz) { + // define x,y,z + + x = geo.getRowInfo(iRow).x; + geo.convUVtoLocal(iRoc, u, v, y, z); + + // get the corrections cx,cy,cz at x,y,z + float cu, cv; + corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); + geo.convUVtoLocal(iRoc, cu, cv, cy, cz); + + float corrected_u = u + cu; + float corrected_v = v + cv; + float corrected_x = x + cx; + float corrected_y, corrected_z; + geo.convUVtoLocal(iRoc, corrected_u, corrected_v, corrected_y, corrected_z); + + // get the inverse corrections ix,iy,iz at the corrected x,y,z + float inverted_x, inverted_u, inverted_v, inverted_y, inverted_z; + corr.getCorrectionInvCorrectedX(iRoc, iRow, corrected_u, corrected_v, inverted_x); + corr.getCorrectionInvUV(iRoc, iRow, corrected_u, corrected_v, inverted_u, inverted_v); + geo.convUVtoLocal(iRoc, inverted_u, inverted_v, inverted_y, inverted_z); + + ix = corrected_x - inverted_x; + iy = corrected_y - inverted_y; + iz = corrected_z - inverted_z; + }; + o2::tpc::TrackResiduals::VoxRes* v = nullptr; TBranch* branch = voxResTree->GetBranch("voxRes"); branch->SetAddress(&v); @@ -261,6 +292,8 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", int32_t iRocLast = -1; int32_t iRowLast = -1; + std::cout << "fill debug ntuples at voxels ..." << std::endl; + for (int32_t iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { voxResTree->GetEntry(iVox); @@ -312,12 +345,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", z = x * v->stat[o2::tpc::TrackResiduals::VoxZ]; } - float u, v, cx, cu, cv, cy, cz; + float u, v; geo.convLocalToUV(iRoc, y, z, u, v); - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); - cy -= y; - cz -= z; + float x1, y1, z1, cx, cy, cz, ix, iy, iz; + getAllCorrections(iRoc, iRow, u, v, x1, y1, z1, cx, cy, cz, ix, iy, iz); double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; if (voxEntries >= 1.) { @@ -334,13 +365,14 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", nDiff++; } - debugVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, - cx, cy, cz); + debugVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ); + debugCorrVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, - cx, cy, cz); + cx, cy, cz, ix, iy, iz); } - std::cout << "create debug ntuples ..." << std::endl; + std::cout + << "fill debug ntuples everywhere .." << std::endl; for (int32_t iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { // for (int32_t iRoc = 0; iRoc < 1; iRoc++) { @@ -399,18 +431,14 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", for (uint32_t iv = 0; iv < pv.size(); iv++) { float u = pu[iu]; float v = pv[iv]; - float x, y, z; - geo.convUVtoLocal(iRoc, u, v, y, z); - float cx, cu, cv; - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - float cy, cz; - geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); - cy -= y; - cz -= z; + + float x, y, z, cx, cy, cz, ix, iy, iz; + getAllCorrections(iRoc, iRow, u, v, x, y, z, cx, cy, cz, ix, iy, iz); + if (iter == 0) { - debugGrid->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + debugGrid->Fill(iRoc, iRow, x, y, z, cx, cy, cz, ix, iy, iz); } else { - debugCorr->Fill(iRoc, iRow, x, y, z, cx, cy, cz); + debugCorr->Fill(iRoc, iRow, x, y, z, cx, cy, cz, ix, iy, iz); } } } @@ -462,7 +490,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", std::cout << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] << " " << sumDiff[2] << std::endl; - corr.testInverse(0); + corr.testInverse(true); debugFile->cd(); debugCorr->Write(); From a7f6d132189315fed468aa3237d5fb23c4380bf8 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Mon, 27 Jan 2025 17:35:50 +0000 Subject: [PATCH 09/26] TPC Splines: fix reading track residuals --- .../src/TPCFastSpaceChargeCorrectionHelper.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 3696df5343ad3..c0bba6f4908a8 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -457,9 +457,9 @@ std::unique_ptr TPCFastSpaceChargeCorrect y = iy * dy; y = y / (y1 - y0) * 2 - 1.; if (iuv == 0) { - LOG(info) << "convert y bin: " << yold << " -> " << y << " -> " << iy; + LOG(info) << "TPC SC splines: convert y bin: " << yold << " -> " << y << " -> " << iy; } else { - LOG(info) << "convert z bin: " << yold << " -> " << y << " -> " << iy; + LOG(info) << "TPC SC splines: convert z bin: " << yold << " -> " << y << " -> " << iy; } } @@ -514,11 +514,12 @@ std::unique_ptr TPCFastSpaceChargeCorrect double uMax = yMax; double vMin = geo.getTPCzLength(iRoc) - zMax; double vMax = geo.getTPCzLength(iRoc) - zMin; - // std::cout << " uMin: " << uMin << " uMax: " << yuMax << " zMin: " << vMin << " zMax: " << vMax << std::endl; info.gridU0 = uMin; info.scaleUtoGrid = spline.getGridX1().getUmax() / (uMax - uMin); info.gridV0 = vMin; info.scaleVtoGrid = spline.getGridX2().getUmax() / (vMax - vMin); + // std::cout << " iRoc " << iRoc << " iRow " << iRow << " uMin: " << uMin << " uMax: " << uMax << " vMin: " << vMin << " vMax: " << vMax + //<< " grid scale u "<< info.scaleUtoGrid << " grid scale v "<< info.scaleVtoGrid<< std::endl; } } @@ -629,7 +630,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect << std::endl; } */ - if (1) { // always use voxel center instead of the mean position + if (0) { // debug: always use voxel center instead of the mean position data.mY = vox.mY; data.mZ = vox.mZ; } From e23508dd0b2aea5468c4f05b689e6fd74c422b00 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Mon, 27 Jan 2025 17:37:35 +0000 Subject: [PATCH 10/26] TPC Splines: fix scaling splines outside of the measured area --- .../TPCFastSpaceChargeCorrection.h | 152 +++++++----------- 1 file changed, 54 insertions(+), 98 deletions(-) diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 2d2940054023e..7957d36b494c3 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -58,16 +58,16 @@ class TPCFastSpaceChargeCorrection : public FlatObject }; struct SliceRowInfo { - float gridU0{0.f}; //< U coordinate of the U-grid start - float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate - float gridV0{0.f}; ///< V coordinate of the V-grid start - float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate - float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U - float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate - float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V - float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate - float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV - float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV + float gridU0{0.f}; //< U coordinate of the U-grid start + float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate + float gridV0{0.f}; ///< V coordinate of the V-grid start + float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate + float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U + float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate + float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V + float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate + float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV + float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV RowActiveArea activeArea; void resetMaxValues() @@ -199,12 +199,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// _______________ Utilities _______________________________________________ - /// shrink u,v coordinats to the TPC row area +/- fkInterpolationSafetyMargin - GPUd() void schrinkUV(int32_t slice, int32_t row, float& u, float& v) const; - - /// shrink corrected u,v coordinats to the TPC row area +/- fkInterpolationSafetyMargin - GPUd() void schrinkCorrectedUV(int32_t slice, int32_t row, float& corrU, float& corrV) const; - /// convert u,v to internal grid coordinates GPUd() void convUVtoGrid(int32_t slice, int32_t row, float u, float v, float& gridU, float& gridV) const; @@ -338,60 +332,9 @@ GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t slice, return reinterpret_cast(mSplineData[iSpline] + mSliceDataSizeBytes[iSpline] * slice + rowInfo.dataOffsetBytes[iSpline]); } -GPUdi() void TPCFastSpaceChargeCorrection::schrinkUV(int32_t slice, int32_t row, float& u, float& v) const -{ - /// shrink u,v coordinats to the TPC row area +/- fInterpolationSafetyMargin - - const TPCFastTransformGeo::RowInfo& rowInfo = mGeo.getRowInfo(row); - - float uWidth05 = rowInfo.getUwidth() * (0.5f + fInterpolationSafetyMargin); - float vWidth = mGeo.getTPCzLength(slice); - - if (u < -uWidth05) { - u = -uWidth05; - } - if (u > uWidth05) { - u = uWidth05; - } - if (v < -0.1f * vWidth) { - v = -0.1f * vWidth; - } - if (v > 1.1f * vWidth) { - v = 1.1f * vWidth; - } -} - -GPUdi() void TPCFastSpaceChargeCorrection::schrinkCorrectedUV(int32_t slice, int32_t row, float& corrU, float& corrV) const -{ - /// shrink corrected u,v coordinats to the TPC row area +/- fInterpolationSafetyMargin - - const TPCFastTransformGeo::RowInfo& rowInfo = mGeo.getRowInfo(row); - const SliceRowInfo& sliceRowInfo = getSliceRowInfo(slice, row); - - float uMargin = fInterpolationSafetyMargin * rowInfo.getUwidth(); - float vMargin = fInterpolationSafetyMargin * mGeo.getTPCzLength(slice); - - if (corrU < sliceRowInfo.activeArea.cuMin - uMargin) { - corrU = sliceRowInfo.activeArea.cuMin - uMargin; - } - - if (corrU > sliceRowInfo.activeArea.cuMax + uMargin) { - corrU = sliceRowInfo.activeArea.cuMax + uMargin; - } - - if (corrV < 0.f - vMargin) { - corrV = 0.f - vMargin; - } - - if (corrV > sliceRowInfo.activeArea.cvMax + vMargin) { - corrV = sliceRowInfo.activeArea.cvMax + vMargin; - } -} - GPUdi() void TPCFastSpaceChargeCorrection::convUVtoGrid(int32_t slice, int32_t row, float u, float v, float& gu, float& gv) const { - schrinkUV(slice, row, u, v); - const SliceRowInfo& info = getSliceRowInfo(slice, row); + const auto& info = getSliceRowInfo(slice, row); gu = (u - info.gridU0) * info.scaleUtoGrid; gv = (v - info.gridV0) * info.scaleVtoGrid; } @@ -406,34 +349,36 @@ GPUdi() void TPCFastSpaceChargeCorrection::convGridToUV(int32_t slice, int32_t r GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t slice, int32_t row, float corrU, float corrV, float& gridU, float& gridV) const { - schrinkCorrectedUV(slice, row, corrU, corrV); - - const SliceRowInfo& sliceRowInfo = getSliceRowInfo(slice, row); - - gridU = (corrU - sliceRowInfo.gridCorrU0) * sliceRowInfo.scaleCorrUtoGrid; - gridV = (corrV - sliceRowInfo.gridCorrV0) * sliceRowInfo.scaleCorrVtoGrid; + const SliceRowInfo& info = getSliceRowInfo(slice, row); + gridU = (corrU - info.gridCorrU0) * info.scaleCorrUtoGrid; + gridV = (corrV - info.gridCorrV0) * info.scaleCorrVtoGrid; } GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t slice, int32_t row, float u, float v, float& dx, float& du, float& dv) const { + const auto& info = getSliceRowInfo(slice, row); const SplineType& spline = getSpline(slice, row); const float* splineData = getSplineData(slice, row); float gridU = 0, gridV = 0; convUVtoGrid(slice, row, u, v, gridU, gridV); + // shrink to the grid area + gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); + gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); + float dxuv[3]; spline.interpolateU(splineData, gridU, gridV, dxuv); - const auto& info = getSliceRowInfo(slice, row); + float s = v / info.gridV0; - if (s < 0.) { - s = 0.; - } - if (s > 1.) { - s = 1.; + + if (v >= info.gridV0) { + s = 1.f; + } else if (v <= 0.f) { + s = 0.f; } - dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], s * dxuv[0])); - du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], s * dxuv[1])); - dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], s * dxuv[2])); + dx = GPUCommonMath::Clamp(s * dxuv[0], info.minCorr[0], info.maxCorr[0]); + du = GPUCommonMath::Clamp(s * dxuv[1], info.minCorr[1], info.maxCorr[1]); + dv = GPUCommonMath::Clamp(s * dxuv[2], info.minCorr[2], info.maxCorr[2]); return 0; } @@ -462,22 +407,28 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t slice, in GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( int32_t slice, int32_t row, float corrU, float corrV, float& x) const { + const auto& info = getSliceRowInfo(slice, row); + const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); + const float* splineData = getSplineData(slice, row, 1); + float gridU, gridV; convCorrectedUVtoGrid(slice, row, corrU, corrV, gridU, gridV); - const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); - const float* splineData = getSplineData(slice, row, 1); + // shrink to the grid area + gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); + gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); + float dx = 0; spline.interpolateU(splineData, gridU, gridV, &dx); - const auto& info = getSliceRowInfo(slice, row); float s = corrV / info.gridCorrV0; - if (s < 0.) { - s = 0.; - } - if (s > 1.) { - s = 1.; + + if (corrV >= info.gridCorrV0) { + s = 1.f; + } else if (corrV <= 0.f) { + s = 0.f; } + dx = GPUCommonMath::Clamp(s * dx, info.minCorr[0], info.maxCorr[0]); x = mGeo.getRowInfo(row).x + dx; } @@ -485,22 +436,27 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( int32_t slice, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const { + const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); + const float* splineData = getSplineData(slice, row, 2); + float gridU, gridV; convCorrectedUVtoGrid(slice, row, corrU, corrV, gridU, gridV); - const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); - const float* splineData = getSplineData(slice, row, 2); + // shrink to the grid area + gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); + gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); float duv[2]; spline.interpolateU(splineData, gridU, gridV, duv); const auto& info = getSliceRowInfo(slice, row); float s = corrV / info.gridCorrV0; - if (s < 0.) { - s = 0.; - } - if (s > 1.) { - s = 1.; + + if (corrV >= info.gridCorrV0) { + s = 1.f; + } else if (corrV <= 0.f) { + s = 0.f; } + duv[0] = GPUCommonMath::Clamp(s * duv[0], info.minCorr[1], info.maxCorr[1]); duv[1] = GPUCommonMath::Clamp(s * duv[1], info.minCorr[2], info.maxCorr[2]); nomU = corrU - duv[0]; From dbf53a04ef0ae4d0f2d3f9518eda4d5920d533b4 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Mon, 27 Jan 2025 19:41:36 +0000 Subject: [PATCH 11/26] TPC Splines: rename Slice -> Roc in geometry --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 110 +++---- .../src/TPCFastTransformHelperO2.cxx | 4 +- .../test/testTPCFastTransform.cxx | 30 +- .../TPCFastSpaceChargeCorrection.cxx | 130 ++++---- .../TPCFastSpaceChargeCorrection.h | 146 ++++----- GPU/TPCFastTransformation/TPCFastTransform.h | 278 +++++++++--------- .../TPCFastTransformGeo.cxx | 24 +- .../TPCFastTransformGeo.h | 107 +++---- .../TPCFastTransformManager.cxx | 26 +- .../TPCFastTransformationLinkDef_O2.h | 6 +- .../macro/generateTPCCorrectionNTuple.C | 24 +- 11 files changed, 443 insertions(+), 442 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index c0bba6f4908a8..bac332a837c55 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -134,17 +134,17 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas LOG(info) << "fast space charge correction helper: init from data points"; - for (int slice = 0; slice < correction.getGeometry().getNumberOfSlices(); slice++) { + for (int roc = 0; roc < correction.getGeometry().getNumberOfRocs(); roc++) { auto myThread = [&](int iThread) { for (int row = iThread; row < correction.getGeometry().getNumberOfRows(); row += mNthreads) { - TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(slice, row); + TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(roc, row); Spline2DHelper helper; - float* splineParameters = correction.getSplineData(slice, row); - const std::vector& data = mCorrectionMap.getPoints(slice, row); + float* splineParameters = correction.getSplineData(roc, row); + const std::vector& data = mCorrectionMap.getPoints(roc, row); int nDataPoints = data.size(); - auto& info = correction.getSliceRowInfo(slice, row); + auto& info = correction.getRocRowInfo(roc, row); info.resetMaxValues(); if (nDataPoints >= 4) { std::vector pointSU(nDataPoints); @@ -152,7 +152,7 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas std::vector pointCorr(3 * nDataPoints); // 3 dimensions for (int i = 0; i < nDataPoints; ++i) { double su, sv, dx, du, dv; - getSpaceChargeCorrection(correction, slice, row, data[i], su, sv, dx, du, dv); + getSpaceChargeCorrection(correction, roc, row, data[i], su, sv, dx, du, dv); pointSU[i] = su; pointSV[i] = sv; pointCorr[3 * i + 0] = dx; @@ -182,7 +182,7 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas th.join(); } - } // slice + } // roc watch.Stop(); @@ -191,7 +191,7 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas initInverse(correction, 0); } -void TPCFastSpaceChargeCorrectionHelper::getSpaceChargeCorrection(const TPCFastSpaceChargeCorrection& correction, int slice, int row, o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p, +void TPCFastSpaceChargeCorrectionHelper::getSpaceChargeCorrection(const TPCFastSpaceChargeCorrection& correction, int roc, int row, o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p, double& su, double& sv, double& dx, double& du, double& dv) { // get space charge correction in internal TPCFastTransform coordinates su,sv->dx,du,dv @@ -202,14 +202,14 @@ void TPCFastSpaceChargeCorrectionHelper::getSpaceChargeCorrection(const TPCFastS // not corrected coordinates in u,v float u = 0.f, v = 0.f, fsu = 0.f, fsv = 0.f; - mGeo.convLocalToUV(slice, p.mY, p.mZ, u, v); - correction.convUVtoGrid(slice, row, u, v, fsu, fsv); - // mGeo.convUVtoScaledUV(slice, row, u, v, fsu, fsv); + mGeo.convLocalToUV(roc, p.mY, p.mZ, u, v); + correction.convUVtoGrid(roc, row, u, v, fsu, fsv); + // mGeo.convUVtoScaledUV(roc, row, u, v, fsu, fsv); su = fsu; sv = fsv; // corrected coordinates in u,v float u1 = 0.f, v1 = 0.f; - mGeo.convLocalToUV(slice, p.mY + p.mDy, p.mZ + p.mDz, u1, v1); + mGeo.convLocalToUV(roc, p.mY + p.mDy, p.mZ + p.mDz, u1, v1); dx = p.mDx; du = u1 - u; @@ -286,7 +286,7 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper /// set space charge correction in the local coordinates /// as a continious function - int nRocs = mGeo.getNumberOfSlices(); + int nRocs = mGeo.getNumberOfRocs(); int nRows = mGeo.getNumberOfRows(); mCorrectionMap.init(nRocs, nRows); @@ -337,8 +337,8 @@ void TPCFastSpaceChargeCorrectionHelper::testGeometry(const TPCFastTransformGeo& { const Mapper& mapper = Mapper::instance(); - if (geo.getNumberOfSlices() != Sector::MAXSECTOR) { - LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfSlices() << " instead of " << Sector::MAXSECTOR << std::endl; + if (geo.getNumberOfRocs() != Sector::MAXSECTOR) { + LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfRocs() << " instead of " << Sector::MAXSECTOR << std::endl; } if (geo.getNumberOfRows() != mapper.getNumberOfRows()) { @@ -404,7 +404,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); o2::gpu::TPCFastSpaceChargeCorrectionMap& map = helper->getCorrectionMap(); - map.init(geo.getNumberOfSlices(), geo.getNumberOfRows()); + map.init(geo.getNumberOfRocs(), geo.getNumberOfRows()); int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); @@ -480,7 +480,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect // std::cout << "n knots Z: " << nKnotsZ << std::endl; const int nRows = geo.getNumberOfRows(); - const int nROCs = geo.getNumberOfSlices(); + const int nROCs = geo.getNumberOfRocs(); { // create the correction object @@ -501,10 +501,10 @@ std::unique_ptr TPCFastSpaceChargeCorrect } // .. create the correction object // set the grid borders - for (int iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { + for (int iRoc = 0; iRoc < geo.getNumberOfRocs(); iRoc++) { for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { const auto& rowInfo = geo.getRowInfo(iRow); - auto& info = correction.getSliceRowInfo(iRoc, iRow); + auto& info = correction.getRocRowInfo(iRoc, iRow); const auto& spline = correction.getSpline(iRoc, iRow); double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); @@ -616,7 +616,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect vox.mZ = x * z2x; vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); vox.mDz = x * trackResiduals.getDZ2X(iz); - if (iRoc >= geo.getNumberOfSlicesA()) { + if (iRoc >= geo.getNumberOfRocsA()) { vox.mZ = -vox.mZ; } data.mY *= x; @@ -720,7 +720,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect // feed the row data to the helper - auto& info = correction.getSliceRowInfo(iRoc, iRow); + auto& info = correction.getRocRowInfo(iRoc, iRow); const auto& spline = correction.getSpline(iRoc, iRow); auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nSteps) { @@ -813,21 +813,21 @@ void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpac double tpcR2min = mGeo.getRowInfo(0).x - 1.; tpcR2min = tpcR2min * tpcR2min; double tpcR2max = mGeo.getRowInfo(mGeo.getNumberOfRows() - 1).x; - tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfSlicesA() / 2) + 1.; + tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfRocsA() / 2) + 1.; tpcR2max = tpcR2max * tpcR2max; ChebyshevFit1D chebFitter; - for (int slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { + for (int roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { if (prn) { - LOG(info) << "init MaxDriftLength for slice " << slice; + LOG(info) << "init MaxDriftLength for roc " << roc; } - double vLength = (slice < mGeo.getNumberOfSlicesA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); - TPCFastSpaceChargeCorrection::SliceInfo& sliceInfo = correction.getSliceInfo(slice); - sliceInfo.vMax = 0.f; + double vLength = (roc < mGeo.getNumberOfRocsA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); + TPCFastSpaceChargeCorrection::RocInfo& rocInfo = correction.getRocInfo(roc); + rocInfo.vMax = 0.f; for (int row = 0; row < mGeo.getNumberOfRows(); row++) { - TPCFastSpaceChargeCorrection::RowActiveArea& area = correction.getSliceRowInfo(slice, row).activeArea; + TPCFastSpaceChargeCorrection::RowActiveArea& area = correction.getRocRowInfo(roc, row).activeArea; area.cvMax = 0; area.vMax = 0; area.cuMin = mGeo.convPadToU(row, 0.f); @@ -843,7 +843,7 @@ void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpac while (v1 - v0 > 0.1) { float v = 0.5 * (v0 + v1); float dx, du, dv; - correction.getCorrection(slice, row, u, v, dx, du, dv); + correction.getCorrection(roc, row, u, v, dx, du, dv); double cx = x + dx; double cu = u + du; double cv = v + dv; @@ -872,11 +872,11 @@ void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpac for (int i = 0; i < 5; i++) { area.maxDriftLengthCheb[i] = chebFitter.getCoefficients()[i]; } - if (sliceInfo.vMax < area.vMax) { - sliceInfo.vMax = area.vMax; + if (rocInfo.vMax < area.vMax) { + rocInfo.vMax = area.vMax; } } // row - } // slice + } // roc } void TPCFastSpaceChargeCorrectionHelper::initInverse(o2::gpu::TPCFastSpaceChargeCorrection& correction, bool prn) @@ -902,22 +902,22 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector helper; std::vector splineParameters; for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { - TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(slice, row); + TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(roc, row); helper.setSpline(spline, 10, 10); double x = mGeo.getRowInfo(row).x; - auto& sliceRowInfo = correction.getSliceRowInfo(slice, row); + auto& rocRowInfo = correction.getRocRowInfo(roc, row); std::vector gridU; { @@ -951,7 +951,7 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vectorgetCorrection(slice, row, u, v, dxTmp, duTmp, dvTmp); + corrections[i]->getCorrection(roc, row, u, v, dxTmp, duTmp, dvTmp); dx += dxTmp * scaling[i]; du += duTmp * scaling[i]; dv += dvTmp * scaling[i]; @@ -1002,28 +1002,28 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vectorgetCorrectionMap(); scData.init(nRocs, nRows); @@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) } } } // row - } // slice + } // roc std::unique_ptr fastTransform(TPCFastTransformHelperO2::instance()->create(0)); @@ -158,12 +158,12 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) double statDiff = 0., statN = 0.; double statDiffFile = 0., statNFile = 0.; - for (int slice = 0; slice < geo.getNumberOfSlices(); slice += 1) { - //std::cout << "slice " << slice << " ... " << std::endl; + for (int roc = 0; roc < geo.getNumberOfRocs(); roc += 1) { + // std::cout << "roc " << roc << " ... " << std::endl; - const TPCFastTransformGeo::SliceInfo& sliceInfo = geo.getSliceInfo(slice); + const TPCFastTransformGeo::RocInfo& rocInfo = geo.getRocInfo(roc); - float lastTimeBin = fastTransform->getMaxDriftTime(slice, 0.f); + float lastTimeBin = fastTransform->getMaxDriftTime(roc, 0.f); for (int row = 0; row < geo.getNumberOfRows(); row++) { @@ -172,31 +172,31 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) for (int pad = 0; pad < nPads; pad += 10) { for (float time = 0; time < lastTimeBin; time += 30) { - //std::cout<<"slice "<setApplyCorrectionOff(); float x0, y0, z0; - fastTransform->Transform(slice, row, pad, time, x0, y0, z0); + fastTransform->Transform(roc, row, pad, time, x0, y0, z0); - BOOST_CHECK_EQUAL(geo.test(slice, row, y0, z0), 0); + BOOST_CHECK_EQUAL(geo.test(roc, row, y0, z0), 0); fastTransform->setApplyCorrectionOn(); float x1, y1, z1; - fastTransform->Transform(slice, row, pad, time, x1, y1, z1); + fastTransform->Transform(roc, row, pad, time, x1, y1, z1); // local to UV float u0, v0, u1, v1; - geo.convLocalToUV(slice, y0, z0, u0, v0); - geo.convLocalToUV(slice, y1, z1, u1, v1); + geo.convLocalToUV(roc, y0, z0, u0, v0); + geo.convLocalToUV(roc, y1, z1, u1, v1); double dx, du, dv; - correctionUV(slice, row, u0, v0, dx, du, dv); + correctionUV(roc, row, u0, v0, dx, du, dv); statDiff += fabs((x1 - x0) - dx) + fabs((u1 - u0) - du) + fabs((v1 - v0) - dv); statN += 3; //std::cout << (x1 - x0) - dx << " " << (u1 - u0) - du << " " << (v1 - v0) - dv << std::endl; //": v0 " << v0 <<" z0 "<Transform(slice, row, pad, time, x1f, y1f, z1f); + fromFile->Transform(roc, row, pad, time, x1f, y1f, z1f); statDiffFile += fabs(x1f - x1) + fabs(y1f - y1) + fabs(z1f - z1); statNFile += 3; } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index e519716b6eec0..5d3c186a06d42 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -35,7 +35,7 @@ TPCFastSpaceChargeCorrection::TPCFastSpaceChargeCorrection() mScenarioPtr(nullptr), mTimeStamp(-1), mSplineData{nullptr, nullptr, nullptr}, - mSliceDataSizeBytes{0, 0, 0} + mRocDataSizeBytes{0, 0, 0} { // Default Constructor: creates an empty uninitialized object } @@ -64,7 +64,7 @@ void TPCFastSpaceChargeCorrection::destroy() mTimeStamp = -1; for (int32_t is = 0; is < 3; is++) { mSplineData[is] = nullptr; - mSliceDataSizeBytes[is] = 0; + mRocDataSizeBytes[is] = 0; } FlatObject::destroy(); } @@ -101,13 +101,13 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mTimeStamp = obj.mTimeStamp; - for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfSlices(); ++i) { - mSliceInfo[i] = obj.mSliceInfo[i]; + for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfRocs(); ++i) { + mRocInfo[i] = obj.mRocInfo[i]; } - mSliceDataSizeBytes[0] = obj.mSliceDataSizeBytes[0]; - mSliceDataSizeBytes[1] = obj.mSliceDataSizeBytes[1]; - mSliceDataSizeBytes[2] = obj.mSliceDataSizeBytes[2]; + mRocDataSizeBytes[0] = obj.mRocDataSizeBytes[0]; + mRocDataSizeBytes[1] = obj.mRocDataSizeBytes[1]; + mRocDataSizeBytes[2] = obj.mRocDataSizeBytes[2]; // variable-size data mScenarioPtr = obj.mScenarioPtr; @@ -121,8 +121,8 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mRowInfos[i] = obj.mRowInfos[i]; } - for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { - mSliceRowInfos[i] = obj.mSliceRowInfos[i]; + for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfRocs() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + mRocRowInfos[i] = obj.mRocRowInfos[i]; } relocateBufferPointers(oldFlatBufferPtr, mFlatBufferPtr); @@ -143,7 +143,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer struct RowInfoVersion3 { int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC slice + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC roc }; struct RowActiveAreaVersion3 { @@ -154,7 +154,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer float cvMax{0.f}; }; - struct SliceRowInfoVersion3 { + struct RocRowInfoVersion3 { float gridV0{0.f}; ///< V coordinate of the V-grid start float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V @@ -171,13 +171,13 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer rowsSize = sizeof(RowInfoVersion3) * mGeo.getNumberOfRows(); } - size_t sliceRowsOffset = rowsOffset + rowsSize; - size_t sliceRowsSize = 0; - if (mClassVersion == 3) { // copy old-format slicerow data from the buffer to the arrays - sliceRowsSize = sizeof(SliceRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfSlices(); + size_t rocRowsOffset = rowsOffset + rowsSize; + size_t rocRowsSize = 0; + if (mClassVersion == 3) { // copy old-format rocrow data from the buffer to the arrays + rocRowsSize = sizeof(RocRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfRocs(); } - size_t scOffset = alignSize(sliceRowsOffset + sliceRowsSize, SplineType::getClassAlignmentBytes()); + size_t scOffset = alignSize(rocRowsOffset + rocRowsSize, SplineType::getClassAlignmentBytes()); size_t scSize = sizeof(SplineType) * mNumberOfScenarios; mScenarioPtr = reinterpret_cast(mFlatBufferPtr + scOffset); @@ -192,12 +192,12 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer } size_t bufferSize = scBufferOffset + scBufferSize; for (int32_t is = 0; is < 3; is++) { - size_t sliceDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sliceDataOffset); - bufferSize = sliceDataOffset + mSliceDataSizeBytes[is] * mGeo.getNumberOfSlices(); + size_t rocDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + rocDataOffset); + bufferSize = rocDataOffset + mRocDataSizeBytes[is] * mGeo.getNumberOfRocs(); } - if (mClassVersion == 3) { // copy old-format slicerow data from the buffer to the arrays + if (mClassVersion == 3) { // copy old-format rocrow data from the buffer to the arrays auto* rowInfosOld = reinterpret_cast(mFlatBufferPtr + rowsOffset); for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { @@ -214,18 +214,18 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer spline.setXrange(0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax()); } - auto* sliceRowInfosOld = reinterpret_cast(mFlatBufferPtr + sliceRowsOffset); + auto* rocRowInfosOld = reinterpret_cast(mFlatBufferPtr + rocRowsOffset); - for (int32_t slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { + for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - SliceRowInfoVersion3& infoOld = sliceRowInfosOld[mGeo.getNumberOfRows() * slice + row]; - SliceRowInfo& info = getSliceRowInfo(slice, row); - const auto& spline = getSpline(slice, row); + RocRowInfoVersion3& infoOld = rocRowInfosOld[mGeo.getNumberOfRows() * roc + row]; + RocRowInfo& info = getRocRowInfo(roc, row); + const auto& spline = getSpline(roc, row); info.gridU0 = mGeo.getRowInfo(row).u0; info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); info.gridV0 = infoOld.gridV0; - info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength(slice) + 3. - info.gridV0); + info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength(roc) + 3. - info.gridV0); info.gridCorrU0 = infoOld.gridCorrU0; info.scaleCorrUtoGrid = infoOld.scaleCorrUtoGrid; @@ -276,7 +276,7 @@ void TPCFastSpaceChargeCorrection::print() const mGeo.print(); LOG(info) << " mNumberOfScenarios = " << mNumberOfScenarios; LOG(info) << " mTimeStamp = " << mTimeStamp; - LOG(info) << " mSliceDataSizeBytes = " << mSliceDataSizeBytes[0] << " " << mSliceDataSizeBytes[1] << " " << mSliceDataSizeBytes[2]; + LOG(info) << " mRocDataSizeBytes = " << mRocDataSizeBytes[0] << " " << mRocDataSizeBytes[1] << " " << mRocDataSizeBytes[2]; { LOG(info) << " TPC rows: "; for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { @@ -292,9 +292,9 @@ void TPCFastSpaceChargeCorrection::print() const } if (mScenarioPtr) { LOG(info) << " Spline Data: "; - for (int32_t is = 0; is < mGeo.getNumberOfSlices(); is++) { + for (int32_t is = 0; is < mGeo.getNumberOfRocs(); is++) { for (int32_t ir = 0; ir < mGeo.getNumberOfRows(); ir++) { - LOG(info) << "slice " << is << " row " << ir << ": "; + LOG(info) << "roc " << is << " row " << ir << ": "; const SplineType& spline = getSpline(is, ir); const float* d = getSplineData(is, ir); int32_t k = 0; @@ -305,8 +305,8 @@ void TPCFastSpaceChargeCorrection::print() const LOG(info) << ""; } } - // LOG(info) << "inverse correction: slice " << slice - // << " dx " << maxDslice[0] << " du " << maxDslice[1] << " dv " << maxDslice[2] ; + // LOG(info) << "inverse correction: roc " << roc + // << " dx " << maxDroc[0] << " du " << maxDroc[1] << " dv " << maxDroc[2] ; } } } @@ -345,7 +345,7 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& mScenarioPtr = nullptr; for (int32_t s = 0; s < 3; s++) { mSplineData[s] = nullptr; - mSliceDataSizeBytes[s] = 0; + mRocDataSizeBytes[s] = 0; } mClassVersion = 4; } @@ -401,18 +401,18 @@ void TPCFastSpaceChargeCorrection::finishConstruction() scBufferSize = alignSize(scBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); } size_t bufferSize = scBufferOffsets[0] + scBufferSize; - size_t sliceDataOffset[3]; + size_t rocDataOffset[3]; for (int32_t is = 0; is < 3; is++) { - sliceDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mSliceDataSizeBytes[is] = 0; + rocDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mRocDataSizeBytes[is] = 0; for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { RowInfo& row = mRowInfos[i]; SplineType& spline = mConstructionScenarios[row.splineScenarioID]; - row.dataOffsetBytes[is] = alignSize(mSliceDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - mSliceDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); + row.dataOffsetBytes[is] = alignSize(mRocDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + mRocDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); } - mSliceDataSizeBytes[is] = alignSize(mSliceDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - bufferSize = sliceDataOffset[is] + mSliceDataSizeBytes[is] * mGeo.getNumberOfSlices(); + mRocDataSizeBytes[is] = alignSize(mRocDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + bufferSize = rocDataOffset[is] + mRocDataSizeBytes[is] * mGeo.getNumberOfRocs(); } FlatObject::finishConstruction(bufferSize); @@ -427,7 +427,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() } for (int32_t is = 0; is < 3; is++) { - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sliceDataOffset[is]); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + rocDataOffset[is]); } releaseConstructionMemory(); @@ -439,15 +439,15 @@ void TPCFastSpaceChargeCorrection::finishConstruction() GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() { // initialise all corrections to 0. - for (int32_t slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { - double vLength = (slice < mGeo.getNumberOfSlicesA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); - SliceInfo& sliceInfo = getSliceInfo(slice); - sliceInfo.vMax = vLength; + for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { + double vLength = (roc < mGeo.getNumberOfRocsA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); + RocInfo& rocInfo = getRocInfo(roc); + rocInfo.vMax = vLength; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - const SplineType& spline = getSpline(slice, row); + const SplineType& spline = getSpline(roc, row); for (int32_t is = 0; is < 3; is++) { - float* data = getSplineData(slice, row, is); + float* data = getSplineData(roc, row, is); int32_t nPar = spline.getNumberOfParameters(); if (is == 1) { nPar = nPar / 3; @@ -460,7 +460,7 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() } } - SliceRowInfo& info = getSliceRowInfo(slice, row); + RocRowInfo& info = getRocRowInfo(roc, row); info.gridU0 = mGeo.getRowInfo(row).u0; info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); @@ -484,7 +484,7 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() area.cvMax = vLength; } // row - } // slice + } // roc } void TPCFastSpaceChargeCorrection::constructWithNoCorrection(const TPCFastTransformGeo& geo) @@ -512,7 +512,7 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) double tpcR2min = mGeo.getRowInfo(0).x - 1.; tpcR2min = tpcR2min * tpcR2min; double tpcR2max = mGeo.getRowInfo(mGeo.getNumberOfRows() - 1).x; - tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfSlicesA() / 2) + 1.; + tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfRocsA() / 2) + 1.; tpcR2max = tpcR2max * tpcR2max; struct MaxValue { @@ -544,27 +544,27 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) MaxValue maxDtpc[3]; MaxValue maxD; - for (int32_t slice = 0; slice < mGeo.getNumberOfSlices(); slice++) { + for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { if (prn) { - LOG(info) << "check inverse transform for slice " << slice; + LOG(info) << "check inverse transform for roc " << roc; } - double vLength = mGeo.getTPCzLength(slice); - MaxValue maxDslice[3]; + double vLength = mGeo.getTPCzLength(roc); + MaxValue maxDroc[3]; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { float u0, u1, v0, v1; - mGeo.convScaledUVtoUV(slice, row, 0., 0., u0, v0); - mGeo.convScaledUVtoUV(slice, row, 1., 1., u1, v1); + mGeo.convScaledUVtoUV(roc, row, 0., 0., u0, v0); + mGeo.convScaledUVtoUV(roc, row, 1., 1., u1, v1); double x = mGeo.getRowInfo(row).x; double stepU = (u1 - u0) / 100.; double stepV = (v1 - v0) / 100.; MaxValue maxDrow[3]; for (double u = u0; u < u1; u += stepU) { for (double v = v0; v < v1; v += stepV) { - if (v < getSliceRowInfo(slice, row).gridV0) { + if (v < getRocRowInfo(roc, row).gridV0) { continue; } float dx, du, dv; - getCorrection(slice, row, u, v, dx, du, dv); + getCorrection(roc, row, u, v, dx, du, dv); double cx = x + dx; double cu = u + du; double cv = v + dv; @@ -573,11 +573,11 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) continue; } float nx, nu, nv; - getCorrectionInvCorrectedX(slice, row, cu, cv, nx); - getCorrectionInvUV(slice, row, cu, cv, nu, nv); + getCorrectionInvCorrectedX(roc, row, cu, cv, nx); + getCorrectionInvUV(roc, row, cu, cv, nu, nv); double d[3] = {(cx - nx) - dx, (cu - nu) - du, (cv - nv) - dv}; for (int32_t i = 0; i < 3; i++) { - maxDrow[i].update(d[i], slice, row); + maxDrow[i].update(d[i], roc, row); } if (0 && prn && fabs(d[0]) + fabs(d[1]) + fabs(d[2]) > 0.1) { @@ -589,20 +589,20 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) } } if (1 && prn) { - LOG(info) << "slice " << slice << " row " << row + LOG(info) << "roc " << roc << " row " << row << " dx " << maxDrow[0].V << " du " << maxDrow[1].V << " dv " << maxDrow[2].V; } for (int32_t i = 0; i < 3; i++) { - maxDslice[i].update(maxDrow[i]); + maxDroc[i].update(maxDrow[i]); maxDtpc[i].update(maxDrow[i]); maxD.update(maxDrow[i]); } } if (prn) { - LOG(info) << "inverse correction: slice " << slice << ". Max deviations: " - << " dx " << maxDslice[0].toString() << " du " << maxDslice[1].toString() << " dv " << maxDslice[2].toString(); + LOG(info) << "inverse correction: roc " << roc << ". Max deviations: " + << " dx " << maxDroc[0].toString() << " du " << maxDroc[1].toString() << " dv " << maxDroc[2].toString(); } - } // slice + } // roc LOG(info) << "Test inverse TPC correction. max deviations: " << " dx " << maxDtpc[0].toString() << " du " << maxDtpc[1].toString() << " dv " << maxDtpc[2].toString() << " cm"; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 7957d36b494c3..b6244bfee1e0f 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -44,7 +44,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// struct RowInfo { int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC slice + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing the TPC roc ClassDefNV(RowInfo, 1); }; @@ -57,7 +57,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject ClassDefNV(RowActiveArea, 1); }; - struct SliceRowInfo { + struct RocRowInfo { float gridU0{0.f}; //< U coordinate of the U-grid start float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate float gridV0{0.f}; ///< V coordinate of the V-grid start @@ -92,12 +92,12 @@ class TPCFastSpaceChargeCorrection : public FlatObject minCorr[2] = GPUCommonMath::Min(minCorr[2], dv); } - ClassDefNV(SliceRowInfo, 2); + ClassDefNV(RocRowInfo, 2); }; - struct SliceInfo { + struct RocInfo { float vMax{0.f}; ///< Max value of V coordinate - ClassDefNV(SliceInfo, 1); + ClassDefNV(RocInfo, 1); }; typedef Spline2D SplineType; @@ -167,46 +167,46 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() void setInterpolationSafetyMargin(float val) { fInterpolationSafetyMargin = val; } /// Gives const pointer to a spline - GPUd() const SplineType& getSpline(int32_t slice, int32_t row) const; + GPUd() const SplineType& getSpline(int32_t roc, int32_t row) const; /// Gives pointer to a spline - GPUd() SplineType& getSpline(int32_t slice, int32_t row); + GPUd() SplineType& getSpline(int32_t roc, int32_t row); /// Gives pointer to spline data - GPUd() float* getSplineData(int32_t slice, int32_t row, int32_t iSpline = 0); + GPUd() float* getSplineData(int32_t roc, int32_t row, int32_t iSpline = 0); /// Gives pointer to spline data - GPUd() const float* getSplineData(int32_t slice, int32_t row, int32_t iSpline = 0) const; + GPUd() const float* getSplineData(int32_t roc, int32_t row, int32_t iSpline = 0) const; /// _______________ The main method: cluster correction _______________________ /// - GPUd() int32_t getCorrection(int32_t slice, int32_t row, float u, float v, float& dx, float& du, float& dv) const; + GPUd() int32_t getCorrection(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; /// inverse correction: Corrected U and V -> coorrected X - GPUd() void getCorrectionInvCorrectedX(int32_t slice, int32_t row, float corrU, float corrV, float& corrX) const; + GPUd() void getCorrectionInvCorrectedX(int32_t roc, int32_t row, float corrU, float corrV, float& corrX) const; /// inverse correction: Corrected U and V -> uncorrected U and V - GPUd() void getCorrectionInvUV(int32_t slice, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const; + GPUd() void getCorrectionInvUV(int32_t roc, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const; /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t slice, int32_t row, float pad) const; + GPUd() float getMaxDriftLength(int32_t roc, int32_t row, float pad) const; /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t slice, int32_t row) const; + GPUd() float getMaxDriftLength(int32_t roc, int32_t row) const; /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t slice) const; + GPUd() float getMaxDriftLength(int32_t roc) const; /// _______________ Utilities _______________________________________________ /// convert u,v to internal grid coordinates - GPUd() void convUVtoGrid(int32_t slice, int32_t row, float u, float v, float& gridU, float& gridV) const; + GPUd() void convUVtoGrid(int32_t roc, int32_t row, float u, float v, float& gridU, float& gridV) const; /// convert u,v to internal grid coordinates - GPUd() void convGridToUV(int32_t slice, int32_t row, float gridU, float gridV, float& u, float& v) const; + GPUd() void convGridToUV(int32_t roc, int32_t row, float gridU, float gridV, float& u, float& v) const; /// convert corrected u,v to internal grid coordinates - GPUd() void convCorrectedUVtoGrid(int32_t slice, int32_t row, float cu, float cv, float& gridU, float& gridV) const; + GPUd() void convCorrectedUVtoGrid(int32_t roc, int32_t row, float cu, float cv, float& gridU, float& gridV) const; /// TPC geometry information GPUd() const TPCFastTransformGeo& getGeometry() const @@ -223,28 +223,28 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Gives TPC row info GPUd() const RowInfo& getRowInfo(int32_t row) const { return mRowInfos[row]; } - /// Gives TPC slice info - GPUd() const SliceInfo& getSliceInfo(int32_t slice) const + /// Gives TPC roc info + GPUd() const RocInfo& getRocInfo(int32_t roc) const { - return mSliceInfo[slice]; + return mRocInfo[roc]; } - /// Gives TPC slice info - GPUd() SliceInfo& getSliceInfo(int32_t slice) + /// Gives TPC roc info + GPUd() RocInfo& getRocInfo(int32_t roc) { - return mSliceInfo[slice]; + return mRocInfo[roc]; } - /// Gives TPC slice & row info - GPUd() const SliceRowInfo& getSliceRowInfo(int32_t slice, int32_t row) const + /// Gives TPC roc & row info + GPUd() const RocRowInfo& getRocRowInfo(int32_t roc, int32_t row) const { - return mSliceRowInfos[mGeo.getMaxNumberOfRows() * slice + row]; + return mRocRowInfos[mGeo.getMaxNumberOfRows() * roc + row]; } - /// Gives TPC slice & row info - GPUd() SliceRowInfo& getSliceRowInfo(int32_t slice, int32_t row) + /// Gives TPC roc & row info + GPUd() RocRowInfo& getRocRowInfo(int32_t roc, int32_t row) { - return mSliceRowInfos[mGeo.getMaxNumberOfRows() * slice + row]; + return mRocRowInfos[mGeo.getMaxNumberOfRows() * roc + row]; } #if !defined(GPUCA_GPUCODE) @@ -260,7 +260,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject void releaseConstructionMemory(); /// temporary method with the an way of calculating 2D spline - GPUd() int32_t getCorrectionOld(int32_t slice, int32_t row, float u, float v, float& dx, float& du, float& dv) const; + GPUd() int32_t getCorrectionOld(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; /// _______________ Data members _______________________________________________ @@ -274,7 +274,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject int32_t mNumberOfScenarios; ///< Number of approximation spline scenarios - SliceInfo mSliceInfo[TPCFastTransformGeo::getNumberOfSlices()]; ///< SliceInfo array + RocInfo mRocInfo[TPCFastTransformGeo::getNumberOfRocs()]; ///< RocInfo array SplineType* mScenarioPtr; //! (transient!!) pointer to spline scenarios @@ -284,7 +284,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject char* mSplineData[3]; //! (transient!!) pointer to the spline data in the flat buffer - size_t mSliceDataSizeBytes[3]; ///< size of the data for one slice in the flat buffer + size_t mRocDataSizeBytes[3]; ///< size of the data for one roc in the flat buffer float fInterpolationSafetyMargin{0.1f}; // 10% area around the TPC row. Outside of this area the interpolation returns the boundary values. @@ -295,72 +295,72 @@ class TPCFastSpaceChargeCorrection : public FlatObject RowInfo mRowInfos[TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RowInfo array - SliceRowInfo mSliceRowInfos[TPCFastTransformGeo::getNumberOfSlices() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< SliceRowInfo array + RocRowInfo mRocRowInfos[TPCFastTransformGeo::getNumberOfRocs() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RocRowInfo array - ClassDefNV(TPCFastSpaceChargeCorrection, 4); + ClassDefNV(TPCFastSpaceChargeCorrection, 5); }; /// ==================================================== /// Inline implementations of some methods /// ==================================================== -GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t slice, int32_t row) const +GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t roc, int32_t row) const { /// Gives const pointer to spline const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } -GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t slice, int32_t row) +GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t roc, int32_t row) { /// Gives pointer to spline const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } -GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t slice, int32_t row, int32_t iSpline) +GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t roc, int32_t row, int32_t iSpline) { /// Gives pointer to spline data const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mSliceDataSizeBytes[iSpline] * slice + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + mRocDataSizeBytes[iSpline] * roc + rowInfo.dataOffsetBytes[iSpline]); } -GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t slice, int32_t row, int32_t iSpline) const +GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t roc, int32_t row, int32_t iSpline) const { /// Gives pointer to spline data const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mSliceDataSizeBytes[iSpline] * slice + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + mRocDataSizeBytes[iSpline] * roc + rowInfo.dataOffsetBytes[iSpline]); } -GPUdi() void TPCFastSpaceChargeCorrection::convUVtoGrid(int32_t slice, int32_t row, float u, float v, float& gu, float& gv) const +GPUdi() void TPCFastSpaceChargeCorrection::convUVtoGrid(int32_t roc, int32_t row, float u, float v, float& gu, float& gv) const { - const auto& info = getSliceRowInfo(slice, row); + const auto& info = getRocRowInfo(roc, row); gu = (u - info.gridU0) * info.scaleUtoGrid; gv = (v - info.gridV0) * info.scaleVtoGrid; } -GPUdi() void TPCFastSpaceChargeCorrection::convGridToUV(int32_t slice, int32_t row, float gridU, float gridV, float& u, float& v) const +GPUdi() void TPCFastSpaceChargeCorrection::convGridToUV(int32_t roc, int32_t row, float gridU, float gridV, float& u, float& v) const { /// convert internal grid coordinates to u,v - const SliceRowInfo& info = getSliceRowInfo(slice, row); + const RocRowInfo& info = getRocRowInfo(roc, row); u = info.gridU0 + gridU / info.scaleUtoGrid; v = info.gridV0 + gridV / info.scaleVtoGrid; } -GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t slice, int32_t row, float corrU, float corrV, float& gridU, float& gridV) const +GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t roc, int32_t row, float corrU, float corrV, float& gridU, float& gridV) const { - const SliceRowInfo& info = getSliceRowInfo(slice, row); + const RocRowInfo& info = getRocRowInfo(roc, row); gridU = (corrU - info.gridCorrU0) * info.scaleCorrUtoGrid; gridV = (corrV - info.gridCorrV0) * info.scaleCorrVtoGrid; } -GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t slice, int32_t row, float u, float v, float& dx, float& du, float& dv) const +GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const { - const auto& info = getSliceRowInfo(slice, row); - const SplineType& spline = getSpline(slice, row); - const float* splineData = getSplineData(slice, row); + const auto& info = getRocRowInfo(roc, row); + const SplineType& spline = getSpline(roc, row); + const float* splineData = getSplineData(roc, row); float gridU = 0, gridV = 0; - convUVtoGrid(slice, row, u, v, gridU, gridV); + convUVtoGrid(roc, row, u, v, gridU, gridV); // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); @@ -382,15 +382,15 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t slice, int32 return 0; } -GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t slice, int32_t row, float u, float v, float& dx, float& du, float& dv) const +GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const { - const SplineType& spline = getSpline(slice, row); - const float* splineData = getSplineData(slice, row); + const SplineType& spline = getSpline(roc, row); + const float* splineData = getSplineData(roc, row); float gridU = 0, gridV = 0; - convUVtoGrid(slice, row, u, v, gridU, gridV); + convUVtoGrid(roc, row, u, v, gridU, gridV); float dxuv[3]; spline.interpolateUold(splineData, gridU, gridV, dxuv); - const auto& info = getSliceRowInfo(slice, row); + const auto& info = getRocRowInfo(roc, row); float s = v / info.gridV0; if (s < 0.) { s = 0.; @@ -405,14 +405,14 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t slice, in } GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( - int32_t slice, int32_t row, float corrU, float corrV, float& x) const + int32_t roc, int32_t row, float corrU, float corrV, float& x) const { - const auto& info = getSliceRowInfo(slice, row); - const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); - const float* splineData = getSplineData(slice, row, 1); + const auto& info = getRocRowInfo(roc, row); + const Spline2D& spline = reinterpret_cast&>(getSpline(roc, row)); + const float* splineData = getSplineData(roc, row, 1); float gridU, gridV; - convCorrectedUVtoGrid(slice, row, corrU, corrV, gridU, gridV); + convCorrectedUVtoGrid(roc, row, corrU, corrV, gridU, gridV); // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); @@ -434,13 +434,13 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( } GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( - int32_t slice, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const + int32_t roc, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const { - const Spline2D& spline = reinterpret_cast&>(getSpline(slice, row)); - const float* splineData = getSplineData(slice, row, 2); + const Spline2D& spline = reinterpret_cast&>(getSpline(roc, row)); + const float* splineData = getSplineData(roc, row, 2); float gridU, gridV; - convCorrectedUVtoGrid(slice, row, corrU, corrV, gridU, gridV); + convCorrectedUVtoGrid(roc, row, corrU, corrV, gridU, gridV); // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); @@ -448,7 +448,7 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( float duv[2]; spline.interpolateU(splineData, gridU, gridV, duv); - const auto& info = getSliceRowInfo(slice, row); + const auto& info = getRocRowInfo(roc, row); float s = corrV / info.gridCorrV0; if (corrV >= info.gridCorrV0) { @@ -463,9 +463,9 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( nomV = corrV - duv[1]; } -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t slice, int32_t row, float pad) const +GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc, int32_t row, float pad) const { - const RowActiveArea& area = getSliceRowInfo(slice, row).activeArea; + const RowActiveArea& area = getRocRowInfo(roc, row).activeArea; const float* c = area.maxDriftLengthCheb; float x = -1.f + 2.f * pad / mGeo.getRowInfo(row).maxPad; float y = c[0] + c[1] * x; @@ -481,14 +481,14 @@ GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t slice, int return y; } -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t slice, int32_t row) const +GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc, int32_t row) const { - return getSliceRowInfo(slice, row).activeArea.vMax; + return getRocRowInfo(roc, row).activeArea.vMax; } -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t slice) const +GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc) const { - return getSliceInfo(slice).vMax; + return getRocInfo(roc).vMax; } } // namespace gpu diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index d9e35ba8bf405..8aef1748ebf62 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -46,14 +46,14 @@ struct TPCSlowSpaceChargeCorrection { ~TPCSlowSpaceChargeCorrection(); /// getting the corrections for global coordinates - void getCorrections(const float gx, const float gy, const float gz, const int32_t slice, float& gdxC, float& gdyC, float& gdzC) const; + void getCorrections(const float gx, const float gy, const float gz, const int32_t roc, float& gdxC, float& gdyC, float& gdzC) const; o2::tpc::SpaceCharge* mCorr{nullptr}; ///< reference space charge corrections #else ~TPCSlowSpaceChargeCorrection() = default; /// setting dummy corrections for GPU - GPUd() void getCorrections(const float gx, const float gy, const float gz, const int32_t slice, float& gdxC, float& gdyC, float& gdzC) const + GPUd() void getCorrections(const float gx, const float gy, const float gz, const int32_t roc, float& gdxC, float& gdyC, float& gdzC) const { gdxC = 0; gdyC = 0; @@ -182,50 +182,50 @@ class TPCFastTransform : public FlatObject /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a slice + /// Transforms raw TPC coordinates to local XYZ withing a roc /// taking calibration + alignment into account. /// - GPUd() void Transform(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; - GPUd() void TransformXYZ(int32_t slice, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Transformation in the time frame - GPUd() void TransformInTimeFrame(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const; - GPUd() void TransformInTimeFrame(int32_t slice, float time, float& z, float maxTimeBin) const; + GPUd() void TransformInTimeFrame(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const; + GPUd() void TransformInTimeFrame(int32_t roc, float time, float& z, float maxTimeBin) const; /// Inverse transformation - GPUd() void InverseTransformInTimeFrame(int32_t slice, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const; - GPUd() float InverseTransformInTimeFrame(int32_t slice, float z, float maxTimeBin) const; + GPUd() void InverseTransformInTimeFrame(int32_t roc, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const; + GPUd() float InverseTransformInTimeFrame(int32_t roc, float z, float maxTimeBin) const; /// Inverse transformation: Transformed Y and Z -> transformed X - GPUd() void InverseTransformYZtoX(int32_t slice, int32_t row, float y, float z, float& x, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoX(int32_t roc, int32_t row, float y, float z, float& x, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Inverse transformation: Transformed Y and Z -> Y and Z, transformed w/o space charge correction - GPUd() void InverseTransformYZtoNominalYZ(int32_t slice, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoNominalYZ(int32_t roc, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction - GPUd() void InverseTransformXYZtoNominalXYZ(int32_t slice, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformXYZtoNominalXYZ(int32_t roc, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Ideal transformation with Vdrift only - without calibration - GPUd() void TransformIdeal(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; - GPUd() void TransformIdealZ(int32_t slice, float time, float& z, float vertexTime) const; + GPUd() void TransformIdeal(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; + GPUd() void TransformIdealZ(int32_t roc, float time, float& z, float vertexTime) const; - GPUd() void convPadTimeToUV(int32_t slice, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const; - GPUd() void convPadTimeToUVinTimeFrame(int32_t slice, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const; - GPUd() void convTimeToVinTimeFrame(int32_t slice, float time, float& v, float maxTimeBin) const; + GPUd() void convPadTimeToUV(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const; + GPUd() void convPadTimeToUVinTimeFrame(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const; + GPUd() void convTimeToVinTimeFrame(int32_t roc, float time, float& v, float maxTimeBin) const; - GPUd() void convUVtoPadTime(int32_t slice, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const; - GPUd() void convUVtoPadTimeInTimeFrame(int32_t slice, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const; + GPUd() void convUVtoPadTime(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const; + GPUd() void convUVtoPadTimeInTimeFrame(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const; GPUd() void convVtoTime(float v, float& time, float vertexTime) const; - GPUd() float convTimeToZinTimeFrame(int32_t slice, float time, float maxTimeBin) const; - GPUd() float convZtoTimeInTimeFrame(int32_t slice, float z, float maxTimeBin) const; - GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t slice, float deltaTime) const; - GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t slice, float deltaZ) const; + GPUd() float convTimeToZinTimeFrame(int32_t roc, float time, float maxTimeBin) const; + GPUd() float convZtoTimeInTimeFrame(int32_t roc, float z, float maxTimeBin) const; + GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const; + GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t roc, float deltaZ) const; GPUd() float convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const; - GPUd() float convZOffsetToVertexTime(int32_t slice, float zOffset, float maxTimeBin) const; - GPUd() float convVertexTimeToZOffset(int32_t slice, float vertexTime, float maxTimeBin) const; + GPUd() float convZOffsetToVertexTime(int32_t roc, float zOffset, float maxTimeBin) const; + GPUd() float convVertexTimeToZOffset(int32_t roc, float vertexTime, float maxTimeBin) const; - GPUd() void getTOFcorrection(int32_t slice, int32_t row, float x, float y, float z, float& dz) const; + GPUd() void getTOFcorrection(int32_t roc, int32_t row, float x, float y, float z, float& dz) const; void setApplyCorrectionOn() { mApplyCorrection = 1; } void setApplyCorrectionOff() { mApplyCorrection = 0; } @@ -276,13 +276,13 @@ class TPCFastTransform : public FlatObject GPUd() float getLumiScaleFactor() const { return mLumiScaleFactor; } /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t slice, int32_t row, float pad) const; + GPUd() float getMaxDriftTime(int32_t roc, int32_t row, float pad) const; /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t slice, int32_t row) const; + GPUd() float getMaxDriftTime(int32_t roc, int32_t row) const; /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t slice) const; + GPUd() float getMaxDriftTime(int32_t roc) const; #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) @@ -359,7 +359,7 @@ class TPCFastTransform : public FlatObject /// Correction of (x,u,v) with tricubic interpolator on a regular grid TPCSlowSpaceChargeCorrection* mCorrectionSlow{nullptr}; ///< reference space charge corrections - GPUd() void TransformInternal(int32_t slice, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; + GPUd() void TransformInternal(int32_t roc, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; ClassDefNV(TPCFastTransform, 4); }; @@ -368,69 +368,69 @@ class TPCFastTransform : public FlatObject // Inline implementations of some methods // ======================================================================= -GPUdi() void TPCFastTransform::convPadTimeToUV(int32_t slice, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const +GPUdi() void TPCFastTransform::convPadTimeToUV(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const { - bool sideC = (slice >= getGeometry().getNumberOfSlicesA()); + bool sideC = (roc >= getGeometry().getNumberOfRocsA()); const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::SliceInfo& sliceInfo = getGeometry().getSliceInfo(slice); + const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); float x = rowInfo.x; u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * sliceInfo.cosAlpha + x * sliceInfo.sinAlpha; + float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; v = (time - mT0 - vertexTime) * (mVdrift + mVdriftCorrY * yLab) + mLdriftCorr; // drift length cm } -GPUdi() void TPCFastTransform::convTimeToVinTimeFrame(int32_t slice, float time, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convTimeToVinTimeFrame(int32_t roc, float time, float& v, float maxTimeBin) const { v = (time - mT0 - maxTimeBin) * mVdrift + mLdriftCorr; // drift length cm - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { v += getGeometry().getTPCzLengthA(); } else { v += getGeometry().getTPCzLengthC(); } } -GPUdi() void TPCFastTransform::convPadTimeToUVinTimeFrame(int32_t slice, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convPadTimeToUVinTimeFrame(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const { const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - convTimeToVinTimeFrame(slice, time, v, maxTimeBin); + convTimeToVinTimeFrame(roc, time, v, maxTimeBin); } -GPUdi() float TPCFastTransform::convZOffsetToVertexTime(int32_t slice, float zOffset, float maxTimeBin) const +GPUdi() float TPCFastTransform::convZOffsetToVertexTime(int32_t roc, float zOffset, float maxTimeBin) const { - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { return maxTimeBin - (getGeometry().getTPCzLengthA() + zOffset) / mVdrift; } else { return maxTimeBin - (getGeometry().getTPCzLengthC() - zOffset) / mVdrift; } } -GPUdi() float TPCFastTransform::convVertexTimeToZOffset(int32_t slice, float vertexTime, float maxTimeBin) const +GPUdi() float TPCFastTransform::convVertexTimeToZOffset(int32_t roc, float vertexTime, float maxTimeBin) const { - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { return (maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLengthA(); } else { return -((maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLengthC()); } } -GPUdi() void TPCFastTransform::convUVtoPadTime(int32_t slice, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const +GPUdi() void TPCFastTransform::convUVtoPadTime(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const { - bool sideC = (slice >= getGeometry().getNumberOfSlicesA()); + bool sideC = (roc >= getGeometry().getNumberOfRocsA()); const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::SliceInfo& sliceInfo = getGeometry().getSliceInfo(slice); + const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; float x = rowInfo.x; float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * sliceInfo.cosAlpha + x * sliceInfo.sinAlpha; + float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; time = mT0 + vertexTime + (v - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); } @@ -440,9 +440,9 @@ GPUdi() void TPCFastTransform::convVtoTime(float v, float& time, float vertexTim time = mT0 + vertexTime + (v - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); } -GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t slice, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const +GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const { - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { v -= getGeometry().getTPCzLengthA(); } else { v -= getGeometry().getTPCzLengthC(); @@ -452,17 +452,17 @@ GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t slice, int32_t time = mT0 + maxTimeBin + (v - mLdriftCorr) / mVdrift; } -GPUdi() void TPCFastTransform::getTOFcorrection(int32_t slice, int32_t /*row*/, float x, float y, float z, float& dz) const +GPUdi() void TPCFastTransform::getTOFcorrection(int32_t roc, int32_t /*row*/, float x, float y, float z, float& dz) const { // calculate time of flight correction for z coordinate - bool sideC = (slice >= getGeometry().getNumberOfSlicesA()); + bool sideC = (roc >= getGeometry().getNumberOfRocsA()); float distZ = z - mPrimVtxZ; float dv = -GPUCommonMath::Sqrt(x * x + y * y + distZ * distZ) * mTOFcorr; dz = sideC ? dv : -dv; } -GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::TransformInternal(int32_t roc, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); if (mApplyCorrection) { @@ -471,15 +471,15 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo #ifndef GPUCA_GPUCODE if (mCorrectionSlow) { float ly, lz; - getGeometry().convUVtoLocal(slice, u, v, ly, lz); + getGeometry().convUVtoLocal(roc, u, v, ly, lz); float gx, gy, gz; - getGeometry().convLocalToGlobal(slice, x, ly, lz, gx, gy, gz); + getGeometry().convLocalToGlobal(roc, x, ly, lz, gx, gy, gz); float gdxC, gdyC, gdzC; - mCorrectionSlow->getCorrections(gx, gy, gz, slice, gdxC, gdyC, gdzC); - getGeometry().convGlobalToLocal(slice, gdxC, gdyC, gdzC, dx, du, dv); + mCorrectionSlow->getCorrections(gx, gy, gz, roc, gdxC, gdyC, gdzC); + getGeometry().convGlobalToLocal(roc, gdxC, gdyC, gdzC, dx, du, dv); - if (slice >= 18) { + if (roc >= 18) { du = -du; // mirror for c-Side } else { dv = -dv; // mirror z for A-Side @@ -487,17 +487,17 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo } else #endif // GPUCA_GPUCODE { - mCorrection.getCorrection(slice, row, u, v, dx, du, dv); + mCorrection.getCorrection(roc, row, u, v, dx, du, dv); if (ref) { if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested float dxRef, duRef, dvRef; - ref->mCorrection.getCorrection(slice, row, u, v, dxRef, duRef, dvRef); + ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); dx = (dx - dxRef) * scale + dxRef; du = (du - duRef) * scale + duRef; dv = (dv - dvRef) * scale + dvRef; } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { float dxRef, duRef, dvRef; - ref->mCorrection.getCorrection(slice, row, u, v, dxRef, duRef, dvRef); + ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); dx = dxRef * scale + dx; du = duRef * scale + du; dv = dvRef * scale + dv; @@ -505,7 +505,7 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo } if (ref2 && (scale2 != 0)) { float dxRef, duRef, dvRef; - ref2->mCorrection.getCorrection(slice, row, u, v, dxRef, duRef, dvRef); + ref2->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); dx = dxRef * scale2 + dx; du = duRef * scale2 + du; dv = dvRef * scale2 + dv; @@ -514,43 +514,43 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo } GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { float ly, lz; - getGeometry().convUVtoLocal(slice, u, v, ly, lz); + getGeometry().convUVtoLocal(roc, u, v, ly, lz); float gx, gy, gz; - getGeometry().convLocalToGlobal(slice, x, ly, lz, gx, gy, gz); + getGeometry().convLocalToGlobal(roc, x, ly, lz, gx, gy, gz); float lyT, lzT; float uCorr = u + du; float vCorr = v + dv; float lxT = x + dx; - getGeometry().convUVtoLocal(slice, uCorr, vCorr, lyT, lzT); + getGeometry().convUVtoLocal(roc, uCorr, vCorr, lyT, lzT); float invYZtoXScaled; - InverseTransformYZtoX(slice, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); float invYZtoX; - InverseTransformYZtoX(slice, row, lyT, lzT, invYZtoX); + InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoX); float YZtoNominalY; float YZtoNominalZ; - InverseTransformYZtoNominalYZ(slice, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); + InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); float YZtoNominalYScaled; float YZtoNominalZScaled; - InverseTransformYZtoNominalYZ(slice, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); float dxRef, duRef, dvRef; if (ref) { - ref->mCorrection.getCorrection(slice, row, u, v, dxRef, duRef, dvRef); + ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); } float dxRef2, duRef2, dvRef2; if (ref2) { - ref2->mCorrection.getCorrection(slice, row, u, v, dxRef2, duRef2, dvRef2); + ref2->mCorrection.getCorrection(roc, row, u, v, dxRef2, duRef2, dvRef2); } float dxOrig, duOrig, dvOrig; - mCorrection.getCorrection(slice, row, u, v, dxOrig, duOrig, dvOrig); + mCorrection.getCorrection(roc, row, u, v, dxOrig, duOrig, dvOrig); o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() // corrections in x, u, v @@ -569,7 +569,7 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo << "v=" << v << "u=" << u << "row=" << row - << "slice=" << slice + << "roc=" << roc << "scale=" << scale << "scale2=" << scale2 // original local coordinates @@ -601,51 +601,51 @@ GPUdi() void TPCFastTransform::TransformInternal(int32_t slice, int32_t row, flo } } -GPUdi() void TPCFastTransform::TransformXYZ(int32_t slice, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { float u, v; - getGeometry().convLocalToUV(slice, y, z, u, v); - TransformInternal(slice, row, u, v, x, ref, ref2, scale, scale2, scaleMode); - getGeometry().convUVtoLocal(slice, u, v, y, z); + getGeometry().convLocalToUV(roc, y, z, u, v); + TransformInternal(roc, row, u, v, x, ref, ref2, scale, scale2, scaleMode); + getGeometry().convUVtoLocal(roc, u, v, y, z); float dzTOF = 0; - getTOFcorrection(slice, row, x, y, z, dzTOF); + getTOFcorrection(roc, row, x, y, z, dzTOF); z += dzTOF; } -GPUdi() void TPCFastTransform::Transform(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a slice + /// Transforms raw TPC coordinates to local XYZ withing a roc /// taking calibration + alignment into account. /// const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - // const SliceInfo &sliceInfo = getSliceInfo( slice ); - // bool sideC = ( slice >= NumberOfSlices / 2 ); + // const RocInfo &rocInfo = getRocInfo( roc ); + // bool sideC = ( roc >= NumberOfRocs / 2 ); x = rowInfo.x; float u = 0, v = 0; - convPadTimeToUV(slice, row, pad, time, u, v, vertexTime); + convPadTimeToUV(roc, row, pad, time, u, v, vertexTime); - TransformInternal(slice, row, u, v, x, ref, ref2, scale, scale2, scaleMode); + TransformInternal(roc, row, u, v, x, ref, ref2, scale, scale2, scaleMode); - getGeometry().convUVtoLocal(slice, u, v, y, z); + getGeometry().convUVtoLocal(roc, u, v, y, z); float dzTOF = 0; - getTOFcorrection(slice, row, x, y, z, dzTOF); + getTOFcorrection(roc, row, x, y, z, dzTOF); z += dzTOF; } -GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t slice, float time, float& z, float maxTimeBin) const +GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, float time, float& z, float maxTimeBin) const { float v = 0; - convTimeToVinTimeFrame(slice, time, v, maxTimeBin); - getGeometry().convVtoLocal(slice, v, z); + convTimeToVinTimeFrame(roc, time, v, maxTimeBin); + getGeometry().convVtoLocal(roc, v, z); } -GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const +GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const { /// _______________ Special cluster transformation for a time frame _______________________ /// @@ -656,43 +656,43 @@ GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t slice, int32_t row, const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); x = rowInfo.x; float u = 0, v = 0; - convPadTimeToUVinTimeFrame(slice, row, pad, time, u, v, maxTimeBin); - getGeometry().convUVtoLocal(slice, u, v, y, z); + convPadTimeToUVinTimeFrame(roc, row, pad, time, u, v, maxTimeBin); + getGeometry().convUVtoLocal(roc, u, v, y, z); } -GPUdi() void TPCFastTransform::InverseTransformInTimeFrame(int32_t slice, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const +GPUdi() void TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const { /// Inverse transformation to TransformInTimeFrame float u = 0, v = 0; - getGeometry().convLocalToUV(slice, y, z, u, v); - convUVtoPadTimeInTimeFrame(slice, row, u, v, pad, time, maxTimeBin); + getGeometry().convLocalToUV(roc, y, z, u, v); + convUVtoPadTimeInTimeFrame(roc, row, u, v, pad, time, maxTimeBin); } -GPUdi() float TPCFastTransform::InverseTransformInTimeFrame(int32_t slice, float z, float maxTimeBin) const +GPUdi() float TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, float z, float maxTimeBin) const { float pad, time; - InverseTransformInTimeFrame(slice, 0, 0, 0, z, pad, time, maxTimeBin); + InverseTransformInTimeFrame(roc, 0, 0, 0, z, pad, time, maxTimeBin); return time; } -GPUdi() void TPCFastTransform::TransformIdealZ(int32_t slice, float time, float& z, float vertexTime) const +GPUdi() void TPCFastTransform::TransformIdealZ(int32_t roc, float time, float& z, float vertexTime) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms time TPC coordinates to local Z withing a slice + /// Transforms time TPC coordinates to local Z withing a roc /// Ideal transformation: only Vdrift from DCS. /// No space charge corrections, no time of flight correction /// float v = (time - mT0 - vertexTime) * mVdrift; // drift length cm - getGeometry().convVtoLocal(slice, v, z); + getGeometry().convVtoLocal(roc, v, z); } -GPUdi() void TPCFastTransform::TransformIdeal(int32_t slice, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const +GPUdi() void TPCFastTransform::TransformIdeal(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a slice + /// Transforms raw TPC coordinates to local XYZ withing a roc /// Ideal transformation: only Vdrift from DCS. /// No space charge corrections, no time of flight correction /// @@ -703,10 +703,10 @@ GPUdi() void TPCFastTransform::TransformIdeal(int32_t slice, int32_t row, float float u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; float v = (time - mT0 - vertexTime) * mVdrift; // drift length cm - getGeometry().convUVtoLocal(slice, u, v, y, z); + getGeometry().convUVtoLocal(roc, u, v, y, z); } -GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t slice, float time, float maxTimeBin) const +GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t roc, float time, float maxTimeBin) const { /// _______________ Special cluster transformation for a time frame _______________________ /// @@ -717,7 +717,7 @@ GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t slice, float time float v = (time - mT0 - maxTimeBin) * mVdrift + mLdriftCorr; // drift length cm float z = getGeometry().getTPCalignmentZ(); // global TPC alignment - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { z -= v; } else { z += v; @@ -725,11 +725,11 @@ GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t slice, float time return z; } -GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t slice, float z, float maxTimeBin) const +GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t roc, float z, float maxTimeBin) const { /// Inverse transformation of convTimeToZinTimeFrame() float v; - if (slice < getGeometry().getNumberOfSlicesA()) { + if (roc < getGeometry().getNumberOfRocsA()) { v = getGeometry().getTPCalignmentZ() - z; } else { v = z - getGeometry().getTPCalignmentZ(); @@ -737,10 +737,10 @@ GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t slice, float z, f return mT0 + maxTimeBin + (v - mLdriftCorr) / mVdrift; } -GPUdi() float TPCFastTransform::convDeltaTimeToDeltaZinTimeFrame(int32_t slice, float deltaTime) const +GPUdi() float TPCFastTransform::convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const { float deltaZ = deltaTime * mVdrift; - return slice < getGeometry().getNumberOfSlicesA() ? -deltaZ : deltaZ; + return roc < getGeometry().getNumberOfRocsA() ? -deltaZ : deltaZ; } GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const @@ -748,80 +748,80 @@ GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ return deltaZ / mVdrift; } -GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrame(int32_t slice, float deltaZ) const +GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrame(int32_t roc, float deltaZ) const { float deltaT = deltaZ / mVdrift; - return slice < getGeometry().getNumberOfSlicesA() ? -deltaT : deltaT; + return roc < getGeometry().getNumberOfRocsA() ? -deltaT : deltaT; } /* -GPUdi() float TPCFastTransform::getLastCalibratedTimeBin(int32_t slice) const +GPUdi() float TPCFastTransform::getLastCalibratedTimeBin(int32_t roc) const { /// Return a value of the last timebin where correction map is valid float u, v, pad, time; - getGeometry().convScaledUVtoUV(slice, 0, 0.f, 1.f, u, v); - convUVtoPadTime(slice, 0, u, v, pad, time, 0); + getGeometry().convScaledUVtoUV(roc, 0, 0.f, 1.f, u, v); + convUVtoPadTime(roc, 0, u, v, pad, time, 0); return time; } */ -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t slice, int32_t row, float pad) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row, float pad) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(slice, row, pad); + float maxL = mCorrection.getMaxDriftLength(roc, row, pad); - bool sideC = (slice >= getGeometry().getNumberOfSlicesA()); + bool sideC = (roc >= getGeometry().getNumberOfRocsA()); const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::SliceInfo& sliceInfo = getGeometry().getSliceInfo(slice); + const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); float x = rowInfo.x; float u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * sliceInfo.cosAlpha + x * sliceInfo.sinAlpha; + float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; return mT0 + (maxL - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); } -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t slice, int32_t row) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(slice, row); + float maxL = mCorrection.getMaxDriftLength(roc, row); float maxTime = 0.f; convVtoTime(maxL, maxTime, 0.f); return maxTime; } -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t slice) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(slice); + float maxL = mCorrection.getMaxDriftLength(roc); float maxTime = 0.f; convVtoTime(maxL, maxTime, 0.f); return maxTime; } -GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t slice, int32_t row, float y, float z, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t roc, int32_t row, float y, float z, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); /// Transformation y,z -> x float u = 0, v = 0; - getGeometry().convLocalToUV(slice, y, z, u, v); + getGeometry().convLocalToUV(roc, y, z, u, v); if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { - mCorrection.getCorrectionInvCorrectedX(slice, row, u, v, x); + mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, x); if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { float xr; - ref->mCorrection.getCorrectionInvCorrectedX(slice, row, u, v, xr); + ref->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); x = (x - xr) * scale + xr; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { float xr; - ref->mCorrection.getCorrectionInvCorrectedX(slice, row, u, v, xr); + ref->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); x = (xr - getGeometry().getRowInfo(row).x) * scale + x; // xr=mGeo.getRowInfo(row).x + dx; } } if (ref2 && (scale2 != 0)) { float xr; - ref2->mCorrection.getCorrectionInvCorrectedX(slice, row, u, v, xr); + ref2->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); x = (xr - getGeometry().getRowInfo(row).x) * scale2 + x; // xr=mGeo.getRowInfo(row).x + dx; } } else { @@ -829,7 +829,7 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t slice, int32_t row, } GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoX").data() - << "slice=" << slice + << "roc=" << roc << "row=" << row << "scale=" << scale << "y=" << y @@ -841,29 +841,29 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t slice, int32_t row, }) } -GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t slice, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t roc, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); /// Transformation y,z -> x float u = 0, v = 0, un = 0, vn = 0; - getGeometry().convLocalToUV(slice, y, z, u, v); + getGeometry().convLocalToUV(roc, y, z, u, v); if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { - mCorrection.getCorrectionInvUV(slice, row, u, v, un, vn); + mCorrection.getCorrectionInvUV(roc, row, u, v, un, vn); if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { float unr = 0, vnr = 0; - ref->mCorrection.getCorrectionInvUV(slice, row, u, v, unr, vnr); + ref->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); un = (un - unr) * scale + unr; vn = (vn - vnr) * scale + vnr; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { float unr = 0, vnr = 0; - ref->mCorrection.getCorrectionInvUV(slice, row, u, v, unr, vnr); + ref->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); un = (unr - u) * scale + un; // unr = u - duv[0]; vn = (vnr - v) * scale + vn; } if (ref2 && (scale2 != 0)) { float unr = 0, vnr = 0; - ref2->mCorrection.getCorrectionInvUV(slice, row, u, v, unr, vnr); + ref2->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); un = (unr - u) * scale2 + un; // unr = u - duv[0]; vn = (vnr - v) * scale2 + vn; } @@ -872,11 +872,11 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t slice, int3 un = u; vn = v; } - getGeometry().convUVtoLocal(slice, un, vn, ny, nz); + getGeometry().convUVtoLocal(roc, un, vn, ny, nz); GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoNominalYZ").data() - << "slice=" << slice + << "roc=" << roc << "row=" << row << "scale=" << scale << "y=" << y @@ -891,7 +891,7 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t slice, int3 }) } -GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t slice, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t roc, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction int32_t row2 = row + 1; @@ -902,8 +902,8 @@ GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t slice, in float nx2, ny2, nz2; // nominal coordinates for row2 nx1 = getGeometry().getRowInfo(row).x; nx2 = getGeometry().getRowInfo(row2).x; - InverseTransformYZtoNominalYZ(slice, row, y, z, ny1, nz1, ref, ref2, scale, scale2, scaleMode); - InverseTransformYZtoNominalYZ(slice, row2, y, z, ny2, nz2, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(roc, row, y, z, ny1, nz1, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(roc, row2, y, z, ny2, nz2, ref, ref2, scale, scale2, scaleMode); float c1 = (nx2 - nx) / (nx2 - nx1); float c2 = (nx - nx1) / (nx2 - nx1); nx = x; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index 3c624b3222d77..b472868fa1071 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -28,14 +28,14 @@ using namespace o2::gpu; TPCFastTransformGeo::TPCFastTransformGeo() { // Default Constructor: creates an empty uninitialized object - double dAlpha = 2. * M_PI / (NumberOfSlicesA); - for (int32_t i = 0; i < NumberOfSlices; i++) { - SliceInfo& s = mSliceInfos[i]; + double dAlpha = 2. * M_PI / (NumberOfRocsA); + for (int32_t i = 0; i < NumberOfRocs; i++) { + RocInfo& s = mRocInfos[i]; double alpha = dAlpha * (i + 0.5); s.sinAlpha = sin(alpha); s.cosAlpha = cos(alpha); } - mSliceInfos[NumberOfSlices] = SliceInfo{0.f, 0.f}; + mRocInfos[NumberOfRocs] = RocInfo{0.f, 0.f}; for (int32_t i = 0; i < MaxNumberOfRows + 1; i++) { mRowInfos[i] = RowInfo{0.f, -1, 0.f, 0.f, 0.f, 0.f}; @@ -104,7 +104,7 @@ void TPCFastTransformGeo::setTPCrow(int32_t iRow, float x, int32_t nPads, float // Make scaled U = area between the geometrical sector borders - const double sectorAngle = 2. * M_PI / NumberOfSlicesA; + const double sectorAngle = 2. * M_PI / NumberOfRocsA; const double scaleXtoRowWidth = 2. * tan(0.5 * sectorAngle); double uWidth = x * scaleXtoRowWidth; // distance to the sector border @@ -148,7 +148,7 @@ void TPCFastTransformGeo::print() const #endif } -int32_t TPCFastTransformGeo::test(int32_t slice, int32_t row, float ly, float lz) const +int32_t TPCFastTransformGeo::test(int32_t roc, int32_t row, float ly, float lz) const { /// Check consistency of the class @@ -164,16 +164,16 @@ int32_t TPCFastTransformGeo::test(int32_t slice, int32_t row, float ly, float lz float lx1 = 0.f, ly1 = 0.f, lz1 = 0.f; float gx = 0.f, gy = 0.f, gz = 0.f; - convLocalToGlobal(slice, lx, ly, lz, gx, gy, gz); - convGlobalToLocal(slice, gx, gy, gz, lx1, ly1, lz1); + convLocalToGlobal(roc, lx, ly, lz, gx, gy, gz); + convGlobalToLocal(roc, gx, gy, gz, lx1, ly1, lz1); if (fabs(lx1 - lx) > 1.e-4 || fabs(ly1 - ly) > 1.e-4 || fabs(lz1 - lz) > 1.e-7) { LOG(info) << "Error local <-> global: x " << lx << " dx " << lx1 - lx << " y " << ly << " dy " << ly1 - ly << " z " << lz << " dz " << lz1 - lz; error = -3; } float u = 0.f, v = 0.f; - convLocalToUV(slice, ly, lz, u, v); - convUVtoLocal(slice, u, v, ly1, lz1); + convLocalToUV(roc, ly, lz, u, v); + convUVtoLocal(roc, u, v, ly1, lz1); if (fabs(ly1 - ly) + fabs(lz1 - lz) > 1.e-6) { LOG(info) << "Error local <-> UV: y " << ly << " dy " << ly1 - ly << " z " << lz << " dz " << lz1 - lz; @@ -182,7 +182,7 @@ int32_t TPCFastTransformGeo::test(int32_t slice, int32_t row, float ly, float lz float su = 0.f, sv = 0.f; - convUVtoScaledUV(slice, row, u, v, su, sv); + convUVtoScaledUV(roc, row, u, v, su, sv); if (su < 0.f || su > 1.f) { LOG(info) << "Error scaled U range: u " << u << " su " << su; @@ -190,7 +190,7 @@ int32_t TPCFastTransformGeo::test(int32_t slice, int32_t row, float ly, float lz } float u1 = 0.f, v1 = 0.f; - convScaledUVtoUV(slice, row, su, sv, u1, v1); + convScaledUVtoUV(roc, row, su, sv, u1, v1); if (fabs(u1 - u) > 1.e-4 || fabs(v1 - v) > 1.e-4) { LOG(info) << "Error UV<->scaled UV: u " << u << " du " << u1 - u << " v " << v << " dv " << v1 - v; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index d20331ba6ab0f..3382d1d926ce2 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -34,11 +34,11 @@ namespace gpu class TPCFastTransformGeo { public: - /// The struct contains necessary info for TPC slice - struct SliceInfo { + /// The struct contains necessary info for TPC ROC + struct RocInfo { float sinAlpha; float cosAlpha; - ClassDefNV(SliceInfo, 1); + ClassDefNV(RocInfo, 1); }; /// The struct contains necessary info about TPC padrow @@ -58,6 +58,7 @@ class TPCFastTransformGeo /// get width in U GPUd() float getUwidth() const { return -2.f * u0; } + ClassDefNV(RowInfo, 1); }; @@ -107,11 +108,11 @@ class TPCFastTransformGeo /// _______________ Getters _________________________________ - /// Gives number of TPC slices - GPUd() static constexpr int32_t getNumberOfSlices() { return NumberOfSlices; } + /// Gives number of TPC ROCs + GPUd() static constexpr int32_t getNumberOfRocs() { return NumberOfRocs; } - /// Gives number of TPC slices in A side - GPUd() static constexpr int32_t getNumberOfSlicesA() { return NumberOfSlicesA; } + /// Gives number of TPC ROCs on the A side + GPUd() static constexpr int32_t getNumberOfRocsA() { return NumberOfRocsA; } /// Gives number of TPC rows GPUd() int32_t getNumberOfRows() const { return mNumberOfRows; } @@ -119,8 +120,8 @@ class TPCFastTransformGeo /// Gives number of TPC rows GPUd() static constexpr int getMaxNumberOfRows() { return MaxNumberOfRows; } - /// Gives slice info - GPUd() const SliceInfo& getSliceInfo(int32_t slice) const; + /// Gives roc info + GPUd() const RocInfo& getRocInfo(int32_t roc) const; /// Gives TPC row info GPUd() const RowInfo& getRowInfo(int32_t row) const; @@ -131,11 +132,11 @@ class TPCFastTransformGeo /// Gives Z length of the TPC, side C GPUd() float getTPCzLengthC() const { return mTPCzLengthC; } - /// Gives Z length of the TPC, depending on the slice - GPUd() float getTPCzLength(int32_t slice) const + /// Gives Z length of the TPC, depending on the roc + GPUd() float getTPCzLength(int32_t roc) const { - return (slice < NumberOfSlicesA) ? mTPCzLengthA - : mTPCzLengthC; + return (roc < NumberOfRocsA) ? mTPCzLengthA + : mTPCzLengthC; } /// Gives TPC alignment in Z @@ -144,26 +145,26 @@ class TPCFastTransformGeo /// _______________ Conversion of coordinate systems __________ /// convert Local -> Global c.s. - GPUd() void convLocalToGlobal(int32_t slice, float lx, float ly, float lz, float& gx, float& gy, float& gz) const; + GPUd() void convLocalToGlobal(int32_t roc, float lx, float ly, float lz, float& gx, float& gy, float& gz) const; /// convert Global->Local c.s. - GPUd() void convGlobalToLocal(int32_t slice, float gx, float gy, float gz, float& lx, float& ly, float& lz) const; + GPUd() void convGlobalToLocal(int32_t roc, float gx, float gy, float gz, float& lx, float& ly, float& lz) const; /// convert UV -> Local c.s. - GPUd() void convUVtoLocal(int32_t slice, float u, float v, float& y, float& z) const; - GPUd() void convVtoLocal(int32_t slice, float v, float& z) const; + GPUd() void convUVtoLocal(int32_t roc, float u, float v, float& y, float& z) const; + GPUd() void convVtoLocal(int32_t roc, float v, float& z) const; /// convert Local-> UV c.s. - GPUd() void convLocalToUV(int32_t slice, float y, float z, float& u, float& v) const; + GPUd() void convLocalToUV(int32_t roc, float y, float z, float& u, float& v) const; /// convert UV -> Scaled UV - GPUd() void convUVtoScaledUV(int32_t slice, int32_t row, float u, float v, float& su, float& sv) const; + GPUd() void convUVtoScaledUV(int32_t roc, int32_t row, float u, float v, float& su, float& sv) const; /// convert Scaled UV -> UV - GPUd() void convScaledUVtoUV(int32_t slice, int32_t row, float su, float sv, float& u, float& v) const; + GPUd() void convScaledUVtoUV(int32_t roc, int32_t row, float su, float sv, float& u, float& v) const; /// convert Scaled UV -> Local c.s. - GPUd() void convScaledUVtoLocal(int32_t slice, int32_t row, float su, float sv, float& ly, float& lz) const; + GPUd() void convScaledUVtoLocal(int32_t roc, int32_t row, float su, float sv, float& ly, float& lz) const; /// convert Pad coordinate -> U GPUd() float convPadToU(int32_t row, float pad) const; @@ -175,7 +176,7 @@ class TPCFastTransformGeo void print() const; /// Method for testing consistency - int32_t test(int32_t slice, int32_t row, float ly, float lz) const; + int32_t test(int32_t roc, int32_t row, float ly, float lz) const; /// Method for testing consistency int32_t test() const; @@ -183,9 +184,9 @@ class TPCFastTransformGeo private: /// _______________ Data members _______________________________________________ - static constexpr int32_t NumberOfSlices = 36; ///< Number of TPC slices ( slice = inner + outer sector ) - static constexpr int32_t NumberOfSlicesA = NumberOfSlices / 2; ///< Number of TPC slices side A - static constexpr int32_t MaxNumberOfRows = 160; ///< Max Number of TPC rows in a slice + static constexpr int32_t NumberOfRocs = 36; ///< Number of TPC rocs ( roc = inner + outer sector ) + static constexpr int32_t NumberOfRocsA = NumberOfRocs / 2; ///< Number of TPC rocs side A + static constexpr int32_t MaxNumberOfRows = 160; ///< Max Number of TPC rows in a roc /// _______________ Construction control _______________________________________________ @@ -211,23 +212,23 @@ class TPCFastTransformGeo float mScaleSVtoVsideA = 0.f; ///< scale for sv->v for TPC side A float mScaleSVtoVsideC = 0.f; ///< scale for sv->v for TPC side C - SliceInfo mSliceInfos[NumberOfSlices + 1]; ///< array of slice information [fixed size] + RocInfo mRocInfos[NumberOfRocs + 1]; ///< array of roc information [fixed size] RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] - ClassDefNV(TPCFastTransformGeo, 1); + ClassDefNV(TPCFastTransformGeo, 2); }; // ======================================================================= // Inline implementations of some methods // ======================================================================= -GPUdi() const TPCFastTransformGeo::SliceInfo& TPCFastTransformGeo::getSliceInfo(int32_t slice) const +GPUdi() const TPCFastTransformGeo::RocInfo& TPCFastTransformGeo::getRocInfo(int32_t roc) const { - /// Gives slice info - if (slice < 0 || slice >= NumberOfSlices) { // return zero object - slice = NumberOfSlices; + /// Gives roc info + if (roc < 0 || roc >= NumberOfRocs) { // return zero object + roc = NumberOfRocs; } - return mSliceInfos[slice]; + return mRocInfos[roc]; } GPUdi() const TPCFastTransformGeo::RowInfo& TPCFastTransformGeo::getRowInfo(int32_t row) const @@ -239,28 +240,28 @@ GPUdi() const TPCFastTransformGeo::RowInfo& TPCFastTransformGeo::getRowInfo(int3 return mRowInfos[row]; } -GPUdi() void TPCFastTransformGeo::convLocalToGlobal(int32_t slice, float lx, float ly, float lz, float& gx, float& gy, float& gz) const +GPUdi() void TPCFastTransformGeo::convLocalToGlobal(int32_t roc, float lx, float ly, float lz, float& gx, float& gy, float& gz) const { /// convert Local -> Global c.s. - const SliceInfo& sliceInfo = getSliceInfo(slice); - gx = lx * sliceInfo.cosAlpha - ly * sliceInfo.sinAlpha; - gy = lx * sliceInfo.sinAlpha + ly * sliceInfo.cosAlpha; + const RocInfo& rocInfo = getRocInfo(roc); + gx = lx * rocInfo.cosAlpha - ly * rocInfo.sinAlpha; + gy = lx * rocInfo.sinAlpha + ly * rocInfo.cosAlpha; gz = lz; } -GPUdi() void TPCFastTransformGeo::convGlobalToLocal(int32_t slice, float gx, float gy, float gz, float& lx, float& ly, float& lz) const +GPUdi() void TPCFastTransformGeo::convGlobalToLocal(int32_t roc, float gx, float gy, float gz, float& lx, float& ly, float& lz) const { /// convert Global -> Local c.s. - const SliceInfo& sliceInfo = getSliceInfo(slice); - lx = gx * sliceInfo.cosAlpha + gy * sliceInfo.sinAlpha; - ly = -gx * sliceInfo.sinAlpha + gy * sliceInfo.cosAlpha; + const RocInfo& rocInfo = getRocInfo(roc); + lx = gx * rocInfo.cosAlpha + gy * rocInfo.sinAlpha; + ly = -gx * rocInfo.sinAlpha + gy * rocInfo.cosAlpha; lz = gz; } -GPUdi() void TPCFastTransformGeo::convVtoLocal(int32_t slice, float v, float& lz) const +GPUdi() void TPCFastTransformGeo::convVtoLocal(int32_t roc, float v, float& lz) const { /// convert UV -> Local c.s. - if (slice < NumberOfSlicesA) { // TPC side A + if (roc < NumberOfRocsA) { // TPC side A lz = mTPCzLengthA - v; } else { // TPC side C lz = v - mTPCzLengthC; // drift direction is mirrored on C-side @@ -268,10 +269,10 @@ GPUdi() void TPCFastTransformGeo::convVtoLocal(int32_t slice, float v, float& lz lz += mTPCalignmentZ; // global TPC alignment } -GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t slice, float u, float v, float& ly, float& lz) const +GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t roc, float u, float v, float& ly, float& lz) const { /// convert UV -> Local c.s. - if (slice < NumberOfSlicesA) { // TPC side A + if (roc < NumberOfRocsA) { // TPC side A ly = u; lz = mTPCzLengthA - v; } else { // TPC side C @@ -281,11 +282,11 @@ GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t slice, float u, float v, lz += mTPCalignmentZ; // global TPC alignment } -GPUdi() void TPCFastTransformGeo::convLocalToUV(int32_t slice, float ly, float lz, float& u, float& v) const +GPUdi() void TPCFastTransformGeo::convLocalToUV(int32_t roc, float ly, float lz, float& u, float& v) const { /// convert Local-> UV c.s. lz = lz - mTPCalignmentZ; // global TPC alignment - if (slice < NumberOfSlicesA) { // TPC side A + if (roc < NumberOfRocsA) { // TPC side A u = ly; v = mTPCzLengthA - lz; } else { // TPC side C @@ -294,36 +295,36 @@ GPUdi() void TPCFastTransformGeo::convLocalToUV(int32_t slice, float ly, float l } } -GPUdi() void TPCFastTransformGeo::convUVtoScaledUV(int32_t slice, int32_t row, float u, float v, float& su, float& sv) const +GPUdi() void TPCFastTransformGeo::convUVtoScaledUV(int32_t roc, int32_t row, float u, float v, float& su, float& sv) const { /// convert UV -> Scaled UV const RowInfo& rowInfo = getRowInfo(row); su = (u - rowInfo.u0) * rowInfo.scaleUtoSU; - if (slice < NumberOfSlicesA) { + if (roc < NumberOfRocsA) { sv = v * mScaleVtoSVsideA; } else { sv = v * mScaleVtoSVsideC; } } -GPUdi() void TPCFastTransformGeo::convScaledUVtoUV(int32_t slice, int32_t row, float su, float sv, float& u, float& v) const +GPUdi() void TPCFastTransformGeo::convScaledUVtoUV(int32_t roc, int32_t row, float su, float sv, float& u, float& v) const { /// convert Scaled UV -> UV const RowInfo& rowInfo = getRowInfo(row); u = rowInfo.u0 + su * rowInfo.scaleSUtoU; - if (slice < NumberOfSlicesA) { + if (roc < NumberOfRocsA) { v = sv * mScaleSVtoVsideA; } else { v = sv * mScaleSVtoVsideC; } } -GPUdi() void TPCFastTransformGeo::convScaledUVtoLocal(int32_t slice, int32_t row, float su, float sv, float& ly, float& lz) const +GPUdi() void TPCFastTransformGeo::convScaledUVtoLocal(int32_t roc, int32_t row, float su, float sv, float& ly, float& lz) const { /// convert Scaled UV -> Local c.s. float u, v; - convScaledUVtoUV(slice, row, su, sv, u, v); - convUVtoLocal(slice, u, v, ly, lz); + convScaledUVtoUV(roc, row, su, sv, u, v); + convUVtoLocal(roc, u, v, ly, lz); } GPUdi() float TPCFastTransformGeo::convPadToU(int32_t row, float pad) const diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx index 7d0aa29545578..aa28b6a414876 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx @@ -87,14 +87,14 @@ int32_t TPCFastTransformManager::create(TPCFastTransform& fastTransform, float tpcZlengthSideA = tpcParam->GetZLength(0); float tpcZlengthSideC = - tpcParam->GetZLength(TPCFastTransformGeo::getNumberOfSlices() / 2); + tpcParam->GetZLength(TPCFastTransformGeo::getNumberOfRocs() / 2); geo.setTPCzLength(tpcZlengthSideA, tpcZlengthSideC); geo.setTPCalignmentZ(-mOrigTransform->GetDeltaZCorrTime()); for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { - int32_t slice = 0, sector = 0, secrow = 0; - AliHLTTPCGeometry::Slice2Sector(slice, row, sector, secrow); + int32_t roc = 0, sector = 0, secrow = 0; + AliHLTTPCGeometry::Slice2Sector(roc, row, sector, secrow); Int_t nPads = tpcParam->GetNPads(sector, secrow); float xRow = tpcParam->GetPadRowRadii(sector, secrow); float padWidth = tpcParam->GetInnerPadPitchWidth(); @@ -272,40 +272,40 @@ int32_t TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransfo recoParam->SetUseTOFCorrection(kFALSE); - for (int32_t slice = 0; slice < geo.getNumberOfSlices(); slice++) { + for (int32_t roc = 0; roc < geo.getNumberOfRocs(); roc++) { for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { const TPCFastTransformGeo::RowInfo& rowInfo = geo.getRowInfo(row); - const TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(slice, row); - float* data = correction.getSplineData(slice, row); + const TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(roc, row); + float* data = correction.getSplineData(roc, row); Spline2DHelper helper; helper.setSpline(spline, 4, 4); auto F = [&](double su, double sv, double dxuv[3]) { float x = rowInfo.x; - // x, u, v cordinates of the knot (local cartesian coord. of slice + // x, u, v cordinates of the knot (local cartesian coord. of roc // towards central electrode ) float u = 0, v = 0; - geo.convScaledUVtoUV(slice, row, su, sv, u, v); + geo.convScaledUVtoUV(roc, row, su, sv, u, v); // row, pad, time coordinates of the knot float vertexTime = 0.f; float pad = 0.f, time = 0.f; - fastTransform.convUVtoPadTime(slice, row, u, v, pad, time, vertexTime); + fastTransform.convUVtoPadTime(roc, row, u, v, pad, time, vertexTime); // nominal x,y,z coordinates of the knot (without corrections and // time-of-flight correction) float y = 0, z = 0; - geo.convUVtoLocal(slice, u, v, y, z); + geo.convUVtoLocal(roc, u, v, y, z); // original TPC transformation (row,pad,time) -> (x,y,z) without // time-of-flight correction float ox = 0, oy = 0, oz = 0; { int32_t sector = 0, secrow = 0; - AliHLTTPCGeometry::Slice2Sector(slice, row, sector, secrow); + AliHLTTPCGeometry::Slice2Sector(roc, row, sector, secrow); int32_t is[] = {sector}; double xx[] = {static_cast(secrow), pad, time}; mOrigTransform->Transform(xx, is, 0, 1); @@ -315,7 +315,7 @@ int32_t TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransfo } // convert to u,v float ou = 0, ov = 0; - geo.convLocalToUV(slice, oy, oz, ou, ov); + geo.convLocalToUV(roc, oy, oz, ou, ov); // corrections in x,u,v: dxuv[0] = ox - x; @@ -325,7 +325,7 @@ int32_t TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransfo helper.approximateFunction(data, 0., 1., 0., 1., F); } // row - } // slice + } // roc // set back the time-of-flight correction; diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index 4421d44aab0c8..7c1ae8fd56800 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -59,7 +59,7 @@ #pragma link C++ class o2::gpu::IrregularSpline2D3DCalibrator + ; #pragma link C++ class o2::gpu::TPCFastTransformGeo + ; -#pragma link C++ class o2::gpu::TPCFastTransformGeo::SliceInfo + ; +#pragma link C++ class o2::gpu::TPCFastTransformGeo::RocInfo + ; #pragma link C++ class o2::gpu::TPCFastTransformGeo::RowInfo + ; #pragma link C++ class o2::gpu::TPCFastTransform + ; @@ -68,9 +68,9 @@ #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RowInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SliceInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RocInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RowActiveArea + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SliceRowInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RocRowInfo + ; #pragma link C++ class o2::gpu::CorrectionMapsHelper + ; #pragma link C++ struct o2::gpu::MultivariatePolynomialContainer + ; diff --git a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C index 67a0f09522f60..69b7909cda683 100644 --- a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C +++ b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C @@ -82,12 +82,12 @@ void generateTPCCorrectionNTuple(const char* path = "InputSCDensityHistograms.ro const o2::gpu::TPCFastTransformGeo& geo = fastTransform->getGeometry(); TFile* f = new TFile("tpcCorrection.root", "RECREATE"); - TNtuple* nt = new TNtuple("dist", "dist", "slice:row:su:sv:dx:du:dv"); + TNtuple* nt = new TNtuple("dist", "dist", "sector:row:su:sv:dx:du:dv"); - int32_t nSlices = 1; // fastTransform->getNumberOfSlices(); - // for( int32_t slice=0; slicegetNumberOfSectors(); + // for( int32_t sector=0; sectorFill(slice, row, su, sv, dx, du, dv); + std::cout << sector << " " << row << " " << su << " " << sv << " " << dx << " " << du << " " << dv << std::endl; + nt->Fill(sector, row, su, sv, dx, du, dv); } } } From d75e375f8d02a9991868f8e91a70778888d8f6e7 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 5 Feb 2025 16:19:23 +0000 Subject: [PATCH 12/26] TPC Splines: minimise the amount of transformations --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 20 +- .../src/TPCFastTransformHelperO2.cxx | 25 +- .../test/testTPCFastTransform.cxx | 6 +- .../TPCFastSpaceChargeCorrection.cxx | 16 +- .../TPCFastSpaceChargeCorrection.h | 52 ++- .../TPCFastTransform.cxx | 16 +- GPU/TPCFastTransformation/TPCFastTransform.h | 413 +++++++----------- .../TPCFastTransformGeo.cxx | 71 +-- .../TPCFastTransformGeo.h | 116 +---- .../TPCFastTransformManager.cxx | 1 + 10 files changed, 262 insertions(+), 474 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index bac332a837c55..710a4356dd457 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -63,12 +63,8 @@ void TPCFastSpaceChargeCorrectionHelper::initGeometry() mGeo.startConstruction(nRows); auto& detParam = ParameterDetector::Instance(); - float tpcZlengthSideA = detParam.TPClength; - float tpcZlengthSideC = detParam.TPClength; - mGeo.setTPCzLength(tpcZlengthSideA, tpcZlengthSideC); - - mGeo.setTPCalignmentZ(0.); + mGeo.setTPCzLength(detParam.TPClength); for (int iRow = 0; iRow < mGeo.getNumberOfRows(); iRow++) { Sector sector = 0; @@ -295,7 +291,7 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper auto myThread = [&](int iThread) { for (int iRow = iThread; iRow < nRows; iRow += mNthreads) { const auto& info = mGeo.getRowInfo(iRow); - double vMax = mGeo.getTPCzLength(iRoc); + double vMax = mGeo.getTPCzLength(); double dv = vMax / (6. * (nKnotsZ - 1)); double dpad = info.maxPad / (6. * (nKnotsY - 1)); @@ -512,8 +508,8 @@ std::unique_ptr TPCFastSpaceChargeCorrect double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); double uMin = yMin; double uMax = yMax; - double vMin = geo.getTPCzLength(iRoc) - zMax; - double vMax = geo.getTPCzLength(iRoc) - zMin; + double vMin = geo.getTPCzLength() - zMax; + double vMax = geo.getTPCzLength() - zMin; info.gridU0 = uMin; info.scaleUtoGrid = spline.getGridX1().getUmax() / (uMax - uMin); info.gridV0 = vMin; @@ -822,7 +818,7 @@ void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpac if (prn) { LOG(info) << "init MaxDriftLength for roc " << roc; } - double vLength = (roc < mGeo.getNumberOfRocsA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); + double vLength = mGeo.getTPCzLength(); TPCFastSpaceChargeCorrection::RocInfo& rocInfo = correction.getRocInfo(roc); rocInfo.vMax = 0.f; @@ -843,7 +839,7 @@ void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpac while (v1 - v0 > 0.1) { float v = 0.5 * (v0 + v1); float dx, du, dv; - correction.getCorrection(roc, row, u, v, dx, du, dv); + correction.getCorrectionInternal(roc, row, u, v, dx, du, dv); double cx = x + dx; double cu = u + du; double cv = v + dv; @@ -962,14 +958,14 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vectorgetCorrection(roc, row, u, v, dxTmp, duTmp, dvTmp); + corrections[i]->getCorrectionInternal(roc, row, u, v, dxTmp, duTmp, dvTmp); dx += dxTmp * scaling[i]; du += duTmp * scaling[i]; dv += dvTmp * scaling[i]; diff --git a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx index cfa54a12f9f42..c83ee6d0cfa19 100644 --- a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx +++ b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx @@ -56,12 +56,7 @@ void TPCFastTransformHelperO2::init() mGeo.startConstruction(nRows); auto& detParam = ParameterDetector::Instance(); - float tpcZlengthSideA = detParam.TPClength; - float tpcZlengthSideC = detParam.TPClength; - - mGeo.setTPCzLength(tpcZlengthSideA, tpcZlengthSideC); - - mGeo.setTPCalignmentZ(0.); + mGeo.setTPCzLength(detParam.TPClength); for (int iRow = 0; iRow < mGeo.getNumberOfRows(); iRow++) { Sector sector = 0; @@ -114,12 +109,8 @@ std::unique_ptr TPCFastTransformHelperO2::create(Long_t TimeSt // set some initial calibration values, will be reinitialised later int updateCalibration() const float t0 = 0.; const float vDrift = 0.f; - const float vdCorrY = 0.; - const float ldCorr = 0.; - const float tofCorr = 0.; - const float primVtxZ = 0.; const long int initTimeStamp = -1; - fastTransform.setCalibration(initTimeStamp, t0, vDrift, vdCorrY, ldCorr, tofCorr, primVtxZ); + fastTransform.setCalibration1(initTimeStamp, t0, vDrift); fastTransform.finishConstruction(); } @@ -171,19 +162,13 @@ int TPCFastTransformHelperO2::updateCalibration(TPCFastTransform& fastTransform, const double vDrift = elParam.ZbinWidth * vDriftRef * vDriftFactor; // cm/timebin // fast transform formula: - // L = (t-t0)*(mVdrift + mVdriftCorrY*yLab ) + mLdriftCorr - // Z = Z(L) + tpcAlignmentZ + // L = (t-t0)*mVdrift + // Z = Z(L) // spline corrections for xyz - // Time-of-flight correction: ldrift += dist-to-vtx*tofCorr const double t0 = (driftTimeOffset + elParam.getAverageShapingTime()) / elParam.ZbinWidth; - const double vdCorrY = 0.; - const double ldCorr = 0.; - const double tofCorr = 0.; - const double primVtxZ = 0.; - - fastTransform.setCalibration(TimeStamp, t0, vDrift, vdCorrY, ldCorr, tofCorr, primVtxZ); + fastTransform.setCalibration1(TimeStamp, t0, vDrift); return 0; } diff --git a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx index 0141b80819b64..53cfe08f3a7f4 100644 --- a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(FastTransform_test1) const GlobalPadNumber p = mapper.globalPadNumber(PadPos(row, pad)); const PadCentre& c = mapper.padCentre(p); float u = 0, v = 0; - fastTransform.convPadTimeToUV(0, row, pad, 0, u, v, 0.); + fastTransform.convPadTimeToUV(row, pad, 0, u, v, 0.); double dx = x - c.X(); double dy = u - (-c.Y()); // diferent sign convention for Y coordinate in the map @@ -192,8 +192,8 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) correctionUV(roc, row, u0, v0, dx, du, dv); statDiff += fabs((x1 - x0) - dx) + fabs((u1 - u0) - du) + fabs((v1 - v0) - dv); statN += 3; - //std::cout << (x1 - x0) - dx << " " << (u1 - u0) - du << " " << (v1 - v0) - dv << std::endl; //": v0 " << v0 <<" z0 "<Transform(roc, row, pad, time, x1f, y1f, z1f); diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 5d3c186a06d42..111e70072c58e 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -225,7 +225,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); info.gridV0 = infoOld.gridV0; - info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength(roc) + 3. - info.gridV0); + info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength() + 3. - info.gridV0); info.gridCorrU0 = infoOld.gridCorrU0; info.scaleCorrUtoGrid = infoOld.scaleCorrUtoGrid; @@ -440,7 +440,7 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() { // initialise all corrections to 0. for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { - double vLength = (roc < mGeo.getNumberOfRocsA()) ? mGeo.getTPCzLengthA() : mGeo.getTPCzLengthC(); + double vLength = mGeo.getTPCzLength(); RocInfo& rocInfo = getRocInfo(roc); rocInfo.vMax = vLength; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { @@ -548,12 +548,14 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) if (prn) { LOG(info) << "check inverse transform for roc " << roc; } - double vLength = mGeo.getTPCzLength(roc); + double vLength = mGeo.getTPCzLength(); MaxValue maxDroc[3]; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - float u0, u1, v0, v1; - mGeo.convScaledUVtoUV(roc, row, 0., 0., u0, v0); - mGeo.convScaledUVtoUV(roc, row, 1., 1., u1, v1); + float u0 = mGeo.getRowInfo(row).getUmin(); + float u1 = mGeo.getRowInfo(row).getUmax(); + float v0 = 0.; + float v1 = vLength; + double x = mGeo.getRowInfo(row).x; double stepU = (u1 - u0) / 100.; double stepV = (v1 - v0) / 100.; @@ -564,7 +566,7 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) continue; } float dx, du, dv; - getCorrection(roc, row, u, v, dx, du, dv); + getCorrectionInternal(roc, row, u, v, dx, du, dv); double cx = x + dx; double cu = u + du; double cv = v + dv; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index b6244bfee1e0f..fa5cf7a1736bd 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -180,7 +180,9 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// _______________ The main method: cluster correction _______________________ /// - GPUd() int32_t getCorrection(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; + GPUd() int32_t getCorrectionInternal(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; + + GPUdi() std::tuple getCorrectionLocal(int32_t roc, int32_t row, float y, float z) const; /// inverse correction: Corrected U and V -> coorrected X GPUd() void getCorrectionInvCorrectedX(int32_t roc, int32_t row, float corrU, float corrV, float& corrX) const; @@ -199,6 +201,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// _______________ Utilities _______________________________________________ + /// convert local y, z to internal grid coordinates u,v + /// return values: u, v, scaling factor + GPUd() std::tuple convLocalToGrid(int32_t roc, int32_t row, float y, float z) const; + /// convert u,v to internal grid coordinates GPUd() void convUVtoGrid(int32_t roc, int32_t row, float u, float v, float& gridU, float& gridV) const; @@ -259,9 +265,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// release temporary memory used during construction void releaseConstructionMemory(); - /// temporary method with the an way of calculating 2D spline - GPUd() int32_t getCorrectionOld(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; - /// _______________ Data members _______________________________________________ /// _______________ Construction control _______________________________________________ @@ -354,7 +357,7 @@ GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t roc, in gridV = (corrV - info.gridCorrV0) * info.scaleCorrVtoGrid; } -GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const +GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionInternal(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const { const auto& info = getRocRowInfo(roc, row); const SplineType& spline = getSpline(roc, row); @@ -382,26 +385,41 @@ GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrection(int32_t roc, int32_t return 0; } -GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionOld(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t roc, int32_t row, float y, float z) const { + const auto& info = getRocRowInfo(roc, row); const SplineType& spline = getSpline(roc, row); const float* splineData = getSplineData(roc, row); + + float u, v; + + mGeo.convLocalToUV(roc, y, z, u, v); + float gridU = 0, gridV = 0; convUVtoGrid(roc, row, u, v, gridU, gridV); + // shrink to the grid area + gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); + gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); + float dxuv[3]; - spline.interpolateUold(splineData, gridU, gridV, dxuv); - const auto& info = getRocRowInfo(roc, row); + spline.interpolateU(splineData, gridU, gridV, dxuv); + float s = v / info.gridV0; - if (s < 0.) { - s = 0.; - } - if (s > 1.) { - s = 1.; + + if (v >= info.gridV0) { + s = 1.f; + } else if (v <= 0.f) { + s = 0.f; } - dx = GPUCommonMath::Max(info.minCorr[0], GPUCommonMath::Min(info.maxCorr[0], s * dxuv[0])); - du = GPUCommonMath::Max(info.minCorr[1], GPUCommonMath::Min(info.maxCorr[1], s * dxuv[1])); - dv = GPUCommonMath::Max(info.minCorr[2], GPUCommonMath::Min(info.maxCorr[2], s * dxuv[2])); - return 0; + + float dx = GPUCommonMath::Clamp(s * dxuv[0], info.minCorr[0], info.maxCorr[0]); + float du = GPUCommonMath::Clamp(s * dxuv[1], info.minCorr[1], info.maxCorr[1]); + float dv = GPUCommonMath::Clamp(s * dxuv[2], info.minCorr[2], info.maxCorr[2]); + + float dy, dz; + mGeo.convUVtoLocal(roc, du, dv, dy, dz); + + return {dx, dy, dz}; } GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( diff --git a/GPU/TPCFastTransformation/TPCFastTransform.cxx b/GPU/TPCFastTransformation/TPCFastTransform.cxx index bd29a760615ad..625f70c1710a1 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransform.cxx @@ -37,7 +37,7 @@ using namespace o2::gpu; TPCFastTransform::TPCFastTransform() - : FlatObject(), mTimeStamp(0), mCorrection(), mApplyCorrection(1), mT0(0.f), mVdrift(0.f), mVdriftCorrY(0.f), mLdriftCorr(0.f), mTOFcorr(0.f), mPrimVtxZ(0.f), mLumi(TPCFastTransform::DEFLUMI), mLumiError(0.f), mLumiScaleFactor(1.0f), mIDC(TPCFastTransform::DEFIDC), mIDCError(0.f), mCTP2IDCFallBackThreshold(30.f) + : FlatObject(), mTimeStamp(0), mCorrection(), mApplyCorrection(1), mT0(0.f), mVdrift(0.f), mLumi(TPCFastTransform::DEFLUMI), mLumiError(0.f), mLumiScaleFactor(1.0f), mIDC(TPCFastTransform::DEFIDC), mIDCError(0.f), mCTP2IDCFallBackThreshold(30.f) { // Default Constructor: creates an empty uninitialized object } @@ -54,10 +54,6 @@ void TPCFastTransform::cloneFromObject(const TPCFastTransform& obj, char* newFla mApplyCorrection = obj.mApplyCorrection; mT0 = obj.mT0; mVdrift = obj.mVdrift; - mVdriftCorrY = obj.mVdriftCorrY; - mLdriftCorr = obj.mLdriftCorr; - mTOFcorr = obj.mTOFcorr; - mPrimVtxZ = obj.mPrimVtxZ; mLumi = obj.mLumi; mLumiError = obj.mLumiError; mIDC = obj.mIDC; @@ -123,7 +119,7 @@ void TPCFastTransform::startConstruction(const TPCFastSpaceChargeCorrection& cor mCorrection.cloneFromObject(correction, nullptr); } -void TPCFastTransform::setCalibration(int64_t timeStamp, float t0, float vDrift, float vDriftCorrY, float lDriftCorr, float tofCorr, float primVtxZ) +void TPCFastTransform::setCalibration1(int64_t timeStamp, float t0, float vDrift) { /// Sets all drift calibration parameters and the time stamp /// @@ -133,10 +129,6 @@ void TPCFastTransform::setCalibration(int64_t timeStamp, float t0, float vDrift, mTimeStamp = timeStamp; mT0 = t0; mVdrift = vDrift; - mVdriftCorrY = vDriftCorrY; - mLdriftCorr = lDriftCorr; - mTOFcorr = tofCorr; - mPrimVtxZ = primVtxZ; mConstructionMask |= ConstructionExtraState::CalibrationIsSet; } @@ -160,10 +152,6 @@ void TPCFastTransform::print() const LOG(info) << "mApplyCorrection = " << mApplyCorrection; LOG(info) << "mT0 = " << mT0; LOG(info) << "mVdrift = " << mVdrift; - LOG(info) << "mVdriftCorrY = " << mVdriftCorrY; - LOG(info) << "mLdriftCorr = " << mLdriftCorr; - LOG(info) << "mTOFcorr = " << mTOFcorr; - LOG(info) << "mPrimVtxZ = " << mPrimVtxZ; LOG(info) << "mLumi = " << mLumi; LOG(info) << "mLumiError = " << mLumiError; LOG(info) << "mIDC = " << mIDC; diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 8aef1748ebf62..1ecd577eb7dac 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -159,7 +159,7 @@ class TPCFastTransform : public FlatObject /// /// It must be called once during construction, /// but also may be called afterwards to reset these parameters. - void setCalibration(int64_t timeStamp, float t0, float vDrift, float vDriftCorrY, float lDriftCorr, float tofCorr, float primVtxZ); + void setCalibration1(int64_t timeStamp, float t0, float vDrift); /// Set Lumi info void setLumi(float l) { mLumi = l; } @@ -183,7 +183,7 @@ class TPCFastTransform : public FlatObject /// _______________ The main method: cluster transformation _______________________ /// /// Transforms raw TPC coordinates to local XYZ withing a roc - /// taking calibration + alignment into account. + /// taking calibration into account. /// GPUd() void Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; GPUd() void TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; @@ -209,12 +209,12 @@ class TPCFastTransform : public FlatObject GPUd() void TransformIdeal(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; GPUd() void TransformIdealZ(int32_t roc, float time, float& z, float vertexTime) const; - GPUd() void convPadTimeToUV(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const; - GPUd() void convPadTimeToUVinTimeFrame(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const; - GPUd() void convTimeToVinTimeFrame(int32_t roc, float time, float& v, float maxTimeBin) const; + GPUd() void convPadTimeToUV(int32_t row, float pad, float time, float& u, float& v, float vertexTime) const; + GPUd() void convPadTimeToUVinTimeFrame(int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const; + GPUd() void convTimeToVinTimeFrame(float time, float& v, float maxTimeBin) const; - GPUd() void convUVtoPadTime(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const; - GPUd() void convUVtoPadTimeInTimeFrame(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const; + GPUd() void convUVtoPadTime(int32_t row, float u, float v, float& pad, float& time, float vertexTime) const; + GPUd() void convUVtoPadTimeInTimeFrame(int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const; GPUd() void convVtoTime(float v, float& time, float vertexTime) const; GPUd() float convTimeToZinTimeFrame(int32_t roc, float time, float maxTimeBin) const; @@ -222,10 +222,8 @@ class TPCFastTransform : public FlatObject GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const; GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t roc, float deltaZ) const; GPUd() float convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const; - GPUd() float convZOffsetToVertexTime(int32_t roc, float zOffset, float maxTimeBin) const; - GPUd() float convVertexTimeToZOffset(int32_t roc, float vertexTime, float maxTimeBin) const; - - GPUd() void getTOFcorrection(int32_t roc, int32_t row, float x, float y, float z, float& dz) const; + GPUd() float convZOffsetToVertexTime(int32_t sector, float zOffset, float maxTimeBin) const; + GPUd() float convVertexTimeToZOffset(int32_t sector, float vertexTime, float maxTimeBin) const; void setApplyCorrectionOn() { mApplyCorrection = 1; } void setApplyCorrectionOff() { mApplyCorrection = 0; } @@ -245,15 +243,6 @@ class TPCFastTransform : public FlatObject /// Return T0 in time bin units GPUd() float getT0() const { return mT0; } - /// Return VdriftCorrY in time_bin / cn - GPUd() float getVdriftCorrY() const { return mVdriftCorrY; } - - /// Return LdriftCorr offset in cm - GPUd() float getLdriftCorr() const { return mLdriftCorr; } - - /// Return TOF correction (vdrift / C) - GPUd() float getTOFCorr() const { return mLdriftCorr; } - /// Return map lumi GPUd() float getLumi() const { return mLumi; } @@ -330,23 +319,10 @@ class TPCFastTransform : public FlatObject /// /// t = (float) time bin, y = global y /// - /// L(t,y) = (t-mT0)*(mVdrift + mVdriftCorrY*y ) + mLdriftCorr ____ + /// L(t,y) = (t-mT0)*mVdrift ____ /// - float mT0; ///< T0 in [time bin] - float mVdrift; ///< VDrift in [cm/time bin] - float mVdriftCorrY; ///< VDrift correction for global Y[cm] in [1/time bin] - float mLdriftCorr; ///< drift length correction in [cm] - - /// A coefficient for Time-Of-Flight correction: drift length -= EstimatedDistanceToVtx[cm]*mTOFcorr - /// - /// Since this correction requires a knowledge of the spatial position, it is appied after mCorrection, - /// not on the drift length but directly on V coordinate. - /// - /// mTOFcorr == mVdrift/(speed of light) - /// - float mTOFcorr; - - float mPrimVtxZ; ///< Z of the primary vertex, needed for the Time-Of-Flight correction + float mT0; ///< T0 in [time bin] + float mVdrift; ///< VDrift in [cm/time bin] float mLumi; ///< luminosity estimator float mLumiError; ///< error on luminosity @@ -359,7 +335,7 @@ class TPCFastTransform : public FlatObject /// Correction of (x,u,v) with tricubic interpolator on a regular grid TPCSlowSpaceChargeCorrection* mCorrectionSlow{nullptr}; ///< reference space charge corrections - GPUd() void TransformInternal(int32_t roc, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; + GPUd() void TransformLocal(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; ClassDefNV(TPCFastTransform, 4); }; @@ -368,248 +344,195 @@ class TPCFastTransform : public FlatObject // Inline implementations of some methods // ======================================================================= -GPUdi() void TPCFastTransform::convPadTimeToUV(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float vertexTime) const +GPUdi() void TPCFastTransform::convPadTimeToUV(int32_t row, float pad, float time, float& u, float& v, float vertexTime) const { - bool sideC = (roc >= getGeometry().getNumberOfRocsA()); - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); - float x = rowInfo.x; u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - - float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; - - v = (time - mT0 - vertexTime) * (mVdrift + mVdriftCorrY * yLab) + mLdriftCorr; // drift length cm + v = (time - mT0 - vertexTime) * (mVdrift); // drift length cm } -GPUdi() void TPCFastTransform::convTimeToVinTimeFrame(int32_t roc, float time, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convTimeToVinTimeFrame(float time, float& v, float maxTimeBin) const { - v = (time - mT0 - maxTimeBin) * mVdrift + mLdriftCorr; // drift length cm - if (roc < getGeometry().getNumberOfRocsA()) { - v += getGeometry().getTPCzLengthA(); - } else { - v += getGeometry().getTPCzLengthC(); - } + v = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm + v += getGeometry().getTPCzLength(); } -GPUdi() void TPCFastTransform::convPadTimeToUVinTimeFrame(int32_t roc, int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convPadTimeToUVinTimeFrame(int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const { const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - convTimeToVinTimeFrame(roc, time, v, maxTimeBin); + convTimeToVinTimeFrame(time, v, maxTimeBin); } -GPUdi() float TPCFastTransform::convZOffsetToVertexTime(int32_t roc, float zOffset, float maxTimeBin) const +GPUdi() float TPCFastTransform::convZOffsetToVertexTime(int32_t sector, float zOffset, float maxTimeBin) const { - if (roc < getGeometry().getNumberOfRocsA()) { - return maxTimeBin - (getGeometry().getTPCzLengthA() + zOffset) / mVdrift; + if (sector < getGeometry().getNumberOfSectorsA()) { + return maxTimeBin - (getGeometry().getTPCzLength() + zOffset) / mVdrift; } else { - return maxTimeBin - (getGeometry().getTPCzLengthC() - zOffset) / mVdrift; + return maxTimeBin - (getGeometry().getTPCzLength() - zOffset) / mVdrift; } } -GPUdi() float TPCFastTransform::convVertexTimeToZOffset(int32_t roc, float vertexTime, float maxTimeBin) const +GPUdi() float TPCFastTransform::convVertexTimeToZOffset(int32_t sector, float vertexTime, float maxTimeBin) const { - if (roc < getGeometry().getNumberOfRocsA()) { - return (maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLengthA(); + if (sector < getGeometry().getNumberOfSectorsA()) { + return (maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLength(); } else { - return -((maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLengthC()); + return -((maxTimeBin - vertexTime) * mVdrift - getGeometry().getTPCzLength()); } } -GPUdi() void TPCFastTransform::convUVtoPadTime(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float vertexTime) const +GPUdi() void TPCFastTransform::convUVtoPadTime(int32_t row, float u, float v, float& pad, float& time, float vertexTime) const { - bool sideC = (roc >= getGeometry().getNumberOfRocsA()); - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); - pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; - - float x = rowInfo.x; - float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; - time = mT0 + vertexTime + (v - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); + time = mT0 + vertexTime + v / mVdrift; } GPUdi() void TPCFastTransform::convVtoTime(float v, float& time, float vertexTime) const { - float yLab = 0.f; - time = mT0 + vertexTime + (v - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); + time = mT0 + vertexTime + v / mVdrift; } -GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t roc, int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const +GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const { - if (roc < getGeometry().getNumberOfRocsA()) { - v -= getGeometry().getTPCzLengthA(); - } else { - v -= getGeometry().getTPCzLengthC(); - } + v -= getGeometry().getTPCzLength(); const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; - time = mT0 + maxTimeBin + (v - mLdriftCorr) / mVdrift; + time = mT0 + maxTimeBin + v / mVdrift; } -GPUdi() void TPCFastTransform::getTOFcorrection(int32_t roc, int32_t /*row*/, float x, float y, float z, float& dz) const +GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { - // calculate time of flight correction for z coordinate + GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); - bool sideC = (roc >= getGeometry().getNumberOfRocsA()); - float distZ = z - mPrimVtxZ; - float dv = -GPUCommonMath::Sqrt(x * x + y * y + distZ * distZ) * mTOFcorr; - dz = sideC ? dv : -dv; -} + if (!mApplyCorrection) { + return; + } -GPUdi() void TPCFastTransform::TransformInternal(int32_t roc, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const -{ - GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); - if (mApplyCorrection) { - float dx = 0.f, du = 0.f, dv = 0.f; - if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { + float dx = 0.f, dy = 0.f, dz = 0.f; + + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { #ifndef GPUCA_GPUCODE - if (mCorrectionSlow) { - float ly, lz; - getGeometry().convUVtoLocal(roc, u, v, ly, lz); - float gx, gy, gz; - getGeometry().convLocalToGlobal(roc, x, ly, lz, gx, gy, gz); - - float gdxC, gdyC, gdzC; - mCorrectionSlow->getCorrections(gx, gy, gz, roc, gdxC, gdyC, gdzC); - getGeometry().convGlobalToLocal(roc, gdxC, gdyC, gdzC, dx, du, dv); - - if (roc >= 18) { - du = -du; // mirror for c-Side - } else { - dv = -dv; // mirror z for A-Side - } - } else + if (mCorrectionSlow) { + float gx, gy, gz; + getGeometry().convLocalToGlobal(roc, x, y, z, gx, gy, gz); + float gdxC, gdyC, gdzC; + mCorrectionSlow->getCorrections(gx, gy, gz, roc, gdxC, gdyC, gdzC); + getGeometry().convGlobalToLocal(roc, gdxC, gdyC, gdzC, dx, dy, dz); + } else #endif // GPUCA_GPUCODE - { - mCorrection.getCorrection(roc, row, u, v, dx, du, dv); - if (ref) { - if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested - float dxRef, duRef, dvRef; - ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); - dx = (dx - dxRef) * scale + dxRef; - du = (du - duRef) * scale + duRef; - dv = (dv - dvRef) * scale + dvRef; - } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { - float dxRef, duRef, dvRef; - ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); - dx = dxRef * scale + dx; - du = duRef * scale + du; - dv = dvRef * scale + dv; - } - } - if (ref2 && (scale2 != 0)) { - float dxRef, duRef, dvRef; - ref2->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); - dx = dxRef * scale2 + dx; - du = duRef * scale2 + du; - dv = dvRef * scale2 + dv; + { + std::tie(dx, dy, dz) = mCorrection.getCorrectionLocal(roc, row, y, z); + if (ref) { + if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested + auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + dx = (dx - dxRef) * scale + dxRef; + dy = (dy - dyRef) * scale + dyRef; + dz = (dz - dzRef) * scale + dzRef; + } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { + auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + dx = dxRef * scale + dx; + dy = dyRef * scale + dy; + dz = dzRef * scale + dz; } } + if (ref2 && (scale2 != 0)) { + auto [dxRef, dyRef, dzRef] = ref2->mCorrection.getCorrectionLocal(roc, row, y, z); + dx = dxRef * scale2 + dx; + dy = dyRef * scale2 + dy; + dz = dzRef * scale2 + dz; + } } - GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { - float ly, lz; - getGeometry().convUVtoLocal(roc, u, v, ly, lz); + } - float gx, gy, gz; - getGeometry().convLocalToGlobal(roc, x, ly, lz, gx, gy, gz); + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + float lx = x, ly = y, lz = z; - float lyT, lzT; - float uCorr = u + du; - float vCorr = v + dv; - float lxT = x + dx; - getGeometry().convUVtoLocal(roc, uCorr, vCorr, lyT, lzT); + float gx, gy, gz; + getGeometry().convLocalToGlobal(roc, lx, ly, lz, gx, gy, gz); - float invYZtoXScaled; - InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); + float lxT = lx + dx; + float lyT = ly + dy; + float lzT = lz + dz; - float invYZtoX; - InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoX); + float invYZtoXScaled; + InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); - float YZtoNominalY; - float YZtoNominalZ; - InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); + float invYZtoX; + InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoX); - float YZtoNominalYScaled; - float YZtoNominalZScaled; - InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); + float YZtoNominalY; + float YZtoNominalZ; + InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); - float dxRef, duRef, dvRef; - if (ref) { - ref->mCorrection.getCorrection(roc, row, u, v, dxRef, duRef, dvRef); - } + float YZtoNominalYScaled; + float YZtoNominalZScaled; + InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); - float dxRef2, duRef2, dvRef2; - if (ref2) { - ref2->mCorrection.getCorrection(roc, row, u, v, dxRef2, duRef2, dvRef2); - } + float dxRef = 0.f, dyRef = 0.f, dzRef = 0.f; + if (ref) { + std::tie(dxRef, dyRef, dzRef) = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + } - float dxOrig, duOrig, dvOrig; - mCorrection.getCorrection(roc, row, u, v, dxOrig, duOrig, dvOrig); - - o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() - // corrections in x, u, v - << "dxOrig=" << dxOrig - << "duOrig=" << duOrig - << "dvOrig=" << dvOrig - << "dxRef=" << dxRef - << "duRef=" << duRef - << "dvRef=" << dvRef - << "dxRef2=" << dxRef2 - << "duRef2=" << duRef2 - << "dvRef2=" << dvRef2 - << "dx=" << dx - << "du=" << du - << "dv=" << dv - << "v=" << v - << "u=" << u - << "row=" << row - << "roc=" << roc - << "scale=" << scale - << "scale2=" << scale2 - // original local coordinates - << "ly=" << ly - << "lz=" << lz - << "lx=" << x - // corrected local coordinated - << "lxT=" << lxT - << "lyT=" << lyT - << "lzT=" << lzT - // global uncorrected coordinates - << "gx=" << gx - << "gy=" << gy - << "gz=" << gz - // some transformations which are applied - << "invYZtoX=" << invYZtoX - << "invYZtoXScaled=" << invYZtoXScaled - << "YZtoNominalY=" << YZtoNominalY - << "YZtoNominalYScaled=" << YZtoNominalYScaled - << "YZtoNominalZ=" << YZtoNominalZ - << "YZtoNominalZScaled=" << YZtoNominalZScaled - << "scaleMode=" << scaleMode - << "\n"; - }) - - x += dx; - u += du; - v += dv; - } + float dxRef2 = 0.f, duRef2 = 0.f, dvRef2 = 0.f; + if (ref2) { + std::tie(dxRef2, duRef2, dvRef2) = ref2->mCorrection.getCorrectionLocal(roc, row, y, z); + } + + auto [dxOrig, dyOrig, dzOrig] = mCorrection.getCorrectionLocal(roc, row, y, z); + + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() + // corrections in x, u, v + << "dxOrig=" << dxOrig + << "dyOrig=" << dyOrig + << "dzOrig=" << dzOrig + << "dxRef=" << dxRef + << "dyRef=" << dyRef + << "dzRef=" << dzRef + << "dxRef2=" << dxRef2 + << "dyRef2=" << dyRef2 + << "dzRef2=" << dzRef2 + << "dx=" << dx + << "dy=" << dy + << "dz=" << dz + << "row=" << row + << "roc=" << roc + << "scale=" << scale + << "scale2=" << scale2 + // original local coordinates + << "ly=" << ly + << "lz=" << lz + << "lx=" << lx + // corrected local coordinated + << "lxT=" << lxT + << "lyT=" << lyT + << "lzT=" << lzT + // global uncorrected coordinates + << "gx=" << gx + << "gy=" << gy + << "gz=" << gz + // some transformations which are applied + << "invYZtoX=" << invYZtoX + << "invYZtoXScaled=" << invYZtoXScaled + << "YZtoNominalY=" << YZtoNominalY + << "YZtoNominalYScaled=" << YZtoNominalYScaled + << "YZtoNominalZ=" << YZtoNominalZ + << "YZtoNominalZScaled=" << YZtoNominalZScaled + << "scaleMode=" << scaleMode + << "\n"; + }) + + x += dx; + y += dy; + z += dz; } GPUdi() void TPCFastTransform::TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { - float u, v; - getGeometry().convLocalToUV(roc, y, z, u, v); - TransformInternal(roc, row, u, v, x, ref, ref2, scale, scale2, scaleMode); - getGeometry().convUVtoLocal(roc, u, v, y, z); - float dzTOF = 0; - getTOFcorrection(roc, row, x, y, z, dzTOF); - z += dzTOF; + + TransformLocal(roc, row, x, y, z, ref, ref2, scale, scale2, scaleMode); } GPUdi() void TPCFastTransform::Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const @@ -617,31 +540,23 @@ GPUdi() void TPCFastTransform::Transform(int32_t roc, int32_t row, float pad, fl /// _______________ The main method: cluster transformation _______________________ /// /// Transforms raw TPC coordinates to local XYZ withing a roc - /// taking calibration + alignment into account. + /// taking calibration into account. /// const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - // const RocInfo &rocInfo = getRocInfo( roc ); - // bool sideC = ( roc >= NumberOfRocs / 2 ); - x = rowInfo.x; float u = 0, v = 0; - convPadTimeToUV(roc, row, pad, time, u, v, vertexTime); - - TransformInternal(roc, row, u, v, x, ref, ref2, scale, scale2, scaleMode); - + convPadTimeToUV(row, pad, time, u, v, vertexTime); getGeometry().convUVtoLocal(roc, u, v, y, z); - float dzTOF = 0; - getTOFcorrection(roc, row, x, y, z, dzTOF); - z += dzTOF; + TransformLocal(roc, row, x, y, z, ref, ref2, scale, scale2, scaleMode); } GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, float time, float& z, float maxTimeBin) const { float v = 0; - convTimeToVinTimeFrame(roc, time, v, maxTimeBin); + convTimeToVinTimeFrame(time, v, maxTimeBin); getGeometry().convVtoLocal(roc, v, z); } @@ -656,7 +571,7 @@ GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, int32_t row, fl const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); x = rowInfo.x; float u = 0, v = 0; - convPadTimeToUVinTimeFrame(roc, row, pad, time, u, v, maxTimeBin); + convPadTimeToUVinTimeFrame(row, pad, time, u, v, maxTimeBin); getGeometry().convUVtoLocal(roc, u, v, y, z); } @@ -665,7 +580,7 @@ GPUdi() void TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, int32_t /// Inverse transformation to TransformInTimeFrame float u = 0, v = 0; getGeometry().convLocalToUV(roc, y, z, u, v); - convUVtoPadTimeInTimeFrame(roc, row, u, v, pad, time, maxTimeBin); + convUVtoPadTimeInTimeFrame(row, u, v, pad, time, maxTimeBin); } GPUdi() float TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, float z, float maxTimeBin) const @@ -715,26 +630,16 @@ GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t roc, float time, /// Only Z coordinate. /// - float v = (time - mT0 - maxTimeBin) * mVdrift + mLdriftCorr; // drift length cm - float z = getGeometry().getTPCalignmentZ(); // global TPC alignment - if (roc < getGeometry().getNumberOfRocsA()) { - z -= v; - } else { - z += v; - } + float v = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm + float z = (roc < getGeometry().getNumberOfRocsA()) ? -v : v; return z; } GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t roc, float z, float maxTimeBin) const { /// Inverse transformation of convTimeToZinTimeFrame() - float v; - if (roc < getGeometry().getNumberOfRocsA()) { - v = getGeometry().getTPCalignmentZ() - z; - } else { - v = z - getGeometry().getTPCalignmentZ(); - } - return mT0 + maxTimeBin + (v - mLdriftCorr) / mVdrift; + float v = (roc < getGeometry().getNumberOfRocsA()) ? -z : z; + return mT0 + maxTimeBin + v / mVdrift; } GPUdi() float TPCFastTransform::convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const @@ -769,17 +674,7 @@ GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row, float { /// maximal possible drift time of the active area float maxL = mCorrection.getMaxDriftLength(roc, row, pad); - - bool sideC = (roc >= getGeometry().getNumberOfRocsA()); - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - const TPCFastTransformGeo::RocInfo& rocInfo = getGeometry().getRocInfo(roc); - - float x = rowInfo.x; - float u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - - float y = sideC ? -u : u; // pads are mirrorred on C-side - float yLab = y * rocInfo.cosAlpha + x * rocInfo.sinAlpha; - return mT0 + (maxL - mLdriftCorr) / (mVdrift + mVdriftCorrY * yLab); + return mT0 + maxL / mVdrift; } GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row) const diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index b472868fa1071..c8982f05d4730 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -35,10 +35,10 @@ TPCFastTransformGeo::TPCFastTransformGeo() s.sinAlpha = sin(alpha); s.cosAlpha = cos(alpha); } - mRocInfos[NumberOfRocs] = RocInfo{0.f, 0.f}; + mRocInfos[NumberOfRocs] = RocInfo{}; for (int32_t i = 0; i < MaxNumberOfRows + 1; i++) { - mRowInfos[i] = RowInfo{0.f, -1, 0.f, 0.f, 0.f, 0.f}; + mRowInfos[i] = RowInfo{}; } } @@ -51,45 +51,25 @@ void TPCFastTransformGeo::startConstruction(int32_t numberOfRows) mConstructionMask = ConstructionState::InProgress; mNumberOfRows = numberOfRows; - mTPCzLengthA = 0.f; - mTPCzLengthC = 0.f; - mTPCalignmentZ = 0.f; - mScaleVtoSVsideA = 0.f; - mScaleVtoSVsideC = 0.f; - mScaleSVtoVsideA = 0.f; - mScaleSVtoVsideC = 0.f; + mTPCzLength = 0.f; for (int32_t i = 0; i < MaxNumberOfRows; i++) { - mRowInfos[i] = RowInfo{0.f, -1, 0.f, 0.f, 0.f, 0.f}; + mRowInfos[i] = RowInfo{}; } } -void TPCFastTransformGeo::setTPCzLength(float tpcZlengthSideA, float tpcZlengthSideC) +void TPCFastTransformGeo::setTPCzLength(float tpcZlength) { /// Sets TPC z length for both sides assert(mConstructionMask & ConstructionState::InProgress); - assert((tpcZlengthSideA > 0.f) && (tpcZlengthSideC > 0.f)); + assert(tpcZlength > 0.f); - mTPCzLengthA = tpcZlengthSideA; - mTPCzLengthC = tpcZlengthSideC; - mScaleSVtoVsideA = tpcZlengthSideA + 3.; // add some extra possible drift length due to the space charge distortions - mScaleSVtoVsideC = tpcZlengthSideC + 3.; - mScaleVtoSVsideA = 1. / mScaleSVtoVsideA; - mScaleVtoSVsideC = 1. / mScaleSVtoVsideC; + mTPCzLength = tpcZlength; mConstructionMask |= ConstructionState::GeometryIsSet; } -void TPCFastTransformGeo::setTPCalignmentZ(float tpcAlignmentZ) -{ - /// Sets the TPC alignment - assert(mConstructionMask & ConstructionState::InProgress); - - mTPCalignmentZ = tpcAlignmentZ; - mConstructionMask |= ConstructionState::AlignmentIsSet; -} - void TPCFastTransformGeo::setTPCrow(int32_t iRow, float x, int32_t nPads, float padWidth) { /// Initializes a TPC row @@ -113,8 +93,6 @@ void TPCFastTransformGeo::setTPCrow(int32_t iRow, float x, int32_t nPads, float row.maxPad = nPads - 1; row.padWidth = padWidth; row.u0 = -uWidth / 2.; - row.scaleUtoSU = 1. / uWidth; - row.scaleSUtoU = uWidth; } void TPCFastTransformGeo::finishConstruction() @@ -123,7 +101,6 @@ void TPCFastTransformGeo::finishConstruction() assert(mConstructionMask & ConstructionState::InProgress); // construction in process assert(mConstructionMask & ConstructionState::GeometryIsSet); // geometry is set - assert(mConstructionMask & ConstructionState::AlignmentIsSet); // alignment is set for (int32_t i = 0; i < mNumberOfRows; i++) { // all TPC rows are initialized assert(getRowInfo(i).maxPad > 0); @@ -138,9 +115,7 @@ void TPCFastTransformGeo::print() const #if !defined(GPUCA_GPUCODE) LOG(info) << "TPC Fast Transformation Geometry: "; LOG(info) << "mNumberOfRows = " << mNumberOfRows; - LOG(info) << "mTPCzLengthA = " << mTPCzLengthA; - LOG(info) << "mTPCzLengthC = " << mTPCzLengthC; - LOG(info) << "mTPCalignmentZ = " << mTPCalignmentZ; + LOG(info) << "mTPCzLength = " << mTPCzLength; LOG(info) << "TPC Rows : "; for (int32_t i = 0; i < mNumberOfRows; i++) { LOG(info) << " tpc row " << i << ": x = " << mRowInfos[i].x << " maxPad = " << mRowInfos[i].maxPad << " padWidth = " << mRowInfos[i].padWidth; @@ -179,26 +154,26 @@ int32_t TPCFastTransformGeo::test(int32_t roc, int32_t row, float ly, float lz) LOG(info) << "Error local <-> UV: y " << ly << " dy " << ly1 - ly << " z " << lz << " dz " << lz1 - lz; error = -4; } + /* + float su = 0.f, sv = 0.f; - float su = 0.f, sv = 0.f; + convUVtoScaledUV(roc, row, u, v, su, sv); - convUVtoScaledUV(roc, row, u, v, su, sv); + if (su < 0.f || su > 1.f) { + LOG(info) << "Error scaled U range: u " << u << " su " << su; + error = -5; + } - if (su < 0.f || su > 1.f) { - LOG(info) << "Error scaled U range: u " << u << " su " << su; - error = -5; - } - - float u1 = 0.f, v1 = 0.f; - convScaledUVtoUV(roc, row, su, sv, u1, v1); - - if (fabs(u1 - u) > 1.e-4 || fabs(v1 - v) > 1.e-4) { - LOG(info) << "Error UV<->scaled UV: u " << u << " du " << u1 - u << " v " << v << " dv " << v1 - v; - error = -6; - } + float u1 = 0.f, v1 = 0.f; + convScaledUVtoUV(roc, row, su, sv, u1, v1); + if (fabs(u1 - u) > 1.e-4 || fabs(v1 - v) > 1.e-4) { + LOG(info) << "Error UV<->scaled UV: u " << u << " du " << u1 - u << " v " << v << " dv " << v1 - v; + error = -6; + } + */ float pad = convUtoPad(row, u); - u1 = convPadToU(row, pad); + float u1 = convPadToU(row, pad); if (fabs(u1 - u) > 1.e-5) { LOG(info) << "Error U<->Pad: u " << u << " pad " << pad << " du " << u1 - u; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index 3382d1d926ce2..a5d642158cd8f 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -36,19 +36,17 @@ class TPCFastTransformGeo public: /// The struct contains necessary info for TPC ROC struct RocInfo { - float sinAlpha; - float cosAlpha; + float sinAlpha{0.f}; ///< sin of the angle between the local x and the global x + float cosAlpha{0.f}; ///< cos of the angle between the local x and the global x ClassDefNV(RocInfo, 1); }; /// The struct contains necessary info about TPC padrow struct RowInfo { - float x; ///< nominal X coordinate of the row [cm] - int32_t maxPad; ///< maximal pad number = n pads - 1 - float padWidth; ///< width of pads [cm] - float u0; ///< min. u coordinate - float scaleUtoSU; ///< scale for su (scaled u ) coordinate - float scaleSUtoU; ///< scale for u coordinate + float x{0.f}; ///< nominal X coordinate of the padrow [cm] + int32_t maxPad{0}; ///< maximal pad number = n pads - 1 + float padWidth{0.f}; ///< width of pads [cm] + float u0{0.f}; ///< min. u coordinate /// get U min GPUd() float getUmin() const { return u0; } @@ -92,13 +90,7 @@ class TPCFastTransformGeo /// Sets TPC geometry /// /// It must be called once during initialization - void setTPCzLength(float tpcZlengthSideA, float tpcZlengthSideC); - - /// Sets all drift calibration parameters and the time stamp - /// - /// It must be called once during construction, - /// but also may be called afterwards to reset these parameters. - void setTPCalignmentZ(float tpcAlignmentZ); + void setTPCzLength(float tpcZlength); /// Finishes initialization: puts everything to the flat buffer, releases temporary memory void finishConstruction(); @@ -126,21 +118,8 @@ class TPCFastTransformGeo /// Gives TPC row info GPUd() const RowInfo& getRowInfo(int32_t row) const; - /// Gives Z length of the TPC, side A - GPUd() float getTPCzLengthA() const { return mTPCzLengthA; } - - /// Gives Z length of the TPC, side C - GPUd() float getTPCzLengthC() const { return mTPCzLengthC; } - - /// Gives Z length of the TPC, depending on the roc - GPUd() float getTPCzLength(int32_t roc) const - { - return (roc < NumberOfRocsA) ? mTPCzLengthA - : mTPCzLengthC; - } - - /// Gives TPC alignment in Z - GPUd() float getTPCalignmentZ() const { return mTPCalignmentZ; } + /// Gives Z length of the TPC, one Z side + GPUd() float getTPCzLength() const { return mTPCzLength; } /// _______________ Conversion of coordinate systems __________ @@ -157,15 +136,6 @@ class TPCFastTransformGeo /// convert Local-> UV c.s. GPUd() void convLocalToUV(int32_t roc, float y, float z, float& u, float& v) const; - /// convert UV -> Scaled UV - GPUd() void convUVtoScaledUV(int32_t roc, int32_t row, float u, float v, float& su, float& sv) const; - - /// convert Scaled UV -> UV - GPUd() void convScaledUVtoUV(int32_t roc, int32_t row, float su, float sv, float& u, float& v) const; - - /// convert Scaled UV -> Local c.s. - GPUd() void convScaledUVtoLocal(int32_t roc, int32_t row, float su, float sv, float& ly, float& lz) const; - /// convert Pad coordinate -> U GPUd() float convPadToU(int32_t row, float pad) const; @@ -196,7 +166,6 @@ class TPCFastTransformGeo Constructed = 0x1, ///< the object is constructed, temporary memory is released InProgress = 0x2, ///< construction started: temporary memory is reserved GeometryIsSet = 0x4, ///< the TPC geometry is set - AlignmentIsSet = 0x8 ///< the TPC alignment is set }; uint32_t mConstructionMask = ConstructionState::NotConstructed; ///< mask for constructed object members, first two bytes are used by this class @@ -204,18 +173,12 @@ class TPCFastTransformGeo /// _______________ Geometry _______________________________________________ int32_t mNumberOfRows = 0; ///< Number of TPC rows. It is different for the Run2 and the Run3 setups - float mTPCzLengthA = 0.f; ///< Z length of the TPC, side A - float mTPCzLengthC = 0.f; ///< Z length of the TPC, side C - float mTPCalignmentZ = 0.f; ///< Global Z shift of the TPC detector. It is applied at the end of the transformation. - float mScaleVtoSVsideA = 0.f; ///< scale for v->sv for TPC side A - float mScaleVtoSVsideC = 0.f; ///< scale for v->sv for TPC side C - float mScaleSVtoVsideA = 0.f; ///< scale for sv->v for TPC side A - float mScaleSVtoVsideC = 0.f; ///< scale for sv->v for TPC side C - - RocInfo mRocInfos[NumberOfRocs + 1]; ///< array of roc information [fixed size] - RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] - - ClassDefNV(TPCFastTransformGeo, 2); + float mTPCzLength = 0.f; ///< Z length of one TPC side (A or C) + + RocInfo mRocInfos[NumberOfRocs + 1]; ///< array of roc information [fixed size] + RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] + + ClassDefNV(TPCFastTransformGeo, 3); }; // ======================================================================= @@ -262,11 +225,10 @@ GPUdi() void TPCFastTransformGeo::convVtoLocal(int32_t roc, float v, float& lz) { /// convert UV -> Local c.s. if (roc < NumberOfRocsA) { // TPC side A - lz = mTPCzLengthA - v; + lz = mTPCzLength - v; } else { // TPC side C - lz = v - mTPCzLengthC; // drift direction is mirrored on C-side + lz = v - mTPCzLength; // drift direction is mirrored on C-side } - lz += mTPCalignmentZ; // global TPC alignment } GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t roc, float u, float v, float& ly, float& lz) const @@ -274,59 +236,25 @@ GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t roc, float u, float v, f /// convert UV -> Local c.s. if (roc < NumberOfRocsA) { // TPC side A ly = u; - lz = mTPCzLengthA - v; + lz = mTPCzLength - v; } else { // TPC side C ly = -u; // pads are mirrorred on C-side - lz = v - mTPCzLengthC; // drift direction is mirrored on C-side + lz = v - mTPCzLength; // drift direction is mirrored on C-side } - lz += mTPCalignmentZ; // global TPC alignment } GPUdi() void TPCFastTransformGeo::convLocalToUV(int32_t roc, float ly, float lz, float& u, float& v) const { /// convert Local-> UV c.s. - lz = lz - mTPCalignmentZ; // global TPC alignment - if (roc < NumberOfRocsA) { // TPC side A + if (roc < NumberOfRocsA) { // TPC side A u = ly; - v = mTPCzLengthA - lz; + v = mTPCzLength - lz; } else { // TPC side C u = -ly; // pads are mirrorred on C-side - v = lz + mTPCzLengthC; // drift direction is mirrored on C-side + v = lz + mTPCzLength; // drift direction is mirrored on C-side } } -GPUdi() void TPCFastTransformGeo::convUVtoScaledUV(int32_t roc, int32_t row, float u, float v, float& su, float& sv) const -{ - /// convert UV -> Scaled UV - const RowInfo& rowInfo = getRowInfo(row); - su = (u - rowInfo.u0) * rowInfo.scaleUtoSU; - if (roc < NumberOfRocsA) { - sv = v * mScaleVtoSVsideA; - } else { - sv = v * mScaleVtoSVsideC; - } -} - -GPUdi() void TPCFastTransformGeo::convScaledUVtoUV(int32_t roc, int32_t row, float su, float sv, float& u, float& v) const -{ - /// convert Scaled UV -> UV - const RowInfo& rowInfo = getRowInfo(row); - u = rowInfo.u0 + su * rowInfo.scaleSUtoU; - if (roc < NumberOfRocsA) { - v = sv * mScaleSVtoVsideA; - } else { - v = sv * mScaleSVtoVsideC; - } -} - -GPUdi() void TPCFastTransformGeo::convScaledUVtoLocal(int32_t roc, int32_t row, float su, float sv, float& ly, float& lz) const -{ - /// convert Scaled UV -> Local c.s. - float u, v; - convScaledUVtoUV(roc, row, su, sv, u, v); - convUVtoLocal(roc, u, v, ly, lz); -} - GPUdi() float TPCFastTransformGeo::convPadToU(int32_t row, float pad) const { /// convert Pad coordinate -> U diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx index aa28b6a414876..c553d9cc6dac1 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx @@ -22,6 +22,7 @@ #include "AliTPCcalibDB.h" #include "TPCFastTransform.h" #include "Spline2DHelper.h" +blabla using namespace o2::gpu; From e21fb987273804f798532436665f66232001bbac Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 6 Mar 2025 23:58:56 +0000 Subject: [PATCH 13/26] TPC Splines: init inverse from the inverse voxel map; rebase --- .../TPCFastSpaceChargeCorrectionHelper.h | 13 +- .../TPCFastSpaceChargeCorrectionHelper.cxx | 921 +++++++++--------- .../src/TPCFastTransformHelperO2.cxx | 4 +- .../test/testTPCFastTransform.cxx | 61 +- GPU/TPCFastTransformation/Spline1DSpec.h | 36 +- .../TPCFastSpaceChargeCorrection.cxx | 201 ++-- .../TPCFastSpaceChargeCorrection.h | 334 +++---- .../TPCFastSpaceChargeCorrectionMap.h | 24 +- GPU/TPCFastTransformation/TPCFastTransform.h | 347 +++---- .../TPCFastTransformGeo.cxx | 55 +- .../TPCFastTransformGeo.h | 160 ++- .../TPCFastTransformManager.cxx | 336 ------- .../TPCFastTransformManager.h | 86 -- .../TPCFastTransformationLinkDef_O2.h | 7 +- .../macro/TPCFastTransformInit.C | 211 ++-- 15 files changed, 1159 insertions(+), 1637 deletions(-) delete mode 100644 GPU/TPCFastTransformation/TPCFastTransformManager.cxx delete mode 100644 GPU/TPCFastTransformation/TPCFastTransformManager.h diff --git a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h index eff4972679ed8..abbc5b7116b2d 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h @@ -86,15 +86,14 @@ class TPCFastSpaceChargeCorrectionHelper /// Create SpaceCharge correction out of the voxel tree std::unique_ptr createFromTrackResiduals( - const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, bool useSmoothed = false, bool invertSigns = false); + const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, bool useSmoothed, bool invertSigns); + /// _______________ Utilities ________________________ const TPCFastTransformGeo& getGeometry() { return mGeo; } TPCFastSpaceChargeCorrectionMap& getCorrectionMap() { return mCorrectionMap; } - void fillSpaceChargeCorrectionFromMap(TPCFastSpaceChargeCorrection& correction); - void testGeometry(const TPCFastTransformGeo& geo) const; /// initialise inverse transformation @@ -103,15 +102,13 @@ class TPCFastSpaceChargeCorrectionHelper /// initialise inverse transformation from linear combination of several input corrections void initInverse(std::vector& corrections, const std::vector& scaling, bool prn); + void MergeCorrections(std::vector& corrections, const std::vector& scaling, bool prn); + private: /// geometry initialization void initGeometry(); - /// get space charge correction in internal TPCFastTransform coordinates u,v->dx,du,dv - void getSpaceChargeCorrection(const TPCFastSpaceChargeCorrection& correction, int slice, int row, o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p, double& su, double& sv, double& dx, double& du, double& dv); - - /// initialise max drift length - void initMaxDriftLength(o2::gpu::TPCFastSpaceChargeCorrection& correction, bool prn); + void fillSpaceChargeCorrectionFromMap(TPCFastSpaceChargeCorrection& correction, bool processingInverseCorrection); static TPCFastSpaceChargeCorrectionHelper* sInstance; ///< singleton instance bool mIsInitialized = 0; ///< initialization flag diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 710a4356dd457..92817063831f6 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -32,6 +32,7 @@ #include "TTreeReader.h" #include "TTreeReaderValue.h" #include "ROOT/TTreeProcessorMT.hxx" +#include using namespace o2::gpu; @@ -112,7 +113,7 @@ void TPCFastSpaceChargeCorrectionHelper::setNthreadsToMaximum() } } -void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFastSpaceChargeCorrection& correction) +void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFastSpaceChargeCorrection& correction, bool processingInverseCorrection) { // calculate correction map: dx,du,dv = ( origTransform() -> x,u,v) - fastTransformNominal:x,u,v // for the future: switch TOF correction off for a while @@ -130,39 +131,64 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas LOG(info) << "fast space charge correction helper: init from data points"; - for (int roc = 0; roc < correction.getGeometry().getNumberOfRocs(); roc++) { + for (int sector = 0; sector < correction.getGeometry().getNumberOfSectors(); sector++) { auto myThread = [&](int iThread) { for (int row = iThread; row < correction.getGeometry().getNumberOfRows(); row += mNthreads) { - TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(roc, row); + TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(sector, row); Spline2DHelper helper; - float* splineParameters = correction.getSplineData(roc, row); - const std::vector& data = mCorrectionMap.getPoints(roc, row); + std::vector splineParameters; + splineParameters.resize(spline.getNumberOfParameters()); + + const std::vector& data = mCorrectionMap.getPoints(sector, row); int nDataPoints = data.size(); - auto& info = correction.getRocRowInfo(roc, row); - info.resetMaxValues(); + auto& info = correction.getSectorRowInfo(sector, row); + if (!processingInverseCorrection) { + info.resetMaxValues(); + } if (nDataPoints >= 4) { - std::vector pointSU(nDataPoints); - std::vector pointSV(nDataPoints); + std::vector pointGU(nDataPoints); + std::vector pointGV(nDataPoints); std::vector pointCorr(3 * nDataPoints); // 3 dimensions for (int i = 0; i < nDataPoints; ++i) { - double su, sv, dx, du, dv; - getSpaceChargeCorrection(correction, roc, row, data[i], su, sv, dx, du, dv); - pointSU[i] = su; - pointSV[i] = sv; - pointCorr[3 * i + 0] = dx; - pointCorr[3 * i + 1] = du; - pointCorr[3 * i + 2] = dv; - info.updateMaxValues(20. * dx, 20. * du, 20. * dv); + o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p = data[i]; + // not corrected grid coordinates + auto [gu, gv, scale] = correction.convLocalToGrid(sector, row, p.mY, p.mZ); + if (scale - 1.f > 1.e-6) { // point is outside the grid + continue; + } + pointGU[i] = gu; + pointGV[i] = gv; + pointCorr[3 * i + 0] = p.mDx; + pointCorr[3 * i + 1] = p.mDy; + pointCorr[3 * i + 2] = p.mDz; + if (!processingInverseCorrection) { + info.updateMaxValues(20. * p.mDx, 20. * p.mDy, 20. * p.mDz); + } } - helper.approximateDataPoints(spline, splineParameters, 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointSU[0], - &pointSV[0], &pointCorr[0], nDataPoints); + helper.approximateDataPoints(spline, splineParameters.data(), 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointGU[0], + &pointGV[0], &pointCorr[0], nDataPoints); } else { for (int i = 0; i < spline.getNumberOfParameters(); i++) { splineParameters[i] = 0.f; } } + + if (processingInverseCorrection) { + float* splineX = correction.getSplineData(sector, row, 1); + float* splineYZ = correction.getSplineData(sector, row, 2); + for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { + splineX[i] = splineParameters[3 * i + 0]; + splineYZ[2 * i + 0] = splineParameters[3 * i + 1]; + splineYZ[2 * i + 1] = splineParameters[3 * i + 2]; + } + } else { + float* splineXYZ = correction.getSplineData(sector, row); + for (int i = 0; i < spline.getNumberOfParameters(); i++) { + splineXYZ[i] = splineParameters[i]; + } + } } // row }; // thread @@ -178,57 +204,30 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas th.join(); } - } // roc + } // sector watch.Stop(); LOGP(info, "Space charge correction tooks: {}s", watch.RealTime()); - - initInverse(correction, 0); -} - -void TPCFastSpaceChargeCorrectionHelper::getSpaceChargeCorrection(const TPCFastSpaceChargeCorrection& correction, int roc, int row, o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p, - double& su, double& sv, double& dx, double& du, double& dv) -{ - // get space charge correction in internal TPCFastTransform coordinates su,sv->dx,du,dv - - if (!mIsInitialized) { - initGeometry(); - } - - // not corrected coordinates in u,v - float u = 0.f, v = 0.f, fsu = 0.f, fsv = 0.f; - mGeo.convLocalToUV(roc, p.mY, p.mZ, u, v); - correction.convUVtoGrid(roc, row, u, v, fsu, fsv); - // mGeo.convUVtoScaledUV(roc, row, u, v, fsu, fsv); - su = fsu; - sv = fsv; - // corrected coordinates in u,v - float u1 = 0.f, v1 = 0.f; - mGeo.convLocalToUV(roc, p.mY + p.mDy, p.mZ + p.mDz, u1, v1); - - dx = p.mDx; - du = u1 - u; - dv = v1 - v; -} +} // fillSpaceChargeCorrectionFromMap std::unique_ptr TPCFastSpaceChargeCorrectionHelper::createFromGlobalCorrection( - std::function correctionGlobal, const int nKnotsY, const int nKnotsZ) { /// creates TPCFastSpaceChargeCorrection object from a continious space charge correction in global coordinates - auto correctionLocal = [&](int roc, int irow, double ly, double lz, + auto correctionLocal = [&](int sector, int irow, double ly, double lz, double& dlx, double& dly, double& dlz) { double lx = mGeo.getRowInfo(irow).x; float gx, gy, gz; - mGeo.convLocalToGlobal(roc, lx, ly, lz, gx, gy, gz); + mGeo.convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); double dgx, dgy, dgz; - correctionGlobal(roc, gx, gy, gz, dgx, dgy, dgz); + correctionGlobal(sector, gx, gy, gz, dgx, dgy, dgz); float lx1, ly1, lz1; - mGeo.convGlobalToLocal(roc, gx + dgx, gy + dgy, gz + dgz, lx1, ly1, lz1); + mGeo.convGlobalToLocal(sector, gx + dgx, gy + dgy, gz + dgz, lx1, ly1, lz1); dlx = lx1 - lx; dly = ly1 - ly; dlz = lz1 - lz; @@ -237,7 +236,7 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper } std::unique_ptr TPCFastSpaceChargeCorrectionHelper::createFromLocalCorrection( - std::function correctionLocal, + std::function correctionLocal, const int nKnotsY, const int nKnotsZ) { /// creates TPCFastSpaceChargeCorrection object from a continious space charge correction in local coordinates @@ -282,28 +281,24 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper /// set space charge correction in the local coordinates /// as a continious function - int nRocs = mGeo.getNumberOfRocs(); + int nSectors = mGeo.getNumberOfSectors(); int nRows = mGeo.getNumberOfRows(); - mCorrectionMap.init(nRocs, nRows); + mCorrectionMap.init(nSectors, nRows); - for (int iRoc = 0; iRoc < nRocs; iRoc++) { + for (int iSector = 0; iSector < nSectors; iSector++) { auto myThread = [&](int iThread) { for (int iRow = iThread; iRow < nRows; iRow += mNthreads) { const auto& info = mGeo.getRowInfo(iRow); - double vMax = mGeo.getTPCzLength(); - double dv = vMax / (6. * (nKnotsZ - 1)); - + double dl = mGeo.getTPCzLength() / (6. * (nKnotsZ - 1)); double dpad = info.maxPad / (6. * (nKnotsY - 1)); for (double pad = 0; pad < info.maxPad + .5 * dpad; pad += dpad) { - float u = mGeo.convPadToU(iRow, pad); - for (double v = 0.; v < vMax + .5 * dv; v += dv) { - float ly, lz; - mGeo.convUVtoLocal(iRoc, u, v, ly, lz); + for (double l = 0.; l < mGeo.getTPCzLength() + .5 * dl; l += dl) { + auto [y, z] = mGeo.convPadDriftLengthToLocal(iSector, iRow, pad, l); double dx, dy, dz; - correctionLocal(iRoc, iRow, ly, lz, dx, dy, dz); - mCorrectionMap.addCorrectionPoint(iRoc, iRow, - ly, lz, dx, dy, dz); + correctionLocal(iSector, iRow, y, z, dx, dy, dz); + mCorrectionMap.addCorrectionPoint(iSector, iRow, + y, z, dx, dy, dz); } } } // row @@ -321,20 +316,21 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper th.join(); } - } // roc + } // sector - fillSpaceChargeCorrectionFromMap(correction); + fillSpaceChargeCorrectionFromMap(correction, false); + initInverse(correction, false); } return std::move(correctionPtr); -} +} // createFromLocalCorrection void TPCFastSpaceChargeCorrectionHelper::testGeometry(const TPCFastTransformGeo& geo) const { const Mapper& mapper = Mapper::instance(); - if (geo.getNumberOfRocs() != Sector::MAXSECTOR) { - LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfRocs() << " instead of " << Sector::MAXSECTOR << std::endl; + if (geo.getNumberOfSectors() != Sector::MAXSECTOR) { + LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfSectors() << " instead of " << Sector::MAXSECTOR << std::endl; } if (geo.getNumberOfRows() != mapper.getNumberOfRows()) { @@ -384,7 +380,7 @@ void TPCFastSpaceChargeCorrectionHelper::testGeometry(const TPCFastTransformGeo& } std::unique_ptr TPCFastSpaceChargeCorrectionHelper::createFromTrackResiduals( - const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, bool useSmoothed, bool invertSigns) + const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, bool useSmoothed, bool invertSigns) { // create o2::gpu::TPCFastSpaceChargeCorrection from o2::tpc::TrackResiduals::VoxRes voxel tree @@ -399,9 +395,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect auto* helper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); - o2::gpu::TPCFastSpaceChargeCorrectionMap& map = helper->getCorrectionMap(); - map.init(geo.getNumberOfRocs(), geo.getNumberOfRows()); - int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); @@ -476,7 +469,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect // std::cout << "n knots Z: " << nKnotsZ << std::endl; const int nRows = geo.getNumberOfRows(); - const int nROCs = geo.getNumberOfRocs(); + const int nSectors = geo.getNumberOfSectors(); { // create the correction object @@ -497,11 +490,11 @@ std::unique_ptr TPCFastSpaceChargeCorrect } // .. create the correction object // set the grid borders - for (int iRoc = 0; iRoc < geo.getNumberOfRocs(); iRoc++) { + for (int iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { const auto& rowInfo = geo.getRowInfo(iRow); - auto& info = correction.getRocRowInfo(iRoc, iRow); - const auto& spline = correction.getSpline(iRoc, iRow); + auto& info = correction.getSectorRowInfo(iSector, iRow); + const auto& spline = correction.getSpline(iSector, iRow); double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); double zMin = rowInfo.x * trackResiduals.getZ2X(0); @@ -514,366 +507,319 @@ std::unique_ptr TPCFastSpaceChargeCorrect info.scaleUtoGrid = spline.getGridX1().getUmax() / (uMax - uMin); info.gridV0 = vMin; info.scaleVtoGrid = spline.getGridX2().getUmax() / (vMax - vMin); - // std::cout << " iRoc " << iRoc << " iRow " << iRow << " uMin: " << uMin << " uMax: " << uMax << " vMin: " << vMin << " vMax: " << vMax + info.gridCorrU0 = info.gridU0; + info.gridCorrV0 = info.gridV0; + info.scaleCorrUtoGrid = info.scaleUtoGrid; + info.scaleCorrVtoGrid = info.scaleVtoGrid; + + // std::cout << " iSector " << iSector << " iRow " << iRow << " uMin: " << uMin << " uMax: " << uMax << " vMin: " << vMin << " vMax: " << vMax //<< " grid scale u "<< info.scaleUtoGrid << " grid scale v "<< info.scaleVtoGrid<< std::endl; } } LOG(info) << "fast space charge correction helper: preparation took " << watch1.RealTime() << "s"; - LOG(info) << "fast space charge correction helper: fill data points from track residuals.. "; - - TStopwatch watch3; + for (int processingInverseCorrection = 0; processingInverseCorrection < 2; processingInverseCorrection++) { - // read the data ROC by ROC + TTree* currentTree = (processingInverseCorrection) ? voxResTreeInverse : voxResTree; - // data in the tree is not sorted by row - // first find which data belong to which row + if (!currentTree) { + continue; + } - struct VoxelData { - int mNentries{0}; // number of entries - float mX, mY, mZ; // mean position in the local coordinates - float mCx, mCy, mCz; // corrections to the local coordinates - }; + LOG(info) << "fast space charge correction helper: " << ((processingInverseCorrection) ? "inverse" : "direct") + << " : fill data points from track residuals.. "; - std::vector vRocData[nRows * nROCs]; - for (int ir = 0; ir < nRows * nROCs; ir++) { - vRocData[ir].resize(nY2Xbins * nZ2Xbins); - } + TStopwatch watch3; + o2::gpu::TPCFastSpaceChargeCorrectionMap& map = helper->getCorrectionMap(); + map.init(geo.getNumberOfSectors(), geo.getNumberOfRows()); - { // read data from the tree to vRocData + // read the data Sector by Sector - ROOT::TTreeProcessorMT processor(*voxResTree, mNthreads); + // data in the tree is not sorted by row + // first find which data belong to which row - auto myThread = [&](TTreeReader& readerSubRange) { - TTreeReaderValue v(readerSubRange, "voxRes"); - while (readerSubRange.Next()) { - int iRoc = (int)v->bsec; - if (iRoc < 0 || iRoc >= nROCs) { - LOG(fatal) << "Error reading voxels: voxel ROC number " << iRoc << " is out of range"; - continue; - } - int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) - if (iRow < 0 || iRow >= nRows) { - LOG(fatal) << "Row number " << iRow << " is out of range"; - } - int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 - int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; - data.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; - data.mX = v->stat[o2::tpc::TrackResiduals::VoxX]; - data.mY = v->stat[o2::tpc::TrackResiduals::VoxF]; - data.mZ = v->stat[o2::tpc::TrackResiduals::VoxZ]; - data.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; - data.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; - data.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; - if (0 && data.mNentries < 1) { - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - data.mNentries = 1; - } - } + struct VoxelData { + int mNentries{0}; // number of entries + float mX, mY, mZ; // mean position in the local coordinates + float mCx, mCy, mCz; // corrections to the local coordinates }; - processor.Process(myThread); - } - for (int iRoc = 0; iRoc < nROCs; iRoc++) { + std::vector vSectorData[nRows * nSectors]; + for (int ir = 0; ir < nRows * nSectors; ir++) { + vSectorData[ir].resize(nY2Xbins * nZ2Xbins); + } - // now process the data row-by-row + { // read data from the tree to vSectorData - auto myThread = [&](int iThread, int nTreads) { - struct Voxel { - float mY, mZ; // not-distorted local coordinates - float mDy, mDz; // bin size - int mSmoothingStep{100}; // is the voxel data original or smoothed at this step + ROOT::TTreeProcessorMT processor(*currentTree, mNthreads); + + auto myThread = [&](TTreeReader& readerSubRange) { + TTreeReaderValue v(readerSubRange, "voxRes"); + while (readerSubRange.Next()) { + int iSector = (int)v->bsec; + if (iSector < 0 || iSector >= nSectors) { + LOG(fatal) << "Error reading voxels: voxel Sector number " << iSector << " is out of range"; + continue; + } + int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) + if (iRow < 0 || iRow >= nRows) { + LOG(fatal) << "Row number " << iRow << " is out of range"; + } + int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 + int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 + auto& data = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; + data.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; + data.mX = v->stat[o2::tpc::TrackResiduals::VoxX]; + data.mY = v->stat[o2::tpc::TrackResiduals::VoxF]; + data.mZ = v->stat[o2::tpc::TrackResiduals::VoxZ]; + data.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; + data.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; + data.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; + if (0 && data.mNentries < 1) { + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + data.mNentries = 1; + } + } }; + processor.Process(myThread); + } - std::vector vRowVoxels(nY2Xbins * nZ2Xbins); + for (int iSector = 0; iSector < nSectors; iSector++) { - for (int iRow = iThread; iRow < nRows; iRow += nTreads) { - // LOG(info) << "Processing ROC " << iRoc << " row " << iRow; + // now process the data row-by-row - // complete the voxel data + auto myThread = [&](int iThread, int nTreads) { + struct Voxel { + float mY, mZ; // not-distorted local coordinates + float mDy, mDz; // bin size + int mSmoothingStep{100}; // is the voxel data original or smoothed at this step + }; - { - int xBin = iRow; - double x = trackResiduals.getX(xBin); // radius of the pad row - bool isDataFound = false; - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - // y/x coordinate of the bin ~-0.15 ... 0.15 - double y2x = trackResiduals.getY2X(xBin, iy); - // z/x coordinate of the bin 0.1 .. 0.9 - double z2x = trackResiduals.getZ2X(iz); - vox.mY = x * y2x; - vox.mZ = x * z2x; - vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); - vox.mDz = x * trackResiduals.getDZ2X(iz); - if (iRoc >= geo.getNumberOfRocsA()) { - vox.mZ = -vox.mZ; - } - data.mY *= x; - data.mZ *= x; - /* - if ( fabs(x - data.mX) > 0.01 || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { - std::cout - << " roc " << iRoc << " row " << iRow - << " voxel x " << x << " y " << vox.mY << " z " << vox.mZ - << " data x " << data.mX << " y " << data.mY << " z " << data.mZ - << std::endl; - } - */ - if (0) { // debug: always use voxel center instead of the mean position - data.mY = vox.mY; - data.mZ = vox.mZ; - } - if (data.mNentries < 1) { // no data - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - data.mY = vox.mY; - data.mZ = vox.mZ; - vox.mSmoothingStep = 100; - } else { // voxel contains data - if (invertSigns) { - data.mCx *= -1.; - data.mCy *= -1.; - data.mCz *= -1.; - } - vox.mSmoothingStep = 0; // original data - isDataFound = true; - } - } - } + std::vector vRowVoxels(nY2Xbins * nZ2Xbins); + + for (int iRow = iThread; iRow < nRows; iRow += nTreads) { + // LOG(info) << "Processing Sector " << iSector << " row " << iRow; - if (!isDataFound) { // fill everything with 0 + // complete the voxel data + + { + int xBin = iRow; + double x = trackResiduals.getX(xBin); // radius of the pad row + bool isDataFound = false; for (int iy = 0; iy < nY2Xbins; iy++) { for (int iz = 0; iz < nZ2Xbins; iz++) { - vRowVoxels[iy * nZ2Xbins + iz].mSmoothingStep = 0; + auto& data = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + // y/x coordinate of the bin ~-0.15 ... 0.15 + double y2x = trackResiduals.getY2X(xBin, iy); + // z/x coordinate of the bin 0.1 .. 0.9 + double z2x = trackResiduals.getZ2X(iz); + vox.mY = x * y2x; + vox.mZ = x * z2x; + vox.mDy = x / trackResiduals.getDY2XI(xBin, iy); + vox.mDz = x * trackResiduals.getDZ2X(iz); + if (iSector >= geo.getNumberOfSectorsA()) { + vox.mZ = -vox.mZ; + } + data.mY *= x; + data.mZ *= x; + /* + if ( fabs(x - data.mX) > 0.01 || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { + std::cout + << " sector " << iSector << " row " << iRow + << " voxel x " << x << " y " << vox.mY << " z " << vox.mZ + << " data x " << data.mX << " y " << data.mY << " z " << data.mZ + << std::endl; + } + */ + if (0) { // debug: always use voxel center instead of the mean position + data.mY = vox.mY; + data.mZ = vox.mZ; + } + if (data.mNentries < 1) { // no data + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + data.mY = vox.mY; + data.mZ = vox.mZ; + vox.mSmoothingStep = 100; + } else { // voxel contains data + if (invertSigns) { + data.mCx *= -1.; + data.mCy *= -1.; + data.mCz *= -1.; + } + vox.mSmoothingStep = 0; // original data + isDataFound = true; + } } } - } - } // complete the voxel data - // repare the voxel data: fill empty voxels - - int nRepairs = 0; - - for (int ismooth = 1; ismooth <= 2; ismooth++) { - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins; iz++) { - auto& data = vRocData[iRoc * nRows + iRow][iy * nZ2Xbins + iz]; - auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; - if (vox.mSmoothingStep <= ismooth) { // already filled - continue; - } - nRepairs++; - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - double w = 0.; - bool filled = false; - auto update = [&](int iy1, int iz1) { - auto& data1 = vRocData[iRoc * nRows + iRow][iy1 * nZ2Xbins + iz1]; - auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; - if (vox1.mSmoothingStep >= ismooth) { - return false; + if (!isDataFound) { // fill everything with 0 + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + vRowVoxels[iy * nZ2Xbins + iz].mSmoothingStep = 0; } - double w1 = 1. / (abs(iy - iy1) + abs(iz - iz1) + 1); - data.mCx += w1 * data1.mCx; - data.mCy += w1 * data1.mCy; - data.mCz += w1 * data1.mCz; - w += w1; - filled = true; - return true; - }; - - for (int iy1 = iy - 1; iy1 >= 0 && !update(iy1, iz); iy1--) { - } - for (int iy1 = iy + 1; iy1 < nY2Xbins && !update(iy1, iz); iy1++) { - } - for (int iz1 = iz - 1; iz1 >= 0 && !update(iy, iz1); iz1--) { - } - for (int iz1 = iz + 1; iz1 < nZ2Xbins && !update(iy, iz1); iz1++) { } + } + } // complete the voxel data - if (filled) { - data.mCx /= w; - data.mCy /= w; - data.mCz /= w; - vox.mSmoothingStep = ismooth; - } - } // iz - } // iy - } // ismooth + // repare the voxel data: fill empty voxels - if (nRepairs > 0) { - LOG(debug) << "ROC " << iRoc << " row " << iRow << ": " << nRepairs << " voxel repairs for " << nY2Xbins * nZ2Xbins << " voxels"; - } + int nRepairs = 0; - // feed the row data to the helper + for (int ismooth = 1; ismooth <= 2; ismooth++) { + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& data = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep <= ismooth) { // already filled + continue; + } + nRepairs++; + data.mCx = 0.; + data.mCy = 0.; + data.mCz = 0.; + double w = 0.; + bool filled = false; + auto update = [&](int iy1, int iz1) { + auto& data1 = vSectorData[iSector * nRows + iRow][iy1 * nZ2Xbins + iz1]; + auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; + if (vox1.mSmoothingStep >= ismooth) { + return false; + } + double w1 = 1. / (abs(iy - iy1) + abs(iz - iz1) + 1); + data.mCx += w1 * data1.mCx; + data.mCy += w1 * data1.mCy; + data.mCz += w1 * data1.mCz; + w += w1; + filled = true; + return true; + }; + + for (int iy1 = iy - 1; iy1 >= 0 && !update(iy1, iz); iy1--) { + } + for (int iy1 = iy + 1; iy1 < nY2Xbins && !update(iy1, iz); iy1++) { + } + for (int iz1 = iz - 1; iz1 >= 0 && !update(iy, iz1); iz1--) { + } + for (int iz1 = iz + 1; iz1 < nZ2Xbins && !update(iy, iz1); iz1++) { + } - auto& info = correction.getRocRowInfo(iRoc, iRow); - const auto& spline = correction.getSpline(iRoc, iRow); + if (filled) { + data.mCx /= w; + data.mCy /= w; + data.mCz /= w; + vox.mSmoothingStep = ismooth; + } + } // iz + } // iy + } // ismooth - auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nSteps) { - auto& data1 = vRocData[iRoc * nRows + iRow][iy1 * nZ2Xbins + iz1]; - auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; - auto& data2 = vRocData[iRoc * nRows + iRow][iy2 * nZ2Xbins + iz2]; - auto& vox2 = vRowVoxels[iy2 * nZ2Xbins + iz2]; - if (vox1.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared: y " << iy1 << " z " << iz1; - } - if (vox2.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared: y " << iy2 << " z " << iz2; - } - double y1 = vox1.mY; - double z1 = vox1.mZ; - double cx1 = data1.mCx; - double cy1 = data1.mCy; - double cz1 = data1.mCz; - double y2 = vox2.mY; - double z2 = vox2.mZ; - double cx2 = data2.mCx; - double cy2 = data2.mCy; - double cz2 = data2.mCz; - - for (int is = 0; is < nSteps; is++) { - double s2 = is / (double)nSteps; - double s1 = 1. - s2; - double y = s1 * y1 + s2 * y2; - double z = s1 * z1 + s2 * z2; - double cx = s1 * cx1 + s2 * cx2; - double cy = s1 * cy1 + s2 * cy2; - double cz = s1 * cz1 + s2 * cz2; - map.addCorrectionPoint(iRoc, iRow, y, z, cx, cy, cz); + if (nRepairs > 0) { + LOG(debug) << "Sector " << iSector << " row " << iRow << ": " << nRepairs << " voxel repairs for " << nY2Xbins * nZ2Xbins << " voxels"; } - }; - for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins - 1; iz++) { - addEdge(iy, iz, iy, iz + 1, 3); - } - addEdge(iy, nZ2Xbins - 1, iy, nZ2Xbins - 1, 1); - } + // feed the row data to the helper - for (int iz = 0; iz < nZ2Xbins; iz++) { - for (int iy = 0; iy < nY2Xbins - 1; iy++) { - addEdge(iy, iz, iy + 1, iz, 3); - } - addEdge(nY2Xbins - 1, iz, nY2Xbins - 1, iz, 1); - } // iy + auto& info = correction.getSectorRowInfo(iSector, iRow); + const auto& spline = correction.getSpline(iSector, iRow); - } // iRow - }; // myThread + auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nSteps) { + auto& data1 = vSectorData[iSector * nRows + iRow][iy1 * nZ2Xbins + iz1]; + auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; + auto& data2 = vSectorData[iSector * nRows + iRow][iy2 * nZ2Xbins + iz2]; + auto& vox2 = vRowVoxels[iy2 * nZ2Xbins + iz2]; + if (vox1.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared: y " << iy1 << " z " << iz1; + } + if (vox2.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared: y " << iy2 << " z " << iz2; + } + double y1 = vox1.mY; + double z1 = vox1.mZ; + double cx1 = data1.mCx; + double cy1 = data1.mCy; + double cz1 = data1.mCz; + double y2 = vox2.mY; + double z2 = vox2.mZ; + double cx2 = data2.mCx; + double cy2 = data2.mCy; + double cz2 = data2.mCz; + + for (int is = 0; is < nSteps; is++) { + double s2 = is / (double)nSteps; + double s1 = 1. - s2; + double y = s1 * y1 + s2 * y2; + double z = s1 * z1 + s2 * z2; + double cx = s1 * cx1 + s2 * cx2; + double cy = s1 * cy1 + s2 * cy2; + double cz = s1 * cz1 + s2 * cz2; + map.addCorrectionPoint(iSector, iRow, y, z, cx, cy, cz); + } + }; - // run n threads + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins - 1; iz++) { + addEdge(iy, iz, iy, iz + 1, 3); + } + addEdge(iy, nZ2Xbins - 1, iy, nZ2Xbins - 1, 1); + } - int nThreads = mNthreads; - // nThreads = 1; + for (int iz = 0; iz < nZ2Xbins; iz++) { + for (int iy = 0; iy < nY2Xbins - 1; iy++) { + addEdge(iy, iz, iy + 1, iz, 3); + } + addEdge(nY2Xbins - 1, iz, nY2Xbins - 1, iz, 1); + } // iy - std::vector threads(nThreads); + } // iRow + }; // myThread - for (int i = 0; i < nThreads; i++) { - threads[i] = std::thread(myThread, i, nThreads); - } + // run n threads - // wait for the threads to finish - for (auto& th : threads) { - th.join(); - } - } // iRoc + int nThreads = mNthreads; + // nThreads = 1; - LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch3.RealTime()); + std::vector threads(nThreads); - LOG(info) << "fast space charge correction helper: create space charge from the map of data points.."; + for (int i = 0; i < nThreads; i++) { + threads[i] = std::thread(myThread, i, nThreads); + } - TStopwatch watch4; + // wait for the threads to finish + for (auto& th : threads) { + th.join(); + } + } // iSector - helper->fillSpaceChargeCorrectionFromMap(correction); + LOGP(info, "Reading & reparing of the track residuals tooks: {}s", watch3.RealTime()); - LOG(info) << "fast space charge correction helper: creation from the data map took " << watch4.RealTime() << "s"; + LOG(info) << "fast space charge correction helper: create space charge from the map of data points.."; - LOGP(info, "Creation from track residuals tooks in total: {}s", watch.RealTime()); + TStopwatch watch4; - return std::move(correctionPtr); -} + helper->fillSpaceChargeCorrectionFromMap(correction, processingInverseCorrection); -void TPCFastSpaceChargeCorrectionHelper::initMaxDriftLength(o2::gpu::TPCFastSpaceChargeCorrection& correction, bool prn) -{ - /// initialise max drift length + LOG(info) << "fast space charge correction helper: creation from the data map took " << watch4.RealTime() << "s"; - double tpcR2min = mGeo.getRowInfo(0).x - 1.; - tpcR2min = tpcR2min * tpcR2min; - double tpcR2max = mGeo.getRowInfo(mGeo.getNumberOfRows() - 1).x; - tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfRocsA() / 2) + 1.; - tpcR2max = tpcR2max * tpcR2max; + } // processingInverseCorrection - ChebyshevFit1D chebFitter; + if (voxResTree && !voxResTreeInverse) { + LOG(info) << "fast space charge correction helper: init inverse correction from direct correction.."; + TStopwatch watch4; + helper->initInverse(correction, false); + LOG(info) << "fast space charge correction helper: init inverse correction took " << watch4.RealTime() << "s"; + } - for (int roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { - if (prn) { - LOG(info) << "init MaxDriftLength for roc " << roc; - } - double vLength = mGeo.getTPCzLength(); - TPCFastSpaceChargeCorrection::RocInfo& rocInfo = correction.getRocInfo(roc); - rocInfo.vMax = 0.f; + LOGP(info, "Creation from track residuals tooks in total: {}s", watch.RealTime()); - for (int row = 0; row < mGeo.getNumberOfRows(); row++) { - TPCFastSpaceChargeCorrection::RowActiveArea& area = correction.getRocRowInfo(roc, row).activeArea; - area.cvMax = 0; - area.vMax = 0; - area.cuMin = mGeo.convPadToU(row, 0.f); - area.cuMax = -area.cuMin; - chebFitter.reset(4, 0., mGeo.getRowInfo(row).maxPad); - double x = mGeo.getRowInfo(row).x; - for (int pad = 0; pad < mGeo.getRowInfo(row).maxPad; pad++) { - float u = mGeo.convPadToU(row, (float)pad); - float v0 = 0; - float v1 = 1.1 * vLength; - float vLastValid = -1; - float cvLastValid = -1; - while (v1 - v0 > 0.1) { - float v = 0.5 * (v0 + v1); - float dx, du, dv; - correction.getCorrectionInternal(roc, row, u, v, dx, du, dv); - double cx = x + dx; - double cu = u + du; - double cv = v + dv; - double r2 = cx * cx + cu * cu; - if (cv < 0) { - v0 = v; - } else if (cv <= vLength && r2 >= tpcR2min && r2 <= tpcR2max) { - v0 = v; - vLastValid = v; - cvLastValid = cv; - } else { - v1 = v; - } - } - if (vLastValid > 0.) { - chebFitter.addMeasurement(pad, vLastValid); - } - if (area.vMax < vLastValid) { - area.vMax = vLastValid; - } - if (area.cvMax < cvLastValid) { - area.cvMax = cvLastValid; - } - } - chebFitter.fit(); - for (int i = 0; i < 5; i++) { - area.maxDriftLengthCheb[i] = chebFitter.getCoefficients()[i]; - } - if (rocInfo.vMax < area.vMax) { - rocInfo.vMax = area.vMax; - } - } // row - } // roc -} + return std::move(correctionPtr); + +} // createFromTrackResiduals void TPCFastSpaceChargeCorrectionHelper::initInverse(o2::gpu::TPCFastSpaceChargeCorrection& correction, bool prn) { @@ -893,28 +839,24 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector helper; std::vector splineParameters; for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { - TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(roc, row); + TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(sector, row); helper.setSpline(spline, 10, 10); - double x = mGeo.getRowInfo(row).x; - auto& rocRowInfo = correction.getRocRowInfo(roc, row); - std::vector gridU; { const auto& grid = spline.getGridX1(); @@ -942,95 +884,64 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector dataPointCU, dataPointCV, dataPointF; - dataPointCU.reserve(gridU.size() * gridV.size()); - dataPointCV.reserve(gridU.size() * gridV.size()); - dataPointF.reserve(gridU.size() * gridV.size()); - - TPCFastSpaceChargeCorrection::RowActiveArea& area = rocRowInfo.activeArea; - area.cuMin = 1.e10; - area.cuMax = -1.e10; - double cvMin = 1.e10; + std::vector dataPointGridU, dataPointGridV, dataPointF; + dataPointGridU.reserve(gridU.size() * gridV.size()); + dataPointGridV.reserve(gridU.size() * gridV.size()); + dataPointF.reserve(3 * gridU.size() * gridV.size()); for (int iu = 0; iu < gridU.size(); iu++) { for (int iv = 0; iv < gridV.size(); iv++) { - float u, v; - correction.convGridToUV(roc, row, gridU[iu], gridV[iv], u, v); - - float dx, du, dv; - correction.getCorrectionInternal(roc, row, u, v, dx, du, dv); - dx *= scaling[0]; - du *= scaling[0]; - dv *= scaling[0]; - // add remaining corrections - for (int i = 1; i < corrections.size(); ++i) { - float dxTmp, duTmp, dvTmp; - corrections[i]->getCorrectionInternal(roc, row, u, v, dxTmp, duTmp, dvTmp); + + auto [y, z] = correction.convGridToLocal(sector, row, gridU[iu], gridV[iv]); + double dx = 0, dy = 0, dz = 0; + + // add corrections + for (int i = 0; i < corrections.size(); ++i) { + auto [dxTmp, dyTmp, dzTmp] = corrections[i]->getCorrectionLocal(sector, row, y, z); dx += dxTmp * scaling[i]; - du += duTmp * scaling[i]; - dv += dvTmp * scaling[i]; - } - double cx = x + dx; - double cu = u + du; - double cv = v + dv; - if (cu < area.cuMin) { - area.cuMin = cu; - } - if (cu > area.cuMax) { - area.cuMax = cu; + dy += dyTmp * scaling[i]; + dz += dzTmp * scaling[i]; } - dataPointCU.push_back(cu); - dataPointCV.push_back(cv); + double realY = y + dy; + double realZ = z + dz; + float realU, realV; + mGeo.convLocalToUV1(sector, realY, realZ, realU, realV); + + dataPointGridU.push_back(realU); + dataPointGridV.push_back(realV); dataPointF.push_back(dx); - dataPointF.push_back(du); - dataPointF.push_back(dv); + dataPointF.push_back(dy); + dataPointF.push_back(dz); } } - if (area.cuMax - area.cuMin < 0.2) { - area.cuMax = .1; - area.cuMin = -.1; - } - if (area.cvMax - cvMin < 0.2) { - area.cvMax = .1; - cvMin = -.1; - } - - if (prn) { - LOG(info) << "roc " << roc << " row " << row << " max drift L = " << correction.getMaxDriftLength(roc, row) - << " active area: cuMin " << area.cuMin << " cuMax " << area.cuMax << " vMax " << area.vMax << " cvMax " << area.cvMax; - } - // define the grid for the inverse correction - rocRowInfo.gridCorrU0 = area.cuMin; - rocRowInfo.gridCorrV0 = cvMin; - rocRowInfo.scaleCorrUtoGrid = spline.getGridX1().getUmax() / (area.cuMax - area.cuMin); - rocRowInfo.scaleCorrVtoGrid = spline.getGridX2().getUmax() / area.cvMax; + auto& sectorRowInfo = correction.getSectorRowInfo(sector, row); + + sectorRowInfo.gridCorrU0 = sectorRowInfo.gridU0; + sectorRowInfo.gridCorrV0 = sectorRowInfo.gridV0; + sectorRowInfo.scaleCorrUtoGrid = sectorRowInfo.scaleUtoGrid; + sectorRowInfo.scaleCorrVtoGrid = sectorRowInfo.scaleVtoGrid; - /* - rocRowInfo.gridCorrU0 = rocRowInfo.gridU0; - rocRowInfo.gridCorrV0 = rocRowInfo.gridV0; - rocRowInfo.scaleCorrUtoGrid = rocRowInfo.scaleUtoGrid; - rocRowInfo.scaleCorrVtoGrid = rocRowInfo.scaleVtoGrid; - */ + int nDataPoints = dataPointGridU.size(); - int nDataPoints = dataPointCU.size(); + // convert real Y,Z to grid U,V for (int i = 0; i < nDataPoints; i++) { - dataPointCU[i] = (dataPointCU[i] - rocRowInfo.gridCorrU0) * rocRowInfo.scaleCorrUtoGrid; - dataPointCV[i] = (dataPointCV[i] - rocRowInfo.gridCorrV0) * rocRowInfo.scaleCorrVtoGrid; + dataPointGridU[i] = (dataPointGridU[i] - sectorRowInfo.gridCorrU0) * sectorRowInfo.scaleCorrUtoGrid; + dataPointGridV[i] = (dataPointGridV[i] - sectorRowInfo.gridCorrV0) * sectorRowInfo.scaleCorrVtoGrid; } splineParameters.resize(spline.getNumberOfParameters()); helper.approximateDataPoints(spline, splineParameters.data(), 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), - dataPointCU.data(), dataPointCV.data(), - dataPointF.data(), dataPointCU.size()); + dataPointGridU.data(), dataPointGridV.data(), + dataPointF.data(), nDataPoints); - float* splineX = correction.getSplineData(roc, row, 1); - float* splineUV = correction.getSplineData(roc, row, 2); + float* splineX = correction.getSplineData(sector, row, 1); + float* splineUV = correction.getSplineData(sector, row, 2); for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { splineX[i] = splineParameters[3 * i + 0]; splineUV[2 * i + 0] = splineParameters[3 * i + 1]; @@ -1051,10 +962,100 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector& corrections, const std::vector& scaling, bool prn) +{ + /// merge several corrections + /* + TStopwatch watch; + LOG(info) << "fast space charge correction helper: Merge corrections"; + + if (corrections.size() != scaling.size()) { + LOGP(error, "Input corrections and scaling values have different size"); + return; + } + + auto& correction = *(corrections.front()); + + for (int sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { + + auto myThread = [&](int iThread) { + for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { + TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(sector, row); + + std::vector splineParameters(spline.getNumberOfParameters()); + std::vector splineParametersInvX(spline.getNumberOfParameters()); + std::vector splineParametersInvYZ(spline.getNumberOfParameters()); + + const auto& gridU = spline.getGridX1(); + const auto& gridV = spline.getGridX2(); + + for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { + double u = gridU.getKnot(iu).u; + for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { + int knotIndex = spline.getKnotIndex(iu, iv); + + double v = gridV.getKnot(iu).u; + auto [y, z] = correction.convGridToLocal(sector, row, u, v); + constexpr int nKnotPar1d = 4; + constexpr int nKnotPar2d = nKnotPar1d * 2; + constexpr int nKnotPar3d = nKnotPar1d * 3; + + for (int i = 0; i < corrections.size(); ++i) { + double s = scaling[i]; + auto p = corrections[i]->getCorrectionParameters(sector, row, y, z); + for (int j = 0; j < nKnotPar3d; ++j) { + splineParameters[knotIndex * nKnotPar3d + j] += s * p[j]; + } + auto pInvX = corrections[i]->getCorrectionParametersInvX(sector, row, y, z); + for (int j = 0; j < nKnotPar1d; ++j) { + splineParametersInvX[knotIndex * nKnotPar1d + j] += s * pInvX[j]; + } + auto pInvYZ = corrections[i]->getCorrectionParametersInvYZ(sector, row, y, z); + for (int j = 0; j < nKnotPar2d; ++j) { + splineParametersInvYZ[knotIndex * nKnotPar2d + j] += s * pInvYZ[j]; + } + } + } // iv + } // iu + + float* splineXYZ = correction.getSplineData(sector, row, 0); + float* splineInvX = correction.getSplineData(sector, row, 1); + float* splineInvYZ = correction.getSplineData(sector, row, 2); + + for (int i = 0; i < spline.getNumberOfParameters(); i++) { + splineXYZ[i] = splineParameters[i]; + } + for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { + splineX[i] = splineParametersInvX[i]; + splineYZ[2 * i + 0] = splineParametersInvYZ[2 * i + 0]; + splineYZ[2 * i + 1] = splineParametersInvYZ[2 * i + 1]; + } + + } // row + }; // thread + + std::vector threads(mNthreads); + + // run n threads + for (int i = 0; i < mNthreads; i++) { + threads[i] = std::thread(myThread, i); + } + + // wait for the threads to finish + for (auto& th : threads) { + th.join(); + } + + } // sector + float duration = watch.RealTime(); + LOGP(info, "Merge of corrections tooks: {}s", duration); + */ +} + } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx index c83ee6d0cfa19..a6a2c9722caeb 100644 --- a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx +++ b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx @@ -177,8 +177,8 @@ void TPCFastTransformHelperO2::testGeometry(const TPCFastTransformGeo& geo) cons { const Mapper& mapper = Mapper::instance(); - if (geo.getNumberOfRocs() != Sector::MAXSECTOR) { - LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfRocs() << " instead of " << Sector::MAXSECTOR << std::endl; + if (geo.getNumberOfSectors() != Sector::MAXSECTOR) { + LOG(fatal) << "Wrong number of sectors :" << geo.getNumberOfSectors() << " instead of " << Sector::MAXSECTOR << std::endl; } if (geo.getNumberOfRows() != mapper.getNumberOfRows()) { diff --git a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx index 53cfe08f3a7f4..fee63e9e38bc2 100644 --- a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(FastTransform_test1) BOOST_CHECK_EQUAL(geo.test(), 0); - BOOST_CHECK_EQUAL(geo.getNumberOfRocs(), Sector::MAXSECTOR); + BOOST_CHECK_EQUAL(geo.getNumberOfSectors(), Sector::MAXSECTOR); BOOST_CHECK_EQUAL(geo.getNumberOfRows(), mapper.getNumberOfRows()); double maxDx = 0, maxDy = 0; @@ -71,15 +71,16 @@ BOOST_AUTO_TEST_CASE(FastTransform_test1) for (int pad = 0; pad < nPads; pad++) { const GlobalPadNumber p = mapper.globalPadNumber(PadPos(row, pad)); const PadCentre& c = mapper.padCentre(p); - float u = 0, v = 0; - fastTransform.convPadTimeToUV(row, pad, 0, u, v, 0.); - + float y = 0, z = 0; + int sector = 0; + float time = 0.; + fastTransform.convPadTimeToLocal(sector, row, pad, time, y, z, 0.); double dx = x - c.X(); - double dy = u - (-c.Y()); // diferent sign convention for Y coordinate in the map + double dy = y - (-c.Y()); // diferent sign convention for Y coordinate in the map BOOST_CHECK(fabs(dx) < 1.e-6); BOOST_CHECK(fabs(dy) < 1.e-5); if (fabs(dy) >= 1.e-5) { - std::cout << "row " << row << " pad " << pad << " y calc " << u << " y in map " << -c.Y() << " dy " << dy << std::endl; + std::cout << "row " << row << " pad " << pad << " y calc " << y << " y in map " << -c.Y() << " dy " << dy << std::endl; } if (fabs(maxDx) < fabs(dx)) { maxDx = dx; @@ -104,46 +105,46 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) std::unique_ptr fastTransform0(TPCFastTransformHelperO2::instance()->create(0)); const TPCFastTransformGeo& geo = fastTransform0->getGeometry(); - auto correctionUV = [&](int roc, int /*row*/, const double u, const double v, double& dX, double& dU, double& dV) { + auto correctionUV = [&](int sector, int /*row*/, const double u, const double v, double& dX, double& dU, double& dV) { // float lx = geo.getRowInfo(row).x; dX = 1. + 1 * u + 0.1 * u * u; dU = 2. + 0.2 * u + 0.002 * u * u; // + 0.001 * u * u * u; dV = 3. + 0.1 * v + 0.01 * v * v; //+ 0.0001 * v * v * v; }; - auto correctionLocal = [&](int roc, int row, double ly, double lz, + auto correctionLocal = [&](int sector, int row, double ly, double lz, double& dx, double& dly, double& dlz) { float u, v; - geo.convLocalToUV(roc, ly, lz, u, v); + geo.convLocalToUV(sector, ly, lz, u, v); double du, dv; - correctionUV(roc, row, u, v, dx, du, dv); + correctionUV(sector, row, u, v, dx, du, dv); float ly1, lz1; - geo.convUVtoLocal(roc, u + du, v + dv, ly1, lz1); + geo.convUVtoLocal(sector, u + du, v + dv, ly1, lz1); dly = ly1 - ly; dlz = lz1 - lz; }; - int nRocs = geo.getNumberOfRocs(); + int nSectors = geo.getNumberOfSectors(); int nRows = geo.getNumberOfRows(); TPCFastSpaceChargeCorrectionMap& scData = TPCFastTransformHelperO2::instance()->getCorrectionMap(); - scData.init(nRocs, nRows); + scData.init(nSectors, nRows); - for (int iRoc = 0; iRoc < nRocs; iRoc++) { + for (int iSector = 0; iSector < nSectors; iSector++) { for (int iRow = 0; iRow < nRows; iRow++) { double dsu = 1. / (3 * 8 - 3); double dsv = 1. / (3 * 20 - 3); for (double su = 0.f; su < 1.f + .5 * dsu; su += dsv) { for (double sv = 0.f; sv < 1.f + .5 * dsv; sv += dsv) { float ly = 0.f, lz = 0.f; - geo.convScaledUVtoLocal(iRoc, iRow, su, sv, ly, lz); + geo.convScaledUVtoLocal(iSector, iRow, su, sv, ly, lz); double dx, dy, dz; - correctionLocal(iRoc, iRow, ly, lz, dx, dy, dz); - scData.addCorrectionPoint(iRoc, iRow, + correctionLocal(iSector, iRow, ly, lz, dx, dy, dz); + scData.addCorrectionPoint(iSector, iRow, ly, lz, dx, dy, dz); } } } // row - } // roc + } // sector std::unique_ptr fastTransform(TPCFastTransformHelperO2::instance()->create(0)); @@ -158,12 +159,12 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) double statDiff = 0., statN = 0.; double statDiffFile = 0., statNFile = 0.; - for (int roc = 0; roc < geo.getNumberOfRocs(); roc += 1) { - // std::cout << "roc " << roc << " ... " << std::endl; + for (int sector = 0; sector < geo.getNumberOfSectors(); sector += 1) { + // std::cout << "sector " << sector << " ... " << std::endl; - const TPCFastTransformGeo::RocInfo& rocInfo = geo.getRocInfo(roc); + const TPCFastTransformGeo::SectorInfo& sectorInfo = geo.getSectorInfo(sector); - float lastTimeBin = fastTransform->getMaxDriftTime(roc, 0.f); + float lastTimeBin = fastTransform->getMaxDriftTime(sector, 0.f); for (int row = 0; row < geo.getNumberOfRows(); row++) { @@ -172,31 +173,31 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) for (int pad = 0; pad < nPads; pad += 10) { for (float time = 0; time < lastTimeBin; time += 30) { - // std::cout<<"roc "<setApplyCorrectionOff(); float x0, y0, z0; - fastTransform->Transform(roc, row, pad, time, x0, y0, z0); + fastTransform->Transform(sector, row, pad, time, x0, y0, z0); - BOOST_CHECK_EQUAL(geo.test(roc, row, y0, z0), 0); + BOOST_CHECK_EQUAL(geo.test(sector, row, y0, z0), 0); fastTransform->setApplyCorrectionOn(); float x1, y1, z1; - fastTransform->Transform(roc, row, pad, time, x1, y1, z1); + fastTransform->Transform(sector, row, pad, time, x1, y1, z1); // local to UV float u0, v0, u1, v1; - geo.convLocalToUV(roc, y0, z0, u0, v0); - geo.convLocalToUV(roc, y1, z1, u1, v1); + geo.convLocalToUV(sector, y0, z0, u0, v0); + geo.convLocalToUV(sector, y1, z1, u1, v1); double dx, du, dv; - correctionUV(roc, row, u0, v0, dx, du, dv); + correctionUV(sector, row, u0, v0, dx, du, dv); statDiff += fabs((x1 - x0) - dx) + fabs((u1 - u0) - du) + fabs((v1 - v0) - dv); statN += 3; // std::cout << (x1 - x0) - dx << " " << (u1 - u0) - du << " " << (v1 - v0) - dv << std::endl; //": v0 " << v0 <<" z0 "<Transform(roc, row, pad, time, x1f, y1f, z1f); + fromFile->Transform(sector, row, pad, time, x1f, y1f, z1f); statDiffFile += fabs(x1f - x1) + fabs(y1f - y1) + fabs(z1f - z1); statNFile += 3; } diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index dc59e77e308a1..2cc95ebdcab9f 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -369,7 +369,41 @@ class Spline1DSpec : public Spline1DContainer dDr = v * a; // F(u) = dSl * Sl + dSr * Sr + dDl * Dl + dDr * Dr; } - + /* + template + GPUd() void getUsecondDerivatives(const Knot& knotL, DataT u, + T& dSl, T& dDl, T& dSr, T& dDr, + T& dSl2, T& dDl2, T& dSr2, T& dDr2) const + { + /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] + /// over the spline values Sl, Sr and the slopes Dl, Dr + + if (u < (DataT)0) { + u = (DataT)0; + } + if (u > (DataT)TBase::getUmax()) { + u = (DataT)TBase::getUmax(); + } + + u = u - knotL.u; + T v = u * T(knotL.Li); // scaled u + T vm1 = v - 1.; + T a = u * vm1; + T v2 = v * v; + dSr = v2 * (3. - 2 * v); + dSl = 1. - dSr; + dDl = vm1 * a; + dDr = v * a; + T dv = T(knotL.Li); + dSr2 = 6. * v * (1. - v) * dv; + dSl2 = -dSr2; + dDl2 = (v - 1) * (3 * v - 1); + dDr = u * (v * v - v); + dDr2 = 3.f * v * v - 2.f * v; + // F(u) = dSl * Sl + dSr * Sr + dDl * Dl + dDr * Dr; + // dF(u)/du = dSl2 * Sl + dSr2 * Sr + dDl2 * Dl + dDr2 * Dr; + } + */ using TBase::convXtoU; using TBase::getKnot; using TBase::getKnots; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 111e70072c58e..2921a74b025ce 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -35,7 +35,7 @@ TPCFastSpaceChargeCorrection::TPCFastSpaceChargeCorrection() mScenarioPtr(nullptr), mTimeStamp(-1), mSplineData{nullptr, nullptr, nullptr}, - mRocDataSizeBytes{0, 0, 0} + mSectorDataSizeBytes{0, 0, 0} { // Default Constructor: creates an empty uninitialized object } @@ -64,7 +64,7 @@ void TPCFastSpaceChargeCorrection::destroy() mTimeStamp = -1; for (int32_t is = 0; is < 3; is++) { mSplineData[is] = nullptr; - mRocDataSizeBytes[is] = 0; + mSectorDataSizeBytes[is] = 0; } FlatObject::destroy(); } @@ -101,13 +101,13 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mTimeStamp = obj.mTimeStamp; - for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfRocs(); ++i) { - mRocInfo[i] = obj.mRocInfo[i]; + for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfSectors(); ++i) { + mSectorInfo[i] = obj.mSectorInfo[i]; } - mRocDataSizeBytes[0] = obj.mRocDataSizeBytes[0]; - mRocDataSizeBytes[1] = obj.mRocDataSizeBytes[1]; - mRocDataSizeBytes[2] = obj.mRocDataSizeBytes[2]; + mSectorDataSizeBytes[0] = obj.mSectorDataSizeBytes[0]; + mSectorDataSizeBytes[1] = obj.mSectorDataSizeBytes[1]; + mSectorDataSizeBytes[2] = obj.mSectorDataSizeBytes[2]; // variable-size data mScenarioPtr = obj.mScenarioPtr; @@ -121,8 +121,8 @@ void TPCFastSpaceChargeCorrection::cloneFromObject(const TPCFastSpaceChargeCorre mRowInfos[i] = obj.mRowInfos[i]; } - for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfRocs() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { - mRocRowInfos[i] = obj.mRocRowInfos[i]; + for (int32_t i = 0; i < TPCFastTransformGeo::getNumberOfSectors() * TPCFastTransformGeo::getMaxNumberOfRows(); i++) { + mSectorRowInfos[i] = obj.mSectorRowInfos[i]; } relocateBufferPointers(oldFlatBufferPtr, mFlatBufferPtr); @@ -143,7 +143,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer struct RowInfoVersion3 { int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC roc + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC sector }; struct RowActiveAreaVersion3 { @@ -154,7 +154,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer float cvMax{0.f}; }; - struct RocRowInfoVersion3 { + struct SectorRowInfoVersion3 { float gridV0{0.f}; ///< V coordinate of the V-grid start float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V @@ -171,13 +171,13 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer rowsSize = sizeof(RowInfoVersion3) * mGeo.getNumberOfRows(); } - size_t rocRowsOffset = rowsOffset + rowsSize; - size_t rocRowsSize = 0; - if (mClassVersion == 3) { // copy old-format rocrow data from the buffer to the arrays - rocRowsSize = sizeof(RocRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfRocs(); + size_t sectorRowsOffset = rowsOffset + rowsSize; + size_t sectorRowsSize = 0; + if (mClassVersion == 3) { // copy old-format sectorrow data from the buffer to the arrays + sectorRowsSize = sizeof(SectorRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfSectors(); } - size_t scOffset = alignSize(rocRowsOffset + rocRowsSize, SplineType::getClassAlignmentBytes()); + size_t scOffset = alignSize(sectorRowsOffset + sectorRowsSize, SplineType::getClassAlignmentBytes()); size_t scSize = sizeof(SplineType) * mNumberOfScenarios; mScenarioPtr = reinterpret_cast(mFlatBufferPtr + scOffset); @@ -192,12 +192,12 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer } size_t bufferSize = scBufferOffset + scBufferSize; for (int32_t is = 0; is < 3; is++) { - size_t rocDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + rocDataOffset); - bufferSize = rocDataOffset + mRocDataSizeBytes[is] * mGeo.getNumberOfRocs(); + size_t sectorDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sectorDataOffset); + bufferSize = sectorDataOffset + mSectorDataSizeBytes[is] * mGeo.getNumberOfSectors(); } - if (mClassVersion == 3) { // copy old-format rocrow data from the buffer to the arrays + if (mClassVersion == 3) { // copy old-format sectorrow data from the buffer to the arrays auto* rowInfosOld = reinterpret_cast(mFlatBufferPtr + rowsOffset); for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { @@ -214,13 +214,13 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer spline.setXrange(0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax()); } - auto* rocRowInfosOld = reinterpret_cast(mFlatBufferPtr + rocRowsOffset); + auto* sectorRowInfosOld = reinterpret_cast(mFlatBufferPtr + sectorRowsOffset); - for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { + for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - RocRowInfoVersion3& infoOld = rocRowInfosOld[mGeo.getNumberOfRows() * roc + row]; - RocRowInfo& info = getRocRowInfo(roc, row); - const auto& spline = getSpline(roc, row); + SectorRowInfoVersion3& infoOld = sectorRowInfosOld[mGeo.getNumberOfRows() * sector + row]; + SectorRowInfo& info = getSectorRowInfo(sector, row); + const auto& spline = getSpline(sector, row); info.gridU0 = mGeo.getRowInfo(row).u0; info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); @@ -232,14 +232,6 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer info.gridCorrV0 = infoOld.gridCorrV0; info.scaleCorrVtoGrid = infoOld.scaleCorrVtoGrid; - - info.activeArea.vMax = infoOld.activeArea.vMax; - info.activeArea.cuMin = infoOld.activeArea.cuMin; - info.activeArea.cuMax = infoOld.activeArea.cuMax; - info.activeArea.cvMax = infoOld.activeArea.cvMax; - for (int32_t i = 0; i < 5; i++) { - info.activeArea.maxDriftLengthCheb[i] = infoOld.activeArea.maxDriftLengthCheb[i]; - } } } } @@ -276,7 +268,7 @@ void TPCFastSpaceChargeCorrection::print() const mGeo.print(); LOG(info) << " mNumberOfScenarios = " << mNumberOfScenarios; LOG(info) << " mTimeStamp = " << mTimeStamp; - LOG(info) << " mRocDataSizeBytes = " << mRocDataSizeBytes[0] << " " << mRocDataSizeBytes[1] << " " << mRocDataSizeBytes[2]; + LOG(info) << " mSectorDataSizeBytes = " << mSectorDataSizeBytes[0] << " " << mSectorDataSizeBytes[1] << " " << mSectorDataSizeBytes[2]; { LOG(info) << " TPC rows: "; for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { @@ -292,9 +284,9 @@ void TPCFastSpaceChargeCorrection::print() const } if (mScenarioPtr) { LOG(info) << " Spline Data: "; - for (int32_t is = 0; is < mGeo.getNumberOfRocs(); is++) { + for (int32_t is = 0; is < mGeo.getNumberOfSectors(); is++) { for (int32_t ir = 0; ir < mGeo.getNumberOfRows(); ir++) { - LOG(info) << "roc " << is << " row " << ir << ": "; + LOG(info) << "sector " << is << " row " << ir << ": "; const SplineType& spline = getSpline(is, ir); const float* d = getSplineData(is, ir); int32_t k = 0; @@ -305,8 +297,8 @@ void TPCFastSpaceChargeCorrection::print() const LOG(info) << ""; } } - // LOG(info) << "inverse correction: roc " << roc - // << " dx " << maxDroc[0] << " du " << maxDroc[1] << " dv " << maxDroc[2] ; + // LOG(info) << "inverse correction: sector " << sector + // << " dx " << maxDsector[0] << " du " << maxDsector[1] << " dv " << maxDsector[2] ; } } } @@ -345,7 +337,7 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& mScenarioPtr = nullptr; for (int32_t s = 0; s < 3; s++) { mSplineData[s] = nullptr; - mRocDataSizeBytes[s] = 0; + mSectorDataSizeBytes[s] = 0; } mClassVersion = 4; } @@ -401,18 +393,18 @@ void TPCFastSpaceChargeCorrection::finishConstruction() scBufferSize = alignSize(scBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); } size_t bufferSize = scBufferOffsets[0] + scBufferSize; - size_t rocDataOffset[3]; + size_t sectorDataOffset[3]; for (int32_t is = 0; is < 3; is++) { - rocDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mRocDataSizeBytes[is] = 0; + sectorDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mSectorDataSizeBytes[is] = 0; for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { RowInfo& row = mRowInfos[i]; SplineType& spline = mConstructionScenarios[row.splineScenarioID]; - row.dataOffsetBytes[is] = alignSize(mRocDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - mRocDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); + row.dataOffsetBytes[is] = alignSize(mSectorDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + mSectorDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); } - mRocDataSizeBytes[is] = alignSize(mRocDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - bufferSize = rocDataOffset[is] + mRocDataSizeBytes[is] * mGeo.getNumberOfRocs(); + mSectorDataSizeBytes[is] = alignSize(mSectorDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + bufferSize = sectorDataOffset[is] + mSectorDataSizeBytes[is] * mGeo.getNumberOfSectors(); } FlatObject::finishConstruction(bufferSize); @@ -427,7 +419,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() } for (int32_t is = 0; is < 3; is++) { - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + rocDataOffset[is]); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sectorDataOffset[is]); } releaseConstructionMemory(); @@ -439,15 +431,15 @@ void TPCFastSpaceChargeCorrection::finishConstruction() GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() { // initialise all corrections to 0. - for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { + for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { double vLength = mGeo.getTPCzLength(); - RocInfo& rocInfo = getRocInfo(roc); - rocInfo.vMax = vLength; + SectorInfo& sectorInfo = getSectorInfo(sector); + sectorInfo.vMax = vLength; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - const SplineType& spline = getSpline(roc, row); + const SplineType& spline = getSpline(sector, row); for (int32_t is = 0; is < 3; is++) { - float* data = getSplineData(roc, row, is); + float* data = getSplineData(sector, row, is); int32_t nPar = spline.getNumberOfParameters(); if (is == 1) { nPar = nPar / 3; @@ -460,7 +452,7 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() } } - RocRowInfo& info = getRocRowInfo(roc, row); + SectorRowInfo& info = getSectorRowInfo(sector, row); info.gridU0 = mGeo.getRowInfo(row).u0; info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); @@ -473,18 +465,8 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() info.scaleCorrUtoGrid = info.scaleUtoGrid; info.scaleCorrVtoGrid = info.scaleVtoGrid; - RowActiveArea& area = info.activeArea; - for (int32_t i = 1; i < 5; i++) { - area.maxDriftLengthCheb[i] = 0; - } - area.maxDriftLengthCheb[0] = vLength; - area.cuMin = info.gridCorrU0; - area.cuMax = -area.cuMin; - area.vMax = vLength; - area.cvMax = vLength; - } // row - } // roc + } // sector } void TPCFastSpaceChargeCorrection::constructWithNoCorrection(const TPCFastTransformGeo& geo) @@ -512,31 +494,31 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) double tpcR2min = mGeo.getRowInfo(0).x - 1.; tpcR2min = tpcR2min * tpcR2min; double tpcR2max = mGeo.getRowInfo(mGeo.getNumberOfRows() - 1).x; - tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfRocsA() / 2) + 1.; + tpcR2max = tpcR2max / cos(2 * M_PI / mGeo.getNumberOfSectorsA() / 2) + 1.; tpcR2max = tpcR2max * tpcR2max; struct MaxValue { double V{0.}; - int Roc{-1}; + int Sector{-1}; int Row{-1}; - void update(double v, int roc, int row) + void update(double v, int sector, int row) { if (fabs(v) > fabs(V)) { V = v; - Roc = roc; + Sector = sector; Row = row; } } void update(const MaxValue& other) { - update(other.V, other.Roc, other.Row); + update(other.V, other.Sector, other.Row); } std::string toString() { std::stringstream ss; - ss << V << "(" << Roc << "," << Row << ")"; + ss << V << "(" << Sector << "," << Row << ")"; return ss.str(); } }; @@ -544,70 +526,75 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) MaxValue maxDtpc[3]; MaxValue maxD; - for (int32_t roc = 0; roc < mGeo.getNumberOfRocs(); roc++) { + for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { if (prn) { - LOG(info) << "check inverse transform for roc " << roc; + LOG(info) << "check inverse transform for sector " << sector; } double vLength = mGeo.getTPCzLength(); - MaxValue maxDroc[3]; + MaxValue maxDsector[3]; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - float u0 = mGeo.getRowInfo(row).getUmin(); - float u1 = mGeo.getRowInfo(row).getUmax(); - float v0 = 0.; - float v1 = vLength; - double x = mGeo.getRowInfo(row).x; - double stepU = (u1 - u0) / 100.; - double stepV = (v1 - v0) / 100.; + auto [y0, y1] = mGeo.getRowInfo(row).getYrange(); + auto [z0, z1] = mGeo.getZrange(sector); + + // grid borders + if (sector < mGeo.getNumberOfSectorsA()) { + z1 = vLength - getSectorRowInfo(sector, row).gridV0; + } else { + z0 = getSectorRowInfo(sector, row).gridV0 - vLength; + } + + double stepY = (y1 - y0) / 100.; + double stepZ = (z1 - z0) / 100.; MaxValue maxDrow[3]; - for (double u = u0; u < u1; u += stepU) { - for (double v = v0; v < v1; v += stepV) { - if (v < getRocRowInfo(roc, row).gridV0) { + for (double y = y0; y < y1; y += stepY) { + for (double z = z0; z < z1; z += stepZ) { + auto [dx, dy, dz] = getCorrectionLocal(sector, row, y, z); + double realX = x + dx; + double realY = y + dy; + double realZ = z + dz; + if (!isLocalInsideGrid(sector, row, y, z) || !isLocalInsideGrid(sector, row, realY, realZ)) { continue; } - float dx, du, dv; - getCorrectionInternal(roc, row, u, v, dx, du, dv); - double cx = x + dx; - double cu = u + du; - double cv = v + dv; - double r2 = cx * cx + cu * cu; - if (cv < 0 || cv > vLength || r2 < tpcR2min || r2 > tpcR2max) { + double r2 = realX * realX + realY * realY; + if (realY < y0 || realY > y1 || + realZ < z0 || realZ > z1 || + r2 < tpcR2min || r2 > tpcR2max) { continue; } - float nx, nu, nv; - getCorrectionInvCorrectedX(roc, row, cu, cv, nx); - getCorrectionInvUV(roc, row, cu, cv, nu, nv); - double d[3] = {(cx - nx) - dx, (cu - nu) - du, (cv - nv) - dv}; + float dxr = getCorrectionXatRealYZ(sector, row, realY, realZ); + auto [dyr, dzr] = getCorrectionYZatRealYZ(sector, row, realY, realZ); + double d[3] = {dxr - dx, dyr - dy, dzr - dz}; for (int32_t i = 0; i < 3; i++) { - maxDrow[i].update(d[i], roc, row); + maxDrow[i].update(d[i], sector, row); } if (0 && prn && fabs(d[0]) + fabs(d[1]) + fabs(d[2]) > 0.1) { - LOG(info) << nx - cx << " " << nu - u << " " << nv - v - << " x,u,v " << x << ", " << u << ", " << v - << " dx,du,dv " << cx - x << ", " << cu - u << ", " << cv - v - << " nx,nu,nv " << nx - x << ", " << cu - nu << ", " << cv - nv; + LOG(info) << dxr - dx << " " << dyr - dy << " " << dzr - dz + << " measured xyz " << x << ", " << y << ", " << z + << " dx,dy,dz from measured point " << dx << ", " << dy << ", " << dz + << " dx,dy,dz from real point " << dxr << ", " << dyr << ", " << dzr; } } } - if (1 && prn) { - LOG(info) << "roc " << roc << " row " << row - << " dx " << maxDrow[0].V << " du " << maxDrow[1].V << " dv " << maxDrow[2].V; + if (0 && prn) { + LOG(info) << "sector " << sector << " row " << row + << " dx " << maxDrow[0].V << " dy " << maxDrow[1].V << " dz " << maxDrow[2].V; } for (int32_t i = 0; i < 3; i++) { - maxDroc[i].update(maxDrow[i]); + maxDsector[i].update(maxDrow[i]); maxDtpc[i].update(maxDrow[i]); maxD.update(maxDrow[i]); } } if (prn) { - LOG(info) << "inverse correction: roc " << roc << ". Max deviations: " - << " dx " << maxDroc[0].toString() << " du " << maxDroc[1].toString() << " dv " << maxDroc[2].toString(); + LOG(info) << "inverse correction: sector " << sector << ". Max deviations: " + << " dx " << maxDsector[0].toString() << " dy " << maxDsector[1].toString() << " dz " << maxDsector[2].toString(); } - } // roc + } // sector LOG(info) << "Test inverse TPC correction. max deviations: " - << " dx " << maxDtpc[0].toString() << " du " << maxDtpc[1].toString() << " dv " << maxDtpc[2].toString() << " cm"; + << " dx " << maxDtpc[0].toString() << " dy " << maxDtpc[1].toString() << " dz " << maxDtpc[2].toString() << " cm"; return maxD.V; } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index fa5cf7a1736bd..f84fde4fffd8c 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -44,20 +44,11 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// struct RowInfo { int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing the TPC roc + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing the TPC sector ClassDefNV(RowInfo, 1); }; - struct RowActiveArea { - float maxDriftLengthCheb[5]{0.f}; - float vMax{0.f}; - float cuMin{0.f}; - float cuMax{0.f}; - float cvMax{0.f}; - ClassDefNV(RowActiveArea, 1); - }; - - struct RocRowInfo { + struct SectorRowInfo { float gridU0{0.f}; //< U coordinate of the U-grid start float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate float gridV0{0.f}; ///< V coordinate of the V-grid start @@ -66,38 +57,37 @@ class TPCFastSpaceChargeCorrection : public FlatObject float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate - float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV - RowActiveArea activeArea; + float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV void resetMaxValues() { - maxCorr[0] = 1.f; minCorr[0] = -1.f; - maxCorr[1] = 1.f; + maxCorr[0] = 1.f; minCorr[1] = -1.f; - maxCorr[2] = 1.f; + maxCorr[1] = 1.f; minCorr[2] = -1.f; + maxCorr[2] = 1.f; } void updateMaxValues(float dx, float du, float dv) { - maxCorr[0] = GPUCommonMath::Max(maxCorr[0], dx); minCorr[0] = GPUCommonMath::Min(minCorr[0], dx); + maxCorr[0] = GPUCommonMath::Max(maxCorr[0], dx); - maxCorr[1] = GPUCommonMath::Max(maxCorr[1], du); minCorr[1] = GPUCommonMath::Min(minCorr[1], du); + maxCorr[1] = GPUCommonMath::Max(maxCorr[1], du); - maxCorr[2] = GPUCommonMath::Max(maxCorr[2], dv); minCorr[2] = GPUCommonMath::Min(minCorr[2], dv); + maxCorr[2] = GPUCommonMath::Max(maxCorr[2], dv); } - ClassDefNV(RocRowInfo, 2); + ClassDefNV(SectorRowInfo, 2); }; - struct RocInfo { + struct SectorInfo { float vMax{0.f}; ///< Max value of V coordinate - ClassDefNV(RocInfo, 1); + ClassDefNV(SectorInfo, 1); }; typedef Spline2D SplineType; @@ -167,52 +157,43 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() void setInterpolationSafetyMargin(float val) { fInterpolationSafetyMargin = val; } /// Gives const pointer to a spline - GPUd() const SplineType& getSpline(int32_t roc, int32_t row) const; + GPUd() const SplineType& getSpline(int32_t sector, int32_t row) const; /// Gives pointer to a spline - GPUd() SplineType& getSpline(int32_t roc, int32_t row); + GPUd() SplineType& getSpline(int32_t sector, int32_t row); /// Gives pointer to spline data - GPUd() float* getSplineData(int32_t roc, int32_t row, int32_t iSpline = 0); + GPUd() float* getSplineData(int32_t sector, int32_t row, int32_t iSpline = 0); /// Gives pointer to spline data - GPUd() const float* getSplineData(int32_t roc, int32_t row, int32_t iSpline = 0) const; + GPUd() const float* getSplineData(int32_t sector, int32_t row, int32_t iSpline = 0) const; /// _______________ The main method: cluster correction _______________________ /// - GPUd() int32_t getCorrectionInternal(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const; + // GPUd() int32_t getCorrectionInternal(int32_t sector, int32_t row, float u, float v, float& dx, float& du, float& dv) const; - GPUdi() std::tuple getCorrectionLocal(int32_t roc, int32_t row, float y, float z) const; + GPUdi() std::tuple getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const; /// inverse correction: Corrected U and V -> coorrected X - GPUd() void getCorrectionInvCorrectedX(int32_t roc, int32_t row, float corrU, float corrV, float& corrX) const; + GPUd() float getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; /// inverse correction: Corrected U and V -> uncorrected U and V - GPUd() void getCorrectionInvUV(int32_t roc, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const; - - /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t roc, int32_t row, float pad) const; - - /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t roc, int32_t row) const; - - /// maximal possible drift length of the active area - GPUd() float getMaxDriftLength(int32_t roc) const; + GPUd() std::tuple getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; /// _______________ Utilities _______________________________________________ /// convert local y, z to internal grid coordinates u,v /// return values: u, v, scaling factor - GPUd() std::tuple convLocalToGrid(int32_t roc, int32_t row, float y, float z) const; - - /// convert u,v to internal grid coordinates - GPUd() void convUVtoGrid(int32_t roc, int32_t row, float u, float v, float& gridU, float& gridV) const; + GPUd() std::tuple convLocalToGrid(int32_t sector, int32_t row, float y, float z) const; - /// convert u,v to internal grid coordinates - GPUd() void convGridToUV(int32_t roc, int32_t row, float gridU, float gridV, float& u, float& v) const; + /// convert internal grid coordinates u,v to local y, z + /// return values: y, z, scaling factor + GPUd() std::tuple convGridToLocal(int32_t sector, int32_t row, float u, float v) const; /// convert corrected u,v to internal grid coordinates - GPUd() void convCorrectedUVtoGrid(int32_t roc, int32_t row, float cu, float cv, float& gridU, float& gridV) const; + GPUd() std::tuple convCorrectedLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + + GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; /// TPC geometry information GPUd() const TPCFastTransformGeo& getGeometry() const @@ -229,28 +210,28 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Gives TPC row info GPUd() const RowInfo& getRowInfo(int32_t row) const { return mRowInfos[row]; } - /// Gives TPC roc info - GPUd() const RocInfo& getRocInfo(int32_t roc) const + /// Gives TPC sector info + GPUd() const SectorInfo& getSectorInfo(int32_t sector) const { - return mRocInfo[roc]; + return mSectorInfo[sector]; } - /// Gives TPC roc info - GPUd() RocInfo& getRocInfo(int32_t roc) + /// Gives TPC sector info + GPUd() SectorInfo& getSectorInfo(int32_t sector) { - return mRocInfo[roc]; + return mSectorInfo[sector]; } - /// Gives TPC roc & row info - GPUd() const RocRowInfo& getRocRowInfo(int32_t roc, int32_t row) const + /// Gives TPC sector & row info + GPUd() const SectorRowInfo& getSectorRowInfo(int32_t sector, int32_t row) const { - return mRocRowInfos[mGeo.getMaxNumberOfRows() * roc + row]; + return mSectorRowInfos[mGeo.getMaxNumberOfRows() * sector + row]; } - /// Gives TPC roc & row info - GPUd() RocRowInfo& getRocRowInfo(int32_t roc, int32_t row) + /// Gives TPC sector & row info + GPUd() SectorRowInfo& getSectorRowInfo(int32_t sector, int32_t row) { - return mRocRowInfos[mGeo.getMaxNumberOfRows() * roc + row]; + return mSectorRowInfos[mGeo.getMaxNumberOfRows() * sector + row]; } #if !defined(GPUCA_GPUCODE) @@ -277,7 +258,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject int32_t mNumberOfScenarios; ///< Number of approximation spline scenarios - RocInfo mRocInfo[TPCFastTransformGeo::getNumberOfRocs()]; ///< RocInfo array + SectorInfo mSectorInfo[TPCFastTransformGeo::getNumberOfSectors()]; ///< SectorInfo array SplineType* mScenarioPtr; //! (transient!!) pointer to spline scenarios @@ -287,7 +268,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject char* mSplineData[3]; //! (transient!!) pointer to the spline data in the flat buffer - size_t mRocDataSizeBytes[3]; ///< size of the data for one roc in the flat buffer + size_t mSectorDataSizeBytes[3]; ///< size of the data for one sector in the flat buffer float fInterpolationSafetyMargin{0.1f}; // 10% area around the TPC row. Outside of this area the interpolation returns the boundary values. @@ -298,7 +279,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject RowInfo mRowInfos[TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RowInfo array - RocRowInfo mRocRowInfos[TPCFastTransformGeo::getNumberOfRocs() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RocRowInfo array + SectorRowInfo mSectorRowInfos[TPCFastTransformGeo::getNumberOfSectors() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< SectorRowInfo array ClassDefNV(TPCFastSpaceChargeCorrection, 5); }; @@ -307,206 +288,167 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Inline implementations of some methods /// ==================================================== -GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t roc, int32_t row) const +GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t sector, int32_t row) const { /// Gives const pointer to spline const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } -GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t roc, int32_t row) +GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t sector, int32_t row) { /// Gives pointer to spline const RowInfo& rowInfo = mRowInfos[row]; return mScenarioPtr[rowInfo.splineScenarioID]; } -GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t roc, int32_t row, int32_t iSpline) +GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) { /// Gives pointer to spline data const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mRocDataSizeBytes[iSpline] * roc + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + mSectorDataSizeBytes[iSpline] * sector + rowInfo.dataOffsetBytes[iSpline]); } -GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t roc, int32_t row, int32_t iSpline) const +GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) const { /// Gives pointer to spline data const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mRocDataSizeBytes[iSpline] * roc + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + mSectorDataSizeBytes[iSpline] * sector + rowInfo.dataOffsetBytes[iSpline]); } -GPUdi() void TPCFastSpaceChargeCorrection::convUVtoGrid(int32_t roc, int32_t row, float u, float v, float& gu, float& gv) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const { - const auto& info = getRocRowInfo(roc, row); - gu = (u - info.gridU0) * info.scaleUtoGrid; - gv = (v - info.gridV0) * info.scaleVtoGrid; -} + /// convert local y, z to internal grid coordinates u,v + /// return values: u, v, scaling factor + const auto& info = getSectorRowInfo(sector, row); + const SplineType& spline = getSpline(sector, row); -GPUdi() void TPCFastSpaceChargeCorrection::convGridToUV(int32_t roc, int32_t row, float gridU, float gridV, float& u, float& v) const -{ - /// convert internal grid coordinates to u,v - const RocRowInfo& info = getRocRowInfo(roc, row); - u = info.gridU0 + gridU / info.scaleUtoGrid; - v = info.gridV0 + gridV / info.scaleVtoGrid; -} + float u, v; + mGeo.convLocalToUV1(sector, y, z, u, v); -GPUdi() void TPCFastSpaceChargeCorrection::convCorrectedUVtoGrid(int32_t roc, int32_t row, float corrU, float corrV, float& gridU, float& gridV) const -{ - const RocRowInfo& info = getRocRowInfo(roc, row); - gridU = (corrU - info.gridCorrU0) * info.scaleCorrUtoGrid; - gridV = (corrV - info.gridCorrV0) * info.scaleCorrVtoGrid; -} + float scale = 1.f; + if (v < 0.f) { + scale = 0.f; + } else if (v < info.gridV0) { + scale = v / info.gridV0; + } + + float gridU = (u - info.gridU0) * info.scaleUtoGrid; + float gridV = (v - info.gridV0) * info.scaleVtoGrid; -GPUdi() int32_t TPCFastSpaceChargeCorrection::getCorrectionInternal(int32_t roc, int32_t row, float u, float v, float& dx, float& du, float& dv) const -{ - const auto& info = getRocRowInfo(roc, row); - const SplineType& spline = getSpline(roc, row); - const float* splineData = getSplineData(roc, row); - float gridU = 0, gridV = 0; - convUVtoGrid(roc, row, u, v, gridU, gridV); // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - float dxuv[3]; - spline.interpolateU(splineData, gridU, gridV, dxuv); + return {gridU, gridV, scale}; +} - float s = v / info.gridV0; +GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// ccheck if local y, z are inside the grid - if (v >= info.gridV0) { - s = 1.f; - } else if (v <= 0.f) { - s = 0.f; - } + const auto& info = getSectorRowInfo(sector, row); + const SplineType& spline = getSpline(sector, row); - dx = GPUCommonMath::Clamp(s * dxuv[0], info.minCorr[0], info.maxCorr[0]); - du = GPUCommonMath::Clamp(s * dxuv[1], info.minCorr[1], info.maxCorr[1]); - dv = GPUCommonMath::Clamp(s * dxuv[2], info.minCorr[2], info.maxCorr[2]); - return 0; + float u, v; + mGeo.convLocalToUV1(sector, y, z, u, v); + + float gridU = (u - info.gridU0) * info.scaleUtoGrid; + float gridV = (v - info.gridV0) * info.scaleVtoGrid; + + // shrink to the grid area + if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax()) + return false; + if (gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) + return false; + return true; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t roc, int32_t row, float y, float z) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToLocal(int32_t sector, int32_t row, float gridU, float gridV) const { - const auto& info = getRocRowInfo(roc, row); - const SplineType& spline = getSpline(roc, row); - const float* splineData = getSplineData(roc, row); + /// convert internal grid coordinates u,v to local y, z + const SectorRowInfo& info = getSectorRowInfo(sector, row); + float u = info.gridU0 + gridU / info.scaleUtoGrid; + float v = info.gridV0 + gridV / info.scaleVtoGrid; + float y, z; + mGeo.convUVtoLocal1(sector, u, v, y, z); + return {y, z}; +} + +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convCorrectedLocalToGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// convert corrected y, z to the internal grid coordinates + const auto& info = getSectorRowInfo(sector, row); + const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); float u, v; + mGeo.convLocalToUV1(sector, y, z, u, v); + + float scale = 1.f; + if (v < 0.f) { + scale = 0.f; + } else if (v < info.gridCorrV0) { + scale = v / info.gridCorrV0; + } - mGeo.convLocalToUV(roc, y, z, u, v); + float gridU = (u - info.gridCorrU0) * info.scaleCorrUtoGrid; + float gridV = (v - info.gridCorrV0) * info.scaleCorrVtoGrid; - float gridU = 0, gridV = 0; - convUVtoGrid(roc, row, u, v, gridU, gridV); // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - float dxuv[3]; - spline.interpolateU(splineData, gridU, gridV, dxuv); - - float s = v / info.gridV0; + return {gridU, gridV, scale}; +} - if (v >= info.gridV0) { - s = 1.f; - } else if (v <= 0.f) { - s = 0.f; - } +GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const +{ + const auto& info = getSectorRowInfo(sector, row); + const SplineType& spline = getSpline(sector, row); + const float* splineData = getSplineData(sector, row); - float dx = GPUCommonMath::Clamp(s * dxuv[0], info.minCorr[0], info.maxCorr[0]); - float du = GPUCommonMath::Clamp(s * dxuv[1], info.minCorr[1], info.maxCorr[1]); - float dv = GPUCommonMath::Clamp(s * dxuv[2], info.minCorr[2], info.maxCorr[2]); + auto [gridU, gridV, scale] = convLocalToGrid(sector, row, y, z); - float dy, dz; - mGeo.convUVtoLocal(roc, du, dv, dy, dz); + float dxyz[3]; + spline.interpolateU(splineData, gridU, gridV, dxyz); + float dx = scale * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); + float dy = scale * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); + float dz = scale * GPUCommonMath::Clamp(dxyz[2], info.minCorr[2], info.maxCorr[2]); return {dx, dy, dz}; } -GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( - int32_t roc, int32_t row, float corrU, float corrV, float& x) const +GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { - const auto& info = getRocRowInfo(roc, row); - const Spline2D& spline = reinterpret_cast&>(getSpline(roc, row)); - const float* splineData = getSplineData(roc, row, 1); + const auto& info = getSectorRowInfo(sector, row); + const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); + const float* splineData = getSplineData(sector, row, 1); - float gridU, gridV; - convCorrectedUVtoGrid(roc, row, corrU, corrV, gridU, gridV); - - // shrink to the grid area - gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); - gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); + auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); float dx = 0; spline.interpolateU(splineData, gridU, gridV, &dx); - float s = corrV / info.gridCorrV0; - - if (corrV >= info.gridCorrV0) { - s = 1.f; - } else if (corrV <= 0.f) { - s = 0.f; - } - - dx = GPUCommonMath::Clamp(s * dx, info.minCorr[0], info.maxCorr[0]); - x = mGeo.getRowInfo(row).x + dx; + dx = scale * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); + return dx; } -GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( - int32_t roc, int32_t row, float corrU, float corrV, float& nomU, float& nomV) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { - const Spline2D& spline = reinterpret_cast&>(getSpline(roc, row)); - const float* splineData = getSplineData(roc, row, 2); - float gridU, gridV; - convCorrectedUVtoGrid(roc, row, corrU, corrV, gridU, gridV); + auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); - // shrink to the grid area - gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); - gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - - float duv[2]; - spline.interpolateU(splineData, gridU, gridV, duv); - const auto& info = getRocRowInfo(roc, row); - float s = corrV / info.gridCorrV0; + const auto& info = getSectorRowInfo(sector, row); + const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); + const float* splineData = getSplineData(sector, row, 2); - if (corrV >= info.gridCorrV0) { - s = 1.f; - } else if (corrV <= 0.f) { - s = 0.f; - } + float dyz[2]; + spline.interpolateU(splineData, gridU, gridV, dyz); - duv[0] = GPUCommonMath::Clamp(s * duv[0], info.minCorr[1], info.maxCorr[1]); - duv[1] = GPUCommonMath::Clamp(s * duv[1], info.minCorr[2], info.maxCorr[2]); - nomU = corrU - duv[0]; - nomV = corrV - duv[1]; -} + dyz[0] = scale * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); + dyz[1] = scale * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc, int32_t row, float pad) const -{ - const RowActiveArea& area = getRocRowInfo(roc, row).activeArea; - const float* c = area.maxDriftLengthCheb; - float x = -1.f + 2.f * pad / mGeo.getRowInfo(row).maxPad; - float y = c[0] + c[1] * x; - float f0 = 1.f; - float f1 = x; - x *= 2.f; - for (int32_t i = 2; i < 5; i++) { - double f = x * f1 - f0; - y += c[i] * f; - f0 = f1; - f1 = f; - } - return y; -} - -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc, int32_t row) const -{ - return getRocRowInfo(roc, row).activeArea.vMax; -} - -GPUdi() float TPCFastSpaceChargeCorrection::getMaxDriftLength(int32_t roc) const -{ - return getRocInfo(roc).vMax; + return {dyz[0], dyz[1]}; } } // namespace gpu diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h index 97b824aa6da32..fcee61ff09425 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h @@ -49,20 +49,20 @@ class TPCFastSpaceChargeCorrectionMap /// _____________ Constructors / destructors __________________________ /// Default constructor: creates an empty uninitialized object - TPCFastSpaceChargeCorrectionMap(int32_t nRocs, int32_t nRows) + TPCFastSpaceChargeCorrectionMap(int32_t nSectors, int32_t nRows) { - init(nRocs, nRows); + init(nSectors, nRows); } /// Destructor ~TPCFastSpaceChargeCorrectionMap() = default; /// (re-)init the map - void init(int32_t nRocs, int32_t nRows) + void init(int32_t nSectors, int32_t nRows) { - mNrocs = nRocs; + mNsectors = nSectors; mNrows = nRows; - int32_t n = mNrocs * mNrows; + int32_t n = mNsectors * mNrows; fDataPoints.resize(n); for (uint32_t i = 0; i < fDataPoints.size(); ++i) { fDataPoints[i].clear(); @@ -70,30 +70,30 @@ class TPCFastSpaceChargeCorrectionMap } /// Starts the construction procedure, reserves temporary memory - void addCorrectionPoint(int32_t iRoc, int32_t iRow, + void addCorrectionPoint(int32_t iSector, int32_t iRow, double y, double z, double dx, double dy, double dz) { - int32_t ind = mNrows * iRoc + iRow; + int32_t ind = mNrows * iSector + iRow; fDataPoints.at(ind).push_back(CorrectionPoint{y, z, dx, dy, dz}); } - const std::vector& getPoints(int32_t iRoc, int32_t iRow) const + const std::vector& getPoints(int32_t iSector, int32_t iRow) const { - int32_t ind = mNrows * iRoc + iRow; + int32_t ind = mNrows * iSector + iRow; return fDataPoints.at(ind); } - int32_t getNrocs() const { return mNrocs; } + int32_t getNsectors() const { return mNsectors; } int32_t getNrows() const { return mNrows; } - bool isInitialized() const { return mNrocs > 0 && mNrows > 0; } + bool isInitialized() const { return mNsectors > 0 && mNrows > 0; } private: /// _______________ Data members _______________________________________________ - int32_t mNrocs{0}; + int32_t mNsectors{0}; int32_t mNrows{0}; std::vector> fDataPoints; //! (transient!!) points with space charge correction diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 1ecd577eb7dac..03d9eaf43ce9b 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -46,14 +46,14 @@ struct TPCSlowSpaceChargeCorrection { ~TPCSlowSpaceChargeCorrection(); /// getting the corrections for global coordinates - void getCorrections(const float gx, const float gy, const float gz, const int32_t roc, float& gdxC, float& gdyC, float& gdzC) const; + void getCorrections(const float gx, const float gy, const float gz, const int32_t sector, float& gdxC, float& gdyC, float& gdzC) const; o2::tpc::SpaceCharge* mCorr{nullptr}; ///< reference space charge corrections #else ~TPCSlowSpaceChargeCorrection() = default; /// setting dummy corrections for GPU - GPUd() void getCorrections(const float gx, const float gy, const float gz, const int32_t roc, float& gdxC, float& gdyC, float& gdzC) const + GPUd() void getCorrections(const float gx, const float gy, const float gz, const int32_t sector, float& gdxC, float& gdyC, float& gdzC) const { gdxC = 0; gdyC = 0; @@ -182,45 +182,43 @@ class TPCFastTransform : public FlatObject /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a roc + /// Transforms raw TPC coordinates to local XYZ withing a sector /// taking calibration into account. /// - GPUd() void Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; - GPUd() void TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void Transform(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void TransformXYZ(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Transformation in the time frame - GPUd() void TransformInTimeFrame(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const; - GPUd() void TransformInTimeFrame(int32_t roc, float time, float& z, float maxTimeBin) const; + GPUd() void TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const; + GPUd() void TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const; /// Inverse transformation - GPUd() void InverseTransformInTimeFrame(int32_t roc, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const; - GPUd() float InverseTransformInTimeFrame(int32_t roc, float z, float maxTimeBin) const; + GPUd() void InverseTransformInTimeFrame(int32_t sector, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const; + GPUd() float InverseTransformInTimeFrame(int32_t sector, float z, float maxTimeBin) const; /// Inverse transformation: Transformed Y and Z -> transformed X - GPUd() void InverseTransformYZtoX(int32_t roc, int32_t row, float y, float z, float& x, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoX(int32_t sector, int32_t row, float y, float z, float& x, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Inverse transformation: Transformed Y and Z -> Y and Z, transformed w/o space charge correction - GPUd() void InverseTransformYZtoNominalYZ(int32_t roc, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoNominalYZ(int32_t sector, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction - GPUd() void InverseTransformXYZtoNominalXYZ(int32_t roc, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformXYZtoNominalXYZ(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref = nullptr, const TPCFastTransform* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; /// Ideal transformation with Vdrift only - without calibration - GPUd() void TransformIdeal(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; - GPUd() void TransformIdealZ(int32_t roc, float time, float& z, float vertexTime) const; + GPUd() void TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; + GPUd() void TransformIdealZ(int32_t sector, float time, float& z, float vertexTime) const; - GPUd() void convPadTimeToUV(int32_t row, float pad, float time, float& u, float& v, float vertexTime) const; - GPUd() void convPadTimeToUVinTimeFrame(int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const; - GPUd() void convTimeToVinTimeFrame(float time, float& v, float maxTimeBin) const; + GPUd() void convPadTimeToLocal(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float vertexTime) const; + GPUd() void convPadTimeToLocalInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float maxTimeBin) const; - GPUd() void convUVtoPadTime(int32_t row, float u, float v, float& pad, float& time, float vertexTime) const; - GPUd() void convUVtoPadTimeInTimeFrame(int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const; - GPUd() void convVtoTime(float v, float& time, float vertexTime) const; + GPUd() void convLocalToPadTime(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float vertexTime) const; + GPUd() void convLocalToPadTimeInTimeFrame(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float maxTimeBin) const; - GPUd() float convTimeToZinTimeFrame(int32_t roc, float time, float maxTimeBin) const; - GPUd() float convZtoTimeInTimeFrame(int32_t roc, float z, float maxTimeBin) const; - GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const; - GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t roc, float deltaZ) const; + GPUd() float convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const; + GPUd() float convZtoTimeInTimeFrame(int32_t sector, float z, float maxTimeBin) const; + GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t sector, float deltaTime) const; + GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t sector, float deltaZ) const; GPUd() float convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const; GPUd() float convZOffsetToVertexTime(int32_t sector, float zOffset, float maxTimeBin) const; GPUd() float convVertexTimeToZOffset(int32_t sector, float vertexTime, float maxTimeBin) const; @@ -265,13 +263,13 @@ class TPCFastTransform : public FlatObject GPUd() float getLumiScaleFactor() const { return mLumiScaleFactor; } /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t roc, int32_t row, float pad) const; + GPUd() float getMaxDriftTime(int32_t sector, int32_t row, float pad) const; /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t roc, int32_t row) const; + GPUd() float getMaxDriftTime(int32_t sector, int32_t row) const; /// maximal possible drift time of the active area - GPUd() float getMaxDriftTime(int32_t roc) const; + GPUd() float getMaxDriftTime(int32_t sector) const; #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) @@ -292,6 +290,8 @@ class TPCFastTransform : public FlatObject /// Print method void print() const; + GPUd() float convDriftLengthToTime(float driftLength, float vertexTime) const; + private: /// Enumeration of possible initialization states enum ConstructionExtraState : uint32_t { @@ -335,7 +335,7 @@ class TPCFastTransform : public FlatObject /// Correction of (x,u,v) with tricubic interpolator on a regular grid TPCSlowSpaceChargeCorrection* mCorrectionSlow{nullptr}; ///< reference space charge corrections - GPUd() void TransformLocal(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; + GPUd() void TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; ClassDefNV(TPCFastTransform, 4); }; @@ -344,27 +344,22 @@ class TPCFastTransform : public FlatObject // Inline implementations of some methods // ======================================================================= -GPUdi() void TPCFastTransform::convPadTimeToUV(int32_t row, float pad, float time, float& u, float& v, float vertexTime) const -{ - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - float x = rowInfo.x; - u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - v = (time - mT0 - vertexTime) * (mVdrift); // drift length cm -} +// ---------------------------------------------------------------------- -GPUdi() void TPCFastTransform::convTimeToVinTimeFrame(float time, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convPadTimeToLocal(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float vertexTime) const { - v = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm - v += getGeometry().getTPCzLength(); + float l = (time - mT0 - vertexTime) * mVdrift; // drift length [cm] + std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); } -GPUdi() void TPCFastTransform::convPadTimeToUVinTimeFrame(int32_t row, float pad, float time, float& u, float& v, float maxTimeBin) const +GPUdi() void TPCFastTransform::convPadTimeToLocalInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float maxTimeBin) const { - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - convTimeToVinTimeFrame(time, v, maxTimeBin); + float l = getGeometry().getTPCzLength() + (time - mT0 - maxTimeBin) * mVdrift; // drift length [cm] + std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); } +// ---------------------------------------------------------------------- + GPUdi() float TPCFastTransform::convZOffsetToVertexTime(int32_t sector, float zOffset, float maxTimeBin) const { if (sector < getGeometry().getNumberOfSectorsA()) { @@ -383,27 +378,30 @@ GPUdi() float TPCFastTransform::convVertexTimeToZOffset(int32_t sector, float ve } } -GPUdi() void TPCFastTransform::convUVtoPadTime(int32_t row, float u, float v, float& pad, float& time, float vertexTime) const +GPUdi() float TPCFastTransform::convDriftLengthToTime(float driftLength, float vertexTime) const { - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; - time = mT0 + vertexTime + v / mVdrift; + return (mT0 + vertexTime + driftLength / mVdrift); } -GPUdi() void TPCFastTransform::convVtoTime(float v, float& time, float vertexTime) const +// ---------------------------------------------------------------------- + +GPUdi() void TPCFastTransform::convLocalToPadTime(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float vertexTime) const { - time = mT0 + vertexTime + v / mVdrift; + float l; + std::tie(pad, l) = getGeometry().convLocalToPadDriftLength(sector, row, y, z); + time = convDriftLengthToTime(l, vertexTime); } -GPUdi() void TPCFastTransform::convUVtoPadTimeInTimeFrame(int32_t row, float u, float v, float& pad, float& time, float maxTimeBin) const +GPUdi() void TPCFastTransform::convLocalToPadTimeInTimeFrame(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float maxTimeBin) const { - v -= getGeometry().getTPCzLength(); - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; - time = mT0 + maxTimeBin + v / mVdrift; + float l; + std::tie(pad, l) = getGeometry().convLocalToPadDriftLength(sector, row, y, z); + time = convDriftLengthToTime(l, maxTimeBin); } -GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +// ---------------------------------------------------------------------- + +GPUdi() void TPCFastTransform::TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); @@ -417,29 +415,29 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x #ifndef GPUCA_GPUCODE if (mCorrectionSlow) { float gx, gy, gz; - getGeometry().convLocalToGlobal(roc, x, y, z, gx, gy, gz); + getGeometry().convLocalToGlobal(sector, x, y, z, gx, gy, gz); float gdxC, gdyC, gdzC; - mCorrectionSlow->getCorrections(gx, gy, gz, roc, gdxC, gdyC, gdzC); - getGeometry().convGlobalToLocal(roc, gdxC, gdyC, gdzC, dx, dy, dz); + mCorrectionSlow->getCorrections(gx, gy, gz, sector, gdxC, gdyC, gdzC); + getGeometry().convGlobalToLocal(sector, gdxC, gdyC, gdzC, dx, dy, dz); } else #endif // GPUCA_GPUCODE { - std::tie(dx, dy, dz) = mCorrection.getCorrectionLocal(roc, row, y, z); + std::tie(dx, dy, dz) = mCorrection.getCorrectionLocal(sector, row, y, z); if (ref) { if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested - auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(sector, row, y, z); dx = (dx - dxRef) * scale + dxRef; dy = (dy - dyRef) * scale + dyRef; dz = (dz - dzRef) * scale + dzRef; } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { - auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(sector, row, y, z); dx = dxRef * scale + dx; dy = dyRef * scale + dy; dz = dzRef * scale + dz; } } if (ref2 && (scale2 != 0)) { - auto [dxRef, dyRef, dzRef] = ref2->mCorrection.getCorrectionLocal(roc, row, y, z); + auto [dxRef, dyRef, dzRef] = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); dx = dxRef * scale2 + dx; dy = dyRef * scale2 + dy; dz = dzRef * scale2 + dz; @@ -451,37 +449,37 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x float lx = x, ly = y, lz = z; float gx, gy, gz; - getGeometry().convLocalToGlobal(roc, lx, ly, lz, gx, gy, gz); + getGeometry().convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); float lxT = lx + dx; float lyT = ly + dy; float lzT = lz + dz; float invYZtoXScaled; - InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoX(sector, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); float invYZtoX; - InverseTransformYZtoX(roc, row, lyT, lzT, invYZtoX); + InverseTransformYZtoX(sector, row, lyT, lzT, invYZtoX); float YZtoNominalY; float YZtoNominalZ; - InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); + InverseTransformYZtoNominalYZ(sector, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); float YZtoNominalYScaled; float YZtoNominalZScaled; - InverseTransformYZtoNominalYZ(roc, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(sector, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); float dxRef = 0.f, dyRef = 0.f, dzRef = 0.f; if (ref) { - std::tie(dxRef, dyRef, dzRef) = ref->mCorrection.getCorrectionLocal(roc, row, y, z); + std::tie(dxRef, dyRef, dzRef) = ref->mCorrection.getCorrectionLocal(sector, row, y, z); } - float dxRef2 = 0.f, duRef2 = 0.f, dvRef2 = 0.f; + float dxRef2 = 0.f, dyRef2 = 0.f, dzRef2 = 0.f; if (ref2) { - std::tie(dxRef2, duRef2, dvRef2) = ref2->mCorrection.getCorrectionLocal(roc, row, y, z); + std::tie(dxRef2, dyRef2, dzRef2) = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); } - auto [dxOrig, dyOrig, dzOrig] = mCorrection.getCorrectionLocal(roc, row, y, z); + auto [dxOrig, dyOrig, dzOrig] = mCorrection.getCorrectionLocal(sector, row, y, z); o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() // corrections in x, u, v @@ -498,7 +496,7 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x << "dy=" << dy << "dz=" << dz << "row=" << row - << "roc=" << roc + << "sector=" << sector << "scale=" << scale << "scale2=" << scale2 // original local coordinates @@ -529,38 +527,34 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t roc, int32_t row, float& x z += dz; } -GPUdi() void TPCFastTransform::TransformXYZ(int32_t roc, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::TransformXYZ(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { - TransformLocal(roc, row, x, y, z, ref, ref2, scale, scale2, scaleMode); + TransformLocal(sector, row, x, y, z, ref, ref2, scale, scale2, scaleMode); } -GPUdi() void TPCFastTransform::Transform(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::Transform(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a roc + /// Transforms raw TPC coordinates to local XYZ withing a sector /// taking calibration into account. /// const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); x = rowInfo.x; - float u = 0, v = 0; - convPadTimeToUV(row, pad, time, u, v, vertexTime); - getGeometry().convUVtoLocal(roc, u, v, y, z); - - TransformLocal(roc, row, x, y, z, ref, ref2, scale, scale2, scaleMode); + convPadTimeToLocal(sector, row, pad, time, y, z, vertexTime); + TransformLocal(sector, row, x, y, z, ref, ref2, scale, scale2, scaleMode); } -GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, float time, float& z, float maxTimeBin) const +GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const { - float v = 0; - convTimeToVinTimeFrame(time, v, maxTimeBin); - getGeometry().convVtoLocal(roc, v, z); + float l = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm + z = getGeometry().convDriftLengthToLocal(sector, l); } -GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const +GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const { /// _______________ Special cluster transformation for a time frame _______________________ /// @@ -570,58 +564,50 @@ GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t roc, int32_t row, fl const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); x = rowInfo.x; - float u = 0, v = 0; - convPadTimeToUVinTimeFrame(row, pad, time, u, v, maxTimeBin); - getGeometry().convUVtoLocal(roc, u, v, y, z); + convPadTimeToLocalInTimeFrame(sector, row, pad, time, y, z, maxTimeBin); } -GPUdi() void TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const +GPUdi() void TPCFastTransform::InverseTransformInTimeFrame(int32_t sector, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const { /// Inverse transformation to TransformInTimeFrame - float u = 0, v = 0; - getGeometry().convLocalToUV(roc, y, z, u, v); - convUVtoPadTimeInTimeFrame(row, u, v, pad, time, maxTimeBin); + convLocalToPadTimeInTimeFrame(sector, row, y, z, pad, time, maxTimeBin); } -GPUdi() float TPCFastTransform::InverseTransformInTimeFrame(int32_t roc, float z, float maxTimeBin) const +GPUdi() float TPCFastTransform::InverseTransformInTimeFrame(int32_t sector, float z, float maxTimeBin) const { float pad, time; - InverseTransformInTimeFrame(roc, 0, 0, 0, z, pad, time, maxTimeBin); + InverseTransformInTimeFrame(sector, 0, 0, 0, z, pad, time, maxTimeBin); return time; } -GPUdi() void TPCFastTransform::TransformIdealZ(int32_t roc, float time, float& z, float vertexTime) const +GPUdi() void TPCFastTransform::TransformIdealZ(int32_t sector, float time, float& z, float vertexTime) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms time TPC coordinates to local Z withing a roc + /// Transforms time TPC coordinates to local Z withing a sector /// Ideal transformation: only Vdrift from DCS. /// No space charge corrections, no time of flight correction /// - float v = (time - mT0 - vertexTime) * mVdrift; // drift length cm - getGeometry().convVtoLocal(roc, v, z); + float l = (time - mT0 - vertexTime) * mVdrift; // drift length cm + z = getGeometry().convDriftLengthToLocal(sector, l); } -GPUdi() void TPCFastTransform::TransformIdeal(int32_t roc, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const +GPUdi() void TPCFastTransform::TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const { /// _______________ The main method: cluster transformation _______________________ /// - /// Transforms raw TPC coordinates to local XYZ withing a roc + /// Transforms raw TPC coordinates to local XYZ withing a sector /// Ideal transformation: only Vdrift from DCS. /// No space charge corrections, no time of flight correction /// - const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); - - x = rowInfo.x; - float u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; - float v = (time - mT0 - vertexTime) * mVdrift; // drift length cm - - getGeometry().convUVtoLocal(roc, u, v, y, z); + x = getGeometry().getRowInfo(row).x; + float driftLength = (time - mT0 - vertexTime) * mVdrift; // drift length cm + std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); } -GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t roc, float time, float maxTimeBin) const +GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const { /// _______________ Special cluster transformation for a time frame _______________________ /// @@ -631,21 +617,21 @@ GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t roc, float time, /// float v = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm - float z = (roc < getGeometry().getNumberOfRocsA()) ? -v : v; + float z = (sector < getGeometry().getNumberOfSectorsA()) ? -v : v; return z; } -GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t roc, float z, float maxTimeBin) const +GPUdi() float TPCFastTransform::convZtoTimeInTimeFrame(int32_t sector, float z, float maxTimeBin) const { /// Inverse transformation of convTimeToZinTimeFrame() - float v = (roc < getGeometry().getNumberOfRocsA()) ? -z : z; + float v = (sector < getGeometry().getNumberOfSectorsA()) ? -z : z; return mT0 + maxTimeBin + v / mVdrift; } -GPUdi() float TPCFastTransform::convDeltaTimeToDeltaZinTimeFrame(int32_t roc, float deltaTime) const +GPUdi() float TPCFastTransform::convDeltaTimeToDeltaZinTimeFrame(int32_t sector, float deltaTime) const { float deltaZ = deltaTime * mVdrift; - return roc < getGeometry().getNumberOfRocsA() ? -deltaZ : deltaZ; + return sector < getGeometry().getNumberOfSectorsA() ? -deltaZ : deltaZ; } GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const @@ -653,140 +639,115 @@ GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ return deltaZ / mVdrift; } -GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrame(int32_t roc, float deltaZ) const +GPUdi() float TPCFastTransform::convDeltaZtoDeltaTimeInTimeFrame(int32_t sector, float deltaZ) const { float deltaT = deltaZ / mVdrift; - return roc < getGeometry().getNumberOfRocsA() ? -deltaT : deltaT; + return sector < getGeometry().getNumberOfSectorsA() ? -deltaT : deltaT; } -/* -GPUdi() float TPCFastTransform::getLastCalibratedTimeBin(int32_t roc) const -{ - /// Return a value of the last timebin where correction map is valid - float u, v, pad, time; - getGeometry().convScaledUVtoUV(roc, 0, 0.f, 1.f, u, v); - convUVtoPadTime(roc, 0, u, v, pad, time, 0); - return time; -} -*/ - -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row, float pad) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t sector, int32_t row, float pad) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(roc, row, pad); - return mT0 + maxL / mVdrift; + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); } -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc, int32_t row) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t sector, int32_t row) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(roc, row); - float maxTime = 0.f; - convVtoTime(maxL, maxTime, 0.f); - return maxTime; + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); } -GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t roc) const +GPUdi() float TPCFastTransform::getMaxDriftTime(int32_t sector) const { /// maximal possible drift time of the active area - float maxL = mCorrection.getMaxDriftLength(roc); - float maxTime = 0.f; - convVtoTime(maxL, maxTime, 0.f); - return maxTime; + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); } -GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t roc, int32_t row, float y, float z, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformYZtoX(int32_t sector, int32_t row, float realY, float realZ, float& realX, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); /// Transformation y,z -> x - float u = 0, v = 0; - getGeometry().convLocalToUV(roc, y, z, u, v); + + float dx = 0.f; + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { - mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, x); + dx = mCorrection.getCorrectionXatRealYZ(sector, row, realY, realZ); if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { - float xr; - ref->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); - x = (x - xr) * scale + xr; + float dxref = ref->mCorrection.getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = (dx - dxref) * scale + dxref; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { - float xr; - ref->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); - x = (xr - getGeometry().getRowInfo(row).x) * scale + x; // xr=mGeo.getRowInfo(row).x + dx; + float dxref = ref->mCorrection.getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = dxref * scale + dx; } } if (ref2 && (scale2 != 0)) { - float xr; - ref2->mCorrection.getCorrectionInvCorrectedX(roc, row, u, v, xr); - x = (xr - getGeometry().getRowInfo(row).x) * scale2 + x; // xr=mGeo.getRowInfo(row).x + dx; + float dxref = ref2->mCorrection.getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = dxref * scale2 + dx; } - } else { - x = mCorrection.getGeometry().getRowInfo(row).x; // corrections are disabled } + + realX = mCorrection.getGeometry().getRowInfo(row).x + dx; + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoX").data() - << "roc=" << roc + << "sector=" << sector << "row=" << row << "scale=" << scale - << "y=" << y - << "z=" << z - << "x=" << x - << "v=" << v - << "u=" << u + << "y=" << realY + << "z=" << realZ + << "x=" << realX << "\n"; }) } -GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t roc, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t sector, int32_t row, float realY, float realZ, float& measuredY, float& measuredZ, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { + /// Transformation real y,z -> measured y,z + GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); - /// Transformation y,z -> x - float u = 0, v = 0, un = 0, vn = 0; - getGeometry().convLocalToUV(roc, y, z, u, v); + + float dy = 0; + float dz = 0; + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { - mCorrection.getCorrectionInvUV(roc, row, u, v, un, vn); + std::tie(dy, dz) = mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { - float unr = 0, vnr = 0; - ref->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); - un = (un - unr) * scale + unr; - vn = (vn - vnr) * scale + vnr; + auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = (dy - dyRef) * scale + dyRef; + dz = (dz - dzRef) * scale + dzRef; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { - float unr = 0, vnr = 0; - ref->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); - un = (unr - u) * scale + un; // unr = u - duv[0]; - vn = (vnr - v) * scale + vn; + auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = dyRef * scale + dy; + dz = dzRef * scale + dz; } if (ref2 && (scale2 != 0)) { - float unr = 0, vnr = 0; - ref2->mCorrection.getCorrectionInvUV(roc, row, u, v, unr, vnr); - un = (unr - u) * scale2 + un; // unr = u - duv[0]; - vn = (vnr - v) * scale2 + vn; + auto [dyRef, dzRef] = ref2->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = dyRef * scale2 + dy; + dz = dzRef * scale2 + dz; } } - } else { - un = u; - vn = v; } - getGeometry().convUVtoLocal(roc, un, vn, ny, nz); + + measuredY = realY - dy; + measuredZ = realZ - dz; GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoNominalYZ").data() - << "roc=" << roc + << "sector=" << sector << "row=" << row << "scale=" << scale - << "y=" << y - << "z=" << z - << "ny=" << ny - << "nz=" << nz - << "u=" << u - << "v=" << v - << "un=" << un - << "vn=" << vn + << "real y=" << realY + << "real z=" << realZ + << "measured y=" << measuredY + << "measured z=" << measuredZ << "\n"; }) } -GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t roc, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const +GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const { /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction int32_t row2 = row + 1; @@ -797,8 +758,8 @@ GPUdi() void TPCFastTransform::InverseTransformXYZtoNominalXYZ(int32_t roc, int3 float nx2, ny2, nz2; // nominal coordinates for row2 nx1 = getGeometry().getRowInfo(row).x; nx2 = getGeometry().getRowInfo(row2).x; - InverseTransformYZtoNominalYZ(roc, row, y, z, ny1, nz1, ref, ref2, scale, scale2, scaleMode); - InverseTransformYZtoNominalYZ(roc, row2, y, z, ny2, nz2, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(sector, row, y, z, ny1, nz1, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(sector, row2, y, z, ny2, nz2, ref, ref2, scale, scale2, scaleMode); float c1 = (nx2 - nx) / (nx2 - nx1); float c2 = (nx - nx1) / (nx2 - nx1); nx = x; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index c8982f05d4730..e7e026f464818 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -28,14 +28,14 @@ using namespace o2::gpu; TPCFastTransformGeo::TPCFastTransformGeo() { // Default Constructor: creates an empty uninitialized object - double dAlpha = 2. * M_PI / (NumberOfRocsA); - for (int32_t i = 0; i < NumberOfRocs; i++) { - RocInfo& s = mRocInfos[i]; + double dAlpha = 2. * M_PI / (NumberOfSectorsA); + for (int32_t i = 0; i < NumberOfSectors; i++) { + SectorInfo& s = mSectorInfos[i]; double alpha = dAlpha * (i + 0.5); s.sinAlpha = sin(alpha); s.cosAlpha = cos(alpha); } - mRocInfos[NumberOfRocs] = RocInfo{}; + mSectorInfos[NumberOfSectors] = SectorInfo{}; for (int32_t i = 0; i < MaxNumberOfRows + 1; i++) { mRowInfos[i] = RowInfo{}; @@ -84,7 +84,7 @@ void TPCFastTransformGeo::setTPCrow(int32_t iRow, float x, int32_t nPads, float // Make scaled U = area between the geometrical sector borders - const double sectorAngle = 2. * M_PI / NumberOfRocsA; + const double sectorAngle = 2. * M_PI / NumberOfSectorsA; const double scaleXtoRowWidth = 2. * tan(0.5 * sectorAngle); double uWidth = x * scaleXtoRowWidth; // distance to the sector border @@ -99,8 +99,8 @@ void TPCFastTransformGeo::finishConstruction() { /// Finishes initialization: puts everything to the flat buffer, releases temporary memory - assert(mConstructionMask & ConstructionState::InProgress); // construction in process - assert(mConstructionMask & ConstructionState::GeometryIsSet); // geometry is set + assert(mConstructionMask & ConstructionState::InProgress); // construction in process + assert(mConstructionMask & ConstructionState::GeometryIsSet); // geometry is set for (int32_t i = 0; i < mNumberOfRows; i++) { // all TPC rows are initialized assert(getRowInfo(i).maxPad > 0); @@ -123,7 +123,7 @@ void TPCFastTransformGeo::print() const #endif } -int32_t TPCFastTransformGeo::test(int32_t roc, int32_t row, float ly, float lz) const +int32_t TPCFastTransformGeo::test(int32_t sector, int32_t row, float ly, float lz) const { /// Check consistency of the class @@ -139,46 +139,21 @@ int32_t TPCFastTransformGeo::test(int32_t roc, int32_t row, float ly, float lz) float lx1 = 0.f, ly1 = 0.f, lz1 = 0.f; float gx = 0.f, gy = 0.f, gz = 0.f; - convLocalToGlobal(roc, lx, ly, lz, gx, gy, gz); - convGlobalToLocal(roc, gx, gy, gz, lx1, ly1, lz1); + convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); + convGlobalToLocal(sector, gx, gy, gz, lx1, ly1, lz1); if (fabs(lx1 - lx) > 1.e-4 || fabs(ly1 - ly) > 1.e-4 || fabs(lz1 - lz) > 1.e-7) { LOG(info) << "Error local <-> global: x " << lx << " dx " << lx1 - lx << " y " << ly << " dy " << ly1 - ly << " z " << lz << " dz " << lz1 - lz; error = -3; } - float u = 0.f, v = 0.f; - convLocalToUV(roc, ly, lz, u, v); - convUVtoLocal(roc, u, v, ly1, lz1); - if (fabs(ly1 - ly) + fabs(lz1 - lz) > 1.e-6) { - LOG(info) << "Error local <-> UV: y " << ly << " dy " << ly1 - ly << " z " << lz << " dz " << lz1 - lz; + auto [pad, length] = convLocalToPadDriftLength(sector, 10, ly, lz); + auto [ly2, lz2] = convPadDriftLengthToLocal(sector, 10, pad, length); + + if (fabs(ly2 - ly) + fabs(lz2 - lz) > 1.e-6) { + LOG(info) << "Error local <-> UV: y " << ly << " dy " << ly2 - ly << " z " << lz << " dz " << lz2 - lz; error = -4; } - /* - float su = 0.f, sv = 0.f; - - convUVtoScaledUV(roc, row, u, v, su, sv); - - if (su < 0.f || su > 1.f) { - LOG(info) << "Error scaled U range: u " << u << " su " << su; - error = -5; - } - - float u1 = 0.f, v1 = 0.f; - convScaledUVtoUV(roc, row, su, sv, u1, v1); - - if (fabs(u1 - u) > 1.e-4 || fabs(v1 - v) > 1.e-4) { - LOG(info) << "Error UV<->scaled UV: u " << u << " du " << u1 - u << " v " << v << " dv " << v1 - v; - error = -6; - } - */ - float pad = convUtoPad(row, u); - float u1 = convPadToU(row, pad); - - if (fabs(u1 - u) > 1.e-5) { - LOG(info) << "Error U<->Pad: u " << u << " pad " << pad << " du " << u1 - u; - error = -7; - } #if !defined(GPUCA_GPUCODE) if (error != 0) { diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index a5d642158cd8f..4072435e948a5 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -34,11 +34,11 @@ namespace gpu class TPCFastTransformGeo { public: - /// The struct contains necessary info for TPC ROC - struct RocInfo { + /// The struct contains necessary info for TPC sector + struct SectorInfo { float sinAlpha{0.f}; ///< sin of the angle between the local x and the global x float cosAlpha{0.f}; ///< cos of the angle between the local x and the global x - ClassDefNV(RocInfo, 1); + ClassDefNV(SectorInfo, 1); }; /// The struct contains necessary info about TPC padrow @@ -54,6 +54,15 @@ class TPCFastTransformGeo /// get U max GPUd() float getUmax() const { return -u0; } + /// get Y min + GPUd() float getYmin() const { return u0; } + + /// get Y max + GPUd() float getYmax() const { return -u0; } + + /// get Y range + GPUd() std::tuple getYrange() const { return {getYmin(), getYmax()}; } + /// get width in U GPUd() float getUwidth() const { return -2.f * u0; } @@ -81,7 +90,7 @@ class TPCFastTransformGeo /// _______________ Construction interface ________________________ - /// Starts the initialization procedure, reserves temporary memory + /// Starts the initialization psectoredure, reserves temporary memory void startConstruction(int32_t numberOfRows); /// Initializes a TPC row @@ -100,11 +109,11 @@ class TPCFastTransformGeo /// _______________ Getters _________________________________ - /// Gives number of TPC ROCs - GPUd() static constexpr int32_t getNumberOfRocs() { return NumberOfRocs; } + /// Gives number of TPC sectors + GPUd() static constexpr int32_t getNumberOfSectors() { return NumberOfSectors; } - /// Gives number of TPC ROCs on the A side - GPUd() static constexpr int32_t getNumberOfRocsA() { return NumberOfRocsA; } + /// Gives number of TPC sectors on the A side + GPUd() static constexpr int32_t getNumberOfSectorsA() { return NumberOfSectorsA; } /// Gives number of TPC rows GPUd() int32_t getNumberOfRows() const { return mNumberOfRows; } @@ -112,8 +121,8 @@ class TPCFastTransformGeo /// Gives number of TPC rows GPUd() static constexpr int getMaxNumberOfRows() { return MaxNumberOfRows; } - /// Gives roc info - GPUd() const RocInfo& getRocInfo(int32_t roc) const; + /// Gives sector info + GPUd() const SectorInfo& getSectorInfo(int32_t sector) const; /// Gives TPC row info GPUd() const RowInfo& getRowInfo(int32_t row) const; @@ -121,20 +130,31 @@ class TPCFastTransformGeo /// Gives Z length of the TPC, one Z side GPUd() float getTPCzLength() const { return mTPCzLength; } + /// Gives Z range for the corresponding TPC side + GPUd() std::tuple getZrange(int32_t sector) const; + /// _______________ Conversion of coordinate systems __________ /// convert Local -> Global c.s. - GPUd() void convLocalToGlobal(int32_t roc, float lx, float ly, float lz, float& gx, float& gy, float& gz) const; + GPUd() void convLocalToGlobal(int32_t sector, float lx, float ly, float lz, float& gx, float& gy, float& gz) const; /// convert Global->Local c.s. - GPUd() void convGlobalToLocal(int32_t roc, float gx, float gy, float gz, float& lx, float& ly, float& lz) const; + GPUd() void convGlobalToLocal(int32_t sector, float gx, float gy, float gz, float& lx, float& ly, float& lz) const; + + /// convert Pad, DriftLength -> Local c.s. + GPUd() std::tuple convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const; + + /// convert DriftLength -> Local c.s. + GPUd() float convDriftLengthToLocal(int32_t sector, float driftLength) const; + + /// convert Local c.s. -> Pad, DriftLength + GPUd() std::tuple convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const; /// convert UV -> Local c.s. - GPUd() void convUVtoLocal(int32_t roc, float u, float v, float& y, float& z) const; - GPUd() void convVtoLocal(int32_t roc, float v, float& z) const; + GPUd() void convUVtoLocal1(int32_t sector, float u, float v, float& y, float& z) const; /// convert Local-> UV c.s. - GPUd() void convLocalToUV(int32_t roc, float y, float z, float& u, float& v) const; + GPUd() void convLocalToUV1(int32_t sector, float y, float z, float& u, float& v) const; /// convert Pad coordinate -> U GPUd() float convPadToU(int32_t row, float pad) const; @@ -146,7 +166,7 @@ class TPCFastTransformGeo void print() const; /// Method for testing consistency - int32_t test(int32_t roc, int32_t row, float ly, float lz) const; + int32_t test(int32_t sector, int32_t row, float ly, float lz) const; /// Method for testing consistency int32_t test() const; @@ -154,9 +174,9 @@ class TPCFastTransformGeo private: /// _______________ Data members _______________________________________________ - static constexpr int32_t NumberOfRocs = 36; ///< Number of TPC rocs ( roc = inner + outer sector ) - static constexpr int32_t NumberOfRocsA = NumberOfRocs / 2; ///< Number of TPC rocs side A - static constexpr int32_t MaxNumberOfRows = 160; ///< Max Number of TPC rows in a roc + static constexpr int32_t NumberOfSectors = 36; ///< Number of TPC sectors ( sector = inner + outer sector ) + static constexpr int32_t NumberOfSectorsA = NumberOfSectors / 2; ///< Number of TPC sectors side A + static constexpr int32_t MaxNumberOfRows = 160; ///< Max Number of TPC rows in a sector /// _______________ Construction control _______________________________________________ @@ -172,10 +192,10 @@ class TPCFastTransformGeo /// _______________ Geometry _______________________________________________ - int32_t mNumberOfRows = 0; ///< Number of TPC rows. It is different for the Run2 and the Run3 setups - float mTPCzLength = 0.f; ///< Z length of one TPC side (A or C) + int32_t mNumberOfRows = 0; ///< Number of TPC rows. It is different for the Run2 and the Run3 setups + float mTPCzLength = 0.f; ///< Z length of one TPC side (A or C) - RocInfo mRocInfos[NumberOfRocs + 1]; ///< array of roc information [fixed size] + SectorInfo mSectorInfos[NumberOfSectors + 1]; ///< array of sector information [fixed size] RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] ClassDefNV(TPCFastTransformGeo, 3); @@ -185,13 +205,13 @@ class TPCFastTransformGeo // Inline implementations of some methods // ======================================================================= -GPUdi() const TPCFastTransformGeo::RocInfo& TPCFastTransformGeo::getRocInfo(int32_t roc) const +GPUdi() const TPCFastTransformGeo::SectorInfo& TPCFastTransformGeo::getSectorInfo(int32_t sector) const { - /// Gives roc info - if (roc < 0 || roc >= NumberOfRocs) { // return zero object - roc = NumberOfRocs; + /// Gives sector info + if (sector < 0 || sector >= NumberOfSectors) { // return zero object + sector = NumberOfSectors; } - return mRocInfos[roc]; + return mSectorInfos[sector]; } GPUdi() const TPCFastTransformGeo::RowInfo& TPCFastTransformGeo::getRowInfo(int32_t row) const @@ -203,55 +223,93 @@ GPUdi() const TPCFastTransformGeo::RowInfo& TPCFastTransformGeo::getRowInfo(int3 return mRowInfos[row]; } -GPUdi() void TPCFastTransformGeo::convLocalToGlobal(int32_t roc, float lx, float ly, float lz, float& gx, float& gy, float& gz) const +GPUdi() void TPCFastTransformGeo::convLocalToGlobal(int32_t sector, float lx, float ly, float lz, float& gx, float& gy, float& gz) const { /// convert Local -> Global c.s. - const RocInfo& rocInfo = getRocInfo(roc); - gx = lx * rocInfo.cosAlpha - ly * rocInfo.sinAlpha; - gy = lx * rocInfo.sinAlpha + ly * rocInfo.cosAlpha; + const SectorInfo& sectorInfo = getSectorInfo(sector); + gx = lx * sectorInfo.cosAlpha - ly * sectorInfo.sinAlpha; + gy = lx * sectorInfo.sinAlpha + ly * sectorInfo.cosAlpha; gz = lz; } -GPUdi() void TPCFastTransformGeo::convGlobalToLocal(int32_t roc, float gx, float gy, float gz, float& lx, float& ly, float& lz) const +GPUdi() void TPCFastTransformGeo::convGlobalToLocal(int32_t sector, float gx, float gy, float gz, float& lx, float& ly, float& lz) const { /// convert Global -> Local c.s. - const RocInfo& rocInfo = getRocInfo(roc); - lx = gx * rocInfo.cosAlpha + gy * rocInfo.sinAlpha; - ly = -gx * rocInfo.sinAlpha + gy * rocInfo.cosAlpha; + const SectorInfo& sectorInfo = getSectorInfo(sector); + lx = gx * sectorInfo.cosAlpha + gy * sectorInfo.sinAlpha; + ly = -gx * sectorInfo.sinAlpha + gy * sectorInfo.cosAlpha; lz = gz; } -GPUdi() void TPCFastTransformGeo::convVtoLocal(int32_t roc, float v, float& lz) const +GPUdi() std::tuple TPCFastTransformGeo::convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const { - /// convert UV -> Local c.s. - if (roc < NumberOfRocsA) { // TPC side A - lz = mTPCzLength - v; - } else { // TPC side C - lz = v - mTPCzLength; // drift direction is mirrored on C-side + /// convert Pad, DriftLength -> Local c.s. + const RowInfo& rowInfo = getRowInfo(row); + float u = (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; + float y, z; + if (sector < NumberOfSectorsA) { // TPC side A + y = u; + z = mTPCzLength - driftLength; + } else { // TPC side C + y = -u; // pads are mirrorred on C-side + z = driftLength - mTPCzLength; // drift direction is mirrored on C-side } + return {y, z}; } -GPUdi() void TPCFastTransformGeo::convUVtoLocal(int32_t roc, float u, float v, float& ly, float& lz) const +GPUdi() float TPCFastTransformGeo::convDriftLengthToLocal(int32_t sector, float driftLength) const +{ + /// convert DriftLength -> Local c.s. + return (sector < NumberOfSectorsA) ? (mTPCzLength - driftLength) : (driftLength - mTPCzLength); +} + +GPUdi() void TPCFastTransformGeo::convUVtoLocal1(int32_t sector, float u, float v, float& ly, float& lz) const { /// convert UV -> Local c.s. - if (roc < NumberOfRocsA) { // TPC side A + if (sector < NumberOfSectorsA) { // TPC side A ly = u; lz = mTPCzLength - v; - } else { // TPC side C - ly = -u; // pads are mirrorred on C-side - lz = v - mTPCzLength; // drift direction is mirrored on C-side + } else { // TPC side C + ly = -u; // pads are mirrorred on C-side + lz = v - mTPCzLength; // drift direction is mirrored on C-side + } +} + +GPUdi() std::tuple TPCFastTransformGeo::getZrange(int32_t sector) const +{ + /// z range for the sector + if (sector < NumberOfSectorsA) { // TPC side A + return {0.f, mTPCzLength}; + } else { // TPC side C + return {-mTPCzLength, 0.f}; + } +} + +GPUdi() std::tuple TPCFastTransformGeo::convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const +{ + /// convert Local c.s. -> Pad, DriftLength + float u, l; + if (sector < NumberOfSectorsA) { // TPC side A + u = y; + l = mTPCzLength - z; + } else { // TPC side C + u = -y; // pads are mirrorred on C-side + l = z + mTPCzLength; // drift direction is mirrored on C-side } + const TPCFastTransformGeo::RowInfo& rowInfo = getRowInfo(row); + float pad = u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; + return {pad, l}; } -GPUdi() void TPCFastTransformGeo::convLocalToUV(int32_t roc, float ly, float lz, float& u, float& v) const +GPUdi() void TPCFastTransformGeo::convLocalToUV1(int32_t sector, float ly, float lz, float& u, float& v) const { /// convert Local-> UV c.s. - if (roc < NumberOfRocsA) { // TPC side A + if (sector < NumberOfSectorsA) { // TPC side A u = ly; v = mTPCzLength - lz; - } else { // TPC side C - u = -ly; // pads are mirrorred on C-side - v = lz + mTPCzLength; // drift direction is mirrored on C-side + } else { // TPC side C + u = -ly; // pads are mirrorred on C-side + v = lz + mTPCzLength; // drift direction is mirrored on C-side } } diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx deleted file mode 100644 index c553d9cc6dac1..0000000000000 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file TPCFastTransformManager.cxx -/// \brief Implementation of TPCFastTransformManager class -/// -/// \author Sergey Gorbunov - -#include "TPCFastTransformManager.h" -#include "AliHLTTPCGeometry.h" -#include "AliTPCParam.h" -#include "AliTPCRecoParam.h" -#include "AliTPCTransform.h" -#include "AliTPCcalibDB.h" -#include "TPCFastTransform.h" -#include "Spline2DHelper.h" -blabla - -using namespace o2::gpu; - -TPCFastTransformManager::TPCFastTransformManager() - : mError(), mOrigTransform(nullptr), fLastTimeBin(0) {} - -int32_t TPCFastTransformManager::create(TPCFastTransform& fastTransform, - AliTPCTransform* transform, - long TimeStamp) -{ - /// Initializes TPCFastTransform object - - AliTPCcalibDB* pCalib = AliTPCcalibDB::Instance(); - if (!pCalib) { - return storeError( - -1, "TPCFastTransformManager::Init: No TPC calibration instance found"); - } - - AliTPCParam* tpcParam = pCalib->GetParameters(); - if (!tpcParam) { - return storeError( - -2, "TPCFastTransformManager::Init: No TPCParam object found"); - } - - if (!transform) { - transform = pCalib->GetTransform(); - } - if (!transform) { - return storeError( - -3, "TPCFastTransformManager::Init: No TPC transformation found"); - } - - mOrigTransform = transform; - - tpcParam->Update(); - tpcParam->ReadGeoMatrices(); - - const AliTPCRecoParam* rec = transform->GetCurrentRecoParam(); - if (!rec) { - return storeError(-5, - "TPCFastTransformManager::Init: No TPC Reco Param " - "set in transformation"); - } - - bool useCorrectionMap = rec->GetUseCorrectionMap(); - - if (useCorrectionMap) { - transform->SetCorrectionMapMode(kTRUE); // If the simulation set this to - // false to simulate corrections, we - // need to reverse it for the - // transformation - } - // find last calibrated time bin - - fLastTimeBin = rec->GetLastBin(); - - const int32_t nRows = tpcParam->GetNRowLow() + tpcParam->GetNRowUp(); - - TPCFastTransformGeo geo; - - { // construct the geometry - geo.startConstruction(nRows); - - float tpcZlengthSideA = tpcParam->GetZLength(0); - float tpcZlengthSideC = - tpcParam->GetZLength(TPCFastTransformGeo::getNumberOfRocs() / 2); - - geo.setTPCzLength(tpcZlengthSideA, tpcZlengthSideC); - geo.setTPCalignmentZ(-mOrigTransform->GetDeltaZCorrTime()); - - for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { - int32_t roc = 0, sector = 0, secrow = 0; - AliHLTTPCGeometry::Slice2Sector(roc, row, sector, secrow); - Int_t nPads = tpcParam->GetNPads(sector, secrow); - float xRow = tpcParam->GetPadRowRadii(sector, secrow); - float padWidth = tpcParam->GetInnerPadPitchWidth(); - if (row >= tpcParam->GetNRowLow()) { - padWidth = tpcParam->GetOuterPadPitchWidth(); - } - geo.setTPCrow(row, xRow, nPads, padWidth); - } - geo.finishConstruction(); - } - - TPCFastSpaceChargeCorrection correction; - - { // create the correction map - - const int32_t nDistortionScenarios = 1; - - correction.startConstruction(geo, nDistortionScenarios); - - TPCFastSpaceChargeCorrection::SplineType spline; - spline.recreate(8, 20); - - int32_t scenario = 0; - correction.setSplineScenario(scenario, spline); - - for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { - correction.setRowScenarioID(row, scenario); - } - - correction.finishConstruction(); - } // .. create the correction map - - { // create the fast transform object - - fastTransform.startConstruction(correction); - - // tell the transformation to apply the space charge corrections - fastTransform.setApplyCorrectionOn(); - - // set some initial calibration values, will be reinitialised later int32_t - // updateCalibration() - const float t0 = 0.; - const float vDrift = 0.f; - const float vdCorrY = 0.; - const float ldCorr = 0.; - const float tofCorr = 0.; - const float primVtxZ = 0.; - const int64_t initTimeStamp = -1; - fastTransform.setCalibration(initTimeStamp, t0, vDrift, vdCorrY, ldCorr, - tofCorr, primVtxZ); - - fastTransform.finishConstruction(); - } - - return updateCalibration(fastTransform, TimeStamp); -} - -int32_t TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransform, - long TimeStamp) -{ - // Update the calibration with the new time stamp - - long lastTS = fastTransform.getTimeStamp(); - - // deinitialize - - fastTransform.setTimeStamp(-1); - - if (TimeStamp < 0) { - return 0; - } - - // search for the calibration database - - if (!mOrigTransform) { - return storeError(-1, - "TPCFastTransformManager::SetCurrentTimeStamp: TPC " - "transformation has not been set properly"); - } - - AliTPCcalibDB* pCalib = AliTPCcalibDB::Instance(); - if (!pCalib) { - return storeError(-2, - "TPCFastTransformManager::SetCurrentTimeStamp: No " - "TPC calibration found"); - } - - AliTPCParam* tpcParam = pCalib->GetParameters(); - if (!tpcParam) { - return storeError(-3, - "TPCFastTransformManager::SetCurrentTimeStamp: No " - "TPCParam object found"); - } - - AliTPCRecoParam* recoParam = mOrigTransform->GetCurrentRecoParamNonConst(); - if (!recoParam) { - return storeError(-5, - "TPCFastTransformManager::Init: No TPC Reco Param " - "set in transformation"); - } - - // calibration found, set the initialized status back - - fastTransform.setTimeStamp(lastTS); - - // less than 60 seconds from the previois time stamp, don't do anything - - if (lastTS >= 0 && TMath::Abs(lastTS - TimeStamp) < 60) { - return 0; - } - - // start the initialization - - bool useCorrectionMap = recoParam->GetUseCorrectionMap(); - - if (useCorrectionMap) { - // If the simulation set this to false to simulate corrections, we need to - // reverse it for the transformation This is a design feature. Historically - // HLT code runs as a part of simulation, not reconstruction. - mOrigTransform->SetCorrectionMapMode(kTRUE); - } - - // set the current time stamp - - mOrigTransform->SetCurrentTimeStamp(static_cast(TimeStamp)); - fastTransform.setTimeStamp(TimeStamp); - - // find last calibrated time bin - - fLastTimeBin = recoParam->GetLastBin(); - - double t0 = mOrigTransform->GetTBinOffset(); - double driftCorrPT = mOrigTransform->GetDriftCorrPT(); - double vdCorrectionTime = mOrigTransform->GetVDCorrectionTime(); - double vdCorrectionTimeGY = mOrigTransform->GetVDCorrectionTimeGY(); - double time0CorrTime = mOrigTransform->GetTime0CorrTime(); - - // original formula: - // L = (t-t0)*ZWidth*driftCorrPT*vdCorrectionTime*( 1 + - // yLab*vdCorrectionTimeGY ) - time0CorrTime + 3.*tpcParam->GetZSigma(); Z = - // Z(L) - fDeltaZCorrTime chebyshev corrections for xyz Time-of-flight - // correction: ldrift += dist-to-vtx*tofCorr - - // fast transform formula: - // L = (t-t0)*(mVdrift + mVdriftCorrY*yLab ) + mLdriftCorr - // Z = Z(L) + tpcAlignmentZ - // spline corrections for xyz - // Time-of-flight correction: ldrift += dist-to-vtx*tofCorr - - double vDrift = tpcParam->GetZWidth() * driftCorrPT * vdCorrectionTime; - double vdCorrY = vDrift * vdCorrectionTimeGY; - double ldCorr = -time0CorrTime + 3 * tpcParam->GetZSigma(); - - double tofCorr = (0.01 * tpcParam->GetDriftV()) / TMath::C(); - double primVtxZ = mOrigTransform->GetPrimVertex()[2]; - - bool useTOFcorrection = recoParam->GetUseTOFCorrection(); - - if (!useTOFcorrection) { - tofCorr = 0; - } - - fastTransform.setCalibration(TimeStamp, t0, vDrift, vdCorrY, ldCorr, tofCorr, - primVtxZ); - - // now calculate the correction map: dx,du,dv = ( origTransform() -> x,u,v) - - // fastTransformNominal:x,u,v - - const TPCFastTransformGeo& geo = fastTransform.getGeometry(); - - TPCFastSpaceChargeCorrection& correction = - fastTransform.getCorrection(); - - // switch TOF correction off for a while - - recoParam->SetUseTOFCorrection(kFALSE); - - for (int32_t roc = 0; roc < geo.getNumberOfRocs(); roc++) { - - for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { - - const TPCFastTransformGeo::RowInfo& rowInfo = geo.getRowInfo(row); - - const TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(roc, row); - float* data = correction.getSplineData(roc, row); - - Spline2DHelper helper; - helper.setSpline(spline, 4, 4); - auto F = [&](double su, double sv, double dxuv[3]) { - float x = rowInfo.x; - // x, u, v cordinates of the knot (local cartesian coord. of roc - // towards central electrode ) - float u = 0, v = 0; - geo.convScaledUVtoUV(roc, row, su, sv, u, v); - - // row, pad, time coordinates of the knot - float vertexTime = 0.f; - float pad = 0.f, time = 0.f; - fastTransform.convUVtoPadTime(roc, row, u, v, pad, time, vertexTime); - - // nominal x,y,z coordinates of the knot (without corrections and - // time-of-flight correction) - float y = 0, z = 0; - geo.convUVtoLocal(roc, u, v, y, z); - - // original TPC transformation (row,pad,time) -> (x,y,z) without - // time-of-flight correction - float ox = 0, oy = 0, oz = 0; - { - int32_t sector = 0, secrow = 0; - AliHLTTPCGeometry::Slice2Sector(roc, row, sector, secrow); - int32_t is[] = {sector}; - double xx[] = {static_cast(secrow), pad, time}; - mOrigTransform->Transform(xx, is, 0, 1); - ox = xx[0]; - oy = xx[1]; - oz = xx[2]; - } - // convert to u,v - float ou = 0, ov = 0; - geo.convLocalToUV(roc, oy, oz, ou, ov); - - // corrections in x,u,v: - dxuv[0] = ox - x; - dxuv[1] = ou - u; - dxuv[2] = ov - v; - }; - - helper.approximateFunction(data, 0., 1., 0., 1., F); - } // row - } // roc - - // set back the time-of-flight correction; - - recoParam->SetUseTOFCorrection(useTOFcorrection); - - return 0; -} diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.h b/GPU/TPCFastTransformation/TPCFastTransformManager.h deleted file mode 100644 index f981b05bec241..0000000000000 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file TPCFastTransformManager.h -/// \brief Definition of TPCFastTransformManager class -/// -/// \author Sergey Gorbunov - -#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_TPCFASTTRANSFORMMANAGER_H -#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_TPCFASTTRANSFORMMANAGER_H - -#include - -#include "GPUCommonDef.h" -#include "Rtypes.h" -#include "TString.h" -#include "AliTPCTransform.h" - -namespace o2 -{ -namespace gpu -{ -class TPCFastTransform; - -/// -/// The TPCFastTransformManager class is to initialize TPCFastTransformation object -/// - -class TPCFastTransformManager -{ - public: - /// _____________ Constructors / destructors __________________________ - - /// Default constructor - TPCFastTransformManager(); - - /// Copy constructor: disabled - TPCFastTransformManager(const TPCFastTransformManager&) = delete; - - /// Assignment operator: disabled - TPCFastTransformManager& operator=(const TPCFastTransformManager&) = delete; - - /// Destructor - ~TPCFastTransformManager() = default; - - /// _______________ Main functionality ________________________ - - /// Initializes TPCFastTransform object - int32_t create(TPCFastTransform& spline, AliTPCTransform* transform, long TimeStamp); - - /// Updates the transformation with the new time stamp - Int_t updateCalibration(TPCFastTransform& spline, long TimeStamp); - - /// _______________ Utilities ________________________ - - AliTPCTransform* getOriginalTransform() { return mOrigTransform; } - - /// Gives error string - const char* getLastError() const { return mError.Data(); } - - private: - /// Stores an error message - int32_t storeError(Int_t code, const char* msg); - - TString mError; ///< error string - AliTPCTransform* mOrigTransform; ///< transient - int32_t fLastTimeBin; ///< last calibrated time bin -}; - -inline int32_t TPCFastTransformManager::storeError(int32_t code, const char* msg) -{ - mError = msg; - return code; -} -} // namespace gpu -} // namespace o2 - -#endif diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index 7c1ae8fd56800..fc15506d5397c 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -59,7 +59,7 @@ #pragma link C++ class o2::gpu::IrregularSpline2D3DCalibrator + ; #pragma link C++ class o2::gpu::TPCFastTransformGeo + ; -#pragma link C++ class o2::gpu::TPCFastTransformGeo::RocInfo + ; +#pragma link C++ class o2::gpu::TPCFastTransformGeo::SectorInfo + ; #pragma link C++ class o2::gpu::TPCFastTransformGeo::RowInfo + ; #pragma link C++ class o2::gpu::TPCFastTransform + ; @@ -68,9 +68,8 @@ #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RowInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RocInfo + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RowActiveArea + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RocRowInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorRowInfo + ; #pragma link C++ class o2::gpu::CorrectionMapsHelper + ; #pragma link C++ struct o2::gpu::MultivariatePolynomialContainer + ; diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 7e889d5a9e7db..bee1f9107ddd2 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -44,7 +44,7 @@ using namespace o2::tpc; using namespace o2::gpu; -void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", +void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* fileNameInv = "debugVoxResInv.root", const char* outFileName = "TPCFastTransform_VoxRes.root", bool useSmoothed = false, bool invertSigns = false) { @@ -56,11 +56,11 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", To visiualise the results: root -l transformDebug.root - corr->Draw("cx:y:z","iRoc==0&&iRow==10","") - grid->Draw("cx:y:z","iRoc==0&&iRow==10","same") - vox->Draw("vx:y:z","iRoc==0&&iRow==10","same") - corrvox->Draw("cx:y:z","iRoc==0&&iRow==10","same") - points->Draw("px:y:z","iRoc==0&&iRow==10","same") + corr->Draw("cx:y:z","iSector==0&&iRow==10","") + grid->Draw("cx:y:z","iSector==0&&iRow==10","same") + vox->Draw("vx:y:z","iSector==0&&iRow==10","same") + corrvox->Draw("cx:y:z","iSector==0&&iRow==10","same") + points->Draw("px:y:z","iSector==0&&iRow==10","same") */ if (gSystem->AccessPathName(fileName)) { @@ -82,6 +82,18 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", return; } + TTree* voxResTreeInverse = nullptr; + std::unique_ptr fileInv; + if (fileNameInv && !std::string(fileNameInv).empty()) { + fileInv = std::unique_ptr(TFile::Open(fileNameInv, "READ")); + if (!fileInv || !fileInv->IsOpen()) { + std::cout << " input file " << fileNameInv << " does not exist!" << std::endl; + return; + } + fileInv->cd(); + gDirectory->GetObject("voxResTree", voxResTreeInverse); + } + auto userInfo = voxResTree->GetUserInfo(); if (!userInfo->FindObject("y2xBinning") || !userInfo->FindObject("z2xBinning")) { @@ -140,7 +152,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", corrHelper->setNthreadsToMaximum(); // corrHelper->setNthreads(1); - auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, useSmoothed, invertSigns); + auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns); std::unique_ptr fastTransform( helper->create(0, *corrPtr)); @@ -168,11 +180,11 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); - // for (int32_t iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { - for (int32_t iRoc = 0; iRoc < 1; iRoc++) { + // for (int32_t iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { + for (int32_t iSector = 0; iSector < 1; iSector++) { for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { - auto& info = corr.getSliceRowInfo(iRoc, iRow); - std::cout << "roc " << iRoc << " row " << iRow + auto& info = corr.getSectorRowInfo(iSector, iRow); + std::cout << "sector " << iSector << " row " << iRow << " gridV0 " << info.gridV0 << " gridCorrU0 " << info.gridCorrU0 << " gridCorrV0 " << info.gridCorrV0 << " scaleCorrUtoGrid " << info.scaleCorrUtoGrid << " scaleCorrVtoGrid " << info.scaleCorrVtoGrid << " gridU0 " << info.gridU0 << " scaleUtoGrid " << info.scaleUtoGrid << " scaleVtoGrid " << info.scaleVtoGrid @@ -189,7 +201,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // the difference double maxDiff[3] = {0., 0., 0.}; - int32_t maxDiffRoc[3] = {0, 0, 0}; + int32_t maxDiffSector[3] = {0, 0, 0}; int32_t maxDiffRow[3] = {0, 0, 0}; double sumDiff[3] = {0., 0., 0.}; @@ -207,7 +219,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // measured x,y,z; corrections cx,cy,cz from the measured to the real x,y,z; // inverse corrections ix,iy,iz at the real position (x+cx,y+cy,z+cz) // ideally, ix = cx, iy = cy, iz = cz - TNtuple* debugCorr = new TNtuple("corr", "corr", "iRoc:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); + TNtuple* debugCorr = new TNtuple("corr", "corr", "iSector:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); debugCorr->SetMarkerStyle(8); debugCorr->SetMarkerSize(0.1); @@ -216,7 +228,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // ntuple with the input data: voxels and corrections debugFile->cd(); TNtuple* debugVox = - new TNtuple("vox", "vox", "iRoc:iRow:n:x:y:z:vx:vy:vz"); + new TNtuple("vox", "vox", "iSector:iRow:n:x:y:z:vx:vy:vz"); debugVox->SetMarkerStyle(8); debugVox->SetMarkerSize(0.8); @@ -225,7 +237,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // duplicate of debugVox + the spline data at voxels in a different color debugFile->cd(); TNtuple* debugCorrVox = - new TNtuple("corrvox", "corrvox", "iRoc:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz"); + new TNtuple("corrvox", "corrvox", "iSector:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz"); debugCorrVox->SetMarkerStyle(8); debugCorrVox->SetMarkerSize(0.8); @@ -233,7 +245,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // corrections at the spline grid points debugFile->cd(); - TNtuple* debugGrid = new TNtuple("grid", "grid", "iRoc:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); + TNtuple* debugGrid = new TNtuple("grid", "grid", "iSector:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); debugGrid->SetMarkerStyle(8); debugGrid->SetMarkerSize(1.2); @@ -242,7 +254,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", // ntuple with data points created from voxels (with the data smearing, extension to the edges etc.) debugFile->cd(); TNtuple* debugPoints = - new TNtuple("points", "points", "iRoc:iRow:x:y:z:px:py:pz:cx:cy:cz"); + new TNtuple("points", "points", "iSector:iRow:x:y:z:px:py:pz:cx:cy:cz"); debugPoints->SetMarkerStyle(8); debugPoints->SetMarkerSize(0.4); @@ -256,32 +268,13 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); - auto getAllCorrections = [&](int iRoc, int iRow, float u, float v, float& x, float& y, float& z, float& cx, float& cy, float& cz, float& ix, float& iy, float& iz) { - // define x,y,z - - x = geo.getRowInfo(iRow).x; - geo.convUVtoLocal(iRoc, u, v, y, z); - + auto getAllCorrections = [&](int iSector, int iRow, float y, float z, float& cx, float& cy, float& cz, float& ix, float& iy, float& iz) { // get the corrections cx,cy,cz at x,y,z - float cu, cv; - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - geo.convUVtoLocal(iRoc, cu, cv, cy, cz); - - float corrected_u = u + cu; - float corrected_v = v + cv; - float corrected_x = x + cx; - float corrected_y, corrected_z; - geo.convUVtoLocal(iRoc, corrected_u, corrected_v, corrected_y, corrected_z); - - // get the inverse corrections ix,iy,iz at the corrected x,y,z - float inverted_x, inverted_u, inverted_v, inverted_y, inverted_z; - corr.getCorrectionInvCorrectedX(iRoc, iRow, corrected_u, corrected_v, inverted_x); - corr.getCorrectionInvUV(iRoc, iRow, corrected_u, corrected_v, inverted_u, inverted_v); - geo.convUVtoLocal(iRoc, inverted_u, inverted_v, inverted_y, inverted_z); - - ix = corrected_x - inverted_x; - iy = corrected_y - inverted_y; - iz = corrected_z - inverted_z; + std::tie(cx, cy, cz) = corr.getCorrectionLocal(iSector, iRow, y, z); + float realY = y + cy; + float realZ = z + cz; + ix = corr.getCorrectionXatRealYZ(iSector, iRow, realY, realZ); + std::tie(iy, iz) = corr.getCorrectionYZatRealYZ(iSector, iRow, realY, realZ); }; o2::tpc::TrackResiduals::VoxRes* v = nullptr; @@ -289,7 +282,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", branch->SetAddress(&v); branch->SetAutoDelete(kTRUE); - int32_t iRocLast = -1; + int32_t iSectorLast = -1; int32_t iRowLast = -1; std::cout << "fill debug ntuples at voxels ..." << std::endl; @@ -309,10 +302,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", int32_t z2xBin = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - int32_t iRoc = (int32_t)v->bsec; + int32_t iSector = (int32_t)v->bsec; int32_t iRow = (int32_t)xBin; - iRocLast = iRoc; + iSectorLast = iSector; iRowLast = iRow; double x = trackResiduals.getX(xBin); // radius of the pad row @@ -326,7 +319,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", double y = x * y2x; double z = x * z2x; - if (iRoc >= geo.getNumberOfSlicesA()) { + if (iSector >= geo.getNumberOfSectorsA()) { z = -z; } @@ -345,19 +338,18 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", z = x * v->stat[o2::tpc::TrackResiduals::VoxZ]; } - float u, v; - geo.convLocalToUV(iRoc, y, z, u, v); - float x1, y1, z1, cx, cy, cz, ix, iy, iz; - getAllCorrections(iRoc, iRow, u, v, x1, y1, z1, cx, cy, cz, ix, iy, iz); + float cx, cy, cz, ix, iy, iz; + getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); - double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; if (voxEntries >= 1.) { + double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; + for (int32_t i = 0; i < 3; i++) { if (fabs(maxDiff[i]) < fabs(d[i])) { maxDiff[i] = d[i]; - maxDiffRoc[i] = iRoc; + maxDiffSector[i] = iSector; maxDiffRow[i] = iRow; - // std::cout << " roc " << iRoc << " row " << iRow << " xyz " << i + // std::cout << " sector " << iSector << " row " << iRow << " xyz " << i // << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; } sumDiff[i] += d[i] * d[i]; @@ -365,80 +357,81 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", nDiff++; } - debugVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ); + debugVox->Fill(iSector, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ); - debugCorrVox->Fill(iRoc, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, + debugCorrVox->Fill(iSector, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, cx, cy, cz, ix, iy, iz); } std::cout << "fill debug ntuples everywhere .." << std::endl; - for (int32_t iRoc = 0; iRoc < geo.getNumberOfSlices(); iRoc++) { - // for (int32_t iRoc = 0; iRoc < 1; iRoc++) { - std::cout << "debug ntules for roc " << iRoc << std::endl; + for (int32_t iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { + // for (int32_t iSector = 0; iSector < 1; iSector++) { + std::cout << "debug ntules for sector " << iSector << std::endl; for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { double x = geo.getRowInfo(iRow).x; // the spline grid - const auto& gridU = corr.getSpline(iRoc, iRow).getGridX1(); - const auto& gridV = corr.getSpline(iRoc, iRow).getGridX2(); - if (iRoc == 0 && iRow == 0) { + const auto& gridY = corr.getSpline(iSector, iRow).getGridX1(); + const auto& gridZ = corr.getSpline(iSector, iRow).getGridX2(); + if (iSector == 0 && iRow == 0) { std::cout << "spline scenario " << corr.getRowInfo(iRow).splineScenarioID << std::endl; - std::cout << "spline grid U: u = " << 0 << ".." << gridU.getUmax() << ", x = " << gridU.getXmin() << ".." << gridU.getXmax() << std::endl; - std::cout << "spline grid V: u = " << 0 << ".." << gridV.getUmax() << ", x = " << gridV.getXmin() << ".." << gridV.getXmax() << std::endl; + std::cout << "spline grid Y: u = " << 0 << ".." << gridY.getUmax() << ", x = " << gridY.getXmin() << ".." << gridY.getXmax() << std::endl; + std::cout << "spline grid Z: u = " << 0 << ".." << gridZ.getUmax() << ", x = " << gridZ.getXmin() << ".." << gridZ.getXmax() << std::endl; } // the correction { - std::vector p[2], g[2]; - - p[0].push_back(geo.getRowInfo(iRow).getUmin()); - for (int32_t iu = 0; iu < gridU.getNumberOfKnots(); iu++) { - float u, v; - corr.convGridToUV(iRoc, iRow, gridU.getKnot(iu).getU(), 0., u, v); - g[0].push_back(u); - p[0].push_back(u); + std::vector points[2], knots[2]; + + auto [yMin, yMax] = geo.getRowInfo(iRow).getYrange(); + auto [zMin, zMax] = geo.getZrange(iSector); + + points[0].push_back(yMin); + points[0].push_back(yMax); + points[1].push_back(zMin); + points[1].push_back(zMax); + + for (int32_t iu = 0; iu < gridY.getNumberOfKnots(); iu++) { + auto [y, z] = corr.convGridToLocal(iSector, iRow, gridY.getKnot(iu).getU(), 0.); + knots[0].push_back(y); + points[0].push_back(y); } - p[0].push_back(geo.getRowInfo(iRow).getUmax()); - - p[1].push_back(0.); - for (int32_t iv = 0; iv < gridV.getNumberOfKnots(); iv++) { - float u, v; - corr.convGridToUV(iRoc, iRow, 0., gridV.getKnot(iv).getU(), u, v); - g[1].push_back(v); - p[1].push_back(v); + for (int32_t iv = 0; iv < gridZ.getNumberOfKnots(); iv++) { + auto [y, z] = corr.convGridToLocal(iSector, iRow, 0., gridZ.getKnot(iv).getU()); + knots[1].push_back(z); + points[1].push_back(z); } - p[1].push_back(geo.getTPCzLength(iRoc)); - for (int32_t iuv = 0; iuv < 2; iuv++) { - int32_t n = p[iuv].size(); + for (int32_t iyz = 0; iyz <= 1; iyz++) { + std::sort(knots[iyz].begin(), knots[iyz].end()); + std::sort(points[iyz].begin(), points[iyz].end()); + int32_t n = points[iyz].size(); for (int32_t i = 0; i < n - 1; i++) { - double d = (p[iuv][i + 1] - p[iuv][i]) / 10.; + double d = (points[iyz][i + 1] - points[iyz][i]) / 10.; for (int32_t ii = 1; ii < 10; ii++) { - p[iuv].push_back(p[iuv][i] + d * ii); + points[iyz].push_back(points[iyz][i] + d * ii); } } - std::sort(p[iuv].begin(), p[iuv].end()); + std::sort(points[iyz].begin(), points[iyz].end()); } for (int32_t iter = 0; iter < 2; iter++) { - std::vector& pu = ((iter == 0) ? g[0] : p[0]); - std::vector& pv = ((iter == 0) ? g[1] : p[1]); - for (uint32_t iu = 0; iu < pu.size(); iu++) { - for (uint32_t iv = 0; iv < pv.size(); iv++) { - float u = pu[iu]; - float v = pv[iv]; - - float x, y, z, cx, cy, cz, ix, iy, iz; - getAllCorrections(iRoc, iRow, u, v, x, y, z, cx, cy, cz, ix, iy, iz); - + std::vector& py = ((iter == 0) ? knots[0] : points[0]); + std::vector& pz = ((iter == 0) ? knots[1] : points[1]); + for (uint32_t iu = 0; iu < py.size(); iu++) { + for (uint32_t iv = 0; iv < pz.size(); iv++) { + float y = py[iu]; + float z = pz[iv]; + float cx, cy, cz, ix, iy, iz; + getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); if (iter == 0) { - debugGrid->Fill(iRoc, iRow, x, y, z, cx, cy, cz, ix, iy, iz); + debugGrid->Fill(iSector, iRow, x, y, z, cx, cy, cz, ix, iy, iz); } else { - debugCorr->Fill(iRoc, iRow, x, y, z, cx, cy, cz, ix, iy, iz); + debugCorr->Fill(iSector, iRow, x, y, z, cx, cy, cz, ix, iy, iz); } } } @@ -451,7 +444,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", o2::gpu::TPCFastSpaceChargeCorrectionMap& map = corrHelper->getCorrectionMap(); - auto& points = map.getPoints(iRoc, iRow); + auto& points = map.getPoints(iSector, iRow); for (uint32_t ip = 0; ip < points.size(); ip++) { auto point = points[ip]; @@ -461,14 +454,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", float correctionY = point.mDy; float correctionZ = point.mDz; - float u, v, cx, cu, cv, cy, cz; - geo.convLocalToUV(iRoc, y, z, u, v); - corr.getCorrection(iRoc, iRow, u, v, cx, cu, cv); - geo.convUVtoLocal(iRoc, u + cu, v + cv, cy, cz); - cy -= y; - cz -= z; + auto [cx, cy, cz] = + corr.getCorrectionLocal(iSector, iRow, y, z); - debugPoints->Fill(iRoc, iRow, x, y, z, correctionX, correctionY, + debugPoints->Fill(iSector, iRow, x, y, z, correctionX, correctionY, correctionZ, cx, cy, cz); } } @@ -478,14 +467,14 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", sumDiff[i] = sqrt(sumDiff[i]) / nDiff; } - std::cout << "Max difference in x : " << maxDiff[0] << " at ROC " - << maxDiffRoc[0] << " row " << maxDiffRow[0] << std::endl; + std::cout << "Max difference in x : " << maxDiff[0] << " at Sector " + << maxDiffSector[0] << " row " << maxDiffRow[0] << std::endl; - std::cout << "Max difference in y : " << maxDiff[1] << " at ROC " - << maxDiffRoc[1] << " row " << maxDiffRow[1] << std::endl; + std::cout << "Max difference in y : " << maxDiff[1] << " at Sector " + << maxDiffSector[1] << " row " << maxDiffRow[1] << std::endl; - std::cout << "Max difference in z : " << maxDiff[2] << " at ROC " - << maxDiffRoc[2] << " row " << maxDiffRow[2] << std::endl; + std::cout << "Max difference in z : " << maxDiff[2] << " at Sector " + << maxDiffSector[2] << " row " << maxDiffRow[2] << std::endl; std::cout << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] << " " << sumDiff[2] << std::endl; From 8eceae55f882dfb33f56cc54e20cc9c479e58dc3 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Sun, 6 Apr 2025 18:43:55 +0000 Subject: [PATCH 14/26] TPC Splines: cleanup --- GPU/TPCFastTransformation/Spline1D.h | 2 +- GPU/TPCFastTransformation/Spline1DSpec.h | 58 ++++++++++--------- GPU/TPCFastTransformation/Spline2DHelper.cxx | 2 +- GPU/TPCFastTransformation/Spline2DSpec.h | 36 ++++++------ GPU/TPCFastTransformation/SplineHelper.cxx | 4 +- GPU/TPCFastTransformation/SplineSpec.h | 20 +++---- .../TPCFastSpaceChargeCorrection.h | 6 +- 7 files changed, 66 insertions(+), 62 deletions(-) diff --git a/GPU/TPCFastTransformation/Spline1D.h b/GPU/TPCFastTransformation/Spline1D.h index ccadaeed23b79..c7a4d927dec1d 100644 --- a/GPU/TPCFastTransformation/Spline1D.h +++ b/GPU/TPCFastTransformation/Spline1D.h @@ -77,7 +77,7 @@ namespace gpu /// One can store all F-dependent spline parameters outside of the spline object /// and provide them at each interpolation call. /// To do so, create a spline with nYdimensions=0; create spline parameters for F via Spline1DHelper class; -/// then use special interpolateU(..) methods for the interpolation. +/// then use special interpolateAtU(..) methods for the interpolation. /// /// This feature allows one to use the same spline object for the approximation of different functions /// on the same grid of knots. diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index 2cc95ebdcab9f..fcabbbad12098 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -287,33 +287,38 @@ class Spline1DSpec : public Spline1DContainer /// Get interpolated value S(x) GPUd() void interpolate(DataT x, GPUgeneric() DataT S[/*mYdim*/]) const { - interpolateU(mYdim, mParameters, convXtoU(x), S); + interpolateAtU(mYdim, mParameters, convXtoU(x), S); } /// Get interpolated value for an nYdim-dimensional S(u) using spline parameters Parameters. template - GPUd() void interpolateU(int32_t inpYdim, GPUgeneric() const DataT Parameters[], - DataT u, GPUgeneric() DataT S[/*nYdim*/]) const + GPUd() void interpolateAtU(int32_t inpYdim, GPUgeneric() const DataT Parameters[], + DataT u, GPUgeneric() DataT S[/*nYdim*/]) const { const auto nYdimTmp = SplineUtil::getNdim(inpYdim); const auto nYdim = nYdimTmp.get(); int32_t iknot = TBase::template getLeftKnotIndexForU(u); const DataT* d = Parameters + (2 * nYdim) * iknot; - interpolateU(nYdim, getKnots()[iknot], &(d[0]), &(d[nYdim]), &(d[2 * nYdim]), &(d[3 * nYdim]), u, S); + interpolateAtU(nYdim, getKnots()[iknot], &(d[0]), &(d[nYdim]), &(d[2 * nYdim]), &(d[3 * nYdim]), u, S); } /// The main mathematical utility. /// Get interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] /// using the spline values Sl, Sr and the slopes Dl, Dr template - GPUd() void interpolateU(int32_t inpYdim, const Knot& knotL, - GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], - GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], - DataT u, GPUgeneric() T S[/*mYdim*/]) const + GPUd() void interpolateAtU(int32_t inpYdim, const Knot& knotL, + GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], + GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], + DataT u, GPUgeneric() T S[/*mYdim*/]) const { const auto nYdimTmp = SplineUtil::getNdim(inpYdim); const auto nYdim = nYdimTmp.get(); + auto [dSdSl, dSdDl, dSdSr, dSdDr] = getSderivativesOverParsAtU(knotL, u); + for (int32_t dim = 0; dim < nYdim; ++dim) { + S[dim] = dSdSr * Sr[dim] + dSdSl * Sl[dim] + dSdDl * Dl[dim] + dSdDr * Dr[dim]; + } + /* if (u < (DataT)0) { u = (DataT)0; } @@ -330,6 +335,7 @@ class Spline1DSpec : public Spline1DContainer T b = df - Dl[dim] - a; S[dim] = ((a * v + b) * v + Dl[dim]) * uu + Sl[dim]; } + */ /* another way to calculate f(u): T uu = T(u - knotL.u); @@ -345,11 +351,10 @@ class Spline1DSpec : public Spline1DContainer } template - GPUd() void getUderivatives(const Knot& knotL, DataT u, - T& dSl, T& dDl, T& dSr, T& dDr) const + GPUd() std::tuple getSderivativesOverParsAtU(const Knot& knotL, DataT u) const { /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] - /// over the spline values Sl, Sr and the slopes Dl, Dr + /// over the spline parameters Sl(eft), Sr(ight) and the slopes Dl, Dr if (u < (DataT)0) { u = (DataT)0; @@ -363,11 +368,12 @@ class Spline1DSpec : public Spline1DContainer T vm1 = v - 1.; T a = u * vm1; T v2 = v * v; - dSr = v2 * (3. - 2 * v); - dSl = 1. - dSr; - dDl = vm1 * a; - dDr = v * a; - // F(u) = dSl * Sl + dSr * Sr + dDl * Dl + dDr * Dr; + T dSdSr = v2 * (3. - 2 * v); + T dSdSl = 1. - dSdSr; + T dSdDl = vm1 * a; + T dSdDr = v * a; + // S(u) = dSdSl * Sl + dSdSr * Sr + dSdDl * Dl + dSdDr * Dr; + return std::make_tuple(dSdSl, dSdDl, dSdSr, dSdDr); } /* template @@ -480,21 +486,21 @@ class Spline1DSpec /// Get interpolated value for an YdimT-dimensional S(u) using spline parameters Parameters. template - GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], - DataT u, GPUgeneric() DataT S[/*nYdim*/]) const + GPUd() void interpolateAtU(GPUgeneric() const DataT Parameters[], + DataT u, GPUgeneric() DataT S[/*nYdim*/]) const { - TBase::template interpolateU(YdimT, Parameters, u, S); + TBase::template interpolateAtU(YdimT, Parameters, u, S); } /// Get interpolated value for an YdimT-dimensional S(u) at the segment [knotL, next knotR] /// using the spline values Sl, Sr and the slopes Dl, Dr template - GPUd() void interpolateU(const typename TBase::Knot& knotL, - GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], - GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], - DataT u, GPUgeneric() T S[/*mYdim*/]) const + GPUd() void interpolateAtU(const typename TBase::Knot& knotL, + GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], + GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], + DataT u, GPUgeneric() T S[/*mYdim*/]) const { - TBase::interpolateU(YdimT, knotL, Sl, Dl, Sr, Dr, u, S); + TBase::interpolateAtU(YdimT, knotL, Sl, Dl, Sr, Dr, u, S); } using TBase::getNumberOfKnots; @@ -504,7 +510,7 @@ class Spline1DSpec #if !defined(GPUCA_GPUCODE) using TBase::recreate; #endif - using TBase::interpolateU; + using TBase::interpolateAtU; }; /// ================================================================================================== @@ -552,7 +558,7 @@ class Spline1DSpec /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ - using TBase::interpolateU; + using TBase::interpolateAtU; ClassDefNV(Spline1DSpec, 0); }; diff --git a/GPU/TPCFastTransformation/Spline2DHelper.cxx b/GPU/TPCFastTransformation/Spline2DHelper.cxx index 03ecf4a3f1707..bec6fc58ff8d7 100644 --- a/GPU/TPCFastTransformation/Spline2DHelper.cxx +++ b/GPU/TPCFastTransformation/Spline2DHelper.cxx @@ -194,7 +194,7 @@ void Spline2DHelper::approximateFunction( for (int32_t ipu = 0; ipu < nDataPointsU; ipu++) { double splineF[Ndim]; double u = mHelperU1.getDataPoint(ipu).u; - mHelperU1.getSpline().interpolateU(Ndim, parUdbl.get(), u, splineF); + mHelperU1.getSpline().interpolateAtU(Ndim, parUdbl.get(), u, splineF); for (int32_t dim = 0; dim < Ndim; dim++) { rotDataPointF[(ipu * nDataPointsV + ipv) * Ndim + dim] = splineF[dim]; } diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index b4d351e8d0407..d235b7ddfde07 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -239,13 +239,13 @@ class Spline2DSpec /// Get interpolated value S(x) GPUd() void interpolate(DataT x1, DataT x2, GPUgeneric() DataT S[/*mYdim*/]) const { - interpolateU(mYdim, mParameters, mGridX1.convXtoU(x1), mGridX2.convXtoU(x2), S); + interpolateAtU(mYdim, mParameters, mGridX1.convXtoU(x1), mGridX2.convXtoU(x2), S); } /// Get interpolated value for an inpYdim-dimensional S(u1,u2) using spline parameters Parameters. template - GPUd() void interpolateUold(int32_t inpYdim, GPUgeneric() const DataT Parameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[/*inpYdim*/]) const + GPUd() void interpolateAtUold(int32_t inpYdim, GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*inpYdim*/]) const { const auto nYdimTmp = SplineUtil::getNdim(inpYdim); @@ -295,7 +295,7 @@ class Spline2DSpec typedef Spline1DSpec TGridX1; const TGridX1& gridX1 = reinterpret_cast(mGridX1); - gridX1.interpolateU(nYdim4, knotU, Su0, Du0, Su1, Du1, u, parU); + gridX1.interpolateAtU(nYdim4, knotU, Su0, Du0, Su1, Du1, u, parU); const DataT* Sv0 = parU + 0; const DataT* Dv0 = parU + nYdim; @@ -304,13 +304,13 @@ class Spline2DSpec typedef Spline1DSpec TGridX2; const TGridX2& gridX2 = reinterpret_cast(mGridX2); - gridX2.interpolateU(nYdim, knotV, Sv0, Dv0, Sv1, Dv1, v, S); + gridX2.interpolateAtU(nYdim, knotV, Sv0, Dv0, Sv1, Dv1, v, S); } /// Get interpolated value for an inpYdim-dimensional S(u1,u2) using spline parameters Parameters. template - GPUd() void interpolateU(int32_t inpYdim, GPUgeneric() const DataT Parameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[/*inpYdim*/]) const + GPUd() void interpolateAtU(int32_t inpYdim, GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*inpYdim*/]) const { const auto nYdimTmp = SplineUtil::getNdim(inpYdim); @@ -334,10 +334,8 @@ class Spline2DSpec const DataT* A = Parameters + (nu * iv + iu) * nYdim4; // values { {Y1,Y2,Y3}, {Y1,Y2,Y3}'v, {Y1,Y2,Y3}'u, {Y1,Y2,Y3}''vu } at {u0, v0} const DataT* B = A + nYdim4 * nu; // values { ... } at {u0, v1} - DataT dSl, dDl, dSr, dDr; - mGridX1.getUderivatives(knotU, u, dSl, dDl, dSr, dDr); - DataT dSd, dDd, dSu, dDu; - mGridX2.getUderivatives(knotV, v, dSd, dDd, dSu, dDu); + auto [dSl, dDl, dSr, dDr] = mGridX1.template getSderivativesOverParsAtU(knotU, u); + auto [dSd, dDd, dSu, dDu] = mGridX2.template getSderivativesOverParsAtU(knotV, v); // when nYdim == 1: // S = dSl * (dSd * A[0] + dDd * A[1]) + dDl * (dSd * A[2] + dDd * A[3]) + @@ -430,18 +428,18 @@ class Spline2DSpec /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. template - GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const + GPUd() void interpolateAtU(GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const { - TBase::template interpolateU(YdimT, Parameters, u1, u2, S); + TBase::template interpolateAtU(YdimT, Parameters, u1, u2, S); } /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. template - GPUd() void interpolateUold(GPUgeneric() const DataT Parameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const + GPUd() void interpolateAtUold(GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const { - TBase::template interpolateUold(YdimT, Parameters, u1, u2, S); + TBase::template interpolateAtUold(YdimT, Parameters, u1, u2, S); } using TBase::getNumberOfKnots; @@ -451,7 +449,7 @@ class Spline2DSpec #if !defined(GPUCA_GPUCODE) using TBase::recreate; #endif - using TBase::interpolateU; + using TBase::interpolateAtU; }; /// ================================================================================================== @@ -507,7 +505,7 @@ class Spline2DSpec /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ - using TBase::interpolateU; + using TBase::interpolateAtU; }; /// ================================================================================================== diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx index 6e1b53510e0d0..af3efb1c4817d 100644 --- a/GPU/TPCFastTransformation/SplineHelper.cxx +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -410,8 +410,8 @@ void SplineHelper::approximateFunction( } double splineF[mFdimensions]; double u = mHelpers[dimension].getDataPoint(i).u; - mHelpers[dimension].getSpline().interpolateU(mFdimensions, parD[dimension].get(), u, splineF); // recalculate at all datapoints of dimension - for (int32_t dim = 0; dim < mFdimensions; dim++) { // writing it in allParameters + mHelpers[dimension].getSpline().interpolateAtU(mFdimensions, parD[dimension].get(), u, splineF); // recalculate at all datapoints of dimension + for (int32_t dim = 0; dim < mFdimensions; dim++) { // writing it in allParameters // LOG(info)< : public SplineContainer for (int32_t i = 0; i < nXdim; i++) { u[i] = mGrid[i].convXtoU(x[i]); } - interpolateU(mXdim, mYdim, mParameters, u, S); + interpolateAtU(mXdim, mYdim, mParameters, u, S); } /// Get interpolated value for S(u):inpXdim->inpYdim using spline parameters Parameters template - GPUd() void interpolateU(int32_t inpXdim, int32_t inpYdim, GPUgeneric() const DataT Parameters[], - const DataT u[/*inpXdim*/], GPUgeneric() DataT S[/*inpYdim*/]) const + GPUd() void interpolateAtU(int32_t inpXdim, int32_t inpYdim, GPUgeneric() const DataT Parameters[], + const DataT u[/*inpXdim*/], GPUgeneric() DataT S[/*inpYdim*/]) const { const auto nXdimTmp = SplineUtil::getNdim(mXdim); const auto nXdim = nXdimTmp.get(); @@ -345,7 +345,7 @@ class SplineSpec : public SplineContainer DataT coordinate = u[d]; typedef Spline1DSpec TGridX; const TGridX& gridX = *((const TGridX*)&(mGrid[d])); - gridX.interpolateU(nInterpolations, knotL, S0, D0, S1, D1, coordinate, iParameters); + gridX.interpolateAtU(nInterpolations, knotL, S0, D0, S1, D1, coordinate, iParameters); nInterpolations /= 4; nKnots /= 2; } // end d (every dimension) @@ -354,7 +354,7 @@ class SplineSpec : public SplineContainer S[i] = iParameters[i]; // write into result-array // LOG(info)< /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. template - GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], - const DataT u[/*XdimT*/], GPUgeneric() DataT S[/*YdimT*/]) const + GPUd() void interpolateAtU(GPUgeneric() const DataT Parameters[], + const DataT u[/*XdimT*/], GPUgeneric() DataT S[/*YdimT*/]) const { - TBase::template interpolateU(XdimT, YdimT, Parameters, u, S); + TBase::template interpolateAtU(XdimT, YdimT, Parameters, u, S); } /// _______________ Suppress some parent class methods ________________________ @@ -432,7 +432,7 @@ class SplineSpec #if !defined(GPUCA_GPUCODE) using TBase::recreate; #endif - using TBase::interpolateU; + using TBase::interpolateAtU; }; /// ================================================================================================== @@ -490,7 +490,7 @@ class SplineSpec /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ - using TBase::interpolateU; + using TBase::interpolateAtU; /// Check dimensions void checkDimensions(int32_t& nXdim, int32_t& nYdim) diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index f84fde4fffd8c..76368efcd8a4f 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -410,7 +410,7 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrect auto [gridU, gridV, scale] = convLocalToGrid(sector, row, y, z); float dxyz[3]; - spline.interpolateU(splineData, gridU, gridV, dxyz); + spline.interpolateAtU(splineData, gridU, gridV, dxyz); float dx = scale * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); float dy = scale * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); @@ -427,7 +427,7 @@ GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t secto auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); float dx = 0; - spline.interpolateU(splineData, gridU, gridV, &dx); + spline.interpolateAtU(splineData, gridU, gridV, &dx); dx = scale * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); return dx; @@ -443,7 +443,7 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionYZat const float* splineData = getSplineData(sector, row, 2); float dyz[2]; - spline.interpolateU(splineData, gridU, gridV, dyz); + spline.interpolateAtU(splineData, gridU, gridV, dyz); dyz[0] = scale * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); dyz[1] = scale * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); From b77a0dd7bcb42f93a179258f28b2493a2628e323 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Fri, 11 Apr 2025 15:06:35 +0000 Subject: [PATCH 15/26] TPC Splines: fast merge of SC corrections --- .../TPCFastSpaceChargeCorrectionHelper.h | 10 +- .../TPCFastSpaceChargeCorrectionHelper.cxx | 163 ++++++++++++------ GPU/TPCFastTransformation/Spline1DSpec.h | 88 +++++----- GPU/TPCFastTransformation/Spline2DSpec.h | 135 ++++++++++++++- .../TPCFastSpaceChargeCorrection.h | 127 ++++++++++++-- 5 files changed, 401 insertions(+), 122 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h index abbc5b7116b2d..747ed74c9bcad 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h @@ -102,7 +102,15 @@ class TPCFastSpaceChargeCorrectionHelper /// initialise inverse transformation from linear combination of several input corrections void initInverse(std::vector& corrections, const std::vector& scaling, bool prn); - void MergeCorrections(std::vector& corrections, const std::vector& scaling, bool prn); + /// merge several corrections + /// \param mainCorrection main correction + /// \param scale scaling factor for the main correction + /// \param additionalCorrections vector of pairs of additional corrections and their scaling factors + /// \param prn printout flag + /// \return main correction merged with additional corrections + void MergeCorrections( + o2::gpu::TPCFastSpaceChargeCorrection& mainCorrection, float scale, + const std::vector>& additionalCorrections, bool prn); private: /// geometry initialization diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 92817063831f6..6ba3d6e12dd9e 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -176,8 +176,8 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas } if (processingInverseCorrection) { - float* splineX = correction.getSplineData(sector, row, 1); - float* splineYZ = correction.getSplineData(sector, row, 2); + float* splineX = correction.getSplineDataInvX(sector, row); + float* splineYZ = correction.getSplineDataInvYZ(sector, row); for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { splineX[i] = splineParameters[3 * i + 0]; splineYZ[2 * i + 0] = splineParameters[3 * i + 1]; @@ -940,8 +940,8 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector& corrections, const std::vector& scaling, bool prn) +void TPCFastSpaceChargeCorrectionHelper::MergeCorrections( + o2::gpu::TPCFastSpaceChargeCorrection& mainCorrection, float mainScale, + const std::vector>& additionalCorrections, bool /*prn*/) { /// merge several corrections - /* + TStopwatch watch; LOG(info) << "fast space charge correction helper: Merge corrections"; - if (corrections.size() != scaling.size()) { - LOGP(error, "Input corrections and scaling values have different size"); - return; - } - - auto& correction = *(corrections.front()); + const auto& geo = mainCorrection.getGeometry(); - for (int sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { + for (int sector = 0; sector < geo.getNumberOfSectors(); sector++) { auto myThread = [&](int iThread) { - for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { - TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(sector, row); + for (int row = iThread; row < geo.getNumberOfRows(); row += mNthreads) { + const auto& spline = mainCorrection.getSpline(sector, row); - std::vector splineParameters(spline.getNumberOfParameters()); - std::vector splineParametersInvX(spline.getNumberOfParameters()); - std::vector splineParametersInvYZ(spline.getNumberOfParameters()); + float* splineParameters = mainCorrection.getSplineData(sector, row); + float* splineParametersInvX = mainCorrection.getSplineDataInvX(sector, row); + float* splineParametersInvYZ = mainCorrection.getSplineDataInvYZ(sector, row); - const auto& gridU = spline.getGridX1(); - const auto& gridV = spline.getGridX2(); - - for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { - double u = gridU.getKnot(iu).u; - for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { - int knotIndex = spline.getKnotIndex(iu, iv); + auto& secRowInfo = mainCorrection.getSectorRowInfo(sector, row); - double v = gridV.getKnot(iu).u; - auto [y, z] = correction.convGridToLocal(sector, row, u, v); - constexpr int nKnotPar1d = 4; - constexpr int nKnotPar2d = nKnotPar1d * 2; - constexpr int nKnotPar3d = nKnotPar1d * 3; + constexpr int nKnotPar1d = 4; + constexpr int nKnotPar2d = nKnotPar1d * 2; + constexpr int nKnotPar3d = nKnotPar1d * 3; - for (int i = 0; i < corrections.size(); ++i) { - double s = scaling[i]; - auto p = corrections[i]->getCorrectionParameters(sector, row, y, z); - for (int j = 0; j < nKnotPar3d; ++j) { - splineParameters[knotIndex * nKnotPar3d + j] += s * p[j]; + { // scale the main correction + for (int i = 0; i < 3; i++) { + secRowInfo.maxCorr[i] *= mainScale; + secRowInfo.minCorr[i] *= mainScale; + } + double parscale[4] = {mainScale, mainScale, mainScale, mainScale * mainScale}; + for (int iknot = 0, ind = 0; iknot < spline.getNumberOfKnots(); iknot++) { + for (int ipar = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 3; idim++, ind++) { + splineParameters[ind] *= parscale[ipar]; } - auto pInvX = corrections[i]->getCorrectionParametersInvX(sector, row, y, z); - for (int j = 0; j < nKnotPar1d; ++j) { - splineParametersInvX[knotIndex * nKnotPar1d + j] += s * pInvX[j]; + } + } + for (int iknot = 0, ind = 0; iknot < spline.getNumberOfKnots(); iknot++) { + for (int ipar = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 1; idim++, ind++) { + splineParametersInvX[ind] *= parscale[ipar]; } - auto pInvYZ = corrections[i]->getCorrectionParametersInvYZ(sector, row, y, z); - for (int j = 0; j < nKnotPar2d; ++j) { - splineParametersInvYZ[knotIndex * nKnotPar2d + j] += s * pInvYZ[j]; + } + } + for (int iknot = 0, ind = 0; iknot < spline.getNumberOfKnots(); iknot++) { + for (int ipar = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 2; idim++, ind++) { + splineParametersInvYZ[ind] *= parscale[ipar]; } } - } // iv - } // iu + } + } - float* splineXYZ = correction.getSplineData(sector, row, 0); - float* splineInvX = correction.getSplineData(sector, row, 1); - float* splineInvYZ = correction.getSplineData(sector, row, 2); + // add the other corrections - for (int i = 0; i < spline.getNumberOfParameters(); i++) { - splineXYZ[i] = splineParameters[i]; - } - for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { - splineX[i] = splineParametersInvX[i]; - splineYZ[2 * i + 0] = splineParametersInvYZ[2 * i + 0]; - splineYZ[2 * i + 1] = splineParametersInvYZ[2 * i + 1]; - } + const auto& gridU = spline.getGridX1(); + const auto& gridV = spline.getGridX2(); + + for (int icorr = 0; icorr < additionalCorrections.size(); ++icorr) { + const auto& corr = *(additionalCorrections[icorr].first); + double scale = additionalCorrections[icorr].second; + auto& linfo = corr.getSectorRowInfo(sector, row); + secRowInfo.updateMaxValues(linfo.getMaxValues(), scale); + secRowInfo.updateMaxValues(linfo.getMinValues(), scale); + + double scaleU = secRowInfo.scaleUtoGrid / linfo.scaleUtoGrid; + double scaleV = secRowInfo.scaleVtoGrid / linfo.scaleVtoGrid; + + for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { + double u = gridU.getKnot(iu).u; + for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { + double v = gridV.getKnot(iu).u; + int knotIndex = spline.getKnotIndex(iu, iv); + float P[nKnotPar3d]; + + { // direct correction + auto [y, z] = mainCorrection.convGridToLocal(sector, row, u, v); + // return values: u, v, scaling factor + auto [lu, lv, ls] = corr.convLocalToGrid(sector, row, y, z); + ls *= scale; + double parscale[4] = {ls, ls * scaleU, ls * scaleV, ls * ls * scaleU * scaleV}; + const auto& spl = corr.getSpline(sector, row); + spl.interpolateParametersAtU(corr.getSplineData(sector, row), lu, lv, P); + for (int ipar = 0, ind = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 3; idim++, ind++) { + splineParameters[knotIndex * nKnotPar3d + ind] += parscale[ipar] * P[ind]; + } + } + } + + auto [y, z] = mainCorrection.convGridToCorrectedLocal(sector, row, u, v); + // return values: u, v, scaling factor + auto [lu, lv, ls] = corr.convCorrectedLocalToGrid(sector, row, y, z); + ls *= scale; + double parscale[4] = {ls, ls * scaleU, ls * scaleV, ls * ls * scaleU * scaleV}; + + { // inverse X correction + corr.getSplineInvX(sector, row).interpolateParametersAtU(corr.getSplineDataInvX(sector, row), lu, lv, P); + for (int ipar = 0, ind = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 1; idim++, ind++) { + splineParametersInvX[knotIndex * nKnotPar1d + ind] += parscale[ipar] * P[ind]; + } + } + } + + { // inverse YZ correction + corr.getSplineInvYZ(sector, row).interpolateParametersAtU(corr.getSplineDataInvYZ(sector, row), lu, lv, P); + for (int ipar = 0, ind = 0; ipar < nKnotPar1d; ++ipar) { + for (int idim = 0; idim < 2; idim++, ind++) { + splineParametersInvYZ[knotIndex * nKnotPar2d + ind] += parscale[ipar] * P[ind]; + } + } + } + + } // iv + } // iu + } // corrections } // row - }; // thread + }; // thread std::vector threads(mNthreads); @@ -1054,7 +1106,6 @@ void TPCFastSpaceChargeCorrectionHelper::MergeCorrections(std::vector : public Spline1DContainer for (int32_t dim = 0; dim < nYdim; ++dim) { S[dim] = dSdSr * Sr[dim] + dSdSl * Sl[dim] + dSdDl * Dl[dim] + dSdDr * Dr[dim]; } + /* + another way to calculate f(u): + if (u < (DataT)0) { u = (DataT)0; } @@ -336,18 +339,6 @@ class Spline1DSpec : public Spline1DContainer S[dim] = ((a * v + b) * v + Dl[dim]) * uu + Sl[dim]; } */ - /* - another way to calculate f(u): - T uu = T(u - knotL.u); - T v = uu * T(knotL.Li); // scaled u - T vm1 = v-1; - T v2 = v * v; - float cSr = v2*(3-2*v); - float cSl = 1-cSr; - float cDl = v*vm1*vm1*knotL.L; - float cDr = v2*vm1*knotL.L; - return cSl*Sl + cSr*Sr + cDl*Dl + cDr*Dr; - */ } template @@ -365,51 +356,50 @@ class Spline1DSpec : public Spline1DContainer u = u - knotL.u; T v = u * T(knotL.Li); // scaled u - T vm1 = v - 1.; + T vm1 = v - T(1.); T a = u * vm1; T v2 = v * v; - T dSdSr = v2 * (3. - 2 * v); - T dSdSl = 1. - dSdSr; + T dSdSr = v2 * (T(3.) - v - v); + T dSdSl = T(1.) - dSdSr; T dSdDl = vm1 * a; T dSdDr = v * a; // S(u) = dSdSl * Sl + dSdSr * Sr + dSdDl * Dl + dSdDr * Dr; return std::make_tuple(dSdSl, dSdDl, dSdSr, dSdDr); } - /* - template - GPUd() void getUsecondDerivatives(const Knot& knotL, DataT u, - T& dSl, T& dDl, T& dSr, T& dDr, - T& dSl2, T& dDl2, T& dSr2, T& dDr2) const - { - /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] - /// over the spline values Sl, Sr and the slopes Dl, Dr - - if (u < (DataT)0) { - u = (DataT)0; - } - if (u > (DataT)TBase::getUmax()) { - u = (DataT)TBase::getUmax(); - } - - u = u - knotL.u; - T v = u * T(knotL.Li); // scaled u - T vm1 = v - 1.; - T a = u * vm1; - T v2 = v * v; - dSr = v2 * (3. - 2 * v); - dSl = 1. - dSr; - dDl = vm1 * a; - dDr = v * a; - T dv = T(knotL.Li); - dSr2 = 6. * v * (1. - v) * dv; - dSl2 = -dSr2; - dDl2 = (v - 1) * (3 * v - 1); - dDr = u * (v * v - v); - dDr2 = 3.f * v * v - 2.f * v; - // F(u) = dSl * Sl + dSr * Sr + dDl * Dl + dDr * Dr; - // dF(u)/du = dSl2 * Sl + dSr2 * Sr + dDl2 * Dl + dDr2 * Dr; + + template + GPUd() std::tuple getSDderivativesOverParsAtU(const Knot& knotL, DataT u) const + { + /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] + /// over the spline values Sl, Sr and the slopes Dl, Dr + + if (u < (DataT)0) { + u = (DataT)0; } - */ + if (u > (DataT)TBase::getUmax()) { + u = (DataT)TBase::getUmax(); + } + + u = u - knotL.u; + T v = u * T(knotL.Li); // scaled u + T vm1 = v - T(1.); + T a = u * vm1; + T v2 = v * v; + T dSdSr = v2 * (T(3.) - v - v); + T dSdSl = T(1.) - dSdSr; + T dSdDl = vm1 * a; + T dSdDr = v * a; + + T dv = T(knotL.Li); + T dDdSr = 6. * v * (T(1.) - v) * dv; + T dDdSl = -dDdSr; + T dDdDl = vm1 * (v + v + vm1); + T dDdDr = v * (v + vm1 + vm1); + // S(u) = dSdSl * Sl + dSdSr * Sr + dSdDl * Dl + dSdDr * Dr; + // D(u) = dS(u)/du = dDdSl * Sl + dDdSr * Sr + dDdDl * Dl + dDdDr * Dr; + return std::make_tuple(dSdSl, dSdDl, dSdSr, dSdDr, dDdSl, dDdDl, dDdSr, dDdDr); + } + using TBase::convXtoU; using TBase::getKnot; using TBase::getKnots; diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index d235b7ddfde07..987ce1ad5d256 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -358,6 +358,132 @@ class Spline2DSpec } } + /// Get interpolated parameters (like parameters stored at knots) for an inpYdim-dimensional S(u1,u2) using spline parameters Parameters. + template + GPUd() void interpolateParametersAtU(int32_t inpYdim, GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT P[/* 4*inpYdim */]) const + { + + const auto nYdimTmp = SplineUtil::getNdim(inpYdim); + const int32_t nYdim = nYdimTmp.get(); + + // const auto maxYdim = SplineUtil::getMaxNdim(inpYdim); + // const int32_t maxYdim4 = 4 * maxYdim.get(); + + // const auto nYdim2 = nYdim * 2; + const auto nYdim4 = nYdim * 4; + + DataT *S = P, + *R = P + nYdim, + *Q = P + nYdim * 2, + *W = P + nYdim * 3; + + const DataT& u = u1; + const DataT& v = u2; + int32_t nu = mGridX1.getNumberOfKnots(); + int32_t iu = mGridX1.template getLeftKnotIndexForU(u); + int32_t iv = mGridX2.template getLeftKnotIndexForU(v); + + const typename TBase::Knot& knotU = mGridX1.template getKnot(iu); + const typename TBase::Knot& knotV = mGridX2.template getKnot(iv); + + const DataT* A = Parameters + (nu * iv + iu) * nYdim4; // values { {Y1,Y2,Y3}, {Y1,Y2,Y3}'v, {Y1,Y2,Y3}'u, {Y1,Y2,Y3}''vu } at {u0, v0} + const DataT* B = A + nYdim4 * nu; // values { ... } at {u0, v1} + + auto [dSdSl, dSdDl, dSdSr, dSdDr, dRdSl, dRdDl, dRdSr, dRdDr] = mGridX1.template getSDderivativesOverParsAtU(knotU, u); + auto [dSdSd, dSdDd, dSdSu, dSdDu, dQdSd, dQdDd, dQdSu, dQdDu] = mGridX2.template getSDderivativesOverParsAtU(knotV, v); + + // when nYdim == 1: + + // Function value S + // S = dSdSl * (dSdSd * A[0] + dSdDd * A[1]) + dSdDl * (dSdSd * A[2] + dSdDd * A[3]) + + // dSdSr * (dSdSd * A[4] + dSdDd * A[5]) + dSdDr * (dSdSd * A[6] + dSdDd * A[7]) + + // dSdSl * (dSdSu * B[0] + dSdDu * B[1]) + dSdDl * (dSdSu * B[2] + dSdDu * B[3]) + + // dSdSr * (dSdSu * B[4] + dSdDu * B[5]) + dSdDr * (dSdSu * B[6] + dSdDu * B[7]); + + { + DataT a[8] = {dSdSl * dSdSd, dSdSl * dSdDd, dSdDl * dSdSd, dSdDl * dSdDd, + dSdSr * dSdSd, dSdSr * dSdDd, dSdDr * dSdSd, dSdDr * dSdDd}; + DataT b[8] = {dSdSl * dSdSu, dSdSl * dSdDu, dSdDl * dSdSu, dSdDl * dSdDu, + dSdSr * dSdSu, dSdSr * dSdDu, dSdDr * dSdSu, dSdDr * dSdDu}; + + // S = sum a[i]*A[i] + b[i]*B[i] + + for (int32_t dim = 0; dim < nYdim; dim++) { + S[dim] = 0; + for (int32_t i = 0; i < 8; i++) { + S[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; + } + } + } + + // Derivative R = dS / du + // R = dRdSl * (dSdSd * A[0] + dSdDd * A[1]) + dRdDl * (dSdSd * A[2] + dSdDd * A[3]) + + // dRdSr * (dSdSd * A[4] + dSdDd * A[5]) + dRdDr * (dSdSd * A[6] + dSdDd * A[7]) + + // dRdSl * (dSdSu * B[0] + dSdDu * B[1]) + dRdDl * (dSdSu * B[2] + dSdDu * B[3]) + + // dRdSr * (dSdSu * B[4] + dSdDu * B[5]) + dRdDr * (dSdSu * B[6] + dSdDu * B[7]); + + { + DataT a[8] = {dRdSl * dSdSd, dRdSl * dSdDd, dRdDl * dSdSd, dRdDl * dSdDd, + dRdSr * dSdSd, dRdSr * dSdDd, dRdDr * dSdSd, dRdDr * dSdDd}; + DataT b[8] = {dRdSl * dSdSu, dRdSl * dSdDu, dRdDl * dSdSu, dRdDl * dSdDu, + dRdSr * dSdSu, dRdSr * dSdDu, dRdDr * dSdSu, dRdDr * dSdDu}; + + // R = sum a[i]*A[i] + b[i]*B[i] + + for (int32_t dim = 0; dim < nYdim; dim++) { + R[dim] = 0; + for (int32_t i = 0; i < 8; i++) { + R[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; + } + } + } + + // Derivative Q = dS / dv + // Q = dSdSl * (dQdSd * A[0] + dQdDd * A[1]) + dSdDl * (dQdSd * A[2] + dQdDd * A[3]) + + // dSdSr * (dQdSd * A[4] + dQdDd * A[5]) + dSdDr * (dQdSd * A[6] + dQdDd * A[7]) + + // dSdSl * (dQdSu * B[0] + dQdDu * B[1]) + dSdDl * (dQdSu * B[2] + dQdDu * B[3]) + + // dSdSr * (dQdSu * B[4] + dQdDu * B[5]) + dSdDr * (dQdSu * B[6] + dQdDu * B[7]); + + { + DataT a[8] = {dSdSl * dQdSd, dSdSl * dQdDd, dSdDl * dQdSd, dSdDl * dQdDd, + dSdSr * dQdSd, dSdSr * dQdDd, dSdDr * dQdSd, dSdDr * dQdDd}; + DataT b[8] = {dSdSl * dQdSu, dSdSl * dQdDu, dSdDl * dQdSu, dSdDl * dQdDu, + dSdSr * dQdSu, dSdSr * dQdDu, dSdDr * dQdSu, dSdDr * dQdDu}; + + // Q = sum a[i]*A[i] + b[i]*B[i] + + for (int32_t dim = 0; dim < nYdim; dim++) { + Q[dim] = 0; + for (int32_t i = 0; i < 8; i++) { + Q[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; + } + } + } + + // cross-derivative W = (dS)^2 / du / dv + // W = dRdSl * (dQdSd * A[0] + dQdDd * A[1]) + dRdDl * (dQdSd * A[2] + dQdDd * A[3]) + + // dRdSr * (dQdSd * A[4] + dQdDd * A[5]) + dRdDr * (dQdSd * A[6] + dQdDd * A[7]) + + // dRdSl * (dQdSu * B[0] + dQdDu * B[1]) + dRdDl * (dQdSu * B[2] + dQdDu * B[3]) + + // dRdSr * (dQdSu * B[4] + dQdDu * B[5]) + dRdDr * (dQdSu * B[6] + dQdDu * B[7]); + + { + DataT a[8] = {dRdSl * dQdSd, dRdSl * dQdDd, dRdDl * dQdSd, dRdDl * dQdDd, + dRdSr * dQdSd, dRdSr * dQdDd, dRdDr * dQdSd, dRdDr * dQdDd}; + DataT b[8] = {dRdSl * dQdSu, dRdSl * dQdDu, dRdDl * dQdSu, dRdDl * dQdDu, + dRdSr * dQdSu, dRdSr * dQdDu, dRdDr * dQdSu, dRdDr * dQdDu}; + + // W = sum a[i]*A[i] + b[i]*B[i] + + for (int32_t dim = 0; dim < nYdim; dim++) { + W[dim] = 0; + for (int32_t i = 0; i < 8; i++) { + W[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; + } + } + } + } + protected: using TBase::mGridX1; using TBase::mGridX2; @@ -429,11 +555,18 @@ class Spline2DSpec /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. template GPUd() void interpolateAtU(GPUgeneric() const DataT Parameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const + DataT u1, DataT u2, GPUgeneric() DataT S[/*YdimT*/]) const { TBase::template interpolateAtU(YdimT, Parameters, u1, u2, S); } + template + GPUd() void interpolateParametersAtU(GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT P[/* 4*YdimT */]) const + { + TBase::template interpolateParametersAtU(YdimT, Parameters, u1, u2, P); + } + /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. template GPUd() void interpolateAtUold(GPUgeneric() const DataT Parameters[], diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 76368efcd8a4f..da37409221d6c 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -82,6 +82,24 @@ class TPCFastSpaceChargeCorrection : public FlatObject maxCorr[2] = GPUCommonMath::Max(maxCorr[2], dv); } + void updateMaxValues(std::tuple dxdudv, float scale) + { + float dx = std::get<0>(dxdudv) * scale; + float du = std::get<1>(dxdudv) * scale; + float dv = std::get<2>(dxdudv) * scale; + updateMaxValues(dx, du, dv); + } + + std::tuple getMaxValues() const + { + return std::make_tuple(maxCorr[0], maxCorr[1], maxCorr[2]); + } + + std::tuple getMinValues() const + { + return std::make_tuple(minCorr[0], minCorr[1], minCorr[2]); + } + ClassDefNV(SectorRowInfo, 2); }; @@ -90,7 +108,11 @@ class TPCFastSpaceChargeCorrection : public FlatObject ClassDefNV(SectorInfo, 1); }; - typedef Spline2D SplineType; + typedef Spline2D SplineTypeXYZ; + typedef Spline2D SplineTypeInvX; + typedef Spline2D SplineTypeInvYZ; + + typedef SplineTypeXYZ SplineType; /// _____________ Constructors / destructors __________________________ @@ -168,6 +190,30 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Gives pointer to spline data GPUd() const float* getSplineData(int32_t sector, int32_t row, int32_t iSpline = 0) const; + /// Gives const pointer to a spline for the inverse X correction + GPUd() const SplineTypeInvX& getSplineInvX(int32_t sector, int32_t row) const; + + /// Gives pointer to a spline for the inverse X correction + GPUd() SplineTypeInvX& getSplineInvX(int32_t sector, int32_t row); + + /// Gives pointer to spline data for the inverse X correction + GPUd() float* getSplineDataInvX(int32_t sector, int32_t row); + + /// Gives pointer to spline data for the inverse X correction + GPUd() const float* getSplineDataInvX(int32_t sector, int32_t row) const; + + /// Gives const pointer to a spline for the inverse YZ correction + GPUd() const SplineTypeInvYZ& getSplineInvYZ(int32_t sector, int32_t row) const; + + /// Gives pointer to a spline for the inverse YZ correction + GPUd() SplineTypeInvYZ& getSplineInvYZ(int32_t sector, int32_t row); + + /// Gives pointer to spline data for the inverse YZ correction + GPUd() float* getSplineDataInvYZ(int32_t sector, int32_t row); + + /// Gives pointer to spline data for the inverse YZ correction + GPUd() const float* getSplineDataInvYZ(int32_t sector, int32_t row) const; + /// _______________ The main method: cluster correction _______________________ /// // GPUd() int32_t getCorrectionInternal(int32_t sector, int32_t row, float u, float v, float& dx, float& du, float& dv) const; @@ -193,6 +239,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// convert corrected u,v to internal grid coordinates GPUd() std::tuple convCorrectedLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + /// convert internal grid coordinates to corrected u,v + /// return values: u, v, scaling factor + GPUd() std::tuple convGridToCorrectedLocal(int32_t sector, int32_t row, float u, float v) const; + GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; /// TPC geometry information @@ -316,6 +366,54 @@ GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, return reinterpret_cast(mSplineData[iSpline] + mSectorDataSizeBytes[iSpline] * sector + rowInfo.dataOffsetBytes[iSpline]); } +GPUdi() TPCFastSpaceChargeCorrection::SplineTypeInvX& TPCFastSpaceChargeCorrection::getSplineInvX(int32_t sector, int32_t row) +{ + /// Gives pointer to spline for the inverse X correction + return reinterpret_cast(getSpline(sector, row)); +} + +GPUdi() const TPCFastSpaceChargeCorrection::SplineTypeInvX& TPCFastSpaceChargeCorrection::getSplineInvX(int32_t sector, int32_t row) const +{ + /// Gives const pointer to spline for the inverse X correction + return reinterpret_cast(getSpline(sector, row)); +} + +GPUdi() float* TPCFastSpaceChargeCorrection::getSplineDataInvX(int32_t sector, int32_t row) +{ + /// Gives pointer to spline data for the inverse X correction + return getSplineData(sector, row, 1); +} + +GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineDataInvX(int32_t sector, int32_t row) const +{ + /// Gives pointer to spline data for the inverse X correction + return getSplineData(sector, row, 1); +} + +GPUdi() TPCFastSpaceChargeCorrection::SplineTypeInvYZ& TPCFastSpaceChargeCorrection::getSplineInvYZ(int32_t sector, int32_t row) +{ + /// Gives pointer to spline for the inverse YZ correction + return reinterpret_cast(getSpline(sector, row)); +} + +GPUdi() const TPCFastSpaceChargeCorrection::SplineTypeInvYZ& TPCFastSpaceChargeCorrection::getSplineInvYZ(int32_t sector, int32_t row) const +{ + /// Gives const pointer to spline for the inverse YZ correction + return reinterpret_cast(getSpline(sector, row)); +} + +GPUdi() float* TPCFastSpaceChargeCorrection::getSplineDataInvYZ(int32_t sector, int32_t row) +{ + /// Gives pointer to spline data for the inverse YZ correction + return getSplineData(sector, row, 2); +} + +GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineDataInvYZ(int32_t sector, int32_t row) const +{ + /// Gives pointer to spline data for the inverse YZ correction + return getSplineData(sector, row, 2); +} + GPUdi() std::tuple TPCFastSpaceChargeCorrection::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const { /// convert local y, z to internal grid coordinates u,v @@ -401,6 +499,17 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convCorrec return {gridU, gridV, scale}; } +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToCorrectedLocal(int32_t sector, int32_t row, float gridU, float gridV) const +{ + /// convert internal grid coordinates u,v to corrected y, z + const SectorRowInfo& info = getSectorRowInfo(sector, row); + float u = info.gridCorrU0 + gridU / info.scaleCorrUtoGrid; + float v = info.gridCorrV0 + gridV / info.scaleCorrVtoGrid; + float y, z; + mGeo.convUVtoLocal1(sector, u, v, y, z); + return {y, z}; +} + GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const { const auto& info = getSectorRowInfo(sector, row); @@ -421,33 +530,21 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrect GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { const auto& info = getSectorRowInfo(sector, row); - const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); - const float* splineData = getSplineData(sector, row, 1); - auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); - float dx = 0; - spline.interpolateAtU(splineData, gridU, gridV, &dx); - + getSplineInvX(sector, row).interpolateAtU(getSplineDataInvX(sector, row), gridU, gridV, &dx); dx = scale * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); return dx; } GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { - auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); - const auto& info = getSectorRowInfo(sector, row); - const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); - const float* splineData = getSplineData(sector, row, 2); - float dyz[2]; - spline.interpolateAtU(splineData, gridU, gridV, dyz); - + getSplineInvYZ(sector, row).interpolateAtU(getSplineDataInvYZ(sector, row), gridU, gridV, dyz); dyz[0] = scale * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); dyz[1] = scale * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); - return {dyz[0], dyz[1]}; } From fc896747137f9258e26efaddc2908653d35b4e85 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Sat, 12 Apr 2025 16:10:13 +0000 Subject: [PATCH 16/26] TPC Splines: get rid of internal UV coordinates --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 59 ++++----- .../src/TPCFastTransformHelperO2.cxx | 7 +- .../TPCFastSpaceChargeCorrection.cxx | 100 ++------------ .../TPCFastSpaceChargeCorrection.h | 125 +++++++++--------- GPU/TPCFastTransformation/TPCFastTransform.h | 4 +- .../TPCFastTransformGeo.cxx | 2 +- .../TPCFastTransformGeo.h | 73 ++-------- .../macro/TPCFastTransformInit.C | 7 +- 8 files changed, 124 insertions(+), 253 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 6ba3d6e12dd9e..021074c49f21a 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -354,15 +354,14 @@ void TPCFastSpaceChargeCorrectionHelper::testGeometry(const TPCFastTransformGeo& for (int pad = 0; pad < nPads; pad++) { const GlobalPadNumber p = mapper.globalPadNumber(PadPos(row, pad)); const PadCentre& c = mapper.padCentre(p); - double u = geo.convPadToU(row, pad); - + auto [y, z] = geo.convPadDriftLengthToLocal(0, row, pad, 0.); const double dx = x - c.X(); - const double dy = u - (-c.Y()); // diferent sign convention for Y coordinate in the map + const double dy = y - (-c.Y()); // diferent sign convention for Y coordinate in the map if (fabs(dx) >= 1.e-6 || fabs(dy) >= 1.e-5) { LOG(warning) << "wrong calculated pad position:" << " row " << row << " pad " << pad << " x calc " << x << " x in map " << c.X() << " dx " << (x - c.X()) - << " y calc " << u << " y in map " << -c.Y() << " dy " << dy << std::endl; + << " y calc " << y << " y in map " << -c.Y() << " dy " << dy << std::endl; } if (fabs(maxDx) < fabs(dx)) { maxDx = dx; @@ -499,18 +498,14 @@ std::unique_ptr TPCFastSpaceChargeCorrect double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); double zMin = rowInfo.x * trackResiduals.getZ2X(0); double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); - double uMin = yMin; - double uMax = yMax; - double vMin = geo.getTPCzLength() - zMax; - double vMax = geo.getTPCzLength() - zMin; - info.gridU0 = uMin; - info.scaleUtoGrid = spline.getGridX1().getUmax() / (uMax - uMin); - info.gridV0 = vMin; - info.scaleVtoGrid = spline.getGridX2().getUmax() / (vMax - vMin); - info.gridCorrU0 = info.gridU0; - info.gridCorrV0 = info.gridV0; - info.scaleCorrUtoGrid = info.scaleUtoGrid; - info.scaleCorrVtoGrid = info.scaleVtoGrid; + double lMin = geo.getTPCzLength() - zMax; + double lMax = geo.getTPCzLength() - zMin; + info.gridMeasured.y0 = yMin; + info.gridMeasured.yScale = spline.getGridX1().getUmax() / (yMax - yMin); + info.gridMeasured.l0 = lMin; + info.gridMeasured.lScale = spline.getGridX2().getUmax() / (lMax - lMin); + + info.gridReal = info.gridMeasured; // std::cout << " iSector " << iSector << " iRow " << iRow << " uMin: " << uMin << " uMax: " << uMax << " vMin: " << vMin << " vMax: " << vMax //<< " grid scale u "<< info.scaleUtoGrid << " grid scale v "<< info.scaleVtoGrid<< std::endl; @@ -593,8 +588,8 @@ std::unique_ptr TPCFastSpaceChargeCorrect auto myThread = [&](int iThread, int nTreads) { struct Voxel { - float mY, mZ; // not-distorted local coordinates - float mDy, mDz; // bin size + float mY, mZ; // non-distorted local coordinates + float mDy, mDz; // voxel size int mSmoothingStep{100}; // is the voxel data original or smoothed at this step }; @@ -905,11 +900,10 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector= 1.e-6 || fabs(dy) >= 1.e-5) { LOG(warning) << "wrong calculated pad position:" << " row " << row << " pad " << pad << " x calc " << x << " x in map " << c.X() << " dx " << (x - c.X()) - << " y calc " << u << " y in map " << -c.Y() << " dy " << dy << std::endl; + << " y calc " << y << " y in map " << -c.Y() << " dy " << dy << std::endl; } if (fabs(maxDx) < fabs(dx)) { maxDx = dx; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 2921a74b025ce..1e6d84b7f8dd9 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -141,48 +141,18 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer { /// Sets the actual location of the external flat buffer after it has been moved (e.g. to another maschine) - struct RowInfoVersion3 { - int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC sector - }; - - struct RowActiveAreaVersion3 { - float maxDriftLengthCheb[5]{0.f}; - float vMax{0.f}; - float cuMin{0.f}; - float cuMax{0.f}; - float cvMax{0.f}; - }; - - struct SectorRowInfoVersion3 { - float gridV0{0.f}; ///< V coordinate of the V-grid start - float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U - float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V - float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate - float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate - RowActiveAreaVersion3 activeArea; - }; - - FlatObject::setActualBufferAddress(actualFlatBufferPtr); - - size_t rowsOffset = 0; - size_t rowsSize = 0; - if (mClassVersion == 3) { - rowsSize = sizeof(RowInfoVersion3) * mGeo.getNumberOfRows(); + if (mClassVersion != 4) { + LOG(error) << "TPCFastSpaceChargeCorrection::setActualBufferAddress() called with class version " << mClassVersion << ". This is not supported."; + return; } - size_t sectorRowsOffset = rowsOffset + rowsSize; - size_t sectorRowsSize = 0; - if (mClassVersion == 3) { // copy old-format sectorrow data from the buffer to the arrays - sectorRowsSize = sizeof(SectorRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfSectors(); - } + FlatObject::setActualBufferAddress(actualFlatBufferPtr); - size_t scOffset = alignSize(sectorRowsOffset + sectorRowsSize, SplineType::getClassAlignmentBytes()); size_t scSize = sizeof(SplineType) * mNumberOfScenarios; - mScenarioPtr = reinterpret_cast(mFlatBufferPtr + scOffset); + mScenarioPtr = reinterpret_cast(mFlatBufferPtr); - size_t scBufferOffset = alignSize(scOffset + scSize, SplineType::getBufferAlignmentBytes()); + size_t scBufferOffset = alignSize(scSize, SplineType::getBufferAlignmentBytes()); size_t scBufferSize = 0; for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -196,45 +166,6 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sectorDataOffset); bufferSize = sectorDataOffset + mSectorDataSizeBytes[is] * mGeo.getNumberOfSectors(); } - - if (mClassVersion == 3) { // copy old-format sectorrow data from the buffer to the arrays - - auto* rowInfosOld = reinterpret_cast(mFlatBufferPtr + rowsOffset); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - RowInfoVersion3& infoOld = rowInfosOld[i]; - RowInfo& info = mRowInfos[i]; - info.splineScenarioID = infoOld.splineScenarioID; - for (int32_t is = 0; is < 3; is++) { - info.dataOffsetBytes[is] = infoOld.dataOffsetBytes[is]; - } - } - - for (int32_t is = 0; is < mNumberOfScenarios; is++) { - auto& spline = mScenarioPtr[is]; - spline.setXrange(0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax()); - } - - auto* sectorRowInfosOld = reinterpret_cast(mFlatBufferPtr + sectorRowsOffset); - - for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { - for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { - SectorRowInfoVersion3& infoOld = sectorRowInfosOld[mGeo.getNumberOfRows() * sector + row]; - SectorRowInfo& info = getSectorRowInfo(sector, row); - const auto& spline = getSpline(sector, row); - info.gridU0 = mGeo.getRowInfo(row).u0; - info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); - - info.gridV0 = infoOld.gridV0; - info.scaleVtoGrid = spline.getGridX2().getUmax() / (mGeo.getTPCzLength() + 3. - info.gridV0); - - info.gridCorrU0 = infoOld.gridCorrU0; - info.scaleCorrUtoGrid = infoOld.scaleCorrUtoGrid; - - info.gridCorrV0 = infoOld.gridCorrV0; - info.scaleCorrVtoGrid = infoOld.scaleCorrVtoGrid; - } - } - } } void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBufferPtr) @@ -454,17 +385,12 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() SectorRowInfo& info = getSectorRowInfo(sector, row); - info.gridU0 = mGeo.getRowInfo(row).u0; - info.scaleUtoGrid = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getUwidth(); - - info.gridV0 = 0.f; - info.scaleVtoGrid = spline.getGridX2().getUmax() / vLength; - - info.gridCorrU0 = info.gridU0; - info.gridCorrV0 = info.gridV0; - info.scaleCorrUtoGrid = info.scaleUtoGrid; - info.scaleCorrVtoGrid = info.scaleVtoGrid; + info.gridMeasured.y0 = mGeo.getRowInfo(row).getYmin(); + info.gridMeasured.yScale = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getYwidth(); + info.gridMeasured.l0 = 0.f; + info.gridMeasured.lScale = spline.getGridX2().getUmax() / vLength; + info.gridReal = info.gridMeasured; } // row } // sector } @@ -539,9 +465,9 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) // grid borders if (sector < mGeo.getNumberOfSectorsA()) { - z1 = vLength - getSectorRowInfo(sector, row).gridV0; + z1 = vLength - getSectorRowInfo(sector, row).gridMeasured.l0; } else { - z0 = getSectorRowInfo(sector, row).gridV0 - vLength; + z0 = getSectorRowInfo(sector, row).gridMeasured.l0 - vLength; } double stepY = (y1 - y0) / 100.; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index da37409221d6c..4564d584c8dce 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -48,17 +48,31 @@ class TPCFastSpaceChargeCorrection : public FlatObject ClassDefNV(RowInfo, 1); }; + struct GridInfo { + float y0{0.f}; ///< Y coordinate of the U-grid start + float yScale{0.f}; //< scale Y to U-grid coordinate + float l0{0.f}; ///< Drift Length coordinate of the V-grid start + float lScale{0.f}; //< scale Drift Length to V-grid coordinate + + float getScale(float l) const + { + if (l < 0.f) { // outside of the TPC + return 0.f; + } + if (l < l0) { // between the grid and the readout + return l / l0; + } + return 1.f; // inside the grid + } + ClassDefNV(GridInfo, 1); + }; + struct SectorRowInfo { - float gridU0{0.f}; //< U coordinate of the U-grid start - float scaleUtoGrid{0.f}; //< scale U to U-grid coordinate - float gridV0{0.f}; ///< V coordinate of the V-grid start - float scaleVtoGrid{0.f}; //< scale V to V-grid coordinate - float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U - float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate - float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V - float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate - float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dU, dV - float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dU, dV + GridInfo gridMeasured; ///< grid info for measured coordinates + GridInfo gridReal; ///< grid info for real coordinates + + float minCorr[3]{-10.f, -10.f, -10.f}; ///< min correction for dX, dY, dZ + float maxCorr[3]{10.f, 10.f, 10.f}; ///< max correction for dX, dY, dZ void resetMaxValues() { @@ -220,10 +234,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUdi() std::tuple getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const; - /// inverse correction: Corrected U and V -> coorrected X + /// inverse correction: Real Y and Z -> Real X GPUd() float getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; - /// inverse correction: Corrected U and V -> uncorrected U and V + /// inverse correction: Real Y and Z -> measred Y and Z GPUd() std::tuple getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; /// _______________ Utilities _______________________________________________ @@ -236,12 +250,13 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// return values: y, z, scaling factor GPUd() std::tuple convGridToLocal(int32_t sector, int32_t row, float u, float v) const; - /// convert corrected u,v to internal grid coordinates - GPUd() std::tuple convCorrectedLocalToGrid(int32_t sector, int32_t row, float y, float z) const; - - /// convert internal grid coordinates to corrected u,v + /// convert real Y, Z to the internal grid coordinates /// return values: u, v, scaling factor - GPUd() std::tuple convGridToCorrectedLocal(int32_t sector, int32_t row, float u, float v) const; + GPUd() std::tuple convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + + /// convert internal grid coordinates to the real Y, Z + /// return values: y, z + GPUd() std::tuple convGridToRealLocal(int32_t sector, int32_t row, float u, float v) const; GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; @@ -421,18 +436,10 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convLocalT const auto& info = getSectorRowInfo(sector, row); const SplineType& spline = getSpline(sector, row); - float u, v; - mGeo.convLocalToUV1(sector, y, z, u, v); - - float scale = 1.f; - if (v < 0.f) { - scale = 0.f; - } else if (v < info.gridV0) { - scale = v / info.gridV0; - } - - float gridU = (u - info.gridU0) * info.scaleUtoGrid; - float gridV = (v - info.gridV0) * info.scaleVtoGrid; + float l = mGeo.convZtoDriftLength(sector, z); + float scale = info.gridMeasured.getScale(l); + float gridU = (y - info.gridMeasured.y0) * info.gridMeasured.yScale; + float gridV = (l - info.gridMeasured.l0) * info.gridMeasured.lScale; // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); @@ -446,19 +453,19 @@ GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int /// ccheck if local y, z are inside the grid const auto& info = getSectorRowInfo(sector, row); - const SplineType& spline = getSpline(sector, row); + const auto& spline = getSpline(sector, row); + float l = mGeo.convZtoDriftLength(sector, z); - float u, v; - mGeo.convLocalToUV1(sector, y, z, u, v); - - float gridU = (u - info.gridU0) * info.scaleUtoGrid; - float gridV = (v - info.gridV0) * info.scaleVtoGrid; + float gridU = (y - info.gridMeasured.y0) * info.gridMeasured.yScale; + float gridV = (l - info.gridMeasured.l0) * info.gridMeasured.lScale; // shrink to the grid area - if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax()) + if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax()) { return false; - if (gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) + } + if (gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { return false; + } return true; } @@ -466,31 +473,22 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToLocal(i { /// convert internal grid coordinates u,v to local y, z const SectorRowInfo& info = getSectorRowInfo(sector, row); - float u = info.gridU0 + gridU / info.scaleUtoGrid; - float v = info.gridV0 + gridV / info.scaleVtoGrid; - float y, z; - mGeo.convUVtoLocal1(sector, u, v, y, z); + float y = info.gridMeasured.y0 + gridU / info.gridMeasured.yScale; + float l = info.gridMeasured.l0 + gridV / info.gridMeasured.lScale; + float z = mGeo.convDriftLengthToZ(sector, l); return {y, z}; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convCorrectedLocalToGrid(int32_t sector, int32_t row, float y, float z) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const { - /// convert corrected y, z to the internal grid coordinates + /// convert real y, z to the internal grid coordinates + scale const auto& info = getSectorRowInfo(sector, row); - const Spline2D& spline = reinterpret_cast&>(getSpline(sector, row)); - - float u, v; - mGeo.convLocalToUV1(sector, y, z, u, v); - - float scale = 1.f; - if (v < 0.f) { - scale = 0.f; - } else if (v < info.gridCorrV0) { - scale = v / info.gridCorrV0; - } + const auto& spline = getSpline(sector, row); - float gridU = (u - info.gridCorrU0) * info.scaleCorrUtoGrid; - float gridV = (v - info.gridCorrV0) * info.scaleCorrVtoGrid; + float l = mGeo.convZtoDriftLength(sector, z); + float scale = info.gridReal.getScale(l); + float gridU = (y - info.gridReal.y0) * info.gridReal.yScale; + float gridV = (l - info.gridReal.l0) * info.gridReal.lScale; // shrink to the grid area gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); @@ -499,14 +497,13 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convCorrec return {gridU, gridV, scale}; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToCorrectedLocal(int32_t sector, int32_t row, float gridU, float gridV) const +GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const { - /// convert internal grid coordinates u,v to corrected y, z + /// convert internal grid coordinates u,v to the real y, z const SectorRowInfo& info = getSectorRowInfo(sector, row); - float u = info.gridCorrU0 + gridU / info.scaleCorrUtoGrid; - float v = info.gridCorrV0 + gridV / info.scaleCorrVtoGrid; - float y, z; - mGeo.convUVtoLocal1(sector, u, v, y, z); + float y = info.gridReal.y0 + gridU / info.gridReal.yScale; + float l = info.gridReal.l0 + gridV / info.gridReal.lScale; + float z = mGeo.convDriftLengthToZ(sector, l); return {y, z}; } @@ -530,7 +527,7 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrect GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { const auto& info = getSectorRowInfo(sector, row); - auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); + auto [gridU, gridV, scale] = convRealLocalToGrid(sector, row, realY, realZ); float dx = 0; getSplineInvX(sector, row).interpolateAtU(getSplineDataInvX(sector, row), gridU, gridV, &dx); dx = scale * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); @@ -539,7 +536,7 @@ GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t secto GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { - auto [gridU, gridV, scale] = convCorrectedLocalToGrid(sector, row, realY, realZ); + auto [gridU, gridV, scale] = convRealLocalToGrid(sector, row, realY, realZ); const auto& info = getSectorRowInfo(sector, row); float dyz[2]; getSplineInvYZ(sector, row).interpolateAtU(getSplineDataInvYZ(sector, row), gridU, gridV, dyz); diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 03d9eaf43ce9b..8807c0e3206f4 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -551,7 +551,7 @@ GPUdi() void TPCFastTransform::Transform(int32_t sector, int32_t row, float pad, GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const { float l = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm - z = getGeometry().convDriftLengthToLocal(sector, l); + z = getGeometry().convDriftLengthToZ(sector, l); } GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const @@ -590,7 +590,7 @@ GPUdi() void TPCFastTransform::TransformIdealZ(int32_t sector, float time, float /// float l = (time - mT0 - vertexTime) * mVdrift; // drift length cm - z = getGeometry().convDriftLengthToLocal(sector, l); + z = getGeometry().convDriftLengthToZ(sector, l); } GPUdi() void TPCFastTransform::TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index e7e026f464818..5b2dcc8da82d5 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -92,7 +92,7 @@ void TPCFastTransformGeo::setTPCrow(int32_t iRow, float x, int32_t nPads, float row.x = x; row.maxPad = nPads - 1; row.padWidth = padWidth; - row.u0 = -uWidth / 2.; + row.yMin = -uWidth / 2.; } void TPCFastTransformGeo::finishConstruction() diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index 4072435e948a5..bbb94dcb8bedd 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -46,25 +46,19 @@ class TPCFastTransformGeo float x{0.f}; ///< nominal X coordinate of the padrow [cm] int32_t maxPad{0}; ///< maximal pad number = n pads - 1 float padWidth{0.f}; ///< width of pads [cm] - float u0{0.f}; ///< min. u coordinate - - /// get U min - GPUd() float getUmin() const { return u0; } - - /// get U max - GPUd() float getUmax() const { return -u0; } + float yMin{0.f}; ///< min. y coordinate /// get Y min - GPUd() float getYmin() const { return u0; } + GPUd() float getYmin() const { return yMin; } /// get Y max - GPUd() float getYmax() const { return -u0; } + GPUd() float getYmax() const { return -yMin; } /// get Y range GPUd() std::tuple getYrange() const { return {getYmin(), getYmax()}; } - /// get width in U - GPUd() float getUwidth() const { return -2.f * u0; } + /// get width in Y + GPUd() float getYwidth() const { return -2.f * yMin; } ClassDefNV(RowInfo, 1); }; @@ -145,23 +139,14 @@ class TPCFastTransformGeo GPUd() std::tuple convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const; /// convert DriftLength -> Local c.s. - GPUd() float convDriftLengthToLocal(int32_t sector, float driftLength) const; + GPUd() float convDriftLengthToZ(int32_t sector, float driftLength) const; + + /// convert Z to DriftLength + GPUd() float convZtoDriftLength(int32_t sector, float z) const; /// convert Local c.s. -> Pad, DriftLength GPUd() std::tuple convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const; - /// convert UV -> Local c.s. - GPUd() void convUVtoLocal1(int32_t sector, float u, float v, float& y, float& z) const; - - /// convert Local-> UV c.s. - GPUd() void convLocalToUV1(int32_t sector, float y, float z, float& u, float& v) const; - - /// convert Pad coordinate -> U - GPUd() float convPadToU(int32_t row, float pad) const; - - /// convert U -> Pad coordinate - GPUd() float convUtoPad(int32_t row, float u) const; - /// Print method void print() const; @@ -257,22 +242,16 @@ GPUdi() std::tuple TPCFastTransformGeo::convPadDriftLengthToLocal( return {y, z}; } -GPUdi() float TPCFastTransformGeo::convDriftLengthToLocal(int32_t sector, float driftLength) const +GPUdi() float TPCFastTransformGeo::convDriftLengthToZ(int32_t sector, float driftLength) const { /// convert DriftLength -> Local c.s. return (sector < NumberOfSectorsA) ? (mTPCzLength - driftLength) : (driftLength - mTPCzLength); } -GPUdi() void TPCFastTransformGeo::convUVtoLocal1(int32_t sector, float u, float v, float& ly, float& lz) const +GPUdi() float TPCFastTransformGeo::convZtoDriftLength(int32_t sector, float z) const { - /// convert UV -> Local c.s. - if (sector < NumberOfSectorsA) { // TPC side A - ly = u; - lz = mTPCzLength - v; - } else { // TPC side C - ly = -u; // pads are mirrorred on C-side - lz = v - mTPCzLength; // drift direction is mirrored on C-side - } + /// convert Z to DriftLength + return (sector < NumberOfSectorsA) ? (mTPCzLength - z) : (z + mTPCzLength); } GPUdi() std::tuple TPCFastTransformGeo::getZrange(int32_t sector) const @@ -301,32 +280,6 @@ GPUdi() std::tuple TPCFastTransformGeo::convLocalToPadDriftLength( return {pad, l}; } -GPUdi() void TPCFastTransformGeo::convLocalToUV1(int32_t sector, float ly, float lz, float& u, float& v) const -{ - /// convert Local-> UV c.s. - if (sector < NumberOfSectorsA) { // TPC side A - u = ly; - v = mTPCzLength - lz; - } else { // TPC side C - u = -ly; // pads are mirrorred on C-side - v = lz + mTPCzLength; // drift direction is mirrored on C-side - } -} - -GPUdi() float TPCFastTransformGeo::convPadToU(int32_t row, float pad) const -{ - /// convert Pad coordinate -> U - const RowInfo& rowInfo = getRowInfo(row); - return (pad - 0.5f * rowInfo.maxPad) * rowInfo.padWidth; -} - -GPUdi() float TPCFastTransformGeo::convUtoPad(int32_t row, float u) const -{ - /// convert U -> Pad coordinate - const RowInfo& rowInfo = getRowInfo(row); - return u / rowInfo.padWidth + 0.5f * rowInfo.maxPad; -} - } // namespace gpu } // namespace o2 diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index bee1f9107ddd2..f0c03d9f5f081 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -185,9 +185,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { auto& info = corr.getSectorRowInfo(iSector, iRow); std::cout << "sector " << iSector << " row " << iRow - << " gridV0 " << info.gridV0 << " gridCorrU0 " << info.gridCorrU0 << " gridCorrV0 " << info.gridCorrV0 - << " scaleCorrUtoGrid " << info.scaleCorrUtoGrid << " scaleCorrVtoGrid " << info.scaleCorrVtoGrid - << " gridU0 " << info.gridU0 << " scaleUtoGrid " << info.scaleUtoGrid << " scaleVtoGrid " << info.scaleVtoGrid + << " gridY0 " << info.gridMeasured.y0 << " gridL0 " << info.gridMeasured.l0 + << " scaleYtoGrid " << info.gridMeasured.yScale << " scaleLtoGrid " << info.gridMeasured.lScale + << " gridRealY0 " << info.gridReal.y0 << " gridRealL0 " << info.gridReal.l0 + << " scaleRealYtoGrid " << info.gridReal.yScale << " scaleRealLtoGrid " << info.gridReal.lScale << std::endl; } } From 2bb0c586a405ac8b935f6006f9e091e9f090f02b Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Mon, 14 Apr 2025 19:01:36 +0000 Subject: [PATCH 17/26] TPC Splines: completely switch to local TPC coordinates in the grid --- .../TPCFastSpaceChargeCorrectionHelper.h | 10 +- .../TPCFastSpaceChargeCorrectionHelper.cxx | 270 +++++++++--------- .../TPCFastSpaceChargeCorrection.cxx | 119 ++++---- .../TPCFastSpaceChargeCorrection.h | 137 ++++----- .../TPCFastTransform.cxx | 4 - GPU/TPCFastTransformation/TPCFastTransform.h | 4 +- .../TPCFastTransformGeo.h | 43 ++- .../TPCFastTransformationLinkDef_O2.h | 1 + .../macro/TPCFastTransformInit.C | 12 +- 9 files changed, 328 insertions(+), 272 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h index 747ed74c9bcad..e8afd9be97d5f 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h @@ -85,8 +85,16 @@ class TPCFastSpaceChargeCorrectionHelper const int nKnotsY = 10, const int nKnotsZ = 20); /// Create SpaceCharge correction out of the voxel tree + /// \param trackResiduals TrackResiduals object + /// \param voxResTree TTree with voxel residuals + /// \param voxResTreeInverse TTree with inverse voxel residuals + /// \param useSmoothed if true, use smoothed residuals + /// \param invertSigns if true, invert the signs of the residuals + /// \return pointer to the created TPCFastSpaceChargeCorrection object + /// \note voxel trees wont be changed. They are read as non-const because of the ROOT::TTreeProcessorMT interface std::unique_ptr createFromTrackResiduals( - const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, bool useSmoothed, bool invertSigns); + const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, // + bool useSmoothed, bool invertSigns); /// _______________ Utilities ________________________ diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 021074c49f21a..d2f6cf57b0de7 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -258,12 +258,14 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper correction.startConstruction(mGeo, nCorrectionScenarios); // assign spline type for TPC rows - for (int row = 0; row < mGeo.getNumberOfRows(); row++) { - int scenario = row / 10; - if (scenario >= nCorrectionScenarios) { - scenario = nCorrectionScenarios - 1; + for (int sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { + for (int row = 0; row < mGeo.getNumberOfRows(); row++) { + int scenario = row / 10; + if (scenario >= nCorrectionScenarios) { + scenario = nCorrectionScenarios - 1; + } + correction.setRowScenarioID(sector, row, scenario); } - correction.setRowScenarioID(row, scenario); } for (int scenario = 0; scenario < nCorrectionScenarios; scenario++) { @@ -397,93 +399,100 @@ std::unique_ptr TPCFastSpaceChargeCorrect int nY2Xbins = trackResiduals.getNY2XBins(); int nZ2Xbins = trackResiduals.getNZ2XBins(); - std::vector uvBinsDouble[2]; + std::vector knotsDouble[3]; + + knotsDouble[0].reserve(nY2Xbins); + knotsDouble[1].reserve(nZ2Xbins); + knotsDouble[2].reserve(nZ2Xbins); - uvBinsDouble[0].reserve(nY2Xbins); - uvBinsDouble[1].reserve(nZ2Xbins); + // to get enouth measurements, make a spline knot at every second bin. Boundary bins are always included. for (int i = 0, j = nY2Xbins - 1; i <= j; i += 2, j -= 2) { - uvBinsDouble[0].push_back(trackResiduals.getY2X(0, i)); + knotsDouble[0].push_back(trackResiduals.getY2X(0, i)); if (j >= i + 1) { - uvBinsDouble[0].push_back(trackResiduals.getY2X(0, j)); + knotsDouble[0].push_back(trackResiduals.getY2X(0, j)); } } for (int i = 0, j = nZ2Xbins - 1; i <= j; i += 2, j -= 2) { - uvBinsDouble[1].push_back(-trackResiduals.getZ2X(i)); + knotsDouble[1].push_back(trackResiduals.getZ2X(i)); + knotsDouble[2].push_back(-trackResiduals.getZ2X(i)); if (j >= i + 1) { - uvBinsDouble[1].push_back(-trackResiduals.getZ2X(j)); + knotsDouble[1].push_back(trackResiduals.getZ2X(j)); + knotsDouble[2].push_back(-trackResiduals.getZ2X(j)); } } - std::vector uvBinsInt[2]; - - for (int iuv = 0; iuv < 2; iuv++) { - auto& bins = uvBinsDouble[iuv]; - std::sort(bins.begin(), bins.end()); + std::vector knotsInt[3]; - auto& binsInt = uvBinsInt[iuv]; - binsInt.reserve(bins.size()); + for (int dim = 0; dim < 3; dim++) { + auto& knotsD = knotsDouble[dim]; + std::sort(knotsD.begin(), knotsD.end()); - double dy = bins[1] - bins[0]; - for (int i = 2; i < bins.size(); i++) { - double dd = bins[i] - bins[i - 1]; - if (dd < dy) { - dy = dd; + double pitch = knotsD[1] - knotsD[0]; // min distance between the knots + for (int i = 2; i < knotsD.size(); i++) { + double d = knotsD[i] - knotsD[i - 1]; + if (d < pitch) { + pitch = d; } } - // spline knots must be positioned on the grid with integer internal coordinate - // take the knot position accuracy of 0.1*dy - dy = dy / 10.; - double y0 = bins[0]; - double y1 = bins[bins.size() - 1]; - for (auto& y : bins) { - y -= y0; - int iy = int(y / dy + 0.5); - binsInt.push_back(iy); - double yold = y / (y1 - y0) * 2 - 1.; - y = iy * dy; - y = y / (y1 - y0) * 2 - 1.; - if (iuv == 0) { - LOG(info) << "TPC SC splines: convert y bin: " << yold << " -> " << y << " -> " << iy; - } else { - LOG(info) << "TPC SC splines: convert z bin: " << yold << " -> " << y << " -> " << iy; - } + // spline knots must be positioned on the grid with an integer internal coordinate + // we set the knot positioning accuracy to 0.1*pitch + pitch = 0.1 * pitch; + auto& knotsI = knotsInt[dim]; + knotsI.reserve(knotsD.size()); + double u0 = knotsD[0]; + double u1 = knotsD[knotsD.size() - 1]; + for (auto& u : knotsD) { + u -= u0; + int iu = int(u / pitch + 0.5); + knotsI.push_back(iu); + // debug printout: corrected vs original knot positions, scaled to [-1,1] interval + double uorig = u / (u1 - u0) * 2 - 1.; + u = (iu * pitch) / (u1 - u0) * 2 - 1.; + LOG(info) << "TPC SC splines: convert " << (dim == 0 ? "y" : (dim == 1 ? "z" : "-z")) << " bin to the knot: " << uorig << " -> " << u << " -> " << iu; } - if (binsInt.size() < 2) { - binsInt.clear(); - binsInt.push_back(0); - binsInt.push_back(1); + if (knotsI.size() < 2) { // minimum 2 knots + knotsI.clear(); + knotsI.push_back(0); + knotsI.push_back(1); } } - auto& yBinsInt = uvBinsInt[0]; - auto& zBinsInt = uvBinsInt[1]; + auto& yKnotsInt = knotsInt[0]; + auto& zKnotsIntA = knotsInt[1]; + auto& zKnotsIntC = knotsInt[2]; - int nKnotsY = yBinsInt.size(); - int nKnotsZ = zBinsInt.size(); + int nKnotsY = yKnotsInt.size(); + int nKnotsZA = zKnotsIntA.size(); + int nKnotsZC = zKnotsIntC.size(); // std::cout << "n knots Y: " << nKnotsY << std::endl; - // std::cout << "n knots Z: " << nKnotsZ << std::endl; + // std::cout << "n knots Z: " << nKnotsZA << ", " << nKnotsZC << std::endl; const int nRows = geo.getNumberOfRows(); const int nSectors = geo.getNumberOfSectors(); { // create the correction object - const int nCorrectionScenarios = 1; + const int nCorrectionScenarios = 2; // different grids for TPC A and TPC C sides correction.startConstruction(geo, nCorrectionScenarios); // init rows - for (int row = 0; row < geo.getNumberOfRows(); row++) { - correction.setRowScenarioID(row, 0); + for (int iSector = 0; iSector < nSectors; iSector++) { + int id = iSector < geo.getNumberOfSectorsA() ? 0 : 1; + for (int row = 0; row < geo.getNumberOfRows(); row++) { + correction.setRowScenarioID(iSector, row, id); + } } { // init spline scenario TPCFastSpaceChargeCorrection::SplineType spline; - spline.recreate(nKnotsY, &yBinsInt[0], nKnotsZ, &zBinsInt[0]); + spline.recreate(nKnotsY, &yKnotsInt[0], nKnotsZA, &zKnotsIntA[0]); correction.setSplineScenario(0, spline); + spline.recreate(nKnotsY, &yKnotsInt[0], nKnotsZC, &zKnotsIntC[0]); + correction.setSplineScenario(1, spline); } correction.finishConstruction(); } // .. create the correction object @@ -491,19 +500,23 @@ std::unique_ptr TPCFastSpaceChargeCorrect // set the grid borders for (int iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { for (int iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { - const auto& rowInfo = geo.getRowInfo(iRow); auto& info = correction.getSectorRowInfo(iSector, iRow); const auto& spline = correction.getSpline(iSector, iRow); - double yMin = rowInfo.x * trackResiduals.getY2X(iRow, 0); - double yMax = rowInfo.x * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); - double zMin = rowInfo.x * trackResiduals.getZ2X(0); - double zMax = rowInfo.x * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); - double lMin = geo.getTPCzLength() - zMax; - double lMax = geo.getTPCzLength() - zMin; - info.gridMeasured.y0 = yMin; - info.gridMeasured.yScale = spline.getGridX1().getUmax() / (yMax - yMin); - info.gridMeasured.l0 = lMin; - info.gridMeasured.lScale = spline.getGridX2().getUmax() / (lMax - lMin); + double rowX = geo.getRowInfo(iRow).x; + double yMin = rowX * trackResiduals.getY2X(iRow, 0); + double yMax = rowX * trackResiduals.getY2X(iRow, trackResiduals.getNY2XBins() - 1); + double zMin = rowX * trackResiduals.getZ2X(0); + double zMax = rowX * trackResiduals.getZ2X(trackResiduals.getNZ2XBins() - 1); + double zOut = zMax; + if (iSector >= geo.getNumberOfSectorsA()) { + // TPC C side + zOut = -zOut; + zMax = -zMin; + zMin = zOut; + } + info.gridMeasured.set(yMin, spline.getGridX1().getUmax() / (yMax - yMin), // y + zMin, spline.getGridX2().getUmax() / (zMax - zMin), // z + zOut, geo.getZreadout(iSector)); // correction scaling region info.gridReal = info.gridMeasured; @@ -514,16 +527,16 @@ std::unique_ptr TPCFastSpaceChargeCorrect LOG(info) << "fast space charge correction helper: preparation took " << watch1.RealTime() << "s"; - for (int processingInverseCorrection = 0; processingInverseCorrection < 2; processingInverseCorrection++) { + for (int processingInverseCorrection = 0; processingInverseCorrection <= 1; processingInverseCorrection++) { TTree* currentTree = (processingInverseCorrection) ? voxResTreeInverse : voxResTree; if (!currentTree) { continue; } - - LOG(info) << "fast space charge correction helper: " << ((processingInverseCorrection) ? "inverse" : "direct") - << " : fill data points from track residuals.. "; + const char* directionName = (processingInverseCorrection) ? "inverse" : "direct"; + LOG(info) << "\n fast space charge correction helper: Process " << directionName + << " correction: fill data points from track residuals.. "; TStopwatch watch3; o2::gpu::TPCFastSpaceChargeCorrectionMap& map = helper->getCorrectionMap(); @@ -548,34 +561,42 @@ std::unique_ptr TPCFastSpaceChargeCorrect { // read data from the tree to vSectorData ROOT::TTreeProcessorMT processor(*currentTree, mNthreads); - + std::string errMsg = std::string("Error reading ") + directionName + " track residuals: "; auto myThread = [&](TTreeReader& readerSubRange) { TTreeReaderValue v(readerSubRange, "voxRes"); while (readerSubRange.Next()) { int iSector = (int)v->bsec; if (iSector < 0 || iSector >= nSectors) { - LOG(fatal) << "Error reading voxels: voxel Sector number " << iSector << " is out of range"; + LOG(fatal) << errMsg << "Sector number " << iSector << " is out of range"; continue; } int iRow = (int)v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) if (iRow < 0 || iRow >= nRows) { - LOG(fatal) << "Row number " << iRow << " is out of range"; + LOG(fatal) << errMsg << "Row number " << iRow << " is out of range"; } + double rowX = trackResiduals.getX(iRow); // X of the pad row int iy = v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 int iz = v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 auto& data = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; data.mNentries = (int)v->stat[o2::tpc::TrackResiduals::VoxV]; data.mX = v->stat[o2::tpc::TrackResiduals::VoxX]; - data.mY = v->stat[o2::tpc::TrackResiduals::VoxF]; - data.mZ = v->stat[o2::tpc::TrackResiduals::VoxZ]; + data.mY = v->stat[o2::tpc::TrackResiduals::VoxF] * rowX; + data.mZ = v->stat[o2::tpc::TrackResiduals::VoxZ] * rowX; data.mCx = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; data.mCy = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; data.mCz = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; - if (0 && data.mNentries < 1) { - data.mCx = 0.; - data.mCy = 0.; - data.mCz = 0.; - data.mNentries = 1; + if (invertSigns) { + data.mCx *= -1.; + data.mCy *= -1.; + data.mCz *= -1.; + } + if (data.mNentries > 0) { + if (iSector < geo.getNumberOfSectorsA() && data.mZ < 0) { + LOG(error) << errMsg << "fitted Z coordinate " << data.mZ << " is negative for sector " << iSector; + } + if (iSector >= geo.getNumberOfSectorsA() && data.mZ > 0) { + LOG(error) << errMsg << "fitted Z coordinate " << data.mZ << " is positive for sector " << iSector; + } } } }; @@ -599,7 +620,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect // LOG(info) << "Processing Sector " << iSector << " row " << iRow; // complete the voxel data - { int xBin = iRow; double x = trackResiduals.getX(xBin); // radius of the pad row @@ -619,36 +639,28 @@ std::unique_ptr TPCFastSpaceChargeCorrect if (iSector >= geo.getNumberOfSectorsA()) { vox.mZ = -vox.mZ; } - data.mY *= x; - data.mZ *= x; - /* - if ( fabs(x - data.mX) > 0.01 || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { - std::cout - << " sector " << iSector << " row " << iRow - << " voxel x " << x << " y " << vox.mY << " z " << vox.mZ - << " data x " << data.mX << " y " << data.mY << " z " << data.mZ - << std::endl; - } - */ - if (0) { // debug: always use voxel center instead of the mean position - data.mY = vox.mY; - data.mZ = vox.mZ; - } - if (data.mNentries < 1) { // no data + if (data.mNentries > 0) { // voxel contains data + vox.mSmoothingStep = 0; // take original data + isDataFound = true; + if (fabs(x - data.mX) > 1. || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { + std::cout << directionName << ": fitted voxel is too far from the nominal position: " + << " sector " << iSector << " row " << iRow + << " center x " << x << " y " << vox.mY << " z " << vox.mZ + << " fitted x " << data.mX << " y " << data.mY << " z " << data.mZ + << std::endl; + } + } else { // no data, take voxel center position data.mCx = 0.; data.mCy = 0.; data.mCz = 0.; + data.mX = x; + data.mY = vox.mY; + data.mZ = vox.mZ; + vox.mSmoothingStep = 100; // fill this data point with smoothed values from the neighbours + } + if (0) { // debug: always use voxel center instead of the mean position data.mY = vox.mY; data.mZ = vox.mZ; - vox.mSmoothingStep = 100; - } else { // voxel contains data - if (invertSigns) { - data.mCx *= -1.; - data.mCy *= -1.; - data.mCz *= -1.; - } - vox.mSmoothingStep = 0; // original data - isDataFound = true; } } } @@ -734,13 +746,13 @@ std::unique_ptr TPCFastSpaceChargeCorrect if (vox2.mSmoothingStep > 2) { LOG(fatal) << "empty voxel is not repared: y " << iy2 << " z " << iz2; } - double y1 = vox1.mY; - double z1 = vox1.mZ; + double y1 = data1.mY; + double z1 = data1.mZ; double cx1 = data1.mCx; double cy1 = data1.mCy; double cz1 = data1.mCz; - double y2 = vox2.mY; - double z2 = vox2.mZ; + double y2 = data2.mY; + double z2 = data2.mZ; double cx2 = data2.mCx; double cy2 = data2.mCy; double cz2 = data2.mCz; @@ -849,6 +861,9 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector splineParameters; for (int row = iThread; row < mGeo.getNumberOfRows(); row += mNthreads) { + auto& sectorRowInfo = correction.getSectorRowInfo(sector, row); + sectorRowInfo.gridReal = sectorRowInfo.gridMeasured; + TPCFastSpaceChargeCorrection::SplineType spline = correction.getSpline(sector, row); helper.setSpline(spline, 10, 10); @@ -897,33 +912,16 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector(mFlatBufferPtr + sectorDataOffset); - bufferSize = sectorDataOffset + mSectorDataSizeBytes[is] * mGeo.getNumberOfSectors(); + size_t splineDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + splineDataOffset); + bufferSize = splineDataOffset + mDataSizeBytes[is]; } } @@ -199,14 +199,8 @@ void TPCFastSpaceChargeCorrection::print() const mGeo.print(); LOG(info) << " mNumberOfScenarios = " << mNumberOfScenarios; LOG(info) << " mTimeStamp = " << mTimeStamp; - LOG(info) << " mSectorDataSizeBytes = " << mSectorDataSizeBytes[0] << " " << mSectorDataSizeBytes[1] << " " << mSectorDataSizeBytes[2]; - { - LOG(info) << " TPC rows: "; - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - const RowInfo& r = mRowInfos[i]; - LOG(info) << " tpc row " << i << ": splineScenarioID = " << r.splineScenarioID << " dataOffsetBytes = " << r.dataOffsetBytes; - } - } + LOG(info) << " mDataSizeBytes = " << mDataSizeBytes[0] << " " << mDataSizeBytes[1] << " " << mDataSizeBytes[2]; + if (mScenarioPtr) { for (int32_t i = 0; i < mNumberOfScenarios; i++) { LOG(info) << " SplineScenario " << i << ": "; @@ -255,8 +249,23 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& assert(mConstructionScenarios != nullptr); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - mRowInfos[i].splineScenarioID = -1; + for (int32_t i = 0; i < mGeo.getNumberOfSectors(); i++) { + mSectorInfo[i].vMax1 = 0.; + for (int32_t j = 0; j < mGeo.getNumberOfRows(); j++) { + auto& row = mSectorRowInfos[mGeo.getMaxNumberOfRows() * i + j]; + row.splineScenarioID = -1; + row.gridReal = {}; + row.gridMeasured = {}; + row.dataOffsetBytes[0] = 0; + row.dataOffsetBytes[1] = 0; + row.dataOffsetBytes[2] = 0; + row.minCorr[0] = 0; + row.minCorr[1] = 0; + row.minCorr[2] = 0; + row.maxCorr[0] = 0; + row.maxCorr[1] = 0; + row.maxCorr[2] = 0; + } } for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -268,18 +277,18 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& mScenarioPtr = nullptr; for (int32_t s = 0; s < 3; s++) { mSplineData[s] = nullptr; - mSectorDataSizeBytes[s] = 0; + mDataSizeBytes[s] = 0; } mClassVersion = 4; } -void TPCFastSpaceChargeCorrection::setRowScenarioID(int32_t iRow, int32_t iScenario) +void TPCFastSpaceChargeCorrection::setRowScenarioID(int32_t iSector, int32_t iRow, int32_t iScenario) { /// Initializes a TPC row assert(mConstructionMask & ConstructionState::InProgress); + assert(iSector >= 0 && iSector < mGeo.getNumberOfSectors()); assert(iRow >= 0 && iRow < mGeo.getNumberOfRows() && iScenario >= 0 && iScenario < mNumberOfScenarios); - - RowInfo& row = mRowInfos[iRow]; + auto& row = getSectorRowInfo(iSector, iRow); row.splineScenarioID = iScenario; for (int32_t s = 0; s < 3; s++) { row.dataOffsetBytes[s] = 0; @@ -302,9 +311,14 @@ void TPCFastSpaceChargeCorrection::finishConstruction() assert(mConstructionMask & ConstructionState::InProgress); - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - assert(mRowInfos[i].splineScenarioID >= 0); + for (int32_t i = 0; i < mGeo.getNumberOfSectors(); i++) { + for (int32_t j = 0; j < mGeo.getNumberOfRows(); j++) { + SectorRowInfo& row = getSectorRowInfo(i, j); + assert(row.splineScenarioID >= 0); + assert(row.splineScenarioID < mNumberOfScenarios); + } } + for (int32_t i = 0; i < mNumberOfScenarios; i++) { assert(mConstructionScenarios[i].isConstructed()); } @@ -324,18 +338,20 @@ void TPCFastSpaceChargeCorrection::finishConstruction() scBufferSize = alignSize(scBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); } size_t bufferSize = scBufferOffsets[0] + scBufferSize; - size_t sectorDataOffset[3]; + size_t splineDataOffset[3]; for (int32_t is = 0; is < 3; is++) { - sectorDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mSectorDataSizeBytes[is] = 0; - for (int32_t i = 0; i < mGeo.getNumberOfRows(); i++) { - RowInfo& row = mRowInfos[i]; - SplineType& spline = mConstructionScenarios[row.splineScenarioID]; - row.dataOffsetBytes[is] = alignSize(mSectorDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - mSectorDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); + splineDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mDataSizeBytes[is] = 0; + for (int32_t i = 0; i < mGeo.getNumberOfSectors(); i++) { + for (int32_t j = 0; j < mGeo.getNumberOfRows(); j++) { + SectorRowInfo& row = getSectorRowInfo(i, j); + SplineType& spline = mConstructionScenarios[row.splineScenarioID]; + row.dataOffsetBytes[is] = alignSize(mDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + mDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); + } } - mSectorDataSizeBytes[is] = alignSize(mSectorDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - bufferSize = sectorDataOffset[is] + mSectorDataSizeBytes[is] * mGeo.getNumberOfSectors(); + mDataSizeBytes[is] = alignSize(mDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); + bufferSize = splineDataOffset[is] + mDataSizeBytes[is]; } FlatObject::finishConstruction(bufferSize); @@ -350,7 +366,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() } for (int32_t is = 0; is < 3; is++) { - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + sectorDataOffset[is]); + mSplineData[is] = reinterpret_cast(mFlatBufferPtr + splineDataOffset[is]); } releaseConstructionMemory(); @@ -363,9 +379,9 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() { // initialise all corrections to 0. for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { - double vLength = mGeo.getTPCzLength(); - SectorInfo& sectorInfo = getSectorInfo(sector); - sectorInfo.vMax = vLength; + + getSectorInfo(sector).vMax1 = mGeo.getTPCzLength(); + for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { const SplineType& spline = getSpline(sector, row); @@ -385,10 +401,12 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() SectorRowInfo& info = getSectorRowInfo(sector, row); - info.gridMeasured.y0 = mGeo.getRowInfo(row).getYmin(); - info.gridMeasured.yScale = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getYwidth(); - info.gridMeasured.l0 = 0.f; - info.gridMeasured.lScale = spline.getGridX2().getUmax() / vLength; + float y0 = mGeo.getRowInfo(row).getYmin(); + float yScale = spline.getGridX1().getUmax() / mGeo.getRowInfo(row).getYwidth(); + float z0 = mGeo.getZmin(sector); + float zScale = spline.getGridX2().getUmax() / mGeo.getTPCzLength(); + float zReadout = mGeo.getZreadout(sector); + info.gridMeasured.set(y0, yScale, z0, zScale, zReadout, zReadout); info.gridReal = info.gridMeasured; } // row @@ -399,8 +417,10 @@ void TPCFastSpaceChargeCorrection::constructWithNoCorrection(const TPCFastTransf { const int32_t nCorrectionScenarios = 1; startConstruction(geo, nCorrectionScenarios); - for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { - setRowScenarioID(row, 0); + for (int32_t sector = 0; sector < geo.getNumberOfSectors(); sector++) { + for (int32_t row = 0; row < geo.getNumberOfRows(); row++) { + setRowScenarioID(sector, row, 0); + } } { TPCFastSpaceChargeCorrection::SplineType spline; @@ -456,20 +476,13 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) if (prn) { LOG(info) << "check inverse transform for sector " << sector; } - double vLength = mGeo.getTPCzLength(); + MaxValue maxDsector[3]; for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { double x = mGeo.getRowInfo(row).x; auto [y0, y1] = mGeo.getRowInfo(row).getYrange(); auto [z0, z1] = mGeo.getZrange(sector); - // grid borders - if (sector < mGeo.getNumberOfSectorsA()) { - z1 = vLength - getSectorRowInfo(sector, row).gridMeasured.l0; - } else { - z0 = getSectorRowInfo(sector, row).gridMeasured.l0 - vLength; - } - double stepY = (y1 - y0) / 100.; double stepZ = (z1 - z0) / 100.; MaxValue maxDrow[3]; @@ -479,7 +492,7 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) double realX = x + dx; double realY = y + dy; double realZ = z + dz; - if (!isLocalInsideGrid(sector, row, y, z) || !isLocalInsideGrid(sector, row, realY, realZ)) { + if (!isLocalInsideGrid(sector, row, y, z) || !isRealLocalInsideGrid(sector, row, realY, realZ)) { continue; } double r2 = realX * realX + realY * realY; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 4564d584c8dce..7112a04b364c6 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -43,31 +43,58 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// \brief The struct contains necessary info for TPC padrow /// struct RowInfo { - int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) - size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing the TPC sector ClassDefNV(RowInfo, 1); }; struct GridInfo { - float y0{0.f}; ///< Y coordinate of the U-grid start - float yScale{0.f}; //< scale Y to U-grid coordinate - float l0{0.f}; ///< Drift Length coordinate of the V-grid start - float lScale{0.f}; //< scale Drift Length to V-grid coordinate + private: + float y0{0.f}; ///< Y coordinate of the U-grid start + float yScale{0.f}; //< scale Y to U-grid coordinate + float z0{0.f}; ///< Z coordinate of the V-grid start + float zScale{0.f}; //< scale Z to V-grid coordinate + float zOut{0.f}; // outer z of the grid; + float splineScalingWithZ{0.f}; ///< spline scaling factor in the Z region between the zOut and the readout plane + + public: + void set(float y0, float yScale, float z0, float zScale, float zOut, float zReadout) + { + this->y0 = y0; + this->yScale = yScale; + this->z0 = z0; + this->zScale = zScale; + this->zOut = zOut; + // no scaling when the distance to the readout is too small + this->splineScalingWithZ = fabs(zReadout - zOut) > 1. ? 1. / (zReadout - zOut) : 0.; + } + + float getY0() const { return y0; } + float getYscale() const { return yScale; } + float getZ0() const { return z0; } + float getZscale() const { return zScale; } + + float getSpineScaleForZ(float z) const + { + return 1.f - GPUCommonMath::Clamp((z - zOut) * splineScalingWithZ, 0.f, 1.f); + } + + /// convert local y, z to internal grid coordinates u,v, and spline scale + std::tuple convLocalToGridUntruncated(float y, float z) const + { + return {(y - y0) * yScale, (z - z0) * zScale, getSpineScaleForZ(z)}; + } - float getScale(float l) const + /// convert internal grid coordinates u,v to local y, z + std::tuple convGridToLocal(float gridU, float gridV) const { - if (l < 0.f) { // outside of the TPC - return 0.f; - } - if (l < l0) { // between the grid and the readout - return l / l0; - } - return 1.f; // inside the grid + return {y0 + gridU / yScale, z0 + gridV / zScale}; } ClassDefNV(GridInfo, 1); }; struct SectorRowInfo { + int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC sector + GridInfo gridMeasured; ///< grid info for measured coordinates GridInfo gridReal; ///< grid info for real coordinates @@ -118,7 +145,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject }; struct SectorInfo { - float vMax{0.f}; ///< Max value of V coordinate + float vMax1{0.f}; ///< Max value of V coordinate ClassDefNV(SectorInfo, 1); }; @@ -170,7 +197,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject void startConstruction(const TPCFastTransformGeo& geo, int32_t numberOfSplineScenarios); /// Initializes a TPC row - void setRowScenarioID(int32_t iRow, int32_t iScenario); + void setRowScenarioID(int32_t iSector, int32_t iRow, int32_t iScenario); /// Sets approximation scenario void setSplineScenario(int32_t scenarioIndex, const SplineType& spline); @@ -259,6 +286,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() std::tuple convGridToRealLocal(int32_t sector, int32_t row, float u, float v) const; GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; + GPUd() bool isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; /// TPC geometry information GPUd() const TPCFastTransformGeo& getGeometry() const @@ -333,7 +361,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject char* mSplineData[3]; //! (transient!!) pointer to the spline data in the flat buffer - size_t mSectorDataSizeBytes[3]; ///< size of the data for one sector in the flat buffer + size_t mDataSizeBytes[3]; ///< size of the data for one sector in the flat buffer float fInterpolationSafetyMargin{0.1f}; // 10% area around the TPC row. Outside of this area the interpolation returns the boundary values. @@ -356,29 +384,25 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUdi() const TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t sector, int32_t row) const { /// Gives const pointer to spline - const RowInfo& rowInfo = mRowInfos[row]; - return mScenarioPtr[rowInfo.splineScenarioID]; + return mScenarioPtr[getSectorRowInfo(sector, row).splineScenarioID]; } GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection::getSpline(int32_t sector, int32_t row) { /// Gives pointer to spline - const RowInfo& rowInfo = mRowInfos[row]; - return mScenarioPtr[rowInfo.splineScenarioID]; + return mScenarioPtr[getSectorRowInfo(sector, row).splineScenarioID]; } GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) { /// Gives pointer to spline data - const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mSectorDataSizeBytes[iSpline] * sector + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); } GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) const { /// Gives pointer to spline data - const RowInfo& rowInfo = mRowInfos[row]; - return reinterpret_cast(mSplineData[iSpline] + mSectorDataSizeBytes[iSpline] * sector + rowInfo.dataOffsetBytes[iSpline]); + return reinterpret_cast(mSplineData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); } GPUdi() TPCFastSpaceChargeCorrection::SplineTypeInvX& TPCFastSpaceChargeCorrection::getSplineInvX(int32_t sector, int32_t row) @@ -433,37 +457,35 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convLocalT { /// convert local y, z to internal grid coordinates u,v /// return values: u, v, scaling factor - const auto& info = getSectorRowInfo(sector, row); const SplineType& spline = getSpline(sector, row); - - float l = mGeo.convZtoDriftLength(sector, z); - float scale = info.gridMeasured.getScale(l); - float gridU = (y - info.gridMeasured.y0) * info.gridMeasured.yScale; - float gridV = (l - info.gridMeasured.l0) * info.gridMeasured.lScale; - - // shrink to the grid area + auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); + // shrink to the grid gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - return {gridU, gridV, scale}; } GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const { - /// ccheck if local y, z are inside the grid - - const auto& info = getSectorRowInfo(sector, row); + /// check if local y, z are inside the grid + auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); const auto& spline = getSpline(sector, row); - float l = mGeo.convZtoDriftLength(sector, z); - - float gridU = (y - info.gridMeasured.y0) * info.gridMeasured.yScale; - float gridV = (l - info.gridMeasured.l0) * info.gridMeasured.lScale; - - // shrink to the grid area - if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax()) { + // shrink to the grid + if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax() || // + gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { return false; } - if (gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { + return true; +} + +GPUdi() bool TPCFastSpaceChargeCorrection::isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// check if local y, z are inside the grid + auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + const auto& spline = getSpline(sector, row); + // shrink to the grid + if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax() || // + gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { return false; } return true; @@ -472,39 +494,24 @@ GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToLocal(int32_t sector, int32_t row, float gridU, float gridV) const { /// convert internal grid coordinates u,v to local y, z - const SectorRowInfo& info = getSectorRowInfo(sector, row); - float y = info.gridMeasured.y0 + gridU / info.gridMeasured.yScale; - float l = info.gridMeasured.l0 + gridV / info.gridMeasured.lScale; - float z = mGeo.convDriftLengthToZ(sector, l); - return {y, z}; + return getSectorRowInfo(sector, row).gridMeasured.convGridToLocal(gridU, gridV); } GPUdi() std::tuple TPCFastSpaceChargeCorrection::convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const { /// convert real y, z to the internal grid coordinates + scale - const auto& info = getSectorRowInfo(sector, row); - const auto& spline = getSpline(sector, row); - - float l = mGeo.convZtoDriftLength(sector, z); - float scale = info.gridReal.getScale(l); - float gridU = (y - info.gridReal.y0) * info.gridReal.yScale; - float gridV = (l - info.gridReal.l0) * info.gridReal.lScale; - - // shrink to the grid area + const SplineType& spline = getSpline(sector, row); + auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + // shrink to the grid gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - return {gridU, gridV, scale}; } GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const { /// convert internal grid coordinates u,v to the real y, z - const SectorRowInfo& info = getSectorRowInfo(sector, row); - float y = info.gridReal.y0 + gridU / info.gridReal.yScale; - float l = info.gridReal.l0 + gridV / info.gridReal.lScale; - float z = mGeo.convDriftLengthToZ(sector, l); - return {y, z}; + return getSectorRowInfo(sector, row).gridReal.convGridToLocal(gridU, gridV); } GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const diff --git a/GPU/TPCFastTransformation/TPCFastTransform.cxx b/GPU/TPCFastTransformation/TPCFastTransform.cxx index 625f70c1710a1..42c4c57ffa086 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransform.cxx @@ -103,10 +103,6 @@ void TPCFastTransform::startConstruction(const TPCFastSpaceChargeCorrection& cor mApplyCorrection = 1; mT0 = 0.f; mVdrift = 0.f; - mVdriftCorrY = 0.f; - mLdriftCorr = 0.f; - mTOFcorr = 0.f; - mPrimVtxZ = 0.f; mLumi = DEFLUMI; mLumiError = 0.f; mIDC = DEFIDC; diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 8807c0e3206f4..3b08296525fc7 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -551,7 +551,7 @@ GPUdi() void TPCFastTransform::Transform(int32_t sector, int32_t row, float pad, GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const { float l = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm - z = getGeometry().convDriftLengthToZ(sector, l); + z = getGeometry().convDriftLengthToZ1(sector, l); } GPUdi() void TPCFastTransform::TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const @@ -590,7 +590,7 @@ GPUdi() void TPCFastTransform::TransformIdealZ(int32_t sector, float time, float /// float l = (time - mT0 - vertexTime) * mVdrift; // drift length cm - z = getGeometry().convDriftLengthToZ(sector, l); + z = getGeometry().convDriftLengthToZ1(sector, l); } GPUdi() void TPCFastTransform::TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index bbb94dcb8bedd..89b099ec63127 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -126,6 +126,9 @@ class TPCFastTransformGeo /// Gives Z range for the corresponding TPC side GPUd() std::tuple getZrange(int32_t sector) const; + GPUd() float getZmin(int32_t sector) const; + GPUd() float getZmax(int32_t sector) const; + GPUd() float getZreadout(int32_t sector) const; /// _______________ Conversion of coordinate systems __________ @@ -139,10 +142,10 @@ class TPCFastTransformGeo GPUd() std::tuple convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const; /// convert DriftLength -> Local c.s. - GPUd() float convDriftLengthToZ(int32_t sector, float driftLength) const; + GPUd() float convDriftLengthToZ1(int32_t sector, float driftLength) const; /// convert Z to DriftLength - GPUd() float convZtoDriftLength(int32_t sector, float z) const; + GPUd() float convZtoDriftLength1(int32_t sector, float z) const; /// convert Local c.s. -> Pad, DriftLength GPUd() std::tuple convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const; @@ -181,7 +184,7 @@ class TPCFastTransformGeo float mTPCzLength = 0.f; ///< Z length of one TPC side (A or C) SectorInfo mSectorInfos[NumberOfSectors + 1]; ///< array of sector information [fixed size] - RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] + RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] ClassDefNV(TPCFastTransformGeo, 3); }; @@ -242,13 +245,13 @@ GPUdi() std::tuple TPCFastTransformGeo::convPadDriftLengthToLocal( return {y, z}; } -GPUdi() float TPCFastTransformGeo::convDriftLengthToZ(int32_t sector, float driftLength) const +GPUdi() float TPCFastTransformGeo::convDriftLengthToZ1(int32_t sector, float driftLength) const { /// convert DriftLength -> Local c.s. return (sector < NumberOfSectorsA) ? (mTPCzLength - driftLength) : (driftLength - mTPCzLength); } -GPUdi() float TPCFastTransformGeo::convZtoDriftLength(int32_t sector, float z) const +GPUdi() float TPCFastTransformGeo::convZtoDriftLength1(int32_t sector, float z) const { /// convert Z to DriftLength return (sector < NumberOfSectorsA) ? (mTPCzLength - z) : (z + mTPCzLength); @@ -264,6 +267,36 @@ GPUdi() std::tuple TPCFastTransformGeo::getZrange(int32_t sector) } } +GPUdi() float TPCFastTransformGeo::getZmin(int32_t sector) const +{ + /// z min for the sector + if (sector < NumberOfSectorsA) { // TPC side A + return 0.f; + } else { // TPC side C + return -mTPCzLength; + } +} + +GPUdi() float TPCFastTransformGeo::getZmax(int32_t sector) const +{ + /// z max for the sector + if (sector < NumberOfSectorsA) { // TPC side A + return mTPCzLength; + } else { // TPC side C + return 0.f; + } +} + +GPUdi() float TPCFastTransformGeo::getZreadout(int32_t sector) const +{ + /// z readout for the sector + if (sector < NumberOfSectorsA) { // TPC side A + return mTPCzLength; + } else { // TPC side C + return -mTPCzLength; + } +} + GPUdi() std::tuple TPCFastTransformGeo::convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const { /// convert Local c.s. -> Pad, DriftLength diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index fc15506d5397c..916695a3be1c7 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -70,6 +70,7 @@ #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorRowInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::GridInfo + ; #pragma link C++ class o2::gpu::CorrectionMapsHelper + ; #pragma link C++ struct o2::gpu::MultivariatePolynomialContainer + ; diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index f0c03d9f5f081..974582792266b 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -150,7 +150,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* o2::tpc::TPCFastSpaceChargeCorrectionHelper* corrHelper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); corrHelper->setNthreadsToMaximum(); - // corrHelper->setNthreads(1); + corrHelper->setNthreads(1); auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns); @@ -185,10 +185,10 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { auto& info = corr.getSectorRowInfo(iSector, iRow); std::cout << "sector " << iSector << " row " << iRow - << " gridY0 " << info.gridMeasured.y0 << " gridL0 " << info.gridMeasured.l0 - << " scaleYtoGrid " << info.gridMeasured.yScale << " scaleLtoGrid " << info.gridMeasured.lScale - << " gridRealY0 " << info.gridReal.y0 << " gridRealL0 " << info.gridReal.l0 - << " scaleRealYtoGrid " << info.gridReal.yScale << " scaleRealLtoGrid " << info.gridReal.lScale + << " gridY0 " << info.gridMeasured.getY0() << " gridZ0 " << info.gridMeasured.getZ0() + << " scaleYtoGrid " << info.gridMeasured.getYscale() << " scaleLtoGrid " << info.gridMeasured.getZscale() + << " gridRealY0 " << info.gridReal.getY0() << " gridRealZ0 " << info.gridReal.getZ0() + << " scaleRealYtoGrid " << info.gridReal.getYscale() << " scaleRealLtoGrid " << info.gridReal.getZscale() << std::endl; } } @@ -379,7 +379,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* const auto& gridY = corr.getSpline(iSector, iRow).getGridX1(); const auto& gridZ = corr.getSpline(iSector, iRow).getGridX2(); if (iSector == 0 && iRow == 0) { - std::cout << "spline scenario " << corr.getRowInfo(iRow).splineScenarioID << std::endl; + std::cout << "spline scenario " << corr.getSectorRowInfo(iSector, iRow).splineScenarioID << std::endl; std::cout << "spline grid Y: u = " << 0 << ".." << gridY.getUmax() << ", x = " << gridY.getXmin() << ".." << gridY.getXmax() << std::endl; std::cout << "spline grid Z: u = " << 0 << ".." << gridZ.getUmax() << ", x = " << gridZ.getXmin() << ".." << gridZ.getXmax() << std::endl; } From 4ccb9f9f06d00496635243a73eef4cd231627f6c Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 20 Aug 2025 07:50:56 +0000 Subject: [PATCH 18/26] TPC Splines: correct biased voxels; features for debugging --- .../TPCFastSpaceChargeCorrectionHelper.h | 32 +- .../TPCFastSpaceChargeCorrectionHelper.cxx | 75 ++- .../macro/TPCFastTransformInit.C | 521 +++++++++++------- 3 files changed, 419 insertions(+), 209 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h index e8afd9be97d5f..40c5634b4f1e8 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/TPCFastSpaceChargeCorrectionHelper.h @@ -90,11 +90,16 @@ class TPCFastSpaceChargeCorrectionHelper /// \param voxResTreeInverse TTree with inverse voxel residuals /// \param useSmoothed if true, use smoothed residuals /// \param invertSigns if true, invert the signs of the residuals + /// \param fitPointsDirect debug: pointer to the data used for the direct correction + /// \param fitPointsInverse debug: pointer to the data used for the inverse correction /// \return pointer to the created TPCFastSpaceChargeCorrection object /// \note voxel trees wont be changed. They are read as non-const because of the ROOT::TTreeProcessorMT interface + /// std::unique_ptr createFromTrackResiduals( const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, // - bool useSmoothed, bool invertSigns); + bool useSmoothed, bool invertSigns, // + TPCFastSpaceChargeCorrectionMap* fitPointsDirect = nullptr, + TPCFastSpaceChargeCorrectionMap* fitPointsInverse = nullptr); /// _______________ Utilities ________________________ @@ -116,10 +121,28 @@ class TPCFastSpaceChargeCorrectionHelper /// \param additionalCorrections vector of pairs of additional corrections and their scaling factors /// \param prn printout flag /// \return main correction merged with additional corrections - void MergeCorrections( + void mergeCorrections( o2::gpu::TPCFastSpaceChargeCorrection& mainCorrection, float scale, const std::vector>& additionalCorrections, bool prn); + /// how far the voxel mean is allowed to be outside of the voxel (1.1 means 10%) + void setVoxelMeanValidityRange(double range) + { + mVoxelMeanValidityRange = range; + } + + double getVoxelMeanValidityRange() const { return mVoxelMeanValidityRange; } + + /// debug: if true, use voxel centers instead of the fitted positions for correction + void setDebugUseVoxelCenters(); + + bool isDebugUseVoxelCenters() const { return mDebugUseVoxelCenters; } + + /// debug: if true, mirror the data from the A side to the C side of the TPC + void setDebugMirrorAdata2C(); + + bool isDebugMirrorAdata2C() const { return mDebugMirrorAdata2C; } + private: /// geometry initialization void initGeometry(); @@ -133,6 +156,11 @@ class TPCFastSpaceChargeCorrectionHelper TPCFastSpaceChargeCorrectionMap mCorrectionMap{0, 0}; + double mVoxelMeanValidityRange{1.1}; ///< debug: how far the voxel mean is allowed to be outside of the voxel (1.1 means 10%) + + bool mDebugUseVoxelCenters{false}; ///< debug: if true, use voxel centers instead of the fitted positions for correction + bool mDebugMirrorAdata2C{false}; ///< debug: if true, mirror the data from the A side to the C side of the TPC + ClassDefNV(TPCFastSpaceChargeCorrectionHelper, 0); }; diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index d2f6cf57b0de7..6122c5717fcbb 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -33,6 +33,7 @@ #include "TTreeReaderValue.h" #include "ROOT/TTreeProcessorMT.hxx" #include +#include using namespace o2::gpu; @@ -381,7 +382,9 @@ void TPCFastSpaceChargeCorrectionHelper::testGeometry(const TPCFastTransformGeo& } std::unique_ptr TPCFastSpaceChargeCorrectionHelper::createFromTrackResiduals( - const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, bool useSmoothed, bool invertSigns) + const o2::tpc::TrackResiduals& trackResiduals, TTree* voxResTree, TTree* voxResTreeInverse, bool useSmoothed, bool invertSigns, + TPCFastSpaceChargeCorrectionMap* fitPointsDirect, + TPCFastSpaceChargeCorrectionMap* fitPointsInverse) { // create o2::gpu::TPCFastSpaceChargeCorrection from o2::tpc::TrackResiduals::VoxRes voxel tree @@ -603,6 +606,24 @@ std::unique_ptr TPCFastSpaceChargeCorrect processor.Process(myThread); } + // debug: mirror the data for TPC C side + + if (mDebugMirrorAdata2C) { + for (int iSector = 0; iSector < geo.getNumberOfSectorsA(); iSector++) { + for (int iRow = 0; iRow < nRows; iRow++) { + for (int iy = 0; iy < nY2Xbins; iy++) { + for (int iz = 0; iz < nZ2Xbins; iz++) { + auto& dataA = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; + auto& dataC = vSectorData[(iSector + geo.getNumberOfSectorsA()) * nRows + iRow][iy * nZ2Xbins + iz]; + dataC = dataA; // copy the data + dataC.mZ = -dataC.mZ; // mirror the Z coordinate + dataC.mCz = -dataC.mCz; // mirror the Z correction + } + } + } + } + } + for (int iSector = 0; iSector < nSectors; iSector++) { // now process the data row-by-row @@ -623,6 +644,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect { int xBin = iRow; double x = trackResiduals.getX(xBin); // radius of the pad row + double dx = 1. / trackResiduals.getDXI(xBin); bool isDataFound = false; for (int iy = 0; iy < nY2Xbins; iy++) { for (int iz = 0; iz < nZ2Xbins; iz++) { @@ -642,13 +664,29 @@ std::unique_ptr TPCFastSpaceChargeCorrect if (data.mNentries > 0) { // voxel contains data vox.mSmoothingStep = 0; // take original data isDataFound = true; - if (fabs(x - data.mX) > 1. || fabs(vox.mY - data.mY) > 5. || fabs(vox.mZ - data.mZ) > 5.) { - std::cout << directionName << ": fitted voxel is too far from the nominal position: " - << " sector " << iSector << " row " << iRow - << " center x " << x << " y " << vox.mY << " z " << vox.mZ - << " fitted x " << data.mX << " y " << data.mY << " z " << data.mZ - << std::endl; + + // correct the mean position if it is outside the voxel + std::stringstream msg; + if (fabs(x - data.mX) > mVoxelMeanValidityRange * dx / 2.) { + msg << "\n x: center " << x << " dx " << data.mX - x << " half bin size: " << dx / 2; + } + + if (fabs(vox.mY - data.mY) > mVoxelMeanValidityRange * vox.mDy / 2.) { + msg << "\n y: center " << vox.mY << " dy " << data.mY - vox.mY << " half bin size: " << vox.mDy / 2; + data.mY = vox.mY; + } + + if (fabs(vox.mZ - data.mZ) > mVoxelMeanValidityRange * vox.mDz / 2.) { + msg << "\n z: center " << vox.mZ << " dz " << data.mZ - vox.mZ << " half bin size: " << vox.mDz / 2; + data.mZ = vox.mZ; } + + if (!msg.str().empty()) { + LOG(warning) << directionName << " correction: fitted voxel position is outside the voxel: " + << " sector " << iSector << " row " << iRow << " bin: " << iy << " " << iz + << msg.str(); + } + } else { // no data, take voxel center position data.mCx = 0.; data.mCy = 0.; @@ -658,7 +696,7 @@ std::unique_ptr TPCFastSpaceChargeCorrect data.mZ = vox.mZ; vox.mSmoothingStep = 100; // fill this data point with smoothed values from the neighbours } - if (0) { // debug: always use voxel center instead of the mean position + if (mDebugUseVoxelCenters) { // debug: always use voxel center instead of the mean position data.mY = vox.mY; data.mZ = vox.mZ; } @@ -809,6 +847,13 @@ std::unique_ptr TPCFastSpaceChargeCorrect TStopwatch watch4; + if (!processingInverseCorrection && fitPointsDirect) { + *fitPointsDirect = helper->getCorrectionMap(); + } + if (processingInverseCorrection && fitPointsInverse) { + *fitPointsInverse = helper->getCorrectionMap(); + } + helper->fillSpaceChargeCorrectionFromMap(correction, processingInverseCorrection); LOG(info) << "fast space charge correction helper: creation from the data map took " << watch4.RealTime() << "s"; @@ -956,7 +1001,7 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector>& additionalCorrections, bool /*prn*/) { @@ -1099,5 +1144,17 @@ void TPCFastSpaceChargeCorrectionHelper::MergeCorrections( LOGP(info, "Merge of corrections tooks: {}s", duration); } +void TPCFastSpaceChargeCorrectionHelper::setDebugUseVoxelCenters() +{ + LOG(info) << "fast space charge correction helper: use voxel centers for correction"; + mDebugUseVoxelCenters = true; +} + +void TPCFastSpaceChargeCorrectionHelper::setDebugMirrorAdata2C() +{ + LOG(info) << "fast space charge correction helper: mirror A data to C data"; + mDebugMirrorAdata2C = true; +} + } // namespace tpc } // namespace o2 diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 974582792266b..50b667bb3e023 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -56,13 +56,14 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* To visiualise the results: root -l transformDebug.root - corr->Draw("cx:y:z","iSector==0&&iRow==10","") - grid->Draw("cx:y:z","iSector==0&&iRow==10","same") - vox->Draw("vx:y:z","iSector==0&&iRow==10","same") - corrvox->Draw("cx:y:z","iSector==0&&iRow==10","same") - points->Draw("px:y:z","iSector==0&&iRow==10","same") + all->Draw("cx:y:z","sec==0&&iRow==10","") + grid->Draw("cx:y:z","sec==0&&iRow==10","same") + vox->Draw("vx:y:z","sec==0&&iRow==10","same") + points->Draw("px:y:z","sec==0&&row==10","same") */ + const bool debugMirrorAdata2C = 0; + if (gSystem->AccessPathName(fileName)) { std::cout << " input file " << fileName << " does not exist!" << std::endl; return; @@ -152,7 +153,15 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* corrHelper->setNthreadsToMaximum(); corrHelper->setNthreads(1); - auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns); + if (debugMirrorAdata2C) { + corrHelper->setDebugMirrorAdata2C(); + } + // corrHelper->setDebugUseVoxelCenters(); + + o2::gpu::TPCFastSpaceChargeCorrectionMap mapDirect(0, 0), mapInverse(0, 0); + + auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns, + &mapDirect, &mapInverse); std::unique_ptr fastTransform( helper->create(0, *corrPtr)); @@ -199,15 +208,6 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* o2::gpu::TPCFastSpaceChargeCorrection& corr = fastTransform->getCorrection(); - // the difference - - double maxDiff[3] = {0., 0., 0.}; - int32_t maxDiffSector[3] = {0, 0, 0}; - int32_t maxDiffRow[3] = {0, 0, 0}; - - double sumDiff[3] = {0., 0., 0.}; - int64_t nDiff = 0; - // a debug file with some NTuples TDirectory* currDir = gDirectory; @@ -220,46 +220,77 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* // measured x,y,z; corrections cx,cy,cz from the measured to the real x,y,z; // inverse corrections ix,iy,iz at the real position (x+cx,y+cy,z+cz) // ideally, ix = cx, iy = cy, iz = cz - TNtuple* debugCorr = new TNtuple("corr", "corr", "iSector:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); + TNtuple* ntAll = new TNtuple("all", "all", + debugMirrorAdata2C ? "sec:row:x:y:z:cx:cy:cz:ix:iy:iz:cxC:cyC:czC:ixC:iyC:izC" + : "sec:row:x:y:z:cx:cy:cz:ix:iy:iz"); - debugCorr->SetMarkerStyle(8); - debugCorr->SetMarkerSize(0.1); - debugCorr->SetMarkerColor(kBlack); + ntAll->SetMarkerStyle(8); + ntAll->SetMarkerSize(0.1); + ntAll->SetMarkerColor(kBlack); - // ntuple with the input data: voxels and corrections debugFile->cd(); - TNtuple* debugVox = - new TNtuple("vox", "vox", "iSector:iRow:n:x:y:z:vx:vy:vz"); + TNtuple* ntInvAll = new TNtuple("invall", "invall", + debugMirrorAdata2C ? "sec:row:x:y:z:cx:cy:cz:cxC:cyC:czC" + : "sec:row:x:y:z:cx:cy:cz"); - debugVox->SetMarkerStyle(8); - debugVox->SetMarkerSize(0.8); - debugVox->SetMarkerColor(kBlue); + ntInvAll->SetMarkerStyle(8); + ntInvAll->SetMarkerSize(0.1); + ntInvAll->SetMarkerColor(kBlack); // duplicate of debugVox + the spline data at voxels in a different color debugFile->cd(); - TNtuple* debugCorrVox = - new TNtuple("corrvox", "corrvox", "iSector:iRow:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz"); + TNtuple* ntVox = + new TNtuple("vox", "vox", + debugMirrorAdata2C ? "sec:row:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz:cxC:cyC:czC:ixC:iyC:izC" + : "sec:row:n:x:y:z:vx:vy:vz:cx:cy:cz:ix:iy:iz"); - debugCorrVox->SetMarkerStyle(8); - debugCorrVox->SetMarkerSize(0.8); - debugCorrVox->SetMarkerColor(kMagenta); + ntVox->SetMarkerStyle(8); + ntVox->SetMarkerSize(0.8); + ntVox->SetMarkerColor(kMagenta); + + // duplicate of debugVox + the spline data at voxels in a different color + debugFile->cd(); + TNtuple* ntInvVox = + new TNtuple("invvox", "invvox", + debugMirrorAdata2C ? "sec:row:n:x:y:z:vx:vy:vz:cx:cy:cz:cxC:cyC:czC" + : "sec:row:n:x:y:z:vx:vy:vz:cx:cy:cz"); + + ntInvVox->SetMarkerStyle(8); + ntInvVox->SetMarkerSize(0.8); + ntInvVox->SetMarkerColor(kMagenta); + + // corrections at the spline grid points + debugFile->cd(); + TNtuple* ntGrid = new TNtuple("grid", "grid", "sec:row:x:y:z:cx:cy:cz:ix:iy:iz"); + + ntGrid->SetMarkerStyle(8); + ntGrid->SetMarkerSize(1.2); + ntGrid->SetMarkerColor(kBlack); // corrections at the spline grid points debugFile->cd(); - TNtuple* debugGrid = new TNtuple("grid", "grid", "iSector:iRow:x:y:z:cx:cy:cz:ix:iy:iz"); + TNtuple* ntInvGrid = new TNtuple("invgrid", "invgrid", "sec:row:x:y:z:cx:cy:cz"); - debugGrid->SetMarkerStyle(8); - debugGrid->SetMarkerSize(1.2); - debugGrid->SetMarkerColor(kBlack); + ntInvGrid->SetMarkerStyle(8); + ntInvGrid->SetMarkerSize(1.2); + ntGrid->SetMarkerColor(kBlack); // ntuple with data points created from voxels (with the data smearing, extension to the edges etc.) debugFile->cd(); - TNtuple* debugPoints = - new TNtuple("points", "points", "iSector:iRow:x:y:z:px:py:pz:cx:cy:cz"); + TNtuple* ntFitPoints = + new TNtuple("fitpoints", "fit points", "sec:row:x:y:z:px:py:pz:cx:cy:cz"); - debugPoints->SetMarkerStyle(8); - debugPoints->SetMarkerSize(0.4); - debugPoints->SetMarkerColor(kRed); + ntFitPoints->SetMarkerStyle(8); + ntFitPoints->SetMarkerSize(0.4); + ntFitPoints->SetMarkerColor(kRed); + + debugFile->cd(); + TNtuple* ntInvFitPoints = + new TNtuple("invfitpoints", "fit points", "sec:row:x:y:z:px:py:pz:cx:cy:cz"); + + ntInvFitPoints->SetMarkerStyle(8); + ntInvFitPoints->SetMarkerSize(0.4); + ntInvFitPoints->SetMarkerColor(kRed); currDir->cd(); @@ -269,224 +300,318 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* const o2::gpu::TPCFastTransformGeo& geo = helper->getGeometry(); + auto getInvCorrections = [&](int iSector, int iRow, float realY, float realZ, float& ix, float& iy, float& iz) { + // get the inverse corrections ix, iy, iz at x,y,z + ix = corr.getCorrectionXatRealYZ(iSector, iRow, realY, realZ); + std::tie(iy, iz) = corr.getCorrectionYZatRealYZ(iSector, iRow, realY, realZ); + }; + auto getAllCorrections = [&](int iSector, int iRow, float y, float z, float& cx, float& cy, float& cz, float& ix, float& iy, float& iz) { // get the corrections cx,cy,cz at x,y,z std::tie(cx, cy, cz) = corr.getCorrectionLocal(iSector, iRow, y, z); - float realY = y + cy; - float realZ = z + cz; - ix = corr.getCorrectionXatRealYZ(iSector, iRow, realY, realZ); - std::tie(iy, iz) = corr.getCorrectionYZatRealYZ(iSector, iRow, realY, realZ); + getInvCorrections(iSector, iRow, y + cy, z + cz, ix, iy, iz); }; - o2::tpc::TrackResiduals::VoxRes* v = nullptr; - TBranch* branch = voxResTree->GetBranch("voxRes"); - branch->SetAddress(&v); - branch->SetAutoDelete(kTRUE); + for (int direction = 0; direction < 2; direction++) { // 0 - normal, 1 - inverse + + TTree* currentTree = (direction == 0) ? voxResTree : voxResTreeInverse; + if (!currentTree) { + std::cout << "tree voxResTree does not exist!" << std::endl; + return; + } - int32_t iSectorLast = -1; - int32_t iRowLast = -1; + o2::tpc::TrackResiduals::VoxRes* v = nullptr; + TBranch* branch = currentTree->GetBranch("voxRes"); + branch->SetAddress(&v); + branch->SetAutoDelete(kTRUE); - std::cout << "fill debug ntuples at voxels ..." << std::endl; + int32_t iSectorLast = -1; + int32_t iRowLast = -1; - for (int32_t iVox = 0; iVox < voxResTree->GetEntriesFast(); iVox++) { + // the difference - voxResTree->GetEntry(iVox); + double maxDiff[3] = {0., 0., 0.}; + int32_t maxDiffSector[3] = {0, 0, 0}; + int32_t maxDiffRow[3] = {0, 0, 0}; - float voxEntries = v->stat[o2::tpc::TrackResiduals::VoxV]; + double sumDiff[3] = {0., 0., 0.}; + int64_t nDiff = 0; - int32_t xBin = - v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) + std::cout << "fill debug ntuples at voxels ..." << std::endl; - int32_t y2xBin = - v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 + for (int32_t iVox = 0; iVox < currentTree->GetEntriesFast(); iVox++) { - int32_t z2xBin = - v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 + currentTree->GetEntry(iVox); - int32_t iSector = (int32_t)v->bsec; - int32_t iRow = (int32_t)xBin; + float voxEntries = v->stat[o2::tpc::TrackResiduals::VoxV]; - iSectorLast = iSector; - iRowLast = iRow; + int32_t xBin = + v->bvox[o2::tpc::TrackResiduals::VoxX]; // bin number in x (= pad row) - double x = trackResiduals.getX(xBin); // radius of the pad row + int32_t y2xBin = + v->bvox[o2::tpc::TrackResiduals::VoxF]; // bin number in y/x 0..14 - double y2x = trackResiduals.getY2X( - xBin, y2xBin); // y/x coordinate of the bin ~-0.15 ... 0.15 + int32_t z2xBin = + v->bvox[o2::tpc::TrackResiduals::VoxZ]; // bin number in z/x 0..4 - double z2x = - trackResiduals.getZ2X(z2xBin); // z/x coordinate of the bin 0.1 .. 0.9 + int32_t iSector = (int32_t)v->bsec; + int32_t iRow = (int32_t)xBin; - double y = x * y2x; - double z = x * z2x; + iSectorLast = iSector; + iRowLast = iRow; - if (iSector >= geo.getNumberOfSectorsA()) { - z = -z; - } + double x = trackResiduals.getX(xBin); // radius of the pad row - double correctionX = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; - double correctionY = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; - double correctionZ = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; + double y2x = trackResiduals.getY2X( + xBin, y2xBin); // y/x coordinate of the bin ~-0.15 ... 0.15 - if (invertSigns) { - correctionX *= -1.; - correctionY *= -1.; - correctionZ *= -1.; - } + double z2x = + trackResiduals.getZ2X(z2xBin); // z/x coordinate of the bin 0.1 .. 0.9 - if (voxEntries > 0.) { // use mean statistical positions instead of the bin centers: - y = x * v->stat[o2::tpc::TrackResiduals::VoxF]; - z = x * v->stat[o2::tpc::TrackResiduals::VoxZ]; - } + double y = x * y2x; + double z = x * z2x; + + double correctionX = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResX] : v->D[o2::tpc::TrackResiduals::ResX]; + double correctionY = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResY] : v->D[o2::tpc::TrackResiduals::ResY]; + double correctionZ = useSmoothed ? v->DS[o2::tpc::TrackResiduals::ResZ] : v->D[o2::tpc::TrackResiduals::ResZ]; + + double voxelSizeY = x / trackResiduals.getDY2XI(xBin, y2xBin); + double voxelSizeZ = x * trackResiduals.getDZ2X(z2xBin); + + if (invertSigns) { + correctionX *= -1.; + correctionY *= -1.; + correctionZ *= -1.; + } - float cx, cy, cz, ix, iy, iz; - getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); + if (!corrHelper->isDebugUseVoxelCenters()) { + if (voxEntries > 0.) { + // use mean statistical positions instead of the bin centers, unless they are wrong + double yFit = x * v->stat[o2::tpc::TrackResiduals::VoxF]; + if (fabs(yFit - y) <= corrHelper->getVoxelMeanValidityRange() * voxelSizeY / 2.) { + y = yFit; + } + double zFit = x * v->stat[o2::tpc::TrackResiduals::VoxZ]; + if (fabs(zFit - z) <= corrHelper->getVoxelMeanValidityRange() * voxelSizeZ / 2.) { + z = zFit; + } + } + } - if (voxEntries >= 1.) { - double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; + int mirrorSector = iSector + geo.getNumberOfSectorsA(); - for (int32_t i = 0; i < 3; i++) { - if (fabs(maxDiff[i]) < fabs(d[i])) { - maxDiff[i] = d[i]; - maxDiffSector[i] = iSector; - maxDiffRow[i] = iRow; - // std::cout << " sector " << iSector << " row " << iRow << " xyz " << i - // << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; + if (iSector >= geo.getNumberOfSectorsA()) { + z = -z; + mirrorSector = iSector - geo.getNumberOfSectorsA(); + } + + float cx{0.f}, cy{0.f}, cz{0.f}, ix{0.f}, iy{0.f}, iz{0.f}; + float cxC{0.f}, cyC{0.f}, czC{0.f}, ixC{0.f}, iyC{0.f}, izC{0.f}; + if (direction == 0) { + getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); + if (debugMirrorAdata2C) { + getAllCorrections(mirrorSector, iRow, y, -z, cxC, cyC, czC, ixC, iyC, izC); } - sumDiff[i] += d[i] * d[i]; + float ntEntry[] = {(float)iSector, (float)iRow, voxEntries, + (float)x, (float)y, (float)z, + (float)correctionX, (float)correctionY, (float)correctionZ, + (float)cx, (float)cy, (float)cz, + (float)ix, (float)iy, (float)iz, + (float)cxC, (float)cyC, (float)czC, (float)ixC, (float)iyC, (float)izC}; + + // fill the ntuple with the correction at the voxel + ntVox->Fill(ntEntry); + } else { + getInvCorrections(iSector, iRow, y, z, cx, cy, cz); + if (debugMirrorAdata2C) { + getInvCorrections(mirrorSector, iRow, y, -z, cxC, cyC, czC); + } + float ntEntry[] = {(float)iSector, (float)iRow, voxEntries, + (float)x, (float)y, (float)z, + (float)correctionX, (float)correctionY, (float)correctionZ, + (float)cx, (float)cy, (float)cz, + (float)cxC, (float)cyC, (float)czC}; + // fill the ntuple with the correction at the voxel + ntInvVox->Fill(ntEntry); + } + + if (voxEntries >= 1.) { + double d[3] = {cx - correctionX, cy - correctionY, cz - correctionZ}; + + for (int32_t i = 0; i < 3; i++) { + if (fabs(maxDiff[i]) < fabs(d[i])) { + maxDiff[i] = d[i]; + maxDiffSector[i] = iSector; + maxDiffRow[i] = iRow; + // std::cout << " sector " << iSector << " row " << iRow << " xyz " << i + // << " diff " << d[i] << " entries " << voxEntries << " y " << y2xBin << " z " << z2xBin << std::endl; + } + sumDiff[i] += d[i] * d[i]; + } + nDiff++; } - nDiff++; } - debugVox->Fill(iSector, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ); + std::cout + << "fill debug ntuples everywhere .." << std::endl; - debugCorrVox->Fill(iSector, iRow, voxEntries, x, y, z, correctionX, correctionY, correctionZ, - cx, cy, cz, ix, iy, iz); - } + for (int32_t iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { + // for (int32_t iSector = 0; iSector < 1; iSector++) { + std::cout << "debug ntules for sector " << iSector << std::endl; - std::cout - << "fill debug ntuples everywhere .." << std::endl; + int mirrorSector = (iSector >= geo.getNumberOfSectorsA()) ? iSector - geo.getNumberOfSectorsA() : iSector + geo.getNumberOfSectorsA(); - for (int32_t iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { - // for (int32_t iSector = 0; iSector < 1; iSector++) { - std::cout << "debug ntules for sector " << iSector << std::endl; - for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { + for (int32_t iRow = 0; iRow < geo.getNumberOfRows(); iRow++) { - double x = geo.getRowInfo(iRow).x; + double x = geo.getRowInfo(iRow).x; - // the spline grid + // the spline grid - const auto& gridY = corr.getSpline(iSector, iRow).getGridX1(); - const auto& gridZ = corr.getSpline(iSector, iRow).getGridX2(); - if (iSector == 0 && iRow == 0) { - std::cout << "spline scenario " << corr.getSectorRowInfo(iSector, iRow).splineScenarioID << std::endl; - std::cout << "spline grid Y: u = " << 0 << ".." << gridY.getUmax() << ", x = " << gridY.getXmin() << ".." << gridY.getXmax() << std::endl; - std::cout << "spline grid Z: u = " << 0 << ".." << gridZ.getUmax() << ", x = " << gridZ.getXmin() << ".." << gridZ.getXmax() << std::endl; - } + const auto& gridY = corr.getSpline(iSector, iRow).getGridX1(); + const auto& gridZ = corr.getSpline(iSector, iRow).getGridX2(); + if (iSector == 0 && iRow == 0) { + std::cout << "spline scenario " << corr.getSectorRowInfo(iSector, iRow).splineScenarioID << std::endl; + std::cout << "spline grid Y: u = " << 0 << ".." << gridY.getUmax() << ", x = " << gridY.getXmin() << ".." << gridY.getXmax() << std::endl; + std::cout << "spline grid Z: u = " << 0 << ".." << gridZ.getUmax() << ", x = " << gridZ.getXmin() << ".." << gridZ.getXmax() << std::endl; + } - // the correction - { - std::vector points[2], knots[2]; + // the correction + { + std::vector points[2], knots[2]; - auto [yMin, yMax] = geo.getRowInfo(iRow).getYrange(); - auto [zMin, zMax] = geo.getZrange(iSector); + auto [yMin, yMax] = geo.getRowInfo(iRow).getYrange(); + auto [zMin, zMax] = geo.getZrange(iSector); - points[0].push_back(yMin); - points[0].push_back(yMax); - points[1].push_back(zMin); - points[1].push_back(zMax); + points[0].push_back(yMin); + points[0].push_back(yMax); + points[1].push_back(zMin); + points[1].push_back(zMax); - for (int32_t iu = 0; iu < gridY.getNumberOfKnots(); iu++) { - auto [y, z] = corr.convGridToLocal(iSector, iRow, gridY.getKnot(iu).getU(), 0.); - knots[0].push_back(y); - points[0].push_back(y); - } - for (int32_t iv = 0; iv < gridZ.getNumberOfKnots(); iv++) { - auto [y, z] = corr.convGridToLocal(iSector, iRow, 0., gridZ.getKnot(iv).getU()); - knots[1].push_back(z); - points[1].push_back(z); - } + for (int32_t iu = 0; iu < gridY.getNumberOfKnots(); iu++) { + auto [y, z] = corr.convGridToLocal(iSector, iRow, gridY.getKnot(iu).getU(), 0.); + knots[0].push_back(y); + points[0].push_back(y); + } + for (int32_t iv = 0; iv < gridZ.getNumberOfKnots(); iv++) { + auto [y, z] = corr.convGridToLocal(iSector, iRow, 0., gridZ.getKnot(iv).getU()); + knots[1].push_back(z); + points[1].push_back(z); + } - for (int32_t iyz = 0; iyz <= 1; iyz++) { - std::sort(knots[iyz].begin(), knots[iyz].end()); - std::sort(points[iyz].begin(), points[iyz].end()); - int32_t n = points[iyz].size(); - for (int32_t i = 0; i < n - 1; i++) { - double d = (points[iyz][i + 1] - points[iyz][i]) / 10.; - for (int32_t ii = 1; ii < 10; ii++) { - points[iyz].push_back(points[iyz][i] + d * ii); + for (int32_t iyz = 0; iyz <= 1; iyz++) { + std::sort(knots[iyz].begin(), knots[iyz].end()); + std::sort(points[iyz].begin(), points[iyz].end()); + int32_t n = points[iyz].size(); + for (int32_t i = 0; i < n - 1; i++) { + double d = (points[iyz][i + 1] - points[iyz][i]) / 10.; + for (int32_t ii = 1; ii < 10; ii++) { + points[iyz].push_back(points[iyz][i] + d * ii); + } } + std::sort(points[iyz].begin(), points[iyz].end()); } - std::sort(points[iyz].begin(), points[iyz].end()); - } - for (int32_t iter = 0; iter < 2; iter++) { - std::vector& py = ((iter == 0) ? knots[0] : points[0]); - std::vector& pz = ((iter == 0) ? knots[1] : points[1]); - for (uint32_t iu = 0; iu < py.size(); iu++) { - for (uint32_t iv = 0; iv < pz.size(); iv++) { - float y = py[iu]; - float z = pz[iv]; - float cx, cy, cz, ix, iy, iz; - getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); - if (iter == 0) { - debugGrid->Fill(iSector, iRow, x, y, z, cx, cy, cz, ix, iy, iz); - } else { - debugCorr->Fill(iSector, iRow, x, y, z, cx, cy, cz, ix, iy, iz); + for (int32_t iter = 0; iter < 2; iter++) { + std::vector& py = ((iter == 0) ? knots[0] : points[0]); + std::vector& pz = ((iter == 0) ? knots[1] : points[1]); + for (uint32_t iu = 0; iu < py.size(); iu++) { + for (uint32_t iv = 0; iv < pz.size(); iv++) { + float y = py[iu]; + float z = pz[iv]; + float cx{0}, cy{0}, cz{0}, ix{0}, iy{0}, iz{0}; + float cxC{0}, cyC{0}, czC{0}, ixC{0}, iyC{0}, izC{0}; + if (direction == 0) { + getAllCorrections(iSector, iRow, y, z, cx, cy, cz, ix, iy, iz); + if (debugMirrorAdata2C) { + getAllCorrections(mirrorSector, iRow, y, -z, cxC, cyC, czC, ixC, iyC, izC); + } + if (iter == 0) { + ntGrid->Fill(iSector, iRow, x, y, z, cx, cy, cz, ix, iy, iz); + } else { + float ntEntry[] = {(float)iSector, (float)iRow, (float)x, y, z, + cx, cy, cz, ix, iy, iz, + cxC, cyC, czC, ixC, iyC, izC}; + ntAll->Fill(ntEntry); + } + } else { + getInvCorrections(iSector, iRow, y, z, cx, cy, cz); + if (debugMirrorAdata2C) { + getInvCorrections(mirrorSector, iRow, y, -z, cxC, cyC, czC); + } + if (iter == 0) { + ntInvGrid->Fill(iSector, iRow, x, y, z, cx, cy, cz); + } else { + float ntEntry[] = {(float)iSector, (float)iRow, (float)x, y, z, + cx, cy, cz, + cxC, cyC, czC}; + ntInvAll->Fill(ntEntry); + } + } } } } } - } - - // the data points used in spline fit - // (they are kept in - // TPCFastTransformHelperO2::instance()->getCorrectionMap() ) - - o2::gpu::TPCFastSpaceChargeCorrectionMap& map = - corrHelper->getCorrectionMap(); - auto& points = map.getPoints(iSector, iRow); - for (uint32_t ip = 0; ip < points.size(); ip++) { - auto point = points[ip]; - float y = point.mY; - float z = point.mZ; - float correctionX = point.mDx; - float correctionY = point.mDy; - float correctionZ = point.mDz; - - auto [cx, cy, cz] = - corr.getCorrectionLocal(iSector, iRow, y, z); - - debugPoints->Fill(iSector, iRow, x, y, z, correctionX, correctionY, - correctionZ, cx, cy, cz); + // the data points used in spline fit + // (they are kept in + // TPCFastTransformHelperO2::instance()->getCorrectionMap() ) + + o2::gpu::TPCFastSpaceChargeCorrectionMap& map = (direction == 0 ? mapDirect : mapInverse); + + auto& points = map.getPoints(iSector, iRow); + + for (uint32_t ip = 0; ip < points.size(); ip++) { + auto point = points[ip]; + float y = point.mY; + float z = point.mZ; + float correctionX = point.mDx; + float correctionY = point.mDy; + float correctionZ = point.mDz; + if (direction == 0) { + auto [cx, cy, cz] = + corr.getCorrectionLocal(iSector, iRow, y, z); + ntFitPoints->Fill(iSector, iRow, x, y, z, correctionX, correctionY, + correctionZ, cx, cy, cz); + } else { + float cx = + corr.getCorrectionXatRealYZ(iSector, iRow, y, z); + auto [cy, cz] = + corr.getCorrectionYZatRealYZ(iSector, iRow, y, z); + ntInvFitPoints->Fill(iSector, iRow, x, y, z, correctionX, correctionY, + correctionZ, cx, cy, cz); + } + } } } - } - for (int32_t i = 0; i < 3; i++) { - sumDiff[i] = sqrt(sumDiff[i]) / nDiff; - } + for (int32_t i = 0; i < 3; i++) { + sumDiff[i] = sqrt(sumDiff[i]) / nDiff; + } - std::cout << "Max difference in x : " << maxDiff[0] << " at Sector " - << maxDiffSector[0] << " row " << maxDiffRow[0] << std::endl; + std::cout << "Max difference in x : " << maxDiff[0] << " at Sector " + << maxDiffSector[0] << " row " << maxDiffRow[0] << std::endl; - std::cout << "Max difference in y : " << maxDiff[1] << " at Sector " - << maxDiffSector[1] << " row " << maxDiffRow[1] << std::endl; + std::cout << "Max difference in y : " << maxDiff[1] << " at Sector " + << maxDiffSector[1] << " row " << maxDiffRow[1] << std::endl; - std::cout << "Max difference in z : " << maxDiff[2] << " at Sector " - << maxDiffSector[2] << " row " << maxDiffRow[2] << std::endl; + std::cout << "Max difference in z : " << maxDiff[2] << " at Sector " + << maxDiffSector[2] << " row " << maxDiffRow[2] << std::endl; - std::cout << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] - << " " << sumDiff[2] << std::endl; + std::cout << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] + << " " << sumDiff[2] << std::endl; + } // direction corr.testInverse(true); debugFile->cd(); - debugCorr->Write(); - debugVox->Write(); - debugCorrVox->Write(); - debugGrid->Write(); - debugPoints->Write(); + ntAll->Write(); + ntVox->Write(); + ntGrid->Write(); + ntFitPoints->Write(); + ntInvAll->Write(); + ntInvVox->Write(); + ntInvGrid->Write(); + ntInvFitPoints->Write(); + debugFile->Close(); } From 14b67e1ed6cf0ed04ffe3b39b7648ef646a561e2 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 27 Aug 2025 17:04:52 +0000 Subject: [PATCH 19/26] TPC Splines: replace std::tuple by std::array --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 8 +-- GPU/TPCFastTransformation/Spline1DSpec.h | 8 +-- GPU/TPCFastTransformation/Spline2DSpec.cxx | 2 - .../TPCFastSpaceChargeCorrection.h | 44 ++++++++--------- GPU/TPCFastTransformation/TPCFastTransform.h | 49 +++++++++++++------ .../TPCFastTransformGeo.h | 15 +++--- .../macro/TPCFastTransformInit.C | 9 +++- 7 files changed, 78 insertions(+), 57 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 6122c5717fcbb..9232598e6a35e 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -668,22 +668,22 @@ std::unique_ptr TPCFastSpaceChargeCorrect // correct the mean position if it is outside the voxel std::stringstream msg; if (fabs(x - data.mX) > mVoxelMeanValidityRange * dx / 2.) { - msg << "\n x: center " << x << " dx " << data.mX - x << " half bin size: " << dx / 2; + msg << "\n x: center " << x << " dx " << data.mX - x << " half bin size " << dx / 2; } if (fabs(vox.mY - data.mY) > mVoxelMeanValidityRange * vox.mDy / 2.) { - msg << "\n y: center " << vox.mY << " dy " << data.mY - vox.mY << " half bin size: " << vox.mDy / 2; + msg << "\n y: center " << vox.mY << " dy " << data.mY - vox.mY << " half bin size " << vox.mDy / 2; data.mY = vox.mY; } if (fabs(vox.mZ - data.mZ) > mVoxelMeanValidityRange * vox.mDz / 2.) { - msg << "\n z: center " << vox.mZ << " dz " << data.mZ - vox.mZ << " half bin size: " << vox.mDz / 2; + msg << "\n z: center " << vox.mZ << " dz " << data.mZ - vox.mZ << " half bin size " << vox.mDz / 2; data.mZ = vox.mZ; } if (!msg.str().empty()) { LOG(warning) << directionName << " correction: fitted voxel position is outside the voxel: " - << " sector " << iSector << " row " << iRow << " bin: " << iy << " " << iz + << " sector " << iSector << " row " << iRow << " bin y " << iy << " bin z " << iz << msg.str(); } diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index 1c591a957847d..28be5dd20e235 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -342,7 +342,7 @@ class Spline1DSpec : public Spline1DContainer } template - GPUd() std::tuple getSderivativesOverParsAtU(const Knot& knotL, DataT u) const + GPUd() std::array getSderivativesOverParsAtU(const Knot& knotL, DataT u) const { /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] /// over the spline parameters Sl(eft), Sr(ight) and the slopes Dl, Dr @@ -364,11 +364,11 @@ class Spline1DSpec : public Spline1DContainer T dSdDl = vm1 * a; T dSdDr = v * a; // S(u) = dSdSl * Sl + dSdSr * Sr + dSdDl * Dl + dSdDr * Dr; - return std::make_tuple(dSdSl, dSdDl, dSdSr, dSdDr); + return {dSdSl, dSdDl, dSdSr, dSdDr}; } template - GPUd() std::tuple getSDderivativesOverParsAtU(const Knot& knotL, DataT u) const + GPUd() std::array getSDderivativesOverParsAtU(const Knot& knotL, DataT u) const { /// Get derivatives of the interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] /// over the spline values Sl, Sr and the slopes Dl, Dr @@ -397,7 +397,7 @@ class Spline1DSpec : public Spline1DContainer T dDdDr = v * (v + vm1 + vm1); // S(u) = dSdSl * Sl + dSdSr * Sr + dSdDl * Dl + dSdDr * Dr; // D(u) = dS(u)/du = dDdSl * Sl + dDdSr * Sr + dDdDl * Dl + dDdDr * Dr; - return std::make_tuple(dSdSl, dSdDl, dSdSr, dSdDr, dDdSl, dDdDl, dDdSr, dDdDr); + return {dSdSl, dSdDl, dSdSr, dSdDr, dDdSl, dDdDl, dDdSr, dDdDr}; } using TBase::convXtoU; diff --git a/GPU/TPCFastTransformation/Spline2DSpec.cxx b/GPU/TPCFastTransformation/Spline2DSpec.cxx index 055530b9314c2..4fbd4dc3d0110 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.cxx +++ b/GPU/TPCFastTransformation/Spline2DSpec.cxx @@ -29,8 +29,6 @@ #include "Riostream.h" #include "TMath.h" #include "Spline2DHelper.h" -#include "TCanvas.h" -#include "TNtuple.h" #include "TFile.h" #include "GPUCommonMath.h" diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 7112a04b364c6..4ca5b74025743 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -78,13 +78,13 @@ class TPCFastSpaceChargeCorrection : public FlatObject } /// convert local y, z to internal grid coordinates u,v, and spline scale - std::tuple convLocalToGridUntruncated(float y, float z) const + std::array convLocalToGridUntruncated(float y, float z) const { return {(y - y0) * yScale, (z - z0) * zScale, getSpineScaleForZ(z)}; } /// convert internal grid coordinates u,v to local y, z - std::tuple convGridToLocal(float gridU, float gridV) const + std::array convGridToLocal(float gridU, float gridV) const { return {y0 + gridU / yScale, z0 + gridV / zScale}; } @@ -123,22 +123,22 @@ class TPCFastSpaceChargeCorrection : public FlatObject maxCorr[2] = GPUCommonMath::Max(maxCorr[2], dv); } - void updateMaxValues(std::tuple dxdudv, float scale) + void updateMaxValues(std::array dxdudv, float scale) { - float dx = std::get<0>(dxdudv) * scale; - float du = std::get<1>(dxdudv) * scale; - float dv = std::get<2>(dxdudv) * scale; + float dx = dxdudv[0] * scale; + float du = dxdudv[1] * scale; + float dv = dxdudv[2] * scale; updateMaxValues(dx, du, dv); } - std::tuple getMaxValues() const + std::array getMaxValues() const { - return std::make_tuple(maxCorr[0], maxCorr[1], maxCorr[2]); + return {maxCorr[0], maxCorr[1], maxCorr[2]}; } - std::tuple getMinValues() const + std::array getMinValues() const { - return std::make_tuple(minCorr[0], minCorr[1], minCorr[2]); + return {minCorr[0], minCorr[1], minCorr[2]}; } ClassDefNV(SectorRowInfo, 2); @@ -259,31 +259,31 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// // GPUd() int32_t getCorrectionInternal(int32_t sector, int32_t row, float u, float v, float& dx, float& du, float& dv) const; - GPUdi() std::tuple getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const; + GPUdi() std::array getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const; /// inverse correction: Real Y and Z -> Real X GPUd() float getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; /// inverse correction: Real Y and Z -> measred Y and Z - GPUd() std::tuple getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; + GPUd() std::array getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; /// _______________ Utilities _______________________________________________ /// convert local y, z to internal grid coordinates u,v /// return values: u, v, scaling factor - GPUd() std::tuple convLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + GPUd() std::array convLocalToGrid(int32_t sector, int32_t row, float y, float z) const; /// convert internal grid coordinates u,v to local y, z /// return values: y, z, scaling factor - GPUd() std::tuple convGridToLocal(int32_t sector, int32_t row, float u, float v) const; + GPUd() std::array convGridToLocal(int32_t sector, int32_t row, float u, float v) const; /// convert real Y, Z to the internal grid coordinates /// return values: u, v, scaling factor - GPUd() std::tuple convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + GPUd() std::array convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const; /// convert internal grid coordinates to the real Y, Z /// return values: y, z - GPUd() std::tuple convGridToRealLocal(int32_t sector, int32_t row, float u, float v) const; + GPUd() std::array convGridToRealLocal(int32_t sector, int32_t row, float u, float v) const; GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; GPUd() bool isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; @@ -453,7 +453,7 @@ GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineDataInvYZ(int32_t se return getSplineData(sector, row, 2); } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const +GPUdi() std::array TPCFastSpaceChargeCorrection::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const { /// convert local y, z to internal grid coordinates u,v /// return values: u, v, scaling factor @@ -491,13 +491,13 @@ GPUdi() bool TPCFastSpaceChargeCorrection::isRealLocalInsideGrid(int32_t sector, return true; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToLocal(int32_t sector, int32_t row, float gridU, float gridV) const +GPUdi() std::array TPCFastSpaceChargeCorrection::convGridToLocal(int32_t sector, int32_t row, float gridU, float gridV) const { /// convert internal grid coordinates u,v to local y, z return getSectorRowInfo(sector, row).gridMeasured.convGridToLocal(gridU, gridV); } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const +GPUdi() std::array TPCFastSpaceChargeCorrection::convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const { /// convert real y, z to the internal grid coordinates + scale const SplineType& spline = getSpline(sector, row); @@ -508,13 +508,13 @@ GPUdi() std::tuple TPCFastSpaceChargeCorrection::convRealLo return {gridU, gridV, scale}; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const +GPUdi() std::array TPCFastSpaceChargeCorrection::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const { /// convert internal grid coordinates u,v to the real y, z return getSectorRowInfo(sector, row).gridReal.convGridToLocal(gridU, gridV); } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const +GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const { const auto& info = getSectorRowInfo(sector, row); const SplineType& spline = getSpline(sector, row); @@ -541,7 +541,7 @@ GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t secto return dx; } -GPUdi() std::tuple TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const +GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { auto [gridU, gridV, scale] = convRealLocalToGrid(sector, row, realY, realZ); const auto& info = getSectorRowInfo(sector, row); diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 3b08296525fc7..35b94446ce088 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -349,13 +349,17 @@ class TPCFastTransform : public FlatObject GPUdi() void TPCFastTransform::convPadTimeToLocal(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float vertexTime) const { float l = (time - mT0 - vertexTime) * mVdrift; // drift length [cm] - std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + y = local[0]; + z = local[1]; } GPUdi() void TPCFastTransform::convPadTimeToLocalInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float maxTimeBin) const { float l = getGeometry().getTPCzLength() + (time - mT0 - maxTimeBin) * mVdrift; // drift length [cm] - std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + y = local[0]; + z = local[1]; } // ---------------------------------------------------------------------- @@ -387,16 +391,16 @@ GPUdi() float TPCFastTransform::convDriftLengthToTime(float driftLength, float v GPUdi() void TPCFastTransform::convLocalToPadTime(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float vertexTime) const { - float l; - std::tie(pad, l) = getGeometry().convLocalToPadDriftLength(sector, row, y, z); - time = convDriftLengthToTime(l, vertexTime); + const auto padLength = getGeometry().convLocalToPadDriftLength(sector, row, y, z); + pad = padLength[0]; + time = convDriftLengthToTime(padLength[1], vertexTime); } GPUdi() void TPCFastTransform::convLocalToPadTimeInTimeFrame(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float maxTimeBin) const { - float l; - std::tie(pad, l) = getGeometry().convLocalToPadDriftLength(sector, row, y, z); - time = convDriftLengthToTime(l, maxTimeBin); + const auto padLength = getGeometry().convLocalToPadDriftLength(sector, row, y, z); + pad = padLength[0]; + time = convDriftLengthToTime(padLength[1], maxTimeBin); } // ---------------------------------------------------------------------- @@ -422,7 +426,10 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t sector, int32_t row, float } else #endif // GPUCA_GPUCODE { - std::tie(dx, dy, dz) = mCorrection.getCorrectionLocal(sector, row, y, z); + const auto corrLocal = mCorrection.getCorrectionLocal(sector, row, y, z); + dx = corrLocal[0]; + dy = corrLocal[1]; + dz = corrLocal[2]; if (ref) { if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(sector, row, y, z); @@ -471,12 +478,18 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t sector, int32_t row, float float dxRef = 0.f, dyRef = 0.f, dzRef = 0.f; if (ref) { - std::tie(dxRef, dyRef, dzRef) = ref->mCorrection.getCorrectionLocal(sector, row, y, z); + const auto corr = ref->mCorrection.getCorrectionLocal(sector, row, y, z); + dxRef = corr[0]; + dyRef = corr[1]; + dzRef = corr[2]; } float dxRef2 = 0.f, dyRef2 = 0.f, dzRef2 = 0.f; if (ref2) { - std::tie(dxRef2, dyRef2, dzRef2) = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); + const auto corr = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); + dxRef2 = corr[0]; + dyRef2 = corr[1]; + dzRef2 = corr[2]; } auto [dxOrig, dyOrig, dzOrig] = mCorrection.getCorrectionLocal(sector, row, y, z); @@ -604,7 +617,9 @@ GPUdi() void TPCFastTransform::TransformIdeal(int32_t sector, int32_t row, float x = getGeometry().getRowInfo(row).x; float driftLength = (time - mT0 - vertexTime) * mVdrift; // drift length cm - std::tie(y, z) = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); + const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); + y = local[0]; + z = local[1]; } GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const @@ -711,20 +726,22 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t sector, int float dz = 0; if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { - std::tie(dy, dz) = mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + const auto corrYZ = mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = corrYZ[0]; + dz = corrYZ[1]; if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { - auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + const auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); dy = (dy - dyRef) * scale + dyRef; dz = (dz - dzRef) * scale + dzRef; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { - auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + const auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); dy = dyRef * scale + dy; dz = dzRef * scale + dz; } if (ref2 && (scale2 != 0)) { - auto [dyRef, dzRef] = ref2->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + const auto [dyRef, dzRef] = ref2->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); dy = dyRef * scale2 + dy; dz = dzRef * scale2 + dz; } diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index 89b099ec63127..fc28bbef33602 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -18,6 +18,7 @@ #define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_TPCFASTTRANSFORMGEO_H #include "GPUCommonDef.h" +#include "GPUCommonArray.h" #ifndef GPUCA_GPUCODE_DEVICE #include #include "GPUCommonRtypes.h" @@ -55,7 +56,7 @@ class TPCFastTransformGeo GPUd() float getYmax() const { return -yMin; } /// get Y range - GPUd() std::tuple getYrange() const { return {getYmin(), getYmax()}; } + GPUd() std::array getYrange() const { return {getYmin(), getYmax()}; } /// get width in Y GPUd() float getYwidth() const { return -2.f * yMin; } @@ -125,7 +126,7 @@ class TPCFastTransformGeo GPUd() float getTPCzLength() const { return mTPCzLength; } /// Gives Z range for the corresponding TPC side - GPUd() std::tuple getZrange(int32_t sector) const; + GPUd() std::array getZrange(int32_t sector) const; GPUd() float getZmin(int32_t sector) const; GPUd() float getZmax(int32_t sector) const; GPUd() float getZreadout(int32_t sector) const; @@ -139,7 +140,7 @@ class TPCFastTransformGeo GPUd() void convGlobalToLocal(int32_t sector, float gx, float gy, float gz, float& lx, float& ly, float& lz) const; /// convert Pad, DriftLength -> Local c.s. - GPUd() std::tuple convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const; + GPUd() std::array convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const; /// convert DriftLength -> Local c.s. GPUd() float convDriftLengthToZ1(int32_t sector, float driftLength) const; @@ -148,7 +149,7 @@ class TPCFastTransformGeo GPUd() float convZtoDriftLength1(int32_t sector, float z) const; /// convert Local c.s. -> Pad, DriftLength - GPUd() std::tuple convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const; + GPUd() std::array convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const; /// Print method void print() const; @@ -229,7 +230,7 @@ GPUdi() void TPCFastTransformGeo::convGlobalToLocal(int32_t sector, float gx, fl lz = gz; } -GPUdi() std::tuple TPCFastTransformGeo::convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const +GPUdi() std::array TPCFastTransformGeo::convPadDriftLengthToLocal(int32_t sector, int32_t row, float pad, float driftLength) const { /// convert Pad, DriftLength -> Local c.s. const RowInfo& rowInfo = getRowInfo(row); @@ -257,7 +258,7 @@ GPUdi() float TPCFastTransformGeo::convZtoDriftLength1(int32_t sector, float z) return (sector < NumberOfSectorsA) ? (mTPCzLength - z) : (z + mTPCzLength); } -GPUdi() std::tuple TPCFastTransformGeo::getZrange(int32_t sector) const +GPUdi() std::array TPCFastTransformGeo::getZrange(int32_t sector) const { /// z range for the sector if (sector < NumberOfSectorsA) { // TPC side A @@ -297,7 +298,7 @@ GPUdi() float TPCFastTransformGeo::getZreadout(int32_t sector) const } } -GPUdi() std::tuple TPCFastTransformGeo::convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const +GPUdi() std::array TPCFastTransformGeo::convLocalToPadDriftLength(int32_t sector, int32_t row, float y, float z) const { /// convert Local c.s. -> Pad, DriftLength float u, l; diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 50b667bb3e023..3cf3b697d2da9 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -303,12 +303,17 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* auto getInvCorrections = [&](int iSector, int iRow, float realY, float realZ, float& ix, float& iy, float& iz) { // get the inverse corrections ix, iy, iz at x,y,z ix = corr.getCorrectionXatRealYZ(iSector, iRow, realY, realZ); - std::tie(iy, iz) = corr.getCorrectionYZatRealYZ(iSector, iRow, realY, realZ); + const auto c = corr.getCorrectionYZatRealYZ(iSector, iRow, realY, realZ); + iy = c[0]; + iz = c[1]; }; auto getAllCorrections = [&](int iSector, int iRow, float y, float z, float& cx, float& cy, float& cz, float& ix, float& iy, float& iz) { // get the corrections cx,cy,cz at x,y,z - std::tie(cx, cy, cz) = corr.getCorrectionLocal(iSector, iRow, y, z); + const auto c = corr.getCorrectionLocal(iSector, iRow, y, z); + cx = c[0]; + cy = c[1]; + cz = c[2]; getInvCorrections(iSector, iRow, y + cy, z + cz, ix, iy, iz); }; From ae8683c855830355b1c511d5ec667ccb2e6d09a0 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 27 Aug 2025 18:28:46 +0000 Subject: [PATCH 20/26] TPC Splines: better smoothing between the voxels --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 104 +++++++++++------- GPU/TPCFastTransformation/Spline2DHelper.cxx | 14 ++- GPU/TPCFastTransformation/Spline2DHelper.h | 2 +- .../TPCFastSpaceChargeCorrectionMap.h | 9 +- .../macro/TPCFastTransformInit.C | 25 +++-- 5 files changed, 94 insertions(+), 60 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 9232598e6a35e..02cdefa85e119 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -148,9 +148,13 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas if (!processingInverseCorrection) { info.resetMaxValues(); } + info.updateMaxValues(1., 1., 1.); + info.updateMaxValues(-1., -1., -1.); + if (nDataPoints >= 4) { std::vector pointGU(nDataPoints); std::vector pointGV(nDataPoints); + std::vector pointWeight(nDataPoints); std::vector pointCorr(3 * nDataPoints); // 3 dimensions for (int i = 0; i < nDataPoints; ++i) { o2::gpu::TPCFastSpaceChargeCorrectionMap::CorrectionPoint p = data[i]; @@ -161,15 +165,14 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas } pointGU[i] = gu; pointGV[i] = gv; + pointWeight[i] = p.mWeight; pointCorr[3 * i + 0] = p.mDx; pointCorr[3 * i + 1] = p.mDy; pointCorr[3 * i + 2] = p.mDz; - if (!processingInverseCorrection) { - info.updateMaxValues(20. * p.mDx, 20. * p.mDy, 20. * p.mDz); - } + info.updateMaxValues(5. * p.mDx, 5. * p.mDy, 5. * p.mDz); } - helper.approximateDataPoints(spline, splineParameters.data(), 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), &pointGU[0], - &pointGV[0], &pointCorr[0], nDataPoints); + helper.approximateDataPoints(spline, splineParameters.data(), 0., spline.getGridX1().getUmax(), 0., spline.getGridX2().getUmax(), pointGU.data(), + pointGV.data(), pointCorr.data(), pointWeight.data(), nDataPoints); } else { for (int i = 0; i < spline.getNumberOfParameters(); i++) { splineParameters[i] = 0.f; @@ -301,7 +304,7 @@ std::unique_ptr TPCFastSpaceChargeCorrectionHelper double dx, dy, dz; correctionLocal(iSector, iRow, y, z, dx, dy, dz); mCorrectionMap.addCorrectionPoint(iSector, iRow, - y, z, dx, dy, dz); + y, z, dx, dy, dz, 1.); } } } // row @@ -593,14 +596,6 @@ std::unique_ptr TPCFastSpaceChargeCorrect data.mCy *= -1.; data.mCz *= -1.; } - if (data.mNentries > 0) { - if (iSector < geo.getNumberOfSectorsA() && data.mZ < 0) { - LOG(error) << errMsg << "fitted Z coordinate " << data.mZ << " is negative for sector " << iSector; - } - if (iSector >= geo.getNumberOfSectorsA() && data.mZ > 0) { - LOG(error) << errMsg << "fitted Z coordinate " << data.mZ << " is positive for sector " << iSector; - } - } } }; processor.Process(myThread); @@ -624,6 +619,9 @@ std::unique_ptr TPCFastSpaceChargeCorrect } } + double maxError[3] = {0., 0., 0.}; + int nErrors = 0; + for (int iSector = 0; iSector < nSectors; iSector++) { // now process the data row-by-row @@ -682,9 +680,21 @@ std::unique_ptr TPCFastSpaceChargeCorrect } if (!msg.str().empty()) { - LOG(warning) << directionName << " correction: fitted voxel position is outside the voxel: " - << " sector " << iSector << " row " << iRow << " bin y " << iy << " bin z " << iz - << msg.str(); + bool isMaxErrorExceeded = (fabs(data.mX - x) / dx > maxError[0]) || + (fabs(data.mY - vox.mY) / vox.mDy > maxError[1]) || + (fabs(data.mZ - vox.mZ) / vox.mDz > maxError[2]); + static std::mutex mutex; + mutex.lock(); + nErrors++; + if (nErrors < 20 || isMaxErrorExceeded) { + LOG(warning) << directionName << " correction: error N " << nErrors << "fitted voxel position is outside the voxel: " + << " sector " << iSector << " row " << iRow << " bin y " << iy << " bin z " << iz + << msg.str(); + maxError[0] = GPUCommonMath::Max(maxError[0], fabs(data.mX - x) / dx); + maxError[1] = GPUCommonMath::Max(maxError[1], fabs(data.mY - vox.mY) / vox.mDy); + maxError[2] = GPUCommonMath::Max(maxError[2], fabs(data.mZ - vox.mZ) / vox.mDz); + } + mutex.unlock(); } } else { // no data, take voxel center position @@ -773,17 +783,27 @@ std::unique_ptr TPCFastSpaceChargeCorrect auto& info = correction.getSectorRowInfo(iSector, iRow); const auto& spline = correction.getSpline(iSector, iRow); - auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nSteps) { + auto addVoxel = [&](int iy, int iz, double weight) { + auto& vox = vRowVoxels[iy * nZ2Xbins + iz]; + if (vox.mSmoothingStep > 2) { + LOG(fatal) << "empty voxel is not repared: y " << iy << " z " << iz; + } + auto& data = vSectorData[iSector * nRows + iRow][iy * nZ2Xbins + iz]; + map.addCorrectionPoint(iSector, iRow, data.mY, data.mZ, data.mCx, data.mCy, data.mCz, weight); + }; + + auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nPoints) { + // add n points on the edge between two voxels excluding the voxel points + if (nPoints < 1) + return; + if (iy1 < 0 || iy1 >= nY2Xbins || iz1 < 0 || iz1 >= nZ2Xbins) + return; + if (iy2 < 0 || iy2 >= nY2Xbins || iz2 < 0 || iz2 >= nZ2Xbins) + return; auto& data1 = vSectorData[iSector * nRows + iRow][iy1 * nZ2Xbins + iz1]; auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; auto& data2 = vSectorData[iSector * nRows + iRow][iy2 * nZ2Xbins + iz2]; auto& vox2 = vRowVoxels[iy2 * nZ2Xbins + iz2]; - if (vox1.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared: y " << iy1 << " z " << iz1; - } - if (vox2.mSmoothingStep > 2) { - LOG(fatal) << "empty voxel is not repared: y " << iy2 << " z " << iz2; - } double y1 = data1.mY; double z1 = data1.mZ; double cx1 = data1.mCx; @@ -795,32 +815,36 @@ std::unique_ptr TPCFastSpaceChargeCorrect double cy2 = data2.mCy; double cz2 = data2.mCz; - for (int is = 0; is < nSteps; is++) { - double s2 = is / (double)nSteps; + for (int is = 1; is <= nPoints; is++) { + double s2 = is / (double)(nPoints + 1); double s1 = 1. - s2; double y = s1 * y1 + s2 * y2; double z = s1 * z1 + s2 * z2; double cx = s1 * cx1 + s2 * cx2; double cy = s1 * cy1 + s2 * cy2; double cz = s1 * cz1 + s2 * cz2; - map.addCorrectionPoint(iSector, iRow, y, z, cx, cy, cz); + map.addCorrectionPoint(iSector, iRow, y, z, cx, cy, cz, 1.); } }; + // original measurements weighted by 8 at each voxel and 8 additional artificial measurements around each voxel + // + // (y+1, z) 8 1 1 8 (y+1, z+1) + // 1 1 1 1 1 + // 1 1 1 1 1 + // (y,z) 8 1 1 8 1 + // 1 1 1 1 1 + for (int iy = 0; iy < nY2Xbins; iy++) { - for (int iz = 0; iz < nZ2Xbins - 1; iz++) { - addEdge(iy, iz, iy, iz + 1, 3); + for (int iz = 0; iz < nZ2Xbins; iz++) { + addVoxel(iy, iz, 8); + addEdge(iy, iz, iy, iz + 1, 2); + addEdge(iy, iz, iy + 1, iz, 2); + addEdge(iy, iz, iy + 1, iz + 1, 2); + addEdge(iy + 1, iz, iy, iz + 1, 2); } - addEdge(iy, nZ2Xbins - 1, iy, nZ2Xbins - 1, 1); } - for (int iz = 0; iz < nZ2Xbins; iz++) { - for (int iy = 0; iy < nY2Xbins - 1; iy++) { - addEdge(iy, iz, iy + 1, iz, 3); - } - addEdge(nY2Xbins - 1, iz, nY2Xbins - 1, iz, 1); - } // iy - } // iRow }; // myThread @@ -939,10 +963,11 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector dataPointGridU, dataPointGridV, dataPointF; + std::vector dataPointGridU, dataPointGridV, dataPointF, dataPointWeight; dataPointGridU.reserve(gridU.size() * gridV.size()); dataPointGridV.reserve(gridU.size() * gridV.size()); dataPointF.reserve(3 * gridU.size() * gridV.size()); + dataPointWeight.reserve(gridU.size() * gridV.size()); for (int iu = 0; iu < gridU.size(); iu++) { for (int iv = 0; iv < gridV.size(); iv++) { @@ -963,6 +988,7 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector::approximateFunctionViaDataPoints( mFdimensions = spline.getYdimensions(); std::vector dataPointX1(getNumberOfDataPoints()); std::vector dataPointX2(getNumberOfDataPoints()); + std::vector dataPointWeight(getNumberOfDataPoints(), 1.); std::vector dataPointF(getNumberOfDataPoints() * mFdimensions); double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); @@ -256,7 +257,8 @@ void Spline2DHelper::approximateFunctionViaDataPoints( F(x1, x2, &dataPointF[ind * mFdimensions]); } } - approximateDataPoints(spline, spline.getParameters(), x1Min, x1Max, x2Min, x2Max, &dataPointX1[0], &dataPointX2[0], &dataPointF[0], getNumberOfDataPoints()); + approximateDataPoints(spline, spline.getParameters(), x1Min, x1Max, x2Min, x2Max, dataPointX1.data(), dataPointX2.data(), dataPointF.data(), + dataPointWeight.data(), getNumberOfDataPoints()); } template @@ -326,7 +328,7 @@ template void Spline2DHelper::approximateDataPoints( Spline2DContainer& spline, DataT* splineParameters, double x1Min, double x1Max, double x2Min, double x2Max, const double dataPointX1[], const double dataPointX2[], const double dataPointF[/*getNumberOfDataPoints() x nFdim*/], - int32_t nDataPoints) + const double dataPointWeight[], int32_t nDataPoints) { /// Create best-fit spline parameters for a given input function F @@ -343,6 +345,10 @@ void Spline2DHelper::approximateDataPoints( for (int32_t iPoint = 0; iPoint < nDataPoints; ++iPoint) { double u = fGridU.convXtoU(dataPointX1[iPoint]); double v = fGridV.convXtoU(dataPointX2[iPoint]); + double weight = dataPointWeight[iPoint]; + if (!(weight > 0.)) { + continue; + } int32_t iu = fGridU.getLeftKnotIndexForU(u); int32_t iv = fGridV.getLeftKnotIndexForU(v); double c[16]; @@ -353,14 +359,14 @@ void Spline2DHelper::approximateDataPoints( for (int32_t i = 0; i < 16; i++) { for (int32_t j = i; j < 16; j++) { - solver.A(ind[i], ind[j]) += c[i] * c[j]; + solver.A(ind[i], ind[j]) += weight * c[i] * c[j]; } } for (int32_t iDim = 0; iDim < nFdim; iDim++) { double f = (double)dataPointF[iPoint * nFdim + iDim]; for (int32_t i = 0; i < 16; i++) { - solver.B(ind[i], iDim) += f * c[i]; + solver.B(ind[i], iDim) += weight * f * c[i]; } } } // data points diff --git a/GPU/TPCFastTransformation/Spline2DHelper.h b/GPU/TPCFastTransformation/Spline2DHelper.h index 7195bab925f85..aa52c306a1a53 100644 --- a/GPU/TPCFastTransformation/Spline2DHelper.h +++ b/GPU/TPCFastTransformation/Spline2DHelper.h @@ -74,7 +74,7 @@ class Spline2DHelper void approximateDataPoints( Spline2DContainer& spline, DataT* splineParameters, double x1Min, double x1Max, double x2Min, double x2Max, const double dataPointX1[/*nDataPoints*/], const double dataPointX2[/*nDataPoints*/], - const double dataPointF[/*nDataPoints x spline.getYdimensions*/], int32_t nDataPoints); + const double dataPointF[/*nDataPoints x spline.getYdimensions*/], const double dataPointWeight[/*nDataPoints*/], int32_t nDataPoints); /// _______________ Interface for a step-wise construction of the best-fit spline ________________________ diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h index fcee61ff09425..e54cf878ee2ff 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrectionMap.h @@ -42,8 +42,9 @@ class TPCFastSpaceChargeCorrectionMap /// \brief The struct contains necessary info for TPC padrow /// struct CorrectionPoint { - double mY, mZ; // not-distorted local coordinates - double mDx, mDy, mDz; // corrections to the local coordinates + double mY{0.}, mZ{0.}; // not-distorted local coordinates + double mDx{0.}, mDy{0.}, mDz{0.}; // corrections to the local coordinates + double mWeight{0.}; // weight of the point }; /// _____________ Constructors / destructors __________________________ @@ -72,11 +73,11 @@ class TPCFastSpaceChargeCorrectionMap /// Starts the construction procedure, reserves temporary memory void addCorrectionPoint(int32_t iSector, int32_t iRow, double y, double z, - double dx, double dy, double dz) + double dx, double dy, double dz, double weight) { int32_t ind = mNrows * iSector + iRow; fDataPoints.at(ind).push_back(CorrectionPoint{y, z, - dx, dy, dz}); + dx, dy, dz, weight}); } const std::vector& getPoints(int32_t iSector, int32_t iRow) const diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 3cf3b697d2da9..3cb4812abafc1 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -319,6 +319,8 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* for (int direction = 0; direction < 2; direction++) { // 0 - normal, 1 - inverse + std::string directionName = (direction == 0) ? "direct" : "inverse"; + TTree* currentTree = (direction == 0) ? voxResTree : voxResTreeInverse; if (!currentTree) { std::cout << "tree voxResTree does not exist!" << std::endl; @@ -342,7 +344,7 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* double sumDiff[3] = {0., 0., 0.}; int64_t nDiff = 0; - std::cout << "fill debug ntuples at voxels ..." << std::endl; + LOG(info) << directionName << " correction: fill debug ntuples at voxels ..."; for (int32_t iVox = 0; iVox < currentTree->GetEntriesFast(); iVox++) { @@ -457,12 +459,11 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* } } - std::cout - << "fill debug ntuples everywhere .." << std::endl; + LOG(info) << directionName << " correction: fill debug ntuples everywhere .."; for (int32_t iSector = 0; iSector < geo.getNumberOfSectors(); iSector++) { // for (int32_t iSector = 0; iSector < 1; iSector++) { - std::cout << "debug ntules for sector " << iSector << std::endl; + LOG(info) << directionName << " correction: fill debug ntuples everywhere in sector " << iSector; int mirrorSector = (iSector >= geo.getNumberOfSectorsA()) ? iSector - geo.getNumberOfSectorsA() : iSector + geo.getNumberOfSectorsA(); @@ -592,17 +593,17 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* for (int32_t i = 0; i < 3; i++) { sumDiff[i] = sqrt(sumDiff[i]) / nDiff; } + LOG(info) << directionName << " correction: max and mean differences between spline and voxel corrections:"; + LOG(info) << "Max difference in x : " << maxDiff[0] << " at Sector " + << maxDiffSector[0] << " row " << maxDiffRow[0]; - std::cout << "Max difference in x : " << maxDiff[0] << " at Sector " - << maxDiffSector[0] << " row " << maxDiffRow[0] << std::endl; - - std::cout << "Max difference in y : " << maxDiff[1] << " at Sector " - << maxDiffSector[1] << " row " << maxDiffRow[1] << std::endl; + LOG(info) << "Max difference in y : " << maxDiff[1] << " at Sector " + << maxDiffSector[1] << " row " << maxDiffRow[1]; - std::cout << "Max difference in z : " << maxDiff[2] << " at Sector " - << maxDiffSector[2] << " row " << maxDiffRow[2] << std::endl; + LOG(info) << "Max difference in z : " << maxDiff[2] << " at Sector " + << maxDiffSector[2] << " row " << maxDiffRow[2]; - std::cout << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] + LOG(info) << "Mean difference in x,y,z : " << sumDiff[0] << " " << sumDiff[1] << " " << sumDiff[2] << std::endl; } // direction From 50e48a34abe80e2e5db3faaae856012409292473 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 1 Sep 2025 15:52:24 +0200 Subject: [PATCH 21/26] TPCFastTransform: fix compilation on GPU with the new splines --- GPU/TPCFastTransformation/Spline1DSpec.h | 6 +- GPU/TPCFastTransformation/Spline2DSpec.h | 12 +++- .../TPCFastSpaceChargeCorrection.h | 70 +++++++++---------- GPU/TPCFastTransformation/TPCFastTransform.h | 60 ++++++++-------- 4 files changed, 80 insertions(+), 68 deletions(-) diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index 28be5dd20e235..d72de5a446718 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -314,7 +314,11 @@ class Spline1DSpec : public Spline1DContainer const auto nYdimTmp = SplineUtil::getNdim(inpYdim); const auto nYdim = nYdimTmp.get(); - auto [dSdSl, dSdDl, dSdSr, dSdDr] = getSderivativesOverParsAtU(knotL, u); + auto val = getSderivativesOverParsAtU(knotL, u); + const auto& dSdSl = val[0]; + const auto& dSdDl = val[1]; + const auto& dSdSr = val[2]; + const auto& dSdDr = val[3]; for (int32_t dim = 0; dim < nYdim; ++dim) { S[dim] = dSdSr * Sr[dim] + dSdSl * Sl[dim] + dSdDl * Dl[dim] + dSdDr * Dr[dim]; } diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index 987ce1ad5d256..7c34b0890ce50 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -334,8 +334,16 @@ class Spline2DSpec const DataT* A = Parameters + (nu * iv + iu) * nYdim4; // values { {Y1,Y2,Y3}, {Y1,Y2,Y3}'v, {Y1,Y2,Y3}'u, {Y1,Y2,Y3}''vu } at {u0, v0} const DataT* B = A + nYdim4 * nu; // values { ... } at {u0, v1} - auto [dSl, dDl, dSr, dDr] = mGridX1.template getSderivativesOverParsAtU(knotU, u); - auto [dSd, dDd, dSu, dDu] = mGridX2.template getSderivativesOverParsAtU(knotV, v); + auto val1 = mGridX1.template getSderivativesOverParsAtU(knotU, u); + auto val2 = mGridX2.template getSderivativesOverParsAtU(knotV, v); + const auto& dSl = val1[0]; + const auto& dDl = val1[1]; + const auto& dSr = val1[2]; + const auto& dDr = val1[3]; + const auto& dSd = val2[0]; + const auto& dDd = val2[1]; + const auto& dSu = val2[2]; + const auto& dDu = val2[3]; // when nYdim == 1: // S = dSl * (dSd * A[0] + dDd * A[1]) + dDl * (dSd * A[2] + dDd * A[3]) + diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index 4ca5b74025743..ffbc8691ea268 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -56,15 +56,15 @@ class TPCFastSpaceChargeCorrection : public FlatObject float splineScalingWithZ{0.f}; ///< spline scaling factor in the Z region between the zOut and the readout plane public: - void set(float y0, float yScale, float z0, float zScale, float zOut, float zReadout) + void set(float y0_, float yScale_, float z0_, float zScale_, float zOut_, float zReadout_) { - this->y0 = y0; - this->yScale = yScale; - this->z0 = z0; - this->zScale = zScale; - this->zOut = zOut; + this->y0 = y0_; + this->yScale = yScale_; + this->z0 = z0_; + this->zScale = zScale_; + this->zOut = zOut_; // no scaling when the distance to the readout is too small - this->splineScalingWithZ = fabs(zReadout - zOut) > 1. ? 1. / (zReadout - zOut) : 0.; + this->splineScalingWithZ = fabs(zReadout_ - zOut_) > 1. ? 1. / (zReadout_ - zOut_) : 0.; } float getY0() const { return y0; } @@ -72,13 +72,13 @@ class TPCFastSpaceChargeCorrection : public FlatObject float getZ0() const { return z0; } float getZscale() const { return zScale; } - float getSpineScaleForZ(float z) const + GPUd() float getSpineScaleForZ(float z) const { return 1.f - GPUCommonMath::Clamp((z - zOut) * splineScalingWithZ, 0.f, 1.f); } /// convert local y, z to internal grid coordinates u,v, and spline scale - std::array convLocalToGridUntruncated(float y, float z) const + GPUd() std::array convLocalToGridUntruncated(float y, float z) const { return {(y - y0) * yScale, (z - z0) * zScale, getSpineScaleForZ(z)}; } @@ -458,21 +458,21 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::convLocalToGrid(int32 /// convert local y, z to internal grid coordinates u,v /// return values: u, v, scaling factor const SplineType& spline = getSpline(sector, row); - auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); + auto val = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); // shrink to the grid - gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); - gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - return {gridU, gridV, scale}; + val[0] = GPUCommonMath::Clamp(val[0], 0.f, (float)spline.getGridX1().getUmax()); + val[1] = GPUCommonMath::Clamp(val[1], 0.f, (float)spline.getGridX2().getUmax()); + return val; } GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const { /// check if local y, z are inside the grid - auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); + auto val = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); const auto& spline = getSpline(sector, row); // shrink to the grid - if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax() || // - gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { + if (val[0] < 0.f || val[0] > (float)spline.getGridX1().getUmax() || // + val[1] < 0.f || val[1] > (float)spline.getGridX2().getUmax()) { return false; } return true; @@ -481,11 +481,11 @@ GPUdi() bool TPCFastSpaceChargeCorrection::isLocalInsideGrid(int32_t sector, int GPUdi() bool TPCFastSpaceChargeCorrection::isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const { /// check if local y, z are inside the grid - auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + auto val = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); const auto& spline = getSpline(sector, row); // shrink to the grid - if (gridU < 0.f || gridU > (float)spline.getGridX1().getUmax() || // - gridV < 0.f || gridV > (float)spline.getGridX2().getUmax()) { + if (val[0] < 0.f || val[0] > (float)spline.getGridX1().getUmax() || // + val[1] < 0.f || val[1] > (float)spline.getGridX2().getUmax()) { return false; } return true; @@ -501,11 +501,11 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::convRealLocalToGrid(i { /// convert real y, z to the internal grid coordinates + scale const SplineType& spline = getSpline(sector, row); - auto [gridU, gridV, scale] = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + auto val = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); // shrink to the grid - gridU = GPUCommonMath::Clamp(gridU, 0.f, (float)spline.getGridX1().getUmax()); - gridV = GPUCommonMath::Clamp(gridV, 0.f, (float)spline.getGridX2().getUmax()); - return {gridU, gridV, scale}; + val[0] = GPUCommonMath::Clamp(val[0], 0.f, (float)spline.getGridX1().getUmax()); + val[1] = GPUCommonMath::Clamp(val[1], 0.f, (float)spline.getGridX2().getUmax()); + return val; } GPUdi() std::array TPCFastSpaceChargeCorrection::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const @@ -520,35 +520,35 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionLocal(in const SplineType& spline = getSpline(sector, row); const float* splineData = getSplineData(sector, row); - auto [gridU, gridV, scale] = convLocalToGrid(sector, row, y, z); + auto val = convLocalToGrid(sector, row, y, z); float dxyz[3]; - spline.interpolateAtU(splineData, gridU, gridV, dxyz); + spline.interpolateAtU(splineData, val[0], val[1], dxyz); - float dx = scale * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); - float dy = scale * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); - float dz = scale * GPUCommonMath::Clamp(dxyz[2], info.minCorr[2], info.maxCorr[2]); + float dx = val[2] * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); + float dy = val[2] * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); + float dz = val[2] * GPUCommonMath::Clamp(dxyz[2], info.minCorr[2], info.maxCorr[2]); return {dx, dy, dz}; } GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { const auto& info = getSectorRowInfo(sector, row); - auto [gridU, gridV, scale] = convRealLocalToGrid(sector, row, realY, realZ); + auto val = convRealLocalToGrid(sector, row, realY, realZ); float dx = 0; - getSplineInvX(sector, row).interpolateAtU(getSplineDataInvX(sector, row), gridU, gridV, &dx); - dx = scale * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); + getSplineInvX(sector, row).interpolateAtU(getSplineDataInvX(sector, row), val[0], val[1], &dx); + dx = val[2] * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); return dx; } GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const { - auto [gridU, gridV, scale] = convRealLocalToGrid(sector, row, realY, realZ); + auto val = convRealLocalToGrid(sector, row, realY, realZ); const auto& info = getSectorRowInfo(sector, row); float dyz[2]; - getSplineInvYZ(sector, row).interpolateAtU(getSplineDataInvYZ(sector, row), gridU, gridV, dyz); - dyz[0] = scale * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); - dyz[1] = scale * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); + getSplineInvYZ(sector, row).interpolateAtU(getSplineDataInvYZ(sector, row), val[0], val[1], dyz); + dyz[0] = val[2] * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); + dyz[1] = val[2] * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); return {dyz[0], dyz[1]}; } diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 35b94446ce088..60f5952e6a1fc 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -349,17 +349,17 @@ class TPCFastTransform : public FlatObject GPUdi() void TPCFastTransform::convPadTimeToLocal(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float vertexTime) const { float l = (time - mT0 - vertexTime) * mVdrift; // drift length [cm] - const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); - y = local[0]; - z = local[1]; + const auto localval = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + y = localval[0]; + z = localval[1]; } GPUdi() void TPCFastTransform::convPadTimeToLocalInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float maxTimeBin) const { float l = getGeometry().getTPCzLength() + (time - mT0 - maxTimeBin) * mVdrift; // drift length [cm] - const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); - y = local[0]; - z = local[1]; + const auto localval = getGeometry().convPadDriftLengthToLocal(sector, row, pad, l); + y = localval[0]; + z = localval[1]; } // ---------------------------------------------------------------------- @@ -432,22 +432,22 @@ GPUdi() void TPCFastTransform::TransformLocal(int32_t sector, int32_t row, float dz = corrLocal[2]; if (ref) { if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested - auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(sector, row, y, z); - dx = (dx - dxRef) * scale + dxRef; - dy = (dy - dyRef) * scale + dyRef; - dz = (dz - dzRef) * scale + dzRef; + auto val = ref->mCorrection.getCorrectionLocal(sector, row, y, z); + dx = (dx - val[0]) * scale + val[0]; + dy = (dy - val[1]) * scale + val[1]; + dz = (dz - val[2]) * scale + val[2]; } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { - auto [dxRef, dyRef, dzRef] = ref->mCorrection.getCorrectionLocal(sector, row, y, z); - dx = dxRef * scale + dx; - dy = dyRef * scale + dy; - dz = dzRef * scale + dz; + auto val = ref->mCorrection.getCorrectionLocal(sector, row, y, z); + dx = val[0] * scale + dx; + dy = val[1] * scale + dy; + dz = val[2] * scale + dz; } } if (ref2 && (scale2 != 0)) { - auto [dxRef, dyRef, dzRef] = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); - dx = dxRef * scale2 + dx; - dy = dyRef * scale2 + dy; - dz = dzRef * scale2 + dz; + auto val = ref2->mCorrection.getCorrectionLocal(sector, row, y, z); + dx = val[0] * scale2 + dx; + dy = val[1] * scale2 + dy; + dz = val[2] * scale2 + dz; } } } @@ -617,9 +617,9 @@ GPUdi() void TPCFastTransform::TransformIdeal(int32_t sector, int32_t row, float x = getGeometry().getRowInfo(row).x; float driftLength = (time - mT0 - vertexTime) * mVdrift; // drift length cm - const auto local = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); - y = local[0]; - z = local[1]; + const auto localval = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); + y = localval[0]; + z = localval[1]; } GPUdi() float TPCFastTransform::convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const @@ -732,18 +732,18 @@ GPUdi() void TPCFastTransform::InverseTransformYZtoNominalYZ(int32_t sector, int if (ref) { // scaling was requested if (scaleMode == 0 && scale > 0.f) { - const auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); - dy = (dy - dyRef) * scale + dyRef; - dz = (dz - dzRef) * scale + dzRef; + const auto val = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = (dy - val[0]) * scale + val[0]; + dz = (dz - val[1]) * scale + val[1]; } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { - const auto [dyRef, dzRef] = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); - dy = dyRef * scale + dy; - dz = dzRef * scale + dz; + const auto val = ref->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = val[0] * scale + dy; + dz = val[1] * scale + dz; } if (ref2 && (scale2 != 0)) { - const auto [dyRef, dzRef] = ref2->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); - dy = dyRef * scale2 + dy; - dz = dzRef * scale2 + dz; + const auto val = ref2->mCorrection.getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = val[0] * scale2 + dy; + dz = val[1] * scale2 + dz; } } } From 3f06ac225d29a58841669818f5630ce76cf7e9b3 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 17 Sep 2025 17:49:29 +0000 Subject: [PATCH 22/26] TPC Splines: bugfixes in spline merging --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 2 +- GPU/TPCFastTransformation/Spline2DSpec.h | 48 +++++++++---------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index 02cdefa85e119..eb7620c358774 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -1103,7 +1103,7 @@ void TPCFastSpaceChargeCorrectionHelper::mergeCorrections( for (int iu = 0; iu < gridU.getNumberOfKnots(); iu++) { double u = gridU.getKnot(iu).u; for (int iv = 0; iv < gridV.getNumberOfKnots(); iv++) { - double v = gridV.getKnot(iu).u; + double v = gridV.getKnot(iv).u; int knotIndex = spline.getKnotIndex(iu, iv); float P[nKnotPar3d]; diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index 7c34b0890ce50..5681de2dc5fe9 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -382,8 +382,8 @@ class Spline2DSpec const auto nYdim4 = nYdim * 4; DataT *S = P, - *R = P + nYdim, - *Q = P + nYdim * 2, + *Q = P + nYdim, + *R = P + nYdim * 2, *W = P + nYdim * 3; const DataT& u = u1; @@ -425,28 +425,6 @@ class Spline2DSpec } } - // Derivative R = dS / du - // R = dRdSl * (dSdSd * A[0] + dSdDd * A[1]) + dRdDl * (dSdSd * A[2] + dSdDd * A[3]) + - // dRdSr * (dSdSd * A[4] + dSdDd * A[5]) + dRdDr * (dSdSd * A[6] + dSdDd * A[7]) + - // dRdSl * (dSdSu * B[0] + dSdDu * B[1]) + dRdDl * (dSdSu * B[2] + dSdDu * B[3]) + - // dRdSr * (dSdSu * B[4] + dSdDu * B[5]) + dRdDr * (dSdSu * B[6] + dSdDu * B[7]); - - { - DataT a[8] = {dRdSl * dSdSd, dRdSl * dSdDd, dRdDl * dSdSd, dRdDl * dSdDd, - dRdSr * dSdSd, dRdSr * dSdDd, dRdDr * dSdSd, dRdDr * dSdDd}; - DataT b[8] = {dRdSl * dSdSu, dRdSl * dSdDu, dRdDl * dSdSu, dRdDl * dSdDu, - dRdSr * dSdSu, dRdSr * dSdDu, dRdDr * dSdSu, dRdDr * dSdDu}; - - // R = sum a[i]*A[i] + b[i]*B[i] - - for (int32_t dim = 0; dim < nYdim; dim++) { - R[dim] = 0; - for (int32_t i = 0; i < 8; i++) { - R[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; - } - } - } - // Derivative Q = dS / dv // Q = dSdSl * (dQdSd * A[0] + dQdDd * A[1]) + dSdDl * (dQdSd * A[2] + dQdDd * A[3]) + // dSdSr * (dQdSd * A[4] + dQdDd * A[5]) + dSdDr * (dQdSd * A[6] + dQdDd * A[7]) + @@ -469,6 +447,28 @@ class Spline2DSpec } } + // Derivative R = dS / du + // R = dRdSl * (dSdSd * A[0] + dSdDd * A[1]) + dRdDl * (dSdSd * A[2] + dSdDd * A[3]) + + // dRdSr * (dSdSd * A[4] + dSdDd * A[5]) + dRdDr * (dSdSd * A[6] + dSdDd * A[7]) + + // dRdSl * (dSdSu * B[0] + dSdDu * B[1]) + dRdDl * (dSdSu * B[2] + dSdDu * B[3]) + + // dRdSr * (dSdSu * B[4] + dSdDu * B[5]) + dRdDr * (dSdSu * B[6] + dSdDu * B[7]); + + { + DataT a[8] = {dRdSl * dSdSd, dRdSl * dSdDd, dRdDl * dSdSd, dRdDl * dSdDd, + dRdSr * dSdSd, dRdSr * dSdDd, dRdDr * dSdSd, dRdDr * dSdDd}; + DataT b[8] = {dRdSl * dSdSu, dRdSl * dSdDu, dRdDl * dSdSu, dRdDl * dSdDu, + dRdSr * dSdSu, dRdSr * dSdDu, dRdDr * dSdSu, dRdDr * dSdDu}; + + // R = sum a[i]*A[i] + b[i]*B[i] + + for (int32_t dim = 0; dim < nYdim; dim++) { + R[dim] = 0; + for (int32_t i = 0; i < 8; i++) { + R[dim] += a[i] * A[nYdim * i + dim] + b[i] * B[nYdim * i + dim]; + } + } + } + // cross-derivative W = (dS)^2 / du / dv // W = dRdSl * (dQdSd * A[0] + dQdDd * A[1]) + dRdDl * (dQdSd * A[2] + dQdDd * A[3]) + // dRdSr * (dQdSd * A[4] + dQdDd * A[5]) + dRdDr * (dQdSd * A[6] + dQdDd * A[7]) + From d3dcdc9b1e71ccfde0ffecef087892b4dac82b8d Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Mon, 6 Oct 2025 21:19:19 +0000 Subject: [PATCH 23/26] TPC Splines: add backward compatibility --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 22 +- .../TPCFastSpaceChargeCorrection.cxx | 331 +++++++++++++++--- .../TPCFastSpaceChargeCorrection.h | 90 ++--- GPU/TPCFastTransformation/TPCFastTransform.h | 2 +- .../TPCFastTransformGeo.cxx | 8 +- .../TPCFastTransformGeo.h | 10 +- .../TPCFastTransformationLinkDef_O2.h | 23 +- .../macro/TPCFastTransformInit.C | 92 ++--- 8 files changed, 408 insertions(+), 170 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index eb7620c358774..faba4f2ce065e 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -180,15 +180,15 @@ void TPCFastSpaceChargeCorrectionHelper::fillSpaceChargeCorrectionFromMap(TPCFas } if (processingInverseCorrection) { - float* splineX = correction.getSplineDataInvX(sector, row); - float* splineYZ = correction.getSplineDataInvYZ(sector, row); + float* splineX = correction.getCorrectionDataInvX(sector, row); + float* splineYZ = correction.getCorrectionDataInvYZ(sector, row); for (int i = 0; i < spline.getNumberOfParameters() / 3; i++) { splineX[i] = splineParameters[3 * i + 0]; splineYZ[2 * i + 0] = splineParameters[3 * i + 1]; splineYZ[2 * i + 1] = splineParameters[3 * i + 2]; } } else { - float* splineXYZ = correction.getSplineData(sector, row); + float* splineXYZ = correction.getCorrectionData(sector, row); for (int i = 0; i < spline.getNumberOfParameters(); i++) { splineXYZ[i] = splineParameters[i]; } @@ -1000,8 +1000,8 @@ void TPCFastSpaceChargeCorrectionHelper::initInverse(std::vector(mFlatBufferPtr + splineDataOffset); - bufferSize = splineDataOffset + mDataSizeBytes[is]; + size_t correctionDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mCorrectionData[is] = reinterpret_cast(mFlatBufferPtr + correctionDataOffset); + bufferSize = correctionDataOffset + mCorrectionDataSize[is]; } } +void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBufferPtr) +{ + /// Sets the actual location of the external flat buffer after it has been moved (e.g. to another maschine) + + if (mClassVersion == 4) { + FlatObject::setActualBufferAddress(actualFlatBufferPtr); + + size_t scSize = sizeof(SplineType) * mNumberOfScenarios; + + mScenarioPtr = reinterpret_cast(mFlatBufferPtr); + + size_t scBufferOffset = alignSize(scSize, SplineType::getBufferAlignmentBytes()); + size_t scBufferSize = 0; + + for (int32_t i = 0; i < mNumberOfScenarios; i++) { + SplineType& sp = mScenarioPtr[i]; + sp.setActualBufferAddress(mFlatBufferPtr + scBufferOffset + scBufferSize); + scBufferSize = alignSize(scBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); + } + size_t bufferSize = scBufferOffset + scBufferSize; + for (int32_t is = 0; is < 3; is++) { + size_t correctionDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mCorrectionData[is] = reinterpret_cast(mFlatBufferPtr + correctionDataOffset); + bufferSize = correctionDataOffset + mCorrectionDataSize[is]; + } + return; + } + + if (mClassVersion != 3) { + LOG(fatal) << "TPCFastSpaceChargeCorrection::setActualBufferAddress() called with class version " << mClassVersion << ". This is not supported."; + return; + } + + // Class version 3 + + struct RowInfoVersion3 { + int32_t splineScenarioID{0}; ///< scenario index (which of Spline2D splines to use) + size_t dataOffsetBytes[3]{0}; ///< offset for the spline data withing a TPC sector + }; + + struct RowActiveAreaVersion3 { + float maxDriftLengthCheb[5]{0.f}; + float vMax{0.f}; + float cuMin{0.f}; + float cuMax{0.f}; + float cvMax{0.f}; + }; + + struct SectorRowInfoVersion3 { + float gridV0{0.f}; ///< V coordinate of the V-grid start + float gridCorrU0{0.f}; ///< U coordinate of the U-grid start for corrected U + float gridCorrV0{0.f}; ///< V coordinate of the V-grid start for corrected V + float scaleCorrUtoGrid{0.f}; ///< scale corrected U to U-grid coordinate + float scaleCorrVtoGrid{0.f}; ///< scale corrected V to V-grid coordinate + RowActiveAreaVersion3 activeArea; + }; + + FlatObject::setActualBufferAddress(actualFlatBufferPtr); + + size_t oldRowsOffset = 0; + size_t oldRowsSize = sizeof(RowInfoVersion3) * mGeo.getNumberOfRows(); + + size_t oldSectorRowsOffset = oldRowsOffset + oldRowsSize; + size_t oldSectorRowsSize = sizeof(SectorRowInfoVersion3) * mGeo.getNumberOfRows() * mGeo.getNumberOfSectors(); + + size_t oldScenariosOffset = alignSize(oldSectorRowsOffset + oldSectorRowsSize, SplineType::getClassAlignmentBytes()); + size_t scenariosSize = sizeof(SplineType) * mNumberOfScenarios; + + SplineType* oldScenarioPtr = reinterpret_cast(mFlatBufferPtr + oldScenariosOffset); + + { // copy old-format sector and row parameters from the buffer to the arrays + + auto* oldRowInfos = reinterpret_cast(mFlatBufferPtr + oldRowsOffset); + auto* oldSectorRowInfos = reinterpret_cast(mFlatBufferPtr + oldSectorRowsOffset); + + size_t sectorDataSize[3]; + for (int32_t is = 0; is < 3; is++) { + sectorDataSize[is] = mCorrectionDataSize[is] / mGeo.getNumberOfSectors(); + } + + for (int32_t iSector = 0; iSector < mGeo.getNumberOfSectors(); iSector++) { + + for (int32_t iRow = 0; iRow < mGeo.getNumberOfRows(); iRow++) { + RowInfoVersion3& oldRowInfo = oldRowInfos[iRow]; + SectorRowInfoVersion3& oldSectorRowInfo = oldSectorRowInfos[mGeo.getNumberOfRows() * iSector + iRow]; + + // the spline buffer is not yet initialised, don't try to access knot positions etc + const auto& spline = oldScenarioPtr[oldRowInfo.splineScenarioID]; + + SectorRowInfo& newSectorRow = getSectorRowInfo(iSector, iRow); + + newSectorRow.splineScenarioID = oldRowInfo.splineScenarioID; + for (int32_t is = 0; is < 3; is++) { + newSectorRow.dataOffsetBytes[is] = sectorDataSize[is] * iSector + oldRowInfo.dataOffsetBytes[is]; + } + + { // grid for the measured coordinates + float y0 = mGeo.getRowInfo(iRow).yMin; + float yScale = spline.getGridX1().getUmax() / mGeo.getRowInfo(iRow).getYwidth(); + float zReadout = mGeo.getZreadout(iSector); + float zOut = mGeo.getTPCzLength() - oldSectorRowInfo.gridV0; + float z0 = -3.; + float zScale = spline.getGridX2().getUmax() / (zOut - z0); + if (iSector >= mGeo.getNumberOfSectorsA()) { + zOut = -zOut; + z0 = zOut; + } + newSectorRow.gridMeasured.set(y0, yScale, z0, zScale, zOut, zReadout); + } + + { // grid for the real coordinates + float y0 = oldSectorRowInfo.gridCorrU0; + float yScale = oldSectorRowInfo.scaleCorrUtoGrid; + float zReadout = mGeo.getZreadout(iSector); + float zOut = mGeo.getTPCzLength() - oldSectorRowInfo.gridCorrV0; + float zScale = oldSectorRowInfo.scaleCorrVtoGrid; + float z0 = zOut - spline.getGridX2().getUmax() / zScale; + if (iSector >= mGeo.getNumberOfSectorsA()) { + zOut = -zOut; + z0 = zOut; + } + newSectorRow.gridReal.set(y0, yScale, z0, zScale, zOut, zReadout); + } + + newSectorRow.resetMaxValues(); + newSectorRow.updateMaxValues(-50.f, -50.f, -50.f); + newSectorRow.updateMaxValues(50.f, 50.f, 50.f); + } + } + } + + // move spline scenarios to the new place in the buffer + + mScenarioPtr = reinterpret_cast(mFlatBufferPtr); + memmove(mScenarioPtr, oldScenarioPtr, scenariosSize); + + size_t oldScenariosBufferOffset = alignSize(oldScenariosOffset + scenariosSize, SplineType::getBufferAlignmentBytes()); + size_t scenariosBufferOffset = alignSize(scenariosSize, SplineType::getBufferAlignmentBytes()); + + size_t oldScenariosBufferSize = 0; + size_t scenariosBufferSize = 0; + for (int32_t i = 0; i < mNumberOfScenarios; i++) { + SplineType& sp = mScenarioPtr[i]; + char* oldAddress = mFlatBufferPtr + oldScenariosBufferOffset + oldScenariosBufferSize; + char* newAddress = mFlatBufferPtr + scenariosBufferOffset + scenariosBufferSize; + memmove(newAddress, oldAddress, sp.getFlatBufferSize()); + sp.setActualBufferAddress(newAddress); + oldScenariosBufferSize = alignSize(oldScenariosBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); + scenariosBufferSize = alignSize(scenariosBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); + } + + size_t oldBufferSize = oldScenariosBufferOffset + oldScenariosBufferSize; + size_t bufferSize = scenariosBufferOffset + scenariosBufferSize; + + // move spline data to the new place in the buffer + + for (int32_t is = 0; is < 3; is++) { + size_t oldCorrectionDataOffset = alignSize(oldBufferSize, SplineType::getParameterAlignmentBytes()); + size_t correctionDataOffset = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mCorrectionData[is] = reinterpret_cast(mFlatBufferPtr + correctionDataOffset); + memmove(mCorrectionData[is], mFlatBufferPtr + oldCorrectionDataOffset, mCorrectionDataSize[is]); + oldBufferSize = oldCorrectionDataOffset + mCorrectionDataSize[is]; + bufferSize = correctionDataOffset + mCorrectionDataSize[is]; + } + + mFlatBufferSize = bufferSize; + + // now convert the spline data to the new format + for (int32_t iSector = 0; iSector < mGeo.getNumberOfSectors(); iSector++) { + bool isAside = (iSector < mGeo.getNumberOfSectorsA()); + for (int32_t iRow = 0; iRow < mGeo.getNumberOfRows(); iRow++) { + + SectorRowInfo& sectorRow = getSectorRowInfo(iSector, iRow); + const auto& spline = mScenarioPtr[sectorRow.splineScenarioID]; + + int nSplineDimensions[3] = {3, 1, 2}; + + for (int iSpline = 0; iSpline < 3; iSpline++) { + int nDim = nSplineDimensions[iSpline]; + int nKnotParameters = 4 * nDim; + auto* data = getCorrectionData(iSector, iRow, iSpline); + + // lambda to swap parameters at two knots + auto swapKnots = [&](int i1, int j1, int i2, int j2) { + auto k1 = spline.getKnotIndex(i1, j1); + auto k2 = spline.getKnotIndex(i2, j2); + for (int ipar = 0; ipar < nKnotParameters; ipar++) { + std::swap(data[nKnotParameters * k1 + ipar], data[nKnotParameters * k2 + ipar]); + } + }; + + // reorder knots for the A side Y == old U, Z == - old V + if (isAside) { + for (int32_t i = 0; i < spline.getGridX1().getNumberOfKnots(); i++) { + for (int32_t j = 0; j < spline.getGridX2().getNumberOfKnots() / 2; j++) { + swapKnots(i, j, i, spline.getGridX2().getNumberOfKnots() - 1 - j); + } + } + } else { // reorder knots for the C side Y == - old U, Z == old V + for (int32_t i = 0; i < spline.getGridX1().getNumberOfKnots() / 2; i++) { + for (int32_t j = 0; j < spline.getGridX2().getNumberOfKnots(); j++) { + swapKnots(i, j, spline.getGridX1().getNumberOfKnots() - 1 - i, j); + } + } + } + + // correct sign of the parameters due to the coordinate swaps + + for (int32_t iKnot = 0; iKnot < spline.getNumberOfKnots(); iKnot++) { + // new grid directions for all corrections + for (int iDim = 0; iDim < nDim; iDim++) { + if (isAside) { + data[nKnotParameters * iKnot + nDim * 1 + iDim] *= -1; // invert Z derivatives on A side + } else { + data[nKnotParameters * iKnot + nDim * 2 + iDim] *= -1; // invert Y derivatives on C side + } + data[nKnotParameters * iKnot + nDim * 3 + iDim] *= -1; // invert cross derivatives on both sides + } + // new correction directions + if (iSpline == 0) { // dX,dU,dV -> dX,dY,dZ + if (isAside) { + data[nKnotParameters * iKnot + nDim * 0 + 2] *= -1; // invert correction in Z + data[nKnotParameters * iKnot + nDim * 1 + 2] *= -1; // invert correction in Z Z-derivative + data[nKnotParameters * iKnot + nDim * 2 + 2] *= -1; // invert correction in Z Y-derivative + data[nKnotParameters * iKnot + nDim * 3 + 2] *= -1; // invert correction in Z cross derivative + } else { + data[nKnotParameters * iKnot + nDim * 0 + 1] *= -1; // invert correction in Y + data[nKnotParameters * iKnot + nDim * 1 + 1] *= -1; // invert correction in Y Z-derivative + data[nKnotParameters * iKnot + nDim * 2 + 1] *= -1; // invert correction in Y Y-derivative + data[nKnotParameters * iKnot + nDim * 3 + 1] *= -1; // invert correction in Y cross derivative + } + } else if (iSpline == 2) { // dU,dV at real U,V -> dY,dZ at real Y,Z + if (isAside) { + data[nKnotParameters * iKnot + nDim * 0 + 1] *= -1; // invert correction in Z + data[nKnotParameters * iKnot + nDim * 1 + 1] *= -1; // invert correction in Z Z-derivative + data[nKnotParameters * iKnot + nDim * 2 + 1] *= -1; // invert correction in Z Y-derivative + data[nKnotParameters * iKnot + nDim * 3 + 1] *= -1; // invert correction in Z cross derivative + } else { + data[nKnotParameters * iKnot + nDim * 0 + 0] *= -1; // invert correction in Y + data[nKnotParameters * iKnot + nDim * 1 + 0] *= -1; // invert correction in Y Z-derivative + data[nKnotParameters * iKnot + nDim * 2 + 0] *= -1; // invert correction in Y Y-derivative + data[nKnotParameters * iKnot + nDim * 3 + 0] *= -1; // invert correction in Y cross derivative + } + } + } + + } // iSpline + } // iRow + } // iSector + + // set the class version to the current one + mClassVersion = 4; +} + void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBufferPtr) { /// Sets a future location of the external flat buffer before moving it to this location (i.e. when copying to GPU). @@ -186,9 +432,9 @@ void TPCFastSpaceChargeCorrection::setFutureBufferAddress(char* futureFlatBuffer sp.setFutureBufferAddress(newSplineBuf); } mScenarioPtr = relocatePointer(oldBuffer, newBuffer, mScenarioPtr); - mSplineData[0] = relocatePointer(oldBuffer, newBuffer, mSplineData[0]); - mSplineData[1] = relocatePointer(oldBuffer, newBuffer, mSplineData[1]); - mSplineData[2] = relocatePointer(oldBuffer, newBuffer, mSplineData[2]); + mCorrectionData[0] = relocatePointer(oldBuffer, newBuffer, mCorrectionData[0]); + mCorrectionData[1] = relocatePointer(oldBuffer, newBuffer, mCorrectionData[1]); + mCorrectionData[2] = relocatePointer(oldBuffer, newBuffer, mCorrectionData[2]); FlatObject::setFutureBufferAddress(futureFlatBufferPtr); } @@ -199,7 +445,7 @@ void TPCFastSpaceChargeCorrection::print() const mGeo.print(); LOG(info) << " mNumberOfScenarios = " << mNumberOfScenarios; LOG(info) << " mTimeStamp = " << mTimeStamp; - LOG(info) << " mDataSizeBytes = " << mDataSizeBytes[0] << " " << mDataSizeBytes[1] << " " << mDataSizeBytes[2]; + LOG(info) << " mCorrectionDataSize = " << mCorrectionDataSize[0] << " " << mCorrectionDataSize[1] << " " << mCorrectionDataSize[2]; if (mScenarioPtr) { for (int32_t i = 0; i < mNumberOfScenarios; i++) { @@ -213,7 +459,7 @@ void TPCFastSpaceChargeCorrection::print() const for (int32_t ir = 0; ir < mGeo.getNumberOfRows(); ir++) { LOG(info) << "sector " << is << " row " << ir << ": "; const SplineType& spline = getSpline(is, ir); - const float* d = getSplineData(is, ir); + const float* d = getCorrectionData(is, ir); int32_t k = 0; for (int32_t i = 0; i < spline.getGridX1().getNumberOfKnots(); i++) { for (int32_t j = 0; j < spline.getGridX2().getNumberOfKnots(); j++, k++) { @@ -250,7 +496,6 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& assert(mConstructionScenarios != nullptr); for (int32_t i = 0; i < mGeo.getNumberOfSectors(); i++) { - mSectorInfo[i].vMax1 = 0.; for (int32_t j = 0; j < mGeo.getNumberOfRows(); j++) { auto& row = mSectorRowInfos[mGeo.getMaxNumberOfRows() * i + j]; row.splineScenarioID = -1; @@ -276,8 +521,8 @@ void TPCFastSpaceChargeCorrection::startConstruction(const TPCFastTransformGeo& mScenarioPtr = nullptr; for (int32_t s = 0; s < 3; s++) { - mSplineData[s] = nullptr; - mDataSizeBytes[s] = 0; + mCorrectionData[s] = nullptr; + mCorrectionDataSize[s] = 0; } mClassVersion = 4; } @@ -338,20 +583,20 @@ void TPCFastSpaceChargeCorrection::finishConstruction() scBufferSize = alignSize(scBufferSize + sp.getFlatBufferSize(), sp.getBufferAlignmentBytes()); } size_t bufferSize = scBufferOffsets[0] + scBufferSize; - size_t splineDataOffset[3]; + size_t correctionDataOffset[3]; for (int32_t is = 0; is < 3; is++) { - splineDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); - mDataSizeBytes[is] = 0; + correctionDataOffset[is] = alignSize(bufferSize, SplineType::getParameterAlignmentBytes()); + mCorrectionDataSize[is] = 0; for (int32_t i = 0; i < mGeo.getNumberOfSectors(); i++) { for (int32_t j = 0; j < mGeo.getNumberOfRows(); j++) { SectorRowInfo& row = getSectorRowInfo(i, j); SplineType& spline = mConstructionScenarios[row.splineScenarioID]; - row.dataOffsetBytes[is] = alignSize(mDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - mDataSizeBytes[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); + row.dataOffsetBytes[is] = alignSize(mCorrectionDataSize[is], SplineType::getParameterAlignmentBytes()); + mCorrectionDataSize[is] = row.dataOffsetBytes[is] + spline.getSizeOfParameters(); } } - mDataSizeBytes[is] = alignSize(mDataSizeBytes[is], SplineType::getParameterAlignmentBytes()); - bufferSize = splineDataOffset[is] + mDataSizeBytes[is]; + mCorrectionDataSize[is] = alignSize(mCorrectionDataSize[is], SplineType::getParameterAlignmentBytes()); + bufferSize = correctionDataOffset[is] + mCorrectionDataSize[is]; } FlatObject::finishConstruction(bufferSize); @@ -366,7 +611,7 @@ void TPCFastSpaceChargeCorrection::finishConstruction() } for (int32_t is = 0; is < 3; is++) { - mSplineData[is] = reinterpret_cast(mFlatBufferPtr + splineDataOffset[is]); + mCorrectionData[is] = reinterpret_cast(mFlatBufferPtr + correctionDataOffset[is]); } releaseConstructionMemory(); @@ -380,13 +625,11 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() // initialise all corrections to 0. for (int32_t sector = 0; sector < mGeo.getNumberOfSectors(); sector++) { - getSectorInfo(sector).vMax1 = mGeo.getTPCzLength(); - for (int32_t row = 0; row < mGeo.getNumberOfRows(); row++) { const SplineType& spline = getSpline(sector, row); for (int32_t is = 0; is < 3; is++) { - float* data = getSplineData(sector, row, is); + float* data = getCorrectionData(sector, row, is); int32_t nPar = spline.getNumberOfParameters(); if (is == 1) { nPar = nPar / 3; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index ffbc8691ea268..b4fab68b91542 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -39,11 +39,9 @@ namespace gpu class TPCFastSpaceChargeCorrection : public FlatObject { public: - /// - /// \brief The struct contains necessary info for TPC padrow - /// - struct RowInfo { - ClassDefNV(RowInfo, 1); + // obsolete structure, declared here only for backward compatibility + struct SliceInfo { + ClassDefNV(SliceInfo, 2); }; struct GridInfo { @@ -144,11 +142,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject ClassDefNV(SectorRowInfo, 2); }; - struct SectorInfo { - float vMax1{0.f}; ///< Max value of V coordinate - ClassDefNV(SectorInfo, 1); - }; - typedef Spline2D SplineTypeXYZ; typedef Spline2D SplineTypeInvX; typedef Spline2D SplineTypeInvYZ; @@ -188,6 +181,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Moving the class with its external buffer to another location + void setActualBufferAddressOld(char* actualFlatBufferPtr); void setActualBufferAddress(char* actualFlatBufferPtr); void setFutureBufferAddress(char* futureFlatBufferPtr); @@ -215,10 +209,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Sets the time stamp of the current calibaration GPUd() void setTimeStamp(int64_t v) { mTimeStamp = v; } - /// Set safety marging for the interpolation around the TPC row. - /// Outside of this area the interpolation returns the boundary values. - GPUd() void setInterpolationSafetyMargin(float val) { fInterpolationSafetyMargin = val; } - /// Gives const pointer to a spline GPUd() const SplineType& getSpline(int32_t sector, int32_t row) const; @@ -226,10 +216,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() SplineType& getSpline(int32_t sector, int32_t row); /// Gives pointer to spline data - GPUd() float* getSplineData(int32_t sector, int32_t row, int32_t iSpline = 0); + GPUd() float* getCorrectionData(int32_t sector, int32_t row, int32_t iSpline = 0); /// Gives pointer to spline data - GPUd() const float* getSplineData(int32_t sector, int32_t row, int32_t iSpline = 0) const; + GPUd() const float* getCorrectionData(int32_t sector, int32_t row, int32_t iSpline = 0) const; /// Gives const pointer to a spline for the inverse X correction GPUd() const SplineTypeInvX& getSplineInvX(int32_t sector, int32_t row) const; @@ -238,10 +228,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() SplineTypeInvX& getSplineInvX(int32_t sector, int32_t row); /// Gives pointer to spline data for the inverse X correction - GPUd() float* getSplineDataInvX(int32_t sector, int32_t row); + GPUd() float* getCorrectionDataInvX(int32_t sector, int32_t row); /// Gives pointer to spline data for the inverse X correction - GPUd() const float* getSplineDataInvX(int32_t sector, int32_t row) const; + GPUd() const float* getCorrectionDataInvX(int32_t sector, int32_t row) const; /// Gives const pointer to a spline for the inverse YZ correction GPUd() const SplineTypeInvYZ& getSplineInvYZ(int32_t sector, int32_t row) const; @@ -250,10 +240,10 @@ class TPCFastSpaceChargeCorrection : public FlatObject GPUd() SplineTypeInvYZ& getSplineInvYZ(int32_t sector, int32_t row); /// Gives pointer to spline data for the inverse YZ correction - GPUd() float* getSplineDataInvYZ(int32_t sector, int32_t row); + GPUd() float* getCorrectionDataInvYZ(int32_t sector, int32_t row); /// Gives pointer to spline data for the inverse YZ correction - GPUd() const float* getSplineDataInvYZ(int32_t sector, int32_t row) const; + GPUd() const float* getCorrectionDataInvYZ(int32_t sector, int32_t row) const; /// _______________ The main method: cluster correction _______________________ /// @@ -297,24 +287,6 @@ class TPCFastSpaceChargeCorrection : public FlatObject /// Gives the time stamp of the current calibaration parameters int64_t getTimeStamp() const { return mTimeStamp; } - /// Gives the interpolation safety marging around the TPC row. - GPUd() float getInterpolationSafetyMargin() const { return fInterpolationSafetyMargin; } - - /// Gives TPC row info - GPUd() const RowInfo& getRowInfo(int32_t row) const { return mRowInfos[row]; } - - /// Gives TPC sector info - GPUd() const SectorInfo& getSectorInfo(int32_t sector) const - { - return mSectorInfo[sector]; - } - - /// Gives TPC sector info - GPUd() SectorInfo& getSectorInfo(int32_t sector) - { - return mSectorInfo[sector]; - } - /// Gives TPC sector & row info GPUd() const SectorRowInfo& getSectorRowInfo(int32_t sector, int32_t row) const { @@ -351,30 +323,24 @@ class TPCFastSpaceChargeCorrection : public FlatObject int32_t mNumberOfScenarios; ///< Number of approximation spline scenarios - SectorInfo mSectorInfo[TPCFastTransformGeo::getNumberOfSectors()]; ///< SectorInfo array - SplineType* mScenarioPtr; //! (transient!!) pointer to spline scenarios /// _______________ Calibration data _______________________________________________ int64_t mTimeStamp; ///< time stamp of the current calibration - char* mSplineData[3]; //! (transient!!) pointer to the spline data in the flat buffer + char* mCorrectionData[3]; //! (transient!!) pointer to the spline data in the flat buffer - size_t mDataSizeBytes[3]; ///< size of the data for one sector in the flat buffer - - float fInterpolationSafetyMargin{0.1f}; // 10% area around the TPC row. Outside of this area the interpolation returns the boundary values. + size_t mCorrectionDataSize[3]; ///< size of the data per transformation (direct, inverseX, inverse YZ) in the flat buffer /// Class version. It is used to read older versions from disc. /// The default version 3 is the one before this field was introduced. /// The actual version must be set in startConstruction(). int32_t mClassVersion{3}; - RowInfo mRowInfos[TPCFastTransformGeo::getMaxNumberOfRows()]; ///< RowInfo array - SectorRowInfo mSectorRowInfos[TPCFastTransformGeo::getNumberOfSectors() * TPCFastTransformGeo::getMaxNumberOfRows()]; ///< SectorRowInfo array - ClassDefNV(TPCFastSpaceChargeCorrection, 5); + ClassDefNV(TPCFastSpaceChargeCorrection, 4); }; /// ==================================================== @@ -393,16 +359,16 @@ GPUdi() TPCFastSpaceChargeCorrection::SplineType& TPCFastSpaceChargeCorrection:: return mScenarioPtr[getSectorRowInfo(sector, row).splineScenarioID]; } -GPUdi() float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) +GPUdi() float* TPCFastSpaceChargeCorrection::getCorrectionData(int32_t sector, int32_t row, int32_t iSpline) { /// Gives pointer to spline data - return reinterpret_cast(mSplineData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); + return reinterpret_cast(mCorrectionData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); } -GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineData(int32_t sector, int32_t row, int32_t iSpline) const +GPUdi() const float* TPCFastSpaceChargeCorrection::getCorrectionData(int32_t sector, int32_t row, int32_t iSpline) const { /// Gives pointer to spline data - return reinterpret_cast(mSplineData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); + return reinterpret_cast(mCorrectionData[iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); } GPUdi() TPCFastSpaceChargeCorrection::SplineTypeInvX& TPCFastSpaceChargeCorrection::getSplineInvX(int32_t sector, int32_t row) @@ -417,16 +383,16 @@ GPUdi() const TPCFastSpaceChargeCorrection::SplineTypeInvX& TPCFastSpaceChargeCo return reinterpret_cast(getSpline(sector, row)); } -GPUdi() float* TPCFastSpaceChargeCorrection::getSplineDataInvX(int32_t sector, int32_t row) +GPUdi() float* TPCFastSpaceChargeCorrection::getCorrectionDataInvX(int32_t sector, int32_t row) { /// Gives pointer to spline data for the inverse X correction - return getSplineData(sector, row, 1); + return getCorrectionData(sector, row, 1); } -GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineDataInvX(int32_t sector, int32_t row) const +GPUdi() const float* TPCFastSpaceChargeCorrection::getCorrectionDataInvX(int32_t sector, int32_t row) const { /// Gives pointer to spline data for the inverse X correction - return getSplineData(sector, row, 1); + return getCorrectionData(sector, row, 1); } GPUdi() TPCFastSpaceChargeCorrection::SplineTypeInvYZ& TPCFastSpaceChargeCorrection::getSplineInvYZ(int32_t sector, int32_t row) @@ -441,16 +407,16 @@ GPUdi() const TPCFastSpaceChargeCorrection::SplineTypeInvYZ& TPCFastSpaceChargeC return reinterpret_cast(getSpline(sector, row)); } -GPUdi() float* TPCFastSpaceChargeCorrection::getSplineDataInvYZ(int32_t sector, int32_t row) +GPUdi() float* TPCFastSpaceChargeCorrection::getCorrectionDataInvYZ(int32_t sector, int32_t row) { /// Gives pointer to spline data for the inverse YZ correction - return getSplineData(sector, row, 2); + return getCorrectionData(sector, row, 2); } -GPUdi() const float* TPCFastSpaceChargeCorrection::getSplineDataInvYZ(int32_t sector, int32_t row) const +GPUdi() const float* TPCFastSpaceChargeCorrection::getCorrectionDataInvYZ(int32_t sector, int32_t row) const { /// Gives pointer to spline data for the inverse YZ correction - return getSplineData(sector, row, 2); + return getCorrectionData(sector, row, 2); } GPUdi() std::array TPCFastSpaceChargeCorrection::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const @@ -518,7 +484,7 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionLocal(in { const auto& info = getSectorRowInfo(sector, row); const SplineType& spline = getSpline(sector, row); - const float* splineData = getSplineData(sector, row); + const float* splineData = getCorrectionData(sector, row); auto val = convLocalToGrid(sector, row, y, z); @@ -536,7 +502,7 @@ GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t secto const auto& info = getSectorRowInfo(sector, row); auto val = convRealLocalToGrid(sector, row, realY, realZ); float dx = 0; - getSplineInvX(sector, row).interpolateAtU(getSplineDataInvX(sector, row), val[0], val[1], &dx); + getSplineInvX(sector, row).interpolateAtU(getCorrectionDataInvX(sector, row), val[0], val[1], &dx); dx = val[2] * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); return dx; } @@ -546,7 +512,7 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionYZatReal auto val = convRealLocalToGrid(sector, row, realY, realZ); const auto& info = getSectorRowInfo(sector, row); float dyz[2]; - getSplineInvYZ(sector, row).interpolateAtU(getSplineDataInvYZ(sector, row), val[0], val[1], dyz); + getSplineInvYZ(sector, row).interpolateAtU(getCorrectionDataInvYZ(sector, row), val[0], val[1], dyz); dyz[0] = val[2] * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); dyz[1] = val[2] * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); return {dyz[0], dyz[1]}; diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 60f5952e6a1fc..64fdba9d94bd3 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -337,7 +337,7 @@ class TPCFastTransform : public FlatObject GPUd() void TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; - ClassDefNV(TPCFastTransform, 4); + ClassDefNV(TPCFastTransform, 5); }; // ======================================================================= diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index 5b2dcc8da82d5..2fe773a76e4d3 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -28,12 +28,10 @@ using namespace o2::gpu; TPCFastTransformGeo::TPCFastTransformGeo() { // Default Constructor: creates an empty uninitialized object - double dAlpha = 2. * M_PI / (NumberOfSectorsA); for (int32_t i = 0; i < NumberOfSectors; i++) { - SectorInfo& s = mSectorInfos[i]; - double alpha = dAlpha * (i + 0.5); - s.sinAlpha = sin(alpha); - s.cosAlpha = cos(alpha); + double angle = (i + 0.5) * 2. * M_PI / NumberOfSectorsA; + mSectorInfos[i].sinAlpha = sin(angle); + mSectorInfos[i].cosAlpha = cos(angle); } mSectorInfos[NumberOfSectors] = SectorInfo{}; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index fc28bbef33602..09793b6677d83 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -19,6 +19,8 @@ #include "GPUCommonDef.h" #include "GPUCommonArray.h" +#include "GPUCommonMath.h" + #ifndef GPUCA_GPUCODE_DEVICE #include #include "GPUCommonRtypes.h" @@ -34,6 +36,7 @@ namespace gpu /// class TPCFastTransformGeo { + public: /// The struct contains necessary info for TPC sector struct SectorInfo { @@ -61,7 +64,7 @@ class TPCFastTransformGeo /// get width in Y GPUd() float getYwidth() const { return -2.f * yMin; } - ClassDefNV(RowInfo, 1); + ClassDefNV(RowInfo, 2); }; /// _____________ Constructors / destructors __________________________ @@ -187,6 +190,11 @@ class TPCFastTransformGeo SectorInfo mSectorInfos[NumberOfSectors + 1]; ///< array of sector information [fixed size] RowInfo mRowInfos[MaxNumberOfRows + 1]; ///< array of row information [fixed size] + public: + struct SliceInfo { // legacy, needed only for schema evolution + ClassDefNV(SliceInfo, 2); + }; + ClassDefNV(TPCFastTransformGeo, 3); }; diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index 916695a3be1c7..284d5f229d5e0 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -58,19 +58,36 @@ #pragma link C++ class o2::gpu::SemiregularSpline2D3D + ; #pragma link C++ class o2::gpu::IrregularSpline2D3DCalibrator + ; -#pragma link C++ class o2::gpu::TPCFastTransformGeo + ; +#pragma link C++ class o2::gpu::TPCFastTransformGeo::SliceInfo + ; #pragma link C++ class o2::gpu::TPCFastTransformGeo::SectorInfo + ; + +#pragma link C++ class o2::gpu::TPCFastTransformGeo + ; +#pragma read \ + sourceClass = "o2::gpu::TPCFastTransformGeo" targetClass = "o2::gpu::TPCFastTransformGeo" source = "float mTPCzLengthA; float mTPCzLengthC; float mTPCalignmentZ; float mScaleVtoSVsideA; float mScaleVtoSVsideC; float mScaleSVtoVsideA; float mScaleSVtoVsideC;" version = "[-1]" target = "mTPCzLength" code = "{ mTPCzLength = onfile.mTPCzLengthA; }"; + +#pragma read \ + sourceClass = "o2::gpu::TPCFastTransformGeo" targetClass = "o2::gpu::TPCFastTransformGeo" source = "o2::gpu::TPCFastTransformGeo::SliceInfo mSliceInfos[37]" version = "[1-]" target = "" code = "{}"; + #pragma link C++ class o2::gpu::TPCFastTransformGeo::RowInfo + ; +#pragma read \ + sourceClass = "o2::gpu::TPCFastTransformGeo::RowInfo" targetClass = "o2::gpu::TPCFastTransformGeo::RowInfo" source = "float u0; float scaleUtoSU; float scaleSUtoU" version = "[-2]" target = "yMin" code = "{ yMin = onfile.u0; }" #pragma link C++ class o2::gpu::TPCFastTransform + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrectionMap + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::RowInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection + ; -#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorInfo + ; +#pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SliceInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::SectorRowInfo + ; #pragma link C++ class o2::gpu::TPCFastSpaceChargeCorrection::GridInfo + ; +#pragma read \ + sourceClass = "o2::gpu::TPCFastSpaceChargeCorrection" targetClass = "o2::gpu::TPCFastSpaceChargeCorrection" source = "o2::gpu::TPCFastSpaceChargeCorrection::SliceInfo mSliceInfo[36]" version = "[-3]" target = "" code = "{}"; + +#pragma read \ + sourceClass = "o2::gpu::TPCFastSpaceChargeCorrection" targetClass = "o2::gpu::TPCFastSpaceChargeCorrection" source = "size_t mSliceDataSizeBytes[3]" version = "[-3]" target = "mCorrectionDataSize" code = "{ for (int i=0; i<3; i++) mCorrectionDataSize[i] = onfile.mSliceDataSizeBytes[i] * 36; }"; + +#pragma read \ + sourceClass = "o2::gpu::TPCFastSpaceChargeCorrection" targetClass = "o2::gpu::TPCFastSpaceChargeCorrection" source = "float fInterpolationSafetyMargin" version = "[-3]" target = "" code = "{}"; #pragma link C++ class o2::gpu::CorrectionMapsHelper + ; #pragma link C++ struct o2::gpu::MultivariatePolynomialContainer + ; diff --git a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C index 3cb4812abafc1..baaeca90202d5 100644 --- a/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C +++ b/GPU/TPCFastTransformation/macro/TPCFastTransformInit.C @@ -18,7 +18,7 @@ /// how to run the macro: /// -/// root -l TPCFastTransformInit.C'("debugVoxRes.root")' +/// root -l TPCFastTransformInit.C'("VoxRes.root", "VoxResInv.root")' /// #if !defined(__CLING__) || defined(__ROOTCLING__) @@ -45,7 +45,7 @@ using namespace o2::tpc; using namespace o2::gpu; void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* fileNameInv = "debugVoxResInv.root", - const char* outFileName = "TPCFastTransform_VoxRes.root", bool useSmoothed = false, bool invertSigns = false) + const char* outFileName = "TPCFastTransform_VoxRes.root", bool useSmoothed = false, bool invertSigns = false, bool doDebug = true) { // Initialise TPCFastTransform object from "voxRes" tree of @@ -56,9 +56,9 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* To visiualise the results: root -l transformDebug.root - all->Draw("cx:y:z","sec==0&&iRow==10","") - grid->Draw("cx:y:z","sec==0&&iRow==10","same") - vox->Draw("vx:y:z","sec==0&&iRow==10","same") + all->Draw("cx:y:z","sec==0&&row==10","") + grid->Draw("cx:y:z","sec==0&&row==10","same") + vox->Draw("vx:y:z","sec==0&&row==10","same") points->Draw("px:y:z","sec==0&&row==10","same") */ @@ -112,6 +112,38 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* trackResiduals.setZ2XBinning(z2xBins); trackResiduals.init(); + std::cout << "create fast transformation ... " << std::endl; + + auto* helper = o2::tpc::TPCFastTransformHelperO2::instance(); + + o2::tpc::TPCFastSpaceChargeCorrectionHelper* corrHelper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); + + corrHelper->setNthreadsToMaximum(); + // corrHelper->setNthreads(1); + + if (debugMirrorAdata2C) { + corrHelper->setDebugMirrorAdata2C(); + } + // corrHelper->setDebugUseVoxelCenters(); + + o2::gpu::TPCFastSpaceChargeCorrectionMap mapDirect(0, 0), mapInverse(0, 0); + + auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns, + &mapDirect, &mapInverse); + + std::unique_ptr fastTransform( + helper->create(0, *corrPtr)); + + std::cout << "... create fast transformation completed " << std::endl; + + if (*outFileName) { + fastTransform->writeToFile(outFileName, "ccdb_object"); + } + + if (!doDebug) { + return; + } + { // debug output std::cout << " ===== input track residuals ==== " << std::endl; @@ -144,40 +176,12 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* std::cout << " ==================================== " << std::endl; } - std::cout << "create fast transformation ... " << std::endl; - - auto* helper = o2::tpc::TPCFastTransformHelperO2::instance(); - - o2::tpc::TPCFastSpaceChargeCorrectionHelper* corrHelper = o2::tpc::TPCFastSpaceChargeCorrectionHelper::instance(); - - corrHelper->setNthreadsToMaximum(); - corrHelper->setNthreads(1); - - if (debugMirrorAdata2C) { - corrHelper->setDebugMirrorAdata2C(); - } - // corrHelper->setDebugUseVoxelCenters(); - - o2::gpu::TPCFastSpaceChargeCorrectionMap mapDirect(0, 0), mapInverse(0, 0); - - auto corrPtr = corrHelper->createFromTrackResiduals(trackResiduals, voxResTree, voxResTreeInverse, useSmoothed, invertSigns, - &mapDirect, &mapInverse); - - std::unique_ptr fastTransform( - helper->create(0, *corrPtr)); - - std::cout << "... create fast transformation completed " << std::endl; - - if (*outFileName) { - fastTransform->writeToFile(outFileName, "ccdb_object"); - } - - if (1) { // read transformation from the file - - // const char* fileName = "master/out.root"; + if (1) { // read transformation from the output file to verify the io const char* fileName = outFileName; + // fileName = "~/test/master/TPCFastTransform_VoxRes.root"; + std::cout << "load corrections from file " << fileName << std::endl; fastTransform->cloneFromObject(*TPCFastTransform::loadFromFile(fileName, "ccdb_object"), nullptr); @@ -488,11 +492,6 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* auto [yMin, yMax] = geo.getRowInfo(iRow).getYrange(); auto [zMin, zMax] = geo.getZrange(iSector); - points[0].push_back(yMin); - points[0].push_back(yMax); - points[1].push_back(zMin); - points[1].push_back(zMax); - for (int32_t iu = 0; iu < gridY.getNumberOfKnots(); iu++) { auto [y, z] = corr.convGridToLocal(iSector, iRow, gridY.getKnot(iu).getU(), 0.); knots[0].push_back(y); @@ -508,12 +507,19 @@ void TPCFastTransformInit(const char* fileName = "debugVoxRes.root", const char* std::sort(knots[iyz].begin(), knots[iyz].end()); std::sort(points[iyz].begin(), points[iyz].end()); int32_t n = points[iyz].size(); + int nsteps = (iyz == 0) ? 10 : 5; for (int32_t i = 0; i < n - 1; i++) { - double d = (points[iyz][i + 1] - points[iyz][i]) / 10.; - for (int32_t ii = 1; ii < 10; ii++) { + double d = (points[iyz][i + 1] - points[iyz][i]) / nsteps; + for (int32_t ii = 1; ii < nsteps; ii++) { points[iyz].push_back(points[iyz][i] + d * ii); } } + } + points[0].push_back(yMin); + points[0].push_back(yMax); + points[1].push_back(zMin); + points[1].push_back(zMax); + for (int32_t iyz = 0; iyz <= 1; iyz++) { std::sort(points[iyz].begin(), points[iyz].end()); } From c6de88688866d3917ef7f3606f0a6a3db6beaf0e Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Wed, 15 Oct 2025 16:36:51 +0200 Subject: [PATCH 24/26] Fix compiler-warnings, codechecker violations and compilation Fix compiler warnings on MacOS Fix compiler warning, memmove must only operate on trivial types Fix coding rule violations TPC Splines: compilation fix --- .../TPCFastSpaceChargeCorrectionHelper.cxx | 15 ++++---- .../macro/createTPCSpaceChargeCorrection.C | 34 +++++++++---------- .../TPCFastSpaceChargeCorrection.cxx | 2 +- .../TPCFastTransformationLinkDef_O2.h | 4 +-- .../macro/generateTPCCorrectionNTuple.C | 21 +++++------- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx index faba4f2ce065e..7622c40001e1d 100644 --- a/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx +++ b/Detectors/TPC/calibration/src/TPCFastSpaceChargeCorrectionHelper.cxx @@ -690,9 +690,9 @@ std::unique_ptr TPCFastSpaceChargeCorrect LOG(warning) << directionName << " correction: error N " << nErrors << "fitted voxel position is outside the voxel: " << " sector " << iSector << " row " << iRow << " bin y " << iy << " bin z " << iz << msg.str(); - maxError[0] = GPUCommonMath::Max(maxError[0], fabs(data.mX - x) / dx); - maxError[1] = GPUCommonMath::Max(maxError[1], fabs(data.mY - vox.mY) / vox.mDy); - maxError[2] = GPUCommonMath::Max(maxError[2], fabs(data.mZ - vox.mZ) / vox.mDz); + maxError[0] = GPUCommonMath::Max(maxError[0], fabs(data.mX - x) / dx); + maxError[1] = GPUCommonMath::Max(maxError[1], fabs(data.mY - vox.mY) / vox.mDy); + maxError[2] = GPUCommonMath::Max(maxError[2], fabs(data.mZ - vox.mZ) / vox.mDz); } mutex.unlock(); } @@ -794,12 +794,15 @@ std::unique_ptr TPCFastSpaceChargeCorrect auto addEdge = [&](int iy1, int iz1, int iy2, int iz2, int nPoints) { // add n points on the edge between two voxels excluding the voxel points - if (nPoints < 1) + if (nPoints < 1) { return; - if (iy1 < 0 || iy1 >= nY2Xbins || iz1 < 0 || iz1 >= nZ2Xbins) + } + if (iy1 < 0 || iy1 >= nY2Xbins || iz1 < 0 || iz1 >= nZ2Xbins) { return; - if (iy2 < 0 || iy2 >= nY2Xbins || iz2 < 0 || iz2 >= nZ2Xbins) + } + if (iy2 < 0 || iy2 >= nY2Xbins || iz2 < 0 || iz2 >= nZ2Xbins) { return; + } auto& data1 = vSectorData[iSector * nRows + iRow][iy1 * nZ2Xbins + iz1]; auto& vox1 = vRowVoxels[iy1 * nZ2Xbins + iz1]; auto& data2 = vSectorData[iSector * nRows + iRow][iy2 * nZ2Xbins + iz2]; diff --git a/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C b/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C index 723cf2ee30491..af066598d1317 100644 --- a/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C +++ b/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C @@ -397,10 +397,9 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, const o2::gpu::TPCFastTransformGeo& geo, TPCFastTransform* fastTransform) { - for (int slice = 0; slice < geo.getNumberOfSlices(); slice += 1) { - // for (int slice = 21; slice < 22; slice += 1) { - std::cout << "debug slice " << slice << " ... " << std::endl; - const o2::gpu::TPCFastTransformGeo::SliceInfo& sliceInfo = geo.getSliceInfo(slice); + for (int sector = 0; sector < geo.getNumberOfSectors(); sector += 1) { + // for (int sector = 21; sector < 22; sector += 1) { + std::cout << "debug sector " << sector << " ... " << std::endl; for (int row = 0; row < geo.getNumberOfRows(); row++) { int nPads = geo.getRowInfo(row).maxPad + 1; @@ -411,28 +410,28 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, // non-corrected point fastTransform->setApplyCorrectionOff(); float lx, ly, lz; - fastTransform->Transform(slice, row, pad, time, lx, ly, lz); + fastTransform->Transform(sector, row, pad, time, lx, ly, lz); float gx, gy, gz, r, phi; - geo.convLocalToGlobal(slice, lx, ly, lz, gx, gy, gz); + geo.convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); r = std::sqrt(lx * lx + ly * ly); phi = std::atan2(gy, gx); fastTransform->setApplyCorrectionOn(); // fast transformation float lxT, lyT, lzT; - fastTransform->Transform(slice, row, pad, time, lxT, lyT, lzT); + fastTransform->Transform(sector, row, pad, time, lxT, lyT, lzT); float gxT, gyT, gzT, rT; - geo.convLocalToGlobal(slice, lxT, lyT, lzT, gxT, gyT, gzT); + geo.convLocalToGlobal(sector, lxT, lyT, lzT, gxT, gyT, gzT); rT = std::sqrt(lxT * lxT + lyT * lyT); // the original correction double gdC[3] = {0, 0, 0}; - Side side = slice < geo.getNumberOfSlicesA() ? Side::A : Side::C; + Side side = sector < geo.getNumberOfSectorsA() ? Side::A : Side::C; if (spaceCharge) { spaceCharge->getCorrections(gx, gy, gz, side, gdC[0], gdC[1], gdC[2]); } float ldxC, ldyC, ldzC; - geo.convGlobalToLocal(slice, gdC[0], gdC[1], gdC[2], ldxC, ldyC, ldzC); + geo.convGlobalToLocal(sector, gdC[0], gdC[1], gdC[2], ldxC, ldyC, ldzC); double rC = std::sqrt((gx + gdC[0]) * (gx + gdC[0]) + (gy + gdC[1]) * (gy + gdC[1])); @@ -466,7 +465,7 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, if (spaceChargeExB) { double gdC_ExB[3] = {0, 0, 0}; spaceChargeExB->getCorrections(gx, gy, gz, side, gdC_ExB[0], gdC_ExB[1], gdC_ExB[2]); - geo.convGlobalToLocal(slice, gdC_ExB[0], gdC_ExB[1], gdC_ExB[2], ldxC_ExB, ldyC_ExB, ldzC_ExB); + geo.convGlobalToLocal(sector, gdC_ExB[0], gdC_ExB[1], gdC_ExB[2], ldxC_ExB, ldyC_ExB, ldzC_ExB); } // static distortions @@ -474,18 +473,18 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, if (spaceChargeStack) { double gdC_static[3] = {0, 0, 0}; spaceChargeStack->getCorrections(gx, gy, gz, side, gdC_static[0], gdC_static[1], gdC_static[2]); - geo.convGlobalToLocal(slice, gdC_static[0], gdC_static[1], gdC_static[2], ldxC_static, ldyC_static, ldzC_static); + geo.convGlobalToLocal(sector, gdC_static[0], gdC_static[1], gdC_static[2], ldxC_static, ldyC_static, ldzC_static); } // get combined corrections double dx_comb = 0, dy_comb = 0, dz_comb = 0; - getGlobalSpaceChargeCorrectionLinearCombination(slice, gx, gy, gz, dx_comb, dy_comb, dz_comb); + getGlobalSpaceChargeCorrectionLinearCombination(sector, gx, gy, gz, dx_comb, dy_comb, dz_comb); float ldxC_comb, ldyC_comb, ldzC_comb; - geo.convGlobalToLocal(slice, dx_comb, dy_comb, dz_comb, ldxC_comb, ldyC_comb, ldzC_comb); + geo.convGlobalToLocal(sector, dx_comb, dy_comb, dz_comb, ldxC_comb, ldyC_comb, ldzC_comb); pcstream << "fastTransform" // internal coordinates - << "slice=" << slice + << "sector=" << sector << "row=" << row << "pad=" << pad << "time=" << time @@ -613,10 +612,9 @@ void debugGridpoints(utils::TreeStreamRedirector& pcstream, const o2::gpu::TPCFa break; } } - float u = 0.f, v = 0.f; - geo.convLocalToUV(sector, y0, z0, u, v); + float pad = 0.f, time = 0.f; - fastTransform->convUVtoPadTime(sector, row, u, v, pad, time, 0.f); + fastTransform->convLocalToPadTime(sector, row, y0, z0, pad, time, 0.f); if (pad < 0) { continue; } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 5a2cd21deeb2b..5f39e749f73d9 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -294,7 +294,7 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer // move spline scenarios to the new place in the buffer mScenarioPtr = reinterpret_cast(mFlatBufferPtr); - memmove(mScenarioPtr, oldScenarioPtr, scenariosSize); + memmove((void*)mScenarioPtr, (const void*)oldScenarioPtr, scenariosSize); size_t oldScenariosBufferOffset = alignSize(oldScenariosOffset + scenariosSize, SplineType::getBufferAlignmentBytes()); size_t scenariosBufferOffset = alignSize(scenariosSize, SplineType::getBufferAlignmentBytes()); diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index 284d5f229d5e0..f1872549a46aa 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -66,11 +66,11 @@ sourceClass = "o2::gpu::TPCFastTransformGeo" targetClass = "o2::gpu::TPCFastTransformGeo" source = "float mTPCzLengthA; float mTPCzLengthC; float mTPCalignmentZ; float mScaleVtoSVsideA; float mScaleVtoSVsideC; float mScaleSVtoVsideA; float mScaleSVtoVsideC;" version = "[-1]" target = "mTPCzLength" code = "{ mTPCzLength = onfile.mTPCzLengthA; }"; #pragma read \ - sourceClass = "o2::gpu::TPCFastTransformGeo" targetClass = "o2::gpu::TPCFastTransformGeo" source = "o2::gpu::TPCFastTransformGeo::SliceInfo mSliceInfos[37]" version = "[1-]" target = "" code = "{}"; + sourceClass = "o2::gpu::TPCFastTransformGeo" targetClass = "o2::gpu::TPCFastTransformGeo" source = "o2::gpu::TPCFastTransformGeo::SliceInfo mSliceInfos[37]" version = "[-2]" target = "" code = "{}"; #pragma link C++ class o2::gpu::TPCFastTransformGeo::RowInfo + ; #pragma read \ - sourceClass = "o2::gpu::TPCFastTransformGeo::RowInfo" targetClass = "o2::gpu::TPCFastTransformGeo::RowInfo" source = "float u0; float scaleUtoSU; float scaleSUtoU" version = "[-2]" target = "yMin" code = "{ yMin = onfile.u0; }" + sourceClass = "o2::gpu::TPCFastTransformGeo::RowInfo" targetClass = "o2::gpu::TPCFastTransformGeo::RowInfo" source = "float u0; float scaleUtoSU; float scaleSUtoU" version = "[-1]" target = "yMin" code = "{ yMin = onfile.u0; }" #pragma link C++ class o2::gpu::TPCFastTransform + ; diff --git a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C index 69b7909cda683..2c8f22e4a3f3b 100644 --- a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C +++ b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C @@ -82,7 +82,7 @@ void generateTPCCorrectionNTuple(const char* path = "InputSCDensityHistograms.ro const o2::gpu::TPCFastTransformGeo& geo = fastTransform->getGeometry(); TFile* f = new TFile("tpcCorrection.root", "RECREATE"); - TNtuple* nt = new TNtuple("dist", "dist", "sector:row:su:sv:dx:du:dv"); + TNtuple* nt = new TNtuple("dist", "dist", "sector:row:x:y:z:dx:dy:dz"); int32_t nSectors = 1; // fastTransform->getNumberOfSectors(); // for( int32_t sector=0; sectorFill(sector, row, su, sv, dx, du, dv); + float dy = y1 - y; + float dz = z1 - z; + nt->Fill(sector, row, x, y, z, dx, dy, dz); } } } From d30e01aef237ebb6bb56f696a6c4b01857d6bc26 Mon Sep 17 00:00:00 2001 From: Sergey Gorbunov Date: Thu, 5 Feb 2026 09:38:08 +0000 Subject: [PATCH 25/26] TPC Splines: keep old cropping scheme --- .../TPCFastSpaceChargeCorrection.cxx | 4 ++-- .../TPCFastSpaceChargeCorrection.h | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 5f39e749f73d9..241a1fcfc795b 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -285,8 +285,8 @@ void TPCFastSpaceChargeCorrection::setActualBufferAddress(char* actualFlatBuffer } newSectorRow.resetMaxValues(); - newSectorRow.updateMaxValues(-50.f, -50.f, -50.f); - newSectorRow.updateMaxValues(50.f, 50.f, 50.f); + newSectorRow.updateMaxValues(-100.f, -100.f, -100.f); + newSectorRow.updateMaxValues(100.f, 100.f, 100.f); } } } diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index b4fab68b91542..b1a3d0c35da7c 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -491,9 +491,14 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionLocal(in float dxyz[3]; spline.interpolateAtU(splineData, val[0], val[1], dxyz); + if (CAMath::Abs(dxyz[0]) > 100.f || CAMath::Abs(dxyz[1]) > 100.f || CAMath::Abs(dxyz[2]) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } + float dx = val[2] * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); float dy = val[2] * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); float dz = val[2] * GPUCommonMath::Clamp(dxyz[2], info.minCorr[2], info.maxCorr[2]); + return {dx, dy, dz}; } @@ -503,6 +508,9 @@ GPUdi() float TPCFastSpaceChargeCorrection::getCorrectionXatRealYZ(int32_t secto auto val = convRealLocalToGrid(sector, row, realY, realZ); float dx = 0; getSplineInvX(sector, row).interpolateAtU(getCorrectionDataInvX(sector, row), val[0], val[1], &dx); + if (CAMath::Abs(dx) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } dx = val[2] * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); return dx; } @@ -513,6 +521,9 @@ GPUdi() std::array TPCFastSpaceChargeCorrection::getCorrectionYZatReal const auto& info = getSectorRowInfo(sector, row); float dyz[2]; getSplineInvYZ(sector, row).interpolateAtU(getCorrectionDataInvYZ(sector, row), val[0], val[1], dyz); + if (CAMath::Abs(dyz[0]) > 100.f || CAMath::Abs(dyz[1]) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } dyz[0] = val[2] * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); dyz[1] = val[2] * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); return {dyz[0], dyz[1]}; From cd9df99e7cc4e8b37babec6a839110a90c15b5ad Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 22 Feb 2026 12:43:33 +0100 Subject: [PATCH 26/26] Add POD version of TPCFastTransform The TPCFastTransformPOD is a pointerless version of the TPCFastTransform. It can be created from the original TPCFastTransform as e.g. auto lold = o2::gpu::TPCFastTransform::loadFromFile("o2-gpu-TPCFastTransform.root","ccdb_object"); // load original transform std::vector v; // one has to provide a vector (could be a std or pmr), which later can be messaged via DPL auto* pod = o2::gpu::TPCFastTransformPOD::create(v, *lold); // pointer pod is just v.data() cast to TPCFastTransformPOD* // run test: pod->test(*lold); [INFO] (ns per call) original this Nmissmatch [INFO] getCorrection 1.330e+02 1.400e+02 0 [INFO] getCorrectionInvCorrectedX 8.856e+01 8.434e+01 0 [INFO] getCorrectionInvUV 6.266e+01 6.142e+01 0 It can be also created directly from the TPCFastSpaceChargeCorrection as TPCFastSpaceChargeCorrection& oldCorr = lold->getCorrection(); auto* pod = o2::gpu::TPCFastTransformPOD::create(v, oldCorr); but in this case one should afterwards set the vdrift and t0 using provided getters. TPCFastTransformPOD replicates all the methods of the TPCFastTransform (and of the TPCFastSpaceChargeCorrection), including those which allow to query rescaled corrections (by providing refernce maps and scaling coefficients). Since the idea of this class is to create a final correction map as a weighted sum of different contribution and to distribute it to consumer processes via shared memory, also the query methods w/o rescaling are added, they have the suffix _new added. Eventually, the scalable legacy methods can be suppressed and the suffix new can be dropped. --- GPU/TPCFastTransformation/CMakeLists.txt | 1 + .../TPCFastSpaceChargeCorrection.h | 2 + .../TPCFastTransformPOD.cxx | 238 +++++ .../TPCFastTransformPOD.h | 920 ++++++++++++++++++ .../TPCFastTransformationLinkDef_O2.h | 1 + 5 files changed, 1162 insertions(+) create mode 100644 GPU/TPCFastTransformation/TPCFastTransformPOD.cxx create mode 100644 GPU/TPCFastTransformation/TPCFastTransformPOD.h diff --git a/GPU/TPCFastTransformation/CMakeLists.txt b/GPU/TPCFastTransformation/CMakeLists.txt index 182a66fb28296..769e9981102ef 100644 --- a/GPU/TPCFastTransformation/CMakeLists.txt +++ b/GPU/TPCFastTransformation/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRCS TPCFastSpaceChargeCorrectionMap.cxx TPCFastTransform.cxx CorrectionMapsHelper.cxx + TPCFastTransformPOD.cxx ) if(NOT ALIGPU_BUILD_TYPE STREQUAL "Standalone") diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index b1a3d0c35da7c..1a11c94888067 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -38,6 +38,8 @@ namespace gpu /// class TPCFastSpaceChargeCorrection : public FlatObject { + friend class TPCFastTransformPOD; + public: // obsolete structure, declared here only for backward compatibility struct SliceInfo { diff --git a/GPU/TPCFastTransformation/TPCFastTransformPOD.cxx b/GPU/TPCFastTransformation/TPCFastTransformPOD.cxx new file mode 100644 index 0000000000000..8796e96f228d5 --- /dev/null +++ b/GPU/TPCFastTransformation/TPCFastTransformPOD.cxx @@ -0,0 +1,238 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file TPCFastTransformPOD.cxx +/// \brief Implementation of POD correction map +/// +/// \author ruben.shahoayn@cern.ch + +#include "TPCFastTransformPOD.h" +/// \brief Implementation of POD correction map +/// +/// \author ruben.shahoayn@cern.ch + +#include "TPCFastTransformPOD.h" +#include "GPUDebugStreamer.h" +#if !defined(GPUCA_GPUCODE) +#include +#endif + +namespace o2 +{ +namespace gpu +{ + +#if !defined(GPUCA_GPUCODE) + +size_t TPCFastTransformPOD::estimateSize(const TPCFastSpaceChargeCorrection& origCorr) +{ + // estimate size of own buffer + const size_t selfSizeFix = sizeof(TPCFastTransformPOD); + size_t nextDynOffs = alignOffset(selfSizeFix); + nextDynOffs = alignOffset(nextDynOffs + origCorr.mNumberOfScenarios * sizeof(size_t)); // spline scenarios start here + // space for splines + for (int isc = 0; isc < origCorr.mNumberOfScenarios; isc++) { + const auto& spline = origCorr.mScenarioPtr[isc]; + nextDynOffs = alignOffset(nextDynOffs + sizeof(spline)); + } + // space for splines data + for (int is = 0; is < 3; is++) { + for (int sector = 0; sector < origCorr.mGeo.getNumberOfSectors(); sector++) { + for (int row = 0; row < NROWS; row++) { + const auto& spline = origCorr.getSpline(sector, row); + int nPar = spline.getNumberOfParameters(); + if (is == 1) { + nPar = nPar / 3; + } + if (is == 2) { + nPar = nPar * 2 / 3; + } + nextDynOffs += nPar * sizeof(float); + } + } + } + nextDynOffs = alignOffset(nextDynOffs); + return nextDynOffs; +} + +TPCFastTransformPOD* TPCFastTransformPOD::create(char* buff, size_t buffSize, const TPCFastSpaceChargeCorrection& origCorr) +{ + // instantiate object to already created buffer of the right size + assert(buffSize > sizeof(TPCFastTransformPOD)); + auto& podMap = getNonConst(buff); + podMap.mApplyCorrection = true; // by default always apply corrections + + // copy fixed size data --- start + podMap.mNumberOfScenarios = origCorr.mNumberOfScenarios; + std::memcpy(&podMap.mGeo, &origCorr.mGeo, sizeof(TPCFastTransformGeo)); // copy geometry (fixed size) + for (int sector = 0; sector < TPCFastTransformGeo::getNumberOfSectors(); sector++) { + for (int row = 0; row < NROWS; row++) { + podMap.mSectorRowInfos[NROWS * sector + row] = origCorr.getSectorRowInfo(sector, row); + } + } + podMap.mTimeStamp = origCorr.mTimeStamp; + // + // init data members coming from the TPCFastTrasform + podMap.mVdrift = 0.; + podMap.mT0 = 0.; + // copy fixed size data --- end + + size_t nextDynOffs = alignOffset(sizeof(TPCFastTransformPOD)); + + // copy sector scenarios + podMap.mOffsScenariosOffsets = nextDynOffs; // spline scenarios offsets start here + LOGP(debug, "Set mOffsScenariosOffsets = {}", podMap.mOffsScenariosOffsets); + nextDynOffs = alignOffset(nextDynOffs + podMap.mNumberOfScenarios * sizeof(size_t)); // spline scenarios start here + + // copy spline objects + size_t* scenOffs = reinterpret_cast(buff + podMap.mOffsScenariosOffsets); + for (int isc = 0; isc < origCorr.mNumberOfScenarios; isc++) { + scenOffs[isc] = nextDynOffs; + const auto& spline = origCorr.mScenarioPtr[isc]; + if (buffSize < nextDynOffs + sizeof(spline)) { + throw std::runtime_error(fmt::format("attempt to copy {} bytes for spline for scenario {} to {}, overflowing the buffer of size {}", sizeof(spline), isc, nextDynOffs + sizeof(spline), buffSize)); + } + std::memcpy(buff + scenOffs[isc], &spline, sizeof(spline)); + nextDynOffs = alignOffset(nextDynOffs + sizeof(spline)); + LOGP(debug, "Copy {} bytes for spline scenario {} (ptr:{}) to offsset {}", sizeof(spline), isc, (void*)&spline, scenOffs[isc]); + } + + // copy splines data + for (int is = 0; is < 3; is++) { + float* data = reinterpret_cast(buff + nextDynOffs); + LOGP(debug, "splinID={} start offset {} -> {}", is, nextDynOffs, (void*)data); + for (int sector = 0; sector < origCorr.mGeo.getNumberOfSectors(); sector++) { + podMap.mSplineDataOffsets[sector][is] = nextDynOffs; + size_t rowDataOffs = 0; + for (int row = 0; row < NROWS; row++) { + const auto& spline = origCorr.getSpline(sector, row); + const float* dataOr = origCorr.getCorrectionData(sector, row, is); + int nPar = spline.getNumberOfParameters(); + if (is == 1) { + nPar = nPar / 3; + } + if (is == 2) { + nPar = nPar * 2 / 3; + } + LOGP(debug, "Copying {} floats for spline{} of sector:{} row:{} to offset {}", nPar, is, sector, row, nextDynOffs); + size_t nbcopy = nPar * sizeof(float); + if (buffSize < nextDynOffs + nbcopy) { + throw std::runtime_error(fmt::format("attempt to copy {} bytes of data for spline{} of sector{}/row{} to {}, overflowing the buffer of size {}", nbcopy, is, sector, row, nextDynOffs, buffSize)); + } + std::memcpy(data, dataOr, nbcopy); + podMap.getSectorRowInfo(sector, row).dataOffsetBytes[is] = rowDataOffs; + rowDataOffs += nbcopy; + data += nPar; + nextDynOffs += nbcopy; + } + } + } + podMap.mTotalSize = alignOffset(nextDynOffs); + if (buffSize != podMap.mTotalSize) { + throw std::runtime_error(fmt::format("Estimated buffer size {} differs from filled one {}", buffSize, podMap.mTotalSize)); + } + return &getNonConst(buff); +} + +TPCFastTransformPOD* TPCFastTransformPOD::create(char* buff, size_t buffSize, const TPCFastTransform& src) +{ + // instantiate objec to already created buffer of the right size + auto podMap = create(buff, buffSize, src.getCorrection()); + // set data members of TPCFastTransform + podMap->mVdrift = src.getVDrift(); + podMap->mT0 = src.getT0(); + // copy fixed size data --- end + return podMap; +} + +bool TPCFastTransformPOD::test(const TPCFastSpaceChargeCorrection& origCorr, int npoints) const +{ + if (npoints < 1) { + return false; + } + std::vector sector, row; + std::vector y, z; + std::vector> corr0, corr1; + std::vector> corrInv0, corrInv1; + std::vector corrInvX0, corrInvX1; + + sector.reserve(npoints); + row.reserve(npoints); + y.reserve(npoints); + z.reserve(npoints); + corr0.resize(npoints); + corr1.resize(npoints); + corrInv0.resize(npoints); + corrInv1.resize(npoints); + corrInvX0.resize(npoints); + corrInvX1.resize(npoints); + + for (int i = 0; i < npoints; i++) { + sector.push_back(gRandom->Integer(NSECTORS)); + row.push_back(gRandom->Integer(NROWS)); + y.push_back(2 * (gRandom->Rndm() - 0.5) * mGeo.getRowInfo(row.back()).getYmax()); + z.push_back((sector.back() < NSECTORS / 2 ? 1.f : -1.f) * gRandom->Rndm() * 240); + } + long origStart[3], origEnd[3], thisStart[3], thisEnd[3]; + origStart[0] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corr0.push_back(origCorr.getCorrectionLocal(sector[i], row[i], y[i], z[i])); + } + + origEnd[0] = origStart[1] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corrInv0.push_back(origCorr.getCorrectionYZatRealYZ(sector[i], row[i], y[i], z[i])); + } + + origEnd[1] = origStart[2] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corrInvX0.push_back(origCorr.getCorrectionXatRealYZ(sector[i], row[i], y[i], z[i])); + } + // + origEnd[2] = thisStart[0] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corr1.push_back(this->getCorrectionLocal(sector[i], row[i], y[i], z[i])); + } + thisEnd[0] = thisStart[1] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corrInv1.push_back(this->getCorrectionYZatRealYZ(sector[i], row[i], y[i], z[i])); + } + + thisEnd[1] = thisStart[2] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + for (int i = 0; i < npoints; i++) { + corrInvX1.push_back(this->getCorrectionXatRealYZ(sector[i], row[i], y[i], z[i])); + } + thisEnd[2] = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + // + size_t ndiff[3] = {}; + for (int i = 0; i < npoints; i++) { + if (corr0[i][0] != corr1[i][0] || corr0[i][1] != corr1[i][1] || corr0[i][2] != corr1[i][2]) { + ndiff[0]++; + } + if (corrInv0[i][0] != corrInv1[i][0] || corrInv0[i][1] != corrInv1[i][1]) { + ndiff[1]++; + } + if (corrInvX0[i] != corrInvX1[i]) { + ndiff[2]++; + } + } + // + LOGP(info, " (ns per call) original this Nmissmatch"); + LOGP(info, "getCorrection {:.3e} {:.3e} {}", double(origEnd[0] - origStart[0]) / npoints * 1000., double(thisEnd[0] - thisStart[0]) / npoints * 1000., ndiff[0]); + LOGP(info, "getCorrectionInvCorrectedX {:.3e} {:.3e} {}", double(origEnd[1] - origStart[1]) / npoints * 1000., double(thisEnd[1] - thisStart[1]) / npoints * 1000., ndiff[1]); + LOGP(info, "getCorrectionInvUV {:.3e} {:.3e} {}", double(origEnd[2] - origStart[2]) / npoints * 1000., double(thisEnd[2] - thisStart[2]) / npoints * 1000., ndiff[2]); + return ndiff[0] == 0 && ndiff[1] == 0 && ndiff[2] == 0; +} + +#endif + +} // namespace gpu +} // namespace o2 diff --git a/GPU/TPCFastTransformation/TPCFastTransformPOD.h b/GPU/TPCFastTransformation/TPCFastTransformPOD.h new file mode 100644 index 0000000000000..0d06a13d0a83c --- /dev/null +++ b/GPU/TPCFastTransformation/TPCFastTransformPOD.h @@ -0,0 +1,920 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file TPCFastTransformPOD.h +/// \brief POD correction map +/// +/// \author ruben.shahoayn@cern.ch + +#ifndef ALICEO2_GPU_TPCFastTransformPOD_H +#define ALICEO2_GPU_TPCFastTransformPOD_H + +#include "TPCFastTransform.h" + +/* +Binary buffer should be cast to TPCFastTransformPOD class using static TPCFastTransformPOD& t = get(buffer); method, +so that its head becomes `this` pointer of the object. + +First we have all the fixed size data members mentioned explicitly. Part of them is duplicating fixed size +data members of TPCFastSpaceChargeCorrection but those starting with mOffs... provide the offset in bytes +(wrt this) for dynamic data which cannot be declared as data member explicitly (since we cannot have any +pointer except `this`) but obtained via getters using stored offsets wrt `this`. +This is followed dynamic part itself. + +dynamic part layout: +1) size_t[ mNumberOfScenarios ] array starting at offset mOffsScenariosOffsets, each element is the offset +of distict spline object (scenario in TPCFastSpaceChargeCorrection) +2) size_t[ mNSplineIDs ] array starting at offset mOffsSplineDataOffsets, each element is the offset of the +beginning of splines data for give splineID + +*/ + +namespace o2 +{ +namespace gpu +{ +class TPCFastTransformPOD +{ + public: + using SliceInfo = TPCFastSpaceChargeCorrection::SliceInfo; // obsolete + using GridInfo = TPCFastSpaceChargeCorrection::GridInfo; + using SectorRowInfo = TPCFastSpaceChargeCorrection::SectorRowInfo; + + using SplineTypeXYZ = TPCFastSpaceChargeCorrection::SplineTypeXYZ; + using SplineTypeInvX = TPCFastSpaceChargeCorrection::SplineTypeInvX; + using SplineTypeInvYZ = TPCFastSpaceChargeCorrection::SplineTypeInvYZ; + using SplineType = TPCFastSpaceChargeCorrection::SplineType; + + /// convert prefilled buffer to TPCFastTransformPOD + GPUd() static const TPCFastTransformPOD& get(const char* head) { return *reinterpret_cast(head); } + + /// _______________ high level methods a la TPCFastTransform _______________________ + /// + // Methods taking extra reference transform are legacy compound transforms used to scale corrections. + GPUd() void Transform(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0, const TPCFastTransformPOD* ref = nullptr, const TPCFastTransformPOD* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void TransformXYZ(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransformPOD* ref = nullptr, const TPCFastTransformPOD* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + + GPUd() void Transform_new(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime = 0) const; + GPUd() void TransformXYZ_new(int32_t sector, int32_t row, float& x, float& y, float& z) const; + + /// Transformation in the time frame + GPUd() void TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const; + GPUd() void TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const; + + /// Inverse transformation + GPUd() void InverseTransformInTimeFrame(int32_t sector, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const; + GPUd() float InverseTransformInTimeFrame(int32_t sector, float z, float maxTimeBin) const; + + /// Inverse transformation: Transformed Y and Z -> transformed X + GPUd() void InverseTransformYZtoX(int32_t sector, int32_t row, float y, float z, float& x, const TPCFastTransformPOD* ref = nullptr, const TPCFastTransformPOD* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoX_new(int32_t sector, int32_t row, float y, float z, float& x) const; + + /// Inverse transformation: Transformed Y and Z -> Y and Z, transformed w/o space charge correction + GPUd() void InverseTransformYZtoNominalYZ(int32_t sector, int32_t row, float y, float z, float& ny, float& nz, const TPCFastTransformPOD* ref = nullptr, const TPCFastTransformPOD* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformYZtoNominalYZ_new(int32_t sector, int32_t row, float y, float z, float& ny, float& nz) const; + + /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction + GPUd() void InverseTransformXYZtoNominalXYZ(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransformPOD* ref = nullptr, const TPCFastTransformPOD* ref2 = nullptr, float scale = 0.f, float scale2 = 0.f, int32_t scaleMode = 0) const; + GPUd() void InverseTransformXYZtoNominalXYZ_new(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz) const; + + /// Ideal transformation with Vdrift only - without calibration + GPUd() void TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const; + GPUd() void TransformIdealZ(int32_t sector, float time, float& z, float vertexTime) const; + + GPUd() void convPadTimeToLocal(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float vertexTime) const; + GPUd() void convPadTimeToLocalInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& y, float& z, float maxTimeBin) const; + + GPUd() void convLocalToPadTime(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float vertexTime) const; + GPUd() void convLocalToPadTimeInTimeFrame(int32_t sector, int32_t row, float y, float z, float& pad, float& time, float maxTimeBin) const; + + GPUd() float convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const; + GPUd() float convZtoTimeInTimeFrame(int32_t sector, float z, float maxTimeBin) const; + GPUd() float convDeltaTimeToDeltaZinTimeFrame(int32_t sector, float deltaTime) const; + GPUd() float convDeltaZtoDeltaTimeInTimeFrame(int32_t sector, float deltaZ) const; + GPUd() float convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const; + GPUd() float convZOffsetToVertexTime(int32_t sector, float zOffset, float maxTimeBin) const; + GPUd() float convVertexTimeToZOffset(int32_t sector, float vertexTime, float maxTimeBin) const; + + /// _______________ methods a la TPCFastSpaceChargeCorrection: cluster correction _______________________ + void setApplyCorrectionOn() { mApplyCorrection = 1; } + void setApplyCorrectionOff() { mApplyCorrection = 0; } + bool isCorrectionApplied() { return mApplyCorrection; } + + /// TPC geometry information + GPUd() const TPCFastTransformGeo& getGeometry() const { return mGeo; } + + /// Gives TPC sector & row info + GPUd() const SectorRowInfo& getSectorRowInfo(int32_t sector, int32_t row) const { return mSectorRowInfos[NROWS * sector + row]; } + + /// Gives TPC sector & row info + GPUd() SectorRowInfo& getSectorRowInfo(int32_t sector, int32_t row) { return mSectorRowInfos[NROWS * sector + row]; } + + /// Gives its own size including dynamic part + GPUd() size_t size() const { return mTotalSize; } + + /// Gives the time stamp of the current calibaration parameters + GPUd() long int getTimeStamp() const { return mTimeStamp; } + + /// Return mVDrift in cm / time bin + GPUd() float getVDrift() const { return mVdrift; } + + /// Return T0 in time bin units + GPUd() float getT0() const { return mT0; } + + /// Return IDC estimator + GPUd() float getIDC() const { return mIDC; } + + /// Return Lumi estimator + GPUd() float getLumi() const { return mLumi; } + + /// maximal possible drift time of the active area + GPUd() float getMaxDriftTime(int32_t sector, int32_t row, float pad) const; + + /// maximal possible drift time of the active area + GPUd() float getMaxDriftTime(int32_t sector, int32_t row) const; + + /// maximal possible drift time of the active area + GPUd() float getMaxDriftTime(int32_t sector) const; + + /// Sets the time stamp of the current calibaration + GPUd() void setTimeStamp(long int v) { mTimeStamp = v; } + + /// Sets current vdrift + GPUd() void setVDrift(float v) { mVdrift = v; } + + /// Sets current T0 + GPUd() void setT0(float v) { mT0 = v; } + + /// Sets IDC estimator + GPUd() void setIDC(float v) { mIDC = v; } + + /// Sets CTP Lumi estimator + GPUd() void setLumi(float v) { mLumi = v; } + + /// Gives a reference to a spline + GPUd() const SplineType& getSpline(int32_t sector, int32_t row) const { return *reinterpret_cast(getThis() + getScenarioOffset(getSectorRowInfo(sector, row).splineScenarioID)); } + + /// Gives pointer to spline data + GPUd() const float* getCorrectionData(int32_t sector, int32_t row, int32_t iSpline = 0) const { return reinterpret_cast(getThis() + mSplineDataOffsets[sector][iSpline] + getSectorRowInfo(sector, row).dataOffsetBytes[iSpline]); } + + /// Gives const pointer to a spline for the inverse X correction + GPUd() const SplineTypeInvX& getSplineInvX(int32_t sector, int32_t row) const { return reinterpret_cast(getSpline(sector, row)); } + + /// Gives pointer to spline data for the inverse X correction + GPUd() const float* getCorrectionDataInvX(int32_t sector, int32_t row) const { return getCorrectionData(sector, row, 1); } + + /// Gives const pointer to a spline for the inverse YZ correction + GPUd() const SplineTypeInvYZ& getSplineInvYZ(int32_t sector, int32_t row) const { return reinterpret_cast(getSpline(sector, row)); } + + /// Gives pointer to spline data for the inverse YZ correction + GPUd() const float* getCorrectionDataInvYZ(int32_t sector, int32_t row) const { return getCorrectionData(sector, row, 2); } + + /// _______________ The main method: cluster correction _______________________ + GPUdi() std::array getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const; + + /// inverse correction: Real Y and Z -> Real X + GPUd() float getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; + + /// inverse correction: Real Y and Z -> measred Y and Z + GPUd() std::array getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const; + + /// transformation in the sector local frame + GPUd() void TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const; + GPUd() void TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z) const; + + /// _______________ Utilities _______________________________________________ + + /// convert local y, z to internal grid coordinates u,v + /// return values: u, v, scaling factor + GPUd() std::array convLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + + /// convert internal grid coordinates u,v to local y, z + /// return values: y, z, scaling factor + GPUd() std::array convGridToLocal(int32_t sector, int32_t row, float u, float v) const; + + /// convert real Y, Z to the internal grid coordinates + /// return values: u, v, scaling factor + GPUd() std::array convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const; + + /// convert internal grid coordinates to the real Y, Z + /// return values: y, z + GPUd() std::array convGridToRealLocal(int32_t sector, int32_t row, float u, float v) const; + + GPUd() bool isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; + GPUd() bool isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const; + +#if !defined(GPUCA_GPUCODE) + /// Create POD transform from old flat-buffer one. Provided vector will serve as a buffer + template + static TPCFastTransformPOD* create(V& destVector, const TPCFastTransform& src); + + /// create filling only part corresponding to TPCFastSpaceChargeCorrection. Data members coming from TPCFastTransform (e.g. VDrift, T0..) are not set + template + static TPCFastTransformPOD* create(V& destVector, const TPCFastSpaceChargeCorrection& src); + + bool test(const TPCFastTransform& src, int32_t npoints = 100000) const { return test(src.getCorrection(), npoints); } + bool test(const TPCFastSpaceChargeCorrection& origCorr, int32_t npoints = 100000) const; +#endif + + /// Print method + void print() const; + + GPUd() float convDriftLengthToTime(float driftLength, float vertexTime) const; + + static constexpr int NROWS = 152; + static constexpr int NSECTORS = TPCFastTransformGeo::getNumberOfSectors(); + static constexpr int NSplineIDs = 3; ///< number of spline data sets for each sector/row + + private: +#if !defined(GPUCA_GPUCODE) + static constexpr size_t AlignmentBytes = 8; + static size_t alignOffset(size_t offs) + { + auto res = offs % AlignmentBytes; + return res ? offs + (AlignmentBytes - res) : offs; + } + static size_t estimateSize(const TPCFastTransform& src) { return estimateSize(src.getCorrection()); } + static size_t estimateSize(const TPCFastSpaceChargeCorrection& origCorr); + static TPCFastTransformPOD* create(char* buff, size_t buffSize, const TPCFastTransform& src); + static TPCFastTransformPOD* create(char* buff, size_t buffSize, const TPCFastSpaceChargeCorrection& src); + ///< get address to which the offset in bytes must be added to arrive to particular dynamic part + GPUd() const char* getThis() const { return reinterpret_cast(this); } + GPUd() static TPCFastTransformPOD& getNonConst(char* head) { return *reinterpret_cast(head); } +#endif + + ///< return offset of the spline object start (equivalent of mScenarioPtr in the TPCFastSpaceChargeCorrection) + GPUd() const size_t getScenarioOffset(int s) const { return (reinterpret_cast(getThis() + mOffsScenariosOffsets))[s]; } + + bool mApplyCorrection{}; ///< flag to apply corrections + int mNumberOfScenarios{}; ///< Number of approximation spline scenarios + size_t mTotalSize{}; ///< total size of the buffer + size_t mOffsScenariosOffsets{}; ///< start of the array of mNumberOfScenarios offsets for each type of spline + size_t mSplineDataOffsets[TPCFastTransformGeo::getNumberOfSectors()][NSplineIDs]; ///< start of data for each sector and iSpline data + long int mTimeStamp{}; ///< time stamp of the current calibration + float mT0; ///< T0 in [time bin] + float mVdrift; ///< VDrift in [cm/time bin] + float mLumi; ///< luminosity estimator (for info only) + float mIDC; ///< IDC estimator (for info only) + + TPCFastTransformGeo mGeo; ///< TPC geometry information + SectorRowInfo mSectorRowInfos[NROWS * TPCFastTransformGeo::getNumberOfSectors()]; + + ClassDefNV(TPCFastTransformPOD, 0); +}; + +GPUdi() std::array TPCFastTransformPOD::getCorrectionLocal(int32_t sector, int32_t row, float y, float z) const +{ + const auto& info = getSectorRowInfo(sector, row); + const SplineType& spline = getSpline(sector, row); + const float* splineData = getCorrectionData(sector, row); + + auto val = convLocalToGrid(sector, row, y, z); + + float dxyz[3]; + spline.interpolateAtU(splineData, val[0], val[1], dxyz); + + if (CAMath::Abs(dxyz[0]) > 100.f || CAMath::Abs(dxyz[1]) > 100.f || CAMath::Abs(dxyz[2]) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } + + float dx = val[2] * GPUCommonMath::Clamp(dxyz[0], info.minCorr[0], info.maxCorr[0]); + float dy = val[2] * GPUCommonMath::Clamp(dxyz[1], info.minCorr[1], info.maxCorr[1]); + float dz = val[2] * GPUCommonMath::Clamp(dxyz[2], info.minCorr[2], info.maxCorr[2]); + + return {dx, dy, dz}; +} + +GPUdi() float TPCFastTransformPOD::getCorrectionXatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const +{ + const auto& info = getSectorRowInfo(sector, row); + auto val = convRealLocalToGrid(sector, row, realY, realZ); + float dx = 0; + getSplineInvX(sector, row).interpolateAtU(getCorrectionDataInvX(sector, row), val[0], val[1], &dx); + if (CAMath::Abs(dx) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } + dx = val[2] * GPUCommonMath::Clamp(dx, info.minCorr[0], info.maxCorr[0]); + return dx; +} + +GPUdi() std::array TPCFastTransformPOD::getCorrectionYZatRealYZ(int32_t sector, int32_t row, float realY, float realZ) const +{ + auto val = convRealLocalToGrid(sector, row, realY, realZ); + const auto& info = getSectorRowInfo(sector, row); + float dyz[2]; + getSplineInvYZ(sector, row).interpolateAtU(getCorrectionDataInvYZ(sector, row), val[0], val[1], dyz); + if (CAMath::Abs(dyz[0]) > 100.f || CAMath::Abs(dyz[1]) > 100.f) { + val[2] = 0.f; // TODO: DR: Protect from FPEs, fix upstream and remove once guaranteed that it is fixed + } + dyz[0] = val[2] * GPUCommonMath::Clamp(dyz[0], info.minCorr[1], info.maxCorr[1]); + dyz[1] = val[2] * GPUCommonMath::Clamp(dyz[1], info.minCorr[2], info.maxCorr[2]); + return {dyz[0], dyz[1]}; +} + +GPUdi() std::array TPCFastTransformPOD::convLocalToGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// convert local y, z to internal grid coordinates u,v + /// return values: u, v, scaling factor + const SplineType& spline = getSpline(sector, row); + auto val = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); + // shrink to the grid + val[0] = GPUCommonMath::Clamp(val[0], 0.f, (float)spline.getGridX1().getUmax()); + val[1] = GPUCommonMath::Clamp(val[1], 0.f, (float)spline.getGridX2().getUmax()); + return val; +} + +GPUdi() std::array TPCFastTransformPOD::convGridToLocal(int32_t sector, int32_t row, float gridU, float gridV) const +{ + /// convert internal grid coordinates u,v to local y, z + return getSectorRowInfo(sector, row).gridMeasured.convGridToLocal(gridU, gridV); +} + +GPUdi() std::array TPCFastTransformPOD::convRealLocalToGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// convert real y, z to the internal grid coordinates + scale + const SplineType& spline = getSpline(sector, row); + auto val = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + // shrink to the grid + val[0] = GPUCommonMath::Clamp(val[0], 0.f, (float)spline.getGridX1().getUmax()); + val[1] = GPUCommonMath::Clamp(val[1], 0.f, (float)spline.getGridX2().getUmax()); + return val; +} + +GPUdi() std::array TPCFastTransformPOD::convGridToRealLocal(int32_t sector, int32_t row, float gridU, float gridV) const +{ + /// convert internal grid coordinates u,v to the real y, z + return getSectorRowInfo(sector, row).gridReal.convGridToLocal(gridU, gridV); +} + +GPUdi() bool TPCFastTransformPOD::isLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// check if local y, z are inside the grid + auto val = getSectorRowInfo(sector, row).gridMeasured.convLocalToGridUntruncated(y, z); + const auto& spline = getSpline(sector, row); + // shrink to the grid + if (val[0] < 0.f || val[0] > (float)spline.getGridX1().getUmax() || // + val[1] < 0.f || val[1] > (float)spline.getGridX2().getUmax()) { + return false; + } + return true; +} + +GPUdi() bool TPCFastTransformPOD::isRealLocalInsideGrid(int32_t sector, int32_t row, float y, float z) const +{ + /// check if local y, z are inside the grid + auto val = getSectorRowInfo(sector, row).gridReal.convLocalToGridUntruncated(y, z); + const auto& spline = getSpline(sector, row); + // shrink to the grid + if (val[0] < 0.f || val[0] > (float)spline.getGridX1().getUmax() || // + val[1] < 0.f || val[1] > (float)spline.getGridX2().getUmax()) { + return false; + } + return true; +} + +#if !defined(GPUCA_GPUCODE) +/// Create POD transform from old flat-buffer one. Provided vector will serve as a buffer +template +TPCFastTransformPOD* TPCFastTransformPOD::create(V& destVector, const TPCFastTransform& src) +{ + const auto& origCorr = src.getCorrection(); + size_t estSize = estimateSize(src); + destVector.resize(estSize); // allocate exact size + LOGP(debug, "OrigCorrSize:{} SelfSize: {} Estimated POS size: {}", src.getCorrection().getFlatBufferSize(), sizeof(TPCFastTransformPOD), estSize); + char* base = destVector.data(); + auto res = create(destVector.data(), destVector.size(), src); + res->setTimeStamp(src.getTimeStamp()); + res->setVDrift(src.getVDrift()); + res->setT0(src.getT0()); + res->setLumi(src.getLumi()); + res->setIDC(src.getIDC()); + return res; +} + +template +TPCFastTransformPOD* TPCFastTransformPOD::create(V& destVector, const TPCFastSpaceChargeCorrection& origCorr) +{ + // create filling only part corresponding to TPCFastSpaceChargeCorrection. Data members coming from TPCFastTransform (e.g. VDrift, T0..) are not set + size_t estSize = estimateSize(origCorr); + destVector.resize(estSize); // allocate exact size + LOGP(debug, "OrigCorrSize:{} SelfSize: {} Estimated POS size: {}", origCorr.getFlatBufferSize(), sizeof(TPCFastTransformPOD), estSize); + char* base = destVector.data(); + return create(destVector.data(), destVector.size(), origCorr); +} +#endif + +GPUdi() void TPCFastTransformPOD::TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); + + if (!mApplyCorrection) { + return; + } + + float dx = 0.f, dy = 0.f, dz = 0.f; + + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { + const auto corrLocal = getCorrectionLocal(sector, row, y, z); + dx = corrLocal[0]; + dy = corrLocal[1]; + dz = corrLocal[2]; + if (ref) { + if ((scale > 0.f) && (scaleMode == 0)) { // scaling was requested + auto val = ref->getCorrectionLocal(sector, row, y, z); + dx = (dx - val[0]) * scale + val[0]; + dy = (dy - val[1]) * scale + val[1]; + dz = (dz - val[2]) * scale + val[2]; + } else if ((scale != 0.f) && ((scaleMode == 1) || (scaleMode == 2))) { + auto val = ref->getCorrectionLocal(sector, row, y, z); + dx = val[0] * scale + dx; + dy = val[1] * scale + dy; + dz = val[2] * scale + dz; + } + } + if (ref2 && (scale2 != 0)) { + auto val = ref2->getCorrectionLocal(sector, row, y, z); + dx = val[0] * scale2 + dx; + dy = val[1] * scale2 + dy; + dz = val[2] * scale2 + dz; + } + } + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + float lx = x, ly = y, lz = z; + + float gx, gy, gz; + getGeometry().convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); + + float lxT = lx + dx; + float lyT = ly + dy; + float lzT = lz + dz; + + float invYZtoXScaled; + InverseTransformYZtoX(sector, row, lyT, lzT, invYZtoXScaled, ref, ref2, scale, scale2, scaleMode); + + float invYZtoX; + InverseTransformYZtoX(sector, row, lyT, lzT, invYZtoX); + + float YZtoNominalY; + float YZtoNominalZ; + InverseTransformYZtoNominalYZ(sector, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); + + float YZtoNominalYScaled; + float YZtoNominalZScaled; + InverseTransformYZtoNominalYZ(sector, row, lyT, lzT, YZtoNominalYScaled, YZtoNominalZScaled, ref, ref2, scale, scale2, scaleMode); + + float dxRef = 0.f, dyRef = 0.f, dzRef = 0.f; + if (ref) { + const auto corr = ref->getCorrectionLocal(sector, row, y, z); + dxRef = corr[0]; + dyRef = corr[1]; + dzRef = corr[2]; + } + + float dxRef2 = 0.f, dyRef2 = 0.f, dzRef2 = 0.f; + if (ref2) { + const auto corr = ref2->getCorrectionLocal(sector, row, y, z); + dxRef2 = corr[0]; + dyRef2 = corr[1]; + dzRef2 = corr[2]; + } + + auto [dxOrig, dyOrig, dzOrig] = getCorrectionLocal(sector, row, y, z); + + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() + // corrections in x, u, v + << "dxOrig=" << dxOrig + << "dyOrig=" << dyOrig + << "dzOrig=" << dzOrig + << "dxRef=" << dxRef + << "dyRef=" << dyRef + << "dzRef=" << dzRef + << "dxRef2=" << dxRef2 + << "dyRef2=" << dyRef2 + << "dzRef2=" << dzRef2 + << "dx=" << dx + << "dy=" << dy + << "dz=" << dz + << "row=" << row + << "sector=" << sector + << "scale=" << scale + << "scale2=" << scale2 + // original local coordinates + << "ly=" << ly + << "lz=" << lz + << "lx=" << lx + // corrected local coordinated + << "lxT=" << lxT + << "lyT=" << lyT + << "lzT=" << lzT + // global uncorrected coordinates + << "gx=" << gx + << "gy=" << gy + << "gz=" << gz + // some transformations which are applied + << "invYZtoX=" << invYZtoX + << "invYZtoXScaled=" << invYZtoXScaled + << "YZtoNominalY=" << YZtoNominalY + << "YZtoNominalYScaled=" << YZtoNominalYScaled + << "YZtoNominalZ=" << YZtoNominalZ + << "YZtoNominalZScaled=" << YZtoNominalZScaled + << "scaleMode=" << scaleMode + << "\n"; + }) + + x += dx; + y += dy; + z += dz; +} + +GPUdi() void TPCFastTransformPOD::TransformLocal(int32_t sector, int32_t row, float& x, float& y, float& z) const +{ + if (!mApplyCorrection) { + return; + } + const auto corrLocal = getCorrectionLocal(sector, row, y, z); + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + float lx = x, ly = y, lz = z; + float gx, gy, gz; + getGeometry().convLocalToGlobal(sector, lx, ly, lz, gx, gy, gz); + dx = corrLocal[0]; + dy = corrLocal[1]; + dz = corrLocal[2]; + float lxT = lx + dx; + float lyT = ly + dy; + float lzT = lz + dz; + float invYZtoX; + InverseTransformYZtoX_new(sector, row, lyT, lzT, invYZtoX); + + float YZtoNominalY; + float YZtoNominalZ; + InverseTransformYZtoNominalYZ_new(sector, row, lyT, lzT, YZtoNominalY, YZtoNominalZ); + + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_Transform").data() + // corrections in x, u, v + << "dx=" << dx + << "dy=" << dy + << "dz=" << dz + << "row=" << row + << "sector=" << sector + // original local coordinates + << "ly=" << ly + << "lz=" << lz + << "lx=" << lx + // corrected local coordinated + << "lxT=" << lxT + << "lyT=" << lyT + << "lzT=" << lzT + // global uncorrected coordinates + << "gx=" << gx + << "gy=" << gy + << "gz=" << gz + // some transformations which are applied + << "invYZtoX=" << invYZtoX + << "YZtoNominalY=" << YZtoNominalY + << "YZtoNominalZ=" << YZtoNominalZ + << "\n"; + }) + + x += corrLocal[0]; + y += corrLocal[1]; + z += corrLocal[2]; +} + +GPUdi() void TPCFastTransformPOD::Transform(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + /// _______________ The main method: cluster transformation _______________________ + /// + /// Transforms raw TPC coordinates to local XYZ withing a sector + /// taking calibration into account. + /// + + const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); + + x = rowInfo.x; + convPadTimeToLocal(sector, row, pad, time, y, z, vertexTime); + TransformLocal(sector, row, x, y, z, ref, ref2, scale, scale2, scaleMode); +} + +GPUdi() void TPCFastTransformPOD::Transform_new(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const +{ + /// _______________ The main method: cluster transformation _______________________ + /// + /// Transforms raw TPC coordinates to local XYZ withing a sector + /// taking calibration into account. + /// + + const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); + + x = rowInfo.x; + convPadTimeToLocal(sector, row, pad, time, y, z, vertexTime); + TransformLocal(sector, row, x, y, z); +} + +GPUdi() void TPCFastTransformPOD::TransformXYZ(int32_t sector, int32_t row, float& x, float& y, float& z, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + + TransformLocal(sector, row, x, y, z, ref, ref2, scale, scale2, scaleMode); +} + +GPUdi() void TPCFastTransformPOD::TransformXYZ_new(int32_t sector, int32_t row, float& x, float& y, float& z) const +{ + + TransformLocal(sector, row, x, y, z); +} + +GPUdi() void TPCFastTransformPOD::TransformInTimeFrame(int32_t sector, float time, float& z, float maxTimeBin) const +{ + float l = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm + z = getGeometry().convDriftLengthToZ1(sector, l); +} + +GPUdi() void TPCFastTransformPOD::TransformInTimeFrame(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float maxTimeBin) const +{ + /// _______________ Special cluster transformation for a time frame _______________________ + /// + /// Same as Transform(), but clusters are shifted in z such, that Z(maxTimeBin)==0 + /// Corrections and Time-Of-Flight correction are not alpplied. + /// + + const TPCFastTransformGeo::RowInfo& rowInfo = getGeometry().getRowInfo(row); + x = rowInfo.x; + convPadTimeToLocalInTimeFrame(sector, row, pad, time, y, z, maxTimeBin); +} + +GPUdi() void TPCFastTransformPOD::InverseTransformInTimeFrame(int32_t sector, int32_t row, float /*x*/, float y, float z, float& pad, float& time, float maxTimeBin) const +{ + /// Inverse transformation to TransformInTimeFrame + convLocalToPadTimeInTimeFrame(sector, row, y, z, pad, time, maxTimeBin); +} + +GPUdi() float TPCFastTransformPOD::InverseTransformInTimeFrame(int32_t sector, float z, float maxTimeBin) const +{ + float pad, time; + InverseTransformInTimeFrame(sector, 0, 0, 0, z, pad, time, maxTimeBin); + return time; +} + +GPUdi() void TPCFastTransformPOD::TransformIdealZ(int32_t sector, float time, float& z, float vertexTime) const +{ + /// _______________ The main method: cluster transformation _______________________ + /// + /// Transforms time TPC coordinates to local Z withing a sector + /// Ideal transformation: only Vdrift from DCS. + /// No space charge corrections, no time of flight correction + /// + + float l = (time - mT0 - vertexTime) * mVdrift; // drift length cm + z = getGeometry().convDriftLengthToZ1(sector, l); +} + +GPUdi() void TPCFastTransformPOD::TransformIdeal(int32_t sector, int32_t row, float pad, float time, float& x, float& y, float& z, float vertexTime) const +{ + /// _______________ The main method: cluster transformation _______________________ + /// + /// Transforms raw TPC coordinates to local XYZ withing a sector + /// Ideal transformation: only Vdrift from DCS. + /// No space charge corrections, no time of flight correction + /// + + x = getGeometry().getRowInfo(row).x; + float driftLength = (time - mT0 - vertexTime) * mVdrift; // drift length cm + const auto localval = getGeometry().convPadDriftLengthToLocal(sector, row, pad, driftLength); + y = localval[0]; + z = localval[1]; +} + +GPUdi() float TPCFastTransformPOD::convTimeToZinTimeFrame(int32_t sector, float time, float maxTimeBin) const +{ + /// _______________ Special cluster transformation for a time frame _______________________ + /// + /// Same as Transform(), but clusters are shifted in z such, that Z(maxTimeBin)==0 + /// Corrections and Time-Of-Flight correction are not alpplied. + /// Only Z coordinate. + /// + + float v = (time - mT0 - maxTimeBin) * mVdrift; // drift length cm + float z = (sector < getGeometry().getNumberOfSectorsA()) ? -v : v; + return z; +} + +GPUdi() float TPCFastTransformPOD::convZtoTimeInTimeFrame(int32_t sector, float z, float maxTimeBin) const +{ + /// Inverse transformation of convTimeToZinTimeFrame() + float v = (sector < getGeometry().getNumberOfSectorsA()) ? -z : z; + return mT0 + maxTimeBin + v / mVdrift; +} + +GPUdi() float TPCFastTransformPOD::convDeltaTimeToDeltaZinTimeFrame(int32_t sector, float deltaTime) const +{ + float deltaZ = deltaTime * mVdrift; + return sector < getGeometry().getNumberOfSectorsA() ? -deltaZ : deltaZ; +} + +GPUdi() float TPCFastTransformPOD::convDeltaZtoDeltaTimeInTimeFrameAbs(float deltaZ) const +{ + return deltaZ / mVdrift; +} + +GPUdi() float TPCFastTransformPOD::convDeltaZtoDeltaTimeInTimeFrame(int32_t sector, float deltaZ) const +{ + float deltaT = deltaZ / mVdrift; + return sector < getGeometry().getNumberOfSectorsA() ? -deltaT : deltaT; +} + +GPUdi() float TPCFastTransformPOD::getMaxDriftTime(int32_t sector, int32_t row, float pad) const +{ + /// maximal possible drift time of the active area + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); +} + +GPUdi() float TPCFastTransformPOD::getMaxDriftTime(int32_t sector, int32_t row) const +{ + /// maximal possible drift time of the active area + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); +} + +GPUdi() float TPCFastTransformPOD::getMaxDriftTime(int32_t sector) const +{ + /// maximal possible drift time of the active area + return convDriftLengthToTime(getGeometry().getTPCzLength(), 0.f); +} + +GPUdi() void TPCFastTransformPOD::InverseTransformYZtoX(int32_t sector, int32_t row, float realY, float realZ, float& realX, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); + /// Transformation y,z -> x + + float dx = 0.f; + + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { + dx = getCorrectionXatRealYZ(sector, row, realY, realZ); + if (ref) { // scaling was requested + if (scaleMode == 0 && scale > 0.f) { + float dxref = ref->getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = (dx - dxref) * scale + dxref; + } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { + float dxref = ref->getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = dxref * scale + dx; + } + } + if (ref2 && (scale2 != 0)) { + float dxref = ref2->getCorrectionXatRealYZ(sector, row, realY, realZ); + dx = dxref * scale2 + dx; + } + } + + realX = getGeometry().getRowInfo(row).x + dx; + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoX").data() + << "sector=" << sector + << "row=" << row + << "scale=" << scale + << "y=" << realY + << "z=" << realZ + << "x=" << realX + << "\n"; + }) +} + +GPUdi() void TPCFastTransformPOD::InverseTransformYZtoX_new(int32_t sector, int32_t row, float realY, float realZ, float& realX) const +{ + /// Transformation y,z -> x + + float dx = 0.f; + + dx = getCorrectionXatRealYZ(sector, row, realY, realZ); + realX = getGeometry().getRowInfo(row).x + dx; + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoX").data() + << "sector=" << sector + << "row=" << row + << "y=" << realY + << "z=" << realZ + << "x=" << realX + << "\n"; + }) +} + +GPUdi() void TPCFastTransformPOD::InverseTransformYZtoNominalYZ(int32_t sector, int32_t row, float realY, float realZ, float& measuredY, float& measuredZ, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + /// Transformation real y,z -> measured y,z + + GPUCA_RTC_SPECIAL_CODE(ref2 = nullptr; scale2 = 0.f;); + + float dy = 0; + float dz = 0; + + if ((scale >= 0.f) || (scaleMode == 1) || (scaleMode == 2)) { + const auto corrYZ = getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = corrYZ[0]; + dz = corrYZ[1]; + + if (ref) { // scaling was requested + if (scaleMode == 0 && scale > 0.f) { + const auto val = ref->getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = (dy - val[0]) * scale + val[0]; + dz = (dz - val[1]) * scale + val[1]; + } else if ((scale != 0) && ((scaleMode == 1) || (scaleMode == 2))) { + const auto val = ref->getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = val[0] * scale + dy; + dz = val[1] * scale + dz; + } + if (ref2 && (scale2 != 0)) { + const auto val = ref2->getCorrectionYZatRealYZ(sector, row, realY, realZ); + dy = val[0] * scale2 + dy; + dz = val[1] * scale2 + dz; + } + } + } + + measuredY = realY - dy; + measuredZ = realZ - dz; + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoNominalYZ").data() + << "sector=" << sector + << "row=" << row + << "scale=" << scale + << "real y=" << realY + << "real z=" << realZ + << "measured y=" << measuredY + << "measured z=" << measuredZ + << "\n"; + }) +} + +GPUdi() void TPCFastTransformPOD::InverseTransformYZtoNominalYZ_new(int32_t sector, int32_t row, float realY, float realZ, float& measuredY, float& measuredZ) const +{ + /// Transformation real y,z -> measured y,z + const auto corrYZ = getCorrectionYZatRealYZ(sector, row, realY, realZ); + measuredY = realY - corrYZ[0]; + measuredZ = realZ - corrYZ[1]; + + GPUCA_DEBUG_STREAMER_CHECK(if (o2::utils::DebugStreamer::checkStream(o2::utils::StreamFlags::streamFastTransform)) { + o2::utils::DebugStreamer::instance()->getStreamer("debug_fasttransform", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_InverseTransformYZtoNominalYZ").data() + << "sector=" << sector + << "row=" << row + << "real y=" << realY + << "real z=" << realZ + << "measured y=" << measuredY + << "measured z=" << measuredZ + << "\n"; + }) +} + +GPUdi() void TPCFastTransformPOD::InverseTransformXYZtoNominalXYZ(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz, const TPCFastTransformPOD* ref, const TPCFastTransformPOD* ref2, float scale, float scale2, int32_t scaleMode) const +{ + /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction + int32_t row2 = row + 1; + if (row2 >= getGeometry().getNumberOfRows()) { + row2 = row - 1; + } + float nx1, ny1, nz1; // nominal coordinates for row + float nx2, ny2, nz2; // nominal coordinates for row2 + nx1 = getGeometry().getRowInfo(row).x; + nx2 = getGeometry().getRowInfo(row2).x; + InverseTransformYZtoNominalYZ(sector, row, y, z, ny1, nz1, ref, ref2, scale, scale2, scaleMode); + InverseTransformYZtoNominalYZ(sector, row2, y, z, ny2, nz2, ref, ref2, scale, scale2, scaleMode); + float c1 = (nx2 - nx) / (nx2 - nx1); + float c2 = (nx - nx1) / (nx2 - nx1); + nx = x; + ny = (ny1 * c1 + ny2 * c2); + nz = (nz1 * c1 + nz2 * c2); +} + +GPUdi() void TPCFastTransformPOD::InverseTransformXYZtoNominalXYZ_new(int32_t sector, int32_t row, float x, float y, float z, float& nx, float& ny, float& nz) const +{ + /// Inverse transformation: Transformed X, Y and Z -> X, Y and Z, transformed w/o space charge correction + int32_t row2 = row + 1; + if (row2 >= getGeometry().getNumberOfRows()) { + row2 = row - 1; + } + float nx1, ny1, nz1; // nominal coordinates for row + float nx2, ny2, nz2; // nominal coordinates for row2 + nx1 = getGeometry().getRowInfo(row).x; + nx2 = getGeometry().getRowInfo(row2).x; + InverseTransformYZtoNominalYZ_new(sector, row, y, z, ny1, nz1); + InverseTransformYZtoNominalYZ_new(sector, row2, y, z, ny2, nz2); + float c1 = (nx2 - nx) / (nx2 - nx1); + float c2 = (nx - nx1) / (nx2 - nx1); + nx = x; + ny = (ny1 * c1 + ny2 * c2); + nz = (nz1 * c1 + nz2 * c2); +} + +} // namespace gpu +} // namespace o2 + +#endif diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index f1872549a46aa..0247bbbfbb65b 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -93,5 +93,6 @@ #pragma link C++ struct o2::gpu::MultivariatePolynomialContainer + ; #pragma link C++ struct o2::gpu::NDPiecewisePolynomialContainer + ; #pragma link C++ struct o2::gpu::TPCSlowSpaceChargeCorrection + ; +#pragma link C++ class o2::gpu::TPCFastTransformPOD + ; #endif