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 sampleIdx += (24 - i);
127 break;
128 } else {
129 sampleIdx++;
130 }
131
132
133 FADCsamples.push_back(ADC);
134 }
135
136 m_baseline[side][module] = 0;
137 m_maxADC[side][module] = 0;
138 m_maxNegDeriv2nd[side][module] = 0;
139
140 if (adcOverflow) {
141 //
142 // If the ADC overflows, the firmware returns amplitude of 4095
143 //
144 moduleAmplitudes.push_back(4095);
145 }
146 else {
147 std::vector<unsigned int> negDeriv2nd = CalculateNeg2ndDerivatives(FADCsamples, 2);
148
149 // Now loop over the min-max sample range (within single channel) and see
150 // if the second derivative threshold is exceeded. If so, we pick off the
151 // maximum amplitude in that same range -- this is what the firmware does
152 //
153 bool havePulse = false;
154 unsigned int maxAmp = 0;
155 unsigned int baseline = 0;
156 unsigned int maxNeg2ndDeriv = 0;
157
158 for (unsigned int sampleTest = m_minSampleAna; sampleTest <= m_maxSampleAna; sampleTest++) {
159 if (negDeriv2nd.at(sampleTest) > maxNeg2ndDeriv) maxNeg2ndDeriv = negDeriv2nd.at(sampleTest);
160 if (negDeriv2nd.at(sampleTest) > m_deriv2ndThresholds[side][module] && !havePulse) {
161 havePulse = true;
162
163 // The firmware evaluates the baseline a certain number of samples before
164 // the 2nd derivative threshold is crossed
165 //
166 baseline = FADCsamples.at(sampleTest - m_baselineDelta);
167 }
168
169 if (FADCsamples.at(sampleTest) > maxAmp) maxAmp = FADCsamples.at(sampleTest);
170 }
171
172 m_maxNegDeriv2nd[side][module] = maxNeg2ndDeriv;
173 if (havePulse) {
174 moduleAmplitudes.push_back(std::max<int>(int(maxAmp - baseline), 0));
175 m_baseline[side][module] = baseline;
176 m_maxADC[side][module] = maxAmp;
177 }
178 else {
179 moduleAmplitudes.push_back(0);
180 m_baseline[side][module] = 0;
181 m_maxADC[side][module] = 0;
182 }
183 }
184 }
185 }
186
188 static_cast<ZDCTriggerSim::ModuleAmplInputsInt*>(inputs_p.get())->setData(moduleAmplitudes);
189
190 stackPush(inputs_p);
191
193}
194
195
196std::vector<unsigned int>
197ZDCTriggerSimFADC::CalculateNeg2ndDerivatives(const std::vector<unsigned int>& samples, unsigned int step)
198{
199 std::vector<unsigned int> der2ndVec(step, 0);
200
201 for (size_t sample = step; sample < samples.size() - step; sample++) {
202 int diff2nd = samples[sample + step] + samples[sample - step] - 2*samples[sample];
203 if (diff2nd > 0) der2ndVec.push_back(0);
204 else der2ndVec.push_back(-diff2nd);
205 }
206
207 der2ndVec.insert(der2ndVec.end(), step, 0);
208
209 return der2ndVec;
210}
@ 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