ATLAS Offline Software
Loading...
Searching...
No Matches
LArAutoCorrTotalCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7
9
12
14
16 ISvcLocator *pSvcLocator)
17 : ::AthCondAlgorithm(name, pSvcLocator),
18 m_LArADC2MeVObjKey("LArADC2MeV"),
19 m_LArOnOffIdMappingObjKey("LArOnOffIdMap"),
20 m_LArShapeObjKey("LArShapeSym"),
21 m_LArAutoCorrObjKey("LArAutoCorrSym"),
22 m_LArNoiseObjKey("LArNoiseSym"),
23 m_LArPedestalObjKey("LArPedestal"),
24 m_LArfSamplObjKey("LArfSamplSym"),
25 m_LArMinBiasObjKey("LArMinBiasSym"),
26 m_LArAutoCorrTotalObjKey("LArAutoCorrTotal"),
27 m_NoPile(false), m_isMC(true),
28 m_isSuperCell(false), m_Nsamples(5),
30 declareProperty("LArADC2MeVObjKey", m_LArADC2MeVObjKey,
31 "Key to read LArADC2MeV object");
32 declareProperty("LArOnOffIdMappingObjKey", m_LArOnOffIdMappingObjKey,
33 "Key to read LArOnOffIdMapping object");
34 declareProperty("LArShapeObjKey", m_LArShapeObjKey,
35 "Key to read LArShape object");
36 declareProperty("LArAutoCorrObjKey", m_LArAutoCorrObjKey,
37 "Key to read LArAutoCorr object");
38 declareProperty("LArNoiseObjKey", m_LArNoiseObjKey,
39 "Key to read LArNoise object");
40 declareProperty("LArPedestalObjKey", m_LArPedestalObjKey,
41 "Key to read LArPedestal object");
42 declareProperty("LArfSamplObjKey", m_LArfSamplObjKey,
43 "Key to read LArfSampl object");
44 declareProperty("LArMinBiasObjKey", m_LArMinBiasObjKey,
45 "Key to read LArMinBias object");
46 declareProperty("LArAutoCorrTotalObjKey", m_LArAutoCorrTotalObjKey,
47 "Key to write LArAutoCorrTotal object");
48 declareProperty("NoPileUp", m_NoPile);
49 declareProperty("isMC", m_isMC);
50 declareProperty("isSuperCell", m_isSuperCell);
51 declareProperty("Nsamples", m_Nsamples, "Max number of samples to use");
53 "firstSample", m_firstSample,
54 "First sample to use for in-time event on the full pulse shape");
55 declareProperty("deltaBunch", m_deltaBunch,
56 "Delta between filled bunches in 25 ns units");
57}
58
60
62 ATH_MSG_DEBUG("initialize " << name());
63
64 // ReadCondHandle initialization
65 ATH_CHECK(m_LArShapeObjKey.initialize());
66 ATH_CHECK(m_LArAutoCorrObjKey.initialize());
68 ATH_CHECK( m_LArADC2MeVObjKey.initialize());
69
71
76
77 // Number of gains (does this have to be in initialize now b/c of AthenaMT?)
78 if (m_isSuperCell) {
79 m_nGains = 1;
80 } else {
81 m_nGains = 3;
82 }
83
84 ATH_MSG_DEBUG("settings: m_NoPile " << m_NoPile);
85 return StatusCode::SUCCESS;
86}
87
88StatusCode LArAutoCorrTotalCondAlg::execute(const EventContext& ctx) const {
89
90 // WriteHandle setup
92 // So the following should not be called usually?!
93 if (writeHandle.isValid()) {
95 "CondHandle "
96 << writeHandle.fullKey() << " is already valid.");
97 return StatusCode::SUCCESS;
98 }
99
100 // Identifier helper
101 const LArOnlineID_Base *larOnlineID = nullptr;
102 if (m_isSuperCell) {
103 const LArOnline_SuperCellID *scidhelper;
104 ATH_CHECK(detStore()->retrieve(scidhelper, "LArOnline_SuperCellID"));
105 larOnlineID = scidhelper; // cast to base-class
106 } else { // regular cells
107 const LArOnlineID *idhelper;
108 ATH_CHECK(detStore()->retrieve(idhelper, "LArOnlineID"));
109 larOnlineID = idhelper; // cast to base-class
110 }
111 // Mapping helper
112 const LArOnOffIdMapping *larOnOffIdMapping = nullptr;
113 SG::ReadCondHandle<LArOnOffIdMapping> larOnOffIdMappingHdl{
115 };
116 larOnOffIdMapping = *larOnOffIdMappingHdl;
117 if (larOnOffIdMapping == nullptr) {
118 ATH_MSG_ERROR("Failed to retrieve LArOnOffIdMapping object");
119 }
120
121 // Get pointers to inputs
123 // FIXME: should check if handle is properly created and/or check if handle is
124 // properly retrieved
125 // operator star of a ReadCondHandle returns a const pointer to type T
126 const ILArShape *larShape{ *ShapeHdl };
127 writeHandle.addDependency(ShapeHdl);
128
130 const ILArAutoCorr *larAutoCorr{ *AutoCorrHdl };
131 writeHandle.addDependency(AutoCorrHdl);
132
134 const LArADC2MeV *larADC2MeV = nullptr;
135 larADC2MeV = *ADC2MeVHdl;
136 if (larADC2MeV == nullptr) {
137 ATH_MSG_ERROR("Failed to retrieve LArADC2MeV object");
138 return StatusCode::FAILURE;
139 }
140 writeHandle.addDependency(ADC2MeVHdl);
141
142 // Consider the determinstic objects
143 // checking isMC and NoPile again seems very clumsy. How to check if key has
144 // already been initialized?
145 const ILArNoise *larNoise = nullptr;
146 const ILArPedestal *larPedestal = nullptr;
147 const ILArfSampl *larfSampl = nullptr;
148 const ILArMinBias *larMinBias = nullptr;
149
150 if (!m_NoPile) {
151 if (m_isMC) {
153 larNoise = *NoiseHdl;
154 writeHandle.addDependency(NoiseHdl);
155 } else {
157 larPedestal = *PedestalHdl;
158 writeHandle.addDependency(PedestalHdl);
159 }
160
162 larfSampl = *fSamplHdl;
163 writeHandle.addDependency(fSamplHdl);
164
166 larMinBias = *MinBiasHdl;
167 writeHandle.addDependency(MinBiasHdl);
168 }
169
170 ATH_MSG_INFO("IOV found from intersection for AutoCorrTotal object: "
171 << writeHandle.getRange());
172
173 // make output object
174 // dimensions: number of gains x number of channel IDs x elements of
175 // AutoCorrTotal
176 std::unique_ptr<LArAutoCorrTotal> larAutoCorrTotal =
177 std::make_unique<LArAutoCorrTotal>(larOnlineID, larOnOffIdMapping, m_nGains);
178
179 int count = 0;
180 int count2 = 0;
181 int count3 =0;
182
183 for (const HWIdentifier chid : larOnlineID->channel_range()) {
184 count++;
185 const IdentifierHash hid = larOnlineID->channel_Hash(chid);
186 // const unsigned int id32 = chid.get_identifier32().get_compact();
187
188 if (larOnOffIdMapping->isOnlineConnected(chid)) {
189 count2++;
190
191 for (size_t igain = 0; igain < m_nGains; igain++) {
192 const ILArShape::ShapeRef_t Shape = larShape->Shape(chid, igain);
193 const int nsamples_shape = static_cast<int>(Shape.size());
194
196 larAutoCorr->autoCorr(chid, igain);
197
198 if (AC.size() == 0) {
199 ATH_MSG_INFO("No ElecCalib AC for channel " << larOnlineID->channel_name(chid) << ", gain "<<igain << ". Skip.");
200 continue;
201 }
202
203 count3++;
204 int nsamples_AC_OFC = AC.size() + 1;
205
206 if (nsamples_AC_OFC > m_Nsamples) {
207 nsamples_AC_OFC = m_Nsamples;
208 }
209
210 // fix HEC first sample +1 if the firstSample is 0 and nsamples 4
211 unsigned int ihecshift = 0;
212 if (larOnlineID->isHECchannel(chid) && nsamples_AC_OFC == 4 &&
213 m_firstSample == 0) {
214 ihecshift = 1;
215 // ATH_MSG_DEBUG( "Using firstSample +1 for HEC ChID 0x" << MSG::hex
216 // << id << MSG::dec );
217 }
218
219 //:::::::::::::::::::::::::::::::
220 // NB:
221 // nsamples_shape = number of samples of the Shape function (e.g 32)
222 // nsamples_AC_OFC = size of AC matrix & OFC vector (e.g 5 in Atlas)
223 //:::::::::::::::::::::::::::::::
224 float fSigma2 = 0.;
225 if (!m_NoPile) {
226 float SigmaNoise;
227 if (m_isMC)
228 SigmaNoise = larNoise->noise(chid, igain);
229 else {
230 float RMSpedestal = larPedestal->pedestalRMS(chid, igain);
231 if (RMSpedestal > (1.0 + LArElecCalib::ERRORCODE))
232 SigmaNoise = RMSpedestal;
233 else
234 SigmaNoise = 0.; //(we will have the ERROR message below)
235 }
236 float fSampl = larfSampl->FSAMPL(chid);
237 float MinBiasRMS = larMinBias->minBiasRMS(chid);
238 if (fSampl != 0)
239 MinBiasRMS /= fSampl;
240 const auto polynom_adc2mev =
241 larADC2MeV->ADC2MEV(hid, igain);
242 float Adc2MeV = 0.;
243 if (polynom_adc2mev.size() > 0) {
244 Adc2MeV = (polynom_adc2mev)[1];
245 }
246 if (SigmaNoise != 0 && Adc2MeV != 0)
247 fSigma2 = pow(MinBiasRMS / (SigmaNoise * Adc2MeV), 2);
248
249 if (fSampl == 0 || SigmaNoise == 0 || Adc2MeV == 0) {
250 if (m_isMC) {
251 ATH_MSG_ERROR(larOnlineID->show_to_string(
252 larOnOffIdMapping->cnvToIdentifier(chid))
253 << "fSampl (" << fSampl << "), SigmaNoise ("
254 << SigmaNoise << ") or Adc2MeV (" << Adc2MeV
255 << ") null "
256 << "=> AutoCorrTotal = only AutoCorr elect. part ");
257 }
258 fSigma2 = 0.;
259 }
260 ATH_MSG_DEBUG(chid.get_identifier32().get_compact()
261 << ") fSampl (" << fSampl << ") "
262 << ") SigmaNoise (" << SigmaNoise << ") "
263 << ") Adc2MeV (" << Adc2MeV << ") "
264
265 );
266
267 // warning: MinBiasRMS is in MeV (at the scale of the hits)
268 // SigmaNoise is in ADC counts
269 // so MinBiasRMS/fScale and SigmaNoise*Adc2MeV are the same scale
270 // (MeV at the scale of the cells)
271 } // end if m_NoPile
272
273 // get in vTerms all the possible non trivial N(N-1)/2 terms of the
274 // autocorrelation matrix
275 int nsize_tot = (nsamples_AC_OFC - 1) * (nsamples_AC_OFC) / 2;
276
277 ATH_MSG_DEBUG(chid.get_identifier32().get_compact()
278 << ") fSigma2 (" << fSigma2 << ") "
279 << ") nsamples_AC_OFC ( " << nsamples_AC_OFC);
280 std::vector<float> vTerms;
281
282 vTerms.resize(2 * nsize_tot + nsamples_AC_OFC, 0.);
283 //:::::::::::::::::::::::::::::::
284
285 for (int j1 = 0; j1 < nsamples_AC_OFC - 1; j1++) {
286 for (int j2 = j1 + 1; j2 < nsamples_AC_OFC; j2++) {
287 int l = abs(j2 - j1) - 1;
288 int index =
289 j1 * nsamples_AC_OFC - j1 * (j1 + 1) / 2 + j2 - (j1 + 1);
290 vTerms[index] = AC[l];
291 }
292 }
293
294 ATH_MSG_DEBUG(chid.get_identifier32().get_compact()
295 << ") vTerms[1] (" << vTerms[1] << ") ");
296 // 2nd terms :
297 for (int j1 = 0; j1 < nsamples_AC_OFC - 1; ++j1) {
298 for (int j2 = j1 + 1; j2 < nsamples_AC_OFC; j2++) {
299 int index =
300 j1 * nsamples_AC_OFC - j1 * (j1 + 1) / 2 + j2 - (j1 + 1);
301 float Rij = 0;
302 for (int k = 0; k < nsamples_shape; ++k) {
303 if ((j2 - j1 + k) >= 0 && (j2 - j1 + k) < nsamples_shape) {
304 int ibunch = 0;
305 if ((j1 + m_firstSample + ihecshift - k) % m_deltaBunch == 0)
306 ibunch = 1;
307 Rij += Shape[k] * Shape[j2 - j1 + k] * ibunch;
308 }
309 }
310 vTerms[nsize_tot + index] = fSigma2 * Rij;
311 }
312 }
313 ATH_MSG_DEBUG(chid.get_identifier32().get_compact()
314 << ") vTerms[mid] (" << vTerms[vTerms.size()/2] << ") ");
315
316 // 3rd term : RMS of pileup per samples (multiplied by fSigma2)
317 for (int j1 = 0; j1 < nsamples_AC_OFC; j1++) {
318 float Rms2i = 0;
319 for (int k = 0; k < nsamples_shape; ++k) {
320 int ibunch = 0;
321 if ((j1 + m_firstSample + ihecshift - k) % m_deltaBunch == 0)
322 ibunch = 1;
323 Rms2i += pow(Shape[k], 2) * ibunch;
324 }
325 vTerms[2 * nsize_tot + j1] = fSigma2 * Rms2i;
326 }
327 ATH_MSG_DEBUG(chid.get_identifier32().get_compact()
328 << ") vTerms[last] (" << vTerms[vTerms.size()-1] << ") ");
329
330
331 // storage
332 larAutoCorrTotal->set(hid, igain, vTerms);
333
334 } //(loop on gains)
335
336 } else // unconnected
337 for (unsigned int igain = 0; igain < m_nGains; igain++) {
338 unsigned nsize_tot = (m_Nsamples - 1) * (m_Nsamples) + m_Nsamples;
339 std::vector<float> empty(nsize_tot, 0.);
340 larAutoCorrTotal->set(hid, igain, empty);
341 }
342 }
343
344 ATH_MSG_INFO("LArAutoCorrTotal Ncell " << count);
345 ATH_MSG_INFO("LArAutoCorrTotal Ncell * Ngain " << count3);
346 ATH_MSG_INFO("LArAutoCorrTotal Nconnected " << count2);
347
348 ATH_MSG_INFO("LArAutoCorrTotal record with key" << m_LArAutoCorrTotalObjKey);
349
350 ATH_CHECK(writeHandle.record(std::move(larAutoCorrTotal)));
351
352
353 return StatusCode::SUCCESS;
354}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
static const Attributes_t empty
constexpr int pow(int base, int exp) noexcept
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
std::string show_to_string(Identifier id, const IdContext *context=0, char sep='.') const
or provide the printout in string form
This class defines the interface for accessing AutoCorrelation parameters for each channel @stereotyp...
LArVectorProxy AutoCorrRef_t
virtual AutoCorrRef_t autoCorr(const HWIdentifier &CellID, int gain) const =0
virtual const float & minBiasRMS(const HWIdentifier &id) const =0
access to RMS of E in minimum bias events index by Identifier
virtual const float & noise(const HWIdentifier &id, int gain) const =0
virtual float pedestalRMS(const HWIdentifier &id, int gain) const =0
access to RMS of Pedestal index by Identifier, and gain setting
LArVectorProxy ShapeRef_t
This class defines the interface for accessing Shape (Nsample variable, Dt = 25 ns fixed) @stereotype...
Definition ILArShape.h:26
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
virtual const float & FSAMPL(const HWIdentifier &id) const =0
This is a "hash" representation of an Identifier.
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
Definition LArADC2MeV.h:32
SG::WriteCondHandleKey< LArAutoCorrTotal > m_LArAutoCorrTotalObjKey
SG::ReadCondHandleKey< LArOnOffIdMapping > m_LArOnOffIdMappingObjKey
SG::ReadCondHandleKey< ILArShape > m_LArShapeObjKey
SG::ReadCondHandleKey< ILArPedestal > m_LArPedestalObjKey
SG::ReadCondHandleKey< ILArMinBias > m_LArMinBiasObjKey
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadCondHandleKey< ILArAutoCorr > m_LArAutoCorrObjKey
virtual ~LArAutoCorrTotalCondAlg() override
SG::ReadCondHandleKey< LArADC2MeV > m_LArADC2MeVObjKey
SG::ReadCondHandleKey< ILArNoise > m_LArNoiseObjKey
SG::ReadCondHandleKey< ILArfSampl > m_LArfSamplObjKey
LArAutoCorrTotalCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode initialize() override
Identifier cnvToIdentifier(const HWIdentifier &sid) const
create an Identifier from a HWIdentifier (inline)
bool isOnlineConnected(const HWIdentifier &sid) const
Test whether a HWIdentifier is connected of not (inline)
Helper for the Liquid Argon Calorimeter cell identifiers.
id_range channel_range() const
IdentifierHash channel_Hash(HWIdentifier channelId) const
Create channel_hash from channel_Id.
std::string channel_name(const HWIdentifier id) const
Return a string corresponding to a feedthrough name given an identifier.
virtual bool isHECchannel(const HWIdentifier id) const =0
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
Definition index.py:1