187 {
188
190
191
192 const LArDigitContainer* inputContainer{};
194
195
196 auto outputContainer = std::make_unique<LArRawChannelContainer>();
197
198
199 const ILArPedestal* peds{};
201
202 const LArADC2MeV* adc2MeVs{};
204
205 const ILArOFC* ofcs{nullptr};
207
208 const ILArShape* shapes{};
210
211 const LArOnOffIdMapping*
cabling{};
213
214 std::unique_ptr<LArDSPThresholdsFlat> run2DSPThresh;
215 const LArDSPThresholdsComplete* run1DSPThresh = nullptr;
219 SG::ReadCondHandle<AthenaAttributeList> dspThrshAttr(
221 run2DSPThresh = std::make_unique<LArDSPThresholdsFlat>(*dspThrshAttr);
224 "Failed to initialize LArDSPThresholdFlat from attribute list "
225 "loaded from "
227 return StatusCode::FAILURE;
228 }
230 SG::ReadCondHandle<LArDSPThresholdsComplete> dspThresh(
232 run1DSPThresh = dspThresh.cptr();
233 } else {
235 return StatusCode::FAILURE;
236 }
237 }
238
239
240 for (const LArDigit* digit : *inputContainer) {
241
243
244 const HWIdentifier
id =
digit->hardwareID();
245
246 const bool connected =
cabling->isOnlineConnected(
id);
247
248 const std::vector<short>& samples =
digit->samples();
250 const float p = peds->
pedestal(
id, gain);
251
252
253 const auto& ofca = ofcs->
OFC_a(
id, gain);
254 const auto& adc2mev = adc2MeVs->
ADC2MEV(
id, gain);
255 const size_t nOFC = ofca.size();
256
257
258
259
260 const size_t nSamples = samples.size() - firstSample;
261 if (nSamples < nOFC) {
263 << nSamples << ", must be >= OFC_a size: " << ofca.size());
264 return StatusCode::FAILURE;
265 }
266
268 if (!connected)
269 continue;
271 <<
m_onlineId->channel_name(
id) <<
" gain " << gain);
272 return StatusCode::FAILURE;
273 }
274
276 if (!connected)
277 continue;
279 <<
m_onlineId->channel_name(
id) <<
" gain " << gain);
280 return StatusCode::FAILURE;
281 }
282
283
284
285
286
288
289 std::vector<double> samp_no_ped(nOFC, 0.0);
290 for (
size_t i = 0;
i < nOFC; ++
i) {
291 if (samples[i + firstSample] == 4096 || samples[i + firstSample] == 0)
293 samp_no_ped[
i] = samples[
i + firstSample] -
p;
294 }
295
297 float tau = 0;
298
300 if (saturated)
301 prov |= 0x0400;
302
303 float ecut(0.);
305 if (run2DSPThresh) {
306 ecut = run2DSPThresh->tQThr(id);
307 } else if (run1DSPThresh) {
308 ecut = run1DSPThresh->
tQThr(
id);
309 } else {
311 return StatusCode::FAILURE;
312 }
313 } else {
315 }
316
317 const auto& fullShape = shapes->
Shape(
id, gain);
318
319 double A =
computeOFFC(samples, firstSample, ofca, fullShape, p);
320
321 const float E = adc2mev[0] +
A * adc2mev[1];
322
324
325 if (E1 > ecut) {
327 << gain
328 << " above threshold for tQ computation");
329 prov |= 0x2000;
330
331
332
333 const auto& ofcb = ofcs->
OFC_b(
id, gain);
334 double At = 0;
335 for (
size_t i = 0;
i < nOFC; ++
i) {
336 At +=
static_cast<double>(samp_no_ped[
i]) * ofcb[i];
337 }
338
339
340
341
342 tau = (std::fabs(A) > 0.1) ? At / A : 0.0;
343
344
345
346
347 const size_t nSamples = samples.size();
348 if (fullShape.size() > nSamples && nSamples == 4 &&
m_firstSample == 0) {
350 firstSample = 1;
351 }
352 }
353
354 if (
ATH_UNLIKELY(fullShape.size() < nOFC + firstSample)) {
355 if (!connected)
356 continue;
358 <<
m_onlineId->channel_name(
id) <<
" gain " << gain);
359 ATH_MSG_ERROR(
"Got size " << fullShape.size() <<
", expected at least "
360 << nSamples + firstSample);
361 return StatusCode::FAILURE;
362 }
363
364 std::span<const float> shape(fullShape.data() + firstSample, fullShape.size() - firstSample);
365
368 const auto& fullshapeDer = shapes->
ShapeDer(
id, gain);
369 if (
ATH_UNLIKELY(fullshapeDer.size() < nOFC + firstSample)) {
371 <<
m_onlineId->channel_name(
id) <<
" gain " << gain);
373 << ", expected at least "
374 << nOFC + firstSample);
375 return StatusCode::FAILURE;
376 }
377
378 std::span<const float> shapeDer(fullshapeDer.data() + firstSample, fullshapeDer.size() - firstSample);
379
380
381 for (
size_t i = 0;
i < nOFC; ++
i) {
382 q += std::pow((A * (shape[i] - tau * shapeDer[i]) - (samp_no_ped[i])),
383 2);
384 }
385 }
386 else {
387
388 for (
size_t i = 0;
i < nOFC; ++
i) {
389 q += std::pow((A * shape[i] - (samp_no_ped[i])), 2);
390 }
391 }
392
393 int iqua = std::min(static_cast<int>(q), 0xFFFF);
394
395 iquaShort =
static_cast<uint16_t>(iqua & 0xFFFF);
396
398 tau *= (Gaudi::Units::nanosecond /
399 Gaudi::Units::picosecond);
400 }
401
402 outputContainer->emplace_back(id, static_cast<int>(std::floor(E + 0.5)),
403 static_cast<int>(std::floor(tau + 0.5)),
405 }
406
407 SG::WriteHandle<LArRawChannelContainer> outputHandle(
m_rawChannelKey, ctx);
408 ATH_CHECK(outputHandle.record(std::move(outputContainer)));
409
410 return StatusCode::SUCCESS;
411}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
virtual OFCRef_t OFC_b(const HWIdentifier &id, int gain, int tbin=0) const =0
virtual OFCRef_t OFC_a(const HWIdentifier &id, int gain, int tbin=0) const =0
access to OFCs by online ID, gain, and tbin (!=0 for testbeam)
virtual float timeOffset(const HWIdentifier &CellID, int gain) const =0
virtual float pedestal(const HWIdentifier &id, int gain) const =0
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
virtual ShapeRef_t ShapeDer(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
float tQThr(const HWIdentifier chid) const
SG::WriteHandleKey< LArRawChannelContainer > m_rawChannelKey
Gaudi::Property< bool > m_useDBFortQ
double computeOFFC(const std::vector< short > &samples, int firstSample, const ILArOFC::OFCRef_t &ofc, const ILArShape::ShapeRef_t &shape, double pedestal) const
SG::ReadCondHandleKey< ILArShape > m_shapeKey
Gaudi::Property< bool > m_absECutFortQ
SG::ReadCondHandleKey< LArADC2MeV > m_adc2MeVKey
Gaudi::Property< int > m_firstSample
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
const LArOnlineID * m_onlineId
SG::ReadCondHandleKey< ILArPedestal > m_pedestalKey
Gaudi::Property< float > m_eCutFortQ
SG::ReadHandleKey< LArDigitContainer > m_digitKey
SG::ReadCondHandleKey< ILArOFC > m_ofcKey
Gaudi::Property< bool > m_useShapeDer
SG::ReadCondHandleKey< AthenaAttributeList > m_run2DSPThresholdsKey
SG::ReadCondHandleKey< LArDSPThresholdsComplete > m_run1DSPThresholdsKey
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
setScaleOne setStatusOne saturated