From 99541e059c14ae10d9670aeb965c73ed50580c75 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner Date: Tue, 3 Nov 2026 11:01:18 +0100 Subject: [PATCH] TPC SCD: TrackResiduals y/x grid edge from the pad plane The y/x range of the voxel grid was x tan(10 deg) - 1.5 cm (a fixed dead zone) per x bin. It does not follow the pad plane (the number of pads per row grows in steps, the pad width changes per region): relative to the outer side of the row's last pad it ends -0.83 to +0.33 pads off (negative: inside the pad plane), inside in 112 of 152 rows, in 36 of them by more than half a pad (the last pad's centre outside the grid), outside (in the gap to the next sector) in 40. Bins refined at the sector edges therefore covered a different part of the pad plane in each row. Now y/x = +-maxY2X is half the row's pads times its pad width (Mapper), for uniform X-binning the pad row closest to the bin centre. Unit test: the edge in every row. Maps binned with the old definition are to be read with an O2 version from before this change (their trees store bin indices and mean positions, the bin centres come from TrackResiduals). Co-Authored-By: Claude Opus 5.5 --- .../include/SpacePoints/TrackResiduals.h | 3 +-- .../calibration/SpacePoints/src/TrackResiduals.cxx | 12 ++++++++++-- .../SpacePoints/test/testTrackResiduals.cxx | 13 +++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h index c95f3efe5048a..5a997742c17e1 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackResiduals.h @@ -460,7 +460,6 @@ class TrackResiduals // some constants static constexpr float sFloatEps{1.e-7f}; ///< float epsilon for robust linear fitting - static constexpr float sDeadZone{1.5f}; ///< dead zone for TPC in between sectors static constexpr int sSmtLinDim{4}; ///< max matrix size for smoothing (pol1) static constexpr int sMaxSmtDim{7}; ///< max matrix size for smoothing (pol2) @@ -483,7 +482,7 @@ class TrackResiduals int mNVoxPerSector{}; ///< number of voxels per sector float mDX{}; ///< x bin size float mDXI{}; ///< inverse of x bin size - std::vector mMaxY2X{}; ///< max y/x at each x bin, accounting dead zones + std::vector mMaxY2X{}; ///< max y/x at each x bin: the pad plane's edge in its pad row std::vector mDY2X{}; ///< y/x bin size at given x bin std::vector mDY2XI{}; ///< inverse y/x bin size at given x bin std::vector mY2XBinsDH{}; ///< half width in y/x within the interval [-1..1] diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx index eba2974ba6e26..c33668fbcf749 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx @@ -17,6 +17,7 @@ /// #include "SpacePoints/TrackResiduals.h" +#include "TPCBase/Mapper.h" #include "CommonConstants/MathConstants.h" #include "ReconstructionDataFormats/Track.h" #include "MathUtils/fit.h" @@ -164,14 +165,21 @@ void TrackResiduals::initBinning() mDXI = 1.f / mDX; // should not be used } // - // Y/X binning + // Y/X binning: y/x = +-mMaxY2X is the pad plane's edge in the pad row of the x bin (the outer edge of its outermost pads; with uniform + // X-binning the pad row closest to the bin centre), so the outermost y/x bins end with the row's last pads mMaxY2X.resize(mNXBins); mDY2XI.resize(mNXBins); mDY2X.resize(mNXBins); // + const auto& mapper = Mapper::instance(); for (int ix = 0; ix < mNXBins; ++ix) { float x = getX(ix); - mMaxY2X[ix] = tan(.5f * SECPHIWIDTH) - sDeadZone / x; + int row = ix; + if (mUniformBins[VoxX]) { + row = int(std::min_element(param::RowX, param::RowX + param::NPadRows, [x](float a, float b) { return std::abs(a - x) < std::abs(b - x); }) - param::RowX); + } + const float halfWidth = 0.5f * mapper.getNumberOfPadsInRowSector(row) * mapper.getPadRegionInfo(Mapper::REGION[row]).getPadWidth(); + mMaxY2X[ix] = halfWidth / x; mDY2XI[ix] = mNY2XBins / (2.f * mMaxY2X[ix]); mDY2X[ix] = 1.f / mDY2XI[ix]; } diff --git a/Detectors/TPC/calibration/SpacePoints/test/testTrackResiduals.cxx b/Detectors/TPC/calibration/SpacePoints/test/testTrackResiduals.cxx index a5105329f8eb6..2b399bf5529a7 100644 --- a/Detectors/TPC/calibration/SpacePoints/test/testTrackResiduals.cxx +++ b/Detectors/TPC/calibration/SpacePoints/test/testTrackResiduals.cxx @@ -19,6 +19,7 @@ #define BOOST_TEST_DYN_LINK #include #include "SpacePoints/TrackResiduals.h" +#include "TPCBase/Mapper.h" namespace o2::tpc { @@ -58,4 +59,16 @@ BOOST_AUTO_TEST_CASE(TrackResidualsBinning_test) } } +// the y/x grid ends at the pad plane's edge of each pad row +BOOST_AUTO_TEST_CASE(TrackResidualsY2XEdge_test) +{ + TrackResiduals resid; + resid.initBinning(); + const auto& mapper = Mapper::instance(); + for (int ix = 0; ix < resid.getNXBins(); ++ix) { + const float halfWidth = 0.5f * mapper.getNumberOfPadsInRowSector(ix) * mapper.getPadRegionInfo(Mapper::REGION[ix]).getPadWidth(); + BOOST_CHECK_CLOSE(resid.getMaxY2X(ix) * resid.getX(ix), halfWidth, 1e-3); + } +} + } // namespace o2::tpc