ATLAS Offline Software
Loading...
Searching...
No Matches
jFexTower2SCellDecorator.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// jFexTower2SCellDecorator - description
7// -------------------
8// This reentrant algorithm is meant to decorate the FEX Towers (input data and simulation) with the corresponding matching set of SuperCell from LAr
9// Information about SCellContainer objetcs are in:
10// - https://gitlab.cern.ch/atlas/athena/-/blob/22.0/Calorimeter/CaloEvent/CaloEvent/CaloCell.h
11//
12// begin : 01 09 2022
13// email : sergi.rodriguez@cern.ch
14//***************************************************************************/
15
16
19
20#include <iostream>
21#include <fstream>
22#include <sstream>
23#include <algorithm>
24#include <string>
25#include <optional>
26#include <stdio.h>
27
28namespace {
29
30template <class T>
31std::optional<SG::WriteDecorHandle<xAOD::jFexTowerContainer, T> >
33 const EventContext& ctx,
34 bool flag)
35{
36 std::optional<SG::WriteDecorHandle<xAOD::jFexTowerContainer, T> > h;
37 if (flag)
38 h.emplace (key, ctx);
39 return h;
40}
41
42
43}
44
45namespace LVL1 {
46
48
50
51 ATH_MSG_INFO( "Initializing L1CaloFEXTools/jFexTower2SCellDecorator algorithm with name: "<< name());
52 ATH_MSG_INFO( "Decorating SG key: "<< m_jTowersReadKey);
53
54 ATH_CHECK( m_SCellKey.initialize() );
55 ATH_CHECK( m_triggerTowerKey.initialize() );
56 ATH_CHECK( m_jTowersReadKey.initialize() );
57
58 // This will avoid extra variables when the Key is different than DataTowers
59 if( (m_jTowersReadKey.key()).compare("L1_jFexDataTowers") != 0 ){
60 m_save_emulated_var = false;
61 }
62
63 //Decarator keys
64 ATH_CHECK( m_jtowerEtMeVdecorKey.initialize() );
65 ATH_CHECK( m_SCellEtMeVdecorKey.initialize() );
66 ATH_CHECK( m_TileEtMeVdecorKey.initialize() );
68
77
78
79
80 //Reading from CVMFS Trigger Tower and their corresponding SCell ID
83
84 return StatusCode::SUCCESS;
85}
86
87StatusCode jFexTower2SCellDecorator::execute(const EventContext& ctx) const {
88
89 //Reading the Scell container
91 if(!ScellContainer.isValid()) {
92 ATH_MSG_ERROR("Could not retrieve collection " << ScellContainer.key() );
93 return StatusCode::FAILURE;
94 }
95
96 //Reading the TriggerTower container
98 if(!triggerTowerContainer.isValid()) {
99 ATH_MSG_ERROR("Could not retrieve collection " << triggerTowerContainer.key() );
100 return StatusCode::FAILURE;
101 }
102
103 //Reading the jTower container
105 if(!jTowerContainer.isValid()) {
106 ATH_MSG_ERROR("Could not retrieve collection " << jTowerContainer.key() );
107 return StatusCode::FAILURE;
108 }
109
110 if(ScellContainer->empty() || triggerTowerContainer->empty() || jTowerContainer->empty() ){
111 ATH_MSG_DEBUG("Nothing to decorate here, at least one container is empty. ScellContainer.size="<<ScellContainer->size() << " or jTowerContainer.size=" << jTowerContainer->size() << " or triggerTowerContainer.size=" << triggerTowerContainer->size() );
112 return StatusCode::SUCCESS;
113 }
114
115 // building Scell ID pointers
116 std::unordered_map< uint64_t, const CaloCell*> map_ScellID2ptr;
117
118 for(const CaloCell* scell : *ScellContainer){
119 const uint64_t ID = scell->ID().get_compact();
120 map_ScellID2ptr[ID] = scell;
121 }
122
123 // building Tile ID pointers
124 std::unordered_map< uint32_t, const xAOD::TriggerTower*> map_TileID2ptr;
125
126 for(const xAOD::TriggerTower* tower : *triggerTowerContainer){
127
128 // keeping just
129 if(std::abs(tower->eta())>1.5 || tower->sampling()!=1) continue;
130 map_TileID2ptr[tower->coolId()]=tower;
131 }
132
133 // FIXME: In C++20, we could do this more nicely with a templated lambda.
134 auto jTowerSCellEt = makeOptionalKey<std::vector<float> > (m_SCellEtdecorKey, ctx, m_save_extras);
135 auto jTowerSCellEta = makeOptionalKey<std::vector<float> > (m_SCellEtadecorKey, ctx, m_save_extras);
136 auto jTowerSCellPhi = makeOptionalKey<std::vector<float> > (m_SCellPhidecorKey, ctx, m_save_extras);
137 auto jTowerSCellID = makeOptionalKey<std::vector<int> > (m_SCellIDdecorKey, ctx, m_save_extras);
138 auto jTowerSCellMask = makeOptionalKey<std::vector<bool> > (m_SCellMaskdecorKey, ctx, m_save_extras);
139 auto jTowerTileEt = makeOptionalKey<int> (m_TileEtdecorKey, ctx, m_save_extras);
140 auto jTowerTileEta = makeOptionalKey<float> (m_TileEtadecorKey, ctx, m_save_extras);
141 auto jTowerTilePhi = makeOptionalKey<float> (m_TilePhidecorKey, ctx, m_save_extras);
142 auto jTowerEtencoded = makeOptionalKey<int> (m_jTowerEtdecorKey, ctx, m_save_emulated_var);
143
147
148 //looping over the jTowers to decorate them!
150
151 uint32_t jFexID = jTower->jFEXtowerID();
152 uint8_t source = jTower->Calosource();
153 int jFexEt = 0;
154 uint16_t jFexEtencoded = 0;
155
156 if(source >=7){
157 ATH_MSG_WARNING("Undefined source element: "<<source);
158 }
159
160 std::vector<float> scEt;
161 std::vector<float> scEta;
162 std::vector<float> scPhi;
163 std::vector<int> scID;
164 std::vector<bool> scMask;
165 float SCellEt = 0.0;
166 int TileEt = 0;
167 float TileEta = -99.0;
168 float TilePhi = -99.0;
169
170 if(source != 1){ // Source == 1 is belong to Tile Calorimeter, and of course the is not SCell information!
171
172 const std::unordered_map< uint32_t, std::vector<uint64_t> > * ptr_TTower2Cells;
173
174 //HAD layer for HEC, FCAL2 and FCAL3
175 if(source == 3 or source > 4){
176 ptr_TTower2Cells = &m_map_TTower2SCellsHAD;
177 }
178 else{
179 ptr_TTower2Cells = &m_map_TTower2SCellsEM;
180 }
181
182 //check that the jFEX Tower ID exists in the map
183 auto it_TTower2SCells = (*ptr_TTower2Cells).find(jFexID);
184 if(it_TTower2SCells == (*ptr_TTower2Cells).end()) {
185 ATH_MSG_ERROR("ID: "<<jFexID<< " not found on map m_map_TTower2SCellsEM/HAD");
186 return StatusCode::FAILURE;
187 }
188
189 bool invalid=true;
190 for (auto const& SCellID : it_TTower2SCells->second ) {
191
192 //check that the SCell Identifier exists in the map
193 auto it_ScellID2ptr = map_ScellID2ptr.find(SCellID);
194 if(it_ScellID2ptr == map_ScellID2ptr.end()) {
195 ATH_MSG_DEBUG("Scell ID: 0x"<<std::hex<<(SCellID >> 32)<<std::dec<< " not found on map map_ScellID2ptr");
196
197 scEt.push_back(0);
198 scEta.push_back(-99);
199 scPhi.push_back(-99);
200 // bit shifting to get only a 32 bit number
201 scID.push_back( SCellID >> 32 );
202 scMask.push_back(1); // treat missing cells as masked, so that if all missing will get a 0 not an invalid code
203
204 }
205 else{
206 const CaloCell* myCell = it_ScellID2ptr->second;
207
208 int val = std::round(myCell->energy()/(12.5*std::cosh(myCell->eta()))); // 12.5 is b.c. energy is in units of 12.5MeV per count
209 bool isMasked = m_apply_masking ? ((myCell)->provenance()&0x80) : false;
210 bool isInvalid = m_apply_masking ? ((myCell)->provenance()&0x40) : false;
211
212 invalid &= isInvalid;
213 //masked &= isMasked;
214
215 if( isMasked || isInvalid ) {
216 val = 0;
217 }
218
219 scEt.push_back(val);
220 scEta.push_back(myCell->eta());
221 scPhi.push_back(myCell->phi());
222 // bit shifting to get only a 32 bit number
223 scID.push_back( SCellID >> 32 );
224 scMask.push_back( isMasked );
225 }
226 }
227
228 //emulated encoded Et
229 float tmpSCellEt = 0;
230 for(const auto& tmpet : scEt){
231 tmpSCellEt += tmpet;
232 }
233
234 //How many SCell are masked? if all then send invalid code
235 unsigned int count_scMask =0;
236 for(const bool masked : scMask){
237 if(masked) count_scMask++;
238 }
239
240 SCellEt = tmpSCellEt*12.5;
241 // now must convert Total_Et int value into fex value: multi-level encoding
242 if(count_scMask==scMask.size()) {
243 jFexEtencoded = 0; // no data
244 } else if(invalid) {
245 jFexEtencoded = 4095; // invalid
246 } else {
247 jFexEtencoded = jFEXCompression::Compress( tmpSCellEt*12.5, false );
248 }
249
250 jFexEt = jFEXCompression::Expand( jTower->jTowerEt() );
251 }
252 else if(source == 1){
253
254 //check that the jFEX Tower ID exists in the map
255 auto it_TTower2Tile = m_map_TTower2Tile.find(jFexID);
256 if(it_TTower2Tile == m_map_TTower2Tile.end()) {
257 ATH_MSG_ERROR("ID: "<<jFexID<< " not found on map m_map_TTower2Tile");
258 return StatusCode::FAILURE;
259 }
260
261 uint32_t TileID = std::get<0>( it_TTower2Tile->second );
262
263 //check that the Tile Identifier exists in the map
264 auto it_TileID2ptr = map_TileID2ptr.find(TileID);
265 if(it_TileID2ptr == map_TileID2ptr.end()) {
266 ATH_MSG_WARNING("Scell ID: 0x"<<std::hex<<TileID<<std::dec<< " not found on map map_TileID2ptr");
267
268 jFexEtencoded = 0;
269 TileEt = 0;
270 TileEta = -99;
271 TilePhi = -99;
272 }
273 else{
274 jFexEtencoded = (it_TileID2ptr->second)->cpET();
275 TileEt = jFexEtencoded*500; // cf 500 since it is cpET
276 TileEta = (it_TileID2ptr->second)->eta();
277 float phi = (it_TileID2ptr->second)->phi() < M_PI ? (it_TileID2ptr->second)->phi() : (it_TileID2ptr->second)->phi()-2*M_PI;
278 TilePhi = phi;
279
280 }
281
282 jFexEt = jTower->jTowerEt()*500; // cf 500 since it is cpET
283
284 }
285
286 // Decorating the tower with the corresponding information
287 //Setup Decorator Handlers
288 if(m_save_extras) {
289 (*jTowerSCellEt) (*jTower) = std::move(scEt);
290 (*jTowerSCellEta) (*jTower) = std::move(scEta);
291 (*jTowerSCellPhi) (*jTower) = std::move(scPhi);
292 (*jTowerSCellID) (*jTower) = std::move(scID);
293 (*jTowerSCellMask) (*jTower) = std::move(scMask);
294 (*jTowerTileEt) (*jTower) = static_cast<int>( TileEt );
295 (*jTowerTileEta) (*jTower) = TileEta;
296 (*jTowerTilePhi) (*jTower) = TilePhi;
297 }
298
299 jTowerEtMeV (*jTower) = jFexEt;
300 SCellEtMeV (*jTower) = SCellEt;
301 TileEtMeV (*jTower) = TileEt;
302
304 (*jTowerEtencoded) (*jTower) = jFexEtencoded;
305 }
306
307
308 }
309
310 // Return gracefully
311 return StatusCode::SUCCESS;
312}
313
314
315StatusCode jFexTower2SCellDecorator::ReadSCfromFile(const std::string& fileName){
316
317 std::string myline;
318
319 //openning file with ifstream
320 std::ifstream myfile(fileName);
321
322 if ( !myfile.is_open() ){
323 ATH_MSG_ERROR("Could not open file:" << fileName);
324 return StatusCode::FAILURE;
325 }
326
327 //loading the mapping information into an unordered_map <Fex Tower ID, vector of SCell IDs>
328 while ( std::getline (myfile, myline) ) {
329 std::vector<uint64_t> SCellvectorEM;
330 SCellvectorEM.clear();
331 std::vector<uint64_t> SCellvectorHAD;
332 SCellvectorHAD.clear();
333
334 //removing the header of the file (it is just information!)
335 if(myline[0] == '#') continue;
336
337 //Splitting myline in different substrings
338 std::stringstream oneSCellID(myline);
339
340 //reading elements
341 std::string substr = "";
342 int TTID = 0;
343 int elem = 0;
344
345 while(std::getline(oneSCellID, substr, ' '))
346 {
347 ++elem;
348 if(elem == 1){
349 TTID = std::stoi(substr);
350 }
351 else{
352 //Check if it looks like a SCell Identifier
353 if(isBadSCellID(substr)){
354 return StatusCode::FAILURE;
355 }
356
357 // converts hex number to unsigned long long int
358 uint64_t scid_uint64 = std::strtoull(substr.c_str(), nullptr, 0);
359
360 //empty slots are filled with 0xffffffffffffffff
361 if(scid_uint64 == 0xffffffffffffffff) continue;
362
363 //from element from 2 to 13 are EM SCells, element 14 is a HAD SCell
364 if(elem<14) SCellvectorEM.push_back(scid_uint64);
365 else SCellvectorHAD.push_back(scid_uint64);
366 }
367 }
368
369 m_map_TTower2SCellsEM[TTID] = std::move(SCellvectorEM);
370 m_map_TTower2SCellsHAD[TTID] = std::move(SCellvectorHAD);
371
372 }
373 myfile.close();
374
375 return StatusCode::SUCCESS;
376}
377
378bool jFexTower2SCellDecorator::isBadSCellID(const std::string& ID) const{
379
380 // does it start with "0x"?, if so then is a GOOD SCell ID!
381 if (ID.find("0x") == std::string::npos) {
382 ATH_MSG_ERROR("Invalid SuperCell ID " << ID << ". Expecting hexadecimal number on the mapping file");
383 return true;
384 }
385 return false;
386}
387
388
389
390
391StatusCode jFexTower2SCellDecorator::ReadTilefromFile(const std::string& fileName){
392
393 std::string myline;
394
395 //openning file with ifstream
396 std::ifstream myfile(fileName);
397
398 if ( !myfile.is_open() ){
399 ATH_MSG_ERROR("Could not open file:" << fileName);
400 return StatusCode::FAILURE;
401 }
402
403 //loading the mapping information into an unordered_map <Fex Tower ID, vector of SCell IDs>
404 while ( std::getline (myfile, myline) ) {
405
406 //removing the header of the file (it is just information!)
407 if(myline[0] == '#') continue;
408
409 //Splitting myline in different substrings
410 std::stringstream oneLine(myline);
411
412 std::vector<std::string> elements;
413 std::string element = "";
414
415 while(std::getline(oneLine, element, ' ')){
416 elements.push_back(element);
417 }
418
419 if(elements.size() != 4){
420 ATH_MSG_ERROR("Invalid number of element in " << myline << ". Expecting 4 elements {jFexID, TileID, eta, phi}");
421 return StatusCode::FAILURE;
422 }
423
424 uint32_t jFexID = std::stoi( elements.at(0) );
425 uint32_t TileID = std::stoi( elements.at(1) );
426 float eta = std::stof( elements.at(2) );
427 float phi = std::stof( elements.at(3) );
428
429 m_map_TTower2Tile[jFexID] = {TileID,eta,phi};
430
431 }
432 myfile.close();
433
434 return StatusCode::SUCCESS;
435}
436
437
438
439
440
441}
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#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)
std::vector< Identifier > ID
Header file for AthHistogramAlgorithm.
An algorithm that can be simultaneously executed in multiple threads.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
double energy() const
get energy (data member)
Definition CaloCell.h:327
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
static int Expand(unsigned int code)
Uncompress data.
static unsigned int Compress(float floatEt, bool empty=false)
Compress data.
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_TileEtadecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellEtdecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellEtadecorKey
std::unordered_map< uint32_t, std::tuple< uint32_t, float, float > > m_map_TTower2Tile
StatusCode ReadTilefromFile(const std::string &)
StatusCode ReadSCfromFile(const std::string &)
jFexTower2SCellDecorator(const std::string &name, ISvcLocator *svc)
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellEtMeVdecorKey
SG::ReadHandleKey< CaloCellContainer > m_SCellKey
std::unordered_map< uint32_t, std::vector< uint64_t > > m_map_TTower2SCellsHAD
Gaudi::Property< std::string > m_jFEX2Scellmapping
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_jtowerEtMeVdecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellPhidecorKey
Gaudi::Property< std::string > m_jFEX2Tilemapping
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_TileEtMeVdecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_TilePhidecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_jTowerEtdecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellMaskdecorKey
SG::ReadHandleKey< xAOD::TriggerTowerContainer > m_triggerTowerKey
virtual StatusCode execute(const EventContext &) const override
Function executing the algorithm.
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_SCellIDdecorKey
SG::WriteDecorHandleKey< xAOD::jFexTowerContainer > m_TileEtdecorKey
std::unordered_map< uint32_t, std::vector< uint64_t > > m_map_TTower2SCellsEM
bool isBadSCellID(const std::string &) const
virtual StatusCode initialize() override
Function initialising the algorithm.
SG::ReadHandleKey< xAOD::jFexTowerContainer > m_jTowersReadKey
The jTower class is an interface object for jFEX trigger algorithms The purposes are twofold:
Definition jTower.h:36
virtual bool isValid() override final
Can the handle be successfully dereferenced?
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
Handle class for adding a decoration to an object.
Helper class for TileCal offline identifiers.
Definition TileID.h:67
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
TriggerTower_v2 TriggerTower
Define the latest version of the TriggerTower class.
jFexTower_v1 jFexTower
Define the latest version of the TriggerTower class.
Definition jFexTower.h:15