ATLAS Offline Software
Loading...
Searching...
No Matches
LArCellMuxAlg.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4
5/*
6 This Algorithm simulates both the input bitsream which would be received by the MUX from the LASP based on
7 the input GlobalLArCellContainer, as well as the output bitsream which each MUX would send to the GEPs. All
8 bitstreams are stored as textfiles in the running directory
9*/
10
11#include "LArCellMuxAlg.h"
12
15
16#include <fstream>
17#include <format>
18
19namespace GlobalSim {
20
21 // Initializing LArCellMuxAlg
23 ATH_MSG_INFO ("Initializing " << name());
24
25 CHECK(m_eventInfo.initialize());
26 CHECK(m_gblLArCellContainerKey.initialize());
27
28 return StatusCode::SUCCESS;
29 }
30
31
32 // Execute function which retrieves containers from StoreGate and then calls the two
33 // functions which write the input and output bitstream of the MUX
34 StatusCode LArCellMuxAlg::execute(const EventContext& ctx) const {
35
36 ATH_MSG_DEBUG ("Executing LArCellMuxAlg algorithm");
37
38 // Get EventInfo
40 CHECK(eventInfo.isValid());
41
42 // Read in GlobalLArCellContainer
43 auto h_gblLArCells = SG::makeHandle(m_gblLArCellContainerKey, ctx);
44 CHECK(h_gblLArCells.isValid());
45 const auto & gblLArCells = *h_gblLArCells;
46
47 ATH_MSG_DEBUG("Reading " << std::to_string(h_gblLArCells->size()) << " cells in input GlobalLArCellContainer");
48
49 Feb2BitsetMap feb2Bitsets;
50
51 // Compile and write the input bitstreams which are sent from LASP to MUX
52 CHECK(writeMuxInputBitstream(feb2Bitsets, *eventInfo, gblLArCells));
53
54 // Compile and write the output bitstreams which are sent from MUX to GEP
55 CHECK(writeMuxOutputBitstream(feb2Bitsets, *eventInfo, gblLArCells));
56
57 return StatusCode::SUCCESS;
58 }
59
60
61 // Function that takes the GlobalLArCellContainer as input and writes the input bitstreams
62 // to the MUX for all FEB2 to file (if requested in job options). All bistreams are stored
63 // in a map for later use
65 const xAOD::EventInfo& eventInfo,
66 const GlobalSim::GlobalLArCellContainer& gblLArCells) const {
67
68 std::ofstream out;
70 std::string filename = std::format("{}_MuxInput_{}_{}.dat", name(), eventInfo.runNumber(), eventInfo.eventNumber());
71 out.open(filename);
72 if (!out) {
73 ATH_MSG_ERROR("Failed to open file: " << filename);
74 return StatusCode::FAILURE;
75 }
76 }
77
78 for (const auto& feb2Key : gblLArCells.getFeb2Keys()) {
79
80 const std::vector<GlobalLArCell*>& cells = gblLArCells.getCellsForFeb2(feb2Key);
81 std::bitset<FEB2_BITSTREAM_SIZE> input_bitstream = assembleBitsetForFeb2(cells,
82 gblLArCells.getMaxCellsPerFeb2(),
83 gblLArCells.feb2InOverflow(feb2Key),
84 gblLArCells.feb2InError(feb2Key),
85 eventInfo.bcid());
86
87 feb2Bitsets[feb2Key] = input_bitstream;
88
90 out << "====== " << feb2Key << " is sending to " << gblLArCells.getMuxForFeb2(feb2Key) << ":\n";
91
92 for (std::size_t row = 0; row < FEB2_BITSTREAM_SIZE / BITWIDTH_MUX_INPUT; ++row) {
93 for (int col = BITWIDTH_MUX_INPUT-1; col >= 0; --col) {
94 int bitIndex = row * BITWIDTH_MUX_INPUT + col;
95 out << input_bitstream[bitIndex];
96 }
97 out << "\n";
98 }
99 out << "\n";
100 }
101 }
102
103 if (m_writeMuxInputBitstreamToFile) out.close();
104
105 return StatusCode::SUCCESS;
106 }
107
108
109 // Function that assembles the bitstream from each FEB2
110 std::bitset<LArCellMuxAlg::FEB2_BITSTREAM_SIZE> LArCellMuxAlg::assembleBitsetForFeb2(const std::vector<GlobalSim::GlobalLArCell*>& cells, std::size_t maxCells, bool inOverflow, bool inError, uint32_t bcid) const {
111
112 // Sort cells based on channel number
113 std::vector<const GlobalSim::GlobalLArCell*> sortedCells(cells.begin(), cells.end());
114 std::sort(sortedCells.begin(), sortedCells.end(), [](const auto* a, const auto* b) {
115 return a->getChannel() < b->getChannel();
116 });
117
118 // Declare bitsets for 2sigma and 4sigma mask, as well as energies
119 const std::size_t bitwidth_4SigmaMask = maxCells;
120 const std::size_t bitwidth_energyBlock = FEB2_BITSTREAM_SIZE - BITWIDTH_2SIGMAMASK - bitwidth_4SigmaMask - 2 - 8;
121
122 std::vector<bool> mask_twoSigma(BITWIDTH_2SIGMAMASK, false);
123 std::vector<bool> mask_fourSigma(bitwidth_4SigmaMask, false);
124 std::vector<bool> energyBits(bitwidth_energyBlock, false);
125
126 std::size_t bitPosEnergy = 0;
127
128 for (std::size_t i = 0; i < sortedCells.size(); ++i) {
129
130 const auto* cell = sortedCells[i];
131
132 // 2sigma mask by channel
133 mask_twoSigma[cell->getChannel()] = true;
134
135 // 4sigma mask by order of 2sigma cells
136 mask_fourSigma[i] = (cell->getSigma() >= 4.0);
137
138 // Energy bits
139 const boost::dynamic_bitset<>& enBits = cell->getEnergyBitstring();
140 for (std::size_t j = 0; j < enBits.size() && bitPosEnergy < bitwidth_energyBlock; ++j, ++bitPosEnergy) {
141 energyBits[bitPosEnergy]= enBits[j];
142 }
143 }
144
145 // 8b bunch crossing number
146 std::bitset<8> bitsBCN(bcid & 0xFF);
147
148 // Assemble final bitstream
149 std::bitset<FEB2_BITSTREAM_SIZE> bitstream;
150 std::size_t pos = 0;
151
152 pos = appendBits(bitstream, mask_twoSigma, pos);
153 pos = appendBits(bitstream, mask_fourSigma, pos);
154
155 if (inOverflow) bitstream.set(pos);
156 ++pos;
157 if (inError) bitstream.set(pos);
158 ++pos;
159
160 pos = appendBits(bitstream, energyBits, pos);
161 pos = appendBits(bitstream, bitsBCN, pos);
162
163 return bitstream;
164 }
165
166
167 // Function which writes the output bitstream of each MUX to file (if requested in job options)
168 // Each bitstream consists of a header, which is assembled here, the body, which is taken from
169 // the map previously filled when assembling the input bitsets, and a footer, which is seven
170 // words of zeros
172 const xAOD::EventInfo& eventInfo,
173 const GlobalSim::GlobalLArCellContainer& gblLArCells) const {
174
176 return StatusCode::SUCCESS;
177 }
178
179 std::string filename = std::format("{}_MuxOutput_{}_{}.dat", name(), eventInfo.runNumber(), eventInfo.eventNumber());
180 std::ofstream out(filename);
181 if (!out) {
182 ATH_MSG_ERROR("Failed to open file: " << filename);
183 return StatusCode::FAILURE;
184 }
185
186 // Assemble the header for each MUX
187 const int nBitsMarker = BITWIDTH_MUX_OUTPUT / 8;
188
189 // MUX marker line has the pattern ABBA ABBA
190 unsigned long long markerPattern =
191 (0xAULL << nBitsMarker*7) |
192 (0xBULL << nBitsMarker*6) |
193 (0xBULL << nBitsMarker*5) |
194 (0xAULL << nBitsMarker*4) |
195 (0xAULL << nBitsMarker*3) |
196 (0xBULL << nBitsMarker*2) |
197 (0xBULL << nBitsMarker) |
198 (0xAULL);
199
200 std::bitset<BITWIDTH_MUX_OUTPUT> markerBitset(markerPattern);
201
202 // 12b bunch crossing number
203 std::bitset<12> bitsBCN(eventInfo.bcid() & 0xFFF);
204
205 // Loop over all MUX IDs
206 for (int muxID = 0; muxID < 32; ++muxID) {
207
208 std::string muxKey = std::format("apl-gbl-mux-lasp-{:02}", muxID);
209 out << "====== " << muxKey << " is sending to GEP:\n";
210
211 std::bitset<6> bitsetMuxID(muxID);
212
213 // Bitset for the entire header block
214 const int bitwidthMuxHeader = BITWIDTH_MUX_OUTPUT * N_WORDS_MUX_HEADER;
215 std::bitset<bitwidthMuxHeader> fullMuxHeader;
216
217 // Assemble the header block
218 std::size_t pos = 0;
219 pos = appendBits(fullMuxHeader, markerBitset, pos);
220 pos = appendBits(fullMuxHeader, bitsBCN, pos);
221 pos = appendBits(fullMuxHeader, bitsetMuxID, pos);
222
223 // Overflow and error bits
224 if (gblLArCells.muxInOverflow(muxKey)) fullMuxHeader.set(pos);
225 ++pos;
226 if (gblLArCells.muxInError(muxKey)) fullMuxHeader.set(pos);
227 ++pos;
228
229 // Write header in lines of BITWIDTH_MUX_OUTPUT
230 for (std::size_t row = 0; row < N_WORDS_MUX_HEADER; ++row) {
231 for (int col = BITWIDTH_MUX_OUTPUT-1; col >= 0; --col) {
232 int bitIndex = row * BITWIDTH_MUX_OUTPUT + col;
233 out << fullMuxHeader[bitIndex];
234 }
235 out << "\n";
236 }
237
238 // Get and loop over FEB2s to write the FEB2 block
239 const std::vector<std::string>& feb2s = gblLArCells.getOrderedFeb2sForMux(muxKey);
240 for (const auto& feb2 : feb2s) {
241
242 auto it = feb2Bitsets.find(feb2);
243 if (it == feb2Bitsets.end()) {
244 ATH_MSG_ERROR("No bitset for FEB2 " << feb2);
245 return StatusCode::FAILURE;
246 }
247 const std::bitset<FEB2_BITSTREAM_SIZE>& feb2Bitset = it->second;
248
249 for (std::size_t row = 0; row < FEB2_BITSTREAM_SIZE / BITWIDTH_MUX_OUTPUT; ++row) {
250 for (int col = BITWIDTH_MUX_OUTPUT-1; col >= 0; --col) {
251 int bitIndex = row * BITWIDTH_MUX_OUTPUT + col;
252 out << feb2Bitset[bitIndex];
253 }
254 out << "\n";
255 }
256 }
257
258 // Close by writing the footer of the MUX (N_WORDS_MUX_FOOTER empty words)
259 for (std::size_t row = 0; row < N_WORDS_MUX_FOOTER; ++row) {
260 for (std::size_t col = 0; col < BITWIDTH_MUX_OUTPUT; ++col) {
261 out << '0';
262 }
263 out << "\n";
264 }
265 out << "\n";
266
267 } // Loop over all MUX IDs
268
269 out.close();
270 return StatusCode::SUCCESS;
271 }
272
273 template <std::size_t N, typename T> std::size_t LArCellMuxAlg::appendBits(std::bitset<N>& target, const T& src, std::size_t pos) {
274 for (std::size_t i = 0; i < src.size(); ++i, ++pos)
275 if (src[i]) target.set(pos);
276 return pos;
277 }
278
279} // namespace GlobalSim
280
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t a
bool muxInError(const std::string &muxKey) const
Check if a given MUX is in error.
bool feb2InOverflow(const std::string &feb2Key) const
Check if a given FEB2 is in overflow.
const std::unordered_set< std::string > & getFeb2Keys() const
Function to return the full list of FEB2 names.
std::size_t getMaxCellsPerFeb2() const
Function to get maximum number of cells per FEB2.
const std::string & getMuxForFeb2(const std::string &feb2Key) const
Function to get the associated MUX name for a given FEB2.
bool muxInOverflow(const std::string &muxKey) const
Check if a given MUX is in overflow.
const std::vector< GlobalLArCell * > & getCellsForFeb2(const std::string &feb2) const
Function to get all GlobalLArCells for a given FEB2 name.
bool feb2InError(const std::string &feb2Key) const
Check if a given FEB2 is in error.
const std::vector< std::string > & getOrderedFeb2sForMux(const std::string &mux) const
Function to get ordered list of FEB2s for a given MUX name.
static constexpr std::size_t FEB2_BITSTREAM_SIZE
Gaudi::Property< bool > m_writeMuxInputBitstreamToFile
Flag to enable writing of MUX input bitstreams (FEB2/LASP -> MUX) to file.
std::map< std::string, std::bitset< FEB2_BITSTREAM_SIZE > > Feb2BitsetMap
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
Key for the EventInfo object.
Gaudi::Property< bool > m_writeMuxOutputBitstreamToFile
Flag to enable writing ofMUX output bitstreams (MUX -> GEP) to file.
static constexpr std::size_t BITWIDTH_MUX_OUTPUT
static constexpr std::size_t BITWIDTH_MUX_INPUT
static constexpr std::size_t N_WORDS_MUX_FOOTER
virtual StatusCode initialize() override
initialize function running before first event
SG::ReadHandleKey< GlobalSim::GlobalLArCellContainer > m_gblLArCellContainerKey
Key to the GlobalLArCellContainer.
StatusCode writeMuxInputBitstream(Feb2BitsetMap &feb2Bitsets, const xAOD::EventInfo &eventInfo, const GlobalSim::GlobalLArCellContainer &gblLArCells) const
Function that compiles the LASP to MUX bitstream and writes it to file.
static constexpr std::size_t N_WORDS_MUX_HEADER
static constexpr std::size_t BITWIDTH_2SIGMAMASK
StatusCode writeMuxOutputBitstream(const Feb2BitsetMap &feb2Bitsets, const xAOD::EventInfo &eventInfo, const GlobalSim::GlobalLArCellContainer &gblLArCells) const
Function that compiles the MUX to GEP bitstream and writes it to file.
virtual StatusCode execute(const EventContext &) const override
execute function running for every event
std::bitset< FEB2_BITSTREAM_SIZE > assembleBitsetForFeb2(const std::vector< GlobalSim::GlobalLArCell * > &cells, std::size_t maxCells, bool inOverflow, bool inError, uint32_t bcid) const
Function which compiles the bitset for one particular FEB2.
static std::size_t appendBits(std::bitset< N > &target, const T &src, std::size_t pos)
Helper function to append a bitset or vector of bools at a specific position in another bitset.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
uint32_t bcid() const
The bunch crossing ID of the event.
uint32_t runNumber() const
The current event's run number.
uint64_t eventNumber() const
The current event's event number.
AlgTool that to test whether expected the TIP values generated by data supplied by eEmMultTestBench c...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
EventInfo_v1 EventInfo
Definition of the latest event info version.