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_neighKey.initialize());
57 CHECK(m_phimaxKey.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
76 std::vector<const CaloCell*> cells;
77 CHECK(m_cellProducer->cells(cells, ctx));
78 ATH_MSG_DEBUG(cells.size() <<"Cells read in");
79
80 std::vector<const xAOD::eFexEMRoI*> rois;
81 CHECK(m_roiAlgTool->RoIs(rois, ctx));
82 ATH_MSG_DEBUG(rois.size() << " RoI(s) read in");
83
84 // find cells in the neighborhood of RoIs.
85 // A neighborhood is a collection of CellData objects which
86 // contain cell eta, phi and Et.
87
88 auto neighborhoodTOBs = std::make_unique<IOBitwise::eEmNbhoodTOBContainer>();
89 auto phimax = std::make_unique<std::vector<int>>();
90
91 CHECK(findNeighborhoods_RowAware(rois, cells, *neighborhoodTOBs, *phimax));
92
95
97 if(m_dump || m_dumpTerse){
98 if (m_dump) {
99 CHECK(dumper.dump(name(), *eventInfo, *neighborhoodTOBs));
100 }
101
102 if (m_dumpTerse) {
103 CHECK(dumper.dumpTerse(name(), *eventInfo, *neighborhoodTOBs));
104 }
105 }
106
107 CHECK(h_neighborhoodTOBs.record(std::move(neighborhoodTOBs)));
108 CHECK(h_phimax.record(std::move(phimax)));
109
110 return StatusCode::SUCCESS;
111 }
112
113 StatusCode
114 Egamma1_LArStrip_Fex_RowAware::findNeighborhoods_RowAware(const std::vector<const xAOD::eFexEMRoI*>& rois,
115 const std::vector<const CaloCell*>& cells,
116 IOBitwise::eEmNbhoodTOBContainer& neighborhoodTOBs,
117 std::vector<int>& phimax) const{
118
119 for (const auto& roi : rois) {
120 CHECK(findNeighborhood_RowAware(roi, cells, neighborhoodTOBs, phimax));
121 }
122
123 return StatusCode::SUCCESS;
124 }
125
126
127 StatusCode
129 const std::vector<const CaloCell*>& cells,
130 IOBitwise::eEmNbhoodTOBContainer& neighborhoodTOBs,
131 std::vector<int>& phimax) const {
132
133 // this member function constructs an LArStripNeighborhood.
134 //
135 // A neighourhood is constructed from StripData objects constructed
136 // from CalCells (strips) in the vicinity of an EM RoI the following manner:
137 //
138 // - the cell in the vicinity of the RoI is identified. The neighboorhood
139 // strips are the strups centered on the maximum energy strip.
140 //
141 // In more detail:
142 // A rectangular eta-phi subset of all strips is made.
143 // This subset constains the cells needed for the maximum energy search
144 // and for any subsequent neigborhood strip selection.
145 //
146 // The eta window for the initial selection ismade with half-width of
147 // 0.05 + 8.5* DeltaEta where DeltaEta = 0.003125, the nominal strip width
148 // in eta. A cut-oof off eta = +-1.4 is applied in the selection.
149 //
150 // Phi selection consists of calculating a phi index for the the RoI,
151 // then requiring selected strips to be have a phi indix within +=1 of
152 // the RoI phi index.
153 //
154 // The strips used to identigy the max energy strip the are within +-1 of the
155 // as the phi index of the RoI, and eta that lies within 0.1 in eta to the RoI.
156 //
157 // The strips selected for the Neighborhood have eta within +- 8.5 DeltaEta
158 // of the max energy strip, and +- 1 of the max RoI strip phi Index.
159
160 auto cells_near_roi = std::vector<const CaloCell*>();
161
162 ATH_MSG_DEBUG("roi eta " << roi->eta() << " phi " << roi->phi());
163
164 // lambda function to calculate the phi index of a eta-phi point
165 auto phi_ind = [](const auto& c) {
166 constexpr double dphi = std::numbers::pi/32;
167 std::size_t iphi = 32 + int(std::floor(c->phi()/dphi));
168 return iphi > 63 ?
169 std::optional<std::size_t>() : std::make_optional(iphi);
170 };
171
172 const std::optional<std::size_t> roi_phi_index_opt = phi_ind(roi);
173 if (not roi_phi_index_opt.has_value()) {
174 return StatusCode::FAILURE;
175 }
176 const std::size_t roi_phi_index = *roi_phi_index_opt;
177
178 // obtain adjacent phi indices
179 auto roi_phi_indices = *wrap5(roi_phi_index);
180
181 // container for strips close to RoI in eta
182 auto close = std::deque<std::vector<const CaloCell*>>(5);
183 for (auto& v :close) {v.reserve(100);}
184
185 //One ROI is 0.1 wide in eta, this is the half width
186 constexpr double half_deta_roi{0.05};
187 //One cell in the barrel is 0.003125, this is the half width of the 17 cell window
188 constexpr double half_deta_neigh{8.5*0.003125};
189 //To define the ±eta limit of our window, we need to sum the above
190 constexpr double half_deta_fid{half_deta_roi + half_deta_neigh};
191
192
193 double etalim_low = std::max(roi->eta()-half_deta_fid, -1.4);
194 double etalim_high = std::min(roi->eta()+half_deta_fid, 1.4);
195
196
197 // double loop. outer: all strips. inner: adjacent roi indices.
198 for (const auto& cell : cells) {
199 auto icell = *phi_ind(cell);
200 std::size_t pos{0};
201 for(const auto& iroi : roi_phi_indices) {
202 auto c_eta = cell->eta();
203 if (iroi == icell and c_eta >= etalim_low and c_eta < etalim_high) {
204 close[pos].push_back(cell);
205 break;
206 }
207 ++pos;
208 }
209 }
210
211 // select the cells within a a tower width of the RoI. Then find the
212 // cell in this selction with the highest energy
213 auto roi_cells = std::deque<std::vector<const CaloCell*>>(5);
214 auto roi_max_it = std::vector<std::vector<const CaloCell*>::iterator>();
215
216 for (std::size_t i{0ul}; i != close.size(); ++i) {
217 roi_cells[i].reserve(close[i].size());
218 std::copy_if(std::begin(close[i]),
219 std::end(close[i]),
220 std::back_inserter(roi_cells[i]),
221 [&roi](const auto& c) {
222 return std::abs(c->eta() - roi->eta()) < half_deta_roi;
223 });
224 //Work out where the max is in the central block.
225 if(i > 0 && i < 4){
226 auto it = std::max_element(std::begin(roi_cells[i]),
227 std::end(roi_cells[i]),
228 [](const auto& l,const auto& r) {
229 return l->e() < r->e();
230 });
231 ATH_MSG_DEBUG("max cell row "
232 << i << " position "
233 << std::distance(std::begin(roi_cells[i]), it)
234 << " :" << **it);
235 roi_max_it.push_back(it);
236 }
237 }
238
239 auto max_row = std::max_element(std::begin(roi_max_it),
240 std::end(roi_max_it),
241 [](const auto& l,const auto& r) {
242 return (*l)->e() < (*r)->e();
243 });
244
245 int max_row_pos = std::distance( roi_max_it.begin(), max_row );
246
247 phimax.push_back(max_row_pos);
248
249 ATH_MSG_DEBUG("max cell row "
250 << ' ' << std::distance( roi_max_it.begin(), max_row )+1);
251
252 //If the maximum is not in the centre row, we need to re-seed
253 switch(max_row_pos)
254 {
255 case 0:
256 {
257 close.pop_back();
258 close.pop_back();
259 break;
260 }
261 case 1:
262 {
263 close.pop_front();
264 close.pop_back();
265 break;
266 }
267 case 2:
268 {
269 close.pop_front();
270 close.pop_front();
271 break;
272 }
273 }
274
275 ATH_MSG_DEBUG("popped ");
276
277 // set up Cell containers for the neighborhood. One container
278 // per adjacent RoI phi indices.
279 auto neigh_cells = std::vector<std::vector<const CaloCell*>>(3);
280
281 const CaloCell* max_cell{*(*max_row)};
282 const auto max_cell_eta = max_cell->eta();
283
284 ATH_MSG_DEBUG("Got the max cell");
285
286 for (std::size_t iv{0ul}; iv != close.size(); ++iv) {
287 std::copy_if(std::begin(close[iv]),
288 std::end(close[iv]),
289 std::back_inserter(neigh_cells[iv]),
290 [&max_cell_eta, &half_deta_neigh](const auto& c){
291 return abs(c->eta()-max_cell_eta) < half_deta_neigh;
292 });
293 }
294
295 ATH_MSG_DEBUG("Made our neighbourhood");
296
297 auto max_neigh_cell_it = std::find(std::begin(neigh_cells[1]),
298 std::end(neigh_cells[1]),
299 max_cell);
300 if (max_neigh_cell_it == std::end(neigh_cells[1])){
301 ATH_MSG_ERROR("Lost the max cell");
302 return StatusCode::FAILURE;
303 }
304
305 auto max_neigh_cell_pos{std::distance(std::begin(neigh_cells[1]),
306 max_neigh_cell_it)};
307
308 ATH_MSG_DEBUG("Rediscovered our neighbourhood max");
309
310 auto toStripData = [](const auto& fromCells){
311 auto stripdata = std::vector<StripData>();
312 stripdata.reserve(fromCells.size());
313 std::transform(std::begin(fromCells),
314 std::end(fromCells),
315 back_inserter(stripdata),
316 [](const auto& c) {
317 return StripData(c->eta(),
318 c->phi(),
319 c->e());});
320 return stripdata;
321 };
322
323 auto low = toStripData(neigh_cells[0]);
324 auto center = toStripData(neigh_cells[1]);
325 auto high = toStripData(neigh_cells[2]);
326
327 Coords roi_c{roi->eta(), roi->phi()};
328 Coords cell_c{max_cell->eta(), max_cell->phi()};
329
330 ATH_MSG_DEBUG("Fill with strip data");
331
332 LArStripNeighborhood neighborhood = LArStripNeighborhood(low, center, high, roi_c, cell_c, max_neigh_cell_pos);
333
334 neighborhoodTOBs.push_back(std::make_unique<IOBitwise::eEmNbhoodTOB>(*roi, neighborhood));
335
336 return StatusCode::SUCCESS;
337 }
338}
#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.
StatusCode findNeighborhood_RowAware(const xAOD::eFexEMRoI *, const std::vector< const CaloCell * > &, IOBitwise::eEmNbhoodTOBContainer &, std::vector< int > &) const
SG::WriteHandleKey< IOBitwise::eEmNbhoodTOBContainer > m_neighKey
virtual StatusCode execute(const EventContext &) const override
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
SG::WriteHandleKey< std::vector< int > > m_phimaxKey
Egamma1_LArStrip_Fex_RowAware(const std::string &name, ISvcLocator *pSvcLocator)
StatusCode findNeighborhoods_RowAware(const std::vector< const xAOD::eFexEMRoI * > &, const std::vector< const CaloCell * > &, IOBitwise::eEmNbhoodTOBContainer &, std::vector< int > &) const
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