ATLAS Offline Software
Loading...
Searching...
No Matches
GepCellsHandlerAlg.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
5
8
9#include "TMath.h"
11#include <fstream>
12#include <cmath> //std::pow
13
14GepCellsHandlerAlg::GepCellsHandlerAlg( const std::string& name, ISvcLocator* pSvcLocator ) :
15AthReentrantAlgorithm( name, pSvcLocator ){
16 }
17
18
20 ATH_MSG_INFO ("Initializing " << name() << "...");
21 ATH_MSG_INFO ("Target GepCell container name " << m_outputGepCellsKey);
22
23 // Retrieve AlgTools
24 ATH_CHECK(m_electronicNoiseKey.initialize());
25 ATH_CHECK(m_totalNoiseKey.initialize());
26
27 CHECK(m_caloCellsKey.initialize());
28 CHECK(m_outputGepCellsKey.initialize());
29
30 // CaloIndentifier
31 CHECK( detStore()->retrieve (m_CaloCell_ID, "CaloCell_ID") );
32
33 ATH_MSG_INFO("Hardware-style energy encoding for GEP cells has been set to " << m_doGepHardwareStyleEnergyEncoding.value());
34 if (!m_doGepHardwareStyleEnergyEncoding) ATH_MSG_WARNING("Hardware-style energy encoding for GEP cells has been disabled. Cell energies will have larger precision than realistically possible");
35
36 ATH_MSG_INFO("Truncation of Gep cells from FEBs which are overflowing has been set to " << m_doTruncationOfOverflowingFEBs.value());
37 if (!m_doTruncationOfOverflowingFEBs) ATH_MSG_WARNING("Truncation of GEP cells from overflowing FEBs has been disabled. More GEP cells will be send to algorithms than realistically possible");
38
39 ATH_MSG_INFO("Flag to enabling the writting of all cells has been set to " << m_writeAllCells.value());
40 if (m_writeAllCells) {
41 ATH_MSG_WARNING("Will write all cells even if they would get truncated for GEP and/or are below the 2sigma threshold. This might lead to large output Ntuples and is not a realistic representation of GEP cells");
43 ATH_MSG_INFO("Setting energies of the truncated and noisy cells to 0");
44 }
45 } else if (m_cleanOutputCells) {
46 ATH_MSG_ERROR("Cannot use CleanOutputCells without WriteAllCells");
47 return StatusCode::FAILURE;
48 }
49
50
51 // Setting up GEP energy encoding scheme
53
54 // Read values of Gep readout scheme from argument
55 int GepScheme[3];
56 for (int i = 0; i < 3; ++i) {
57 GepScheme[i] = std::stoi(m_GepEnergyEncodingScheme.value().substr(0,m_GepEnergyEncodingScheme.value().find("-")));
58 m_GepEnergyEncodingScheme.value().erase(0, m_GepEnergyEncodingScheme.value().find("-")+1);
59 }
60
61 CHECK(setNumberOfEnergyBits(GepScheme[0]));
62 CHECK(setLeastSignificantBit(GepScheme[1]));
63 CHECK(setG(GepScheme[2]));
64
65 m_stepsPerRange = std::pow(2,m_nEnergyBits-2);
66
67 m_readoutRanges[0] = 0;
72
73 ATH_MSG_DEBUG("Readout scheme with " << m_nEnergyBits << "-bits provides the following four energy thresholds (with " << m_stepsPerRange << " discrete steps on each threshold)");
74 ATH_MSG_DEBUG("GEP cell energy range 0: min = " << m_readoutRanges[0] << " MeV -> max = " << m_readoutRanges[1] << " MeV");
75 ATH_MSG_DEBUG("GEP cell energy range 1: min = " << m_readoutRanges[1] + m_valLeastSigBit << " MeV -> max = " << m_readoutRanges[2] << " MeV");
76 ATH_MSG_DEBUG("GEP cell energy range 2: min = " << m_readoutRanges[2]+(m_valG*m_valLeastSigBit) << " MeV -> max = " << m_readoutRanges[3] << " MeV");
77 ATH_MSG_DEBUG("GEP cell energy range 3: min = " << m_readoutRanges[3]+(m_valG*m_valG*m_valLeastSigBit) << " MeV -> max = " << m_readoutRanges[4] << " MeV");
78 }
79
81 // Loading the invariant cell data and storing in m_gepCellsBase for later use on event-by-event basis
82 m_gepCellsBase.clear();
83
84 ATH_MSG_DEBUG("Loading cell map associating cells to FEBs");
85
86 std::string cellMapPath = PathResolverFindCalibFile(m_LArCellMap);
87 if(cellMapPath.empty()) ATH_MSG_ERROR("Could not find file with cell map data: " << m_LArCellMap.value());
88
89 std::ifstream file(cellMapPath.c_str());
90
91 unsigned n_cells = 0;
92
93 // Read input file
94 if (file.is_open()) {
95
96 int online_id, offline_id, ch, con_num, fbr;
97 std::string feb, con_type;
98
99 // Skipping header of file
100 std::getline(file, feb);
101
102 // start reading data
103 while (true) {
104
105 file >> offline_id >> online_id >> feb >> ch >> con_type >> con_num >> fbr;
106
107 if (file.eof()) break;
108
109 Gep::GepCaloCell caloCell;
110 caloCell.id = offline_id;
111 caloCell.FEB = feb;
112 caloCell.channel = ch;
113 caloCell.fiber = fbr;
114 caloCell.connection_type = con_type;
115 caloCell.connection_number = con_num;
116
117 m_gepCellsBase.insert(std::pair<unsigned int, Gep::GepCaloCell>(caloCell.id, caloCell));
118
119 ++n_cells;
120 }
121 }
122 else {
123 ATH_MSG_ERROR("Could not open file containing the cell to FEB association");
124 return StatusCode::FAILURE;
125 }
126
127 ATH_MSG_DEBUG("Loaded FEB information for " << n_cells << " cells");
128 }
129
130 return StatusCode::SUCCESS;
131}
132
133
134StatusCode GepCellsHandlerAlg::execute(const EventContext& ctx) const {
135
136 // PS this function creates and stores a map which has Gep::GepCaloCells as its values
137 // The cells are made up of data which is invariant for all events, and dynamic
138 // data which varies with event.
139 // The invariant data should be setup in initialize(), and the dynamic
140 // data should be updated here in a way which is compatible with the const-ness of this
141 // function.
142 // This will be attended to in the future.
143
144 ATH_MSG_DEBUG ("Executing " << name() << "...");
145
146 // Read in a container containing (all) CaloCells
147 auto h_caloCells = SG::makeHandle(m_caloCellsKey, ctx);
148 CHECK(h_caloCells.isValid());
149 const auto & cells = *h_caloCells;
150
151 ATH_MSG_DEBUG("Read in " + std::to_string(h_caloCells->size()) + " cells");
152
154 if (!electronicNoiseHdl.isValid()) {return StatusCode::FAILURE;}
155 const CaloNoise* electronicNoiseCDO = *electronicNoiseHdl;
156
158 if (!totalNoiseHdl.isValid()) {return StatusCode::FAILURE;}
159 const CaloNoise* totalNoiseCDO = *totalNoiseHdl;
160
161 int idx = -1;
162 std::map<std::string,std::vector<Gep::GepCaloCell>> gepCellsPerFEB;
163
164 for(const auto *cell: cells){
165
166 Gep::GepCaloCell caloCell;
167 ++idx;
168
169 caloCell.id = (cell->ID().get_identifier32()).get_compact();
170 auto base_cell_itr = m_gepCellsBase.find(caloCell.id);
171 if (base_cell_itr != m_gepCellsBase.end()) caloCell = base_cell_itr->second;
172 else {
173 // Tile cells are not included in the cell base map
174 // In the future this might change, for now just setting FEB value to a dummy
175 caloCell.FEB = "Tile";
176 }
177
178 float electronicNoise = electronicNoiseCDO->getNoise(cell->ID(), cell->gain());
179 float totalNoise = totalNoiseCDO->getNoise(cell->ID(), cell->gain());
180
181 // Only send positive-energy 2sigma cells to the GEP
182 const bool pass_2sigma = cell->energy() / totalNoise >= 2.0;
183 if (!pass_2sigma && !m_writeAllCells) continue;
184
185 const double energy = m_cleanOutputCells && !pass_2sigma ? 0 : cell->energy();
186
187 // GEP will only have ET available for LAr cells, so convert to energy from ET
188 caloCell.offline_et = energy / TMath::CosH(cell->eta());
189 if (m_doGepHardwareStyleEnergyEncoding && !m_CaloCell_ID->is_tile(cell->ID())) {
190 caloCell.et = getGepEnergy(energy / TMath::CosH(cell->eta()));
191 caloCell.e = caloCell.et * TMath::CosH(cell->eta());
192 }
193 else {
194 caloCell.e = energy;
195 caloCell.et = caloCell.offline_et;
196 }
197 caloCell.time = cell->time();
198 caloCell.quality = cell->quality();
199 caloCell.provenance = cell->provenance();
200
201 caloCell.totalNoise = totalNoise;
202 caloCell.electronicNoise = electronicNoise;
203 caloCell.sigma = cell->energy() / totalNoise;
204
205 caloCell.isBad = cell->badcell();
206 caloCell.eta = cell->eta();
207 caloCell.phi = cell->phi();
208 caloCell.sinTh = cell->sinTh();
209 caloCell.cosTh = cell->cosTh();
210 caloCell.sinPhi = cell->sinPhi();
211 caloCell.cosPhi = cell->cosPhi();
212 caloCell.cotTh = cell->cotTh();
213 caloCell.x = cell->x();
214 caloCell.y = cell->y();
215 caloCell.z = cell->z();
216
217 unsigned int samplingEnum = m_CaloCell_ID->calo_sample(cell->ID());
218
219 bool IsEM = m_CaloCell_ID->is_em(cell->ID());
220 bool IsEM_Barrel=false;
221 bool IsEM_EndCap=false;
222 bool IsEM_BarrelPos=false;
223 bool IsEM_BarrelNeg=false;
224 if(IsEM){
225 IsEM_Barrel=m_CaloCell_ID->is_em_barrel(cell->ID());
226 if(IsEM_Barrel){
227 if(m_CaloCell_ID->pos_neg(cell->ID())>0) IsEM_BarrelPos=true;
228 }
229 IsEM_EndCap=m_CaloCell_ID->is_em_endcap(cell->ID());
230 }
231
232 caloCell.isEM = IsEM;
233 caloCell.isEM_barrel = IsEM_Barrel;
234 caloCell.isEM_endCap = IsEM_EndCap;
235 caloCell.isEM_barrelPos = IsEM_BarrelPos;
236 caloCell.isEM_barrelNeg = IsEM_BarrelNeg; //always false?
237 caloCell.isFCAL = m_CaloCell_ID->is_fcal(cell->ID());
238 caloCell.isHEC = m_CaloCell_ID->is_hec(cell->ID());
239 caloCell.isTile = m_CaloCell_ID->is_tile(cell->ID());
240
241 caloCell.sampling = samplingEnum;
242 caloCell.detName = CaloSampling::getSamplingName(samplingEnum);
243
244 caloCell.neighbours = getNeighbours(cells, cell, ctx);
245 caloCell.id = (cell->ID().get_identifier32()).get_compact();
246
247 const CaloDetDescriptor *elt = cell->caloDDE()->descriptor();
248 caloCell.layer = cell->caloDDE()->getLayer();
249
250 float deta = elt->deta();
251 float dphi = elt->dphi();
252
253 float etamin = caloCell.eta - (0.5*deta);
254 float etamax = caloCell.eta + (0.5*deta);
255
256 float phimin = caloCell.phi - (0.5*dphi);
257 float phimax = caloCell.phi + (0.5*dphi);
258
259 caloCell.etaMin = etamin;
260 caloCell.etaMax = etamax;
261 caloCell.phiMin = phimin;
262 caloCell.phiMax = phimax;
263 caloCell.etaGranularity = deta;
264 caloCell.phiGranularity = dphi;
265
266 caloCell.index = idx;
267
268 // Fill cells into map according to FEB
269 auto feb_itr = gepCellsPerFEB.find(caloCell.FEB);
270 if (feb_itr != gepCellsPerFEB.end()) feb_itr->second.push_back(std::move(caloCell));
271 else {
272 std::vector<Gep::GepCaloCell> cellsThisFEB;
273 cellsThisFEB.push_back(caloCell);
274 gepCellsPerFEB.insert(std::pair<std::string,std::vector<Gep::GepCaloCell>>(caloCell.FEB,cellsThisFEB));
275 }
276 }
277
278 Gep::GepCellMap gepCellMap;
279
280 // do truncation
281 auto itr = gepCellsPerFEB.begin();
282 int nFeb2sInOverflow = 0;
283 for ( ;itr != gepCellsPerFEB.end(); ++itr) {
284
285 // LAr FEBs might overflow, so they will get truncated
286 if (m_doTruncationOfOverflowingFEBs && itr->second.size() > m_maxCellsPerFEB && itr->first != "Tile" && (!m_writeAllCells || m_cleanOutputCells)) {
287 ATH_MSG_DEBUG("FEB " << itr->first << " is sending " << itr->second.size() << " cells, which is more cells than GEP can receive. Removing all but the possible " << m_maxCellsPerFEB << " cells.");
289 ++nFeb2sInOverflow;
290 }
291 for (const Gep::GepCaloCell& cell : itr->second)
292 gepCellMap.insert(cell.id, cell);
293 }
294 ATH_MSG_DEBUG("GEP is receiving a total of " << gepCellMap.size() << " cells in this event");
295 gepCellMap.setNumberOfOverflowingFEB2s(nFeb2sInOverflow);
296
298 ATH_CHECK( h_gepCellMap.record( std::make_unique<Gep::GepCellMap>(gepCellMap) ) );
299
300 return StatusCode::SUCCESS;
301}
302
303
304
305int GepCellsHandlerAlg::getGepEnergy(float offline_et) const {
306
307 // If cell saturates readout range, largest possible value is send
308 if (offline_et > m_readoutRanges[4])
310
311 int readoutRange = 0;
312 for (int i = 1; i <= 3; ++i) {
313 if (offline_et > m_readoutRanges[i]) readoutRange = i;
314 }
315
316 float step = (static_cast<float>(m_readoutRanges[readoutRange+1]) - static_cast<float>(m_readoutRanges[readoutRange])) / m_stepsPerRange;
317 int gep_energy = -1;
318 for (int i = 0; i < m_stepsPerRange; ++i) {
319 gep_energy = m_readoutRanges[readoutRange]+(step*i);
320 if (offline_et < (m_readoutRanges[readoutRange]+(step*(i+1)))) break;
321 }
322
323 return gep_energy;
324}
325
326
327
328// Get neighbours of a given calo cell
329std::vector<unsigned int> GepCellsHandlerAlg::getNeighbours(const CaloCellContainer& allcells,
330 const CaloCell* acell,
331 const EventContext&) const {
332
333 // get all neighboring cells
334 std::vector<IdentifierHash> cellNeighbours;
335
336 IdentifierHash cellHashID = m_CaloCell_ID->calo_cell_hash(acell->ID());
337 m_CaloCell_ID->get_neighbours(cellHashID,LArNeighbours::super3D,cellNeighbours);
338
339 std::vector<unsigned int> neighbour_ids;
340 for (unsigned int iNeighbour = 0;
341 iNeighbour < cellNeighbours.size();
342 ++iNeighbour) {
343
344 const CaloCell* neighbour = allcells.findCell(cellNeighbours[iNeighbour]);
345 if (neighbour) {
346 neighbour_ids.push_back((neighbour->ID().get_identifier32()).get_compact());
347 } else {
348 ATH_MSG_ERROR("Couldn't access neighbour #" << iNeighbour
349 << " for cell ID "
350 << (acell->ID().get_identifier32()).get_compact());
351 }
352 }
353 return neighbour_ids;
354}
355
356
357
358StatusCode GepCellsHandlerAlg::removeCellsFromOverloadedFEB(std::vector<Gep::GepCaloCell> &cells) const {
359
360 std::map<int,Gep::GepCaloCell> orderedCells;
361 for (const Gep::GepCaloCell& cell : cells)
362 orderedCells.insert(std::pair<int,Gep::GepCaloCell>(cell.channel,cell));
363
364 cells.clear();
365
366 std::map<int,Gep::GepCaloCell>::iterator cell_itr = orderedCells.begin();
367 for ( ;cell_itr != orderedCells.end(); ++cell_itr) {
368 cells.push_back(cell_itr->second);
369 if (!m_cleanOutputCells && cells.size() == m_maxCellsPerFEB) break;
370 else if (m_cleanOutputCells && cells.size() > m_maxCellsPerFEB) {
371 cells.back().offline_et = 0;
372 cells.back().e = 0;
373 cells.back().et = 0;
374 }
375 }
376
377 return StatusCode::SUCCESS;
378}
#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)
#define CHECK(...)
Evaluate an expression and check for errors.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
Container class for CaloCell.
const CaloCell * findCell(const IdentifierHash theHash) const
fast find method given identifier hash.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
This is a base class for LAr and Tile Descriptors The primary goal is to speed up loops over all the ...
double deta() const
delta eta
double dphi() const
delta phi
float getNoise(const IdentifierHash h, const int gain) const
Accessor by IdentifierHash and gain.
Definition CaloNoise.h:35
static std::string getSamplingName(CaloSample theSample)
Returns a string (name) for each CaloSampling.
std::map< unsigned int, Gep::GepCaloCell > m_gepCellsBase
Gaudi::Property< std::string > m_GepEnergyEncodingScheme
Gaudi::Property< bool > m_cleanOutputCells
Gaudi::Property< bool > m_doTruncationOfOverflowingFEBs
virtual StatusCode execute(const EventContext &) const override
virtual StatusCode initialize() override
Gaudi::Property< std::string > m_LArCellMap
GepCellsHandlerAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadCondHandleKey< CaloNoise > m_totalNoiseKey
Gaudi::Property< bool > m_writeAllCells
StatusCode setG(int value)
StatusCode setNumberOfEnergyBits(int value)
SG::WriteHandleKey< Gep::GepCellMap > m_outputGepCellsKey
StatusCode removeCellsFromOverloadedFEB(std::vector< Gep::GepCaloCell > &cells) const
SG::ReadCondHandleKey< CaloNoise > m_electronicNoiseKey
Key of the CaloNoise Conditions data object.
int getGepEnergy(float offline_et) const
StatusCode setLeastSignificantBit(int value)
Gaudi::Property< bool > m_doGepHardwareStyleEnergyEncoding
SG::ReadHandleKey< CaloCellContainer > m_caloCellsKey
std::vector< unsigned int > getNeighbours(const CaloCellContainer &allcells, const CaloCell *acell, const EventContext &) const
const CaloCell_ID * m_CaloCell_ID
void setNumberOfOverflowingFEB2s(int n)
Definition GepCellMap.h:37
unsigned int size()
Definition GepCellMap.h:25
void insert(unsigned int id, const Gep::GepCaloCell &cell)
Definition GepCellMap.h:21
This is a "hash" representation of an Identifier.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
unsigned int sampling
Definition GepCaloCell.h:49
unsigned int provenance
Definition GepCaloCell.h:19
std::string connection_type
Definition GepCaloCell.h:55
unsigned int quality
Definition GepCaloCell.h:18
unsigned int id
Definition GepCaloCell.h:50
std::vector< unsigned int > neighbours
Definition GepCaloCell.h:57
std::string detName
Definition GepCaloCell.h:51
std::string FEB
Definition GepCaloCell.h:52
TFile * file