ATLAS Offline Software
Loading...
Searching...
No Matches
gFEXaltMetAlgo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4//***************************************************************************
5// gFEXaltMetAlgo - Noise cut and Rho+RMS algorithm for gFEX MET
6// -------------------
7// begin : 31 03 2022
8// email : cecilia.tosciri@cern.ch
9//***************************************************************************
10
11#include "gFEXaltMetAlgo.h"
13#include "L1CaloFEXSim/gTower.h"
14
15#include <cmath>
16#include <vector>
17
18namespace LVL1 {
19
20gFEXaltMetAlgo::gFEXaltMetAlgo(const std::string& type, const std::string& name, const IInterface* parent):
21base_class(type, name, parent)
22{}
23
25
26 ATH_CHECK(m_l1MenuKey.initialize());
27
28 return StatusCode::SUCCESS;
29
30}
31
32void gFEXaltMetAlgo::altMetAlgo(const EventContext& ctx, const gTowersCentral &Atwr, const gTowersCentral &Btwr, const gTowersCentral &Ctwr,
33 std::array<uint32_t, 4> & outTOB) const {
34
35 // Retrieve the L1 menu configuration
37
38 //Parameters related to altMet (noise cut and rho+RMS algorithms)
39 const auto & thr_gXE_altMet = l1Menu->thrExtraInfo().gXE();
40 int noiseCutThrA = thr_gXE_altMet.noiseCutThr('A');
41 int noiseCutThrB = thr_gXE_altMet.noiseCutThr('B');
42 int noiseCutThrC = thr_gXE_altMet.noiseCutThr('C');
43
44 std::vector<int> thr_A(12, noiseCutThrA);
45 std::vector<int> thr_B(12, noiseCutThrB);
46 std::vector<int> thr_C(16, noiseCutThrC);
47
48 std::array<std::vector<int>, 3> etaThr; // A, B, C
49 etaThr[0] = std::move(thr_A);
50 etaThr[1] = std::move(thr_B);
51 etaThr[2] = std::move(thr_C);
52
53 //FPGA A observables
54 int A_MET_x_nc = 0x0;
55 int A_MET_y_nc = 0x0;
56 int A_MET_x_rms = 0x0;
57 int A_MET_y_rms = 0x0;
58
59 int A_sumEt_nc = 0x0;
60 int A_sumEt_rms = 0x0;
61
62 //FPGA B observables
63 int B_MET_x_nc = 0x0;
64 int B_MET_y_nc = 0x0;
65 int B_MET_x_rms = 0x0;
66 int B_MET_y_rms = 0x0;
67
68 int B_sumEt_nc = 0x0;
69 int B_sumEt_rms = 0x0;
70
71 // FPGA C observables
72 int C_MET_x_nc = 0x0;
73 int C_MET_y_nc = 0x0;
74 int C_MET_x_rms = 0x0;
75 int C_MET_y_rms = 0x0;
76
77 int C_sumEt_nc = 0x0;
78 int C_sumEt_rms = 0x0;
79
80 //Global observables
81 int MET_x_nc = 0x0;
82 int MET_y_nc = 0x0;
83 int MET_nc = 0x0;
84 int MET_x_rms = 0x0;
85 int MET_y_rms = 0x0;
86 int MET_rms = 0x0;
87
88
89 int total_sumEt_nc = 0x0;
90 int total_sumEt_rms = 0x0;
91
92 metFPGA(Atwr, A_MET_x_nc, A_MET_y_nc, 0, etaThr);
93 metFPGA(Btwr, B_MET_x_nc, B_MET_y_nc, 1, etaThr);
94 metFPGA(Ctwr, C_MET_x_nc, C_MET_y_nc, 2, etaThr);
95
96 metTotal(A_MET_x_nc, A_MET_y_nc, B_MET_x_nc, B_MET_y_nc, C_MET_x_nc, C_MET_y_nc, MET_x_nc, MET_y_nc, MET_nc);
97
98 int A_rho{get_rho(Atwr)};
99 int B_rho{get_rho(Btwr)};
100 int C_rho{get_rho(Ctwr)};
101 int A_sigma{3*get_sigma(Atwr)};
102 int B_sigma{3*get_sigma(Btwr)};
103 int C_sigma{3*get_sigma(Ctwr)};
104
105 rho_MET(Atwr, A_MET_x_rms, A_MET_y_rms, A_rho, A_sigma);
106 rho_MET(Btwr, B_MET_x_rms, B_MET_y_rms, B_rho, B_sigma);
107 rho_MET(Ctwr, C_MET_x_rms, C_MET_y_rms, C_rho, C_sigma);
108
109 metTotal(A_MET_x_rms, A_MET_y_rms, B_MET_x_rms, B_MET_y_rms, C_MET_x_rms, C_MET_y_rms, MET_x_rms, MET_y_rms, MET_rms);
110
111 A_sumEt_nc = sumEtFPGAnc(Atwr, 0, etaThr);
112 B_sumEt_nc = sumEtFPGAnc(Btwr, 1, etaThr);
113 C_sumEt_nc = sumEtFPGAnc(Ctwr, 2, etaThr);
114 total_sumEt_nc = sumEt(A_sumEt_nc, B_sumEt_nc, C_sumEt_nc);
115 total_sumEt_nc = total_sumEt_nc/4;
116
117 A_sumEt_rms = sumEtFPGArms(Atwr, A_sigma);
118 B_sumEt_rms = sumEtFPGArms(Btwr, B_sigma);
119 C_sumEt_rms = sumEtFPGArms(Ctwr, C_sigma);
120 total_sumEt_rms = sumEt(A_sumEt_rms, B_sumEt_rms, C_sumEt_rms);
121 total_sumEt_rms = total_sumEt_rms/4;
122 //Define a vector to be filled with all the TOBs of one event
123
124 //TOB order
125 // 1) MET_x | MET_y <- ncMET
126 // 2) MET_x | MET_y <- rms
127 // 3) MET | sumET <- ncMET
128 // 4) MET | sumET <- rms
129
130 // fill in TOBs
131 // The order of the TOBs is given according to the TOB ID (TODO: check how it's done in fw)
132
133 // First TOB is (MET, SumEt)
134 outTOB[0] = (MET_y_nc& 0x00000FFF) << 0; //set the Quantity2 to the corresponding slot (LSB)
135 outTOB[0] = outTOB[0] | (MET_x_nc & 0x00000FFF) << 12;//Quantity 1 (in bit number 12)
136 if (MET_y_nc != 0) outTOB[0] = outTOB[0] | 0x00000001 << 24;//Status bit for Quantity 2 (0 if quantity is null)
137 if (MET_x_nc != 0) outTOB[0] = outTOB[0] | 0x00000001 << 25;//Status bit for Quantity 1 (0 if quantity is null)
138 outTOB[0] = outTOB[0] | (2 & 0x0000001F) << 26;//TOB ID temporary set to 2 according to JwoJ convention (need updates in EDM)
139
140// Second TOB is (MET_x, MET_y)
141 outTOB[1] = (MET_y_rms& 0x00000FFF) << 0; //set the Quantity2 to the corresponding slot (LSB)
142 outTOB[1] = outTOB[1] | (MET_x_rms & 0x00000FFF) << 12;//Quantity 1 (in bit number 12)
143 if (MET_y_rms != 0) outTOB[1] = outTOB[1] | 0x00000001 << 24;//Status bit for Quantity 2 (0 if quantity is null)
144 if (MET_x_rms != 0) outTOB[1] = outTOB[1] | 0x00000001 << 25;//Status bit for Quantity 1 (0 if quantity is null)
145 outTOB[1] = outTOB[1] | (2 & 0x0000001F) << 26;//TOB ID temporary set to 2 according to JwoJ convention (need updates in EDM)
146
147// Third TOB is hard components (MHT_x, MHT_y)
148 outTOB[2] = (total_sumEt_nc& 0x00000FFF) << 0; //set the Quantity2 to the corresponding slot (LSB)
149 outTOB[2] = outTOB[2] | (MET_nc & 0x00000FFF) << 12;//Quantity 1 (in bit number 12)
150 if (total_sumEt_nc != 0) outTOB[2] = outTOB[2] | 0x00000001 << 24;//Status bit for Quantity 2 (0 if quantity is null)
151 if (MET_nc != 0) outTOB[2] = outTOB[2] | 0x00000001 << 25;//Status bit for Quantity 1 (0 if quantity is null)
152 outTOB[2] = outTOB[2] | (1 & 0x0000001F) << 26;//TOB ID temporary set to 1 according to JwoJ convention (need updates in EDM)
153
154 // Fourth TOB is hard components (MST_x, MST_y)
155 outTOB[3] = (total_sumEt_rms& 0x00000FFF) << 0; //set the Quantity2 to the corresponding slot (LSB)
156 outTOB[3] = outTOB[3] | (MET_rms & 0x00000FFF) << 12;//Quantity 1 (in bit number 12)
157 if (total_sumEt_rms != 0) outTOB[3] = outTOB[3] | 0x00000001 << 24;//Status bit for Quantity 2 (0 if quantity is null)
158 if (MET_rms != 0) outTOB[3] = outTOB[3] | 0x00000001 << 25;//Status bit for Quantity 1 (0 if quantity is null)
159 outTOB[3] = outTOB[3] | (1 & 0x0000001F) << 26;//TOB ID temporary set to 1 according to JwoJ convention (need updates in EDM)
160
161
162}
163
164 void gFEXaltMetAlgo::metFPGA(const gTowersCentral &twrs, int & MET_x, int & MET_y, const unsigned short FPGA_NO, const std::array<std::vector<int>, 3>& etaThr) const {
165 static const int s_cosLUT[32] = {
166 31, 30, 29, 26, 22, 17, 12, 6,
167 0, -6,-12,-17,-22,-26,-29,-30,
168 -31,-30,-29,-26,-22,-17,-12, -6,
169 0, 6, 12, 17, 22, 26, 29, 30
170 };
171 static const int s_sinLUT[32] = {
172 0, 6, 12, 17, 22, 26, 29, 30,
173 31, 30, 29, 26, 22, 17, 12, 6,
174 0, -6,-12,-17,-22,-26,-29,-30,
175 -31,-30,-29,-26,-22,-17,-12, -6
176 };
177
178 int rows = twrs.size();
179 int cols = twrs[0].size();
180
181 for (int irow = 0; irow < rows; irow++) {
182 int etasum = 0;
183 for (int jcolumn = 0; jcolumn < cols; jcolumn++) {
184 int tower_et = twrs[irow][jcolumn] & ~3; // Clear 2 LSBs
185 int scaled_thr = etaThr[FPGA_NO][jcolumn] * 4; // factor of 4 converts threshold from 800 MeV/count (fw) to 200 MeV/count (sim)
186 if (tower_et > scaled_thr) {
187 etasum += tower_et;
188 }
189 }
190
191 MET_x += etasum * s_cosLUT[irow];
192 MET_y += etasum * s_sinLUT[irow];
193 }
194
195 MET_x >>= 5;
196 MET_y >>= 5;
197
198}
199
200
201inline void gFEXaltMetAlgo::metTotal(const int A_MET_x, const int A_MET_y,
202 const int B_MET_x, const int B_MET_y,
203 const int C_MET_x, const int C_MET_y,
204 int & MET_x, int & MET_y, int & MET) const {
205
206 MET_x = A_MET_x + B_MET_x + C_MET_x;
207 MET_y = A_MET_y + B_MET_y + C_MET_y;
208
209 if (MET_x < -0x0007FF) MET_x = -0x0007FF;
210 if (MET_y < -0x0007FF) MET_y = -0x0007FF;
211
212 if (MET_x > 0x0007FF) MET_x = 0x0007FF;
213 if (MET_y > 0x0007FF) MET_y = 0x0007FF;
214
215 int MET2 = MET_x * MET_x + MET_y * MET_y;
216
217 if (MET2 > 0x000FFF) MET = 0x000FFF;
218 else if (MET2 < 0) MET = 0x000FFF;
219 else MET = std::sqrt(MET2);
220
221}
222
223//Function to calculate rho for the given set of gtowers
225 const int rows = twrs.size();
226 const int cols = twrs[0].size();
227 const int n{rows*cols};
228 float rho = 0;
229 for(int i = 0; i < rows; i++) {
230 for(int j = 0; j < cols; j++) {
231 rho += twrs[i][j] < m_rhoPlusThr ? twrs[i][j] : 0;
232 }
233 }
234 return rho/n;
235}
236
237//Function calculates standard deviation of the gtowers
239
240 int rows = twrs.size();
241 int cols = twrs[0].size();
242 const int n{rows*cols};
243 int sigma = 0;
244 for(int i = 0; i < rows; ++i) {
245 for(int j = 0; j < cols; ++j) {
246 const int towers{twrs[i][j]};
247 sigma += twrs[i][j] < m_rhoPlusThr ? towers*towers: 0;
248 }
249 }
250
251 return static_cast<int>(std::sqrt(sigma * 1. / n));
252
253}
254
255
256void gFEXaltMetAlgo::rho_MET(const gTowersCentral &twrs, int & MET_x, int & MET_y, const int rho, const int sigma) const {
257
258 int rows = twrs.size();
259 int cols = twrs[0].size();
260 for( int irow = 0; irow < rows; irow++ ){
261 for(int jcolumn = 0; jcolumn < cols; jcolumn++){
262 const int ET_gTower_sub{(twrs[irow][jcolumn] - rho) & 0xFFF};
263 const bool filter{ET_gTower_sub > sigma && !(ET_gTower_sub & 0x800)};
264 MET_x += filter ? (ET_gTower_sub)*cosLUT(irow, 5) : 0;
265 MET_y += filter ? (ET_gTower_sub)*sinLUT(irow, 5) : 0;
266
267 }
268 }
269}
270
271 int gFEXaltMetAlgo::sumEtFPGAnc(const gTowersCentral &twrs, const unsigned short FPGA_NO, const std::array<std::vector<int>, 3>& etaThr) const {
272
273 int partial_sumEt = 0;
274 const int rows = twrs.size();
275 const int cols = twrs[0].size();
276 for( int irow = 0; irow < rows; irow++ ){
277 for(int jcolumn = 0; jcolumn<cols; jcolumn++){
278 partial_sumEt += twrs[irow][jcolumn] > etaThr[FPGA_NO][jcolumn] * 4 ? twrs[irow][jcolumn] : 0; // factor of 4 converts threshold from 800 MeV/count (fw) to 200 MeV/count (sim)
279 }
280 }
281 return partial_sumEt;
282}
283
284int gFEXaltMetAlgo::sumEtFPGArms(const gTowersCentral &twrs, const int sigma) const {
285
286 int partial_sumEt = 0;
287 const int rows = twrs.size();
288 const int cols = twrs[0].size();
289 for(int i{0}; i < rows; ++i){
290 for(int j{0}; j < cols; ++j) {
291 partial_sumEt += twrs[i][j] > sigma ? twrs[i][j] : 0;
292 }
293 }
294 return partial_sumEt;
295}
296
297int gFEXaltMetAlgo::sumEt(const int A_sumEt, const int B_sumEt, const int C_sumEt) const {
298 return A_sumEt + B_sumEt + C_sumEt;
299}
300
301//----------------------------------------------------------------------------------
302// bitwise simulation of sine LUT in firmware
303//----------------------------------------------------------------------------------
304float gFEXaltMetAlgo::sinLUT(const unsigned int phiIDX, const unsigned int aw) const
305{
306 float c = ((float)phiIDX)/std::pow(2,aw);
307 float rad = (2*M_PI) *c;
308 float rsin = std::sin(rad);
309 return rsin;
310}
311
312//----------------------------------------------------------------------------------
313// bitwise simulation cosine LUT in firmware
314//----------------------------------------------------------------------------------
315float gFEXaltMetAlgo::cosLUT(const unsigned int phiIDX, const unsigned int aw) const
316{
317 float c = ((float)phiIDX)/std::pow(2,aw);
318 float rad = (2*M_PI) *c;
319 float rcos = std::cos(rad);
320 return rcos;
321}
322
323
324} // namespace LVL1
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
void metFPGA(const gTowersCentral &twrs, int &MET_x, int &MET_y, const unsigned short FPGA_NO, const std::array< std::vector< int >, 3 > &etaThr) const
gFEXaltMetAlgo(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
int sumEtFPGAnc(const gTowersCentral &twrs, const unsigned short FPGA_NO, const std::array< std::vector< int >, 3 > &etaThr) const
float cosLUT(const unsigned int phiIDX, const unsigned int aw) const
virtual void altMetAlgo(const EventContext &ctx, const gTowersCentral &Atwr, const gTowersCentral &Btwr, const gTowersCentral &Ctwr, std::array< uint32_t, 4 > &outTOB) const override
float sinLUT(const unsigned int phiIDX, const unsigned int aw) const
virtual StatusCode initialize() override
standard Athena-Algorithm method
SG::ReadHandleKey< TrigConf::L1Menu > m_l1MenuKey
void metTotal(const int A_MET_x, const int A_MET_y, const int B_MET_x, const int B_MET_y, const int C_MET_x, const int C_MET_y, int &MET_x, int &MET_y, int &MET) const
int sumEt(const int A_sumEt, const int B_sumEt, const int C_sumEt) const
int sumEtFPGArms(const gTowersCentral &twrs, const int sigma) const
int get_sigma(const gTowersCentral &twrs) const
void rho_MET(const gTowersCentral &twrs, int &MET_x, int &MET_y, const int rho, const int sigma) const
int get_rho(const gTowersCentral &twrs) const
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
std::array< std::array< int, 12 >, 32 > gTowersCentral
Definition MET.py:1