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