ATLAS Offline Software
Loading...
Searching...
No Matches
CaloNoiseCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "CaloNoiseCondAlg.h"
6#include <forward_list>
9
11
12 unsigned nFolders=0;
13 if (!m_caloNoiseKey.key().empty()) {
14 ATH_CHECK(m_caloNoiseKey.initialize());
15 nFolders++;
16 }
17 if (!m_larNoiseKey.key().empty()) {
18 ATH_CHECK(m_larNoiseKey.initialize());
19 nFolders++;
20 }
21 if (!m_tileNoiseKey.key().empty()) {
22 ATH_CHECK(m_tileNoiseKey.initialize());
23 nFolders++;
24 }
25
26 if (nFolders==0) {
27 ATH_MSG_ERROR("No noise DB folder found, LArNoiseFolder, TileNoiseFolder and CaloNoiseFolder properties are all empty!");
28 return StatusCode::FAILURE;
29 }
30
31 const std::string& noiseKey=m_outputKey.key();
32 if(noiseKey=="electronicNoise") {
33 ATH_MSG_INFO("Will compute electronic noise");
35 }
36 else if (noiseKey == "electronicNoiseNoHV") {
37 ATH_MSG_INFO("Will compute electronic noise without HV corrections");
39 if (m_useHVCorr) {
40 ATH_MSG_WARNING("Inconsistent configuration, set useHVCorr=False");
41 m_useHVCorr=false;
42 }
43 }
44 else if (noiseKey == "pileupNoise") {
45 ATH_MSG_INFO("Will compute pileup noise");
47 if (m_useHVCorr) {
48 ATH_MSG_INFO("Disabling HV correction, only pile-up noise");
49 }
50 m_useHVCorr=false;
51 } else if (noiseKey == "totalNoise") {
53 ATH_MSG_INFO("Will compute total (electronic + pileup) noise");
54 } else {
55 ATH_MSG_ERROR("Unexpected noise key given: " << noiseKey << ". Expeced 'electronicNoise' or 'pileupNoise' or 'totalNoise'.");
56 return StatusCode::FAILURE;
57 }
58
59 ATH_CHECK( m_hvCorrKey.initialize(m_useHVCorr) );
60
61 const bool doLumiFolderInit = m_lumi0 < 0 && m_noiseType!=CaloNoise::ELEC;
62 if (m_lumiFolderKey.initialize(doLumiFolderInit).isFailure()) {
63 ATH_MSG_ERROR("Luminosity set to < 0 but failed to initialize LumiFolder");
64 }
65
66
67 ATH_CHECK(m_outputKey.initialize());
68
69 ATH_CHECK(detStore()->retrieve(m_caloCellID,"CaloCell_ID"));
70
71 m_hashRange=std::make_unique<CaloNoiseHashRanges>(m_caloCellID);
72
73 return StatusCode::SUCCESS;
74}
75
76
77StatusCode CaloNoiseCondAlg::execute(const EventContext& ctx) const {
78
79 //Set up write handle
81 if (writeHandle.isValid()) {
82 ATH_MSG_DEBUG("Found valid write handle");
83 return StatusCode::SUCCESS;
84 }
85
86 //Obtain AttrListsCollections for all possible folders (LAr,Tile,Calo)
87 std::vector<const CondAttrListCollection*> attrListNoise;
88
89 if (!m_larNoiseKey.key().empty()) {
90 //Separete LAr/Tile folder
92 attrListNoise.push_back(*larNoiseHdl);
93 writeHandle.addDependency(larNoiseHdl);
94 ATH_MSG_DEBUG("Range of LArNoise " << larNoiseHdl.getRange() << ", intersection:" << writeHandle.getRange());
95 }
96
97 if (!m_tileNoiseKey.key().empty()) {
99 attrListNoise.push_back(*tileNoiseHdl);
100 writeHandle.addDependency(tileNoiseHdl);
101 ATH_MSG_DEBUG("Range of TileNoise " << tileNoiseHdl.getRange() << ", intersection:" << writeHandle.getRange());
102 }
103
104 if (!m_caloNoiseKey.key().empty()) {
106 attrListNoise.push_back(*caloNoiseHdl);
107 writeHandle.addDependency(caloNoiseHdl);
108 ATH_MSG_DEBUG("Range of CaloNoise " << caloNoiseHdl.getRange() << ", intersection:" << writeHandle.getRange());
109 }
110
111 //Get noise-blobs out of all COOL-channels in all COOL Folders we know about:
112 std::forward_list<std::pair<unsigned, const coral::Blob&> > blobList;
113 for (const auto& attrListColl : attrListNoise) {
114 for (const auto& coll : *attrListColl) {
115 ATH_MSG_DEBUG("Working on channel " << coll.first);
116 const coral::Blob& blob = (coll.second)["CaloCondBlob16M"].data<coral::Blob>();
117 if (blob.size()<1) {
118 ATH_MSG_DEBUG("Empty blob in channel " << coll.first << ". Ignored.");
119 continue;
120 }
121 blobList.emplace_front(coll.first, blob);
122 }
123 }
124
125 //Get LAr HVScale Corr (if requested)
126 const LArHVCorr* larHVCorr=nullptr;
127 if (m_useHVCorr) {
129 larHVCorr=*larHVCorrHdl;
130 writeHandle.addDependency(larHVCorrHdl);
131 ATH_MSG_DEBUG("Range of LArHVScale " << larHVCorrHdl.getRange() << ", intersection:" << writeHandle.getRange());
132 }
133
134 //Get Luminosity:
135 float lumi=m_lumi0;
136 //if (m_lumi0<0 && m_noiseType!=CaloNoise::ELEC) {
137 if (not m_lumiFolderKey.empty()) {
139 const CondAttrListCollection* lumiAttrListColl=*lumiHdl;
140 writeHandle.addDependency(lumiHdl);
141 ATH_MSG_DEBUG("Range of Luminosity " << lumiHdl.getRange() << ", intersection:" << writeHandle.getRange() );
142 const coral::AttributeList& attrList = lumiAttrListColl->attributeList(0); //Get lumi from COOL channel 0
143 if (attrList["LBAvInstLumi"].isNull()) {
144 ATH_MSG_WARNING( " NULL Luminosity information in database ... set it to 0 " );
145 lumi = 0.;
146 } else {
147 lumi = attrList["LBAvInstLumi"].data<float>() *1e-3; // luminosity (from 10**30 units in db to 10*33 units)
148 }
149 if (std::isnan(lumi)) {
150 ATH_MSG_WARNING( " Luminosity is not a number.. " << m_lumi0 << " ... set it to 0 " );
151 lumi=0.;
152 }
153 }//end if m_lumi0<0
154 else if (lumi < 0) {
155 // Clang may speculatively evaluate the sqrt(lumi) below even if
156 // m_noiseType is ELEC, which can then be an issue if one looks
157 // at FPEs. Protect against this by making sure that lumi
158 // is not negative.
159 lumi = 0;
160 }
161
162
163 const size_t maxCells=m_caloCellID->calo_cell_hash_max();
164 //Create the CaloNoise CDO:
165 const size_t nLArCells=m_hashRange->maxLArCells();
166 const size_t nTileCells=m_hashRange->maxTileCells();
167 std::unique_ptr<CaloNoise> caloNoiseObj=std::make_unique<CaloNoise>(nLArCells,3,
168 nTileCells,4,
170
171 //Counters for crosschecks
172 std::array<unsigned,4> cellsPerGain{0,0,0,0};
173 unsigned nBlobs=0;
174
175 //Loop over the list of blobs we got:
176 for (auto& blobPair : blobList) {
177 nBlobs++;
178 const CaloNoiseHashRanges::SYSTEM sys=static_cast<CaloNoiseHashRanges::SYSTEM>(blobPair.first);
179 const IdentifierHash offset=m_hashRange->hashOffsets().at(sys);
180 std::unique_ptr<const CaloCondBlobFlt> blob(CaloCondBlobFlt::getInstance(blobPair.second));
181 if (blob->getObjVersion()!=1) {
182 ATH_MSG_ERROR("Unexpected blob object version in COOL channel " << blobPair.first
183 << ". Found " << blob->getObjVersion() << ", expected 1");
184 return StatusCode::FAILURE;
185 }
186 //Get writeable access to underlying storage (boost::multi_array)
187 auto& noise = (sys==CaloNoiseHashRanges::TILE) ? caloNoiseObj->tileStorage() : caloNoiseObj->larStorage();
188
189 const unsigned nChansThisblob=blob->getNChans();
190 const unsigned nGains=blob->getNGains();
191 for (unsigned igain=0;igain<nGains;++igain) {
192 for (unsigned i=0;i<nChansThisblob;++i) {
193 float hvcorr=1.0;
194 if (sys!=CaloNoiseHashRanges::TILE && larHVCorr) {
195 const IdentifierHash oflHash(offset+i);
196 hvcorr=larHVCorr->HVScaleCorr_oflHash(oflHash);
197 //hvcorr might be zero in case of problems with the DCS database
198 if (hvcorr<0.01) hvcorr=1.0;
199 }
200 const float a=blob->getData(i,igain,0)*hvcorr;
201 const float b=blob->getData(i,igain,1);
202 ++(cellsPerGain[igain]);
203 const size_t hash = (sys==CaloNoiseHashRanges::TILE) ? i : i+offset;
204 switch (m_noiseType){
205 case CaloNoise::ELEC:
206 noise[igain][hash]=a;
207 break;
209 noise[igain][hash]=b*std::sqrt(lumi);
210 break;
211 case CaloNoise::TOTAL:
212 noise[igain][hash]=std::sqrt(a*a + b*b*lumi);
213 break;
214 default:
215 break;
216 }
217 }//end loop over channels
218 }//end loop over gains
219
220
221 // Cache data to calculate effective sigma for tile double-gaussian noise
222 // Matters for Electronic and total noise
224 caloNoiseObj->setTileBlob(blob.release(),lumi);
225 }
226
227 }//end loop over blob (COOL channels)
228
229
230
231 if (nBlobs!=7) {
232 ATH_MSG_ERROR("Unexpected number of COOL channels containing noise-blobs. Got " << nBlobs << " expected 7 (6 LAr, 1 Tile)");
233 return StatusCode::FAILURE;
234 }
235
236
237 switch (m_noiseType){
238 case CaloNoise::ELEC:
239 ATH_MSG_INFO("Calculated electronic noise" << (larHVCorr ? " with " : " without ") << "HV Scale correction");
240 break;
242 ATH_MSG_INFO("Calculated pile-up noise for lumi " << lumi);
243 break;
244 case CaloNoise::TOTAL:
245 ATH_MSG_INFO("Calculated total noise for lumi " << lumi<< (larHVCorr ? " with " : " without ") << "HV Scale correction");
246 break;
247 default:
248 break;
249 }
250
251 for (unsigned igain=0;igain<4;++igain) {
252
253 if (igain<3 && cellsPerGain[igain]!=maxCells) {
254 ATH_MSG_ERROR("Expected " << maxCells << " cells for gain " << igain << ", got " << cellsPerGain[igain]);
255 }
256 else {
257 ATH_MSG_DEBUG("Gain " << igain << " Nbr of cells: " << cellsPerGain[igain]);
258 }
259
260 }
261
262 //Create output object
263 ATH_CHECK(writeHandle.record(std::move(caloNoiseObj)));
264 ATH_MSG_INFO("recorded new CaloNoise object with key " << writeHandle.key() << " and range " << writeHandle.getRange());
265
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_WARNING(x)
#define ATH_MSG_DEBUG(x)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
const ServiceHandle< StoreGateSvc > & detStore() const
static CaloCondBlobFlt * getInstance(coral::Blob &blob)
Returns a pointer to a non-const CaloCondBlobFlt.
CaloNoise::NOISETYPE m_noiseType
Gaudi::Property< bool > m_useHVCorr
StatusCode initialize() override final
SG::ReadCondHandleKey< CondAttrListCollection > m_larNoiseKey
const CaloCell_ID * m_caloCellID
std::unique_ptr< CaloNoiseHashRanges > m_hashRange
SG::ReadCondHandleKey< LArHVCorr > m_hvCorrKey
SG::ReadCondHandleKey< CondAttrListCollection > m_lumiFolderKey
SG::WriteCondHandleKey< CaloNoise > m_outputKey
SG::ReadCondHandleKey< CondAttrListCollection > m_tileNoiseKey
Gaudi::Property< float > m_lumi0
SG::ReadCondHandleKey< CondAttrListCollection > m_caloNoiseKey
StatusCode execute(const EventContext &ctx) const override final
This class is a collection of AttributeLists where each one is associated with a channel number.
const AttributeList & attributeList(ChanNum chanNum) const
attribute list for a given channel number
This is a "hash" representation of an Identifier.
const float & HVScaleCorr_oflHash(const IdentifierHash &h) const
Definition LArHVCorr.h:32
const EventIDRange & getRange()
const std::string & key() const
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED