ATLAS Offline Software
Loading...
Searching...
No Matches
LArADC2MeVCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "LArADC2MeVCondAlg.h"
8#include <memory>
9#include "GaudiKernel/EventIDRange.h"
10
12
13
15
16 //Identifier helper:
17 if (m_isSuperCell) {
18 m_nGains=1;
19 const LArOnline_SuperCellID* scidhelper;
20 ATH_CHECK(detStore()->retrieve(scidhelper,"LArOnline_SuperCellID"));
21 m_larOnlineID=scidhelper; //cast to base-class
22 }
23 else {//regular cells
24 const LArOnlineID* idhelper;
25 ATH_CHECK(detStore()->retrieve(idhelper,"LArOnlineID"));
26 m_larOnlineID=idhelper; //cast to base-class
27 }
28
29 if (!m_larOnlineID) {
30 ATH_MSG_ERROR("Failed to obtain LArOnlineID");
31 return StatusCode::FAILURE;
32 }
33
34 // Read handle for cabling
35 ATH_CHECK(m_cablingKey.initialize());
36
37 // Read handles for input conditions
38 ATH_CHECK(m_lAruA2MeVKey.initialize());
39 ATH_CHECK(m_lArDAC2uAKey.initialize());
40 ATH_CHECK(m_lArRampKey.initialize());
41
42 //The following two are optional (not used for MC and/or SuperCells)
43 if (!m_lArMphysOverMcalKey.key().empty()) {
44 ATH_CHECK(m_lArMphysOverMcalKey.initialize());
45 }
46 if (!m_lArHVScaleCorrKey.key().empty()) {
47 ATH_CHECK(m_lArHVScaleCorrKey.initialize());
48 }
49
50 //Write handle
51 ATH_CHECK( m_ADC2MeVKey.initialize() );
52
54
55 return StatusCode::SUCCESS;
56}
57
58
59StatusCode LArADC2MeVCondAlg::execute(const EventContext& ctx) const{
60
61 //Set up write handle
63
64 if (writeHandle.isValid()) {
65 ATH_MSG_DEBUG("Found valid write handle");
66 return StatusCode::SUCCESS;
67 }
68
69 //Cabling (should have an ~infinte IOV)
71 const LArOnOffIdMapping* cabling{*cablingHdl};
72 writeHandle.addDependency(cablingHdl);
73
74 //Get pointers to input data and determine validity range
76 const ILAruA2MeV* laruA2MeV{*uA2MeVHdl};
77 writeHandle.addDependency(uA2MeVHdl);
78
80 const ILArDAC2uA* larDAC2uA{*DAC2uAHdl};
81 writeHandle.addDependency(DAC2uAHdl);
82
84 const ILArRamp* larRamp{*rampHdl};
85 writeHandle.addDependency(rampHdl);
86
87 // retrieve LArFebConfig if needed
88 const LArFebConfig *febConfig=nullptr;
91 febConfig = *configHdl;
92 if (febConfig==nullptr) {
93 ATH_MSG_ERROR( "Unable to retrieve LArFebConfig with key " << m_febConfigKey.key());
94 return StatusCode::FAILURE;
95 }
96 writeHandle.addDependency(configHdl);
97 }
98 //The following two are optional (not used for MC and/or SuperCells)
99 const ILArMphysOverMcal* larmPhysOverMCal=nullptr;
100 if (!m_lArMphysOverMcalKey.key().empty()) {
102 larmPhysOverMCal=*mphysOverMcalHdl;
103 writeHandle.addDependency(mphysOverMcalHdl);
104 }//end if have MphysOverMcal
105
106 const ILArHVScaleCorr* larHVScaleCorr=nullptr;
107 if (!m_lArHVScaleCorrKey.key().empty()) {
109 larHVScaleCorr=*HVScaleCorrHdl;
110 writeHandle.addDependency(HVScaleCorrHdl);
111 }//end if have HVScaleCorr
112
113
114 ATH_MSG_INFO("IOV of ADC2MeV object is " << writeHandle.getRange());
115
116 //Sanity & debugging conters:
117 unsigned nNouA2MeV=0;
118 unsigned nNoDAC2uA=0;
119 unsigned nNoMphysOverMcal=0;
120 unsigned nNoRamp=0;
121 unsigned nNoHVScaleCorr=0;
122
123 //'Guess' the degree of the ramp polynom by searching the first filled ramp
124 //The value should be all the same for all cells & gains and in reality always 2
125 unsigned rampPolyDeg=0;
126 std::vector<HWIdentifier>::const_iterator it = m_larOnlineID->channel_begin();
127 std::vector<HWIdentifier>::const_iterator it_e= m_larOnlineID->channel_end();
128 while (rampPolyDeg==0 && it!=it_e) {
129 size_t gain=0;
130 while ( rampPolyDeg==0 && gain < m_nGains) {
131 rampPolyDeg=larRamp->ADC2DAC(*it,gain).size();
132 ++gain;
133 }
134 ++it;
135 }
136
137 ATH_MSG_INFO("Working with a ramp polynom of degree " << rampPolyDeg);
138 //Create output object
139 std::unique_ptr<LArADC2MeV> lArADC2MeVObj=std::make_unique<LArADC2MeV>(m_larOnlineID,cabling,m_nGains,rampPolyDeg);
140
141 std::vector<float> ADC2MeV; //output data, overwritten in each loop iteration (avoid re-allocation)
142
143 for (const HWIdentifier chid : m_larOnlineID->channel_range()) {
144 const IdentifierHash hid=m_larOnlineID->channel_Hash(chid);
145
146 //Check if connected:
147 if (cabling->isOnlineConnectedFromHash(hid)) {
148 //uA2MeV and DAC2uA are gain-less and always needed:
149 const float& uA2MeV=laruA2MeV->UA2MEV(chid);
150 if (uA2MeV == (float)ILAruA2MeV::ERRORCODE) {
151 ++nNouA2MeV;
152 continue;
153 }
154
155 const float& DAC2uA=larDAC2uA->DAC2UA(chid);
156 if (DAC2uA == (float)ILArDAC2uA::ERRORCODE) {
157 ATH_MSG_ERROR( "No DAC2uA value for for channel " << m_larOnlineID->channel_name(chid) );
158 ++nNoDAC2uA;
159 continue;
160 }
161
162 //First intermediate result
163 float factor=uA2MeV*DAC2uA;
164
165 if (larHVScaleCorr) { //Have HVScaleCorr (remember, it's optional)
166 const float& HVScaleCorr = larHVScaleCorr->HVScaleCorr(chid);
167 if (HVScaleCorr == (float)ILAruA2MeV::ERRORCODE) {
168 //That's a bit unusual but not a disaster, go ahead w/o HV Scale correction
169 ATH_MSG_DEBUG("No HVScaleCorr value for for channel " << m_larOnlineID->channel_name(chid));
170 ++nNoHVScaleCorr;
171 }
172 else {
173 factor*=HVScaleCorr;
174 }
175 }//end if have HVScaleCorr
176
177
178 //The following factors are gain-dependent:
179 std::vector<float> factorGain(m_nGains,factor);
180
181 if (larmPhysOverMCal) {//Have mPhysOverMcal obj (remember, it's optional)
182 for (size_t igain=0;igain<m_nGains;++igain) {
183 const float& mPhysOverMCal=larmPhysOverMCal->MphysOverMcal(chid,igain);
184 if ( mPhysOverMCal==(float)ILArMphysOverMcal::ERRORCODE) {
185 //That's ok, not all channels actually have an MphysOverMcal value
186 ++nNoMphysOverMcal;
187 }
188 else {
189 factorGain[igain]/=mPhysOverMCal;
190 }
191 }//end loop over gains
192 }//end if have MPhysOverMcal
193
194
195 for(unsigned int igain=0;igain<m_nGains;igain++) {
196
197 // ADC2DAC is a vector (polynomial fit of ramps)
198 const ILArRamp::RampRef_t adc2dac = larRamp->ADC2DAC(chid,igain);
199 if (adc2dac.size()<2) {
200 // Some channels can be missing in some configurations,
201 //for example during the electronic calibration processing
202 ATH_MSG_VERBOSE("No Ramp found for channel " << m_larOnlineID->channel_name(chid) << ", gain " << igain);
203 if (igain == 2 && m_larOnlineID->isEMBPS(chid)) {
204 ATH_MSG_VERBOSE("Ignore missing ramp for barrel presampler channel in low gain");
205 }
206 else {
207 ++nNoRamp;
208 }
209 continue;
210 }
211
212 ATH_MSG_VERBOSE(chid.get_identifier32().get_compact()
213 << " gain (" << igain<< ") "
214 << " uA2MeV (" << uA2MeV << ") "
215 << " DAC2uA (" << DAC2uA << ") "
216 << " factorGain (" << factorGain[igain] << ") "
217 << " adc2dac (" << adc2dac[0]<<" " << adc2dac[1]<< ") "
218 );
219
220 ADC2MeV.resize(adc2dac.size());
221
222 //Determine if the intercept is to be used:
223 if (igain==0 || (igain==1 && febConfig && febConfig->lowerGainThreshold(chid)<5)) {
224 //Don't use ramp intercept in high gain and in medium gain if the no high gain is used
225 //(eg lowerGainThreshold is ~zero)
226 ADC2MeV[0]=0;
227 }
228 else {
229 ADC2MeV[0]=factorGain[igain]*adc2dac[0];
230 }
231
232 //Fill remaining polynom terms (usualy only one left)
233 for (size_t i=1;i<adc2dac.size();++i) {
234 ADC2MeV[i]=factorGain[igain]*adc2dac[i];
235 }
236 //Now we are done with this channel and gain. Add it to the output container
237 bool stat=lArADC2MeVObj->set(hid,igain,ADC2MeV);
238 if (!stat) { //fails only if hash or gain are out-of-range
239 ATH_MSG_ERROR( "LArADC2MeV::set fails for gain " << igain << ", hash " << hid );
240 }
241 assert(stat);
242
243 }//end loop over gains
244 }//end if connected
245 }//end loop over readout channels
246
247
248 ATH_CHECK(writeHandle.record(std::move(lArADC2MeVObj)));
249
250 if (nNouA2MeV) ATH_MSG_ERROR("No uA2MeV values for " << nNouA2MeV << " channels");
251 if (nNoDAC2uA) ATH_MSG_ERROR("No DAC2uA values for " << nNoDAC2uA << " channels");
252 if (nNoRamp) {
253 if (m_completeDetector) {
254 ATH_MSG_ERROR("No Ramp values for " << nNoRamp << " channels * gains " );
255 }
256 else {
257 ATH_MSG_WARNING("No Ramp values for " << nNoRamp << " channels * gains " );
258 }
259 }
260 if (nNoMphysOverMcal) ATH_MSG_INFO("No MphysOverMcal values for " << nNoMphysOverMcal << " channels * gains");
261 if (nNoHVScaleCorr) ATH_MSG_WARNING("No HVScaleCorr values for " << nNoHVScaleCorr << " channels");
262
263 if (nNouA2MeV || nNoDAC2uA || (nNoRamp && m_completeDetector))
264 return StatusCode::FAILURE;
265 else
266 return StatusCode::SUCCESS;
267}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const ServiceHandle< StoreGateSvc > & detStore() const
virtual const float & DAC2UA(const HWIdentifier &id) const =0
access to DAC2UA conversion factor index by Identifier, and gain setting
virtual const float & HVScaleCorr(const HWIdentifier &id) const =0
virtual const float & MphysOverMcal(const HWIdentifier &id, int gain) const =0
virtual RampRef_t ADC2DAC(const HWIdentifier &id, int gain) const =0
LArVectorProxy RampRef_t
This class defines the interface for accessing Ramp @stereotype Interface.
Definition ILArRamp.h:31
virtual const float & UA2MEV(const HWIdentifier &id) const =0
This is a "hash" representation of an Identifier.
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
Gaudi::Property< bool > m_isSuperCell
SG::ReadCondHandleKey< LArFebConfig > m_febConfigKey
Gaudi::Property< unsigned > m_nGains
SG::ReadCondHandleKey< ILArHVScaleCorr > m_lArHVScaleCorrKey
SG::ReadCondHandleKey< ILArMphysOverMcal > m_lArMphysOverMcalKey
SG::ReadCondHandleKey< ILArDAC2uA > m_lArDAC2uAKey
SG::WriteCondHandleKey< LArADC2MeV > m_ADC2MeVKey
Gaudi::Property< bool > m_completeDetector
SG::ReadCondHandleKey< ILArRamp > m_lArRampKey
const LArOnlineID_Base * m_larOnlineID
StatusCode execute(const EventContext &ctx) const override
SG::ReadCondHandleKey< ILAruA2MeV > m_lAruA2MeVKey
StatusCode initialize() override
Gaudi::Property< bool > m_useFEBGainThresholds
short lowerGainThreshold(const HWIdentifier &id) const
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED