ATLAS Offline Software
Loading...
Searching...
No Matches
LArR4ElecCalibCalculator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <chai/Container.h>
8#include <chai/Database.h>
9#include <chai/Iov.h>
10#include <chai/Log.h>
11#include <chai/PayloadSpec.h>
12#include <chai/Types.h>
13
15#include "CaloDetDescr/CaloDetDescrElement.h"
24
25namespace {
26
27// Method to convert coral::Blob to BlobData
28chai::BlobData vecToBlobData(const std::vector<float>& input) {
29 const std::size_t size = input.size() * sizeof(float);
30 const void* inPtr = input.data();
31 // Create vector and copy data
32 std::vector<uint8_t> bytes(size);
33 if (size > 0) {
34 memcpy(bytes.data(), inPtr, size);
35 }
36
37 return chai::BlobData(std::move(bytes));
38}
39} // namespace
40
42
43 ATH_CHECK(detStore()->retrieve(m_onlineHelper, "LArOnlineID"));
44 ATH_CHECK(detStore()->retrieve(m_caloCellID, "CaloCell_ID"));
45
46 ATH_CHECK(m_cablingKey.initialize());
47
48 ATH_CHECK(m_lAruA2MeVKey.initialize());
49 ATH_CHECK(m_lArDAC2uAKey.initialize());
50 ATH_CHECK(m_mcSym.initialize());
51
52 ATH_CHECK(m_caloMgrKey.initialize());
53
54 return StatusCode::SUCCESS;
55}
56
57// ********************** EXECUTE ****************************
58StatusCode LArR4ElecCalibCalculator::execute(const EventContext& /*ctx*/) {
59 return StatusCode::SUCCESS;
60}
61
62// ********************** FINALIZE ****************************
64
65 // Values below are mA, in the lower gain
66 const std::map<CaloSampling::CaloSample, float> dynRange{
67 {CaloSampling::PreSamplerB, 2},
68 {CaloSampling::EMB1, 2},
69 {CaloSampling::EMB2, 10},
70 {CaloSampling::EMB3, 10},
71 {CaloSampling::PreSamplerE, 2},
72 {CaloSampling::EME1, 2},
73 {CaloSampling::EME2, 10},
74 {CaloSampling::EME3, 10},
75 {CaloSampling::HEC0, 2},
76 {CaloSampling::HEC1, 2},
77 {CaloSampling::HEC2, 2},
78 {CaloSampling::HEC3, 2,},
79 {CaloSampling::FCAL0, 10},
80 {CaloSampling::FCAL1, 10},
81 {CaloSampling::FCAL2, 10},
82 };
83
84 // Values are in ADC counts in HIGH gain
85 // Structure: maps of samplings < vector <eta-boundary,value> >
86 const std::map<CaloSampling::CaloSample, std::vector<std::pair<float, float> > > noiseMap{
87 {CaloSampling::PreSamplerB, {{5, 3.2}}},
88 {CaloSampling::EMB1, {{0.8, 1.8}, {5, 2.1}}},
89 {CaloSampling::EMB2, {{0.8, 1.4}, {5, 1.7}}},
90 {CaloSampling::EMB3, {{0.8, 1.4}, {5, 1.7}}},
91 {CaloSampling::PreSamplerE, {{5, 3.5}}},
92 {CaloSampling::EME1, {{2, 2.7}, {5, 2.9}}},
93 {CaloSampling::EME2, {{2, 1.3}, {5, 1.5}}},
94 {CaloSampling::EME3, {{2, 1.3}, {5, 1.5}}},
95 {CaloSampling::HEC0, {{5, 3.1}}},
96 {CaloSampling::HEC1, {{5, 3.1}}},
97 {CaloSampling::HEC2, {{5, 2.1}}},
98 {CaloSampling::HEC3, {{5, 2.1}}},
99
100 {CaloSampling::FCAL0, {{5, 4.3}}},
101 {CaloSampling::FCAL1, {{5, 4.6}}},
102 {CaloSampling::FCAL2, {{5, 4.5}}},
103 };
104
109
111
112 std::unique_ptr<LArRampMC> rampMC = std::make_unique<LArRampMC>();
113 ATH_CHECK(rampMC->setGroupingType("Single", msg()));
114 ATH_CHECK(rampMC->initialize());
115
116 const auto& symIDs = larMCsymHdl->symIds();
117
118 const int nUsableBits = int(pow(2, m_nADCBits) * 3 / 4.);
119
120
121 //Calculate the R4 ramps (ADC2DAC) values, store them in run 1/2/3 style objects (LArRampMC)
122 //Can be stored in COOL-reference POOL files if the RegistrationSvc and OutptuConditionsAlg are scheduled in job-config
123 for (const HWIdentifier hwid : symIDs) {
124 const Identifier id = (*cablingHdl)->cnvToIdentifier(hwid);
125 const auto sampling = (CaloSampling::CaloSample)m_caloCellID->calo_sample(id);
126 const double mARange = dynRange.find(sampling)->second;
127 const double uAperADC = 1000 * mARange / nUsableBits;
128 const double dac2uA = (*DAC2uAHdl)->DAC2UA(hwid); // uA/DAC
129 const double ADC2DAC = uAperADC / dac2uA;
130
131 // For cross-check:
132 const double ADC2MeV = ADC2DAC * dac2uA * uA2MeVHdl->UA2MEV(hwid);
133 const double adc2uA = ADC2DAC * dac2uA;
134 ATH_MSG_DEBUG("sub_calo=" << m_caloCellID->sub_calo(id) << ", layer " << m_caloCellID->sampling(id) << ", region=" << m_caloCellID->region(id) << ": uA/ADC "
135 << uAperADC << ", ADC/mA " << nUsableBits / mARange << ", DAC2uA " << dac2uA << ", Ramp " << ADC2DAC << ", ADC2MeV=" << ADC2MeV
136 << ", ADC2DAC*dac2uA=" << adc2uA);
137
138 std::vector<float> vRamp;
139 vRamp.push_back(0); // ignore intercept for MC
140 vRamp.push_back(ADC2DAC);
141
142 rampMC->set(hwid, CaloGain::LARMEDIUMGAIN, vRamp);
143 // re-use the same short vector for higher gain
144 vRamp[1] /= 23.0; // HIGH gain =23* lower gain
145 rampMC->set(hwid, CaloGain::LARHIGHGAIN, vRamp);
146 }
147
148 // With the backward compatible MT-migration, the LArRampMC object became
149 // "write only". It is stored in the database but on read-back turned into a
150 // LArRampSym object. Only the latter can be used
151 std::unique_ptr<LArRampSym> rampSym = std::make_unique<LArRampSym>(*larMCsymHdl, rampMC.get());
152
153 StatusCode sc = detStore()->record(std::move(rampMC), m_keyoutput);
154 if (sc.isFailure()) {
155 ATH_MSG_ERROR("Failed to record LArRampSym object with key " << m_keyoutput);
156 }
158 if (sc.isFailure()) {
159 ATH_MSG_ERROR("Failed to symlink LArRampMC to ILArRamp base-class");
160 }
161
162 m_keyoutput += "Sym";
163 sc = detStore()->record(std::move(rampSym), m_keyoutput);
164 if (sc.isFailure()) {
165 ATH_MSG_ERROR("Failed to record LArRampSym object with key " << m_keyoutput);
166 }
168 if (sc.isFailure()) {
169 ATH_MSG_ERROR("Failed to symlink LArRampSym to ILArRamp base-class");
170 }
171
172
173 //Pedestal: Use only one value for all channels in the MC case
174 //Again, create a run 1/2/3 style LArPedestalMC object that can be store in a COOL-referenced POOL file
175 std::vector<float> pedVec, pedRMSVec;
176 pedVec.push_back(m_pedestalValue.value());
177 pedRMSVec.push_back(m_pedestalRMS.value());
178 std::unique_ptr<LArPedestalMC> pedPtr = std::make_unique<LArPedestalMC>();
179 pedPtr->set(pedVec, pedRMSVec);
180 ATH_CHECK(detStore()->record(std::move(pedPtr), m_pedkeyoutput));
181
182
183
184 //Noise: Fill a run 1/2/3-style LArNoiseMC object that can be store in a COOL-referenced POOL file
185 std::unique_ptr<LArNoiseMC> noisePtr = std::make_unique<LArNoiseMC>();
186 ATH_CHECK(noisePtr->setGroupingType("Single", msg()));
187 ATH_CHECK(noisePtr->initialize());
188
190 for (const HWIdentifier hwid : symIDs) {
191 const Identifier id = (*cablingHdl)->cnvToIdentifier(hwid);
192 const auto sampling = (CaloSampling::CaloSample)m_caloCellID->calo_sample(id);
193 const CaloDetDescrElement* dde = caloDDM->get_element(id);
194 const float eta = dde->eta_raw();
195
196 const auto& pairs = noiseMap.find(sampling)->second;
197 float noise = -1;
198 for (auto [e, n] : pairs) {
199 if (eta < e) {
200 noise = n;
201 ATH_MSG_DEBUG("Sampling: " << sampling << ", eta=" << eta << ", noise=" << noise);
202 break;
203 }
204 }
205 noisePtr->set(hwid, CaloGain::LARHIGHGAIN, noise);
206 noisePtr->set(hwid, CaloGain::LARMEDIUMGAIN, noise / 23.0);
207 } // end loop over sym-ids
208
209 std::unique_ptr<LArNoiseSym> noiseSym = std::make_unique<LArNoiseSym>(*larMCsymHdl, noisePtr.get());
210
211 ATH_CHECK(detStore()->record(std::move(noisePtr), "LArNoise"));
213 if (sc.isFailure()) {
214 ATH_MSG_ERROR("Failed to symlink LArNoiseMC to ILArNoise base-class");
215 }
216
217 sc = detStore()->record(std::move(noiseSym), "LArNoiseSym");
218 if (sc.isFailure()) {
219 ATH_MSG_ERROR("Failed to record LArNoiseSym object with key " << m_keyoutput);
220 }
222 if (sc.isFailure()) {
223 ATH_MSG_ERROR("Failed to symlink LArNoiseSym to ILArNoise base-class");
224 }
225
226
227
228
229 //If a CREST database is also given, we store the calibration constants in CREST
230 //In this case, the values are stored 'inline' in a Blob, so it can be read back into LArXYZFlat classes that are
231 //used for data-processing also in run 2 and 3.
232 if (!m_crestDBStr.value().empty()) {
233
234 std::vector<float> rampsHG, rampsMG, noiseHG, noiseMG, ped, pedRMS;
235 const LArRampSym* rampsIn = nullptr;
236 ATH_CHECK(detStore()->retrieve(rampsIn, "LArRampSym"));
237 const LArNoiseSym* noiseIn = nullptr;
238 ATH_CHECK(detStore()->retrieve(noiseIn, "LArNoiseSym"));
239
240 const unsigned int hashmax = m_onlineHelper->channelHashMax();
241
242 //Store only one pedestal value for all channels:
243 ped.push_back((m_pedestalValue.value()));
244 pedRMS.push_back(m_pedestalRMS.value());
245 for (unsigned idx = 0; idx < hashmax; ++idx) {
246 IdentifierHash hIdx(idx);
247 HWIdentifier hwid = m_onlineHelper->channel_Id(hIdx);
248 if (!(*cablingHdl)->isOnlineConnectedFromHash(hIdx)) {
249 rampsHG.push_back(0);
250 rampsHG.push_back(-999);
251 rampsMG.push_back(0);
252 rampsMG.push_back(-999);
253 noiseHG.push_back(-999);
254 noiseMG.push_back(-999);
255 } else {
256 const auto rampvecHG = rampsIn->ADC2DAC(hwid, CaloGain::LARHIGHGAIN);
257 rampsHG.push_back(rampvecHG[0]);
258 rampsHG.push_back(rampvecHG[1]);
259 const auto rampvecMG = rampsIn->ADC2DAC(hwid, CaloGain::LARMEDIUMGAIN);
260 rampsMG.push_back(rampvecMG[0]);
261 rampsMG.push_back(rampvecMG[1]);
262
263 noiseHG.push_back(noiseIn->noise(hwid, CaloGain::LARHIGHGAIN));
264 noiseMG.push_back(noiseIn->noise(hwid, CaloGain::LARMEDIUMGAIN));
265 }
266 }
267 chai::Database db = chai::Database(m_crestDBStr);
268
269 // Pedestals
270 {
271 chai::PayloadSpec spec(chai::FieldSpec({{"Pedestal", chai::Type::Blob}, {"PedestalRMS", chai::Type::Blob}, {"version", chai::Type::Uint32}}),
272
273 chai::ChannelSpec({
274 {0, "HIGHGain"},
275 {1, "MEDGain"},
276 }));
277
278 auto tag = db.createTag("LARElecCalibPedestal-R4-00", "Pedestal of FEB 2", spec, chai::Tag::IovType::RunNumberLumiBlock, "crest-json-single-iov",
279 chai::Tag::Synchronization::All, chai::Tag::Status::Unlocked);
280
281 chai::Container container = tag->buildContainer();
282 for (size_t g = 0; g < 2; ++g) {
283 container[g].push(std::move(vecToBlobData(ped)));
284 container[g].push(std::move(vecToBlobData(pedRMS)));
285 container[g].push(0); // version number
286 }
287 tag->addPayload(container, 0);
288 }
289 // Ramps
290 {
291 chai::PayloadSpec spec(chai::FieldSpec({{"RampVec", chai::Type::Blob}, {"nPoints", chai::Type::Uint32}, {"version", chai::Type::Uint32}}),
292
293 chai::ChannelSpec({
294 {0, "HIGHGain"},
295 {1, "MEDGain"},
296 }));
297
298 auto tag = db.createTag("LARElecCalibRamp-R4-00", "Electronic gain of FEB 2", spec, chai::Tag::IovType::RunNumberLumiBlock, "crest-json-single-iov",
299 chai::Tag::Synchronization::All, chai::Tag::Status::Unlocked);
300
301 chai::Container container = tag->buildContainer();
302 container[0].push(std::move(vecToBlobData(rampsHG)));
303 container[0].push(2); // number of points (intercept,gradient)
304 container[0].push(0); // version number
305
306 container[1].push(std::move(vecToBlobData(rampsMG)));
307 container[1].push(2); // number of points (intercept,gradient)
308 container[1].push(0); // version number
309
310 tag->addPayload(container, 0);
311 }
312 // Noise
313 {
314 chai::PayloadSpec spec(chai::FieldSpec({{"Noise", chai::Type::Blob}, {"version", chai::Type::Uint32}}),
315
316 chai::ChannelSpec({
317 {0, "HIGHGain"},
318 {1, "MEDGain"},
319 }));
320
321 auto tag = db.createTag("LARElecCalibNoise-R4-00", "Noise of FEB 2 (in ADC counts)", spec, chai::Tag::IovType::RunNumberLumiBlock,
322 "crest-json-single-iov", chai::Tag::Synchronization::All, chai::Tag::Status::Unlocked);
323
324 chai::Container container = tag->buildContainer();
325
326 container[0].push(std::move(vecToBlobData(noiseHG)));
327 container[0].push(0); // version number
328
329 container[1].push(std::move(vecToBlobData(noiseMG)));
330 container[1].push(0); // version number
331 tag->addPayload(container, 0);
332 }
333 }
334 ATH_MSG_INFO("LArR4RampCalculator has finished.");
335 return StatusCode::SUCCESS;
336} // end finalize-method.
Scalar eta() const
pseudorapidity method
#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 Double_t sc
size_t size() const
Number of registered mappings.
const ServiceHandle< StoreGateSvc > & detStore() const
This class groups all DetDescr information related to a CaloCell.
This is a "hash" representation of an Identifier.
virtual const float & noise(const HWIdentifier &hwid, int gain) const override
SG::ReadCondHandleKey< LArMCSym > m_mcSym
Gaudi::Property< float > m_pedestalRMS
SG::ReadCondHandleKey< ILArDAC2uA > m_lArDAC2uAKey
SG::ReadCondHandleKey< ILAruA2MeV > m_lAruA2MeVKey
Gaudi::Property< std::string > m_keyoutput
Gaudi::Property< std::string > m_pedkeyoutput
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Gaudi::Property< float > m_pedestalValue
virtual StatusCode initialize() override
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
virtual StatusCode stop() override
Gaudi::Property< std::string > m_crestDBStr
virtual StatusCode execute(const EventContext &ctx) override
Execute method.
virtual RampRef_t ADC2DAC(const HWIdentifier &CellID, int gain) const override
@ LARMEDIUMGAIN
Definition CaloGain.h:18
@ LARHIGHGAIN
Definition CaloGain.h:18