ATLAS Offline Software
LArADC2MeVCondAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 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
39 
40  // Read handles for input conditions
44 
45  //The following two are optional (not used for MC and/or SuperCells)
46  if (!m_lArMphysOverMcalKey.key().empty()) {
48  }
49  if (!m_lArHVScaleCorrKey.key().empty()) {
51  }
52 
53  //Write handle
55 
57 
58  return StatusCode::SUCCESS;
59 }
60 
61 
62 StatusCode 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_DEBUG(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 " << nNouA2MeV << " 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 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
LArADC2MeVCondAlg::m_lArDAC2uAKey
SG::ReadCondHandleKey< ILArDAC2uA > m_lArDAC2uAKey
Definition: LArADC2MeVCondAlg.h:41
LArFebConfig::lowerGainThreshold
short lowerGainThreshold(const HWIdentifier &id) const
Definition: LArFebConfig.h:50
ILArMphysOverMcal::ERRORCODE
@ ERRORCODE
Definition: ILArMphysOverMcal.h:29
LArOnlineID_Base::channel_Hash
IdentifierHash channel_Hash(HWIdentifier channelId) const
Create channel_hash from channel_Id.
Definition: LArOnlineID_Base.cxx:1632
ILArHVScaleCorr
Definition: ILArHVScaleCorr.h:13
LArADC2MeVCondAlg.h
LArADC2MeVCondAlg::m_lArMphysOverMcalKey
SG::ReadCondHandleKey< ILArMphysOverMcal > m_lArMphysOverMcalKey
Definition: LArADC2MeVCondAlg.h:45
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
ILAruA2MeV
Definition: ILAruA2MeV.h:13
CaloCondBlobAlgs_fillNoiseFromASCII.gain
gain
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:110
ReadCellNoiseFromCool.cabling
cabling
Definition: ReadCellNoiseFromCool.py:154
skel.it
it
Definition: skel.GENtoEVGEN.py:396
LArADC2MeVCondAlg::m_ADC2MeVKey
SG::WriteCondHandleKey< LArADC2MeV > m_ADC2MeVKey
Definition: LArADC2MeVCondAlg.h:50
LArADC2MeVCondAlg::~LArADC2MeVCondAlg
~LArADC2MeVCondAlg()
Definition: LArADC2MeVCondAlg.cxx:13
ILArDAC2uA
Definition: ILArDAC2uA.h:13
LArADC2MeVCondAlg::m_useFEBGainThresholds
Gaudi::Property< bool > m_useFEBGainThresholds
Definition: LArADC2MeVCondAlg.h:54
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
HWIdentifier
Definition: HWIdentifier.h:13
LArADC2MeVCondAlg::m_larOnlineID
const LArOnlineID_Base * m_larOnlineID
Definition: LArADC2MeVCondAlg.h:59
LArOnlineID_Base::channel_end
id_iterator channel_end() const
Definition: LArOnlineID_Base.cxx:1927
LArADC2MeVCondAlg::m_lArRampKey
SG::ReadCondHandleKey< ILArRamp > m_lArRampKey
Definition: LArADC2MeVCondAlg.h:42
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::detStore
const ServiceHandle< StoreGateSvc > & detStore() const
The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:95
LArADC2MeVCondAlg::initialize
StatusCode initialize() override
Definition: LArADC2MeVCondAlg.cxx:16
LArFebConfig
Definition: LArFebConfig.h:16
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LArOnlineID_Base::channel_range
id_range channel_range() const
Definition: LArOnlineID_Base.cxx:1932
lumiFormat.i
int i
Definition: lumiFormat.py:85
LArADC2MeVCondAlg::m_nGains
size_t m_nGains
Definition: LArADC2MeVCondAlg.h:58
LArADC2MeVCondAlg::execute
StatusCode execute(const EventContext &ctx) const override
Definition: LArADC2MeVCondAlg.cxx:62
LArADC2MeVCondAlg::m_lArHVScaleCorrKey
SG::ReadCondHandleKey< ILArHVScaleCorr > m_lArHVScaleCorrKey
Definition: LArADC2MeVCondAlg.h:47
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ILArRamp
Definition: ILArRamp.h:12
LArADC2MeV::set
bool set(const IdentifierHash &hid, const int gain, const std::vector< float > &adc2mev)
Definition: LArADC2MeV.cxx:23
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
WriteCellNoiseToCool.igain
igain
Definition: WriteCellNoiseToCool.py:338
beamspotman.stat
stat
Definition: beamspotman.py:266
ILArMphysOverMcal
Definition: ILArMphysOverMcal.h:13
ILAruA2MeV::ERRORCODE
@ ERRORCODE
Definition: ILAruA2MeV.h:35
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
LArOnlineID
Definition: LArOnlineID.h:20
LArOnline_SuperCellID
Definition: LArOnline_SuperCellID.h:20
ILArMphysOverMcal::MphysOverMcal
virtual const float & MphysOverMcal(const HWIdentifier &id, int gain) const =0
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
LArOnlineID_Base::isEMBPS
bool isEMBPS(const HWIdentifier id) const
Definition: LArOnlineID_Base.cxx:1661
LArADC2MeVCondAlg::m_isSuperCell
Gaudi::Property< bool > m_isSuperCell
Definition: LArADC2MeVCondAlg.h:55
LArOnline_SuperCellID.h
LArADC2MeVCondAlg::m_lAruA2MeVKey
SG::ReadCondHandleKey< ILAruA2MeV > m_lAruA2MeVKey
Definition: LArADC2MeVCondAlg.h:40
ILArHVScaleCorr::HVScaleCorr
virtual const float & HVScaleCorr(const HWIdentifier &id) const =0
LArADC2MeVCondAlg::m_febConfigKey
SG::ReadCondHandleKey< LArFebConfig > m_febConfigKey
Definition: LArADC2MeVCondAlg.h:52
LArADC2MeVCondAlg::m_cablingKey
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
Definition: LArADC2MeVCondAlg.h:39
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
LArOnlineID_Base::channel_name
std::string channel_name(const HWIdentifier id) const
Return a string corresponding to a feedthrough name given an identifier.
Definition: LArOnlineID_Base.cxx:219
CaloGain.h
ILArDAC2uA::ERRORCODE
@ ERRORCODE
Definition: ILArDAC2uA.h:37
SG::WriteCondHandle
Definition: WriteCondHandle.h:26
LArOnlineID_Base::channel_begin
id_iterator channel_begin() const
Returns an iterator pointing to a channel identifier collection.
Definition: LArOnlineID_Base.cxx:1922
LArOnlineID.h
LArVectorProxy
Proxy for accessing a range of float values like a vector.
Definition: LArVectorProxy.h:38
LArADC2MeVCondAlg::m_completeDetector
Gaudi::Property< bool > m_completeDetector
Definition: LArADC2MeVCondAlg.h:56
LArOnOffIdMapping
Definition: LArOnOffIdMapping.h:20