Project
Loading...
Searching...
No Matches
GPUTPCGMO2Output.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 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.
11
14
15#include "GPUTPCDef.h"
16#include "GPUTPCGMO2Output.h"
17#include "GPUCommonAlgorithm.h"
21#include "TPCFastTransform.h"
23
24#ifndef GPUCA_GPUCODE
27#include "GPUQAHelper.h"
28#endif
29
30using namespace o2::gpu;
31using namespace o2::tpc;
32using namespace o2::tpc::constants;
33
34GPUdi() static constexpr uint8_t getFlagsReject() { return GPUTPCGMMergedTrackHit::flagReject | GPUTPCGMMergedTrackHit::flagNotFit; }
35GPUdi() static uint32_t getFlagsRequired(const GPUSettingsRec& rec) { return rec.tpc.dropSecondaryLegsInOutput ? gputpcgmmergertypes::attachGoodLeg : gputpcgmmergertypes::attachZero; }
36
37template <>
38GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::prepare>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() merger)
39{
40 const GPUTPCGMMergedTrack* tracks = merger.OutputTracks();
41 const uint32_t nTracks = merger.NOutputTracks();
42 const GPUTPCGMMergedTrackHit* trackClusters = merger.Clusters();
43 const GPUdEdxInfo* tracksdEdx = merger.OutputTracksdEdx();
44
45 constexpr uint8_t flagsReject = getFlagsReject();
46 const uint32_t flagsRequired = getFlagsRequired(merger.Param().rec);
47 bool cutOnTrackdEdx = merger.Param().par.dodEdx && merger.Param().dodEdxDownscaled && merger.Param().rec.tpc.minTrackdEdxMax2Tot > 0.f;
48
49 GPUTPCGMMerger::tmpSort* GPUrestrict() trackSort = merger.TrackSortO2();
50 uint2* GPUrestrict() tmpData = merger.ClusRefTmp();
51 for (uint32_t i = get_global_id(0); i < nTracks; i += get_global_size(0)) {
52 if (!tracks[i].OK()) {
53 continue;
54 }
55 uint32_t nCl = 0;
56 for (uint32_t j = 0; j < tracks[i].NClusters(); j++) {
57 if ((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (merger.ClusterAttachment()[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired) {
58 continue;
59 }
60 if (merger.Param().rec.tpc.dropSecondaryLegsInOutput && trackClusters[tracks[i].FirstClusterRef() + j].leg != trackClusters[tracks[i].FirstClusterRef() + tracks[i].NClusters() - 1].leg) {
61 continue;
62 }
63 nCl++;
64 }
65 if (nCl == 0) {
66 continue;
67 }
68 if (merger.Param().rec.tpc.dropSecondaryLegsInOutput && nCl + 2 < GPUCA_TRACKLET_SELECTOR_MIN_HITS_B5(tracks[i].GetParam().GetQPt() * merger.Param().qptB5Scaler)) { // Give 2 hits tolerance in the primary leg, compared to the full fit of the looper
69 continue;
70 }
71 if (merger.Param().rec.tpc.minNClustersFinalTrack != -1 && nCl < (uint32_t)merger.Param().rec.tpc.minNClustersFinalTrack) {
72 continue;
73 }
74 if (cutOnTrackdEdx && (tracksdEdx[i].dEdxMaxTPC < merger.Param().rec.tpc.minTrackdEdxMax || tracksdEdx[i].dEdxMaxTPC < tracksdEdx[i].dEdxTotTPC * merger.Param().rec.tpc.minTrackdEdxMax2Tot) && !(tracksdEdx[i].dEdxMaxTPC == 0 && CAMath::Abs(tracks[i].GetParam().GetDzDs()) > 0.03f)) {
75 continue;
76 }
77 uint32_t myId = CAMath::AtomicAdd(&merger.Memory()->nO2Tracks, 1u);
78 tmpData[i] = {nCl, CAMath::AtomicAdd(&merger.Memory()->nO2ClusRefs, nCl + (nCl + 1) / 2)};
79 trackSort[myId] = {i, (merger.Param().par.earlyTpcTransform || tracks[i].CSide()) ? tracks[i].GetParam().GetTZOffset() : -tracks[i].GetParam().GetTZOffset()};
80 }
81}
82
83template <>
84GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::sort>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() merger)
85{
86#ifndef GPUCA_SPECIALIZE_THRUST_SORTS
87 if (iThread || iBlock) {
88 return;
89 }
90 GPUTPCGMMerger::tmpSort* GPUrestrict() trackSort = merger.TrackSortO2();
91 auto comp = [](const auto& a, const auto& b) { return (a.y > b.y); };
92 GPUCommonAlgorithm::sortDeviceDynamic(trackSort, trackSort + merger.Memory()->nO2Tracks, comp);
93#endif
94}
95
96#if defined(GPUCA_SPECIALIZE_THRUST_SORTS) && !defined(GPUCA_GPUCODE_COMPILEKERNELS) // Specialize GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::sort>
97struct GPUTPCGMO2OutputSort_comp {
98 GPUd() bool operator()(const GPUTPCGMMerger::tmpSort& a, const GPUTPCGMMerger::tmpSort& b)
99 {
100 return (a.y > b.y);
101 }
102};
103
104template <>
105inline void GPUCA_KRNL_BACKEND_CLASS::runKernelBackendInternal<GPUTPCGMO2Output, GPUTPCGMO2Output::sort>(const krnlSetupTime& _xyz)
106{
107 thrust::device_ptr<GPUTPCGMMerger::tmpSort> trackSort(mProcessorsShadow->tpcMerger.TrackSortO2());
109 thrust::sort(GPUCA_THRUST_NAMESPACE::par(alloc).on(mInternals->Streams[_xyz.x.stream]), trackSort, trackSort + processors()->tpcMerger.NOutputTracksTPCO2(), GPUTPCGMO2OutputSort_comp());
110}
111#endif // GPUCA_SPECIALIZE_THRUST_SORTS - Specialize GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::sort>
112
113template <>
114GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::output>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() merger)
115{
116 constexpr float MinDelta = 0.1f;
117 const GPUTPCGMMergedTrack* tracks = merger.OutputTracks();
118 GPUdEdxInfo* tracksdEdx = merger.OutputTracksdEdx();
119 const int32_t nTracks = merger.NOutputTracksTPCO2();
120 const GPUTPCGMMergedTrackHit* trackClusters = merger.Clusters();
121 constexpr uint8_t flagsReject = getFlagsReject();
122 const uint32_t flagsRequired = getFlagsRequired(merger.Param().rec);
123 TrackTPC* outputTracks = merger.OutputTracksTPCO2();
124 uint32_t* clusRefs = merger.OutputClusRefsTPCO2();
125
126 GPUTPCGMMerger::tmpSort* GPUrestrict() trackSort = merger.TrackSortO2();
127 uint2* GPUrestrict() tmpData = merger.ClusRefTmp();
128 float const SNPThresh = 0.999990f;
129
130 for (int32_t iTmp = get_global_id(0); iTmp < nTracks; iTmp += get_global_size(0)) {
131 TrackTPC oTrack;
132 const int32_t i = trackSort[iTmp].x;
133 auto snpIn = tracks[i].GetParam().GetSinPhi();
134 if (snpIn > SNPThresh) {
135 snpIn = SNPThresh;
136 } else if (snpIn < -SNPThresh) {
137 snpIn = -SNPThresh;
138 }
139 oTrack.set(tracks[i].GetParam().GetX(), tracks[i].GetAlpha(),
140 {tracks[i].GetParam().GetY(), tracks[i].GetParam().GetZ(), snpIn, tracks[i].GetParam().GetDzDs(), tracks[i].GetParam().GetQPt()},
141 {tracks[i].GetParam().GetCov(0),
142 tracks[i].GetParam().GetCov(1), tracks[i].GetParam().GetCov(2),
143 tracks[i].GetParam().GetCov(3), tracks[i].GetParam().GetCov(4), tracks[i].GetParam().GetCov(5),
144 tracks[i].GetParam().GetCov(6), tracks[i].GetParam().GetCov(7), tracks[i].GetParam().GetCov(8), tracks[i].GetParam().GetCov(9),
145 tracks[i].GetParam().GetCov(10), tracks[i].GetParam().GetCov(11), tracks[i].GetParam().GetCov(12), tracks[i].GetParam().GetCov(13), tracks[i].GetParam().GetCov(14)});
146
147 oTrack.setChi2(tracks[i].GetParam().GetChi2());
148 auto& outerPar = tracks[i].OuterParam();
149 if (merger.Param().par.dodEdx && merger.Param().dodEdxDownscaled) {
150 oTrack.setdEdx(tracksdEdx[i]);
151 }
152
153 auto snpOut = outerPar.P[2];
154 if (snpOut > SNPThresh) {
155 snpOut = SNPThresh;
156 } else if (snpOut < -SNPThresh) {
157 snpOut = -SNPThresh;
158 }
159 oTrack.setOuterParam(o2::track::TrackParCov(
160 outerPar.X, outerPar.alpha,
161 {outerPar.P[0], outerPar.P[1], snpOut, outerPar.P[3], outerPar.P[4]},
162 {outerPar.C[0], outerPar.C[1], outerPar.C[2], outerPar.C[3], outerPar.C[4], outerPar.C[5],
163 outerPar.C[6], outerPar.C[7], outerPar.C[8], outerPar.C[9], outerPar.C[10], outerPar.C[11],
164 outerPar.C[12], outerPar.C[13], outerPar.C[14]}));
165
166 if (merger.Param().par.dodEdx && merger.Param().dodEdxDownscaled && merger.Param().rec.tpc.enablePID) {
167 PIDResponse pidResponse{};
168 auto pid = pidResponse.getMostProbablePID(oTrack, merger.Param().rec.tpc.PID_EKrangeMin, merger.Param().rec.tpc.PID_EKrangeMax, merger.Param().rec.tpc.PID_EPrangeMin, merger.Param().rec.tpc.PID_EPrangeMax, merger.Param().rec.tpc.PID_EDrangeMin, merger.Param().rec.tpc.PID_EDrangeMax, merger.Param().rec.tpc.PID_ETrangeMin, merger.Param().rec.tpc.PID_ETrangeMax, merger.Param().rec.tpc.PID_useNsigma, merger.Param().rec.tpc.PID_sigma);
169 auto pidRemap = merger.Param().rec.tpc.PID_remap[pid];
170 if (pidRemap >= 0) {
171 pid = pidRemap;
172 }
173 oTrack.setPID(pid, true);
174 oTrack.getParamOut().setPID(pid, true);
175 }
176
177 uint32_t nOutCl = tmpData[i].x;
178 uint32_t clBuff = tmpData[i].y;
179 oTrack.setClusterRef(clBuff, nOutCl);
180 uint32_t* clIndArr = &clusRefs[clBuff];
181 uint8_t* sectorIndexArr = reinterpret_cast<uint8_t*>(clIndArr + nOutCl);
182 uint8_t* rowIndexArr = sectorIndexArr + nOutCl;
183
184 uint32_t nOutCl2 = 0;
185 float t1 = 0, t2 = 0;
186 int32_t sector1 = 0, sector2 = 0;
187 const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem()->ioPtrs.clustersNative;
188 for (uint32_t j = 0; j < tracks[i].NClusters(); j++) {
189 if ((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (merger.ClusterAttachment()[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired) {
190 continue;
191 }
192 if (merger.Param().rec.tpc.dropSecondaryLegsInOutput && trackClusters[tracks[i].FirstClusterRef() + j].leg != trackClusters[tracks[i].FirstClusterRef() + tracks[i].NClusters() - 1].leg) {
193 continue;
194 }
195 int32_t clusterIdGlobal = trackClusters[tracks[i].FirstClusterRef() + j].num;
196 int32_t sector = trackClusters[tracks[i].FirstClusterRef() + j].sector;
197 int32_t globalRow = trackClusters[tracks[i].FirstClusterRef() + j].row;
198 int32_t clusterIdInRow = clusterIdGlobal - clusters->clusterOffset[sector][globalRow];
199 clIndArr[nOutCl2] = clusterIdInRow;
200 sectorIndexArr[nOutCl2] = sector;
201 rowIndexArr[nOutCl2] = globalRow;
202 if (nOutCl2 == 0) {
203 t1 = clusters->clustersLinear[clusterIdGlobal].getTime();
204 sector1 = sector;
205 }
206 if (++nOutCl2 == nOutCl) {
207 t2 = clusters->clustersLinear[clusterIdGlobal].getTime();
208 sector2 = sector;
209 }
210 }
211
212 bool cce = tracks[i].CCE() && ((sector1 < MAXSECTOR / 2) ^ (sector2 < MAXSECTOR / 2));
213 float time0 = 0.f, tFwd = 0.f, tBwd = 0.f;
214 if (merger.Param().par.continuousTracking) {
215 time0 = tracks[i].GetParam().GetTZOffset();
216 if (cce) {
217 bool lastSide = trackClusters[tracks[i].FirstClusterRef()].sector < MAXSECTOR / 2;
218 float delta = 0.f;
219 for (uint32_t iCl = 1; iCl < tracks[i].NClusters(); iCl++) {
220 auto& cacl1 = trackClusters[tracks[i].FirstClusterRef() + iCl];
221 if (lastSide ^ (cacl1.sector < MAXSECTOR / 2)) {
222 auto& cl1 = clusters->clustersLinear[cacl1.num];
223 auto& cl2 = clusters->clustersLinear[trackClusters[tracks[i].FirstClusterRef() + iCl - 1].num];
224 delta = CAMath::Abs(cl1.getTime() - cl2.getTime()) * 0.5f;
225 if (delta < MinDelta) {
226 delta = MinDelta;
227 }
228 break;
229 }
230 }
231 tFwd = tBwd = delta;
232 } else {
233 // estimate max/min time increments which still keep track in the physical limits of the TPC
234 const float tmin = CAMath::Min(t1, t2);
235 const float maxDriftTime = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getMaxDriftTime(t1 > t2 ? sector1 : sector2);
236 const float clusterT0 = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getT0();
237 const float tmax = CAMath::Min(tmin + maxDriftTime, CAMath::Max(t1, t2));
238 float delta = 0.f;
239 if (time0 + maxDriftTime < tmax) {
240 delta = tmax - time0 - maxDriftTime;
241 }
242 if (tmin - clusterT0 < time0 + delta) {
243 delta = tmin - clusterT0 - time0;
244 }
245 if (delta != 0.f) {
246 time0 += delta;
247 const float deltaZ = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convDeltaTimeToDeltaZinTimeFrame(sector2, delta);
248 oTrack.setZ(oTrack.getZ() + deltaZ);
249 }
250 tFwd = tmin - clusterT0 - time0;
251 tBwd = time0 - tmax + maxDriftTime;
252 }
253 }
254 if (tBwd < 0.f) {
255 tBwd = 0.f;
256 }
257 oTrack.setTime0(time0);
258 oTrack.setDeltaTBwd(tBwd);
259 oTrack.setDeltaTFwd(tFwd);
260 if (cce) {
261 oTrack.setHasCSideClusters();
262 oTrack.setHasASideClusters();
263 } else if (tracks[i].CSide()) {
264 oTrack.setHasCSideClusters();
265 } else {
266 oTrack.setHasASideClusters();
267 }
268 outputTracks[iTmp] = oTrack;
269 }
270}
271
272template <>
273GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::mc>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() merger)
274{
275#ifndef GPUCA_GPUCODE
276 const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = merger.GetConstantMem()->ioPtrs.clustersNative;
277 if (clusters == nullptr || clusters->clustersMCTruth == nullptr) {
278 return;
279 }
280 if (merger.OutputTracksTPCO2MC() == nullptr) {
281 return;
282 }
283
284 auto labelAssigner = GPUTPCTrkLbl(clusters->clustersMCTruth, 0.1f);
285 uint32_t* clusRefs = merger.OutputClusRefsTPCO2();
286 for (uint32_t i = get_global_id(0); i < merger.NOutputTracksTPCO2(); i += get_global_size(0)) {
287 labelAssigner.reset();
288 const auto& trk = merger.OutputTracksTPCO2()[i];
289 for (int32_t j = 0; j < trk.getNClusters(); j++) {
290 uint8_t sectorIndex, rowIndex;
291 uint32_t clusterIndex;
292 trk.getClusterReference(clusRefs, j, sectorIndex, rowIndex, clusterIndex);
293 uint32_t clusterIdGlobal = clusters->clusterOffset[sectorIndex][rowIndex] + clusterIndex;
294 labelAssigner.addLabel(clusterIdGlobal);
295 }
296 merger.OutputTracksTPCO2MC()[i] = labelAssigner.computeLabel();
297 }
298#endif
299}
benchmark::State & state
A const (ready only) version of MCTruthContainer.
Helper class to access correction maps.
int32_t i
#define GPUsharedref()
#define get_global_size(dim)
#define GPUrestrict()
#define get_global_id(dim)
#define GPUd()
#define GPUCA_TRACKLET_SELECTOR_MIN_HITS_B5(QPTB5)
GPUdii() void GPUTPCGMO2Output
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint32_t j
Definition RawData.h:0
uint16_t pid
Definition RawData.h:2
Definition of TPCFastTransform class.
PID response class.
Definition PIDResponse.h:39
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
constexpr int MAXSECTOR
Definition Constants.h:28
Global TPC definitions and constants.
Definition SimTraits.h:167
GPUdi() T BetheBlochAleph(T bg
TrackParCovF TrackParCov
Definition Track.h:33
GPUReconstruction * rec
uint32_t x
uint32_t y
std::vector< Cluster > clusters