Skip to content

Commit 8ae4f15

Browse files
TPC SCD: add keepClustersOnPropFail to keep tracks whose reference propagation fails
TrackInterpolation drops the whole track when the propagation of the reference track to a TPC pad row (or to the TRD/TOF anchor) fails, e.g. at scdcalib.maxSnp. That propagation follows the ITS-predicted direction, so the drop selects tracks by the reference's own curvature error and biases the residuals of the surviving sample at low pt. With scdcalib.keepClustersOnPropFail=true the track is kept. TPC clusters without a reference are stored position-only: y, z = cluster position, dy = dz = 0, tgSlp = UnbinnedResid::TgSlpPositionOnly (-0x8000, which the tgSlp packing never produces; UnbinnedResid::isPositionOnly()). extrapolateTrack: all clusters after the failure. interpolateTrack: a row keeps its residual only if both the outward and the inward propagation reached it; a failure of the outer TRD/TOF anchor makes all TPC clusters position-only and suppresses the TRD/TOF residuals. Position-only clusters are excluded from validateTrack and stored in row order. The ITS and PV residuals are unaffected. ResidualsContainer::fill, staticMapCreator.C and TPCResidualReaderSpec skip position-only (and tgSlp-clamped) residuals for the binned voxel fit. Default false: output unchanged (verified on one MC TF, all fields identical). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 0db6a66 commit 8ae4f15

6 files changed

Lines changed: 144 additions & 69 deletions

File tree

‎Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCResidualReaderSpec.cxx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ void TPCResidualReader::run(ProcessingContext& pc)
189189
}
190190
for (int i = trkInfo.idxFirstResidual; i < trkInfo.idxFirstResidual + trkInfo.nResiduals; ++i) {
191191
const auto& residIn = mUnbinnedResiduals[i];
192+
if (residIn.isTgSlpClamped() || residIn.isPositionOnly()) {
193+
continue; // scdcalib.clampTgSlp / keepClustersOnPropFail: tgSlp or dy, dz not usable for the binned voxel fit
194+
}
192195
int sec = residIn.sec;
193196
auto& residVecOut = mResidualsSector[sec];
194197
auto& statVecOut = mVoxStatsSector[sec];

‎Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct SpacePointsCalibConfParam : public o2::conf::ConfigurableParamHelper<Spac
4949
float sigYZ2TOF{.75f}; ///< for now assume cluster error for TOF equal for all clusters in both Y and Z
5050
float maxSnp{.85f}; ///< max snp when propagating tracks
5151
bool clampTgSlp{false}; ///< store TPC cluster residuals with |tan(phi)| >= param::MaxTgSlp saturated (tgSlp = +-0x7fff, see UnbinnedResid::isTgSlpClamped) instead of dropping them: the cut is on the reference track's direction, so dropping selects on the reference's error
52+
bool keepClustersOnPropFail{false}; ///< if the reference track propagation fails (maxSnp, rotation), keep the track: TPC clusters without a reference are stored position-only (y, z = cluster; dy = dz = 0; tgSlp = UnbinnedResid::TgSlpPositionOnly) instead of dropping the whole track, which selects on the reference's error
5253
float maxStep{2.f}; ///< maximum step for propagation
5354
bool debugTRDTOF{false}; ///< if true, ITS-TPC-TRD-TOF tracks and their seeding ITS-TPC-TRD track will both be interpolated and their residuals stored
5455

‎Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ struct UnbinnedResid {
9797

9898
/// true if tgSlp was saturated at +-param::MaxTgSlp (scdcalib.clampTgSlp): unclamped values have |tgSlp| <= 0x7fff - 1
9999
bool isTgSlpClamped() const { return tgSlp == 0x7fff || tgSlp == -0x7fff; }
100+
/// tgSlp marker of a position-only TPC cluster (scdcalib.keepClustersOnPropFail): no reference track at this cluster,
101+
/// y and z are the cluster position, dy = dz = 0. Not reachable by the tgSlp packing (|tgSlp| <= 0x7fff)
102+
static constexpr short TgSlpPositionOnly = -0x8000;
103+
bool isPositionOnly() const { return tgSlp == TgSlpPositionOnly; }
100104
bool isTPC() const { return row < constants::MAXGLOBALPADROW; }
101105
bool isTRD() const { return row >= 160 && row < 166; }
102106
bool isTOF() const { return row == 170; }
@@ -500,6 +504,8 @@ class TrackInterpolation
500504
size_t mNRejRefit = 0;
501505
size_t mNRejProp = 0;
502506
size_t mNRejLoop = 0;
507+
size_t mNPosOnlyTracks = 0; ///< tracks kept with position-only clusters after a propagation failure (keepClustersOnPropFail)
508+
size_t mNPosOnlyClusters = 0; ///< position-only TPC clusters stored (keepClustersOnPropFail)
503509

504510
ClassDefNV(TrackInterpolation, 1);
505511
};

‎Detectors/TPC/calibration/SpacePoints/macro/staticMapCreator.C‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,9 @@ void staticMapCreator(std::string fileInput = "files.txt",
320320
if (useResidualsForVd && residualsVd.size() < 10'000'000UL) {
321321
residualsVd.push_back(residIn);
322322
}
323-
if (residIn.isTgSlpClamped()) {
323+
if (residIn.isTgSlpClamped() || residIn.isPositionOnly()) {
324324
// scdcalib.clampTgSlp: tgSlp saturated -- the voxel fit (dX from dY vs tan(phi)) and the map correction below
325-
// use it, so keep this residual out of the binned residuals
325+
// use it, so keep this residual out of the binned residuals; scdcalib.keepClustersOnPropFail: no reference (dy = dz = 0)
326326
continue;
327327
}
328328
int sec = residIn.sec;

‎Detectors/TPC/calibration/SpacePoints/src/ResidualAggregator.cxx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ void ResidualsContainer::fill(const o2::dataformats::TFIDInfo& ti, const gsl::sp
197197
if (!writeBinnedResid) {
198198
continue;
199199
}
200-
if (residIn.isTgSlpClamped()) {
200+
if (residIn.isTgSlpClamped() || residIn.isPositionOnly()) {
201201
// scdcalib.clampTgSlp: kept in the unbinned output, but its tgSlp is saturated and the voxel fit uses tgSlp (dX from
202-
// dY vs tan(phi)), so it must not enter the binned residuals
202+
// dY vs tan(phi)), so it must not enter the binned residuals; scdcalib.keepClustersOnPropFail: no reference, dy = dz = 0
203203
continue;
204204
}
205205
int sec = residIn.sec;

0 commit comments

Comments
 (0)