ATLAS Offline Software
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 <fmt/core.h>
18 
19 namespace GlobalSim {
20 
21  // Initializing LArCellMuxAlg
23  ATH_MSG_INFO ("Initializing " << name());
24 
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 = fmt::format("MuxInputBitstream/{}_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 = fmt::format("MuxOutputBitstream/{}_MuxOutput_AllMuxes_{}_{}.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 = fmt::format("apl-gbl-mux-lasp-{:02d}", 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 
RunTileCalibRec.cells
cells
Definition: RunTileCalibRec.py:281
GlobalSim::GlobalLArCellContainer::getMaxCellsPerFeb2
std::size_t getMaxCellsPerFeb2() const
Function to get maximum number of cells per FEB2.
Definition: GlobalLArCellContainer.h:65
GlobalSim::GlobalLArCellContainer::feb2InOverflow
bool feb2InOverflow(const std::string &feb2Key) const
Check if a given FEB2 is in overflow.
Definition: GlobalLArCellContainer.cxx:130
GlobalSim::GlobalLArCellContainer::getOrderedFeb2sForMux
const std::vector< std::string > & getOrderedFeb2sForMux(const std::string &mux) const
Function to get ordered list of FEB2s for a given MUX name.
Definition: GlobalLArCellContainer.cxx:89
ReadCellNoiseFromCool.cell
cell
Definition: ReadCellNoiseFromCool.py:53
vtune_athena.format
format
Definition: vtune_athena.py:14
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::EventInfo_v1::eventNumber
uint64_t eventNumber() const
The current event's event number.
GlobalSim::LArCellMuxAlg::BITWIDTH_MUX_INPUT
static constexpr std::size_t BITWIDTH_MUX_INPUT
Definition: LArCellMuxAlg.h:34
GlobalSim::LArCellMuxAlg::appendBits
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.
Definition: LArCellMuxAlg.cxx:273
GlobalSim::GlobalLArCellContainer::feb2InError
bool feb2InError(const std::string &feb2Key) const
Check if a given FEB2 is in error.
Definition: GlobalLArCellContainer.cxx:137
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
GlobalSim::LArCellMuxAlg::m_gblLArCellContainerKey
SG::ReadHandleKey< GlobalSim::GlobalLArCellContainer > m_gblLArCellContainerKey
Key to the GlobalLArCellContainer.
Definition: LArCellMuxAlg.h:63
GlobalSim::LArCellMuxAlg::FEB2_BITSTREAM_SIZE
static constexpr std::size_t FEB2_BITSTREAM_SIZE
Definition: LArCellMuxAlg.h:32
skel.it
it
Definition: skel.GENtoEVGEN.py:407
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
keylayer_zslicemap.row
row
Definition: keylayer_zslicemap.py:155
GlobalSim::LArCellMuxAlg::BITWIDTH_2SIGMAMASK
static constexpr std::size_t BITWIDTH_2SIGMAMASK
Definition: LArCellMuxAlg.h:33
GlobalSim::GlobalLArCellContainer::getFeb2Keys
const std::unordered_set< std::string > & getFeb2Keys() const
Function to return the full list of FEB2 names.
Definition: GlobalLArCellContainer.h:47
GlobalSim::LArCellMuxAlg::N_WORDS_MUX_HEADER
static constexpr std::size_t N_WORDS_MUX_HEADER
Definition: LArCellMuxAlg.h:36
xAOD::EventInfo_v1::runNumber
uint32_t runNumber() const
The current event's run number.
GlobalSim::LArCellMuxAlg::writeMuxInputBitstream
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.
Definition: LArCellMuxAlg.cxx:64
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:274
GlobalSim::LArCellMuxAlg::writeMuxOutputBitstream
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.
Definition: LArCellMuxAlg.cxx:171
GlobalSim::LArCellMuxAlg::execute
virtual StatusCode execute(const EventContext &) const override
execute function running for every event
Definition: LArCellMuxAlg.cxx:34
GlobalSim
AlgTool to obtain a selection of eFex RoIs read in from the event store.
Definition: dump.h:8
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
GlobalSim::LArCellMuxAlg::m_writeMuxOutputBitstreamToFile
Gaudi::Property< bool > m_writeMuxOutputBitstreamToFile
Flag to enable writing ofMUX output bitstreams (MUX -> GEP) to file.
Definition: LArCellMuxAlg.h:69
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
GlobalSim::GlobalLArCellContainer::getCellsForFeb2
const std::vector< GlobalLArCell * > & getCellsForFeb2(const std::string &feb2) const
Function to get all GlobalLArCells for a given FEB2 name.
Definition: GlobalLArCellContainer.cxx:75
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
GlobalSim::LArCellMuxAlg::N_WORDS_MUX_FOOTER
static constexpr std::size_t N_WORDS_MUX_FOOTER
Definition: LArCellMuxAlg.h:37
PathResolver.h
GlobalSim::LArCellMuxAlg::Feb2BitsetMap
std::map< std::string, std::bitset< FEB2_BITSTREAM_SIZE > > Feb2BitsetMap
Definition: LArCellMuxAlg.h:40
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
GlobalSim::LArCellMuxAlg::BITWIDTH_MUX_OUTPUT
static constexpr std::size_t BITWIDTH_MUX_OUTPUT
Definition: LArCellMuxAlg.h:35
xAOD::bcid
setEventNumber setTimeStamp bcid
Definition: EventInfo_v1.cxx:133
GlobalSim::GlobalLArCellContainer::getMuxForFeb2
const std::string & getMuxForFeb2(const std::string &feb2Key) const
Function to get the associated MUX name for a given FEB2.
Definition: GlobalLArCellContainer.cxx:102
EventInfo.h
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
GlobalSim::GlobalLArCellContainer
Definition: GlobalLArCellContainer.h:22
GlobalSim::GlobalLArCellContainer::muxInOverflow
bool muxInOverflow(const std::string &muxKey) const
Check if a given MUX is in overflow.
Definition: GlobalLArCellContainer.cxx:144
a
TList * a
Definition: liststreamerinfos.cxx:10
GlobalSim::LArCellMuxAlg::m_writeMuxInputBitstreamToFile
Gaudi::Property< bool > m_writeMuxInputBitstreamToFile
Flag to enable writing of MUX input bitstreams (FEB2/LASP -> MUX) to file.
Definition: LArCellMuxAlg.h:66
GlobalSim::LArCellMuxAlg::m_eventInfo
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
Key for the EventInfo object.
Definition: LArCellMuxAlg.h:60
copySelective.target
string target
Definition: copySelective.py:36
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:23
LArCellMuxAlg.h
xAOD::EventInfo_v1::bcid
uint32_t bcid() const
The bunch crossing ID of the event.
GlobalSim::LArCellMuxAlg::initialize
virtual StatusCode initialize() override
initialize function running before first event
Definition: LArCellMuxAlg.cxx:22
GlobalSim::LArCellMuxAlg::assembleBitsetForFeb2
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.
Definition: LArCellMuxAlg.cxx:110
GlobalSim::GlobalLArCellContainer::muxInError
bool muxInError(const std::string &muxKey) const
Check if a given MUX is in error.
Definition: GlobalLArCellContainer.cxx:151