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) 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");
41
42 // Setting up GEP energy encoding scheme
44
45 // Read values of Gep readout scheme from argument
46 int GepScheme[3];
47 for (int i = 0; i < 3; ++i) {
48 GepScheme[i] = std::stoi(m_GepEnergyEncodingScheme.value().substr(0,m_GepEnergyEncodingScheme.value().find("-")));
49 m_GepEnergyEncodingScheme.value().erase(0, m_GepEnergyEncodingScheme.value().find("-")+1);
50 }
51
52 CHECK(setNumberOfEnergyBits(GepScheme[0]));
53 CHECK(setLeastSignificantBit(GepScheme[1]));
54 CHECK(setG(GepScheme[2]));
55
56 m_stepsPerRange = std::pow(2,m_nEnergyBits-2);
57
58 m_readoutRanges[0] = 0;
63
64 ATH_MSG_DEBUG("Readout scheme with " << m_nEnergyBits << "-bits provides the following four energy thresholds (with " << m_stepsPerRange << " discrete steps on each threshold)");
65 ATH_MSG_DEBUG("GEP cell energy range 0: min = " << m_readoutRanges[0] << " MeV -> max = " << m_readoutRanges[1] << " MeV");
66 ATH_MSG_DEBUG("GEP cell energy range 1: min = " << m_readoutRanges[1] + m_valLeastSigBit << " MeV -> max = " << m_readoutRanges[2] << " MeV");
67 ATH_MSG_DEBUG("GEP cell energy range 2: min = " << m_readoutRanges[2]+(m_valG*m_valLeastSigBit) << " MeV -> max = " << m_readoutRanges[3] << " MeV");
68 ATH_MSG_DEBUG("GEP cell energy range 3: min = " << m_readoutRanges[3]+(m_valG*m_valG*m_valLeastSigBit) << " MeV -> max = " << m_readoutRanges[4] << " MeV");
69 }
70
72 // Loading the invariant cell data and storing in m_gepCellsBase for later use on event-by-event basis
73 m_gepCellsBase.clear();
74
75 ATH_MSG_DEBUG("Loading cell map associating cells to FEBs");
76
77 std::string cellMapPath = PathResolverFindCalibFile(m_LArCellMap);
78 if(cellMapPath.empty()) ATH_MSG_ERROR("Could not find file with cell map data: " << m_LArCellMap.value());
79
80 std::ifstream file(cellMapPath.c_str());
81
82 unsigned n_cells = 0;
83
84 // Read input file
85 if (file.is_open()) {
86
87 int online_id, offline_id, ch, con_num, fbr;
88 std::string feb, con_type;
89
90 // Skipping header of file
91 std::getline(file, feb);
92
93 // start reading data
94 while (true) {
95
96 file >> offline_id >> online_id >> feb >> ch >> con_type >> con_num >> fbr;
97
98 if (file.eof()) break;
99
100 Gep::GepCaloCell caloCell;
101 caloCell.id = offline_id;
102 caloCell.FEB = feb;
103 caloCell.channel = ch;
104 caloCell.fiber = fbr;
105 caloCell.connection_type = con_type;
106 caloCell.connection_number = con_num;
107
108 m_gepCellsBase.insert(std::pair<unsigned int, Gep::GepCaloCell>(caloCell.id, caloCell));
109
110 ++n_cells;
111 }
112 }
113 else {
114 ATH_MSG_ERROR("Could not open file containing the cell to FEB association");
115 return StatusCode::FAILURE;
116 }
117
118 ATH_MSG_DEBUG("Loaded FEB information for " << n_cells << " cells");
119 }
120
121 return StatusCode::SUCCESS;
122}
123
124
125StatusCode GepCellsHandlerAlg::execute(const EventContext& ctx) const {
126
127 // PS this function creates and stores a map which has Gep::GepCaloCells as its values
128 // The cells are made up of data which is invariant for all events, and dynamic
129 // data which varies with event.
130 // The invariant data should be setup in initialize(), and the dynamic
131 // data should be updated here in a way which is compatible with the const-ness of this
132 // function.
133 // This will be attended to in the future.
134
135 ATH_MSG_DEBUG ("Executing " << name() << "...");
136
137 // Read in a container containing (all) CaloCells
138 auto h_caloCells = SG::makeHandle(m_caloCellsKey, ctx);
139 CHECK(h_caloCells.isValid());
140 const auto & cells = *h_caloCells;
141
142 ATH_MSG_DEBUG("Read in " + std::to_string(h_caloCells->size()) + " cells");
143
145 if (!electronicNoiseHdl.isValid()) {return StatusCode::FAILURE;}
146 const CaloNoise* electronicNoiseCDO = *electronicNoiseHdl;
147
149 if (!totalNoiseHdl.isValid()) {return StatusCode::FAILURE;}
150 const CaloNoise* totalNoiseCDO = *totalNoiseHdl;
151
152 int idx = -1;
153 std::map<std::string,std::vector<Gep::GepCaloCell>> gepCellsPerFEB;
154
155 for(const auto *cell: cells){
156
157 Gep::GepCaloCell caloCell;
158 ++idx;
159
160 caloCell.id = (cell->ID().get_identifier32()).get_compact();
161 auto base_cell_itr = m_gepCellsBase.find(caloCell.id);
162 if (base_cell_itr != m_gepCellsBase.end()) caloCell = base_cell_itr->second;
163 else {
164 // Tile cells are not included in the cell base map
165 // In the future this might change, for now just setting FEB value to a dummy
166 caloCell.FEB = "Tile";
167 }
168
169 float electronicNoise = electronicNoiseCDO->getNoise(cell->ID(), cell->gain());
170 float totalNoise = totalNoiseCDO->getNoise(cell->ID(), cell->gain());
171
172 // Only send positive-energy 2sigma cells to the GEP
173 if (((cell->energy() / totalNoise) < 2.0) && !m_writeAllCells) continue;
174
175 // GEP will only have ET available for LAr cells, so convert to energy from ET
176 caloCell.offline_et = cell->energy() / TMath::CosH(cell->eta());
177 if (m_doGepHardwareStyleEnergyEncoding && !m_CaloCell_ID->is_tile(cell->ID())) {
178 caloCell.et = getGepEnergy(cell->energy() / TMath::CosH(cell->eta()));
179 caloCell.e = caloCell.et * TMath::CosH(cell->eta());
180 }
181 else {
182 caloCell.e = cell->energy();
183 caloCell.et = caloCell.offline_et;
184 }
185 caloCell.time = cell->time();
186 caloCell.quality = cell->quality();
187 caloCell.provenance = cell->provenance();
188
189 caloCell.totalNoise = totalNoise;
190 caloCell.electronicNoise = electronicNoise;
191 caloCell.sigma = cell->energy() / totalNoise;
192
193 caloCell.isBad = cell->badcell();
194 caloCell.eta = cell->eta();
195 caloCell.phi = cell->phi();
196 caloCell.sinTh = cell->sinTh();
197 caloCell.cosTh = cell->cosTh();
198 caloCell.sinPhi = cell->sinPhi();
199 caloCell.cosPhi = cell->cosPhi();
200 caloCell.cotTh = cell->cotTh();
201 caloCell.x = cell->x();
202 caloCell.y = cell->y();
203 caloCell.z = cell->z();
204
205 unsigned int samplingEnum = m_CaloCell_ID->calo_sample(cell->ID());
206
207 bool IsEM = m_CaloCell_ID->is_em(cell->ID());
208 bool IsEM_Barrel=false;
209 bool IsEM_EndCap=false;
210 bool IsEM_BarrelPos=false;
211 bool IsEM_BarrelNeg=false;
212 if(IsEM){
213 IsEM_Barrel=m_CaloCell_ID->is_em_barrel(cell->ID());
214 if(IsEM_Barrel){
215 if(m_CaloCell_ID->pos_neg(cell->ID())>0) IsEM_BarrelPos=true;
216 }
217 IsEM_EndCap=m_CaloCell_ID->is_em_endcap(cell->ID());
218 }
219
220 caloCell.isEM = IsEM;
221 caloCell.isEM_barrel = IsEM_Barrel;
222 caloCell.isEM_endCap = IsEM_EndCap;
223 caloCell.isEM_barrelPos = IsEM_BarrelPos;
224 caloCell.isEM_barrelNeg = IsEM_BarrelNeg; //always false?
225 caloCell.isFCAL = m_CaloCell_ID->is_fcal(cell->ID());
226 caloCell.isHEC = m_CaloCell_ID->is_hec(cell->ID());
227 caloCell.isTile = m_CaloCell_ID->is_tile(cell->ID());
228
229 caloCell.sampling = samplingEnum;
230 caloCell.detName = CaloSampling::getSamplingName(samplingEnum);
231
232 caloCell.neighbours = getNeighbours(cells, cell, ctx);
233 caloCell.id = (cell->ID().get_identifier32()).get_compact();
234
235 const CaloDetDescriptor *elt = cell->caloDDE()->descriptor();
236 caloCell.layer = cell->caloDDE()->getLayer();
237
238 float deta = elt->deta();
239 float dphi = elt->dphi();
240
241 float etamin = caloCell.eta - (0.5*deta);
242 float etamax = caloCell.eta + (0.5*deta);
243
244 float phimin = caloCell.phi - (0.5*dphi);
245 float phimax = caloCell.phi + (0.5*dphi);
246
247 caloCell.etaMin = etamin;
248 caloCell.etaMax = etamax;
249 caloCell.phiMin = phimin;
250 caloCell.phiMax = phimax;
251 caloCell.etaGranularity = deta;
252 caloCell.phiGranularity = dphi;
253
254 caloCell.index = idx;
255
256 // Fill cells into map according to FEB
257 auto feb_itr = gepCellsPerFEB.find(caloCell.FEB);
258 if (feb_itr != gepCellsPerFEB.end()) feb_itr->second.push_back(std::move(caloCell));
259 else {
260 std::vector<Gep::GepCaloCell> cellsThisFEB;
261 cellsThisFEB.push_back(caloCell);
262 gepCellsPerFEB.insert(std::pair<std::string,std::vector<Gep::GepCaloCell>>(caloCell.FEB,cellsThisFEB));
263 }
264 }
265
266 Gep::GepCellMap gepCellMap;
267
268 // do truncation
269 auto itr = gepCellsPerFEB.begin();
270 int nFeb2sInOverflow = 0;
271 for ( ;itr != gepCellsPerFEB.end(); ++itr) {
272
273 // LAr FEBs might overflow, so they will get truncated
274 if (m_doTruncationOfOverflowingFEBs && itr->second.size() > m_maxCellsPerFEB && itr->first != "Tile" && !m_writeAllCells) {
275 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.");
277 ++nFeb2sInOverflow;
278 }
279 for (const Gep::GepCaloCell& cell : itr->second)
280 gepCellMap.insert(cell.id, cell);
281 }
282 ATH_MSG_DEBUG("GEP is receiving a total of " << gepCellMap.size() << " cells in this event");
283 gepCellMap.setNumberOfOverflowingFEB2s(nFeb2sInOverflow);
284
286 ATH_CHECK( h_gepCellMap.record( std::make_unique<Gep::GepCellMap>(gepCellMap) ) );
287
288 return StatusCode::SUCCESS;
289}
290
291
292
293int GepCellsHandlerAlg::getGepEnergy(float offline_et) const {
294
295 // If cell saturates readout range, largest possible value is send
296 if (offline_et > m_readoutRanges[4])
298
299 int readoutRange = 0;
300 for (int i = 1; i <= 3; ++i) {
301 if (offline_et > m_readoutRanges[i]) readoutRange = i;
302 }
303
304 float step = (static_cast<float>(m_readoutRanges[readoutRange+1]) - static_cast<float>(m_readoutRanges[readoutRange])) / m_stepsPerRange;
305 int gep_energy = -1;
306 for (int i = 0; i < m_stepsPerRange; ++i) {
307 gep_energy = m_readoutRanges[readoutRange]+(step*i);
308 if (offline_et < (m_readoutRanges[readoutRange]+(step*(i+1)))) break;
309 }
310
311 return gep_energy;
312}
313
314
315
316// Get neighbours of a given calo cell
317std::vector<unsigned int> GepCellsHandlerAlg::getNeighbours(const CaloCellContainer& allcells,
318 const CaloCell* acell,
319 const EventContext&) const {
320
321 // get all neighboring cells
322 std::vector<IdentifierHash> cellNeighbours;
323
324 IdentifierHash cellHashID = m_CaloCell_ID->calo_cell_hash(acell->ID());
325 m_CaloCell_ID->get_neighbours(cellHashID,LArNeighbours::super3D,cellNeighbours);
326
327 std::vector<unsigned int> neighbour_ids;
328 for (unsigned int iNeighbour = 0;
329 iNeighbour < cellNeighbours.size();
330 ++iNeighbour) {
331
332 const CaloCell* neighbour = allcells.findCell(cellNeighbours[iNeighbour]);
333 if (neighbour) {
334 neighbour_ids.push_back((neighbour->ID().get_identifier32()).get_compact());
335 } else {
336 ATH_MSG_ERROR("Couldn't access neighbour #" << iNeighbour
337 << " for cell ID "
338 << (acell->ID().get_identifier32()).get_compact());
339 }
340 }
341 return neighbour_ids;
342}
343
344
345
346StatusCode GepCellsHandlerAlg::removeCellsFromOverloadedFEB(std::vector<Gep::GepCaloCell> &cells) const {
347
348 std::map<int,Gep::GepCaloCell> orderedCells;
349 for (const Gep::GepCaloCell& cell : cells)
350 orderedCells.insert(std::pair<int,Gep::GepCaloCell>(cell.channel,cell));
351
352 cells.clear();
353
354 std::map<int,Gep::GepCaloCell>::iterator cell_itr = orderedCells.begin();
355 for ( ;cell_itr != orderedCells.end(); ++cell_itr) {
356 cells.push_back(cell_itr->second);
357 if (cells.size() == m_maxCellsPerFEB) break;
358 }
359
360 return StatusCode::SUCCESS;
361}
362
363
364
365
#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:34
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_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:33
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