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