ATLAS Offline Software
Loading...
Searching...
No Matches
L1TriggerTowerToolRun3.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
5// L1TriggerTowerToolRun3.cxx
8#include "GaudiKernel/Incident.h"
9#include "GaudiKernel/IIncidentSvc.h"
10#include "GaudiKernel/GaudiException.h"
11
15
21
23#include "GaudiKernel/ThreadLocalContext.h"
24
25#include <cstdint>
26#include <tuple>
27#include <ranges>
28
29namespace LVL1
30{
31
32//================ Static Constants ============================================
33
36
37//================ Constructor =================================================
38
40 const std::string& n,
41 const IInterface* p )
42 :
43 AthAlgTool(t,n,p),
44 m_caloMgr(0),
45 m_lvl1Helper(0),
46 m_l1CaloTTIdTools("LVL1::L1CaloTTIdTools/L1CaloTTIdTools", this),
47 m_ttSvc("CaloTriggerTowerService/CaloTriggerTowerService", this),
48 m_mappingTool("", this),
49 m_correctFir(false),
51{
52 declareInterface<IL1TriggerTowerToolRun3>(this);
53
54 declareProperty( "BaselineCorrection", m_correctFir );
55 declareProperty( "L1DynamicPedestalProvider", m_dynamicPedestalProvider );
56}
57
58//================ Destructor =================================================
59
61
62//================ Initialisation =================================================
63
65{
66
67 // Reading the Condition Containers Run 3 style
68 ATH_CHECK( m_runParametersContainer.initialize() );
72
73 ATH_CHECK(m_l1CaloTTIdTools.retrieve());
74
75 if(!m_ttSvc.retrieve().isSuccess()) {
76 ATH_MSG_WARNING( "Could not retrieve CaloTriggerTowerService Tool" );
77 } else {
78 ATH_MSG_INFO("Retrieved Tool " << m_ttSvc);
79 }
80
81 StatusCode scID = detStore()->retrieve(m_caloMgr);
82 if (scID.isFailure()) {
83 ATH_MSG_WARNING( "Cannot retrieve m_caloMgr" );
84 } else {
85 m_lvl1Helper = m_caloMgr->getLVL1_ID();
86 }
87
88 if (!m_mappingTool.empty()) {
89 ATH_CHECK( m_mappingTool.retrieve() );
90 }
91
92 // Incident Service:
93 SmartIF<IIncidentSvc> incSvc{service("IncidentSvc")};
94 ATH_CHECK( incSvc.isValid() );
95 incSvc->addListener(this, "BeginRun");
96
97 // Pedestal Correction
98 if (m_correctFir) {
100 ATH_MSG_INFO( "Retrieved L1DynamicPedestalProvider: " << m_dynamicPedestalProvider );
101 }
102
103 ATH_CHECK( m_eventInfoKey.initialize() );
104
105 ATH_CHECK( m_L1MenuKey.initialize() );
106
107
108
109
110 ATH_MSG_INFO( "Initialization completed" );
111
112 return StatusCode::SUCCESS;
113}
114
115//================ Finalisation =================================================
116
118{
119 return StatusCode::SUCCESS;
120}
121
122//================ Reset mapping table at start of run ============================
123
124void L1TriggerTowerToolRun3::handle(const Incident& inc)
125{
126 if (inc.type()=="BeginRun") {
127 ATH_MSG_DEBUG( "Resetting mapping table at start of run" );
128
129 m_idTable.clear();
130 }
131}
132
133
134
137void L1TriggerTowerToolRun3::process(const std::vector<int> &digits, double eta, double phi, int layer,
138 std::vector<int> &et, std::vector<int> &bcidResults,
139 std::vector<int> &bcidDecisions, bool useJepLut /* = true */)
140{
142 L1CaloCoolChannelId id = channelID(eta, phi, layer);
143
145 process(digits, id, et, bcidResults, bcidDecisions, useJepLut);
146}
147
148
151void L1TriggerTowerToolRun3::process(const std::vector<int> &digits, const L1CaloCoolChannelId& channelId,
152 std::vector<int> &et, std::vector<int> &bcidResults,
153 std::vector<int> &bcidDecisions, bool useJepLut /* = true */)
154{
155
156 ATH_MSG_DEBUG( "::process: ==== Entered Process ====" );
157 ATH_MSG_DEBUG( "::process: digits: " << digits);
158 ATH_MSG_DEBUG( " channelID: " << MSG::hex << channelId.id() << MSG::dec );
159
160
162 et.clear();
163 bcidResults.clear();
164 bcidDecisions.clear();
165
166 ATH_MSG_DEBUG( "::process: ---- FIR filter ----" );
167
169 std::vector<int> filter;
170 fir(digits, channelId, filter);
171 std::vector<int> lutInput;
172 dropBits(filter, channelId, lutInput);
173
174 ATH_MSG_DEBUG( "::process: ---- BCID algorithms ----" );
175
177 bcid(filter, digits, channelId, bcidResults);
178
179 ATH_MSG_DEBUG( "::process: ---- BCID decisions ----" );
180
182 std::vector<int> decisionRange;
183 bcidDecisionRange(lutInput, digits, channelId, decisionRange);
184 bcidDecision(bcidResults, decisionRange, bcidDecisions);
185
186 ATH_MSG_DEBUG( "::process: ---- LUT ET calculation ----" );
187
189 std::vector<int> lutOutput;
190 if(useJepLut) jepLut(lutInput, channelId, lutOutput);
191 else cpLut(lutInput, channelId, lutOutput);
192
193
194 ATH_MSG_DEBUG( "::process: ---- use ET range ----" );
195
198 applyEtRange(lutOutput, decisionRange, channelId, et);
199
200 ATH_MSG_DEBUG( "::process: ==== Leaving Process ====" );
201}
202
203namespace {
204// helper function to convert vectors of different type
205template <typename DST, typename SRC>
206std::vector<DST> convertVectorType(const std::vector<SRC>& s) {
207 std::vector<DST> d(s.size());
208 std::transform(std::begin(s), std::end(s), std::begin(d),
209 [](SRC v){return static_cast<DST>(v);});
210 return d;
211}
212}
213
215void L1TriggerTowerToolRun3::simulateChannel(const xAOD::TriggerTower& tt, std::vector<int>& outCpLut, std::vector<int>& outJepLut, std::vector<int>& bcidResults, std::vector<int>& bcidDecisions) const {
216
217 //If we have 80 MHz readout, we need to extract the 40 MHz samples. The central 80 MHz sample is always a 40 MHz sample. We use the cool database (runParameters folder) to understand if we are in 80MHz readout
218
220 unsigned int readoutConfigID = runParameters->runParameters(1)->readoutConfigID();
221 ATH_MSG_DEBUG("RunParameters:: readoutConfigID " << readoutConfigID);
222
223 std::vector<uint16_t> digits40;
224
225 if(readoutConfigID == 5 or readoutConfigID == 6){
226
227
228 ATH_MSG_DEBUG("::simulateChannel: 80 MHz readout detected, emulating 40 MHz samples");
229
230 int nSlices = tt.adc().size();
231
232 if((nSlices%4)==3){
233 for (int i=0 ; i < (nSlices-1)/2 ; i++ ){
234 digits40.push_back(tt.adc().at(2*i+1));
235 }
236 }
237 else if((nSlices%4)==1){
238 for (int i=0 ; i <= (nSlices-1)/2 ; i++){
239 digits40.push_back(tt.adc().at(2*i));
240 }
241 }
242
243
244 }else{
245 ATH_MSG_DEBUG("::simulateChannel: 40 MHz readout detected");
246 digits40 = tt.adc();
247 }
248
249 const auto& digits = convertVectorType<int>(digits40);
250
251 L1CaloCoolChannelId channelId {tt.coolId()};
252
253 ATH_MSG_DEBUG( "::simulateChannel: ==== Entered Process ====" );
254 ATH_MSG_DEBUG( "::simulateChannel: digits: " << digits );
255 ATH_MSG_DEBUG( "::simulateChannel: channelID: " << MSG::hex << channelId.id() << MSG::dec );
256
257
259 outCpLut.clear();
260 outJepLut.clear();
261 bcidResults.clear();
262 bcidDecisions.clear();
263
265 ATH_MSG_DEBUG( "::simulateChannel: ---- FIR filter ----" );
266 std::vector<int> filter;
267 fir(digits, channelId, filter);
268
269
271 ATH_MSG_DEBUG( "::simulateChannel: ---- pedestalCorrection ----" );
272 // the correction is only available for each LUT slice in the read-out (not ADC/Filter slice)
273 // therefore we can only apply it to the #LUT central filter slices
274 const std::size_t nCorr = tt.correctionEnabled().size();
275 const std::size_t filterOffset = filter.size()/2 - nCorr/2;
276 for(std::size_t iCorr = 0; iCorr < nCorr; ++iCorr) {
277 filter[filterOffset + iCorr] -= tt.correction()[iCorr] * tt.correctionEnabled()[iCorr];
278 }
279
280 ATH_MSG_DEBUG("::simulateChannel: filter: " << filter);
281
282
283 std::vector<int> lutInput;
284 dropBits(filter, channelId, lutInput);
285
286 ATH_MSG_DEBUG( "::simulateChannel: ---- BCID algorithms ---- ");
287
289 bcid(filter, digits, channelId, bcidResults);
290
291
293 std::vector<int> decisionRange;
294 bcidDecisionRange(lutInput, digits, channelId, decisionRange);
295 bcidDecision(bcidResults, decisionRange, bcidDecisions);
296
297 ATH_MSG_DEBUG( "::simulateChannel: bcidDecisionRange " << decisionRange);
298 ATH_MSG_DEBUG( "::simulateChannel: bcidDecisions " << bcidDecisions);
299
300
301
302 ATH_MSG_DEBUG( "::simulateChannel: ---- LUT ET calculation ----" );
303
305 std::vector<int> cpLutOutput, jepLutOutput;
306 cpLut(lutInput, channelId, cpLutOutput);
307 jepLut(lutInput, channelId, jepLutOutput);
308
309 ATH_MSG_DEBUG( "::simulateChannel: cpLut " << cpLutOutput);
310 ATH_MSG_DEBUG( "::simulateChannel: jepLut " << jepLutOutput);
311
312 ATH_MSG_DEBUG( "::simulateChannel: ---- use ET range ----" );
313
316 applyEtRange(cpLutOutput, decisionRange, channelId, outCpLut);
317 applyEtRange(jepLutOutput, decisionRange, channelId, outJepLut);
318
319 ATH_MSG_DEBUG( "::simulateChannel: cpLut applyETRange " << outCpLut);
320 ATH_MSG_DEBUG( "::simulateChannel: jepLut applyETRange " << outJepLut);
321
322
323 ATH_MSG_DEBUG( "::simulateChannel: ==== Leaving Process ====" );
324}
325
328
329void L1TriggerTowerToolRun3::bcid(const std::vector<int> &filter, const std::vector<int> &digits, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
330{
331 // Get decision flags for the 2 BCID algorithms
332 std::vector<int> peak;
333 peakBcid(filter, channelId, peak);
334 std::vector<int> sat;
335 satBcid(digits, channelId, sat);
336
337 output.clear();
338 output.reserve(sat.size()); // avoid frequent reallocations
339
340 std::vector<int>::iterator itpeak = peak.begin();
341 std::vector<int>::iterator itsat = sat.begin();
342 for ( ; itpeak!=peak.end() && itsat!=sat.end(); ++itpeak, ++itsat ) {
343 output.push_back( (*itpeak<<2) + (*itsat<<1) );
344 }
345
346 ATH_MSG_DEBUG( "::bcid: bcidResults: " << output);
347
348}
349
352
353void L1TriggerTowerToolRun3::bcid(const std::vector<int> &filter, const std::vector<int> &digits,
354 unsigned int strategy, int satLow, int satHigh, int satLevel, std::vector<int> &output) const
355{
356 // Get decision flags for the 2 BCID algorithms
357 std::vector<int> peak;
358 peakBcid(filter, strategy, peak);
359 std::vector<int> sat;
360 satBcid(digits, satLow, satHigh, satLevel, sat);
361
362 output.clear();
363 output.reserve(sat.size()); // avoid frequent reallocations
364
365 std::vector<int>::iterator itpeak = peak.begin();
366 std::vector<int>::iterator itsat = sat.begin();
367 for ( ; itpeak!=peak.end() && itsat!=sat.end(); ++itpeak, ++itsat ) {
368 output.push_back( (*itpeak<<2) + (*itsat<<1) );
369 }
370
371 ATH_MSG_DEBUG( "::bcid: bcidResults: " << output);
372}
373
376
377void L1TriggerTowerToolRun3::bcid(const std::vector<int> &filter, const std::vector<int> &lutInput, const std::vector<int> &digits, int energyLow, int energyHigh, int decisionSource, std::vector<unsigned int> &decisionConditions,
378 unsigned int strategy, int satLow, int satHigh, int satLevel, std::vector<int> &result, std::vector<int> &decision) const
379{
380 // Get decision flags for the 2 BCID algorithms
381 std::vector<int> peak;
382 peakBcid(filter, strategy, peak);
383 std::vector<int> sat;
384 satBcid(digits, satLow, satHigh, satLevel, sat);
385
386 result.clear();
387 result.reserve(sat.size()); // avoid frequent reallocations
388 decision.clear();
389
390 std::vector<int>::iterator itpeak = peak.begin();
391 std::vector<int>::iterator itsat = sat.begin();
392 for ( ; itpeak!=peak.end() && itsat!=sat.end(); ++itpeak, ++itsat ) {
393 result.push_back( (*itpeak<<2) + (*itsat<<1) );
394 }
395
396 ATH_MSG_DEBUG( "::bcid: bcidResults: " << result);
397
398
399
401 std::vector<int> decisionRange;
402 if (!(decisionSource&0x1)) etRange(digits, energyLow, energyHigh, decisionRange);
403 else etRange(lutInput, energyLow, energyHigh, decisionRange);
404 bcidDecision(result, decisionRange, decisionConditions, decision);
405 ATH_MSG_DEBUG( "::bcid: bcidDecisions: " << decision);
406
407}
408
409namespace { // helper function
410 template<class T>
411 const std::vector<short int>* getFirCoefficients(unsigned int coolId, SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
412 auto settings = pprConditionsRun2->pprConditions(coolId);
413 if(!settings) return nullptr;
414 return &(settings->firCoefficients());
415 }
416} // anonymous namespace
417
421void L1TriggerTowerToolRun3::fir(const std::vector<int> &digits, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
422{
423
425
427 std::vector<int> firCoeffs;
428 if(!m_pprConditionsContainerRun2.empty()) {
429 const std::vector<short int>* hwCoeffs;
430 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
431 if(hwCoeffs) {
435 firCoeffs.reserve(hwCoeffs->size()); // avoid frequent reallocations
436 for (auto &i : std::views::reverse(*hwCoeffs)) {
437 firCoeffs.push_back(i);
438 }
439 } else ATH_MSG_WARNING( "::fir: No L1CaloPprConditions found" );
440 } else ATH_MSG_WARNING( "::fir: No Conditions Container retrieved" );
441
442 ATH_MSG_DEBUG( "::fir: FIR coefficients: " << firCoeffs);
443
444
445 fir(digits, firCoeffs, output);
446}
447
452void L1TriggerTowerToolRun3::fir(const std::vector<int> &digits, const std::vector<int> &firCoeffs, std::vector<int> &output) const
453{
454 output.clear();
455 output.reserve(digits.size()); // avoid frequent reallocations
458 int firstFIR = -1;
459 int lastFIR = 0;
460 for (unsigned int i = 0; i < firCoeffs.size(); ++i) {
461 if (firstFIR < 0 && firCoeffs[i] != 0) firstFIR = i;
462 if (firCoeffs[i] != 0) lastFIR = i;
463 }
464 if (firstFIR < 0) firstFIR = lastFIR + 1;
465
466 for (int i = 0; i < (int)digits.size(); i++) {
467 int sum = 0;
469 if (i >= 2-firstFIR && i < (int)digits.size()+2-lastFIR) {
470 for (int j = firstFIR; j <= lastFIR; ++j) {
471 sum += digits[i+j-2]*firCoeffs[j];
472 }
473 }
474 if (sum < 0) sum = 0;
475 output.push_back(sum);
476 }
477
478 ATH_MSG_DEBUG( "::fir: output: " << output);
479
480}
481
482namespace {
483 template<typename T>
484 unsigned int getStrategy( SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
485 return pprConditionsRun2->peakFinderCond();
486 }
487}
488
490void L1TriggerTowerToolRun3::peakBcid(const std::vector<int> &fir, const L1CaloCoolChannelId& /*channelId*/, std::vector<int> &output) const
491{
492 unsigned int strategy = 0;
494
495
496 if(!m_pprConditionsContainerRun2.empty()) {
497 strategy = getStrategy<L1CaloPprConditionsContainerRun2>( pprConditionsRun2);
498 } else ATH_MSG_WARNING( "::peakBcid: No Conditions Container retrieved" );
499
500 ATH_MSG_DEBUG( "::peakBcid: peak-finder strategy: " << strategy );
501
502 peakBcid(fir, strategy, output);
503}
504
506void L1TriggerTowerToolRun3::peakBcid(const std::vector<int> &fir, unsigned int strategy, std::vector<int> &output) const
507{
508 output.clear();
509 output.reserve(fir.size()); // avoid frequent reallocations
510
511 for (unsigned int i = 0; i < fir.size(); i++) {
512 int result = 0;
514 if (i > 0 && i < fir.size()-1) {
516 if (strategy&0x1) {
517 if ( (fir[i-1]<fir[i]) && (fir[i+1]<fir[i]) ) result = 1;
518 } else {
519 if ( (fir[i-1]<fir[i]) && (fir[i+1]<=fir[i]) ) result = 1;
520 }
521 }
522 output.push_back(result);
523 }
524
525 ATH_MSG_DEBUG( "::peakBcid: output: " << output);
526
527
528}
529
530namespace { // helper function
531 template<class T>
532 std::tuple<bool, int, int, int> getSaturation(unsigned int coolId, SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
533 auto settings = pprConditionsRun2->pprConditions(coolId);
534 if(!settings) return std::make_tuple(false, 0, 0, 0);
535 return std::make_tuple(true, settings->satBcidLevel(), settings->satBcidThreshLow(),
536 settings->satBcidThreshHigh());
537 }
538} // anonymous namespace
539
541void L1TriggerTowerToolRun3::satBcid(const std::vector<int> &digits, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
542{
543 int satLevel = 0;
544 int satLow = 0;
545 int satHigh = 0;
547
548 if (!m_pprConditionsContainerRun2.empty()) {
549 bool available = false;
550 std::tie(available, satLevel, satLow, satHigh) = getSaturation<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
551 if(!available) ATH_MSG_WARNING( "::satBcid: No L1CaloPprConditions found" );
552 } else ATH_MSG_WARNING( "::satBcid: No Conditions Container retrieved" );
553
554 ATH_MSG_DEBUG( "::satBcid: satLevel: " << satLevel
555 << " satLow: " << satLow
556 << " satHigh: " << satHigh );
557
558 satBcid(digits, satLow, satHigh, satLevel, output);
559}
560
562
563void L1TriggerTowerToolRun3::satBcid(const std::vector<int> &digits, int satLow, int satHigh, int satLevel, std::vector<int> &output) const
564{
565 output.clear();
566 output.reserve(digits.size()); // avoid frequent reallocations
567
568 bool enabled = true;
569 int flag[2] = {0,0};
570
571 for (unsigned int i = 0; i<digits.size(); i++) {
572 // Algorithm can set flag for following sample. So here we
573 // propagate such flags into the current sample.
574 flag[0] = flag[1];
575 flag[1] = 0;
576
577 if (digits[i]>=satLevel) { // do we have saturation?
578 if (enabled && i>1) { // is algorithm active?
579 bool low = (digits[i-2]>satLow);
580 bool high = (digits[i-1]>satHigh);
581 if (high) { // flag current or next sample?
582 if (low) {
583 flag[0] = 1;
584 }
585 else {
586 flag[1] = 1;
587 }
588 }
589 else {
590 flag[1] = 1;
591 }
592 }
593 enabled = false; // after first saturation, disable algorithm
594 }
595 else {
596 enabled = true; // unsaturated sample reenables algorithm
597 }
598 output.push_back(flag[0]);
599 }
600
601 ATH_MSG_DEBUG( "::satBcid: output: " << output);
602
603}
604
606namespace {
607 template<typename T>
608 unsigned int getDecisionSource( SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
609 return pprConditionsRun2->decisionSource();
610 }
611}
612
613void L1TriggerTowerToolRun3::bcidDecisionRange(const std::vector<int>& lutInput, const std::vector<int>& digits, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
614{
615 int decisionSource = 0;
617
618 if (!m_pprConditionsContainerRun2.empty()) {
619 decisionSource = getDecisionSource<L1CaloPprConditionsContainerRun2>(pprConditionsRun2);
620
621 } else ATH_MSG_WARNING( "::bcidDecisionRange: No Conditions Container retrieved" );
622
623 if (!(decisionSource&0x1)) etRange(digits, channelId, output);
624 else etRange(lutInput, channelId, output);
625
626 ATH_MSG_DEBUG( "::bcidDecisionRange: decisionSource: " << decisionSource);
627 ATH_MSG_DEBUG( "::bcidDecisionRange: output: " << output);
628
629
630}
631
633namespace { // helper function
634 template<class T>
635 std::tuple<unsigned int, unsigned int, unsigned int> getBcidDecision( SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
636 return std::make_tuple(pprConditionsRun2->bcidDecision1(), pprConditionsRun2->bcidDecision2(), pprConditionsRun2->bcidDecision3());
637 }
638} // anonymous namespace
639void L1TriggerTowerToolRun3::bcidDecision(const std::vector<int> &bcidResults, const std::vector<int> &range , std::vector<int> &output) const
640{
641 unsigned int decision1 = 0;
642 unsigned int decision2 = 0;
643 unsigned int decision3 = 0;
645
646 if(!m_pprConditionsContainerRun2.empty()) {
647 std::tie(decision1, decision2, decision3) = getBcidDecision<L1CaloPprConditionsContainerRun2>(pprConditionsRun2);
648 } else ATH_MSG_WARNING( "::bcidDecision: No Conditions Container retrieved" );
649
650 // Reverse the order! (see elog 97082 9/06/10)
651 std::vector<unsigned int> mask = { decision3, decision2, decision1 };
652
653 ATH_MSG_DEBUG( "::bcidDecision: masks: " << MSG::hex
654 << decision3 << " " << decision2 << " " << decision1 << MSG::dec );
655
656 bcidDecision(bcidResults, range, mask, output);
657}
658
660
661void L1TriggerTowerToolRun3::bcidDecision(const std::vector<int> &bcidResults, const std::vector<int> &range, const std::vector<unsigned int> &mask, std::vector<int> &output) const
662{
663 output.clear();
664 output.reserve(bcidResults.size()); // avoid frequent reallocations
665
666 std::vector<int>::const_iterator itBcid = bcidResults.begin();
667 std::vector<int>::const_iterator itRange = range.begin();
668 int nRange = mask.size();
669
670 for ( ; itBcid != bcidResults.end() && itRange != range.end(); ++itBcid, ++itRange) {
671 if ((*itRange) < nRange && (mask[*itRange]&(0x1<<*itBcid))) output.push_back(1);
672 else output.push_back(0);
673 }
674
675 ATH_MSG_DEBUG( "::bcidDecision: output: " << output);
676
677
678}
679
680// TODO implement scale
681void L1TriggerTowerToolRun3::cpLut(const std::vector<int> &fir, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
682{
683 int startBit = 0;
684 int strategy = 0;
685 int offset = 0;
686 int slope = 0;
687 int cut = 0;
688 unsigned short scale_menu = 0;
689 double pedMean = 0;
690 int hwCoeffSum = 0;
691 const std::vector<short int>* hwCoeffs;
692
693
695 const EventContext& ctx = Gaudi::Hive::currentContext();
696
697 if(!m_pprConditionsContainerRun2.empty()) {
698 auto settings = pprConditionsRun2->pprConditions(channelId.id());
699 if (settings) {
700 startBit = settings->firStartBit();
701 strategy = settings->lutCpStrategy();
702 slope = settings->lutCpSlope();
703 cut = settings->lutCpNoiseCut();
704 pedMean = settings->pedMean();
705
706 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
707
708 auto l1Menu = getL1Menu(ctx);
709 scale_menu = l1Menu->thrExtraInfo().EM().emScale(); // Retrieve scale param from menu
710
711 for( auto &coeffs : *hwCoeffs) {
712 hwCoeffSum += coeffs;
713 }
714
715 offset = this->getLutOffset(pedMean, startBit, *hwCoeffs, slope, strategy);
716
717 } else ATH_MSG_WARNING( "::cpLut: No L1CaloPprConditions found" );
718 } else ATH_MSG_WARNING( "::cpLut: No Conditions Container retrieved" );
719
720 ATH_MSG_DEBUG( "::cpLut: strategy/scale/offset/slope/cut/pedMean/firCoeffSum/startBit: "
721 << strategy << "/" << scale_menu << "/" << offset << "/" << slope << "/" << cut << "/" << pedMean << "/" << hwCoeffSum << "/" << startBit );
722
723 unsigned int noiseCut = 0;
724 bool disabled = disabledChannel(channelId, noiseCut);
725 if (noiseCut > 0) cut = noiseCut;
726 if(strategy == 2) {
727 // take the global scale into account - translate strategy to 1 for Run-1 compatible treatment
728 lut(fir, scale_menu*slope, scale_menu*offset, scale_menu*cut, 1, disabled, output);
729 } else if(strategy == 1 || strategy == 0){
730 lut(fir, slope, offset, cut, strategy, disabled, output);
731 } else if (strategy == 4) {
732 // Run-3 FCAL LUT filling scheme (strategy 4) which is identical to
733 // Run-2 strategy 2, but contains an additional fixed factor of 2.
734 lut(fir, scale_menu*slope, scale_menu*offset, scale_menu*cut, 4, disabled, output);
735
736 }
737
738 else {
739 ATH_MSG_WARNING(" ::cpLut: Unknown stragegy: " << strategy);
740 output.push_back(0); //avoid crashing with Unknown stragegy
741 }
742}
743
744void L1TriggerTowerToolRun3::jepLut(const std::vector<int> &fir, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
745{
746 int startBit = 0;
747 int strategy = 0;
748 int offset = 0;
749 int slope = 0;
750 int cut = 0;
751 unsigned short scale_db = 0;
752 unsigned short scale_menu = 0;
753 double pedMean = 0;
754 int hwCoeffSum = 0;
755 const std::vector<short int>* hwCoeffs;
756 short par1 = 0;
757 short par2 = 0;
758 short par3 = 0;
759 short par4 = 0;
760
761 if(!isRun2()) {
762 // assert instead ?!
763 ATH_MSG_WARNING("::jepLut: Run-1 data - behaviour undefined!");
764 }
765
766
768 const EventContext& ctx = Gaudi::Hive::currentContext();
769
770 if(! m_pprConditionsContainerRun2.empty()) {
771 const auto settings = pprConditionsRun2->pprConditions(channelId.id());
772 if (settings) {
773 startBit = settings->firStartBit();
774 strategy = settings->lutJepStrategy();
775 slope = settings->lutJepSlope();
776 cut = settings->lutJepNoiseCut();
777 pedMean = settings->pedMean();
778 scale_db = settings->lutJepScale();
779
780 auto l1Menu = getL1Menu(ctx);
781 scale_menu = l1Menu->thrExtraInfo().JET().jetScale(); // Retrieve scale param from menu
782
783 if (strategy == 3) {
784 par1 = settings->lutJepPar1();
785 par2 = settings->lutJepPar2();
786 par3 = settings->lutJepPar3();
787 par4 = settings->lutJepPar4();
788 }
789
790 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
791
792 for( auto &coeffs : *hwCoeffs) {
793 hwCoeffSum += coeffs;
794 }
795
796 offset = this->getLutOffset(pedMean, startBit, *hwCoeffs, slope, strategy);
797
798 } else ATH_MSG_WARNING( "::jepLut: No L1CaloPprConditions found" );
799 } else ATH_MSG_WARNING( "::jepLut: No Conditions Container retrieved" );
800
801 ATH_MSG_DEBUG( "::jepLut: strategy/scale/offset/slope/cut/pedMean/firCoeffSum/startBit: "
802 << strategy << "/" << scale_menu << "/" << offset << "/" << slope << "/" << cut << "/" << pedMean << "/" << hwCoeffSum << "/" << startBit );
803
804 unsigned int noiseCut = 0;
805 bool disabled = disabledChannel(channelId, noiseCut);
806 if (noiseCut > 0) cut = noiseCut;
807
808 if(strategy == 3) {
809 nonLinearLut(fir, slope, offset, cut, scale_db, par1, par2, par3, par4, disabled, output);
810 }
811 else if(strategy == 2) {
812 // take the global scale into account - translate strategy to 1 for Run-1 compatible treatment
813 lut(fir, scale_menu*slope, scale_menu*offset, scale_menu*cut, 1, disabled, output);
814
815 }else if(strategy == 1 || strategy == 0) {
816 lut(fir, slope, offset, cut, strategy, disabled, output);
817 }
818 else if (strategy == 4) {
819 // Run-3 FCAL LUT filling scheme (strategy 4) which is identical to
820 // Run-2 strategy 2, but contains an additional fixed factor of 2.
821 lut(fir, scale_menu*slope, scale_menu*offset, scale_menu*cut, 4, disabled, output);
822
823 }
824
825 else {
826 ATH_MSG_WARNING(" ::jepLut: Unknown stragegy: " << strategy);
827 output.push_back(0);//avoid crashing with Unknown stragegy
828 }
829
830
831}
832
834void L1TriggerTowerToolRun3::lut(const std::vector<int> &fir, int slope, int offset, int cut, int strategy, bool disabled, std::vector<int> &output) const
835{
836 output.clear();
837 output.reserve(fir.size()); // avoid frequent reallocations
838
839 const int reScale = 2;
840 for( auto it : fir) {
841 int out = 0;
842 if (!disabled) {
843 if (strategy == 0 && it >= offset+cut) { // Original scheme
844 out = ((it-offset)*slope + 2048)>>12;
845 }
846 else if (strategy == 1 && it*slope >= offset+cut) { // New scheme
847 out = (it*slope - offset + 2048)>>12;
848 }
849 // Note: for strategy 2, the code is called with strategy=1
850 else if (strategy == 4 && it*slope >= offset+ cut/reScale) { // FCAL
851 out = (it*slope*reScale - offset*reScale + 2048)>>12;
852 }
853 if (out < 0) out = 0;
854 if (out > s_saturationValue) out = s_saturationValue;
855 }
856 output.push_back(out);
857 }
858
859 ATH_MSG_DEBUG( "::lut: output: " << output);
860
861}
862
863void L1TriggerTowerToolRun3::nonLinearLut(const std::vector<int> &fir, int slope, int offset, int cut, int scale, short par1, short par2, short par3, short par4, bool disabled, std::vector<int> &output) const
864{
865 output.clear();
866 output.reserve(fir.size()); // avoid frequent reallocations
867
868
869 for( auto it : fir) {
870 int out = 0;
871 if (!disabled) {
872 // turn shorts into double
873 double nll_slope = 0.001 * scale;
874 double nll_offset = 0.001 * par1;
875 double nll_ampl = 0.001 * par2;
876 double nll_expo = 0.;
877 if(par3) {
878 nll_expo = -1. / (4096 * 0.001*par3);
879 } else {
880 nll_ampl = 0.;
881 }
882 double nll_noise = 0.001 * par4;
883
884 // noise cut
885 if (it * slope < offset + nll_noise * cut) {
886 output.push_back(0);
887 continue;
888 }
889 // actual calculation
890 out = int((((int)(2048 + nll_slope * (it * slope - offset)))>>12) + nll_offset + nll_ampl * std::exp(nll_expo * (it * slope - offset)));
891
892 if(out > s_saturationValue) out = s_saturationValue;
893 if(out < 0) out = 0;
894 }
895 output.push_back(out);
896 }
897 ATH_MSG_DEBUG( "::nonLinearLut: output: " << output);
898
899}
900
902
903void L1TriggerTowerToolRun3::applyEtRange(const std::vector<int>& lut, const std::vector<int>& range, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
904{
905 bool disabled = disabledChannel(channelId);
906 std::vector<int>::const_iterator itlut = lut.begin();
907 std::vector<int>::const_iterator itrange = range.begin();
908 while ( itlut != lut.end() && itrange != range.end() ) {
909 if (!disabled && satOverride((*itrange))) output.push_back(s_saturationValue);
910 else output.push_back(*itlut);
911 ++itlut;
912 ++itrange;
913 }
914
915 ATH_MSG_DEBUG( "::applyEtRange: output: " << output);
916
917}
918
920namespace { // helper function
921 template<class T>
922 std::tuple<bool, int, int> getBcidEnergyRange(unsigned int coolId, SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
923 auto settings = pprConditionsRun2->pprConditions(coolId);
924 if(!settings) return std::make_tuple(false, 0, 0);
925 return std::make_tuple(true, settings->bcidEnergyRangeLow(), settings->bcidEnergyRangeHigh());
926 }
927}
928
929// anonymous namespace
930
931void L1TriggerTowerToolRun3::etRange(const std::vector<int> &et, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
932{
933 int energyLow = 0;
934 int energyHigh = 0;
936
937 if (!m_pprConditionsContainerRun2.empty()) {
938 bool available = false;
939 std::tie(available, energyLow, energyHigh) = getBcidEnergyRange<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
940 if(!available) ATH_MSG_WARNING("::etRange: No L1CaloPprConditions found");
941 } else ATH_MSG_WARNING("::etRange: No Conditions Container retrieved");
942
943 ATH_MSG_VERBOSE( "::etRange: energyLow: " << energyLow
944 << " energyHigh: " << energyHigh);
945
946 etRange(et, energyLow, energyHigh, output);
947}
948
950
951void L1TriggerTowerToolRun3::etRange(const std::vector<int> &et, int energyLow, int energyHigh, std::vector<int> &output) const
952{
953 output.clear();
954 output.reserve(et.size()); // avoid frequent reallocations
955 for( auto it : et) {
956 if (it <= energyLow) output.push_back(0);
957 else if (it <= energyHigh) output.push_back(1);
958 else output.push_back(2);
959 }
960
961 ATH_MSG_DEBUG( "::etRange: output: " << output);
962
963
964}
965
967namespace { // helper function
968 template<class T>
969 std::tuple<bool, int> getFirStartBit(unsigned int coolId, SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
970 auto settings = pprConditionsRun2->pprConditions(coolId);
971 if(!settings) return std::make_tuple(false, 0);
972 return std::make_tuple(true, settings->firStartBit());
973 }
974} // anonymous namespace
975
976void L1TriggerTowerToolRun3::dropBits(const std::vector<int> &fir, const L1CaloCoolChannelId& channelId, std::vector<int> &output) const
977{
978 unsigned int start = 0;
980
981 if(!m_pprConditionsContainerRun2.empty()) {
982 bool available = false;
983 std::tie(available, start) = getFirStartBit<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
984 if(!available)ATH_MSG_WARNING( "::dropBits: No L1CaloPprConditions found" );
985 } else ATH_MSG_WARNING( "::dropBits: No Conditions Container retrieved" );
986
987 ATH_MSG_DEBUG( "::dropBits: firStartBit: " << start );
988
989 dropBits(fir, start, output);
990}
991
993
994void L1TriggerTowerToolRun3::dropBits(const std::vector<int> &fir, unsigned int start, std::vector<int> &output) const
995{
996 output.clear();
997 output.reserve(fir.size()); // avoid frequent reallocations
998
1000 unsigned int mask = (0x3ff<<start);
1001
1003 int max = 1<<(10+start);
1004
1005 for( auto it : fir) {
1006 if (it>=max) output.push_back(0x3ff);
1007 else output.push_back((it&mask)>>start);
1008 }
1009
1010 ATH_MSG_DEBUG( "::dropBits: output: " << output);
1011}
1012
1014void L1TriggerTowerToolRun3::firParams(const L1CaloCoolChannelId& channelId, std::vector<int> &firCoeffs) const
1015{
1017 firCoeffs.clear();
1019 if(!m_pprConditionsContainerRun2.empty()) {
1020 const std::vector<short int>* hwCoeffs = nullptr;
1021 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2 );
1022
1023 if(hwCoeffs) {
1027 firCoeffs.reserve(hwCoeffs->size()); // avoid frequent reallocations
1028 for (int i = hwCoeffs->size()-1; i >= 0; --i) firCoeffs.push_back((*hwCoeffs)[i]);
1029
1030 } else ATH_MSG_WARNING( "::firParams: No L1CaloPprConditions found" );
1031 } else ATH_MSG_WARNING( "::firParams: No Conditions Container retrieved" );
1032
1033
1034 ATH_MSG_DEBUG( "::fir: FIR coefficients: " << firCoeffs);
1035
1036}
1037
1039void L1TriggerTowerToolRun3::bcidParams(const L1CaloCoolChannelId& channelId, int &energyLow, int &energyHigh, int &decisionSource, std::vector<unsigned int> &decisionConditions,
1040 unsigned int &peakFinderStrategy, int &satLow, int &satHigh, int &satLevel) const
1041{
1042 energyLow = 0;
1043 energyHigh = 0;
1044 decisionSource = 0;
1045 decisionConditions.clear();
1046 peakFinderStrategy = 0;
1047 satLevel = 0;
1048 satLow = 0;
1049 satHigh = 0;
1050
1052
1053 if(!m_pprConditionsContainerRun2.empty()) {
1054 using std::get;
1055 std::tuple<unsigned int, unsigned int, unsigned int> bcidDecision;
1056 std::tuple<bool, int, int> bcidEnergyRange;
1057 std::tuple<bool, int, int, int> saturation;
1058
1060 bcidDecision = getBcidDecision<Cont>(pprConditionsRun2);
1061 peakFinderStrategy = getStrategy<Cont>(pprConditionsRun2);
1062 decisionSource = getDecisionSource<Cont>(pprConditionsRun2);
1063 bcidEnergyRange = getBcidEnergyRange<Cont>(channelId.id(), pprConditionsRun2);
1064 saturation = getSaturation<Cont>(channelId.id(), pprConditionsRun2);
1065
1066
1067 decisionConditions = { get<2>(bcidDecision),
1069 get<0>(bcidDecision) }; // reverse order
1070 if(get<0>(bcidEnergyRange)) {
1071 std::tie(std::ignore, energyLow, energyHigh) = bcidEnergyRange;
1072 } else ATH_MSG_WARNING( "::bcidParams: No BcidEnergyRange found" );
1073
1074 if(get<0>(saturation)) {
1075 std::tie(std::ignore, satLevel, satLow, satHigh) = saturation;
1076 } else ATH_MSG_WARNING( "::bcidParams: No Saturation found" );
1077 } else ATH_MSG_WARNING( "::bcid:Params No Conditions Container retrieved" );
1078
1079 ATH_MSG_DEBUG( "::bcidParams: satLevel: " << satLevel
1080 << " satLow: " << satLow << " satHigh: " << satHigh << endmsg
1081 << " energyLow: " << energyLow << " energyHigh: " << energyHigh << endmsg
1082 << " decisionSource: " << decisionSource << " peakFinderStrategy: "
1083 << peakFinderStrategy );
1084
1085}
1086
1087void L1TriggerTowerToolRun3::cpLutParams(const L1CaloCoolChannelId& channelId, int& startBit, int& slope, int& offset, int& cut, int& pedValue, float& pedMean, int& strategy, bool& disabled)
1088{
1089 startBit = 0;
1090 strategy = 0;
1091 offset = 0;
1092 slope = 0;
1093 cut = 0;
1094 pedValue = 0;
1095 pedMean = 0.;
1096 disabled = true;
1097 int hwCoeffSum = 0;
1098 const std::vector<short int>* hwCoeffs;
1099
1100
1101 if(!isRun2()) {
1102 // assert instead ?!
1103 ATH_MSG_WARNING("::cpLutParams: Run-1 data - behaviour undefined!");
1104 }
1105
1107
1108 if(!m_pprConditionsContainerRun2.empty()) {
1109 const auto settings = pprConditionsRun2->pprConditions(channelId.id());
1110 if(settings) {
1111 startBit = settings->firStartBit();
1112 strategy = settings->lutCpStrategy();
1113 slope = settings->lutCpSlope();
1114 cut = settings->lutCpNoiseCut();
1115 pedValue = settings->pedValue();
1116 pedMean = settings->pedMean();
1117
1118 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(), pprConditionsRun2);
1119
1120 for( auto &coeffs : *hwCoeffs) {
1121 hwCoeffSum += coeffs;
1122 }
1123
1124 offset = this->getLutOffset(pedMean, startBit, *hwCoeffs, slope, strategy);
1125
1126 ATH_MSG_VERBOSE( "::jepLutParams: Offset: offset/strategy/pedMean/firCoeffSum/startBit/slope: "
1127 << offset << " " << strategy << " " << " " << pedMean << " " << hwCoeffSum << " " << startBit << " " << slope );
1128
1129 } else ATH_MSG_WARNING( "::cpLutParams: No L1CaloPprConditions found" );
1130 } else ATH_MSG_WARNING( "::cpLutParams: No Conditions Container retrieved" );
1131
1132 ATH_MSG_VERBOSE( "::cpLutParams: LUT startBit/strategy/offset/slope/cut/pedValue/pedMean: "
1133 << startBit << " " << strategy << " " << offset << " " << slope << " " << cut << " " << pedValue << " " << pedMean );
1134 unsigned int noiseCut = 0;
1135 disabled = disabledChannel(channelId, noiseCut);
1136 if (noiseCut > 0) cut = noiseCut;
1137}
1138
1139void L1TriggerTowerToolRun3::jepLutParams(const L1CaloCoolChannelId& channelId, int& startBit, int& slope, int& offset, int& cut, int& pedValue, float& pedMean, int& strategy, bool& disabled)
1140{
1141 startBit = 0;
1142 strategy = 0;
1143 offset = 0;
1144 slope = 0;
1145 cut = 0;
1146 pedValue = 0;
1147 pedMean = 0.;
1148 disabled = true;
1149 int hwCoeffSum = 0;
1150 const std::vector<short int>* hwCoeffs;
1151
1152 if(!isRun2()) {
1153 // assert instead ?!
1154 ATH_MSG_WARNING("::jepLutParams: Run-1 data - behaviour undefined!");
1155 }
1156
1158 if(!m_pprConditionsContainerRun2.empty()) {
1159 const auto settings = pprConditionsRun2->pprConditions(channelId.id());
1160 if(settings) {
1161 startBit = settings->firStartBit();
1162 strategy = settings->lutJepStrategy();
1163 slope = settings->lutJepSlope();
1164 cut = settings->lutJepNoiseCut();
1165 pedValue = settings->pedValue();
1166 pedMean = settings->pedMean();
1167
1168 hwCoeffs = getFirCoefficients<L1CaloPprConditionsContainerRun2>(channelId.id(),pprConditionsRun2);
1169
1170 for( auto &coeffs : *hwCoeffs) {
1171 hwCoeffSum += coeffs;
1172 }
1173
1174 offset = this->getLutOffset(pedMean, startBit, *hwCoeffs, slope, strategy);
1175
1176 ATH_MSG_VERBOSE( "::jepLutParams: Offset: offset/strategy/pedMean/firCoeffSum/startBit/slope: "
1177 << offset << " " << strategy << " " << " " << pedMean << " " << hwCoeffSum << " " << startBit << " " << slope );
1178
1179 } else ATH_MSG_WARNING( "::jepLutParams: No L1CaloPprConditions found" );
1180 } else ATH_MSG_WARNING( "::jepLutParams: No Conditions Container retrieved" );
1181
1182 ATH_MSG_VERBOSE( "::jepLutParams: LUT startBit/strategy/offset/slope/cut/pedValue/pedMean: "
1183 << startBit << " " << strategy << " " << offset << " " << slope << " " << cut << " " << pedValue << " " << pedMean );
1184 unsigned int noiseCut = 0;
1185 disabled = disabledChannel(channelId, noiseCut);
1186 if (noiseCut > 0) cut = noiseCut;
1187}
1188
1190
1192{
1193 Identifier id(0);
1195 int pos_neg_z = m_l1CaloTTIdTools->pos_neg_z(eta);
1196 int region = m_l1CaloTTIdTools->regionIndex(eta);
1197 int ieta = m_l1CaloTTIdTools->etaIndex(eta);
1198 int iphi = m_l1CaloTTIdTools->phiIndex(eta, phi);
1199
1200 id = m_lvl1Helper->tower_id(pos_neg_z, layer, region, ieta, iphi);
1201 }
1202 return id;
1203}
1204
1206
1208{
1209 HWIdentifier hwId(0);
1210 if (m_ttSvc) {
1211 try { hwId = m_ttSvc->createTTChannelID(id, false); }
1212 catch (const CaloID_Exception&) { hwId = HWIdentifier(0); }
1213 }
1214 return hwId;
1215}
1216
1218
1220{
1221 Identifier id = identifier(eta, phi, layer);
1222 return hwIdentifier(id);
1223}
1224
1226
1228{
1229 // Use direct lookup table if possible
1230 const double absEta = std::abs(eta);
1231 int index = 0;
1232 if (absEta < 2.5) {
1233 const int etaBin = 10.*absEta;
1234 const int phiBin = phi*(32/M_PI);
1235 index = (etaBin<<6) + phiBin;
1236 } else if (absEta < 3.2) {
1237 const int etaBin = 5.*(absEta - 2.5);
1238 const int phiBin = phi*(16./M_PI);
1239 index = 1600 + (etaBin<<5) + phiBin;
1240 } else {
1241 const int etaBin = (absEta - 3.2)*(1./0.425);
1242 const int phiBin = phi*(8./M_PI);
1243 index = 1728 + (etaBin<<4) + phiBin;
1244 }
1245 if (eta < 0.) index += 1792;
1246 if (layer > 0) index += 3584;
1247 if (index >= s_maxTowers) return L1CaloCoolChannelId(0);
1248 if (m_idTable.empty()) {
1249 m_idTable.reserve(s_maxTowers);
1250 m_idTable.assign(s_maxTowers, 0);
1251 }
1252 if (m_idTable[index] == 0) {
1253 Identifier id = identifier(eta, phi, layer);
1254 L1CaloCoolChannelId coolID = channelID(id);
1255 m_idTable[index] = coolID.id();
1256 }
1258}
1259
1261
1263{
1264 L1CaloCoolChannelId coolId(0);
1265 if (m_ttSvc) {
1266 try {
1267 HWIdentifier hwId = hwIdentifier(id);
1268 coolId = m_ttSvc->createL1CoolChannelId(hwId);
1269 }
1270 catch (const CaloID_Exception&) { coolId = L1CaloCoolChannelId(0); }
1271 }
1272 return coolId;
1273}
1274
1276namespace { // helper function
1277 template<class T>
1278 std::tuple<bool, bool, bool> getSatOverride(SG::ReadCondHandle<L1CaloPprConditionsContainerRun2> pprConditionsRun2) {
1279 return std::make_tuple(pprConditionsRun2->satOverride1(), pprConditionsRun2->satOverride2(), pprConditionsRun2->satOverride3());
1280 }
1281} // anonymous namespace
1282
1284{
1285
1287
1288 bool override = false;
1289 if(!m_pprConditionsContainerRun2.empty()) {
1290 std::tuple<bool, bool, bool> satOverride;
1291 satOverride = getSatOverride<L1CaloPprConditionsContainerRun2>(pprConditionsRun2);
1292 // NB Reverse order as for bcidDecision1/2/3
1293 if (range == 0) override = std::get<2>(satOverride);
1294 else if (range == 1) override = std::get<1>(satOverride);
1295 else if (range == 2) override = std::get<0>(satOverride);
1296 } else ATH_MSG_WARNING( "::satOverride: No Conditions Container retrieved" );
1297
1298 ATH_MSG_VERBOSE( "::satOverride: range " << range
1299 << " has saturation override flag " << override );
1300
1301 return override;
1302}
1303
1305
1307{
1308 unsigned int noiseCut = 0;
1309 return disabledChannel(channelId, noiseCut);
1310}
1311
1313bool L1TriggerTowerToolRun3::disabledChannel(const L1CaloCoolChannelId& channelId, unsigned int& noiseCut) const
1314{
1315
1317 bool isDisabled = false;
1318 noiseCut = 0;
1319 if(!m_pprDisabledChannelContainer.empty()) {
1320
1321 const auto disabledChan = pprDisabledChannel->pprDisabledChannel(channelId.id());
1322
1323 if (disabledChan) {
1324 if (!disabledChan->disabledBits()) {
1325 ChanCalibErrorCode calibError(disabledChan->calibErrorCode());
1326 if (calibError.chanValid()) {
1327 ChanDeadErrorCode deadError(disabledChan->deadErrorCode());
1328 if (deadError.chanValid()) noiseCut = disabledChan->noiseCut();
1329 //else isDisabled = true;
1330 } //else isDisabled = true;
1331 } else isDisabled = true;
1332
1333 ATH_MSG_DEBUG( MSG::hex
1334 << "::disabledChannel: calibErrorCode: " << (disabledChan->calibErrorCode()).errorCode()
1335 << " deadErrorCode: " << (disabledChan->deadErrorCode()).errorCode()
1336 << " noiseCut: " << disabledChan->noiseCut()
1337 << " disabledBits: " << disabledChan->disabledBits()
1338 << MSG::dec );
1339
1340 } else {
1341 ATH_MSG_DEBUG( "::disabledChannel: No L1CaloPprDisabledChannel found" );
1342 }
1343 } else {
1344 ATH_MSG_WARNING( "::disabledChannel: No DisabledChannel Container retrieved" );
1345 }
1346 if (isDisabled) ATH_MSG_DEBUG( "::disabledChannel: Channel is disabled" );
1347
1348 return isDisabled;
1349}
1350
1351
1354
1355double L1TriggerTowerToolRun3::FCalTTeta(double nominalEta, double /*phi*/, int layer)
1356{
1357 double eta = nominalEta;
1358 float abseta = std::abs(eta);
1359 if (abseta<3.2) return eta; // If called for non-FCAL TT return input value
1360 if (layer == 0) {
1361 int sign = ((eta > 0) ? 1 : -1);
1362 if (abseta < 3.6) eta = 3.15 * sign;
1363 else if (abseta < 4.0) eta = 3.33 * sign;
1364 else if (abseta < 4.5) eta = 3.72 * sign;
1365 else eta = 4.41 * sign;
1366 }
1367 else if (eta > 0) {
1368 if (abseta < 3.6) eta = 3.36;
1369 else if (abseta < 4.0) eta = 3.45;
1370 else if (abseta < 4.5) eta = 4.17;
1371 else eta = 4.19;
1372 }
1373 else {
1374 if (abseta < 3.6) eta = -3.45;
1375 else if (abseta < 4.0) eta = -3.36;
1376 else if (abseta < 4.5) eta = -4.19;
1377 else eta = -4.17;
1378 }
1379 return eta;
1380}
1381
1385
1387{
1388 if ( !m_mappingTool.isValid() ) {
1389 throw GaudiException("No mapping tool configured",
1390 "L1TriggerTowerToolRun3::FCalTTeta", StatusCode::FAILURE);
1391 }
1392
1394 unsigned int crate = channelId.crate();
1395 unsigned int module = channelId.module();
1396 unsigned int mcm = channelId.subModule();
1397 unsigned int pin = channelId.channel();
1398 int channel = pin*16 + mcm;
1399
1401 double eta;
1402 double phi;
1403 int layer;
1404 if(!m_mappingTool->mapping(crate, module, channel, eta, phi, layer)) {
1405 ATH_MSG_WARNING("::FCalTTeta: could not map 0x" << std::hex << channelId.id() << std::dec);
1406 }
1407
1409 return FCalTTeta(eta, phi, layer);
1410}
1411
1412
1413
1414std::pair<double, double> L1TriggerTowerToolRun3::refValues(const L1CaloCoolChannelId& channelId)
1415{
1416 //method returning the fine time reference and calibration value
1417 //the fineTimeReference folder has to be loaded first using the method L1TriggerTowerToolRun3::loadFTRefs
1418 double reference = 0;
1419 double calib = 0;
1421
1422 if (!m_ppmFineTimeRefsContainer.empty()) {
1423 const L1CaloPpmFineTimeRefs* ftref = ppmFineTimeRefs->ppmFineTimeRefs(channelId.id());
1424 if (ftref) {
1425 FineTimeErrorCode errorCode(ftref->errorCode());
1426// if (errorCode.chanValid()) { //this should be changed at some point, at the moment the error code is ignored
1427 reference = ftref->refValue();
1428 calib = ftref->calibValue();
1429// }
1430
1431 ATH_MSG_VERBOSE( MSG::hex
1432 << "::refValues: errorCode: " << (ftref->errorCode()).errorCode()
1433 << MSG::dec << " reference: " << ftref->refValue() << " calib: " << ftref->calibValue() );
1434
1435 } else {
1436 ATH_MSG_VERBOSE( "::refValue: No FineTimeRefsTowers found" );
1437 }
1438 } else {
1439 ATH_MSG_VERBOSE( "::refValue: No FineTimeRefs Container retrieved" );
1440 }
1441
1442 return std::make_pair(reference, calib);
1443}
1444
1445void L1TriggerTowerToolRun3::pedestalCorrection(std::vector<int>& firInOut, int firPed, int iElement, int layer, int bcid, float mu, std::vector<int_least16_t>& correctionOut) {
1446 unsigned nFIR = firInOut.size();
1447 correctionOut.assign(nFIR, 0u);
1448
1449 if(!m_correctFir) return;
1450
1451 // apply the pedestal correction
1452 for(unsigned i = 0; i != nFIR; ++i) {
1453 correctionOut[i] = (m_dynamicPedestalProvider->dynamicPedestal(iElement, layer, firPed, bcid + i - nFIR/2, mu) - firPed);
1454 firInOut[i] -= correctionOut[i];
1455
1456 if(firInOut[i] < 0) firInOut[i] = 0;
1457 }
1458
1459 ATH_MSG_DEBUG( "::pedestalCorrection(BCID=" << bcid << ", mu = " << mu << "): " << correctionOut);
1460
1461}
1462
1464{
1465 const EventContext& ctx = Gaudi::Hive::currentContext();
1466 if (ctx.eventID().run_number() >= 253377) return true;
1467
1469 if (eventInfo->eventType (xAOD::EventInfo::IS_SIMULATION)) return true;
1470 return false;
1471}
1472
1473unsigned int L1TriggerTowerToolRun3::getLutOffset(const double &pedMean, const unsigned int &firStartBit, const std::vector<short int> &firCoeff, const unsigned int &lutSlope, const unsigned int &lutStrategy) const
1474{
1475 unsigned int lutOffset = 0;
1476 // essential to save in long long to avoid rounding errors
1477 long long int lutOffsetLong = 0;
1478 long long int lutSlopeLong = lutSlope;
1479 long long int firStartBitLong = firStartBit;
1480 long long int pedMeanLong = std::lround(pedMean * 10000.);
1481 long long int firCoeffSum = 0;
1482
1483 for (unsigned int i=0; i<firCoeff.size(); i++) {
1484 firCoeffSum += firCoeff.at(i);
1485 }
1486
1487 if ( lutStrategy == 0 ) {
1488 lutOffsetLong = ((pedMeanLong*firCoeffSum) >> firStartBitLong);
1489 }
1490 else {
1491 lutOffsetLong = ((pedMeanLong*firCoeffSum*lutSlopeLong) >> firStartBitLong) - ((lutSlopeLong * 10000) >> 1);
1492 }
1493
1494 lutOffsetLong = (lutOffsetLong + (10000-1))/10000;
1495 lutOffset = static_cast<unsigned int>( lutOffsetLong < 0 ? 0 : lutOffsetLong );
1496 return lutOffset;
1497}
1498
1499const TrigConf::L1Menu* L1TriggerTowerToolRun3::getL1Menu(const EventContext& ctx) const {
1500 const TrigConf::L1Menu* menu = nullptr;
1501
1502 StatusCode sc = m_configSvc.retrieve();
1503 if (sc.isFailure()) {
1504 ATH_MSG_WARNING( "Cannot retrieve trigger configuration service" );
1505 }
1506
1509 if( l1MenuHandle.isValid() ){
1510 menu=l1MenuHandle.cptr();
1511 }
1512 } else {
1513 menu = &(m_configSvc->l1Menu(ctx));
1514 }
1515
1516 return menu;
1517}
1518
1519
1520
1521} // end of namespace
1522
1523
1524
1525
#define M_PI
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_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
Handle class for reading from StoreGate.
int sign(int a)
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
Exception class for Calo Identifiers.
ChanCalibErrorCode class for L1Calo error codes Adapted from /LVL1/l1calo/coolL1Calo/coolL1Calo/ChanE...
bool chanValid() const
Checks if channel is valid, ie.
ChanDeadErrorCode class for L1Calo error codes Adapted from /LVL1/l1calo/coolL1Calo/coolL1Calo/ChanDe...
FineTimeErrorCode class for L1Calo error codes.
Encapsulates the ID of one channel of conditions data in COOL, ie the ID of a row in a table.
unsigned int id() const
FineTimeErrorCode errorCode(void) const
double calibValue(void) const
double refValue(void) const
Container of L1CaloPprConditions objects, inherit from the abstract base class AbstractL1CaloConditio...
virtual void peakBcid(const std::vector< int > &fir, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
Peak finder BCID.
virtual StatusCode finalize() override
standard Athena-Algorithm method
SG::ReadCondHandleKey< L1CaloPpmFineTimeRefsContainer > m_ppmFineTimeRefsContainer
virtual void jepLut(const std::vector< int > &fir, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
virtual L1CaloCoolChannelId channelID(double eta, double phi, int layer) override
Return Cool channel identifier for given tower coordinates.
virtual void applyEtRange(const std::vector< int > &lut, const std::vector< int > &range, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
Use ET range to return appropriate ET value Do not test BCID here, since no guarantee enough ADC samp...
virtual HWIdentifier hwIdentifier(const Identifier &id) override
Return online identifier for given offline identifier.
ToolHandle< LVL1::IL1DynamicPedestalProvider > m_dynamicPedestalProvider
ToolHandle< LVL1::IL1CaloTTIdTools > m_l1CaloTTIdTools
virtual std::pair< double, double > refValues(const L1CaloCoolChannelId &channelId) override
virtual bool disabledChannel(const L1CaloCoolChannelId &channelId) const override
Check for disabled channel.
virtual void nonLinearLut(const std::vector< int > &fir, int slope, int offset, int cut, int scale, short par1, short par2, short par3, short par4, bool disabled, std::vector< int > &output) const
ServiceHandle< TrigConf::ITrigConfigSvc > m_configSvc
virtual void fir(const std::vector< int > &digits, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
This FIR simulation produces a vector of same length as digit vector, with peak positions correspondi...
SG::ReadCondHandleKey< L1CaloPprDisabledChannelContainerRun2 > m_pprDisabledChannelContainer
static const int s_saturationValue
Parameters.
virtual void bcidDecisionRange(const std::vector< int > &lutInput, const std::vector< int > &digits, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
virtual void dropBits(const std::vector< int > &fir, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
virtual bool satOverride(int range) const override
virtual void lut(const std::vector< int > &fir, int slope, int offset, int cut, int strategy, bool disabled, std::vector< int > &output) const override
LUT simulation: pedestal subtraction, energy calibration and threshold.
virtual StatusCode initialize() override
standard Athena-Algorithm method
virtual void bcidParams(const L1CaloCoolChannelId &channelId, int &energyLow, int &energyHigh, int &decisionSource, std::vector< unsigned int > &decisionConditions, unsigned int &peakFinderStrategy, int &satLow, int &satHigh, int &satLevel) const override
Return BCID parameters for a channel.
std::vector< unsigned int > m_idTable
Mapping lookup table.
virtual void cpLut(const std::vector< int > &fir, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
virtual void simulateChannel(const xAOD::TriggerTower &tt, std::vector< int > &outCpLut, std::vector< int > &outJepLut, std::vector< int > &bcidResults, std::vector< int > &bcidDecisions) const override
All-in-one routine - give it the TT identifier, and it returns the results.
virtual void process(const std::vector< int > &digits, double eta, double phi, int layer, std::vector< int > &et, std::vector< int > &bcidResults, std::vector< int > &bcidDecisions, bool useJepLut=true) override
Take in vector of ADC digits, return PPrASIC results.
bool m_correctFir
Baseline correction Tool.
SG::ReadCondHandleKey< L1CaloRunParametersContainer > m_runParametersContainer
virtual void cpLutParams(const L1CaloCoolChannelId &channelId, int &startBit, int &slope, int &offset, int &cut, int &pedValue, float &pedMean, int &strategy, bool &disabled) override
L1TriggerTowerToolRun3(const std::string &, const std::string &, const IInterface *)
virtual void bcid(const std::vector< int > &fir, const std::vector< int > &digits, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
Evaluate both peak-finder and saturated BCID algorithms and return vector of predicted BCID result wo...
virtual Identifier identifier(double eta, double phi, int layer) override
Return offline identifier for given tower coordinates.
virtual double FCalTTeta(const L1CaloCoolChannelId &channelId) override
Return median eta of trigger tower from L1CaloCoolChannelId.
ToolHandle< CaloTriggerTowerService > m_ttSvc
virtual void jepLutParams(const L1CaloCoolChannelId &channelId, int &startBit, int &slope, int &offset, int &cut, int &pedValue, float &pedMean, int &strategy, bool &disabled) override
virtual void pedestalCorrection(std::vector< int > &firInOut, int firPed, int iElement, int layer, int bcid, float mu, std::vector< int_least16_t > &correctionOut) override
virtual void satBcid(const std::vector< int > &digits, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
Saturated pulse BCID.
SG::ReadHandleKey< TrigConf::L1Menu > m_L1MenuKey
virtual void etRange(const std::vector< int > &et, const L1CaloCoolChannelId &channelId, std::vector< int > &output) const override
virtual void firParams(const L1CaloCoolChannelId &channelId, std::vector< int > &firCoeffs) const override
Return FIR filter parameters for a channel.
const CaloLVL1_ID * m_lvl1Helper
and tools for computing identifiers
virtual void handle(const Incident &) override
catch begRun
SG::ReadCondHandleKey< L1CaloPprConditionsContainerRun2 > m_pprConditionsContainerRun2
virtual void bcidDecision(const std::vector< int > &bcidResults, const std::vector< int > &range, std::vector< int > &output) const override
const TrigConf::L1Menu * getL1Menu(const EventContext &ctx) const
unsigned int getLutOffset(const double &pedMean, const unsigned int &firStartBit, const std::vector< short int > &firCoeff, const unsigned int &lutSlope, const unsigned int &lutStrategy) const
virtual ~L1TriggerTowerToolRun3()
default destructor
ToolHandle< LVL1::IL1CaloMappingTool > m_mappingTool
and mappings
const CaloIdManager * m_caloMgr
Id managers.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
L1 menu configuration.
Definition L1Menu.h:28
make the sidebar many part of the config
Definition hcg.cxx:552
@ IS_SIMULATION
true: simulation, false: data
const std::string process
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:114
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition index.py:1
TriggerTower_v2 TriggerTower
Define the latest version of the TriggerTower class.
Extra patterns decribing particle interation process.