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