29constexpr float xlumiMC = 0.158478605f;
33constexpr float minBunchIntensity = 0.001f;
36constexpr float minAdc2MeVSlope = 1e-9f;
39constexpr size_t hecShiftNSamples = 4;
57 <<
") is larger than MaxBunchCrossing ("
59 return StatusCode::FAILURE;
65 <<
", so digit sample 0 corresponds to bunch crossing "
68 return StatusCode::SUCCESS;
79 return StatusCode::FAILURE;
85 return StatusCode::FAILURE;
92 return StatusCode::FAILURE;
99 return StatusCode::FAILURE;
104 if (!minBiasAvgHdl.
isValid()) {
106 return StatusCode::FAILURE;
113 return StatusCode::FAILURE;
116 const int bcid =
static_cast<int> (eventInfo->bcid());
117 if (bcid < 0 || bcid >=
s_nBCID) {
119 return StatusCode::FAILURE;
121 const float intperBC = eventInfo->averageInteractionsPerCrossing();
126 outputPtr->
reserve (digitHandle->size());
130 std::vector<float> pileupADC;
131 std::vector<short> correctedSamples;
134 for (
const LArDigit* digit : *digitHandle) {
138 const std::vector<short>& rawSamples = digit->samples();
143 bool correctable = cabling->isOnlineConnected (
id) && !rawSamples.empty();
145 const auto& adc2mev = adc2MeVs->
ADC2MEV (
id, gain);
146 correctable = adc2mev.size() >= 2 &&
147 std::abs (adc2mev[1]) > minAdc2MeVSlope;
150 pulseShape = shapes->
Shape (
id, gain);
151 correctable = !pulseShape.empty();
157 correctable = mbEnergy > 0;
164 outputPtr->
push_back (std::make_unique<LArDigit> (
id, gain, rawSamples));
170 const bool hecShift = rawSamples.size() == hecShiftNSamples &&
174 pileupADC.assign (rawSamples.size(), 0);
176 bcid, slope, intperBC, hecShift, pileupADC);
182 correctedSamples.resize (rawSamples.size());
183 for (
size_t i = 0; i < rawSamples.size(); ++i) {
184 const long corrected =
185 std::lround (
static_cast<double> (rawSamples[i]) -
186 static_cast<double> (pileupADC[i]));
188 std::clamp (corrected,
189 static_cast<long> (std::numeric_limits<short>::lowest()),
190 static_cast<long> (std::numeric_limits<short>::max()));
191 if (clamped != corrected) {
194 correctedSamples[i] =
static_cast<short> (clamped);
198 (std::make_unique<LArDigit> (
id, gain, correctedSamples));
202 ATH_MSG_WARNING( nClamped <<
" corrected sample(s) fell outside the range "
203 "of short and were clamped" );
209 return StatusCode::SUCCESS;
215 if (pattern.empty()) {
216 ATH_MSG_ERROR(
"BeamIntensityPattern is empty. It must be set from "
217 "flags.Digitization.PU.BeamIntensityPattern." );
218 return StatusCode::FAILURE;
221 const int nPattern =
static_cast<int> (pattern.size());
229 <<
" does not fit into " <<
s_nBCID );
232 const int nGuard = 20;
233 for (
int i = 0; i <
s_nBCID / 2 - nGuard; ++i) {
234 const int pos1 = i % nPattern;
235 const int pos2 = nPattern - 1 - (i % nPattern);
236 if (pattern[pos1] > minBunchIntensity) {
239 if (pattern[pos2] > minBunchIntensity) {
245 ATH_MSG_INFO(
"Bunch pattern of length " << nPattern <<
" fits into "
247 for (
int i = 0; i <
s_nBCID; ++i) {
248 if (pattern[i % nPattern] > minBunchIntensity) {
254 const int nFilled = std::count_if (
m_lumi.begin(),
m_lumi.end(),
255 [] (
float lumi) { return lumi > 0; });
257 <<
" bunch crossings" );
259 ATH_MSG_ERROR(
"No filled bunch crossing found in the beam intensity "
260 "pattern, so the correction would be identically zero." );
261 return StatusCode::FAILURE;
264 return StatusCode::SUCCESS;
274 std::vector<float>& pileupADC)
const
276 const int nShape =
static_cast<int> (pulseShape.size());
277 const int nSamples =
static_cast<int> (pileupADC.size());
280 for (
int i = 0; i < nSamples; ++i) {
284 for (
int j = 0; j < nShape; ++j) {
285 const int bc = i + firstSample - j;
289 int idx = (bcid + bc) %
s_nBCID;
293 sum +=
static_cast<double> (
m_lumi[idx]) * pulseShape[j];
296 static_cast<float> (mbEnergy * sum * intperBC / adc2MeVSlope);
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
Subtract the BCID-dependent pile-up offset from the LArDigit samples before digital filterings.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
const ServiceHandle< StoreGateSvc > & detStore() const
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
virtual const float & minBiasAverage(const HWIdentifier &id) const =0
access to average of E in minimum bias events index by Identifier
LArVectorProxy ShapeRef_t
This class defines the interface for accessing Shape (Nsample variable, Dt = 25 ns fixed) @stereotype...
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
Container class for LArDigit.
Liquid Argon digit base class.
void computePileupADCCorrection(float mbEnergy, const ILArShape::ShapeRef_t &pulseShape, int bcid, float adc2MeVSlope, float intperBC, bool hecShift, std::vector< float > &pileupADC) const
Compute the mean pile-up ADC offset per sample for one channel.
Gaudi::Property< int > m_minBunchCrossing
SG::ReadCondHandleKey< LArADC2MeV > m_adc2MeVKey
SG::ReadCondHandleKey< ILArMinBiasAverage > m_minBiasAvgKey
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
virtual StatusCode initialize() override
std::vector< float > m_lumi
Per-BCID luminosity, indexed by absolute BCID in [0, s_nBCID).
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadCondHandleKey< ILArShape > m_shapeKey
const LArOnlineID * m_onlineId
Online identifier helper, used to recognise HEC channels.
static constexpr int s_nBCID
Number of bunch crossings in one LHC orbit.
Gaudi::Property< int > m_firstSample
Gaudi::Property< int > m_maxBunchCrossing
SG::WriteHandleKey< LArDigitContainer > m_digitCorrKey
StatusCode fillLumi()
Fill m_lumi from the beam intensity pattern.
SG::ReadHandleKey< LArDigitContainer > m_digitKey
Gaudi::Property< std::vector< float > > m_beamIntensityPattern
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
@ OWN_ELEMENTS
this data object owns its elements