ATLAS Offline Software
Loading...
Searching...
No Matches
eFEXegAlgo.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// eFEXegAlgo - description
7// -------------------
8// begin : 24 02 2020
9// email : antonio.jacques.costa@cern.ch ulla.blumenschein@cern.ch tong.qiu@cern.ch
10// ***************************************************************************/
11#include <vector>
12#include <mutex>
13
17#include "L1CaloFEXSim/eTower.h"
18
19
20namespace LVL1 {
21
22 // default constructor for persistency
23 eFEXegAlgo::eFEXegAlgo(const std::string& type, const std::string& name, const IInterface* parent):
24 AthAlgTool(type, name, parent)
25 {
26 declareInterface<eFEXegAlgo>(this);
27 }
28
33
35
36 ATH_CHECK(m_eTowerContainerKey.initialize());
38
39 return StatusCode::SUCCESS;
40 }
41
42
43 StatusCode eFEXegAlgo::safetyTest(const EventContext& ctx) {
44
46 if(!eTowerContainer.isValid()){
47 ATH_MSG_FATAL("Could not retrieve container " << m_eTowerContainerKey.key() );
48 return StatusCode::FAILURE;
49 }
51
52 return StatusCode::SUCCESS;
53 }
54
55 void eFEXegAlgo::setup(int inputTable[3][3], int efex_id, int fpga_id, int central_eta) {
56
57 std::copy(&inputTable[0][0], &inputTable[0][0] + 9, &m_eFEXegAlgoTowerID[0][0]);
58
59 m_efexid = efex_id;
60 m_fpgaid = fpga_id;
61 m_central_eta = central_eta;
62
63 setSeed();
64
65 }
66
68
69 const LVL1::eTower * tmpTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[1][1]);
70 et = tmpTower->getLayerTotalET(0) + tmpTower->getLayerTotalET(1) + tmpTower->getLayerTotalET(2) + tmpTower->getLayerTotalET(3);
71 }
72
74
75 const LVL1::eTower * tmpTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[1][1]);
76 et = tmpTower->getLayerTotalET(4);
77 }
78
80
81 phi = m_eTowers->findTower(m_eFEXegAlgoTowerID[1][1])->phi();
82
83 }
84
86
87 eta = m_eTowers->findTower(m_eFEXegAlgoTowerID[1][1])->eta() * m_eTowers->findTower(m_eFEXegAlgoTowerID[1][1])->getPosNeg();
88
89 }
90
91 void eFEXegAlgo::getReta(std::vector<unsigned int> & retavec) {
92
93 unsigned int coresum = 0; // 3x2 L2 sum : core
94 unsigned int totalsum = 0; // 7x3 L2 sum : total
95 unsigned int envsum = 0; // total - core : env
96
97 retavec.clear(); // clear the output vector before starting
98
99 // window limits
100 int iTotalStart = m_seedID-3;
101 int iTotalEnd = m_seedID+3;
102 int iCoreStart = m_seedID-1;
103 int iCoreEnd = m_seedID+1;
104 int phiStart = -999;
105 int phiEnd = -99;
106 if (m_seed_UnD) {
107 phiStart = 1;
108 phiEnd = 2;
109 } else {
110 phiStart = 0;
111 phiEnd = 1;
112 }
113
114 // 3x2 and 7x3 L2 sum
115 for (int i=iTotalStart; i<=iTotalEnd; ++i) { // eta
116 for(int j=0; j<=2; ++j) { // phi
117 if (i>=iCoreStart && i <= iCoreEnd && j>=phiStart && j<=phiEnd) {
118 unsigned int tmp_et; getWindowET(2,j,i,tmp_et);
119 coresum += tmp_et;
120 }
121
122 unsigned int tmptot_et; getWindowET(2,j,i,tmptot_et);
123 totalsum += tmptot_et;
124 }
125 }
126
127 // get environment
128 envsum = totalsum - coresum;
129
130 // Overflow handling
131 if (coresum > 0xffff) coresum = 0xffff;
132 if (envsum > 0xffff) envsum = 0xffff;
133
134 // Return results
135 retavec.push_back(coresum);
136 retavec.push_back(envsum);
137
138 }
139
140 void eFEXegAlgo::getRhad(std::vector<unsigned int> & rhadvec) {
141
142 unsigned int hadsum = 0; // 3x3 Towers Had
143 unsigned int emsum = 0; // (1x3 + 3x3 + 3x3 + 1x3) SCs EM
144
145 rhadvec.clear(); // clear the output vector before starting
146
147 int iCoreStart = m_seedID-1;
148 int iCoreEnd = m_seedID+1;
149
150 if(m_algoVersion==0) {
151 // 3x3 Towers Had ; 1x3 L0 + 1x3 L3 EM
152 for (int i=0; i<3; ++i) { // phi
153 for (int j=0; j<=2; ++j) { // eta
154 if (((m_efexid%3 == 0) && (m_fpgaid == 0) && (m_central_eta == 0) && (j == 0)) || ((m_efexid%3 == 2) && (m_fpgaid == 3) && (m_central_eta == 5) && (j == 2))) {
155 continue;
156 } else {
157 const eTower * tTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[i][j]);
158 hadsum += tTower->getLayerTotalET(4);
159 if (j==1) {
160 emsum += ( tTower->getLayerTotalET(0) + tTower->getLayerTotalET(3) );
161 }
162 }
163 }
164 }
165
166 // 3x3 SCs L1 and L2 sum
167 for (int i=iCoreStart; i<=iCoreEnd; ++i) { // eta
168 for(int j=0; j<=2; ++j) { // phi
169 unsigned int tmp_et_a, tmp_et_b;
170 getWindowET(1,j,i,tmp_et_a);
171 getWindowET(2,j,i,tmp_et_b);
172 emsum += ( tmp_et_a + tmp_et_b );
173 }
174 }
175 } else {
176
177 // see slide 4 of https://indico.cern.ch/event/1513502/contributions/6389265/attachments/3019474/5326755/Rate%20Reduction%20Methods%20Overview.pdf
178 // Update 29-Apr-2025: removing 4 corners of EM3 from sum
179
180 // EM cluster depends on UnD flag
181 int phi2 = (m_seed_UnD > 0 ? 2 : 0);
182
183 // 3x3 Towers Had + EM3 (excluding corners in EM3); 1x2 L0
184 for (int i = 0; i < 3; ++i) { // phi
185 for (int j = 0; j <= 2; ++j) { // eta
186 if (((m_efexid % 3 == 0) && (m_fpgaid == 0) && (m_central_eta == 0) && (j == 0)) ||
187 ((m_efexid % 3 == 2) && (m_fpgaid == 3) && (m_central_eta == 5) && (j == 2))) {
188 continue;
189 } else {
190 const eTower *tTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[i][j]);
191 hadsum += tTower->getLayerTotalET(4) + (((i==0&&j==0)||(i==2&&j==2)||(i==0&&j==2)||(i==2&&j==0)) ? 0 : tTower->getLayerTotalET(3));
192 // For PS add central tower + UnD phi neighbour
193 if (j == 1 && (i == 1 || i == phi2)) {
194 emsum += (tTower->getLayerTotalET(0));
195 }
196 }
197 }
198 }
199
200 // 3x2 SCs L1 and L2 sum, so phi range depends on UnD flag
201 int phiStart = 0;
202 int phiEnd = 1;
203 if (m_seed_UnD > 0) {
204 phiStart = 1;
205 phiEnd = 2;
206 }
207 for (int i = iCoreStart; i <= iCoreEnd; ++i) { // eta
208 for (int j = phiStart; j <= phiEnd; ++j) { // phi
209 unsigned int tmp_et_a, tmp_et_b;
210 getWindowET(1, j, i, tmp_et_a);
211 getWindowET(2, j, i, tmp_et_b);
212 emsum += (tmp_et_a + tmp_et_b);
213 }
214 }
215 }
216 // Overflow handling
217 if (emsum > 0xffff) emsum = 0xffff;
218 if (hadsum > 0xffff) hadsum = 0xffff;
219
220 // Return results
221 rhadvec.push_back(emsum);
222 rhadvec.push_back(hadsum);
223
224 }
225
226 void LVL1::eFEXegAlgo::getWstot(std::vector<unsigned int> & output){
227 unsigned int numer = 0;
228 unsigned int den = 0;
229
230 output.clear(); // clear the output vector before starting
231
232 int iStart = m_seedID - 2;
233 int iEnd = m_seedID + 2;
234
235 for (int i = iStart; i <= iEnd; ++i) { // eta
236 int diff = i - m_seedID;
237 unsigned int weight = diff*diff;
238 for (int j = 0; j <= 2; ++j) { // phi
239 unsigned int eT;
240 getWindowET(1, j, i, eT);
241 // NB need to be careful as numer and den are defined such that wstot=numer/den,
242 // but in the firmware (and therefore this bitwise code) we actually
243 // check that den/numer < Threshold
244 numer += eT*weight;
245 den += eT;
246 }
247 }
248
249 // Overflow handling
250 //if (den > 0xffff) den = 0xffff; - commented out so that denom can overflow, will then automatically pass all thresholds (see eFEXFPGA::SetIsoWP)
251 if (numer > 0xffff) numer = 0xffff;
252
253 // Return results
254 output.push_back(den);
255 output.push_back(numer);
256
257 }
258
261 void LVL1::eFEXegAlgo::getClusterCells(std::vector<unsigned int> &cellETs) {
262
263 int phiUpDownID = 0;
264 if (m_seed_UnD) phiUpDownID = 2;
265
266 // Initialise results vector
267 cellETs.resize(16,0);
268 // Fill vector with 2 PS cells, 6 L1, 6 L2, 2 L3
269 // Presampler
270 getWindowET(0, 1, 0, cellETs[0]);
271 getWindowET(0, phiUpDownID, 0, cellETs[1]);
272 // central phi Layer 1
273 getWindowET(1, 1, m_seedID, cellETs[2]);
274 getWindowET(1, 1, m_seedID - 1, cellETs[3]);
275 getWindowET(1, 1, m_seedID + 1, cellETs[4]);
276 // top/bottom phi Layer 1
277 getWindowET(1, phiUpDownID, m_seedID, cellETs[5]);
278 getWindowET(1, phiUpDownID, m_seedID - 1, cellETs[6]);
279 getWindowET(1, phiUpDownID, m_seedID + 1, cellETs[7]);
280 // central phi Layer 2
281 getWindowET(2, 1, m_seedID, cellETs[8]);
282 getWindowET(2, 1, m_seedID - 1, cellETs[9]);
283 getWindowET(2, 1, m_seedID + 1, cellETs[10]);
284 // top/bottom phi Layer 2
285 getWindowET(2, phiUpDownID, m_seedID, cellETs[11]);
286 getWindowET(2, phiUpDownID, m_seedID - 1, cellETs[12]);
287 getWindowET(2, phiUpDownID, m_seedID + 1, cellETs[13]);
288 // Layer 3
289 getWindowET(3, 1, 0, cellETs[14]);
290 getWindowET(3, phiUpDownID, 0, cellETs[15]);
291
292 return;
293
294 }
295
296 unsigned int LVL1::eFEXegAlgo::getET() {
297
299 std::vector<unsigned int> clusterCells;
300 getClusterCells(clusterCells);
301
302
304 unsigned int PS_ET = 0;
305
306 if(m_algoVersion==0) {
307 PS_ET = dmCorrection(clusterCells[0], 0)
308 + dmCorrection(clusterCells[1], 0);
309 } else {
310 // 2025 algoVersion only uses 1 PS scell, except at most extreme eta values
311 PS_ET = dmCorrection(clusterCells[0], 0);
312 if ( ((m_efexid%3) == 0 && m_fpgaid == 0) || ((m_efexid%3) == 2 && m_fpgaid == 3)) {
313 PS_ET += dmCorrection(clusterCells[1], 0);
314 }
315 }
316 unsigned int L1_ET = dmCorrection(clusterCells[2], 1)
317 + dmCorrection(clusterCells[3], 1)
318 + dmCorrection(clusterCells[4], 1)
319 + dmCorrection(clusterCells[5], 1)
320 + dmCorrection(clusterCells[6], 1)
321 + dmCorrection(clusterCells[7], 1);
322 unsigned int L2_ET = dmCorrection(clusterCells[8], 2)
323 + dmCorrection(clusterCells[9], 2)
324 + dmCorrection(clusterCells[10], 2)
325 + dmCorrection(clusterCells[11], 2)
326 + dmCorrection(clusterCells[12], 2)
327 + dmCorrection(clusterCells[13], 2);
328 unsigned int L3_ET = clusterCells[14] + clusterCells[15];
329
331 unsigned int totET = PS_ET + L1_ET + L2_ET + L3_ET;
332
333 // overflow handling
334 if (totET > 0xffff) totET = 0xffff;
335
336 return totET;
337
338 }
339
340
342 MsgStream& msg)
343 {
344 for (const auto& p : dmCorrections) {
345 if (p.first < 25 || p.first >= 50) continue;
346 m_corrections[0][p.first - 25] = p.second["EmPS"].data<int>();
347 m_corrections[1][p.first - 25] = p.second["EmFR"].data<int>();
348 m_corrections[2][p.first - 25] = p.second["EmMD"].data<int>();
349 if (msg.level() <= MSG::DEBUG) {
350 msg << MSG::DEBUG << "DM Correction for etaIdx=" << (p.first - 25) << " : [" << m_corrections[0][p.first - 25] << ","
351 << m_corrections[1][p.first - 25] << "," << m_corrections[2][p.first - 25] << "]"
352 << endmsg;
353 }
354 }
355 }
356
357 unsigned int LVL1::eFEXegAlgo::dmCorrection (unsigned int ET, unsigned int layer) {
359 if ( !m_dmCorr || layer > 2 ) return ET;
360
363 int efexEta = m_efexid%3;
364 int ieta = 0;
365 if (efexEta == 2) { // Rightmost eFEX
366 // m_central_eta has range 1-4 or 1-5
367 ieta = 8 + m_fpgaid*4 + m_central_eta - 1;
368 }
369 else if (efexEta == 1 && m_fpgaid > 1) { // central eFEX, eta > 0
370 // m_central_eta has range 1-4
371 ieta = (m_fpgaid-2)*4 + m_central_eta - 1;
372 }
373 else if (efexEta == 1) { // central eFEX, eta < 0
374 // m_central_eta had range 1-4
375 ieta = (1-m_fpgaid)*4 + (4-m_central_eta);
376 }
377 else { // Leftmost eFEX
378 // m_central_eta has range 0-4 or 1-4
379 ieta = 8 + 4*(3-m_fpgaid) + (4-m_central_eta);
380 }
381
382 static std::once_flag flag;
383 std::call_once(flag, [&]() {
384
385 if (!m_dmCorrectionsKey.empty()) {
386 // replace m_corrections values with values from database ... only try this once
387 SG::ReadCondHandle <CondAttrListCollection> dmCorrections{m_dmCorrectionsKey/*, ctx*/ };
388 if (dmCorrections.isValid()) {
389 if(dmCorrections->size()==0 && Gaudi::Hive::currentContext().eventID().time_stamp()>1672527600) { // not an error for data before 2023 (will include MC21 and MC23a)
390 ATH_MSG_ERROR("No dead material corrections found in conditions database for this event in folder " << m_dmCorrectionsKey.key());
391 throw std::runtime_error("No dead material corrections found in database for this event");
392 }
393 m_corrections = Corrections (*dmCorrections.cptr(), msg());
394 }
395 ATH_MSG_INFO("Loaded DM Corrections from database");
396 }
397 });
398
400 unsigned int factor = m_corrections.corr(layer, ieta);
401
406
407 unsigned int correction = ET;
408 for (int bit = 6; bit >= 0; bit--) {
409 correction /= 2;
410 if (factor & (1<<bit))
411 ET += correction;
412 }
414 return ET;
415 }
416
417
418 std::unique_ptr<eFEXegTOB> LVL1::eFEXegAlgo::geteFEXegTOB() {
419
420 std::unique_ptr<eFEXegTOB> out = std::make_unique<eFEXegTOB>();
421 out->setET(getET());
422
423 std::vector<unsigned int> temvector;
424 getWstot(temvector);
425 // For wstot, num and den seem switched around, but this is because the 'numerator' and 'denominator'
426 // mean different things at different points in the processing chain
427 // When the threshold comparison is done in the SetIsoWP function, we actually check Den/Num
428 out->setWstotNum(temvector[1]);
429 out->setWstotDen(temvector[0]);
430 getRhad(temvector);
431 out->setRhadEM(temvector[0]);
432 out->setRhadHad(temvector[1]);
433 getReta(temvector);
434 out->setRetaCore(temvector[0]);
435 out->setRetaEnv(temvector[1]);
436 out->setSeedUnD(m_seed_UnD);
437 out->setSeed(m_seedID);
438 return out;
439 }
440
441 void LVL1::eFEXegAlgo::getWindowET(int layer, int jPhi, int SCID, unsigned int & outET) {
442
443 //SG::ReadHandle<eTowerContainer> eTowerContainer(m_eTowerContainerKey/*,ctx*/);
444
445 if (SCID<0) { // left towers in eta
446 if ((m_efexid%3 == 0) && (m_fpgaid == 0) && (m_central_eta == 0)) {
447 outET = 0;
448 } else {
449 int etaID = 4+SCID;
450 const eTower * tmpTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[jPhi][0]);
451 if (layer==1 || layer==2) {
452 outET = tmpTower->getET(layer,etaID);
453 } else if (layer==0 || layer==3 || layer==4) {
454 outET = tmpTower->getLayerTotalET(layer);
455 }
456 }
457 } else if (SCID>=0 && SCID<4) { // central towers in eta
458 const eTower * tmpTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[jPhi][1]);
459 if (layer==1 || layer==2) {
460 outET = tmpTower->getET(layer,SCID);
461 } else if (layer==0 || layer==3 || layer==4) {
462 outET = tmpTower->getLayerTotalET(layer);
463 }
464 } else if (SCID>=4){ // right towers in eta
465 if ((m_efexid%3 == 2) && (m_fpgaid == 3) && (m_central_eta == 5)) {
466 outET = 0;
467 } else {
468 int etaID = SCID-4;
469 const eTower * tmpTower = m_eTowers->findTower(m_eFEXegAlgoTowerID[jPhi][2]);
470 if (layer==1 || layer==2) {
471 outET = tmpTower->getET(layer,etaID);
472 } else if (layer==0 || layer==3 || layer==4) {
473 outET = tmpTower->getLayerTotalET(layer);
474 }
475 }
476 }
477
478 // overflow handling
479 if (outET > 0xffff) outET = 0xffff;
480
481 }
482
483
484// Utility function to calculate and return jet discriminant sums for specified location
485// Intended to allow xAOD TOBs to be decorated with this information
486 void eFEXegAlgo::getSums(unsigned int seed, bool UnD,
487 std::vector<unsigned int> & RetaSums,
488 std::vector<unsigned int> & RhadSums,
489 std::vector<unsigned int> & WstotSums)
490 {
491 // Set seed parameters to supplied values
492 m_seed_UnD = UnD;
493 m_seedID = seed;
494 m_hasSeed = true;
495
496 // Now just call the 3 discriminant calculation methods
497 getReta(RetaSums);
498 getRhad(RhadSums);
499 getWstot(WstotSums);
500
501 }
502
503
504// Find seed and UnD flag
506
507 m_hasSeed = false;
508 m_seed_UnD = false;
509 unsigned int tmpID = 999;
510 unsigned int maxET = 0;
511
512 for (int i=0; i<4 ; ++i) {
513 int iSeedL = i-1;
514 int iSeedR = i+1;
515
516 // eta ID of candidate seed
517 unsigned int cETUp;
518 getWindowET(2,2,i,cETUp);
519 unsigned int iSeedET;
520 getWindowET(2,1,i, iSeedET);
521 unsigned int cETDown;
522 getWindowET(2,0,i, cETDown);
523
524 // left of candidate seed
525 unsigned int lETUp;
526 getWindowET(2,2,iSeedL,lETUp);
527 unsigned int lET;
528 getWindowET(2,1,iSeedL,lET);
529 unsigned int lETDown;
530 getWindowET(2,0,iSeedL,lETDown);
531
532 // right of candidate seed
533 unsigned int rETUp;
534 getWindowET(2,2,iSeedR,rETUp);
535 unsigned int rET;
536 getWindowET(2,1,iSeedR,rET);
537 unsigned int rETDown;
538 getWindowET(2,0,iSeedR,rETDown);
539
540 // greater or equal than for left and down cells, greater than for right and up ones
541 if (iSeedET>=lET && iSeedET>rET
542 && iSeedET>=lETUp && iSeedET>cETUp && iSeedET>rETUp
543 && iSeedET>=lETDown && iSeedET>=cETDown && iSeedET>rETDown) {
544 if (iSeedET>=maxET) { // if two maxima exist and have the same ET, keep the one to the right
545 maxET = iSeedET;
546 tmpID = i;
547 }
548 }
549 }
550
551 if(tmpID!=999) {
552 m_seedID = tmpID;
553 m_hasSeed = true;
554 unsigned int tmp_et_up, tmp_et_down;
555 getWindowET(2,2,m_seedID,tmp_et_up);
556 getWindowET(2,0,m_seedID,tmp_et_down);
557 if (tmp_et_up >= tmp_et_down) {
558 m_seed_UnD = true; // go up if energy greater or equal to bottom
559 }
560 }
561 }
562
563} // namespace LVL1
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
MsgStream & msg() const
This class is a collection of AttributeLists where each one is associated with a channel number.
virtual ~eFEXegAlgo()
Destructor.
virtual unsigned int getET()
virtual void getReta(std::vector< unsigned int > &)
virtual void getRealPhi(float &phi)
int m_eFEXegAlgoTowerID[3][3]
Definition eFEXegAlgo.h:70
SG::ReadHandleKey< LVL1::eTowerContainer > m_eTowerContainerKey
Definition eFEXegAlgo.h:97
Gaudi::Property< int > m_algoVersion
Definition eFEXegAlgo.h:94
virtual void setup(int inputTable[3][3], int efex_id, int fpga_id, int central_eta)
const LVL1::eTowerContainer * m_eTowers
Definition eFEXegAlgo.h:98
virtual void getRealEta(float &eta)
virtual std::unique_ptr< eFEXegTOB > geteFEXegTOB()
virtual void getSums(unsigned int seed, bool UnD, std::vector< unsigned int > &RetaSums, std::vector< unsigned int > &RhadSums, std::vector< unsigned int > &WstotSums)
virtual StatusCode initialize()
standard Athena-Algorithm method
virtual StatusCode safetyTest(const EventContext &ctx)
SG::ReadCondHandleKey< CondAttrListCollection > m_dmCorrectionsKey
Definition eFEXegAlgo.h:101
eFEXegAlgo(const std::string &type, const std::string &name, const IInterface *parent)
Constructors.
virtual unsigned int dmCorrection(unsigned int ET, unsigned int layer)
virtual void getCoreEMTowerET(unsigned int &et)
virtual void getWstot(std::vector< unsigned int > &)
unsigned int m_seedID
Definition eFEXegAlgo.h:69
virtual void getWindowET(int layer, int jPhi, int SCID, unsigned int &)
virtual void getClusterCells(std::vector< unsigned int > &cellETs)
Return cell ET values used in cluster.
Gaudi::Property< bool > m_dmCorr
Definition eFEXegAlgo.h:93
virtual void getRhad(std::vector< unsigned int > &)
virtual void getCoreHADTowerET(unsigned int &et)
The eTower class is an interface object for eFEX trigger algorithms The purposes are twofold:
Definition eTower.h:38
int getLayerTotalET(unsigned int layer) const
Get total ET sum of all cells in a given layer in MeV.
Definition eTower.cxx:249
int getET(unsigned int layer, int cell=0) const
Get ET of a specified cell in MeV.
Definition eTower.cxx:172
const_pointer_type cptr()
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
Extra patterns decribing particle interation process.