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