ATLAS Offline Software
Loading...
Searching...
No Matches
CPMTobAlgorithm.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 CPMTobAlgorithm.cxx - description
6 -------------------
7 begin : Thu 6 Mar 2014
8 Derived from CPAlgorithm (Run 1 version)
9 email : Alan.Watson@cern.ch
10 ***************************************************************************/
11
17#include "TrigConfData/L1Menu.h"
18
19#include <math.h>
20
21namespace LVL1 {
22using namespace TrigConf;
23
24const unsigned int CPMTobAlgorithm::m_maxClus = 0xFF;
25const double CPMTobAlgorithm::m_maxEta = 2.5;
26
27const unsigned int CPMTobAlgorithm::m_emLUT_ClusterFirstBit = 1;
28const unsigned int CPMTobAlgorithm::m_emLUT_ClusterNBits = 6;
29const unsigned int CPMTobAlgorithm::m_emLUT_EMIsolFirstBit = 0;
30const unsigned int CPMTobAlgorithm::m_emLUT_EMIsolNBits = 4;
31const unsigned int CPMTobAlgorithm::m_emLUT_HadVetoFirstBit = 0;
32const unsigned int CPMTobAlgorithm::m_emLUT_HadVetoNBits = 3;
33
35const unsigned int CPMTobAlgorithm::m_tauLUT_ClusterNBits = 7;
36const unsigned int CPMTobAlgorithm::m_tauLUT_EMIsolFirstBit = 0;
37const unsigned int CPMTobAlgorithm::m_tauLUT_EMIsolNBits = 6;
38
39const unsigned int CPMTobAlgorithm::m_noIsol = 999;
40
42 const TrigConf::L1Menu * l1menu, int slice ):
43 m_l1menu(l1menu),
44 m_Core(0),
45 m_EMClus(0),
46 m_TauClus(0),
47 m_EMIsolWord(0),
49 m_EMCore(0),
50 m_EMIsol(0),
51 m_HadCore(0),
52 m_HadIsol(0),
53 m_EtMax(false),
54 m_EMThresh(false),
55 m_TauThresh(false)
56 //m_debug(false)
57{
70
71 TriggerTowerKey get(phi-M_PI/128.,eta-0.025);
72 Coordinate refCoord = get.coord();
73 m_refEta = refCoord.eta();
74 m_refPhi = refCoord.phi();
75
76 // Set coordinate of centre of RoI, starting from reference tower coordinate
78
92
93 std::vector<unsigned int> emEt(4);
94 std::vector<unsigned int> cores(9);
95 for (int etaOffset = -1; etaOffset <= 2; etaOffset++) {
96 double tempEta = m_refEta + etaOffset*0.1;
97 for (int phiOffset = -1; phiOffset <= 2; phiOffset++) {
98 double tempPhi = m_refPhi + phiOffset*M_PI/32;
99 int key = get.ttKey(tempPhi, tempEta);
100 xAOD::CPMTowerMap_t::const_iterator tt = ttContainer->find(key);
101 if (tt != ttContainer->end() && fabs(tempEta) < m_maxEta) {
102 // Get the TT ET values once here, rather than repeat function calls
103 int emTT = 0;
104 int hadTT = 0;
105 if (slice < 0) { // Default to using peak slice
106 emTT = (tt->second)->emEnergy();
107 hadTT = (tt->second)->hadEnergy();
108 }
109 else { // Use user-specified slice
110 emTT = (tt->second)->emSliceEnergy(slice);
111 hadTT = (tt->second)->hadSliceEnergy(slice);
112 }
113 // EM Trigger Clusters and Core clusters
114 if (etaOffset >= 0 && etaOffset <= 1 && phiOffset >= 0 && phiOffset <= 1) {
115 emEt[phiOffset+2*etaOffset] = emTT;
116 m_EMCore += emTT;
117 m_HadCore += hadTT;
118 }
119 // Isolation sums
120 else {
121 m_EMIsol += emTT;
122 m_HadIsol += hadTT;
123 }
124 // Each tower is part of up to 4 RoI core clusters
125 if (etaOffset >= 0) {
126 if (phiOffset >= 0) cores[phiOffset+3*etaOffset] += emTT + hadTT;
127 if (phiOffset < 2) cores[phiOffset+3*etaOffset+1] += emTT + hadTT;
128 }
129 if (etaOffset < 2) {
130 if (phiOffset >= 0) cores[phiOffset+3*etaOffset+3] += emTT + hadTT;
131 if (phiOffset < 2) cores[phiOffset+3*etaOffset+4] += emTT + hadTT;
132 }
133
134 }
135 } // phi offset loop
136 } // eta offset loop
137
138 // Core of this window is cores[4]
139 m_Core = cores[4];
140
141 // Form most energetic 2-tower EM cluster
142 m_EMClus = ( (emEt[0] > emEt[3]) ? emEt[0] : emEt[3] )
143 + ( (emEt[1] > emEt[2]) ? emEt[1] : emEt[2] );
144
145 // Tau cluster
147
148 // Check whether RoI condition is met.
149 testEtMax(cores);
150
151 // test cluster and isolation conditions
152 emAlgorithm();
153 tauAlgorithm();
154
155}
156
159
163
164 // TriggerTowerKey::coord() returns centre of TriggerTower
165 TriggerTowerKey keyLL(phi,eta);
166 Coordinate lowerLeft = keyLL.coord();
167
168 // Get centre of tower at eta+1, phi+1, i.e. opposite corner of RoI core
169 double dEta = keyLL.dEta(lowerLeft);
170 double dPhi = keyLL.dPhi(lowerLeft);
171
172 TriggerTowerKey keyUR(phi+dPhi, eta + dEta);
173 Coordinate upperRight = keyUR.coord();
174
175 // CoordinateRange object will compute centre, correcting for wrap-around
176 CoordinateRange roi(lowerLeft.phi(),upperRight.phi(),lowerLeft.eta(),upperRight.eta());
177 m_eta = roi.eta();
178 m_phi = roi.phi();
179
180 // Range check (shouldn't be needed, but floating point precision errors possible)
181 if (m_eta > 2.5) m_eta = 2.5;
182 else if (m_eta < -2.5) m_eta = -2.5;
183}
184
186void LVL1::CPMTobAlgorithm::testEtMax(const std::vector<unsigned int>& cores) {
187
195
196 // RoI condition test
197 m_EtMax = true;
198 for (int i = 0; i < 4; i++) if (m_Core < cores[i]) m_EtMax = false;
199 for (int i = 5; i < 9; i++) if (m_Core <= cores[i]) m_EtMax = false;
200
201}
202
203
206
207 // Initialise to correct defaults, to be sure
208 m_EMThresh = false;
209 m_EMIsolWord = 0;
210
211 // Don't waste time if it isn't an RoI candidate
212 if (!m_EtMax) return;
213
214 // Does this pass min TOB pT cut?
215 // Need to worry about digit scale not being GeV
216 float emEnergyScale{1};
217 unsigned int tobPtMinEM{0};
218 emEnergyScale = m_l1menu->thrExtraInfo().EM().emScale();
219 tobPtMinEM = m_l1menu->thrExtraInfo().EM().ptMinToTopo();
220
221 unsigned int thresh = tobPtMinEM * emEnergyScale;
222
223 if (m_EMClus <= thresh) return;
224
225 // Passed, so there is a TOB here
226 m_EMThresh = true;
227
228 // Now calculate isolation word
229 // Define cluster and isolation values with appropriate scales and range for isolation LUT
230 unsigned int clusMask = ( (1<<m_emLUT_ClusterNBits)-1 )<<m_emLUT_ClusterFirstBit;
231 unsigned int emIsolMask = ( (1<<m_emLUT_EMIsolNBits) -1 )<<m_emLUT_EMIsolFirstBit;
232 unsigned int hadIsolMask = ( (1<<m_emLUT_HadVetoNBits)-1 )<<m_emLUT_HadVetoFirstBit;
233
234 // If cluster overflows, set all threshold bits
235 if (m_EMClus >= clusMask) {
236 m_EMIsolWord = 0x1F;
237 return;
238 }
239
240 // For consistency with LUT filling and menu parameters, convert ET sums to 100 MeV units
241 int clus = (( (m_EMClus < clusMask) ? (m_EMClus & clusMask) : clusMask ) * 10)/emEnergyScale;
242 int emIsol = (( (m_EMIsol < emIsolMask) ? (m_EMIsol & emIsolMask) : emIsolMask ) * 10)/emEnergyScale;
243 int hadVeto = (( (m_HadCore < hadIsolMask) ? (m_HadCore & hadIsolMask) : hadIsolMask ) * 10)/emEnergyScale;
244
249 std::vector<int> emisolcuts(5,m_noIsol);
250 std::vector<int> hadisolcuts(5,m_noIsol);
251 const std::string emIsolationStr1{"EMIsoForEMthr"};
252 for(size_t bit = 1; bit<=5; ++bit) {
253 const TrigConf::IsolationLegacy & iso = m_l1menu->thrExtraInfo().EM().isolation(emIsolationStr1, bit);
254 if(! iso.isDefined() ) {
255 continue;
256 }
257 int offset = iso.offset();
258 int slope = iso.slope();
259 int mincut = iso.mincut();
260 int upperlimit = iso.upperlimit()*10;
261 if (clus < upperlimit && bit >= 1 && bit <= 5) {
262 // As "slope" = 10* slope, rescale clus too to get fraction right.
263 int cut = offset + (slope != 0 ? 10*clus/slope : 0);
264 if (cut < mincut) cut = mincut;
265 emisolcuts[bit-1] = cut;
266 }
267 }
268 const std::string emIsolationStr2{"HAIsoForEMthr"};
269 for(size_t bit = 1; bit<=5; ++bit) {
270 const TrigConf::IsolationLegacy & iso = m_l1menu->thrExtraInfo().EM().isolation(emIsolationStr2, bit);
271 if(! iso.isDefined() ) {
272 continue;
273 }
274 int offset = iso.offset();
275 int slope = iso.slope();
276 int mincut = iso.mincut();
277 int upperlimit = iso.upperlimit()*10;
278 if (clus < upperlimit && bit >= 1 && bit <= 5) {
279 // As "slope" = 10* slope, rescale clus too to get fraction right.
280 int cut = offset + (slope != 0 ? 10*clus/slope : 0);
281 if (cut < mincut) cut = mincut;
282 hadisolcuts[bit-1] = cut;
283 }
284 }
285
286 // Set isolation bits
287 for (unsigned int isol = 0; isol < 5; ++isol) {
288 if (emIsol <= emisolcuts[isol] && hadVeto <= hadisolcuts[isol]) m_EMIsolWord += (1 << isol);
289 }
290
291}
292
293
296
297 // Initialise to correct defaults, to be sure
298 m_TauThresh = false;
299 m_TauIsolWord = 0;
300
301 // Don't waste time if it isn't an RoI candidate
302 if (!m_EtMax) return;
303
304 // Does this pass min TOB pT cut?
305 // Need to worry about digit scale not being GeV
306 float emEnergyScale{1};
307 unsigned int tobPtMinTau{0};
308 emEnergyScale = m_l1menu->thrExtraInfo().EM().emScale();
309 tobPtMinTau = m_l1menu->thrExtraInfo().TAU().ptMinToTopo();
310 unsigned int thresh = tobPtMinTau * emEnergyScale;
311
312 if (m_TauClus <= thresh) return;
313
314 // Passed, so there is a TOB here
315 m_TauThresh = true;
316
317 // Now calculate isolation word
318 // Define cluster and isolation values with appropriate scales and range for isolation LUT
319 unsigned int clusMask = ( (1<<m_tauLUT_ClusterNBits)-1 )<<m_tauLUT_ClusterFirstBit;
320 unsigned int emIsolMask = ( (1<<m_tauLUT_EMIsolNBits) -1 )<<m_tauLUT_EMIsolFirstBit;
321
322 // If cluster overflows, set all threshold bits
323 if (m_TauClus >= clusMask) {
324 m_TauIsolWord = 0x1F;
325 return;
326 }
327
328 // Convert to 100 MeV units to match parameters
329 int clus = (( (m_TauClus < clusMask) ? (m_TauClus & clusMask) : clusMask ) * 10)/emEnergyScale;
330 int emIsol = (( (m_EMIsol < emIsolMask) ? (m_EMIsol & emIsolMask) : emIsolMask ) * 10)/emEnergyScale;
331
332 // Get isolation values from menu (placeholder code - example logic)
333 std::vector<int> emisolcuts(5,m_noIsol);
334 const std::string tauIsolationStr{"EMIsoForTAUthr"};
335 for(size_t bit = 1; bit<=5; ++bit) {
336 const TrigConf::IsolationLegacy & iso = m_l1menu->thrExtraInfo().TAU().isolation(tauIsolationStr, bit);
337 if(! iso.isDefined() ) {
338 continue;
339 }
340 int offset = iso.offset();
341 int slope = iso.slope();
342 int mincut = iso.mincut();
343 int upperlimit = iso.upperlimit()*10;
344 if (clus < upperlimit && bit >= 1 && bit <= 5) {
345 // As "slope" = 10* slope, rescale clus too to get fraction right.
346 int cut = offset + (slope != 0 ? 10*clus/slope : 0);
347 if (cut < mincut) cut = mincut;
348 emisolcuts[bit-1] = cut;
349 }
350 }
351
352 // Set isolation bits
353 for (unsigned int isol = 0; isol < 5; ++isol)
354 if (emIsol <= emisolcuts[isol]) m_TauIsolWord += (1 << isol);
355
356}
357
360
361 bool passed = ( m_EMThresh && m_EtMax );
362
363 return passed;
364}
365
368
369 bool passed = ( m_TauThresh && m_EtMax );
370
371 return passed;
372}
373
374// Public accessor methods follow
375
378 return m_Core;
379}
380
385
390
395
400
405
410
415
420
423 return m_EtMax;
424}
425
428 int ET = (m_EMClus >> m_emLUT_ClusterFirstBit);
429 if (ET > (1<< m_emLUT_ClusterNBits) - 1) ET = (1<<m_emLUT_ClusterNBits) - 1;
430 return (ET << m_emLUT_ClusterFirstBit);
431}
432
436 if (ET > (1<<m_tauLUT_ClusterNBits) - 1) ET = (1<<m_tauLUT_ClusterNBits) - 1;
437 return (ET << m_tauLUT_ClusterFirstBit);
438}
439
442 int ET = (m_EMIsol >> m_emLUT_EMIsolFirstBit);
443 if (ET > (1<<m_emLUT_EMIsolNBits) - 1) ET = (1<<m_emLUT_EMIsolNBits) - 1;
444 return (ET << m_emLUT_EMIsolFirstBit);
445}
446
450 if (ET > (1<<m_emLUT_HadVetoNBits) - 1) ET = (1<<m_emLUT_HadVetoNBits) - 1;
451 return (ET << m_emLUT_HadVetoFirstBit);
452}
453
456 int ET = (m_EMIsol >> m_tauLUT_EMIsolFirstBit);
457 if (ET > (1<<m_tauLUT_EMIsolNBits) - 1) ET = (1<<m_tauLUT_EMIsolNBits) - 1;
458 return (ET << m_tauLUT_EMIsolFirstBit);
459}
460
463 return m_eta;
464}
465
468 return ( (m_phi <= M_PI) ? m_phi : m_phi - 2.*M_PI);
469}
470
473 if (isEMRoI()) {
475 return pointer;
476 }
477
478 return 0;
479
480}
481
484
485 xAOD::CPMTobRoI* pointer = 0;
486
488
489 return pointer;
490
491}
492
498
499 xAOD::CPMTobRoI* pointer = 0;
500
501 int et = 0;
502 int isol = 0;
503
505 et = EMClusET();
506 isol = EMIsolWord();
507 }
508 else if (type == TrigT1CaloDefs::tauTobType) {
509 et = TauClusET();
510 isol = TauIsolWord();
511 }
512 else return pointer;
513
514 // Need to calculate hardware coordinate
515 // Object coordinate is RoI centre, but this works better if use reference tower coord
516 float eta = m_eta - 0.05;
517 float phi = m_phi - M_PI/64;
518 if (phi < 0) phi += 2*M_PI;
520 CoordToHardware convertor;
521
522 int crate = convertor.cpCrate(coord);
523 int module = convertor.cpModule(coord);
524 int chip = convertor.cpModuleFPGA(coord);
525 int location = convertor.cpModuleLocalRoI(coord);
526
527 /*
528 float phi = ( (m_phi >= 0) ? m_phi : 2.*M_PI + m_phi );
529 int crate = 2*phi/M_PI;
530 int module = (m_eta + 2.8)/0.4 + 1;
531 int iPhi = (phi - crate*M_PI/2)*32/M_PI;
532 int chip = iPhi/2;
533 int iEta = (m_eta + 2.8 - module*0.4)/0.1;
534 int iSide = iEta/2;
535 int location = (iSide << 2) + ((iPhi&1) << 1) + (iEta&1);
536 */
537
538 pointer = new xAOD::CPMTobRoI;
539 pointer->makePrivateStore();
540 pointer->initialize(crate, module, chip, location, type, et, isol);
541
542 return pointer;
543
544}
545
546
547} // end of namespace bracket
548
549
#define M_PI
double coord
Type of coordination system.
bool passed(DecisionID id, const DecisionIDContainer &)
checks if required decision ID is in the set of IDs in the container
static const double m_maxEta
int CoreET()
Additional information for reconstruction & performance studies.
void tauAlgorithm()
Check trigger condition and set hits if appropriate.
void setRoICoord(double eta, double phi)
threshold values
int EMLUTClus()
Sums with the range & precision of isolation LUT inputs.
int HadIsolET()
Returns Had isolation ET.
static const unsigned int m_emLUT_ClusterNBits
double m_eta
Algorithm results.
int EMIsolWord()
Returns EM isolation word (5 bits).
static const unsigned int m_maxClus
Algorithm parameters.
static const unsigned int m_emLUT_HadVetoFirstBit
static const unsigned int m_emLUT_HadVetoNBits
int TauIsolWord()
Returns Tau isolation word (5 bits).
int EMClusET()
Returns EM cluster ET, limited to 8 bits.
bool isTauRoI()
Report whether this passed as a Tau TOB.
int TauLUTClus()
Returns Tau cluster ET with range and precision of LUT input.
void testEtMax(const std::vector< unsigned int > &cores)
Form all 2x2 clusters within window and test centre is a local ET maximum.
static const unsigned int m_emLUT_ClusterFirstBit
xAOD::CPMTobRoI * EMCPMTobRoI()
Create CPMTobRoIs and return pointers to them.
int EMLUTEMIsol()
Returns EM isolation ET with range and precision of EM LUT input.
CPMTobAlgorithm(double eta, double phi, const xAOD::CPMTowerMap_t *ttContainer, const TrigConf::L1Menu *l1menu, int slice=-1)
double eta()
Accessors for TOB data.
static const unsigned int m_tauLUT_EMIsolNBits
static const unsigned int m_emLUT_EMIsolFirstBit
const TrigConf::L1Menu * m_l1menu
static const unsigned int m_tauLUT_ClusterFirstBit
int TauClusET()
Returns Tau cluster ET, limited to 8 bits.
xAOD::CPMTobRoI * createTobRoI(int type)
Create a pointer to a CPMTobRoI and return it.
xAOD::CPMTobRoI * TauCPMTobRoI()
Returns CPMTobRoI for TAU hypothesis, provided TAU Tob conditions passed.
int HadCoreET()
Returns Had core ET (inner isolation sum).
static const unsigned int m_tauLUT_EMIsolFirstBit
int TauLUTEMIsol()
Returns EM isolation ET with range and precision of Tau LUT input.
static const unsigned int m_tauLUT_ClusterNBits
static const unsigned int m_emLUT_EMIsolNBits
int EMCoreET()
Returns EM core ET.
static const unsigned int m_noIsol
void emAlgorithm()
Check trigger condition and set hits if appropriate.
bool isEtMax()
Does this window pass the local ET maximum condition.
double phi()
Returns phi coordinate of RoI, using standard ATLAS convention.
int EMLUTHadVeto()
Returns Had veto ET with range and precision of EM LUT input.
int EMIsolET()
Returns EM isolation ET.
bool isEMRoI()
Report whether this passed as an EM TOB.
returns the trigger hardware components associated with a given Coordinate
unsigned int cpModuleFPGA(const Coordinate &coord)
returns ID [0-7] of the CP FPGA.
unsigned int cpModule(const Coordinate &coord)
return ID of CP module.
unsigned int cpModuleLocalRoI(const Coordinate &coord)
returns local RoI coordinate within FPGA
unsigned int cpCrate(const Coordinate &coord)
returns crate ID covering that coord.
CoordinateRange class declaration.
double phi() const
return phi
double eta() const
return eta
Coordinate coord() const
return central coords of current key value.
The TriggerTowerKey object provides the key for each trigger tower depending on its eta-phi coords.
double dPhi(const Coordinate &coord) const
returns phi height of trigger tower at coordinate coord
double dEta(const Coordinate &coord) const
returns eta width of trigger tower at coordinate coord
L1 menu configuration.
Definition L1Menu.h:29
virtual void initialize(int crate, int cpm, int chip, int location, int type, int energy, int isol)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
CPMTobRoI_v1 CPMTobRoI
Define the latest version of the CPMTobRoI class.
std::map< int, const CPMTower * > CPMTowerMap_t
Extra patterns decribing particle interation process.