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