forked from AliceO2Group/AliceO2
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathClusterNative.h
More file actions
208 lines (193 loc) · 8.57 KB
/
ClusterNative.h
File metadata and controls
208 lines (193 loc) · 8.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// 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 ClusterNative.h
/// \brief Class of a TPC cluster in TPC-native coordinates (row, time)
/// \author David Rohr
#ifndef ALICEO2_DATAFORMATSTPC_CLUSTERNATIVE_H
#define ALICEO2_DATAFORMATSTPC_CLUSTERNATIVE_H
#ifndef GPUCA_GPUCODE_DEVICE
#include <cstdint>
#include <cstddef> // for size_t
#include <utility>
#endif
#include "DataFormatsTPC/Constants.h"
#include "GPUCommonDef.h"
namespace o2
{
class MCCompLabel;
namespace dataformats
{
template <class T>
class ConstMCTruthContainer;
template <class T>
class ConstMCTruthContainerView;
} // namespace dataformats
} // namespace o2
namespace o2
{
namespace tpc
{
/**
* \struct ClusterNative
* A transient data structure for clusters in TPC-native pad,
* and time format. To keep it as small as possible, row coordinate is
* kept outside in the meta information for a sequence of ClusterNative
* objects.
*
* Structure holds float values in a packed integral format, scaling
* factors are chosen according to TPC resolution. The 24-bit wide time
* field allows unique values within 512 TPC drift lengths.
*
* Not for permanent storage.
*/
struct ClusterNative {
// NOTE: These states must match those from GPUTPCGMMergedTrackHit!
enum clusterState { flagSplitPad = 0x1, // Split in pad direction
flagSplitTime = 0x2, // Split in time direction
flagEdge = 0x4, // At edge of TPC sector
flagSingle = 0x8 }; // Single pad or single time-bin cluster
static constexpr int scaleTimePacked = 64; //< ~50 is needed for 0.1mm precision, but leads to float rounding artifacts around 20ms
static constexpr int scalePadPacked = 64; //< ~60 is needed for 0.1mm precision, but power of two avoids rounding
static constexpr int scaleSigmaTimePacked = 32; // 1/32nd of pad/timebin precision for cluster size
static constexpr int scaleSigmaPadPacked = 32;
uint32_t timeFlagsPacked; //< Contains the time in the lower 24 bits in a packed format, contains the flags in the
// upper 8 bits
uint16_t padPacked; //< Contains the pad in a packed format
uint8_t sigmaTimePacked; //< Sigma of the time in packed format
uint8_t sigmaPadPacked; //< Sigma of the pad in packed format
uint16_t qMax; //< QMax of the cluster
uint16_t qTot; //< Total charge of the cluster
GPUd() static uint16_t packPad(float pad) { return (uint16_t)(pad * scalePadPacked + 0.5); }
GPUd() static uint32_t packTime(float time) { return (uint32_t)(time * scaleTimePacked + 0.5); }
GPUd() static float unpackPad(uint16_t pad) { return float(pad) * (1.f / scalePadPacked); }
GPUd() static float unpackTime(uint32_t time) { return float(time) * (1.f / scaleTimePacked); }
GPUdDefault() ClusterNative() = default;
GPUd() ClusterNative(uint32_t time, uint8_t flags, uint16_t pad, uint8_t sigmaTime, uint8_t sigmaPad, uint16_t qmax, uint16_t qtot) : padPacked(pad), sigmaTimePacked(sigmaTime), sigmaPadPacked(sigmaPad), qMax(qmax), qTot(qtot)
{
setTimePackedFlags(time, flags);
}
GPUd() uint16_t getQmax() const { return qMax; }
GPUd() uint16_t getQtot() const { return qTot; }
GPUd() uint8_t getFlags() const { return timeFlagsPacked >> 24; }
GPUd() uint32_t getTimePacked() const { return timeFlagsPacked & 0xFFFFFF; }
GPUd() void setTimePackedFlags(uint32_t timePacked, uint8_t flags)
{
timeFlagsPacked = (timePacked & 0xFFFFFF) | (uint32_t)flags << 24;
}
GPUd() void setTimePacked(uint32_t timePacked)
{
timeFlagsPacked = (timePacked & 0xFFFFFF) | (timeFlagsPacked & 0xFF000000);
}
GPUd() void setFlags(uint8_t flags) { timeFlagsPacked = (timeFlagsPacked & 0xFFFFFF) | ((uint32_t)flags << 24); }
GPUd() float getTime() const { return unpackTime(timeFlagsPacked & 0xFFFFFF); }
GPUd() void setTime(float time)
{
timeFlagsPacked = (packTime(time) & 0xFFFFFF) | (timeFlagsPacked & 0xFF000000);
}
GPUd() void setTimeFlags(float time, uint8_t flags)
{
timeFlagsPacked = (packTime(time) & 0xFFFFFF) | ((decltype(timeFlagsPacked))flags << 24);
}
/// @return Returns the pad position of the cluster.
/// note that the pad position is defined on the left side of the pad.
/// the pad position from clusters are calculated in HwClusterer::hwClusterProcessor()
/// around the centre of gravity around the left side of the pad.
/// i.e. the center of the first pad has pad position zero.
/// To get the corresponding local Y coordinate of the cluster:
/// Y = (pad_position - 0.5 * (n_pads - 1)) * padWidth
/// example:
/// the pad position is for example 12.4 (pad_position = 12.4).
/// there are 66 pads in the first pad row (n_pads = 66).
/// the pad width for pads in the first padrow is 4.16mm (padWidth = 4.16mm).
/// Y = (12.4 - 0.5 * (66 - 1)) * 4.16mm = -83.616mm
GPUd() float getPad() const { return unpackPad(padPacked); }
GPUd() void setPad(float pad) { padPacked = packPad(pad); }
GPUd() float getSigmaTime() const { return float(sigmaTimePacked) * (1.f / scaleSigmaTimePacked); }
GPUd() void setSigmaTime(float sigmaTime)
{
uint32_t tmp = sigmaTime * scaleSigmaTimePacked + 0.5;
if (tmp > 0xFF) {
tmp = 0xFF;
}
sigmaTimePacked = tmp;
}
GPUd() float getSigmaPad() const { return float(sigmaPadPacked) * (1.f / scaleSigmaPadPacked); }
GPUd() void setSigmaPad(float sigmaPad)
{
uint32_t tmp = sigmaPad * scaleSigmaPadPacked + 0.5;
if (tmp > 0xFF) {
tmp = 0xFF;
}
sigmaPadPacked = tmp;
}
GPUd() bool operator<(const ClusterNative& rhs) const
{
if (this->getTimePacked() != rhs.getTimePacked()) {
return (this->getTimePacked() < rhs.getTimePacked());
} else if (this->padPacked != rhs.padPacked) {
return (this->padPacked < rhs.padPacked);
} else if (this->sigmaTimePacked != rhs.sigmaTimePacked) {
return (this->sigmaTimePacked < rhs.sigmaTimePacked);
} else if (this->sigmaPadPacked != rhs.sigmaPadPacked) {
return (this->sigmaPadPacked < rhs.sigmaPadPacked);
} else if (this->qMax != rhs.qMax) {
return (this->qMax < rhs.qMax);
} else if (this->qTot != rhs.qTot) {
return (this->qTot < rhs.qTot);
} else {
return (this->getFlags() < rhs.getFlags());
}
}
GPUd() bool operator==(const ClusterNative& rhs) const
{
return this->getTimePacked() == rhs.getTimePacked() &&
this->padPacked == rhs.padPacked &&
this->sigmaTimePacked == rhs.sigmaTimePacked &&
this->sigmaPadPacked == rhs.sigmaPadPacked &&
this->qMax == rhs.qMax &&
this->qTot == rhs.qTot &&
this->getFlags() == rhs.getFlags();
}
};
// This is an index struct to access TPC clusters inside sectors and rows. It shall not own the data, but just point to
// the data inside a buffer.
struct ClusterNativeAccess {
const ClusterNative* clustersLinear;
const ClusterNative* clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW];
const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* clustersMCTruth;
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW];
unsigned int nClustersSector[constants::MAXSECTOR];
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW];
unsigned int nClustersTotal; // Must be directly after clusterOffsets, --> =clusterOffset[nRows * nSectors]!
void setOffsetPtrs();
#ifndef GPUCA_GPUCODE
using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>;
using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>;
using ConstMCLabelContainerViewWithBuffer = std::pair<ConstMCLabelContainer, ConstMCLabelContainerView>;
#endif
};
inline void ClusterNativeAccess::setOffsetPtrs()
{
int offset = 0;
for (unsigned int i = 0; i < constants::MAXSECTOR; i++) {
nClustersSector[i] = 0;
for (unsigned int j = 0; j < constants::MAXGLOBALPADROW; j++) {
clusterOffset[i][j] = offset;
clusters[i][j] = &clustersLinear[offset];
nClustersSector[i] += nClusters[i][j];
offset += nClusters[i][j];
}
}
nClustersTotal = offset;
}
} // namespace tpc
} // namespace o2
#endif