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 auto rangeIt = dynRange.find(sampling);
127 if (rangeIt == dynRange.end())[[unlikely]]{
128 ATH_MSG_WARNING("LArR4ElecCalibCalculator::stop: sampling not found in dynRange.");
129 continue;
130 }
131 const double mARange = rangeIt->second;
132 const double uAperADC = 1000 * mARange / nUsableBits;
133 const double dac2uA = (*DAC2uAHdl)->DAC2UA(hwid); // uA/DAC
134 const double ADC2DAC = uAperADC / dac2uA;
135
136 // For cross-check:
137 const double ADC2MeV = ADC2DAC * dac2uA * uA2MeVHdl->UA2MEV(hwid);
138 const double adc2uA = ADC2DAC * dac2uA;
139 ATH_MSG_DEBUG("sub_calo=" << m_caloCellID->sub_calo(id) << ", layer " << m_caloCellID->sampling(id) << ", region=" << m_caloCellID->region(id) << ": uA/ADC "
140 << uAperADC << ", ADC/mA " << nUsableBits / mARange << ", DAC2uA " << dac2uA << ", Ramp " << ADC2DAC << ", ADC2MeV=" << ADC2MeV
141 << ", ADC2DAC*dac2uA=" << adc2uA);
142
143 std::vector<float> vRamp;
144 vRamp.push_back(0); // ignore intercept for MC
145 vRamp.push_back(ADC2DAC);
146
147 rampMC->set(hwid, CaloGain::LARMEDIUMGAIN, vRamp);
148 // re-use the same short vector for higher gain
149 vRamp[1] /= 23.0; // HIGH gain =23* lower gain
150 rampMC->set(hwid, CaloGain::LARHIGHGAIN, vRamp);
151 }
152
153 // With the backward compatible MT-migration, the LArRampMC object became
154 // "write only". It is stored in the database but on read-back turned into a
155 // LArRampSym object. Only the latter can be used
156 std::unique_ptr<LArRampSym> rampSym = std::make_unique<LArRampSym>(*larMCsymHdl, rampMC.get());
157
158 StatusCode sc = detStore()->record(std::move(rampMC), m_keyoutput);
159 if (sc.isFailure()) {
160 ATH_MSG_ERROR("Failed to record LArRampSym object with key " << m_keyoutput);
161 }
162
163 m_keyoutput += "Sym";
164 sc = detStore()->record(std::move(rampSym), m_keyoutput);
165 if (sc.isFailure()) {
166 ATH_MSG_ERROR("Failed to record LArRampSym object with key " << m_keyoutput);
167 }
168
169
170 //Pedestal: Use only one value for all channels in the MC case
171 //Again, create a run 1/2/3 style LArPedestalMC object that can be store in a COOL-referenced POOL file
172 std::vector<float> pedVec, pedRMSVec;
173 pedVec.push_back(m_pedestalValue.value());
174 pedRMSVec.push_back(m_pedestalRMS.value());
175 std::unique_ptr<LArPedestalMC> pedPtr = std::make_unique<LArPedestalMC>();
176 pedPtr->set(pedVec, pedRMSVec);
177 ATH_CHECK(detStore()->record(std::move(pedPtr), m_pedkeyoutput));
178
179
180
181 //Noise: Fill a run 1/2/3-style LArNoiseMC object that can be store in a COOL-referenced POOL file
182 std::unique_ptr<LArNoiseMC> noisePtr = std::make_unique<LArNoiseMC>();
183 ATH_CHECK(noisePtr->setGroupingType("Single", msg()));
184 ATH_CHECK(noisePtr->initialize());
185
187 for (const HWIdentifier hwid : symIDs) {
188 const Identifier id = (*cablingHdl)->cnvToIdentifier(hwid);
189 const auto sampling = (CaloSampling::CaloSample)m_caloCellID->calo_sample(id);
190 const CaloDetDescrElement* dde = caloDDM->get_element(id);
191 const float eta = dde->eta_raw();
192
193 const auto& pairs = noiseMap.find(sampling)->second;
194 float noise = -1;
195 for (auto [e, n] : pairs) {
196 if (eta < e) {
197 noise = n;
198 ATH_MSG_DEBUG("Sampling: " << sampling << ", eta=" << eta << ", noise=" << noise);
199 break;
200 }
201 }
202 noisePtr->set(hwid, CaloGain::LARHIGHGAIN, noise);
203 noisePtr->set(hwid, CaloGain::LARMEDIUMGAIN, noise / 23.0);
204 } // end loop over sym-ids
205
206 std::unique_ptr<LArNoiseSym> noiseSym = std::make_unique<LArNoiseSym>(*larMCsymHdl, noisePtr.get());
207
208 ATH_CHECK(detStore()->record(std::move(noisePtr), "LArNoise"));
209
210 sc = detStore()->record(std::move(noiseSym), "LArNoiseSym");
211 if (sc.isFailure()) {
212 ATH_MSG_ERROR("Failed to record LArNoiseSym object with key " << m_keyoutput);
213 }
214
215
216 //If a CREST database is also given, we store the calibration constants in CREST
217 //In this case, the values are stored 'inline' in a Blob, so it can be read back into LArXYZFlat classes that are
218 //used for data-processing also in run 2 and 3.
219 if (!m_crestDBStr.value().empty()) {
220
221 chai::Tag::Metadata chaiMD{.iovType=chai::Tag::IovType::RunNumberLumiBlock,
222 .objectType="crest-json-single-iov",
223 .synchronization=chai::Tag::Synchronization::All,
224 .status=chai::Tag::Status::Unlocked,
225 .nodeDescription = chai::Tag::buildNodeDescription(chai::Tag::IovType::RunNumberLumiBlock, "CondAttrListCollection", 1238547719u)
226 };
227
228 std::vector<float> rampsHG, rampsMG, noiseHG, noiseMG, ped, pedRMS;
229 const LArRampSym* rampsIn = nullptr;
230 ATH_CHECK(detStore()->retrieve(rampsIn, "LArRampSym"));
231 const LArNoiseSym* noiseIn = nullptr;
232 ATH_CHECK(detStore()->retrieve(noiseIn, "LArNoiseSym"));
233
234 const unsigned int hashmax = m_onlineHelper->channelHashMax();
235
236 //Store only one pedestal value for all channels:
237 ped.push_back((m_pedestalValue.value()));
238 pedRMS.push_back(m_pedestalRMS.value());
239 for (unsigned idx = 0; idx < hashmax; ++idx) {
240 IdentifierHash hIdx(idx);
241 HWIdentifier hwid = m_onlineHelper->channel_Id(hIdx);
242 if (!(*cablingHdl)->isOnlineConnectedFromHash(hIdx)) {
243 rampsHG.push_back(0);
244 rampsHG.push_back(-999);
245 rampsMG.push_back(0);
246 rampsMG.push_back(-999);
247 noiseHG.push_back(-999);
248 noiseMG.push_back(-999);
249 } else {
250 const auto rampvecHG = rampsIn->ADC2DAC(hwid, CaloGain::LARHIGHGAIN);
251 rampsHG.push_back(rampvecHG[0]);
252 rampsHG.push_back(rampvecHG[1]);
253 const auto rampvecMG = rampsIn->ADC2DAC(hwid, CaloGain::LARMEDIUMGAIN);
254 rampsMG.push_back(rampvecMG[0]);
255 rampsMG.push_back(rampvecMG[1]);
256
257 noiseHG.push_back(noiseIn->noise(hwid, CaloGain::LARHIGHGAIN));
258 noiseMG.push_back(noiseIn->noise(hwid, CaloGain::LARMEDIUMGAIN));
259 }
260 }
261 chai::Database db = chai::Database(m_crestDBStr);
262 auto gt=db.createGlobalTag("GlobalTestTag", "test", "MC");
263
264 // Pedestals
265 {
266 chai::PayloadSpec spec(chai::FieldSpec({{"Pedestal", chai::Type::Blob}, {"PedestalRMS", chai::Type::Blob}, {"version", chai::Type::UInt32}}),
267
268 chai::ChannelSpec({
269 {0, "HIGHGain"},
270 {1, "MEDGain"},
271 }));
272
273 auto tag = db.createTag("LARElecCalibPedestal-R4-00", "Pedestal of FEB 2", spec, chaiMD);
274 gt->addTag("/LAR/ElecCalibMC/Pedestal","LARElecCalibPedestal-R4-00");
275
276 chai::Container container = tag->buildContainer();
277 for (size_t g = 0; g < 2; ++g) {
278 container[g].push(std::move(vecToBlobData(ped)));
279 container[g].push(std::move(vecToBlobData(pedRMS)));
280 container[g].push(0); // version number
281 }
282 tag->addPayload(container, 0);
283 }
284 // Ramps
285 {
286 chai::PayloadSpec spec(chai::FieldSpec({{"RampVec", chai::Type::Blob}, {"nPoints", chai::Type::UInt32}, {"version", chai::Type::UInt32}}),
287
288 chai::ChannelSpec({
289 {0, "HIGHGain"},
290 {1, "MEDGain"},
291 }));
292
293 auto tag = db.createTag("LARElecCalibMCRamp-R4-00", "Electronic gain of FEB 2", spec, chaiMD);
294 gt->addTag("/LAR/ElecCalibMC/Ramp", "LARElecCalibMCRamp-R4-00");
295
296 chai::Container container = tag->buildContainer();
297 container[0].push(std::move(vecToBlobData(rampsHG)));
298 container[0].push(2); // number of points (intercept,gradient)
299 container[0].push(0); // version number
300
301 container[1].push(std::move(vecToBlobData(rampsMG)));
302 container[1].push(2); // number of points (intercept,gradient)
303 container[1].push(0); // version number
304
305 tag->addPayload(container, 0);
306 }
307 // Noise
308 {
309 chai::PayloadSpec spec(chai::FieldSpec({{"Noise", chai::Type::Blob}, {"version", chai::Type::UInt32}}),
310
311 chai::ChannelSpec({
312 {0, "HIGHGain"},
313 {1, "MEDGain"},
314 }));
315
316 auto tag = db.createTag("LARElecCalibMCNoise-R4-00", "Noise of FEB 2 (in ADC counts)", spec, chaiMD);
317 gt->addTag("/LAR/ElecCalibMC/Noise","LARElecCalibMCNoise-R4-00");
318
319 chai::Container container = tag->buildContainer();
320
321 container[0].push(std::move(vecToBlobData(noiseHG)));
322 container[0].push(0); // version number
323
324 container[1].push(std::move(vecToBlobData(noiseMG)));
325 container[1].push(0); // version number
326 tag->addPayload(container, 0);
327 }
328 }
329 ATH_MSG_INFO("LArR4RampCalculator has finished.");
330 return StatusCode::SUCCESS;
331} // end finalize-method.
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(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
#define unlikely(x)