ATLAS Offline Software
Loading...
Searching...
No Matches
ZDCTriggerSim.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <iostream>
8#include <stdexcept>
9
10// dump stream data
11void ZDCTriggerSimBase::dump(std::ostream& strm) const {
12 for (auto entry : m_stack) {
13 strm << entry->getType() << ": ";
14 entry->dump(strm);
15 strm << std::endl;
16 }
17}
18
19// Obtain 3 bit output from 4*2 bit arm trigger decisions
22 if (ptr->getNumData() != 2 || ptr->getNumBits() != 4)
23 throw std::logic_error("Invalid input data in ZDCTriggerSimCombLUT");
24
25 unsigned int bitsSideA = ptr->getValueTrunc(0);
26 unsigned int bitsSideC = ptr->getValueTrunc(1);
27
28 unsigned int address = (bitsSideC << 4) + bitsSideA;
29 unsigned int comLUTvalue = m_combLUT.at(address);
30
31 // ZDCTriggerSim::SimDataPtr uses shared_ptr semantics so cleanup is
32 // guaranteed
33 //
35 static_cast<ZDCTriggerSim::CombLUTOutput*>(lutOut_p.get())
36 ->setDatum(comLUTvalue);
37
38 stackPush(lutOut_p);
39}
40
41// Obtain 4x2 bit output from arm energy sums
44 if (ptr->getNumData() != 2 || ptr->getNumBits() != 12)
45 throw std::logic_error("Invalid input data in ZDCTriggerSimAllLUTs");
46 ;
47
48 unsigned int inputSideA = ptr->getValueTrunc(0);
49 unsigned int inputSideC = ptr->getValueTrunc(1);
50
51 unsigned int valueA = m_LUTA.at(inputSideA);
52 unsigned int valueC = m_LUTC.at(inputSideC);
53
54 // ZDCTriggerSim::SimDataPtr uses shared_ptr semantics so cleanup is
55 // guaranteed
56 //
58 static_cast<ZDCTriggerSim::CombLUTInputsInt*>(inputs_p.get())
59 ->setData({valueA, valueC});
60
63}
64
65// Obtain arm energy sums from Module by Module Calibrated energies
66//
69 if (ptr->getNumData() != 8 || ptr->getNumBits() != 12)
70 throw std::logic_error("Invalid input data in ZDCTriggerSimModuleAmpls");
71
72 unsigned int sumA = 0;
73 for (size_t i = 0; i < 4; i++) {
74 sumA += ptr->getValueTrunc(i);
75 }
76
77 unsigned int sumC = 0;
78 for (size_t i = 4; i < 8; i++) {
79 sumC += ptr->getValueTrunc(i);
80 }
81
82 // The sums get divided by 4
83 //
84 sumA /= 4;
85 sumC /= 4;
86
88 static_cast<ZDCTriggerSim::SideLUTInputsInt*>(inputs_p.get())
89 ->setData({sumA, sumC});
90
92
94}
95
96// Obtain per-module amplitudes from the FADC data. The FADC data should have 24 samples per channel
97// for 8 channels. It was easier to just concatenate them all together to match the TriggerSimData
98// implementation.
99//
102 if (ptr->getNumData() != 24*8 || ptr->getNumBits() != 12)
103 throw std::logic_error("Invalid input data in ZDCTriggerSimModuleAmpls");
104
105 unsigned int sampleIdx = 0;
106
107 std::vector<unsigned int> moduleAmplitudes;
108
109 // Loop over the eight ZDC modules
110 //
111 for (size_t side : {0, 1}) {
112 for (size_t module : {0, 1, 2, 3}) {
113 std::vector<unsigned int> FADCsamples;
114
115 bool adcOverflow = false;
116
117 //
118 // Loop over the FADCs for the channel and put them in a vector for easier manipulation
119 // While we're at it, check for overflows since the trigger firmware always sends up
120 // 4095 if there is an overflow
121 //
122 for (size_t i = 0; i < 24; i++) {
123 unsigned int ADC = ptr->getValueTrunc(sampleIdx++);
124 if (ADC == 4095) {
125 adcOverflow = true;
126 break;
127 }
128
129 FADCsamples.push_back(ADC);
130 }
131
132 m_baseline[side][module] = 0;
133 m_maxADC[side][module] = 0;
134 m_maxNegDeriv2nd[side][module] = 0;
135
136 if (adcOverflow) {
137 //
138 // If the ADC overflows, the firmware returns amplitude of 4095
139 //
140 moduleAmplitudes.push_back(4095);
141 }
142 else {
143 std::vector<unsigned int> negDeriv2nd = CalculateNeg2ndDerivatives(FADCsamples, 2);
144
145 // Now loop over the min-max sample range (within single channel) and see
146 // if the second derivative threshold is exceeded. If so, we pick off the
147 // maximum amplitude in that same range -- this is what the firmware does
148 //
149 bool havePulse = false;
150 unsigned int maxAmp = 0;
151 unsigned int baseline = 0;
152 unsigned int maxNeg2ndDeriv = 0;
153
154 for (unsigned int sampleTest = m_minSampleAna; sampleTest <= m_maxSampleAna; sampleTest++) {
155 if (negDeriv2nd.at(sampleTest) > maxNeg2ndDeriv) maxNeg2ndDeriv = negDeriv2nd.at(sampleTest);
156 if (negDeriv2nd.at(sampleTest) > m_deriv2ndThresholds[side][module] && !havePulse) {
157 havePulse = true;
158
159 // The firmware evaluates the baseline a certain number of samples before
160 // the 2nd derivative threshold is crossed
161 //
162 baseline = FADCsamples.at(sampleTest - m_baselineDelta);
163 }
164
165 if (FADCsamples.at(sampleTest) > maxAmp) maxAmp = FADCsamples.at(sampleTest);
166 }
167
168 m_maxNegDeriv2nd[side][module] = maxNeg2ndDeriv;
169 if (havePulse) {
170 moduleAmplitudes.push_back(std::max<int>(int(maxAmp - baseline), 0));
171 m_baseline[side][module] = baseline;
172 m_maxADC[side][module] = maxAmp;
173 }
174 else {
175 moduleAmplitudes.push_back(0);
176 m_baseline[side][module] = 0;
177 m_maxADC[side][module] = 0;
178 }
179 }
180 }
181 }
182
184 static_cast<ZDCTriggerSim::ModuleAmplInputsInt*>(inputs_p.get())->setData(moduleAmplitudes);
185
186 stackPush(inputs_p);
187
189}
190
191
192std::vector<unsigned int>
193ZDCTriggerSimFADC::CalculateNeg2ndDerivatives(const std::vector<unsigned int>& samples, unsigned int step)
194{
195 std::vector<unsigned int> der2ndVec(step, 0);
196
197 for (size_t sample = step; sample < samples.size() - step; sample++) {
198 int diff2nd = samples[sample + step] + samples[sample - step] - 2*samples[sample];
199 if (diff2nd > 0) der2ndVec.push_back(0);
200 else der2ndVec.push_back(-diff2nd);
201 }
202
203 der2ndVec.insert(der2ndVec.end(), step, 0);
204
205 return der2ndVec;
206}
@ baseline
A tool to make L1 decision using LUTs.
virtual void doSimStage() override
std::array< unsigned int, 4096 > m_LUTA
std::array< unsigned int, 4096 > m_LUTC
void dump(std::ostream &strm) const
const ZDCTriggerSim::SimDataCPtr & stackTopData() const
void stackPush(const ZDCTriggerSim::SimDataCPtr &ptr)
std::array< unsigned int, 256 > m_combLUT
virtual void doSimStage() override
std::vector< unsigned int > CalculateNeg2ndDerivatives(const std::vector< unsigned int > &samples, unsigned int step)
std::array< std::array< int, 4 >, 2 > m_maxNegDeriv2nd
std::array< std::array< unsigned int, 4 >, 2 > m_deriv2ndThresholds
unsigned int m_maxSampleAna
std::array< std::array< unsigned int, 4 >, 2 > m_maxADC
virtual void doSimStage() override
std::array< std::array< unsigned int, 4 >, 2 > m_baseline
unsigned int m_minSampleAna
unsigned int m_baselineDelta
virtual void doSimStage() override
ZDCTriggerSimData< unsigned int, 8, 12, TModAmplsInput > ModuleAmplInputsInt
ZDCTriggerSimData< unsigned int, 2, 12, TSideLUTsInput > SideLUTInputsInt
ZDCTriggerSimData< unsigned int, 2, 4, TCombLUTInput > CombLUTInputsInt
ZDCTriggerSimData< unsigned int, 1, 3, TCombLUTOutput > CombLUTOutput
std::shared_ptr< const ZDCTriggerSimDataBase > SimDataCPtr
std::shared_ptr< ZDCTriggerSimDataBase > SimDataPtr