ATLAS Offline Software
Loading...
Searching...
No Matches
gFexTowerSummer.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//***************************************************************************
6// gFexTowerSummer - description
7// -------------------
8// Builds gFexDataTowers50 and gFexDataTowers200 from gFexDataTowers
9//
10// begin : 25 06 2025
11// email : jared.little@cern.ch
12//***************************************************************************/
13
14#include "gFexTowerSummer.h"
16
17
18#include <vector>
19#include <memory>
20#include <cmath> //M_PI
21
22namespace LVL1 {
23
24gFexTowerSummer::gFexTowerSummer(const std::string& name, ISvcLocator* svc)
26
28
30 "Initializing L1CaloFEXAlgos/gFexEmulatedTowers algorithm with name: "
31 << name());
32 ATH_MSG_INFO("Writing into SG key: " << m_gTowersWriteKey);
33
34 // initialise keys
36 ATH_CHECK( m_gTowersWriteKey.initialize() );
37 ATH_CHECK( m_gTowers50WriteKey.initialize() );
38
41
42 return StatusCode::SUCCESS;
43}
44
45StatusCode gFexTowerSummer::execute(const EventContext& ctx) const {
46
47 // WriteHandle for gFEX Input Towers
49 ATH_CHECK( gTowersContainer.record(std::make_unique<xAOD::gFexTowerContainer>(), std::make_unique<xAOD::gFexTowerAuxContainer>()));
50 ATH_MSG_DEBUG("Recorded gFexEmulatedTower 200 MeV container with key "<< gTowersContainer.key());
51
53 ATH_CHECK( gTowers50Container.record(std::make_unique<xAOD::gFexTowerContainer>(), std::make_unique<xAOD::gFexTowerAuxContainer>()));
54 ATH_MSG_DEBUG("Recorded gFexEmulatedTower 50 MeV container with key "<< gTowers50Container.key());
55
56 xAOD::gFexTowerContainer* gTowersEMContainerPtr = nullptr;
57 xAOD::gFexTowerContainer* gTowersHADContainerPtr = nullptr;
60
61 if (!m_gTowersEMWriteKey.empty()) {
62 ATH_CHECK( gTowersEMContainer.record(std::make_unique<xAOD::gFexTowerContainer>(), std::make_unique<xAOD::gFexTowerAuxContainer>()));
63 ATH_MSG_DEBUG("Recorded gFexEmulatedTower 200 MeV EM container with key "<< m_gTowersEMWriteKey.key());
64 gTowersEMContainerPtr = &*gTowersEMContainer;
65 }
66 if (!m_gTowersHADWriteKey.empty()) {
67 ATH_CHECK( gTowersHADContainer.record(std::make_unique<xAOD::gFexTowerContainer>(), std::make_unique<xAOD::gFexTowerAuxContainer>()));
68 ATH_MSG_DEBUG("Recorded gFexEmulatedTower 200 MeV HAD container with key "<< m_gTowersHADWriteKey.key());
69 gTowersHADContainerPtr = &*gTowersHADContainer;
70 }
71
72 // Atwr, Btwr, Ctwr will contain gTowers towers for each FPGA
73 gtFPGA Atwr{};
74 gtFPGA Btwr{};
75 gtFPGA Ctwr{};
76
77 gtFPGA AtwrF{};
78 gtFPGA BtwrF{};
79 gtFPGA CtwrF{};
80
81 gtFPGA Asatur{};
82 gtFPGA Bsatur{};
83 gtFPGA Csatur{};
84
85
86 // reconstruct the gTowers/saturation
87 ATH_CHECK( gtReconstructABC(ctx, 0, AtwrF, Atwr, Asatur));
88 ATH_CHECK( gtReconstructABC(ctx, 1, BtwrF, Btwr, Bsatur));
89 ATH_CHECK( gtReconstructABC(ctx, 2, CtwrF, Ctwr, Csatur));
90
91
92 // Write the towers
93 int iEta = 0;
94 int iPhi = 0;
95 float Eta = 0;
96 float Phi = 0;
97 int Et = 0;
98 int EtF = 0;
99 int Fpga = 0;
100 char IsSaturated = 0;
101 int towerID = 0;
102
103 // Assign ID based on FPGA (FPGA-A 0->0; FPGA-B 1->10000, FPGA-C 2->20000) and gTower number assigned as per firmware convention
104
105 int twr_rows = Atwr.size(); // 32
106 int twr_cols = Atwr[0].size(); // 12
107
108 Fpga = 0;
109
110 // Save towers from FPGA A in gTower EDM
111 for (int irow = 0; irow < twr_rows; irow++){
112 for (int icol = 0; icol < twr_cols; icol++){
113 iEta = icol + 8;
114 iPhi = irow;
115 Et = Atwr[irow][icol];
116 EtF = AtwrF[irow][icol];
117 IsSaturated = Asatur[irow][icol];
118 getEtaPhi(Eta, Phi, iEta, iPhi, towerID);
119 gTowersContainer->push_back( std::make_unique<xAOD::gFexTower>() );
120 gTowersContainer->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
121 gTowers50Container->push_back( std::make_unique<xAOD::gFexTower>() );
122 gTowers50Container->back()->initialize(iEta, iPhi, Eta, Phi, EtF, Fpga, IsSaturated, towerID);
123 if (gTowersEMContainerPtr) {
124 gTowersEMContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
125 gTowersEMContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
126 }
127 if (gTowersHADContainerPtr) {
128 gTowersHADContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
129 gTowersHADContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
130 }
131 towerID += 1;
132
133 }
134 }
135
136 // Save towers from FPGA B in gTower EDM
137 Fpga = 1;
138 towerID = 10000;
139 // Save towers from FPGA B in gTower EDM
140 for (int irow = 0; irow < twr_rows; irow++){
141 for (int icol = 0; icol < twr_cols; icol++){
142 iEta = icol + 20;
143 iPhi = irow;
144 Et = Btwr[irow][icol];
145 EtF = BtwrF[irow][icol];
146 IsSaturated = Bsatur[irow][icol];
147 getEtaPhi(Eta, Phi, iEta, iPhi, towerID);
148 gTowersContainer->push_back( std::make_unique<xAOD::gFexTower>() );
149 gTowersContainer->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
150 gTowers50Container->push_back( std::make_unique<xAOD::gFexTower>() );
151 gTowers50Container->back()->initialize(iEta, iPhi, Eta, Phi, EtF, Fpga, IsSaturated, towerID);
152 if (gTowersEMContainerPtr) {
153 gTowersEMContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
154 gTowersEMContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
155 }
156 if (gTowersHADContainerPtr) {
157 gTowersHADContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
158 gTowersHADContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
159 }
160 towerID += 1;
161 }
162 }
163
164 // Save towers from FPGA C in gTower EDM
165 Fpga = 2;
166 towerID = 20000;
167 for (int irow = 0; irow < twr_rows; irow++){
168 for (int icol = 0; icol < twr_cols/2; icol++){
169 iEta = icol + 2;
170 iPhi = irow;
171 Et = Ctwr[irow][icol];
172 EtF = CtwrF[irow][icol];
173 IsSaturated = Csatur[irow][icol];
174 getEtaPhi(Eta, Phi, iEta, iPhi, towerID);
175 gTowersContainer->push_back( std::make_unique<xAOD::gFexTower>() );
176 gTowersContainer->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
177 gTowers50Container->push_back( std::make_unique<xAOD::gFexTower>() );
178 gTowers50Container->back()->initialize(iEta, iPhi, Eta, Phi, EtF, Fpga, IsSaturated, towerID);
179 if (gTowersEMContainerPtr) {
180 gTowersEMContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
181 gTowersEMContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
182 }
183 if (gTowersHADContainerPtr) {
184 gTowersHADContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
185 gTowersHADContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
186 }
187 towerID += 1;
188 }
189 for (int icol = twr_cols/2; icol < twr_cols; icol++){
190 iEta = icol + 26;
191 iPhi = irow;
192 Et = Ctwr[irow][icol];
193 EtF = CtwrF[irow][icol];
194 IsSaturated = Csatur[irow][icol];
195 getEtaPhi(Eta, Phi, iEta, iPhi, towerID);
196 gTowersContainer->push_back( std::make_unique<xAOD::gFexTower>() );
197 gTowersContainer->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
198 gTowers50Container->push_back( std::make_unique<xAOD::gFexTower>() );
199 gTowers50Container->back()->initialize(iEta, iPhi, Eta, Phi, EtF, Fpga, IsSaturated, towerID);
200 if (gTowersEMContainerPtr) {
201 gTowersEMContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
202 gTowersEMContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
203 }
204 if (gTowersHADContainerPtr) {
205 gTowersHADContainerPtr->push_back( std::make_unique<xAOD::gFexTower>() );
206 gTowersHADContainerPtr->back()->initialize(iEta, iPhi, Eta, Phi, Et, Fpga, IsSaturated, towerID);
207 }
208 towerID += 1;
209 }
210 }
211
212 return StatusCode::SUCCESS;
213}
214
215
216StatusCode gFexTowerSummer::gtReconstructABC(const EventContext& ctx,
217 unsigned int XFPGA,
218 gtFPGA &XgtF, gtFPGA &Xgt,
219 gtFPGA &Xsaturation) const{
220
221 // Loop over the Fiber Towers and fill gTower arrays as per original byte stream decoder
222
223 // Reading the Fiber Tower container
225 if (!gFexFiberTowerContainer.isValid()) {
226 ATH_MSG_ERROR("Could not retrieve Fiber tower collection "
227 << gFexFiberTowerContainer.key());
228 return StatusCode::FAILURE;
229 }
230
231 if (gFexFiberTowerContainer->empty()) {
232 ATH_MSG_WARNING("Cannot fill gTowers here, fiber container is empty. "
233 << gFexFiberTowerContainer->size());
234 return StatusCode::SUCCESS;
235 }
236
237 // Zero the input gTower sums/saturation
238 for(int irow=0; irow<LVL1::gFEXPos::ABC_ROWS; irow++){
239 for(int icolumn=0; icolumn<LVL1::gFEXPos::AB_COLUMNS; icolumn++){
240 Xgt[irow][icolumn] = 0;
241 XgtF[irow][icolumn] = 0;
242 Xsaturation[irow][icolumn] = 0;
243 }
244 }
245
246 // Energy arrays for the EM and hadronic in standard and extra eta regions
247 // 200 MeV towers
248 std::array<int, LVL1::gFEXPos::AB_TOWERS> etowerData{}; // 384
249 std::array<int, LVL1::gFEXPos::AB_TOWERS> htowerData{};
250 std::array<int, LVL1::gFEXPos::ABC_ROWS> xetowerData{}; // 32
251 std::array<int, LVL1::gFEXPos::ABC_ROWS> xhtowerData{};
252 std::array<int, LVL1::gFEXPos::ABC_ROWS> ohtowerData{};
253
254 // 50 MeV towers
255 std::array<int, LVL1::gFEXPos::AB_TOWERS> etowerDataF{};
256 std::array<int, LVL1::gFEXPos::AB_TOWERS> htowerDataF{};
257 std::array<int, LVL1::gFEXPos::ABC_ROWS> xetowerDataF{};
258 std::array<int, LVL1::gFEXPos::ABC_ROWS> xhtowerDataF{};
259 std::array<int, LVL1::gFEXPos::ABC_ROWS> ohtowerDataF{};
260
261 // saturation
262 std::array<bool, LVL1::gFEXPos::AB_TOWERS> saturationData{}; // 384
263
264 // loop over the Fiber towers, and fill the tower energy arrays
265 for(const xAOD::gFexTower* gfexFiberTower : *gFexFiberTowerContainer){
266 // first match the FPGA
267 unsigned int fiberTowerFpga = gfexFiberTower->fpga();
268 if (fiberTowerFpga != XFPGA) continue;
269
270 // working with "local" fiber number, iFiber
271 unsigned int fiberTowerId = gfexFiberTower->gFEXtowerID();
272 unsigned int offset = (XFPGA == 2) ? 20000 : (XFPGA == 1) ? 10000 : 0;
273 unsigned int iFiber = (fiberTowerId - offset)/16;
274
275 // Do not exceed maximum number of fibers for FPGA
276 unsigned int maxFiberN = (XFPGA == 2) ? LVL1::gFEXPos::C_FIBERS : LVL1::gFEXPos::AB_FIBERS;
277 if (iFiber >= maxFiberN) continue;
278
279 ATH_MSG_DEBUG(" accessing " << fiberTowerId << " " << XFPGA << " " << offset << " " << iFiber);
280
281 unsigned int iDatum = fiberTowerId%16;
282
283 int fiber_type = (XFPGA == 0) ? LVL1::gFEXPos::AMPD_NFI[iFiber] :
284 (XFPGA == 1) ? LVL1::gFEXPos::BMPD_NFI[iFiber] : LVL1::gFEXPos::CMPD_NFI[iFiber];
285
286 // tells where the data is coming from
287 // - 0 - EMB, EMB/EMEC -> EM contribution
288 // - 1 - TREX,HEC - Had contribution
289 // - 2 - extended region ( EMEC)
290 // - 3 - extended region ( HEC)
291 // - 6 - 200MeV region only ( HEC)
292 // - 11 - HEC - Had contribution
293
294 int dataType = (XFPGA == 0) ? LVL1::gFEXPos::AMPD_DTYP_ARR[fiber_type][iDatum] :
295 (XFPGA == 1) ? LVL1::gFEXPos::BMPD_DTYP_ARR[fiber_type][iDatum] :
296 LVL1::gFEXPos::CMPD_DTYP_ARR[fiber_type][iDatum];
297
298 // tower number 0 - 383
299 int ntower = (XFPGA == 0) ? LVL1::gFEXPos::AMPD_GTRN_ARR[iFiber][iDatum] :
300 (XFPGA == 1) ? LVL1::gFEXPos::BMPD_GTRN_ARR[iFiber][iDatum] :
301 LVL1::gFEXPos::CMPD_GTRN_ARR[iFiber][iDatum];
302
303 // calo type
304 // FPGA 0/1 0,1,2
305 // FPGA 2 3
306 int caloType = (XFPGA == 0) ? LVL1::gFEXPos::ACALO_TYPE[iFiber] :
307 (XFPGA == 1) ? LVL1::gFEXPos::BCALO_TYPE[iFiber] : LVL1::gFEXPos::CCALO_TYPE[iFiber];
308
309 // saturation
310 bool fiberSaturation = (bool)(gfexFiberTower->isSaturated());
311 if (fiberSaturation) {
312 saturationData[ntower] = fiberSaturation;
313 }
314
315 // Get the MLE from the EDM (stored as float)
316 unsigned int Toweret_mle = (unsigned int)(gfexFiberTower->towerEt());
317
318 // FPGA 0/1
319 if(caloType < 3) {
320 switch(dataType){
321 case 0:
322 etowerData[ntower] = Toweret_mle;
323 undoMLE( etowerData[ntower] );
324 etowerDataF[ntower] = etowerData[ntower];
325 break;
326 case 1:
327 htowerData[ntower] = Toweret_mle;
328
329 // mulitply by 20 to make 50 MeV LSB
330 // include this here before mulitplication by 20
331 htowerData[ntower] = 20*htowerData[ntower];
332 htowerDataF[ntower] = htowerData[ntower];
333 break;
334
335 case 2:
336 xetowerData[ntower] = Toweret_mle;
337 undoMLE( xetowerData[ntower] );
338 xetowerDataF[ntower] = xetowerData[ntower];
339 break;
340
341 case 3:
342 xhtowerData[ntower] = Toweret_mle;
343 undoMLE( xhtowerData[ntower] );
344 xhtowerDataF[ntower] = xhtowerData[ntower];
345 break;
346
347 case 6:
348 ohtowerData[ntower] = Toweret_mle;
349 undoMLE( ohtowerData[ntower] );
350 ohtowerDataF[ntower] = ohtowerData[ntower];
351 break;
352
353 case 11:
354 htowerData[ntower] = Toweret_mle;
355 undoMLE( htowerData[ntower] );
356 htowerDataF[ntower] = htowerData[ntower];
357 break;
358 }
359 } else {
360
361 // this is FPGA C
362 // only types 2 and 3 exist in FPGA C
363 switch(dataType){
364 case 2:
365 //
366 etowerData[ntower] = Toweret_mle;
367 undoMLE( etowerData[ntower] );
368 etowerDataF[ntower] = etowerData[ntower];
369
370 break;
371
372 case 3:
373 htowerData[ntower] = Toweret_mle;
374 undoMLE( htowerData[ntower] );
375 htowerDataF[ntower] = htowerData[ntower];
376 break;
377
378 case 15:
379 break;
380
381 case 99:
382 break;
383
384 default:
385 ATH_MSG_ERROR("Tower with unknown datatype "
386 << dataType);
387 return StatusCode::FAILURE;
388
389 }
390 } // end of case statement for FPGAC
391
392 ATH_MSG_DEBUG(" end of loop: " << XFPGA << " tower: " << ntower << " e " << etowerDataF[ntower] << " h " << htowerData[ntower] << " fibertower " << fiberTowerId);
393
394 } // end of loop over fiber towers
395
396 // Sum the energy arrays into the output gTowers
397 if( XFPGA == 0 ) {
398 for(int itower=0;itower<384;itower++){
399 int icolumn = itower%12;
400 int irow = itower/12;
401
402 // saturation
403 Xsaturation[irow][icolumn] = saturationData[itower];
404
405
406 // 50 MeV towers
407 int xF = etowerDataF[itower] + htowerDataF[itower];
408 // 200 MeV towers
409 int x = ( (etowerData[itower]>>2) + (htowerData[itower]>>2) );
410
411 ATH_MSG_DEBUG("sss1 " << icolumn << " " << irow << " " << xF << " " << x << " " << etowerDataF[itower] <<" " << htowerDataF[itower]);
412
413 signExtend(&xF,18);
414 signExtend(&x,18);
415
416 ATH_MSG_DEBUG("sss2 " << icolumn << " " << irow << " " << xF << " " << x);
417
418 Xgt[irow][icolumn] = x;
419 XgtF[irow][icolumn] = xF;
420
421 ATH_MSG_DEBUG("sss3 " << icolumn << " " << irow << " " << XgtF[irow][icolumn] << " " << Xgt[irow][icolumn]);
422
423 // eta region in FPGA A (eta ~ -2.5)
424 if ( icolumn == 0) {
425 int xx = ( (xetowerData[irow]>>2) + (xhtowerData[irow]>>2) );
426 signExtend(&xx,18);
427 Xgt[irow][icolumn] = Xgt[irow][icolumn] + xx;
428 ATH_MSG_DEBUG("sss4 " << icolumn << " " << irow << " " << XgtF[irow][icolumn] << " " << Xgt[irow][icolumn]);
429 }
430
431 if ( icolumn == 4) {
432 // 200 MeV towers
433 int ox = (ohtowerData[irow] >> 2 ) ;
434 signExtend(&ox,18);
435 Xgt[irow][icolumn] = Xgt[irow][icolumn] + ox ;
436 ATH_MSG_DEBUG("sss5 " << icolumn << " " << irow << " " << XgtF[irow][icolumn] << " " << Xgt[irow][icolumn]);
437 }
438
439 ATH_MSG_DEBUG("sss filling standard " << Xgt[irow][icolumn] << " fiber " << XgtF[irow][icolumn]);
440 }
441 }
442 else if ( XFPGA == 1 ) {
443 for(int itower=0;itower<384;itower++){
444 int icolumn = itower%12;
445 int irow = itower/12;
446
447 // saturation
448 Xsaturation[irow][icolumn] = saturationData[itower];
449
450 // 50 MeV towers
451 int xF = etowerDataF[itower] + htowerDataF[itower] ;
452 // 200 MeV towers
453 int x = ( (etowerData[itower]>>2) + (htowerData[itower] >> 2) );
454
455 signExtend(&xF,18);
456 signExtend(&x,18);
457
458 Xgt[irow][icolumn] = x;
459 XgtF[irow][icolumn] = xF;
460
461 // extra region FPGA B (eta ~ 2.5)
462 if ( icolumn == 11) {
463 // 200 MeV towers
464 int xx = ( (xetowerData[irow]>>2) + (xhtowerData[irow]>>2) );
465 signExtend(&xx,18);
466 Xgt[irow][icolumn] = Xgt[irow][icolumn] + xx;
467 }
468 if ( icolumn == 7 ) {
469 // 200 MeV towers
470 int xo = ohtowerData[irow]>>2;
471 signExtend(&xo,18);
472 Xgt[irow][icolumn] = Xgt[irow][icolumn] + xo;
473 }
474 }
475 }
476 else if ( XFPGA == 2 ) {
477 for(int itower=0;itower<384;itower++){
478 int icolumn = itower%12;
479 int irow = itower/12;
480
481 // saturation
482 Xsaturation[irow][icolumn] = saturationData[itower];
483
484 // 50 MeV towers
485 int xF = etowerDataF[itower] + htowerDataF[itower] ;
486 // 200 MeV towers
487 int x = ( (etowerData[itower]>>2 ) + (htowerData[itower]>>2));
488 signExtend(&xF,18);
489 signExtend(&x,18);
490
491 Xgt[irow][icolumn] = x;
492 XgtF[irow][icolumn] = xF;
493 }
494 }
495
496 return StatusCode::SUCCESS;
497}
498
499void gFexTowerSummer::undoMLE(int &datumPtr ) const{
500
501 // limit input to 12 bits to avoid accidental sign extension
502 int din = (0x00000FFF & datumPtr );
503 // map all special cases to zero for now
504 // limit negative values
505 if( (din > 0) && ( din < 962 ) ) din = 962;
506 //zeroZero
507 if( din == 0) din = 0x4EE;
508
509 int dout = 0;
510
511 int FPGA_CONVLIN_TH1 = 5;
512 int FPGA_CONVLIN_TH2 = 749;
513 int FPGA_CONVLIN_TH3 = 1773;
514 int FPGA_CONVLIN_TH4 = 2541;
515 int FPGA_CONVLIN_TH5 = 4029;
516 int FPGA_CONVLIN_TH6 = 4062;
517
518 // These two variables are unused
519 //int FPGA_CONVLIN_OF0 = -5072;
520 //int FPGA_CONVLIN_OF1 = -2012;
521 int FPGA_CONVLIN_OF2 = -1262;
522 int FPGA_CONVLIN_OF3 = -3036;
523 int FPGA_CONVLIN_OF4 = -8120;
524 int FPGA_CONVLIN_OF5 = -4118720;
525
526 int oth0 = 0;
527 int oth1 = 0;
528 int oth2 = 0;
529 int oth3 = 0;
530 int oth4 = 0;
531 int oth5 = 0;
532 int oth6 = 0;
533
534 // These two variables are unused
535 //int r1shv = 0;
536 //int r2shv = 0;
537 int r3shv = 0;
538 int r4shv = 0;
539 int r5shv = 0;
540 int r6shv = 0;
541 // int trxv = 0;
542
543
544 int r3conv = 0;
545 int r4conv = 0;
546 int r5conv = 0;
547 int r6conv = 0;
548 // int r3offs = 0;
549
550 //r1shv = ((din & 0x0000007F) << 9 ) & 0x0000FE00 ;
551 //r2shv = ((din & 0x00000FFF) << 1 ) & 0x00001FFE ;
552 r3shv = (din & 0x00000FFF) ;
553 r4shv = ((din & 0x00000FFF) << 1 ) & 0x00001FFE ;
554 r5shv = ((din & 0x00000FFF) << 2 ) & 0x00003FFC ;
555 r6shv = ((din & 0x00000FFF) << 10 ) & 0x003FFC00 ;
556
557 // These two variables are unused
558 //r1conv = r1shv + FPGA_CONVLIN_OF0;
559 //r2conv = r2shv + FPGA_CONVLIN_OF1;
560 r3conv = r3shv + FPGA_CONVLIN_OF2;
561 r4conv = r4shv + FPGA_CONVLIN_OF3;
562 r5conv = r5shv + FPGA_CONVLIN_OF4;
563 r6conv = r6shv + FPGA_CONVLIN_OF5;
564
565 if( din > 0 ) {
566 oth0 = 1;
567 }
568 else{
569 oth0 = 0;
570 }
571 if ( din > FPGA_CONVLIN_TH1 ){
572 oth1 = 1;
573 }
574 else{
575 oth1 = 0;
576 }
577 if ( din > FPGA_CONVLIN_TH2 ){
578 oth2 = 1;
579 }else{
580 oth2 = 0;
581 }
582 if ( din > FPGA_CONVLIN_TH3 ){
583 oth3 = 1;
584 }else{
585 oth3 = 0;
586 }
587 if ( din > FPGA_CONVLIN_TH4 ){
588 oth4 = 1;
589 }else{
590 oth4 = 0;
591 }
592 if ( din > FPGA_CONVLIN_TH5 ){
593 oth5 = 1;
594 }
595 else{
596 oth5 = 0;
597 }
598 if ( din > FPGA_CONVLIN_TH6 ){
599 oth6 = 1;
600 }
601 else{
602 oth6 = 0;
603 }
604
605
606 // divide by 2 to 50 MeV LSB
607
608 if( (! oth0) & (! oth1 ) & (! oth2 ) & (! oth3 ) & (! oth4 ) & (! oth5 ) & (! oth6 ) ) {
609 dout = 0;
610 }
620 else if( ( oth0) & ( oth1 ) & ( oth2 ) & (! oth3 ) & (! oth4 ) & (! oth5 ) & (! oth6 ) ) {
621 dout = r3conv >>1;
622 }
623 else if( ( oth0) & ( oth1 ) & ( oth2 ) & ( oth3 ) & (! oth4 ) & (! oth5 ) & (! oth6 ) ) {
624 dout = r4conv >>1;
625 }
626 else if( ( oth0) & ( oth1 ) & ( oth2 ) & ( oth3 ) & ( oth4 ) & (! oth5 ) & (! oth6 ) ) {
627 dout = r5conv >>1;
628 }
629 else if( ( oth0) & ( oth1 ) & ( oth2 ) & ( oth3 ) & ( oth4 ) & ( oth5 ) & (! oth6 ) ) {
630 dout = r6conv >>1;
631 }
632 else if( ( oth0) & ( oth1 ) & ( oth2 ) & ( oth3 ) & ( oth4 ) & ( oth5 ) & ( oth6 ) ) {
633 dout = 0;
634 }
635 /* This code cannot be reached, given the preceding conditions.
636 else {
637 dout = 0;
638 }
639 */
640
641 signExtend(&dout,15);
642
643 datumPtr = dout;
644}
645
646
647void gFexTowerSummer::signExtend(int *xptr, int upto) const{
648
649 // sign extend x to 32 bits assuming a hardware word length upto+1 bits (e.g. for 16 bit word upto should be 15 as in firmware)
650 // xptr pointer to input datum
651 // word length in hardware
652 int x = *xptr;
653 //printf("before %x \n", x);
654 //printf("masks %x %x \n", (0x00000001<<upto) , (0xFFFFFFFF<<(upto+1)) );
655 if( x & (0x00000001<<upto) ) {
656 x = ( x | (0xFFFFFFFF<<(upto+1)) );
657 } else {
658 // for now assume 17 bits -- but could be up to 18 bits
659 x = ( x & 0x000FFFF);
660 }
661 *xptr = x;
662
663}
664
665void gFexTowerSummer::getEtaPhi(float& Eta, float& Phi, int iEta, int iPhi,
666 int gFEXtowerID) const {
667
668 float s_centralPhiWidth =
669 (2 * M_PI) / 32; // In central region, gFex has 32 bins in phi
670 float s_forwardPhiWidth =
671 (2 * M_PI) / 16; // In forward region, gFex has 16 bins in phi (before
672 // rearranging bins)
673
674 const std::vector<float> s_EtaCenter = {
675 -4.5, -3.8, -3.38, -3.18, -3.15, -3, -2.8, -2.6, -2.35, -2.1,
676 -1.9, -1.7, -1.5, -1.3, -1.1, -0.9, -0.7, -0.5, -0.3, -0.1,
677 0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9,
678 2.1, 2.35, 2.6, 2.8, 3.0, 3.15, 3.18, 3.38, 3.8, 4.5};
679
680 // Transform Eta and Phi indices for the most forward towers into the
681 // "original" indices, as before rearranging the towers such that the forward
682 // region is 12(ieta)x32(iphi). The FPGA-C has now the same format (12*32) as
683 // FPGA-A and FPGA-B. This is the result of a transformation in the firmware.
684 // Note that for the most forward towers, the Phi index and Eta index have
685 // been considered accordingly, so in order to get the correct float values of
686 // Phi and Eta we need to retrieve the "original" indices.
687 int towerID_base = 20000;
688 int iEtaOld = 0, iPhiOld = 0;
689
690 if (iEta == 2) {
691 if (iPhi == ((gFEXtowerID - towerID_base) / 24) * 2) {
692 iEtaOld = 0;
693 iPhiOld = iPhi / 2;
694 }
695 if (iPhi == (((gFEXtowerID - towerID_base - 12) / 24) * 2) + 1) {
696 iEtaOld = 1;
697 iPhiOld = (iPhi - 1) / 2;
698 }
699 }
700
701 else if (iEta == 3) {
702 if (iPhi == ((gFEXtowerID - towerID_base - 1) / 24) * 2) {
703 iEtaOld = 2;
704 iPhiOld = iPhi / 2;
705 }
706 if (iPhi == (((gFEXtowerID - towerID_base - 13) / 24) * 2) + 1) {
707 iEtaOld = 3;
708 iPhiOld = (iPhi - 1) / 2;
709 }
710 }
711
712 else if (iEta == 36) {
713 if (iPhi == (((gFEXtowerID - towerID_base - 22) / 24) * 2) + 1) {
714 iEtaOld = 36;
715 iPhiOld = (iPhi - 1) / 2;
716 }
717 if (iPhi == ((gFEXtowerID - towerID_base - 10) / 24) * 2) {
718 iEtaOld = 37;
719 iPhiOld = iPhi / 2;
720 }
721 }
722
723 else if (iEta == 37) {
724 if (iPhi == (((gFEXtowerID - towerID_base - 23) / 24) * 2) + 1) {
725 iEtaOld = 38;
726 iPhiOld = (iPhi - 1) / 2;
727 }
728 if (iPhi == ((gFEXtowerID - towerID_base - 11) / 24) * 2) {
729 iEtaOld = 39;
730 iPhiOld = iPhi / 2;
731 }
732 }
733
734 else {
735 iEtaOld = iEta;
736 iPhiOld = iPhi;
737 }
738
739 Eta = s_EtaCenter[iEtaOld];
740
741 float Phi_gFex = -99;
742
743 if ((iEtaOld <= 3) || ((iEtaOld >= 36))) {
744 Phi_gFex = ((iPhiOld * s_forwardPhiWidth) + s_forwardPhiWidth / 2);
745 } else {
746 Phi_gFex = ((iPhiOld * s_centralPhiWidth) + s_centralPhiWidth / 2);
747 }
748
749 if (Phi_gFex < M_PI) {
750 Phi = Phi_gFex;
751 } else {
752 Phi = (Phi_gFex - 2 * M_PI);
753 }
754}
755
756} // namespace LVL1
#define M_PI
#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)
#define x
An algorithm that can be simultaneously executed in multiple threads.
const T * back() const
Access the last element in the collection as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
virtual StatusCode initialize() override
Function initialising the algorithm.
gFexTowerSummer(const std::string &name, ISvcLocator *svc)
SG::WriteHandleKey< xAOD::gFexTowerContainer > m_gTowersWriteKey
void signExtend(int *xptr, int upto) const
SG::WriteHandleKey< xAOD::gFexTowerContainer > m_gTowersHADWriteKey
std::array< std::array< int, LVL1::gFEXPos::AB_COLUMNS >, LVL1::gFEXPos::ABC_ROWS > gtFPGA
virtual StatusCode execute(const EventContext &) const override
Function executing the algorithm.
SG::ReadHandleKey< xAOD::gFexTowerContainer > m_gFexFiberTowersReadKey
SG::WriteHandleKey< xAOD::gFexTowerContainer > m_gTowersEMWriteKey
StatusCode gtReconstructABC(const EventContext &ctx, unsigned int XFPGA, gtFPGA &XgtF, gtFPGA &Xgt, gtFPGA &Xsaturation) const
SG::WriteHandleKey< xAOD::gFexTowerContainer > m_gTowers50WriteKey
void getEtaPhi(float &Eta, float &Phi, int iEta, int iPhi, int gFEXtowerID) const
void undoMLE(int &datumPtr) const
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.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
void initialize(const uint8_t IEta, const uint8_t IPhi)
setter for the above
constexpr std::array< std::array< int, 16 >, 100 > AMPD_GTRN_ARR
Definition gFexPos.h:124
constexpr std::array< std::array< char, 20 >, 4 > CMPD_DTYP_ARR
Definition gFexPos.h:494
constexpr std::array< int, 100 > CMPD_NFI
Definition gFexPos.h:375
constexpr int C_FIBERS
Definition gFexPos.h:60
constexpr std::array< std::array< int, 16 >, 100 > CMPD_GTRN_ARR
Definition gFexPos.h:397
constexpr int AB_COLUMNS
Definition gFexPos.h:64
constexpr std::array< int, 100 > ACALO_TYPE
Definition gFexPos.h:114
constexpr int ABC_ROWS
Definition gFexPos.h:63
constexpr std::array< std::array< char, 20 >, 4 > AMPD_DTYP_ARR
Definition gFexPos.h:216
constexpr std::array< std::array< char, 20 >, 4 > BMPD_DTYP_ARR
Definition gFexPos.h:351
constexpr std::array< int, 100 > BCALO_TYPE
Definition gFexPos.h:249
constexpr std::array< int, 100 > CCALO_TYPE
Definition gFexPos.h:389
constexpr std::array< int, 100 > AMPD_NFI
Definition gFexPos.h:105
constexpr std::array< int, 100 > BMPD_NFI
Definition gFexPos.h:241
constexpr std::array< std::array< int, 16 >, 100 > BMPD_GTRN_ARR
Definition gFexPos.h:257
constexpr int AB_FIBERS
Definition gFexPos.h:59
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
gFexTower_v1 gFexTower
Define the latest version of the TriggerTower class.
Definition gFexTower.h:15
gFexTowerContainer_v1 gFexTowerContainer
Define the latest version of the TriggerTower container.