Project
Loading...
Searching...
No Matches
TrackHelpers.h
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
15
16#ifndef O2_ITS_TRACKING_TRACKHELPERS_H_
17#define O2_ITS_TRACKING_TRACKHELPERS_H_
18
20#include "ITStracking/Cell.h"
21#include "ITStracking/Cluster.h"
26
28{
29
30// Prefer 1) longer track 2) sorted in chi2
31GPUhdi() bool isBetter(const o2::its::TrackITS& a, const o2::its::TrackITS& b)
32{
33 const auto ncla = a.getNumberOfClusters();
34 const auto nclb = b.getNumberOfClusters();
35 // is a as long as b ? then decide on chi2
36 // otherwise prefer longer
37 return (ncla == nclb) ? (a.getChi2() < b.getChi2()) : ncla > nclb;
38}
39
40// Find the populated interior layer closest to the radial midpoint.
41// If no layer can be found, return constants::UnusedIndex.
42// Should minimize the sagitta bias.
43template <int NLayers>
44GPUdi() int selectReseedMidLayer(int minLayer, int maxLayer, const float* layerRadii, const TrackSeed<NLayers>& seed)
45{
47 float distanceToMidR = layerRadii[NLayers - 1]; // midpoint cannot be last layer
48 const float midR = 0.5f * (layerRadii[maxLayer] + layerRadii[minLayer]);
49 for (int iLayer = minLayer + 1; iLayer < maxLayer; ++iLayer) {
50 if (seed.getCluster(iLayer) != constants::UnusedIndex) {
51 const float distance = o2::gpu::CAMath::Abs(midR - layerRadii[iLayer]);
52 if (distance < distanceToMidR) { // keep the smaller-radius layer on ties
53 midLayer = iLayer;
55 }
56 }
57 }
58 return midLayer;
59}
60
62{
63 track.resetCovariance();
64 track.setCov(track.getQ2Pt() * track.getQ2Pt() * track.getCov()[o2::track::CovLabels::kSigQ2Pt2], o2::track::CovLabels::kSigQ2Pt2);
65}
66
67GPUdi() o2::track::TrackParCov buildTrackSeed(const Cluster& cluster1,
68 const Cluster& cluster2,
69 const TrackingFrameInfo& tf3,
70 const float bz,
71 const bool reverse = false)
72{
74 o2::gpu::CAMath::SinCos(tf3.alphaTrackingFrame, sa, ca);
75 const float sign = reverse ? -1.f : 1.f;
76 const float x1 = (cluster1.xCoordinate * ca) + (cluster1.yCoordinate * sa);
77 const float y1 = (-cluster1.xCoordinate * sa) + (cluster1.yCoordinate * ca);
78 const float x2 = (cluster2.xCoordinate * ca) + (cluster2.yCoordinate * sa);
79 const float y2 = (-cluster2.xCoordinate * sa) + (cluster2.yCoordinate * ca);
80 const float x3 = tf3.xTrackingFrame;
81 const float y3 = tf3.positionTrackingFrame[0];
82 if (o2::gpu::CAMath::Abs(bz) < 0.01f) { // zero field
83 const float dx = x3 - x1;
84 const float dy = y3 - y1;
85 snp = sign * dy / o2::gpu::CAMath::Hypot(dx, dy);
86 q2pt = 1.f / o2::track::kMostProbablePt;
87 q2pt2 = 1.f;
88 } else {
89 const float crv = math_utils::computeCurvature(x3, y3, x2, y2, x1, y1);
90 snp = sign * crv * (x3 - math_utils::computeCurvatureCentreX(x3, y3, x2, y2, x1, y1));
91 q2pt = sign * crv / (bz * o2::constants::math::B2C);
92 q2pt2 = crv * crv;
93 }
94 const float tgl = -0.5f * sign * (math_utils::computeTanDipAngle(x1, y1, x2, y2, cluster1.zCoordinate, cluster2.zCoordinate) + math_utils::computeTanDipAngle(x2, y2, x3, y3, cluster2.zCoordinate, tf3.positionTrackingFrame[1]));
95 const float sg2q2pt = o2::track::kC1Pt2max * o2::gpu::CAMath::Clamp(q2pt2, 0.0005f, 1.0f);
96 return {x3, tf3.alphaTrackingFrame, {y3, tf3.positionTrackingFrame[1], snp, tgl, q2pt}, {tf3.covarianceTrackingFrame[0], tf3.covarianceTrackingFrame[1], tf3.covarianceTrackingFrame[2], 0.f, 0.f, o2::track::kCSnp2max, 0.f, 0.f, 0.f, o2::track::kCTgl2max, 0.f, 0.f, 0.f, 0.f, sg2q2pt}};
97}
98
99template <int NLayers>
100GPUdi() TrackITSExt seedTrackForRefit(const TrackSeed<NLayers>& seed,
103 const float* layerRadii,
104 const float bz,
106{
108 int lrMin = NLayers;
109 int lrMax = 0;
110 for (int iL{0}; iL < NLayers; ++iL) {
111 const int idx = seed.getCluster(iL);
112 temporaryTrack.setExternalClusterIndex(iL, idx, idx != constants::UnusedIndex);
113 if (idx != constants::UnusedIndex) {
114 lrMin = o2::gpu::CAMath::Min(lrMin, iL);
115 lrMax = o2::gpu::CAMath::Max(lrMax, iL);
116 }
117 }
118
119 const int ncl = temporaryTrack.getNClusters();
120 if (ncl < reseedIfShorter && ncl > 2) {
121 const int lrMid = selectReseedMidLayer<NLayers>(lrMin, lrMax, layerRadii, seed);
122 if (lrMid != constants::UnusedIndex) {
123 const auto& cluster0TF = foundTrackingFrameInfo[lrMin][seed.getCluster(lrMin)];
124 const auto& cluster1GL = unsortedClusters[lrMid][seed.getCluster(lrMid)];
125 const auto& cluster2GL = unsortedClusters[lrMax][seed.getCluster(lrMax)];
126 temporaryTrack.getParamIn() = buildTrackSeed(cluster2GL, cluster1GL, cluster0TF, bz, true);
127 }
128 }
129
132}
133
134GPUdi() bool fitTrack(TrackITSExt& trk,
135 int start,
136 int end,
137 int step,
141 int nCl,
142 const float bz,
144 const float* layerxX0,
145 const o2::base::Propagator* propagator,
146 const o2::base::PropagatorF::MatCorrType matCorrType,
147 o2::track::TrackPar* linRef = nullptr,
148 const bool shiftRefToCluster = false)
149{
150 for (int iLayer{start}; iLayer != end; iLayer += step) {
151 if (trk.getClusterIndex(iLayer) == constants::UnusedIndex) {
152 continue;
153 }
154
155 const TrackingFrameInfo& trackingHit = tfInfos[iLayer][trk.getClusterIndex(iLayer)];
156 if (linRef) {
157 if (!trk.o2::track::TrackParCovF::rotate(trackingHit.alphaTrackingFrame, *linRef, bz)) {
158 return false;
159 }
160 if (!propagator->propagateToX(trk, *linRef, trackingHit.xTrackingFrame, bz,
163 matCorrType)) {
164 return false;
165 }
166 if (matCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) {
167 if (!trk.correctForMaterial(*linRef, layerxX0[iLayer], layerxX0[iLayer] * constants::Radl * constants::Rho, true)) {
168 continue;
169 }
170 }
171 } else {
172 if (!trk.o2::track::TrackParCovF::rotate(trackingHit.alphaTrackingFrame)) {
173 return false;
174 }
175 if (!propagator->propagateToX(trk, trackingHit.xTrackingFrame, bz,
178 matCorrType)) {
179 return false;
180 }
181 if (matCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) {
182 if (!trk.correctForMaterial(layerxX0[iLayer], layerxX0[iLayer] * constants::Radl * constants::Rho, true)) {
183 continue;
184 }
185 }
186 }
187
188 const auto predChi2{trk.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)};
189 if ((nCl >= 3 && predChi2 > chi2clcut) || predChi2 < 0.f) {
190 return false;
191 }
192 trk.setChi2(trk.getChi2() + predChi2);
193 if (!trk.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) {
194 return false;
195 }
196 if (linRef && shiftRefToCluster) {
197 linRef->setY(trackingHit.positionTrackingFrame[0]);
198 linRef->setZ(trackingHit.positionTrackingFrame[1]);
199 }
200 nCl++;
201 }
202
203 return o2::gpu::CAMath::Abs(trk.getQ2Pt()) < maxQoverPt && trk.getChi2() < chi2ndfcut * (float)((nCl * 2) - 5);
204}
205
206template <int NLayers>
207GPUdi() bool refitTrack(const TrackSeed<NLayers>& trackSeed,
209 float chi2clcut,
210 float chi2ndfcut,
211 const float bz,
212 const TrackingFrameInfo* const* tfInfos,
213 const Cluster* const* clusters,
214 const float* layerxX0,
215 const float* layerRadii,
216 const float* minPt,
217 const o2::base::Propagator* propagator,
218 const o2::base::PropagatorF::MatCorrType matCorrType,
219 const int reseedIfShorter,
220 const bool shiftRefToCluster,
221 const bool repeatRefitOut)
222{
223 temporaryTrack = seedTrackForRefit(trackSeed,
224 tfInfos,
225 clusters,
227 bz,
230 bool fitSuccess = fitTrack(temporaryTrack,
231 0,
232 NLayers,
233 1,
234 chi2clcut,
237 0,
238 bz,
239 tfInfos,
240 layerxX0,
243 &linRef,
244 shiftRefToCluster);
245 if (!fitSuccess) {
246 return false;
247 }
248 temporaryTrack.getParamOut() = temporaryTrack.getParamIn();
249 linRef = temporaryTrack.getParamOut(); // use refitted track as lin.reference
251 temporaryTrack.setChi2(0);
252 fitSuccess = fitTrack(temporaryTrack,
253 NLayers - 1,
254 -1,
255 -1,
256 chi2clcut,
258 50.f,
259 0,
260 bz,
261 tfInfos,
262 layerxX0,
265 &linRef,
266 shiftRefToCluster);
267 if (!fitSuccess || temporaryTrack.getPt() < minPt[NLayers - temporaryTrack.getNClusters()]) {
268 return false;
269 }
270 if (repeatRefitOut) { // repeat outward refit seeding and linearizing with the stable inward fit result
272 linRef = saveInw; // use refitted track as lin.reference
273 float saveChi2 = temporaryTrack.getChi2();
275 temporaryTrack.setChi2(0);
276 fitSuccess = o2::its::track::fitTrack(temporaryTrack,
277 0,
278 NLayers,
279 1,
280 chi2clcut,
283 0,
284 bz,
285 tfInfos,
286 layerxX0,
289 &linRef,
290 shiftRefToCluster);
291 if (!fitSuccess) {
292 return false;
293 }
294 temporaryTrack.getParamOut() = temporaryTrack.getParamIn();
295 temporaryTrack.getParamIn() = saveInw;
296 temporaryTrack.setChi2(saveChi2);
297 }
298 return true;
299}
300
301} // namespace o2::its::track
302
303#endif
Base track model for the Barrel, params only, w/o covariance.
o2::track::TrackParCov TrackParCov
Definition Recon.h:39
std::array< int, 64 > reverse(std::array< int, 64 > a)
Definition of the ITS track.
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition glcorearb.h:5034
GLuint GLuint end
Definition glcorearb.h:469
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei GLsizei GLfloat distance
Definition glcorearb.h:5506
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr float B2C
constexpr float VeryBig
constexpr int UnusedIndex
Definition Constants.h:32
constexpr float Radl
Definition Constants.h:34
constexpr float Rho
Definition Constants.h:35
constexpr float UnsetValue
Definition Constants.h:33
int int int float chi2clcut
const TrackingFrameInfo *const * foundTrackingFrameInfo
int int int float float float int const float const TrackingFrameInfo *const const float const o2::base::Propagator const o2::base::PropagatorF::MatCorrType matCorrType
int int int float float float int nCl
int int int float float float maxQoverPt
const TrackingFrameInfo *const const Cluster *const const float const float bz
resetTrackCovariance(temporaryTrack)
int int int step
const TrackingFrameInfo *const const Cluster *const * unsortedClusters
int const float * layerRadii
return temporaryTrack
int int int float float float int const float const TrackingFrameInfo *const const float * layerxX0
int const float const TrackSeed< NLayers > & seed
int int int float float float int const float const TrackingFrameInfo *const const float const o2::base::Propagator const o2::base::PropagatorF::MatCorrType o2::track::TrackPar * linRef
int int int float float float int const float const TrackingFrameInfo *const * tfInfos
GPUhdi() bool isBetter(const o2
int int int float float chi2ndfcut
const TrackingFrameInfo *const const Cluster *const const float const float const int reseedIfShorter
int int int float float float int const float const TrackingFrameInfo *const const float const o2::base::Propagator * propagator
const float midR
GPUdi() int selectReseedMidLayer(int minLayer
constexpr float kCTgl2max
TrackParCovF TrackParCov
Definition Track.h:33
constexpr float kCSnp2max
constexpr float kMostProbablePt
constexpr float kC1Pt2max
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::array< float, 2 > positionTrackingFrame
Definition Cluster.h:75
std::array< float, 3 > covarianceTrackingFrame
Definition Cluster.h:76
std::vector< Cluster > clusters