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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
#ifndef DataFormats_FTLRecHit_FTLCluster_h
#define DataFormats_FTLRecHit_FTLCluster_h
/** \class FTLCluster
*
* based on SiPixelCluster
*
* \author Paolo Meridiani
*/
#include <cmath>
#include <vector>
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <numeric>
#include "DataFormats/DetId/interface/DetId.h"
class FTLCluster {
public:
typedef DetId key_type;
class FTLHit {
public:
constexpr FTLHit() : x_(0), y_(0), energy_(0), time_(0), time_error_(0) {}
constexpr FTLHit(uint16_t hit_x, uint16_t hit_y, float hit_energy, float hit_time, float hit_time_error)
: x_(hit_x), y_(hit_y), energy_(hit_energy), time_(hit_time), time_error_(hit_time_error) {}
constexpr uint16_t x() { return x_; }
constexpr uint16_t y() { return y_; }
constexpr uint16_t energy() { return energy_; }
constexpr uint16_t time() { return time_; }
constexpr uint16_t time_error() { return time_error_; }
private:
uint16_t x_; //row
uint16_t y_; //col
float energy_;
float time_;
float time_error_;
};
//--- Integer shift in x and y directions.
class Shift {
public:
constexpr Shift(int dx, int dy) : dx_(dx), dy_(dy) {}
constexpr Shift() : dx_(0), dy_(0) {}
constexpr int dx() const { return dx_; }
constexpr int dy() const { return dy_; }
private:
int dx_;
int dy_;
};
//--- Position of a FTL Hit
class FTLHitPos {
public:
constexpr FTLHitPos() : row_(0), col_(0) {}
constexpr FTLHitPos(int row, int col) : row_(row), col_(col) {}
constexpr int row() const { return row_; }
constexpr int col() const { return col_; }
constexpr FTLHitPos operator+(const Shift& shift) const {
return FTLHitPos(row() + shift.dx(), col() + shift.dy());
}
private:
int row_;
int col_;
};
static constexpr unsigned int MAXSPAN = 255;
static constexpr unsigned int MAXPOS = 2047;
/** Construct from a range of digis that form a cluster and from
* a DetID. The range is assumed to be non-empty.
*/
FTLCluster() {}
FTLCluster(DetId id,
unsigned int isize,
float const* energys,
float const* times,
float const* time_errors,
uint16_t const* xpos,
uint16_t const* ypos,
uint16_t const xmin,
uint16_t const ymin)
: theid(id),
theHitOffset(2 * isize),
theHitENERGY(energys, energys + isize),
theHitTIME(times, times + isize),
theHitTIME_ERROR(time_errors, time_errors + isize) {
uint16_t maxCol = 0;
uint16_t maxRow = 0;
int maxHit = -1;
float maxEnergy = -99999;
for (unsigned int i = 0; i != isize; ++i) {
uint16_t xoffset = xpos[i] - xmin;
uint16_t yoffset = ypos[i] - ymin;
theHitOffset[i * 2] = std::min(uint16_t(MAXSPAN), xoffset);
theHitOffset[i * 2 + 1] = std::min(uint16_t(MAXSPAN), yoffset);
if (xoffset > maxRow)
maxRow = xoffset;
if (yoffset > maxCol)
maxCol = yoffset;
if (theHitENERGY[i] > maxEnergy) {
maxHit = i;
maxEnergy = theHitENERGY[i];
}
}
packRow(xmin, maxRow);
packCol(ymin, maxCol);
if (maxHit >= 0)
seed_ = std::min(uint8_t(MAXSPAN), uint8_t(maxHit));
}
// linear average position (barycenter)
inline float x() const {
auto x_pos = [this](unsigned int i) { return this->theHitOffset[i * 2] + minHitRow(); };
return weighted_mean(this->theHitENERGY, x_pos);
}
inline float y() const {
auto y_pos = [this](unsigned int i) { return this->theHitOffset[i * 2 + 1] + minHitCol(); };
return weighted_mean(this->theHitENERGY, y_pos);
}
inline float positionError(const float sigmaPos) const {
float sumW2(0.f), sumW(0.f);
for (const auto& hitW : theHitENERGY) {
sumW2 += hitW * hitW;
sumW += hitW;
}
if (sumW > 0)
return sigmaPos * std::sqrt(sumW2) / sumW;
else
return -999.f;
}
inline float time() const {
auto t = [this](unsigned int i) { return this->theHitTIME[i]; };
return weighted_mean(this->theHitENERGY, t);
}
inline float timeError() const {
auto t_err = [this](unsigned int i) { return this->theHitTIME_ERROR[i]; };
return weighted_mean_error(this->theHitENERGY, t_err);
}
// Return number of hits.
inline int size() const { return theHitENERGY.size(); }
// Return cluster dimension in the x direction.
inline int sizeX() const { return rowSpan() + 1; }
// Return cluster dimension in the y direction.
inline int sizeY() const { return colSpan() + 1; }
inline float energy() const {
return std::accumulate(theHitENERGY.begin(), theHitENERGY.end(), 0.f);
} // Return total cluster energy.
inline int minHitRow() const { return theMinHitRow; } // The min x index.
inline int maxHitRow() const { return minHitRow() + rowSpan(); } // The max x index.
inline int minHitCol() const { return theMinHitCol; } // The min y index.
inline int maxHitCol() const { return minHitCol() + colSpan(); } // The max y index.
const std::vector<uint8_t>& hitOffset() const { return theHitOffset; }
const std::vector<float>& hitENERGY() const { return theHitENERGY; }
const std::vector<float>& hitTIME() const { return theHitTIME; }
const std::vector<float>& hitTIME_ERROR() const { return theHitTIME_ERROR; }
// infinite faster than above...
FTLHit hit(int i) const {
return FTLHit(minHitRow() + theHitOffset[i * 2],
minHitCol() + theHitOffset[i * 2 + 1],
theHitENERGY[i],
theHitTIME[i],
theHitTIME_ERROR[i]);
}
FTLHit seed() const { return hit(seed_); }
int colSpan() const { return theHitColSpan; }
int rowSpan() const { return theHitRowSpan; }
const DetId& id() const { return theid; }
const DetId& detid() const { return id(); }
bool overflowCol() const { return overflow_(theHitColSpan); }
bool overflowRow() const { return overflow_(theHitRowSpan); }
bool overflow() const { return overflowCol() || overflowRow(); }
void packCol(uint16_t ymin, uint16_t yspan) {
theMinHitCol = ymin;
theHitColSpan = std::min(yspan, uint16_t(MAXSPAN));
}
void packRow(uint16_t xmin, uint16_t xspan) {
theMinHitRow = xmin;
theHitRowSpan = std::min(xspan, uint16_t(MAXSPAN));
}
void setClusterPosX(float posx) { pos_x = posx; }
void setClusterErrorX(float errx) { err_x = errx; }
void setClusterErrorTime(float errtime) { err_time = errtime; }
float getClusterPosX() const { return pos_x; }
float getClusterErrorX() const { return err_x; }
float getClusterErrorTime() const { return err_time; }
private:
DetId theid;
std::vector<uint8_t> theHitOffset;
std::vector<float> theHitENERGY;
std::vector<float> theHitTIME;
std::vector<float> theHitTIME_ERROR;
uint16_t theMinHitRow = MAXPOS; // Minimum hit index in the x direction (low edge).
uint16_t theMinHitCol = MAXPOS; // Minimum hit index in the y direction (left edge).
uint8_t theHitRowSpan = 0; // Span hit index in the x direction (low edge).
uint8_t theHitColSpan = 0; // Span hit index in the y direction (left edge).
float pos_x = -99999.9f; // For pixels with internal position information in one coordinate (i.e. BTL crystals)
float err_x = -99999.9f; // For pixels with internal position information in one coordinate (i.e. BTL crystals)
float err_time = -99999.9f;
uint8_t seed_;
template <typename SumFunc, typename OutFunc>
float weighted_sum(const std::vector<float>& weights, SumFunc&& sumFunc, OutFunc&& outFunc) const {
float tot = 0;
float sumW = 0;
for (unsigned int i = 0; i < weights.size(); ++i) {
tot += sumFunc(i);
sumW += weights[i];
}
return outFunc(tot, sumW);
}
template <typename Value>
float weighted_mean(const std::vector<float>& weights, Value&& value) const {
auto sumFunc = [&weights, value](unsigned int i) { return weights[i] * value(i); };
auto outFunc = [](float x, float y) {
if (y > 0)
return (float)x / y;
else
return -999.f;
};
return weighted_sum(weights, sumFunc, outFunc);
}
template <typename Err>
float weighted_mean_error(const std::vector<float>& weights, Err&& err) const {
auto sumFunc = [&weights, err](unsigned int i) { return weights[i] * weights[i] * err(i) * err(i); };
auto outFunc = [](float x, float y) {
if (y > 0)
return (float)sqrt(x) / y;
else
return -999.f;
};
return weighted_sum(weights, sumFunc, outFunc);
}
static int overflow_(uint16_t span) { return span == uint16_t(MAXSPAN); }
};
// Comparison operators (needed by DetSetVector & SortedCollection )
inline bool operator<(const FTLCluster& one, const FTLCluster& other) {
if (one.detid() == other.detid()) {
if (one.minHitRow() < other.minHitRow()) {
return true;
} else if (one.minHitRow() > other.minHitRow()) {
return false;
} else if (one.minHitCol() < other.minHitCol()) {
return true;
} else {
return false;
}
}
return one.detid() < other.detid();
}
inline bool operator<(const FTLCluster& one, const uint32_t& detid) { return one.detid() < detid; }
inline bool operator<(const uint32_t& detid, const FTLCluster& other) { return detid < other.detid(); }
#endif
|