ATLAS Offline Software
Loading...
Searching...
No Matches
Egamma1_LArStrip_Fex_RowAware.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4
5/*
6 This algorithm outputs Calorimeter strip data in the region of
7 eFex RoIs.
8*/
9
12#include "../IO/eEmNbhoodTOB.h"
13
14#include "CaloEvent/CaloCell.h"
15
17
18#include <fstream>
19#include <vector>
20#include <algorithm>
21#include <optional>
22
23namespace GlobalSim {
24
25 std::optional<std::vector<std::size_t>> wrap5(std::size_t center) {
26 if (center > 63) {
27 return std::optional<std::vector<std::size_t>>{};
28 }
29
30 if (center == 63) {
31 return std::make_optional(std::vector<std::size_t>({61ul, 62ul, 63ul, 0ul, 1ul}));
32 }
33
34 if (center == 0) {
35 return std::make_optional(std::vector<std::size_t>({62ul, 63ul, 0ul, 1ul, 2ul}));
36 }
37
38 return std::make_optional(std::vector<std::size_t>(
39 {center-2,
40 center-1,
41 center,
42 center+1,
43 center+2}));
44 }
45
46 Egamma1_LArStrip_Fex_RowAware::Egamma1_LArStrip_Fex_RowAware(const std::string& name, ISvcLocator* pSvcLocator ) :
47 AthReentrantAlgorithm(name, pSvcLocator){
48 }
49
50
52 ATH_MSG_INFO ("Initializing " << name());
53
54 CHECK(m_cellProducer.retrieve());
55 CHECK(m_roiAlgTool.retrieve());
56 CHECK(m_totalNoiseKey.initialize());
57 CHECK(m_neighKey.initialize());
58 CHECK(m_eventInfoKey.initialize());
59
60 return StatusCode::SUCCESS;
61 }
62
63
64 StatusCode Egamma1_LArStrip_Fex_RowAware::execute(const EventContext& ctx) const {
65 // Read in a CaloCell container. Ask producers to create
66 // vectors of CaloCells to be examined.
67
68 ATH_MSG_DEBUG ("Executing");
69
71 if(!eventInfo.isValid()) {
72 ATH_MSG_ERROR ("Error obtaining EventInfo object");
73 return StatusCode::FAILURE;
74 }
75
77 if (!totalNoiseHdl.isValid()) {return StatusCode::FAILURE;}
78 const CaloNoise* totalNoiseCDO = *totalNoiseHdl;
79
80 std::vector<const CaloCell*> cells;
81 CHECK(m_cellProducer->cells(cells, ctx));
82 ATH_MSG_DEBUG(cells.size() <<"Cells read in");
83
84 std::vector<const xAOD::eFexEMRoI*> rois;
85 CHECK(m_roiAlgTool->RoIs(rois, ctx));
86 ATH_MSG_DEBUG(rois.size() << " RoI(s) read in");
87
88 // find cells in the neighborhood of RoIs.
89 // A neighborhood is a collection of CellData objects which
90 // contain cell eta, phi and Et.
91
92 auto neighborhoodTOBs = std::make_unique<IOBitwise::eEmNbhoodTOBContainer>();
93
94 CHECK(findNeighborhoods_RowAware(rois, cells, *neighborhoodTOBs, *totalNoiseCDO));
95
97
99 if(m_dump || m_dumpTerse){
100 if (m_dump) {
101 CHECK(dumper.dump(name(), *eventInfo, *neighborhoodTOBs));
102 }
103
104 if (m_dumpTerse) {
105 CHECK(dumper.dumpTerse(name(), *eventInfo, *neighborhoodTOBs));
106 }
107 }
108
109 CHECK(h_neighborhoodTOBs.record(std::move(neighborhoodTOBs)));
110
111 return StatusCode::SUCCESS;
112 }
113
114 StatusCode
115 Egamma1_LArStrip_Fex_RowAware::findNeighborhoods_RowAware(const std::vector<const xAOD::eFexEMRoI*>& rois,
116 const std::vector<const CaloCell*>& cells,
117 IOBitwise::eEmNbhoodTOBContainer& neighborhoodTOBs,
118 const CaloNoise& noise) const{
119
120 for (const auto& roi : rois) {
121 //kill low energy RoIs
122 if(roi->et() > 5000){ // MeV
123 CHECK(findNeighborhood_RowAware(roi, cells, neighborhoodTOBs, noise));
124 }
125 }
126
127 return StatusCode::SUCCESS;
128 }
129
130
131 StatusCode
133 const std::vector<const CaloCell*>& cells,
134 IOBitwise::eEmNbhoodTOBContainer& neighborhoodTOBs,
135 const CaloNoise& noise) const {
136
137 // this member function constructs an LArStripNeighborhood.
138 //
139 // A neighourhood is constructed from StripData objects constructed
140 // from CalCells (strips) in the vicinity of an EM RoI the following manner:
141 //
142 // - the cell in the vicinity of the RoI is identified. The neighboorhood
143 // strips are the strups centered on the maximum energy strip.
144 //
145 // In more detail:
146 // A rectangular eta-phi subset of all strips is made.
147 // This subset constains the cells needed for the maximum energy search
148 // and for any subsequent neigborhood strip selection.
149 //
150 // The eta window for the initial selection ismade with half-width of
151 // 0.05 + 8.5* DeltaEta where DeltaEta = 0.003125, the nominal strip width
152 // in eta. A cut-oof off eta = +-1.4 is applied in the selection.
153 //
154 // Phi selection consists of calculating a phi index for the the RoI,
155 // then requiring selected strips to be have a phi indix within +=1 of
156 // the RoI phi index.
157 //
158 // The strips used to identigy the max energy strip the are within +-1 of the
159 // as the phi index of the RoI, and eta that lies within 0.1 in eta to the RoI.
160 //
161 // The strips selected for the Neighborhood have eta within +- 8.5 DeltaEta
162 // of the max energy strip, and +- 1 of the max RoI strip phi Index.
163
164 auto cells_near_roi = std::vector<const CaloCell*>();
165
166 ATH_MSG_DEBUG("roi eta " << roi->eta() << " phi " << roi->phi());
167
168 // lambda function to calculate the phi index of a eta-phi point
169 auto phi_ind = [](const auto& c) {
170 constexpr double dphi = std::numbers::pi/32;
171 std::size_t iphi = 32 + int(std::floor(c->phi()/dphi));
172 return iphi > 63 ?
173 std::optional<std::size_t>() : std::make_optional(iphi);
174 };
175
176 const std::optional<std::size_t> roi_phi_index_opt = phi_ind(roi);
177 if (not roi_phi_index_opt.has_value()) {
178 return StatusCode::FAILURE;
179 }
180 const std::size_t roi_phi_index = *roi_phi_index_opt;
181
182 // obtain adjacent phi indices
183 auto roi_phi_indices = *wrap5(roi_phi_index);
184
185 // container for strips close to RoI in eta
186 auto close = std::deque<std::vector<const CaloCell*>>(5);
187 for (auto& v :close) {v.reserve(100);}
188
189 //One ROI is 0.1 wide in eta, this is the half width
190 constexpr double half_deta_roi{0.05};
191 //One cell in the barrel is 0.003125, this is the half width of the 17 cell window
192 constexpr double half_deta_neigh{8.5*0.003125};
193 //To define the ±eta limit of our window, we need to sum the above
194 constexpr double half_deta_fid{half_deta_roi + half_deta_neigh};
195
196
197 double etalim_low = std::max(roi->eta()-half_deta_fid, -1.4);
198 double etalim_high = std::min(roi->eta()+half_deta_fid, 1.4);
199
200
201 // double loop. outer: all strips. inner: adjacent roi indices.
202 for (const auto& cell : cells) {
203 auto icell = *phi_ind(cell);
204 std::size_t pos{0};
205 for(const auto& iroi : roi_phi_indices) {
206 auto c_eta = cell->eta();
207 if (iroi == icell and c_eta >= etalim_low and c_eta < etalim_high) {
208 float totalNoise = noise.getNoise(cell->ID(), cell->gain());
209 if(totalNoise <= 0.0) totalNoise = 0.001;
210 float sigma = cell->energy() / totalNoise;
211 if(sigma >= 2){
212 close[pos].push_back(cell);
213 } else {
214 close[pos].push_back(new CaloCell(cell->caloDDE(), 0.0, cell->time(), cell->quality(), cell->provenance(), cell->gain()));
215 }
216 break;
217 }
218 ++pos;
219 }
220 }
221
222 // select the cells within a a tower width of the RoI. Then find the
223 // cell in this selction with the highest energy
224 auto roi_cells = std::deque<std::vector<const CaloCell*>>(5);
225 auto roi_max_it = std::vector<std::vector<const CaloCell*>::iterator>();
226
227 for (std::size_t i{0ul}; i != close.size(); ++i) {
228 roi_cells[i].reserve(close[i].size());
229 std::copy_if(std::begin(close[i]),
230 std::end(close[i]),
231 std::back_inserter(roi_cells[i]),
232 [&roi](const auto& c) {
233 return std::abs(c->eta() - roi->eta()) < half_deta_roi;
234 });
235 //Work out where the max is in the central block.
236 if(i > 0 && i < 4){
237 auto it = std::max_element(std::begin(roi_cells[i]),
238 std::end(roi_cells[i]),
239 [](const auto& l,const auto& r) {
240 return l->e() < r->e();
241 });
242 ATH_MSG_DEBUG("max cell row "
243 << i << " position "
244 << std::distance(std::begin(roi_cells[i]), it)
245 << " :" << **it);
246 roi_max_it.push_back(it);
247 }
248 }
249
250 auto max_row = std::max_element(std::begin(roi_max_it),
251 std::end(roi_max_it),
252 [](const auto& l,const auto& r) {
253 return (*l)->e() < (*r)->e();
254 });
255
256 int max_row_pos = std::distance( roi_max_it.begin(), max_row );
257
258 ATH_MSG_DEBUG("max cell row "
259 << ' ' << std::distance( roi_max_it.begin(), max_row )+1);
260
261 //If the maximum is not in the centre row, we need to re-seed
262 switch(max_row_pos)
263 {
264 case 0:
265 {
266 close.pop_back();
267 close.pop_back();
268 break;
269 }
270 case 1:
271 {
272 close.pop_front();
273 close.pop_back();
274 break;
275 }
276 case 2:
277 {
278 close.pop_front();
279 close.pop_front();
280 break;
281 }
282 }
283
284 ATH_MSG_DEBUG("popped ");
285
286 // set up Cell containers for the neighborhood. One container
287 // per adjacent RoI phi indices.
288 auto neigh_cells = std::vector<std::vector<const CaloCell*>>(3);
289
290 const CaloCell* max_cell{*(*max_row)};
291 const auto max_cell_eta = max_cell->eta();
292
293 ATH_MSG_DEBUG("Got the max cell");
294
295 for (std::size_t iv{0ul}; iv != close.size(); ++iv) {
296 std::copy_if(std::begin(close[iv]),
297 std::end(close[iv]),
298 std::back_inserter(neigh_cells[iv]),
299 [&max_cell_eta, &half_deta_neigh](const auto& c){
300 return abs(c->eta()-max_cell_eta) < half_deta_neigh;
301 });
302 }
303
304 ATH_MSG_DEBUG("Made our neighbourhood");
305
306 auto max_neigh_cell_it = std::find(std::begin(neigh_cells[1]),
307 std::end(neigh_cells[1]),
308 max_cell);
309 if (max_neigh_cell_it == std::end(neigh_cells[1])){
310 ATH_MSG_ERROR("Lost the max cell");
311 return StatusCode::FAILURE;
312 }
313
314 auto max_neigh_cell_pos{std::distance(std::begin(neigh_cells[1]),
315 max_neigh_cell_it)};
316
317 ATH_MSG_DEBUG("Rediscovered our neighbourhood max");
318
319 auto toStripData = [](const auto& fromCells){
320 auto stripdata = std::vector<StripData>();
321 stripdata.reserve(fromCells.size());
322 std::transform(std::begin(fromCells),
323 std::end(fromCells),
324 back_inserter(stripdata),
325 [](const auto& c) {
326 return StripData(c->eta(),
327 c->phi(),
328 c->e());});
329 return stripdata;
330 };
331
332 auto low = toStripData(neigh_cells[0]);
333 auto center = toStripData(neigh_cells[1]);
334 auto high = toStripData(neigh_cells[2]);
335
336 Coords roi_c{roi->eta(), roi->phi()};
337 Coords cell_c{max_cell->eta(), max_cell->phi()};
338
339 ATH_MSG_DEBUG("Fill with strip data");
340
341 LArStripNeighborhood neighborhood = LArStripNeighborhood(low, center, high, roi_c, cell_c, max_neigh_cell_pos);
342
343 neighborhoodTOBs.push_back(std::make_unique<IOBitwise::eEmNbhoodTOB>(*roi, neighborhood));
344
345 return StatusCode::SUCCESS;
346 }
347}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
An algorithm that can be simultaneously executed in multiple threads.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::ReadCondHandleKey< CaloNoise > m_totalNoiseKey
Key to the total noise used for each CaloCell.
SG::WriteHandleKey< IOBitwise::eEmNbhoodTOBContainer > m_neighKey
virtual StatusCode execute(const EventContext &) const override
StatusCode findNeighborhood_RowAware(const xAOD::eFexEMRoI *, const std::vector< const CaloCell * > &, IOBitwise::eEmNbhoodTOBContainer &, const CaloNoise &) const
StatusCode findNeighborhoods_RowAware(const std::vector< const xAOD::eFexEMRoI * > &, const std::vector< const CaloCell * > &, IOBitwise::eEmNbhoodTOBContainer &, const CaloNoise &) const
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Egamma1_LArStrip_Fex_RowAware(const std::string &name, ISvcLocator *pSvcLocator)
Class to hold windows of LAr strip cells in a the neighbourhood of a eFexRoI.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
float eta() const
setter for the above
float phi() const
Seed supercell index within central tower (0 -> 3)
int r
Definition globals.cxx:22
DataVector< GlobalSim::IOBitwise::eEmNbhoodTOB > eEmNbhoodTOBContainer
AlgTool that to test whether expected the TIP values generated by data supplied by eEmMultTestBench c...
std::optional< std::vector< std::size_t > > wrap5(std::size_t center)
std::pair< double, double > Coords
eFexEMRoI_v1 eFexEMRoI
Define the latest version of the eFexEMRoI class.
Definition eFexEMRoI.h:17