ATLAS Offline Software
Loading...
Searching...
No Matches
jFEXForwardElecAlgo.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// jFEXForwardElecAlgo - Algorithm for Forward Electron Algorithm in jFEX
6// -------------------
7// begin : 16 11 2021
8// email : Sergi.Rodriguez@cern.ch
9// email : ulla.blumenschein@cern.ch
10// email : sjolin@cern.ch
11//***************************************************************************
12
13#include <iostream>
14#include <vector>
15#include <stdio.h>
16#include <math.h>
17#include <fstream>
18#include "jFEXForwardElecAlgo.h"
21#include "L1CaloFEXSim/jTower.h"
24
25namespace LVL1 {
26
27 //Default Constructor
28 LVL1::jFEXForwardElecAlgo::jFEXForwardElecAlgo(const std::string& type, const std::string& name, const IInterface* parent): AthAlgTool(type, name, parent) {
29 declareInterface<IjFEXForwardElecAlgo>(this);
30 }
31
35
47
48 //calls container for TT
51 if(! m_jTowerContainer.isValid()) {
52 ATH_MSG_ERROR("Could not retrieve jTowerContainer " << m_jTowerContainerKey.key());
53 return StatusCode::FAILURE;
54 }
55 return StatusCode::SUCCESS;
56 }
57
59 return StatusCode::SUCCESS;
60 }
61
67
68 //global centre Eta and Phi coord of the TT
69 std::array<float,2> LVL1::jFEXForwardElecAlgo::getEtaPhi(uint ttID) {
70 if(ttID == 0) {
71 return {999,999};
72 }
73 const LVL1::jTower *tmpTower = m_jTowerContainer->findTower(ttID);
74 return {tmpTower->centreEta(),tmpTower->centrePhi()};
75 }
76
77 std::array<int,2> LVL1::jFEXForwardElecAlgo::getEtEmHad(uint ttID) const {
78 if(ttID == 0) {
79 return {0,0};
80 }
81 int TT_EtEM = 0;
82 if(m_map_Etvalues_EM.find(ttID) != m_map_Etvalues_EM.end()) {
83 TT_EtEM = m_map_Etvalues_EM.at(ttID)[0];
84 }
85 int TT_EtHad = 0;
86 if(m_map_Etvalues_HAD.find(ttID) != m_map_Etvalues_HAD.end()) {
87 TT_EtHad = m_map_Etvalues_HAD.at(ttID)[0];
88 }
89
90 return {TT_EtEM, TT_EtHad};
91 }
92
93 bool LVL1::jFEXForwardElecAlgo::getEMSat(unsigned int ttID ) {
94 if(ttID == 0) {
95 return false;
96 }
97
98 const LVL1::jTower * tmpTower = m_jTowerContainer->findTower(ttID);
99 return tmpTower->getEMSat();
100 }
101
103 std::unordered_map<int,std::vector<int> > etmapEM,
104 std::unordered_map<int,std::vector<int> > etmapHAD) {
105 m_map_Etvalues_EM=std::move(etmapEM);
106 m_map_Etvalues_HAD=std::move(etmapHAD);
107 }
108
109
111 auto [centreTT_EtEM,centreTT_EtHad] = getEtEmHad(seedTTID);
112 // check if seed has strictly more energy than its neighbours
113 {
114 auto it_seed_map = m_SearchGTauMap.find(seedTTID);
115 if(it_seed_map == m_SearchGTauMap.end()) {
116 ATH_MSG_ERROR("Could not find TT" << seedTTID << " in the seach (>) local maxima for tau/em file.");
117 return false;
118 }
119 for (const auto& gtt : it_seed_map->second ){
120 auto [tmp_EtEM,tmp_EtHad] = getEtEmHad(gtt);
121 if(tmp_EtEM>=centreTT_EtEM) {
122 return false;
123 }
124 }
125 }
126
127 // check if seed has equal or more energy than its neighbours
128 {
129 auto it_seed_map = m_SearchGeTauMap.find(seedTTID);
130 if(it_seed_map == m_SearchGeTauMap.end()) {
131 ATH_MSG_ERROR("Could not find TT" << seedTTID << " in the seach (>=) local maxima for tau/em file.");
132 return false;
133 }
134 for (const auto& gtt : it_seed_map->second ){
135 auto [tmp_EtEM,tmp_EtHad] = getEtEmHad(gtt);
136 if( tmp_EtEM>centreTT_EtEM) {
137 return false;
138 }
139 }
140 }
141
142 return true;
143 }
144
145
147 //determine direction for offsets (-1 : C-side, +1: A-side)
148 int direction = m_jfex < 3 ? -1 : +1;
149
150 std::vector<std::pair<int,int>> neighbours;
151 //eta/phi index offsets depend on the position of the seed the cluster is created from
152 //differentiate the (many) different cases:
153 if ( direction>0 ? neta < FEXAlgoSpaceDefs::jFEX_algoSpace_A_EMIE_eta - 1 // A-side condition
154 : neta > FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMB_start_eta) // C-side condition
155 { //Barrel
156 neighbours = { {neta , nphi+1},
157 {neta , nphi-1},
158 {neta+1, nphi },
159 {neta-1, nphi }
160 };
161 } else if ( direction>0 ? neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_EMIE_eta - 1
163 { //Barrel next to Endcap
164 neighbours = { {neta, nphi+1},
165 {neta, nphi-1},
166 {neta-direction, nphi},
167 {neta+direction, nphi/2} //boundary crossing into endcap -> reduced phi granularity
168 };
169 } else if ( direction>0 ? neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_EMIE_eta
171 { //Endcap next to Barrel
172 neighbours = { {neta, nphi+1},
173 {neta, nphi-1},
174 {neta+direction, nphi},
175 {neta-direction, 2*nphi+0}, //crossing into barrel region, higher phi granularity
176 {neta-direction, 2*nphi+1}, // -> consider both "touching" towers
177 };
179 : neta < FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMIE_end_eta - 1 && neta > FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMIE_start_eta )
180 { //Endcap
181 neighbours = { {neta , nphi+1},
182 {neta , nphi-1},
183 {neta+1, nphi },
184 {neta-1, nphi }
185 };
186 } else if ( direction>0 ? neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_FCAL_start_eta - 1
188 { //Endcap next to FCal
189 neighbours = { {neta, nphi+1},
190 {neta, nphi-1},
191 {neta-direction, nphi},
192 {neta+2*direction, nphi/2} //boundary crossing into FCal -> reduced phi granularity and skip first FCal bin
193 };
194 } else if ( direction>0 ? neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_FCAL_start_eta + 1 //first FCal bin must be skipped!
195 : neta == FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMIE_start_eta - 2 ) //first FCal bin must be skipped!
196 { //FCal next to Endcap
197 //phi spacing in FCal is very wide, no longer consider adding towers in phi direction
198 neighbours = { {neta-2*direction, 2*nphi+0}, //boundary crossing into endcap, higher phi granularity
199 {neta-2*direction, 2*nphi+1}, // -> consider both "touching" towers
200 {neta+direction, nphi}
201 };
203 : neta < FEXAlgoSpaceDefs::jFEX_algoSpace_C_FCAL_end_eta - 2 && neta > FEXAlgoSpaceDefs::jFEX_algoSpace_C_FCAL_start_eta )
204 { //FCal
205 neighbours = { {neta+1, nphi},
206 {neta-1, nphi}
207 };
208 } else if ( direction>0 ? neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_FCAL_end_eta - 1
210 { //FCal, last eta bin
211 neighbours = { {neta-direction, nphi}
212 };
213 } else {
214 ATH_MSG_ERROR("Eta index " << neta << " (side: "<< (direction>0?"A":"C") << ") does not seem to belong to any valid seed region");
215 }
216
217 //iterate over neighbours, find most energetic one
218 for (const auto& candEtaPhi: neighbours) {
219 uint candID = m_jFEXalgoTowerID[candEtaPhi.second][candEtaPhi.first];
220 const auto [candTT_EtEM, candTT_EtHad] = getEtEmHad(candID);
221 if (candTT_EtEM > elCluster.getNextTTEtEM()) {
222 elCluster.setNextTTEtEM(candTT_EtEM);
223 elCluster.setNextTTID(candID);
224 elCluster.setNextTTSatEM(getEMSat(candID));
225 }
226 }
227
228 }
229
230
231 std::unordered_map<uint, LVL1::jFEXForwardElecInfo> LVL1::jFEXForwardElecAlgo::calculateEDM(void) {
232 std::unordered_map<uint, LVL1::jFEXForwardElecInfo> clusterList;
233 std::vector<int> lower_centre_neta;
234 std::vector<int> upper_centre_neta;
235
236 //check if we are in module 0 or 5 and assign corrrect eta FEXAlgoSpace parameters
237 if(m_jfex == 0) {
238 //Module 0
239 lower_centre_neta.assign({FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMB_start_eta, // 28
242
243 upper_centre_neta.assign({FEXAlgoSpaceDefs::jFEX_algoSpace_C_EMB_end_eta, // 37
246 }
247 else {
248 //Module 5
249 lower_centre_neta.assign({FEXAlgoSpaceDefs::jFEX_algoSpace_A_EMB_eta, // 8
252
253 upper_centre_neta.assign({FEXAlgoSpaceDefs::jFEX_algoSpace_A_EMIE_eta, // 17
256 }
257
258 //define phi FEXAlgoSpace parameters
261
262 //loop over different EM/FCAL1 eta phi core fpga regions with different granularities. These are potential seed towers for electron clusters
263 for(uint region = 0; region<3; region++) {
264 for(int nphi = lower_centre_nphi[region]; nphi < upper_centre_nphi[region]; nphi++) {
265 for(int neta = lower_centre_neta[region]; neta < upper_centre_neta[region]; neta++) {
266
267 // ignore seeds for |eta| < 2.3 or from the first FCAL eta bin
268 if (m_jfex == 0 && neta >= FEXAlgoSpaceDefs::jFEX_algoSpace_C_FwdEl_start) continue;
269 if (m_jfex == 5 && neta <= FEXAlgoSpaceDefs::jFEX_algoSpace_A_FwdEl_start) continue;
270 if (m_jfex == 0 && neta == FEXAlgoSpaceDefs::jFEX_algoSpace_C_FCAL1_1st) continue;
271 if (m_jfex == 5 && neta == FEXAlgoSpaceDefs::jFEX_algoSpace_A_FCAL1_1st) continue;
272
273 // define ttID (only FCAL1 in the third region) which will be the key for class in map, ignore tower ID = 0
274 uint ttID = m_jFEXalgoTowerID[nphi][neta];
275 if(ttID == 0) continue;
276 //check if seed candidate is actual seed (passes local maximum criteria)
277 if(!isValidSeed(ttID)) continue;
278
279 //gather some first, basic information for resulting cluster/TOB
280 jFEXForwardElecInfo elCluster;
281 elCluster.setup(m_jfex, ttID, neta, nphi);
282 const auto [centreTT_eta, centreTT_phi] = getEtaPhi(ttID);
283 const auto [centreTT_EtEM, centreTT_EtHad] = getEtEmHad(ttID);
284 elCluster.setCoreTTfPhi(centreTT_phi);
285 elCluster.setCoreTTfEta(centreTT_eta);
286 elCluster.setCoreTTEtEM(centreTT_EtEM);
287 elCluster.setCoreTTSatEM(getEMSat(ttID));
288 elCluster.setNextTTEtEM(0);
289 elCluster.setNextTTID(0);
290 elCluster.setTTEtEMiso(0);
291
292 //find "NextTT", i.e., highest ET neighbour
293 findAndFillNextTT(elCluster, neta, nphi);
294
295 // sum up EM isolation using the isolation map and remove cluster ET
296 {
297 int sumEtEM = 0;
298 auto it_iso_map = m_IsoMap.find(ttID);
299 if(it_iso_map != m_IsoMap.end()) {
300 for(const auto& gtt : it_iso_map->second){
301 auto [tmp_EtEM,tmp_EtHad] = getEtEmHad(gtt);
302 sumEtEM += tmp_EtEM;
303 }
304 elCluster.setTTEtEMiso(sumEtEM-elCluster.getNextTTEtEM());
305 } else {
306 ATH_MSG_ERROR("Could not find TT" << ttID << " in jEM isolation map file.");
307 }
308 }
309
310 if(fabs(centreTT_eta) < 3.2) {
311 // for non-FCal positions only Frac1 is meaningful and has a "trivial" mapping
312 elCluster.setTTEtHad1(centreTT_EtHad);
313 elCluster.setTTEtHad2(0);
314 } else {
315 // sum up Et for hadronic fraction 1
316 {
317 int sumEtHad1 = 0;
318 auto it_frac1_map = m_Frac1Map.find(ttID);
319 if(it_frac1_map != m_Frac1Map.end()) {
320 for(const auto& gtt : it_frac1_map->second){
321 auto [tmp_EtEM,tmp_EtHad] = getEtEmHad(gtt);
322 sumEtHad1 += tmp_EtHad;
323 }
324 elCluster.setTTEtHad1(sumEtHad1);
325 } else {
326 ATH_MSG_ERROR("Could not find TT" << ttID << " in jEM frac1 map file.");
327 }
328 }
329
330 // sum up Et for hadronic fraction 2 (only FCal!)
331 {
332 int sumEtHad2 = 0;
333 auto it_frac2_map = m_Frac2Map.find(ttID);
334 if(it_frac2_map != m_Frac2Map.end()) {
335 for(const auto& gtt : it_frac2_map->second) {
336 auto [tmp_EtEM,tmp_EtHad] = getEtEmHad(gtt);
337 sumEtHad2 += tmp_EtHad;
338 }
339 elCluster.setTTEtHad2(sumEtHad2);
340 } else {
341 ATH_MSG_ERROR("Could not find TT" << ttID << " in jEM frac2 map file.");
342 }
343 }
344 }
345
346 // save this cluster in the list
347 clusterList[ttID] = std::move(elCluster);
348 }//eta
349 }//phi
350 }// 3 regions
351 return clusterList;
352 }
353
354 StatusCode LVL1::jFEXForwardElecAlgo::ReadfromFile(const std::string & fileName, std::unordered_map<unsigned int, std::vector<unsigned int> >& fillingMap) const {
355 std::string myline;
356 //opening file with ifstream
357 std::ifstream myfile(fileName);
358 if ( !myfile.is_open() ){
359 ATH_MSG_ERROR("Could not open file:" << fileName);
360 return StatusCode::FAILURE;
361 }
362
363 //loading the mapping information
364 while ( std::getline (myfile, myline) ) {
365 //removing the header of the file (it is just information!)
366 if(myline[0] == '#') continue;
367
368 //Splitting myline in different substrings
369 std::stringstream oneLine(myline);
370
371 //reading elements
372 std::vector<unsigned int> elements;
373 std::string element;
374 while(std::getline(oneLine, element, ' '))
375 {
376 elements.push_back(std::stoi(element));
377 }
378
379 // We should have at least two elements! Central TT and (at least) itself
380 if(elements.size() < 1){
381 ATH_MSG_ERROR("Unexpected number of elemennts (<1 expected) in file: "<< fileName);
382 return StatusCode::FAILURE;
383 }
384
385 //Central TiggerTower
386 unsigned int TTID = elements.at(0);
387
388 // rest of TTs that need to be checked
389 elements.erase(elements.begin());
390 fillingMap[TTID] = std::move(elements);
391 }
392 myfile.close();
393
394 return StatusCode::SUCCESS;
395 }
396}// end of namespace LVL1
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
unsigned int uint
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
static constexpr int jFEX_algoSpace_A_FCAL1_1st
static constexpr int jFEX_algoSpace_C_EMB_start_eta
static constexpr int jFEX_wide_algoSpace_width
static constexpr int jFEX_algoSpace_A_FCAL_end_eta
static constexpr int jFEX_algoSpace_C_EMB_end_eta
static constexpr int jFEX_algoSpace_EMIE_end_phi
static constexpr int jFEX_algoSpace_C_FCAL_end_eta
static constexpr int jFEX_algoSpace_A_EMB_eta
static constexpr int jFEX_algoSpace_A_FCAL_start_eta
static constexpr int jFEX_algoSpace_C_FCAL_start_eta
static constexpr int jFEX_algoSpace_A_EMIE_eta
static constexpr int jFEX_algoSpace_FCAL_end_phi
static constexpr int jFEX_algoSpace_C_FCAL1_1st
static constexpr int jFEX_algoSpace_EMB_end_phi
static constexpr int jFEX_algoSpace_A_FwdEl_start
static constexpr int jFEX_algoSpace_FCAL_start_phi
static constexpr int jFEX_algoSpace_EMIE_start_phi
static constexpr int jFEX_algoSpace_C_FwdEl_start
static constexpr int jFEX_algoSpace_EMB_start_phi
static constexpr int jFEX_algoSpace_height
static constexpr int jFEX_algoSpace_C_EMIE_start_eta
static constexpr int jFEX_algoSpace_C_EMIE_end_eta
Gaudi::Property< std::string > m_Frac2MapStr
std::unordered_map< int, std::vector< int > > m_map_Etvalues_EM
std::unordered_map< int, std::vector< int > > m_map_Etvalues_HAD
std::unordered_map< unsigned int, std::vector< unsigned int > > m_Frac1Map
std::unordered_map< unsigned int, std::vector< unsigned int > > m_Frac2Map
virtual std::array< int, 2 > getEtEmHad(uint) const override
jFEXForwardElecAlgo(const std::string &type, const std::string &name, const IInterface *parent)
Constructors.
int m_jFEXalgoTowerID[FEXAlgoSpaceDefs::jFEX_algoSpace_height][FEXAlgoSpaceDefs::jFEX_wide_algoSpace_width]
SG::ReadHandleKey< LVL1::jTowerContainer > m_jTowerContainerKey
virtual void setup(int inputTable[FEXAlgoSpaceDefs::jFEX_algoSpace_height][FEXAlgoSpaceDefs::jFEX_wide_algoSpace_width], int jfex, int fpga) override
virtual StatusCode safetyTest() override
Standard methods.
virtual std::array< float, 2 > getEtaPhi(uint) override
void findAndFillNextTT(jFEXForwardElecInfo &elCluster, int neta, int nphi)
Gaudi::Property< std::string > m_SearchGeTauStr
virtual StatusCode reset() override
bool isValidSeed(uint seedTTID) const
SG::ReadHandle< jTowerContainer > m_jTowerContainer
Gaudi::Property< std::string > m_SearchGTauStr
bool getEMSat(unsigned int ttID)
StatusCode ReadfromFile(const std::string &, std::unordered_map< unsigned int, std::vector< unsigned int > > &) const
virtual void setFPGAEnergy(std::unordered_map< int, std::vector< int > > etmapEM, std::unordered_map< int, std::vector< int > > etmapHAD) override
virtual StatusCode initialize() override
standard Athena-Algorithm method
virtual ~jFEXForwardElecAlgo()
Destructor.
Gaudi::Property< std::string > m_IsoMapStr
Gaudi::Property< std::string > m_Frac1MapStr
std::unordered_map< unsigned int, std::vector< unsigned int > > m_IsoMap
std::unordered_map< unsigned int, std::vector< unsigned int > > m_SearchGTauMap
std::unordered_map< unsigned int, std::vector< unsigned int > > m_SearchGeTauMap
virtual std::unordered_map< uint, jFEXForwardElecInfo > calculateEDM() override
void setup(int jfex, uint ttid, int neta, int nphi)
The jTower class is an interface object for jFEX trigger algorithms The purposes are twofold:
Definition jTower.h:36
float centrePhi() const
Definition jTower.h:80
bool getEMSat() const
Definition jTower.h:56
float centreEta() const
Definition jTower.h:79
static std::string find_calib_file(const std::string &logical_file_name)
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...