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
293
294
295
296
297
298
299
300
301
302
303
304
|
#ifndef DataFormats_HcalRecHit_HBHEChannelInfo_h_
#define DataFormats_HcalRecHit_HBHEChannelInfo_h_
#include <cfloat>
#include <iostream>
#include "DataFormats/HcalDetId/interface/HcalDetId.h"
#include "DataFormats/HcalRecHit/interface/HcalSpecialTimes.h"
/** \class HBHEChannelInfo
*
* Unpacked charge and TDC information in a format which works
* for both QIE8 and QIE11
*/
class HBHEChannelInfo {
public:
typedef HcalDetId key_type;
static const unsigned MAXSAMPLES = 10;
constexpr HBHEChannelInfo()
: id_(),
rawCharge_{0.},
pedestal_{0.},
pedestalWidth_{0.},
gain_{0.},
gainWidth_{0.},
darkCurrent_{0},
fcByPE_{0},
lambda_{0},
noisecorr_{0},
riseTime_{0.f},
adc_{0},
dFcPerADC_{0.f},
recoShape_{0},
nSamples_{0},
soi_{0},
capid_{0},
hasTimeInfo_{false},
hasEffectivePedestals_{false},
dropped_{true},
hasLinkError_{false},
hasCapidError_{false} {}
constexpr explicit HBHEChannelInfo(const bool hasTimeFromTDC, const bool hasEffectivePed)
: id_(),
rawCharge_{0.},
pedestal_{0.},
pedestalWidth_{0.},
gain_{0.},
gainWidth_{0.},
darkCurrent_{0},
fcByPE_{0},
lambda_{0},
noisecorr_{0},
riseTime_{0.f},
adc_{0},
dFcPerADC_{0.f},
recoShape_{0},
nSamples_{0},
soi_{0},
capid_{0},
hasTimeInfo_(hasTimeFromTDC),
hasEffectivePedestals_(hasEffectivePed),
dropped_{true},
hasLinkError_{false},
hasCapidError_{false} {}
constexpr void clear() {
id_ = HcalDetId(0U);
recoShape_ = 0;
nSamples_ = 0;
soi_ = 0;
capid_ = 0;
darkCurrent_ = 0;
fcByPE_ = 0;
lambda_ = 0, dropped_ = true;
noisecorr_ = 0;
hasLinkError_ = false;
hasCapidError_ = false;
}
constexpr void setChannelInfo(const HcalDetId& detId,
const int recoShape,
const unsigned nSamp,
const unsigned iSoi,
const int iCapid,
const double darkCurrent,
const double fcByPE,
const double lambda,
const double noisecorr,
const bool linkError,
const bool capidError,
const bool dropThisChannel) {
recoShape_ = recoShape;
id_ = detId;
nSamples_ = nSamp < MAXSAMPLES ? nSamp : MAXSAMPLES;
soi_ = iSoi;
capid_ = iCapid;
darkCurrent_ = darkCurrent;
fcByPE_ = fcByPE;
lambda_ = lambda, dropped_ = dropThisChannel;
noisecorr_ = noisecorr;
hasLinkError_ = linkError;
hasCapidError_ = capidError;
}
constexpr void tagAsDropped() { dropped_ = true; }
// For speed, the "setSample" function does not perform bounds checking
constexpr void setSample(const unsigned ts,
const uint8_t rawADC,
const float differentialChargeGain,
const double q,
const double ped,
const double pedWidth,
const double g,
const double gainWidth,
const float t) {
rawCharge_[ts] = q;
riseTime_[ts] = t;
adc_[ts] = rawADC;
dFcPerADC_[ts] = differentialChargeGain;
pedestal_[ts] = ped;
gain_[ts] = g;
pedestalWidth_[ts] = pedWidth;
gainWidth_[ts] = gainWidth;
}
// Inspectors
constexpr HcalDetId id() const { return id_; }
// access the recoShape
constexpr int recoShape() const { return recoShape_; }
constexpr unsigned nSamples() const { return nSamples_; }
constexpr unsigned soi() const { return soi_; }
constexpr int capid() const { return capid_; }
constexpr bool hasTimeInfo() const { return hasTimeInfo_; }
constexpr bool hasEffectivePedestals() const { return hasEffectivePedestals_; }
constexpr double darkCurrent() const { return darkCurrent_; }
constexpr double fcByPE() const { return fcByPE_; }
constexpr double lambda() const { return lambda_; }
constexpr double noisecorr() const { return noisecorr_; }
constexpr bool isDropped() const { return dropped_; }
constexpr bool hasLinkError() const { return hasLinkError_; }
constexpr bool hasCapidError() const { return hasCapidError_; }
// Direct read-only access to time slice arrays
constexpr double const* rawCharge() const { return rawCharge_; }
constexpr double const* pedestal() const { return pedestal_; }
constexpr double const* pedestalWidth() const { return pedestalWidth_; }
constexpr double const* gain() const { return gain_; }
constexpr double const* gainWidth() const { return gainWidth_; }
constexpr uint8_t const* adc() const { return adc_; }
constexpr float const* dFcPerADC() const { return dFcPerADC_; }
constexpr float const* riseTime() const {
if (hasTimeInfo_)
return riseTime_;
else
return nullptr;
}
// Indexed access to time slice quantities. No bounds checking.
constexpr double tsRawCharge(const unsigned ts) const { return rawCharge_[ts]; }
constexpr double tsPedestal(const unsigned ts) const { return pedestal_[ts]; }
constexpr double tsPedestalWidth(const unsigned ts) const { return pedestalWidth_[ts]; }
constexpr double tsGain(const unsigned ts) const { return gain_[ts]; }
constexpr double tsGainWidth(const unsigned ts) const { return gainWidth_[ts]; }
constexpr double tsCharge(const unsigned ts) const { return rawCharge_[ts] - pedestal_[ts]; }
constexpr double tsEnergy(const unsigned ts) const { return (rawCharge_[ts] - pedestal_[ts]) * gain_[ts]; }
constexpr uint8_t tsAdc(const unsigned ts) const { return adc_[ts]; }
constexpr float tsDFcPerADC(const unsigned ts) const { return dFcPerADC_[ts]; }
constexpr float tsRiseTime(const unsigned ts) const {
return hasTimeInfo_ ? riseTime_[ts] : HcalSpecialTimes::UNKNOWN_T_NOTDC;
}
// Signal rise time measurement for the SOI, if available
constexpr float soiRiseTime() const {
return (hasTimeInfo_ && soi_ < nSamples_) ? riseTime_[soi_] : HcalSpecialTimes::UNKNOWN_T_NOTDC;
}
// The TS with the "end" index is not included in the window
constexpr double chargeInWindow(const unsigned begin, const unsigned end) const {
double sum = 0.0;
const unsigned imax = end < nSamples_ ? end : nSamples_;
for (unsigned i = begin; i < imax; ++i)
sum += (rawCharge_[i] - pedestal_[i]);
return sum;
}
constexpr double energyInWindow(const unsigned begin, const unsigned end) const {
double sum = 0.0;
const unsigned imax = end < nSamples_ ? end : nSamples_;
for (unsigned i = begin; i < imax; ++i)
sum += (rawCharge_[i] - pedestal_[i]) * gain_[i];
return sum;
}
// The two following methods return MAXSAMPLES if the specified
// window does not overlap with the samples stored
constexpr unsigned peakChargeTS(const unsigned begin, const unsigned end) const {
unsigned iPeak = MAXSAMPLES;
double dmax = -DBL_MAX;
const unsigned imax = end < nSamples_ ? end : nSamples_;
for (unsigned i = begin; i < imax; ++i) {
const double q = rawCharge_[i] - pedestal_[i];
if (q > dmax) {
dmax = q;
iPeak = i;
}
}
return iPeak;
}
constexpr unsigned peakEnergyTS(const unsigned begin, const unsigned end) const {
unsigned iPeak = MAXSAMPLES;
double dmax = -DBL_MAX;
const unsigned imax = end < nSamples_ ? end : nSamples_;
for (unsigned i = begin; i < imax; ++i) {
const double e = (rawCharge_[i] - pedestal_[i]) * gain_[i];
if (e > dmax) {
dmax = e;
iPeak = i;
}
}
return iPeak;
}
// The following function can be used, for example,
// in a check for presence of saturated ADC values
constexpr uint8_t peakAdcValue(const unsigned begin, const unsigned end) const {
uint8_t peak = 0;
const unsigned imax = end < nSamples_ ? end : nSamples_;
for (unsigned i = begin; i < imax; ++i)
if (adc_[i] > peak)
peak = adc_[i];
return peak;
}
private:
HcalDetId id_;
// Charge in fC for all time slices
double rawCharge_[MAXSAMPLES];
// Pedestal in fC
double pedestal_[MAXSAMPLES];
// Pedestal Width in fC
double pedestalWidth_[MAXSAMPLES];
// fC to GeV conversion factor
double gain_[MAXSAMPLES];
// fC to GeV conversion factor
double gainWidth_[MAXSAMPLES];
// needed for the dark current
double darkCurrent_;
double fcByPE_;
double lambda_;
double noisecorr_;
// Signal rise time from TDC in ns (if provided)
float riseTime_[MAXSAMPLES];
// Raw QIE ADC values
uint8_t adc_[MAXSAMPLES];
// Differential fC/ADC gain. Needed for proper determination
// of the ADC quantization error.
float dFcPerADC_[MAXSAMPLES];
// Reco Shapes
int32_t recoShape_;
// Number of time slices actually filled
uint32_t nSamples_;
// "Sample of interest" in the array of time slices
uint32_t soi_;
// QIE8 or QIE11 CAPID for the sample of interest
int32_t capid_;
// Flag indicating presence of the time info from TDC (QIE11)
bool hasTimeInfo_;
// Flag indicating use of effective pedestals
bool hasEffectivePedestals_;
// Flag indicating that this channel should be dropped
// (typically, tagged bad from DB or zero-suppressed)
bool dropped_;
// Flags indicating presence of hardware errors
bool hasLinkError_;
bool hasCapidError_;
};
std::ostream& operator<<(std::ostream& s, const HBHEChannelInfo& inf);
#endif // DataFormats_HcalRecHit_HBHEChannelInfo_h_
|