ATLAS Offline Software
Loading...
Searching...
No Matches
TileTBMonitorAlgorithm.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9
12
14
15#include <algorithm>
16
18
19 ATH_MSG_INFO("in initialize()");
21
22 ATH_CHECK( m_cablingSvc.retrieve() );
23
24 ATH_CHECK( m_caloCellContainerKey.initialize() );
25
26 ATH_CHECK( detStore()->retrieve(m_tileID) );
27 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
28
30
31 std::vector<std::string> modules;
32 for (int fragID : m_fragIDs) {
33 int ros = fragID >> 8;
34 int drawer = fragID & 0x3F;
35 modules.push_back(TileCalibUtils::getDrawerString(ros, drawer));
37 }
38
39 using namespace Monitored;
40 m_timeGroups = buildToolMap<int>(m_tools, "TileTBChannelTime", modules);
41 m_cellMapGroups = buildToolMap<int>(m_tools, "TileTBCellMap", modules);
42
43 std::ostringstream os;
44 if ( m_fragIDs.size() != 0) {
45 std::sort(m_fragIDs.begin(), m_fragIDs.end());
46 for (int fragID : m_fragIDs) {
47 unsigned int ros = fragID >> 8;
48 unsigned int drawer = fragID & 0xFF;
49 std::string module = TileCalibUtils::getDrawerString(ros, drawer);
50 os << " " << module << "/0x" << std::hex << fragID << std::dec;
51 }
52 } else {
53 os << "NONE";
54 }
55
56 ATH_MSG_INFO("Monitored modules/frag ID:" << os.str());
57
58 std::map<std::string, unsigned int> roses = { {"AUX", 0}, {"LBA", 1}, {"LBC", 2}, {"EBA", 3}, {"EBC", 4} };
59 for (const std::string& maskedModuleChannels : m_masked) {
60
61 std::string module = maskedModuleChannels.substr(0, 5);
62 std::string partition = module.substr(0, 3);
63 if (roses.count(partition) != 1) {
64 ATH_MSG_WARNING("There no such partition: " << partition << " in module: " << module
65 << " => skip because of bad format: " << maskedModuleChannels);
66 continue;
67 }
68
69 unsigned int drawer = std::stoi(module.substr(3, 2)) - 1;
70 if (drawer >= TileCalibUtils::MAX_DRAWER) {
71 ATH_MSG_WARNING("There no such drawer: " << drawer + 1 << " in module: " << module
72 << " => skip because of bad format: " << maskedModuleChannels);
73 continue;
74 }
75
76 unsigned int ros = roses.at(partition);
77 unsigned int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
78
79 std::string gain = maskedModuleChannels.substr(5,7);
80 unsigned int adc = std::stoi(gain);
81
82 if (adc >= TileCalibUtils::MAX_GAIN) {
83 ATH_MSG_WARNING("There no such gain: " << gain << " => skip because of bad format: " << maskedModuleChannels);
84 continue;
85 }
86
87 std::stringstream channels(maskedModuleChannels.substr(7));
88 std::string channel;
89 while (std::getline(channels, channel, ',')) {
90 if (!channel.empty()) {
91 unsigned int chan = std::stoi(channel);
92 if (chan >= TileCalibUtils::MAX_CHAN) {
93 ATH_MSG_WARNING("There no such channel: " << chan << " in channels: " << channels.str()
94 << " => skip because of bad format: " << maskedModuleChannels);
95 continue;
96 }
97 m_maskedChannels[drawerIdx][chan] |= (1U << adc);
98 ATH_MSG_INFO(TileCalibUtils::getDrawerString(ros, drawer) << " ch" << chan << (adc ? " HG" : " LG") << ": masked!");
99 }
100 }
101
102 }
103
104 m_xCellLB.push_back(m_xCellLB_A.value());
105 m_xCellLB.push_back(m_xCellLB_BC.value());
106 m_xCellLB.push_back(m_xCellLB_D.value());
107
108 m_yCellLB.push_back(m_yCellLB_A.value());
109 m_yCellLB.push_back(m_yCellLB_BC.value());
110 m_yCellLB.push_back(m_yCellLB_D.value());
111
112 m_xCellEB.push_back(m_xCellEB_A.value());
113 m_xCellEB.push_back(m_xCellEB_BC.value());
114 m_xCellEB.push_back(m_xCellEB_D.value());
115
116 m_yCellEB.push_back(m_yCellEB_A.value());
117 m_yCellEB.push_back(m_yCellEB_BC.value());
118 m_yCellEB.push_back(m_yCellEB_D.value());
119
120 // Sanity check
121 std::vector<unsigned int> maxTower{10, 10, 16, 16};
122 std::vector<std::reference_wrapper<const std::vector<std::vector<std::vector<double>>>>> xyCells{m_xCellLB, m_yCellLB, m_xCellEB, m_yCellEB};
123 for (unsigned int i = 0; i < xyCells.size(); ++i) {
124 for (const std::vector<std::vector<double>>& xy : xyCells[i].get()) {
125 if (xy.size() != maxTower[i]) {
126 std::string properties = ((i % 2 == 0) ? "xCell" : "yCell");
127 properties += (i < 2) ? "LongBarrelSample[A,BC,D]" : "ExtendedBarrelSample[A,BC,D]";
128 ATH_MSG_ERROR("Properties " << properties << " should be configured for " << maxTower[i] << " towers");
129 return StatusCode::FAILURE;
130 }
131 }
132 }
133
134
135 const CaloCell_ID* caloID = nullptr;
136 ATH_CHECK( detStore()->retrieve(caloID) );
137
138 unsigned int minCellTower = 1;
139 unsigned int maxCellTower = 9;
140
141 std::vector<std::vector<int>> lbCellsD{{}, {0, 2}, {2, 4}, {2, 4}, {1, 4, 6}, {4, 6}, {4, 6}, {6}, {6}};
142 for (unsigned int cellTower = minCellTower; cellTower < maxCellTower; ++cellTower) {
143 std::vector<IdentifierHash>& cells = m_cellsNearTower[cellTower];
144 for (unsigned int cellModule = 0; cellModule < 2; ++cellModule) {
145 for (unsigned int cellSample = 0; cellSample < 2; ++cellSample) {
146 for (unsigned int tower = cellTower - 1; tower < cellTower + 2; ++tower) {
147 Identifier cell_id = m_tileID->cell_id(TileID::BARREL, TileID::NEGATIVE, cellModule, tower, cellSample);
148 cells.push_back(caloID->calo_cell_hash(cell_id));
149 }
150 }
151
152 const std::vector<int>& towersD = lbCellsD[cellTower];
153 for (int towerD : towersD) {
154 unsigned int side = (towerD == 0) ? TileID::POSITIVE : TileID::NEGATIVE;
155 Identifier cell_id = m_tileID->cell_id(TileID::BARREL, side, cellModule, towerD, TileID::SAMP_D);
156 cells.push_back(caloID->calo_cell_hash(cell_id));
157 }
158 }
159 }
160
161 static const std::vector<std::vector<std::vector<int>>> ebCellsNearTower{{{}},
162 {{11, 12}, {9, 10, 11, 12}, {8, 10}},
163 {{11, 12}, {9, 10, 11, 12}, {8, 10}},
164 {{12, 13}, {11, 12}, {10, 12}},
165 {{12, 13, 14}, {11, 12, 13}, {10, 12}},
166 {{13, 14}, {12, 13}, {12}},
167 {{14, 15}, {13, 14}, {12}},
168 {{14, 15}, {13, 14}, {12}},
169 {{15}, {14}, {12}}};
170 for (unsigned int cellTower = minCellTower; cellTower < maxCellTower; ++cellTower) {
171 std::vector<IdentifierHash>& cells = m_cellsNearTower[cellTower];
172 const std::vector<std::vector<int>>& ebCells = ebCellsNearTower[cellTower];
173 for (unsigned int cellSample = 0; cellSample < 3; ++cellSample) {
174 const std::vector<int>& ebCellsInSample = ebCells[cellSample];
175 for (int tower : ebCellsInSample) {
176 int section = (tower < 10) ? TileID::GAPDET : TileID::EXTBAR;
177 Identifier cell_id = m_tileID->cell_id(section, TileID::NEGATIVE, 2, tower, cellSample);
178 cells.push_back(caloID->calo_cell_hash(cell_id));
179 }
180 }
181 }
182
183 for (unsigned int cellTower = minCellTower; cellTower < maxCellTower; ++cellTower) {
184 std::vector<IdentifierHash>& cells = m_cellsNearTower[cellTower];
185 ATH_MSG_INFO("The are " << cells.size() << " Tile cells near the tower " << cellTower << " in LBC02: ");
186 for (IdentifierHash hash : cells) {
187 ATH_MSG_INFO(" " << m_tileID->to_string(caloID->cell_id(hash)));
188 }
189 }
190
191 return StatusCode::SUCCESS;
192}
193
194
195StatusCode TileTBMonitorAlgorithm::fillHistograms( const EventContext& ctx ) const {
196
197 // In case you want to measure the execution time
198 auto timer = Monitored::Timer("TIME_execute");
199
201 ATH_CHECK( caloCellContainer.isValid() );
202
203 if (caloCellContainer->empty()) return StatusCode::SUCCESS;
204
205 const TileCell* cellWithMaxEnergy = nullptr;
206
207 double totalEnergy(0.0);
208 bool onlyLBC04(true);
209 int nCellsOverThreshold(0);
210
211 double totalEnergyLBA01 = 0.;
212 double totalEnergyLBA02 = 0.;
213 double totalEnergyLBC01 = 0.;
214 double totalEnergyLBC02 = 0.;
215 double totalEnergyEBC03 = 0.;
216
217 for (const CaloCell* cell : *caloCellContainer) {
218 if (m_tileID->is_tile(cell->ID())) {
219 const TileCell* tile_cell = dynamic_cast<const TileCell*>(cell);
220 if (!tile_cell) continue;
221
222 const CaloDetDescrElement* caloDDE = cell->caloDDE();
223
224 IdentifierHash hash1 = caloDDE->onl1();
225 IdentifierHash hash2 = caloDDE->onl2();
226
227 int side = m_tileID->side(cell->ID());
228 int section = m_tileID->section(cell->ID());
229 int module = m_tileID->module(cell->ID());
230 int tower = m_tileID->tower(cell->ID());
231 int sample = m_tileID->sample(cell->ID());
232
233 if ((section == TileID::BARREL) && (side == TileID::NEGATIVE) && (module == 1) && (sample == TileID::SAMP_A)
234 && (!cellWithMaxEnergy || cellWithMaxEnergy->energy() < tile_cell->energy())) {
235 cellWithMaxEnergy = tile_cell;
236 }
237
238 double energy = 0.0;
239 double energy_pC(0.0);
240
241 int gain1 = tile_cell->gain1();
242
243 HWIdentifier channelId1 = m_tileHWID->channel_id(hash1);
244
245 int ros1 = m_tileHWID->ros(channelId1);
246 int drawer1 = m_tileHWID->drawer(channelId1);
247 int chan1 = m_tileHWID->channel(channelId1);
248 int drawerIdx1 = TileCalibUtils::getDrawerIdx(ros1, drawer1);
249
250 std::string moduleName1 = TileCalibUtils::getDrawerString(ros1, drawer1);
251 int drawerIdx2 = 0;
252 std::string moduleName2 = "";
253
254 if (m_monitoredDrawerIdx[drawerIdx1] && tile_cell->ene1() > m_energyThresholdForTime) {
255 auto monTime = Monitored::Scalar<float>("time", tile_cell->time1());
256 auto monChannel = Monitored::Scalar<float>("channel", chan1);
257 fill(m_tools[m_timeGroups.at(moduleName1)], monTime, monChannel);
258 }
259
260 if (onlyLBC04 && chan1 > 0 && drawerIdx1 != 87) onlyLBC04 = false;
261
262 if (hash2 == TileHWID::NOT_VALID_HASH) {
263 if (gain1 >= 0 && !((m_maskedChannels[drawerIdx1][chan1] >> gain1) & 1U)) {
264 energy = cell->energy();
265 }
266 } else {
267
268 int gain2 = tile_cell->gain2();
269
270 HWIdentifier channelId2 = m_tileHWID->channel_id(hash2);
271
272 int ros2 = m_tileHWID->ros(channelId2);
273 int drawer2 = m_tileHWID->drawer(channelId2);
274 int chan2 = m_tileHWID->channel(channelId2);
275 drawerIdx2 = TileCalibUtils::getDrawerIdx(ros2, drawer2);
276
277 moduleName2 = TileCalibUtils::getDrawerString(ros2, drawer2);
278
279 if (m_monitoredDrawerIdx[drawerIdx1] && tile_cell->ene2() > m_energyThresholdForTime) {
280 auto monTime = Monitored::Scalar<float>("time", tile_cell->time2());
281 auto monChannel = Monitored::Scalar<float>("channel", chan2);
282 fill(m_tools[m_timeGroups.at(moduleName2)], monTime, monChannel);
283 }
284
285 if (gain1 < 0 || ((m_maskedChannels[drawerIdx1][chan1] >> gain1) & 1U)) {
286 if (gain2 >= 0 && !((m_maskedChannels[drawerIdx2][chan2] >> gain2) & 1U)) {
287 energy = tile_cell->ene2() * 2;
288 }
289 } else if (gain2 >= 0 && ((m_maskedChannels[drawerIdx2][chan2] >> gain2) & 1U)) {
290 if (gain1 >= 0 && !((m_maskedChannels[drawerIdx1][chan1] >> gain1) & 1U)) {
291 energy =tile_cell->ene1() * 2;
292 }
293 } else {
294 energy = cell->energy();
295 }
296 }
297
298 energy_pC = energy * 0.001; // keep energy in pC
299 totalEnergy += energy_pC;
300
301 if (section == TileID::BARREL) {
302 if (side == TileID::POSITIVE) {
303 if (module == 0) totalEnergyLBA01 += energy_pC;
304 else if (module == 1) totalEnergyLBA02 += energy_pC;
305 } else if (side == TileID::NEGATIVE) {
306 if (module == 0) totalEnergyLBC01 += energy_pC;
307 else if (module == 1) totalEnergyLBC02 += energy_pC;
308 }
309 } else {
310 if (module == 2 && side == TileID::NEGATIVE && sample < TileID::SAMP_E) {
311 totalEnergyEBC03 += energy_pC;
312 }
313 }
314
315 if (side < 0) {
316 if (energy > m_cellEnergyThreshold) {
317 ++nCellsOverThreshold;
318 }
319 }
320
321 if (section == TileID::BARREL) {
322 if (m_monitoredDrawerIdx[drawerIdx1]) {
323 auto monX = Monitored::Collection("x", m_xCellLB[sample][tower]);
324 auto monY = Monitored::Collection("y", m_yCellLB[sample][tower]);
325
326 std::vector<double> cellEnergy(m_xCellLB[sample][tower].size(), energy_pC);
327 auto monEnergy = Monitored::Collection("energy", cellEnergy);
328 if (m_monitoredDrawerIdx[drawerIdx1]) {
329 fill(m_tools[m_cellMapGroups.at(moduleName1)], monX, monY, monEnergy);
330 }
331
332 if (tower == 0 && sample == TileID::SAMP_D && m_monitoredDrawerIdx[drawerIdx2]) {
333 fill(m_tools[m_cellMapGroups.at(moduleName2)], monX, monY, monEnergy);
334 }
335 }
336 } else if (section == TileID::EXTBAR
338 && (sample == TileID::SAMP_C || sample == TileID::SAMP_D))) {
339 if (m_monitoredDrawerIdx[drawerIdx1]) {
340 auto monX = Monitored::Collection("x", m_xCellEB[sample][tower]);
341 auto monY = Monitored::Collection("y", m_yCellEB[sample][tower]);
342
343 std::vector<double> cellEnergy(m_xCellEB[sample][tower].size(), energy_pC);
344 auto monEnergy = Monitored::Collection("energy", cellEnergy);
345
346 fill(m_tools[m_cellMapGroups.at(moduleName1)], monX, monY, monEnergy);
347 }
348 }
349 }
350 }
351
352 if (cellWithMaxEnergy && !onlyLBC04) {
353
354 int tower = m_tileID->tower(cellWithMaxEnergy->ID());
355 auto monTower = Monitored::Scalar<float>("tower", tower);
356 fill("TileTBHotCellA_LBC02", monTower);
357
358 if ((tower > 0) && (tower < 9)) {
359
360 double sumClong = 0.0;
361 double sumCtot = 0.0;
362
363 const std::vector<IdentifierHash>& cellsHashes = m_cellsNearTower[tower];
365 caloCellContainer->findCellVector(cellsHashes, cells);
366
367 float alpha = (m_beamEnergy < 100000) ? 0.6 : 0.38;
368 unsigned int nCells = cells.size();
369
370 if (nCells) {
371 double sumCellEnergyAlpha = 0.;
372 for (const CaloCell* cell : cells) {
373 double energy = cell->energy();
374 if(energy >= 0) {
375 sumCellEnergyAlpha += std::pow(energy, alpha);
376 }
377 }
378
379 double avgCellEnergyAlpha = sumCellEnergyAlpha / nCells;
380
381 for (const CaloCell* cell : cells) {
382 double energy = cell->energy();
383 if (energy >= 0) {
384 sumCtot += std::pow( std::pow(energy, alpha) - avgCellEnergyAlpha, 2 );
385 int sample = m_tileID->sample(cell->ID());
386 if (sample != TileID::SAMP_D) {
387 sumClong += energy;
388 }
389 }
390 }
391
392 double Ctot = std::sqrt(sumCtot / nCells) / sumCellEnergyAlpha;
393 double Clong = sumClong / m_beamEnergy;
394
395 auto monCtot = Monitored::Scalar<float>("Ctot", Ctot);
396 auto monClong = Monitored::Scalar<float>("Clong", Clong);
397 fill("TileTBCtot", monCtot);
398 fill("TileTBClong", monClong);
399 fill("TileTBCtotVsClong", monClong, monCtot);
400
401 }
402 }
403 }
404
405 if (!onlyLBC04) {
406
407 auto monEnergy = Monitored::Scalar<float>("energy", totalEnergy);
408 fill("TileTBTotalEventEnergy", monEnergy);
409
410 auto monCellsOvThr = Monitored::Scalar<float>("nCells", nCellsOverThreshold);
411 fill("TileTBCellsNumberVsTotalEnergy", monCellsOvThr, monEnergy);
412
413 std::vector<int> side{0,0,1,1,1};
414 auto monSide = Monitored::Collection("side", side);
415
416 std::vector<int> module{0,1,0,1,2};
417 auto monModule = Monitored::Collection("module", module);
418
419 std::vector<double> moduleEnergy{totalEnergyLBA01, totalEnergyLBA02,
420 totalEnergyLBC01, totalEnergyLBC02,
421 totalEnergyEBC03};
422 auto monModEnergy = Monitored::Collection("energy", moduleEnergy);
423
424 fill("TileTBHitMap", monSide, monModule, monModEnergy);
425 }
426
427
428 fill("TileTBMonExecuteTime", timer);
429
430 return StatusCode::SUCCESS;
431}
#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)
Handle class for reading from StoreGate.
void section(const std::string &sec)
const ServiceHandle< StoreGateSvc > & detStore() const
virtual StatusCode initialize() override
initialize
ToolHandleArray< GenericMonitoringTool > m_tools
Array of Generic Monitoring Tools.
std::vector< const CaloCell * > CellVector
type to be used for the internal lookup table, and to return list of cells
IdentifierHash calo_cell_hash(const Identifier cellId) const
create hash id from 'global' cell id
Identifier cell_id(const int subCalo, const int barec_or_posneg, const int sampling_or_fcalmodule, const int region_or_dummy, const int eta, const int phi) const
Make a cell (== channel) ID from constituting fields and subCalo index; for (Mini)FCAL,...
Helper class for offline cell identifiers.
Definition CaloCell_ID.h:34
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
double energy() const
get energy (data member)
Definition CaloCell.h:327
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
This class groups all DetDescr information related to a CaloCell.
IdentifierHash onl2() const
cell online identifier 2
IdentifierHash onl1() const
cell online identifier 1
This is a "hash" representation of an Identifier.
Declare a monitored scalar variable.
A monitored timer.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
static const unsigned int MAX_DRAWERIDX
Maximal drawer index.
static std::string getDrawerString(unsigned int ros, unsigned int drawer)
Return the drawer name, e.g.
static const unsigned int MAX_GAIN
Number of gains per channel.
static const unsigned int MAX_DRAWER
Number of drawers in ROS 1-4.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
static const unsigned int MAX_CHAN
Number of channels in drawer.
float time1(void) const
get time of first PMT
Definition TileCell.h:192
int gain2(void) const
get gain of second PMT
Definition TileCell.cxx:175
int gain1(void) const
get gain of first PMT
Definition TileCell.cxx:168
float ene1(void) const
get energy of first PMT
Definition TileCell.h:187
float time2(void) const
get time of second PMT
Definition TileCell.h:194
float ene2(void) const
get energy of second PMT
Definition TileCell.h:189
@ NOT_VALID_HASH
Definition TileHWID.h:314
Gaudi::Property< std::vector< std::vector< double > > > m_yCellEB_D
Gaudi::Property< std::vector< std::string > > m_masked
Gaudi::Property< std::vector< std::vector< double > > > m_yCellLB_D
std::vector< std::vector< std::vector< double > > > m_xCellLB
std::map< std::string, int > m_timeGroups
std::vector< std::vector< std::vector< double > > > m_yCellEB
Gaudi::Property< std::vector< std::vector< double > > > m_xCellLB_A
Gaudi::Property< std::vector< int > > m_fragIDs
Gaudi::Property< std::vector< std::vector< double > > > m_xCellEB_BC
Gaudi::Property< std::vector< std::vector< double > > > m_yCellEB_A
Gaudi::Property< std::vector< std::vector< double > > > m_xCellEB_A
Gaudi::Property< float > m_energyThresholdForTime
Gaudi::Property< float > m_cellEnergyThreshold
std::map< std::string, int > m_cellMapGroups
Gaudi::Property< std::vector< std::vector< double > > > m_xCellLB_D
SG::ReadHandleKey< CaloCellContainer > m_caloCellContainerKey
Gaudi::Property< std::vector< std::vector< double > > > m_yCellEB_BC
std::vector< bool > m_monitoredDrawerIdx
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
Gaudi::Property< std::vector< std::vector< double > > > m_yCellLB_A
Gaudi::Property< float > m_beamEnergy
Gaudi::Property< std::vector< std::vector< double > > > m_xCellLB_BC
std::vector< std::vector< std::vector< double > > > m_xCellEB
Gaudi::Property< std::vector< std::vector< double > > > m_xCellEB_D
std::array< std::array< unsigned char, TileCalibUtils::MAX_CHAN >, TileCalibUtils::MAX_DRAWERIDX > m_maskedChannels
virtual StatusCode initialize() override
initialize
std::vector< std::vector< std::vector< double > > > m_yCellLB
std::vector< std::vector< IdentifierHash > > m_cellsNearTower
virtual StatusCode fillHistograms(const EventContext &ctx) const override
adds event to the monitoring histograms
Gaudi::Property< std::vector< std::vector< double > > > m_yCellLB_BC
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
Generic monitoring tool for athena components.
std::vector< V > buildToolMap(const ToolHandleArray< GenericMonitoringTool > &tools, const std::string &baseName, int nHist)
Builds an array of indices (base case)
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void fill(H5::Group &out_file, size_t iterations)