ATLAS Offline Software
Loading...
Searching...
No Matches
MuonRoIByteStreamTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local includes
7
8// Trigger includes
11#include "xAODTrigger/MuonRoI.h"
13// Athena includes
15
16// TDAQ includes
17#include "eformat/SourceIdentifier.h"
18
19// get bitsmasks from common definition source:
21
22#include <span>
23
24using namespace LVL1::MuCTPIBits;
25
28
29// -----------------------------------------------------------------------------
30// Helpers
31// -----------------------------------------------------------------------------
32namespace {
34 constexpr static std::array<size_t,static_cast<size_t>(LVL1::MuCTPIBits::WordType::MAX)> s_wordTypes = {0,1,2,3,4,5};
35 using namespace std::literals::string_view_literals;
37 constexpr static std::array<std::string_view,4> s_sectorNames = {{"Undefined"sv, "Barrel"sv, "Forward"sv, "Endcap"sv}};
39 constexpr static int s_bcidsFullOrbit{3564};
41 constexpr int bcidDiff(int a, int b) {
42 int diff = a - b;
43 while (diff < -s_bcidsFullOrbit/2) {diff += s_bcidsFullOrbit;}
44 while (diff > s_bcidsFullOrbit/2 - 1) {diff -= s_bcidsFullOrbit;}
45 return diff;
46 }
48 constexpr int bcidSum(int a, int b) {
49 int sum = a + b;
50 while (sum < 0) {sum += s_bcidsFullOrbit;}
51 while (sum >= s_bcidsFullOrbit) {sum -= s_bcidsFullOrbit;}
52 return sum;
53 }
55 constexpr uint32_t roiWordAddOfflineRun3Flag (uint32_t candidateWord) {
56 return (candidateWord | 0x1u<<31);
57 }
59 constexpr uint32_t roiWordRemoveOfflineRun3Flag (uint32_t candidateWord) {
60 return (candidateWord & ~(0x1u<<31));
61 }
62}
63
64// -----------------------------------------------------------------------------
65// Constructor
66// -----------------------------------------------------------------------------
68 const std::string& name,
69 const IInterface* parent)
70: base_class(type, name, parent) {}
71
72// -----------------------------------------------------------------------------
73// Initialisation
74// -----------------------------------------------------------------------------
76 ConversionMode mode = getConversionMode(m_roiReadKeys, m_roiWriteKeys, msg());
77 ATH_CHECK(mode!=ConversionMode::Undefined);
78 ATH_CHECK(m_roiWriteKeys.initialize(mode==ConversionMode::Decoding));
79 ATH_CHECK(m_roiReadKeys.initialize(mode==ConversionMode::Encoding));
80 ATH_CHECK(m_MuCTPIL1TopoKeys.initialize(m_doTopo.value() && mode==ConversionMode::Decoding));
81
82 ATH_MSG_DEBUG((mode==ConversionMode::Encoding ? "Encoding" : "Decoding") << " ROB IDs: "
83 << MSG::hex << m_robIds.value() << MSG::dec);
84
85 if (m_doTopo.value() && mode==ConversionMode::Decoding && m_MuCTPIL1TopoKeys.size() != m_roiWriteKeys.size()) {
86 ATH_MSG_ERROR("Number of Topo TOB output containers (" << m_MuCTPIL1TopoKeys.size() << ") "
87 << "does not match the number of RoI output containers (" << m_roiWriteKeys.size() << ")");
88 return StatusCode::FAILURE;
89 }
90
91 m_readoutWindow = mode==ConversionMode::Decoding ? m_roiWriteKeys.size() : m_roiReadKeys.size();
93 ATH_MSG_ERROR("The expected readout window must be 1, 3 or 5, but it is " << m_readoutWindow);
94 return StatusCode::FAILURE;
95 }
96
97 if (m_robIds.value().size() != 1) {
98 ATH_MSG_ERROR("This tool implementation assumes there is exactly one MUCTPI ROB, but "
99 << m_robIds.size() << " were configured");
100 return StatusCode::SUCCESS;
101 }
102
103 CHECK( m_rpcTool.retrieve() );
104 CHECK( m_tgcTool.retrieve() );
105 CHECK( m_thresholdTool.retrieve() );
106 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
107
108 if (m_doTopo.value()) {
109 const std::string barrelFileName = PathResolverFindCalibFile( m_barrelRoIFile );
110 const std::string ecfFileName = PathResolverFindCalibFile( m_ecfRoIFile );
111 const std::string side0LUTFileName = PathResolverFindCalibFile( m_side0LUTFile );
112 const std::string side1LUTFileName = PathResolverFindCalibFile( m_side1LUTFile );
113
114 //CHECK( m_l1topoLUT.initializeBarrelLUT(side0LUTFileName,
115 // side1LUTFileName) );
116 CHECK( m_l1topoLUT.initializeLUT(barrelFileName,
117 ecfFileName,
118 side0LUTFileName,
119 side1LUTFileName) );
120 }
121 return StatusCode::SUCCESS;
122}
123
124// -----------------------------------------------------------------------------
125// BS->xAOD conversion
126// -----------------------------------------------------------------------------
127StatusCode MuonRoIByteStreamTool::convertFromBS(const std::vector<const ROBF*>& vrobf,
128 const EventContext& eventContext) const {
129
131 // Create and record the RoI containers
132 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>> roiHandles = m_roiWriteKeys.makeHandles(eventContext);
133 for (auto& roiHandle : roiHandles) {
134 ATH_CHECK(roiHandle.record(std::make_unique<xAOD::MuonRoIContainer>(),
135 std::make_unique<xAOD::MuonRoIAuxContainer>()));
136 ATH_MSG_DEBUG("Recorded MuonRoIContainer with key " << roiHandle.key());
137 }
138
139 // Create a WriteHandle for L1Topo output
140 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>> topoHandles;
141 if (m_doTopo.value()) {
142 topoHandles = m_MuCTPIL1TopoKeys.makeHandles(eventContext);
143 for (auto& topoHandle : topoHandles) {
144 ATH_CHECK(topoHandle.record(std::make_unique<xAOD::MuonRoIContainer>(),
145 std::make_unique<xAOD::MuonRoIAuxContainer>()));
146 ATH_MSG_DEBUG("Recorded MuCTPIL1Topo with key " << topoHandle.key());
147 }
148 }
149
150 // Find the ROB fragment to decode
151 const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
152 auto it = std::find_if(vrobf.begin(), vrobf.end(), [&sid](const ROBF* rob){return rob->rob_source_id() == sid.code();});
153 if (it == vrobf.end()) {
154 ATH_MSG_DEBUG("No MUCTPI ROB fragment with ID 0x" << std::hex << sid.code() << std::dec
155 << " was found, MuonRoIContainer will be empty");
156 return StatusCode::SUCCESS;
157 }
158
159 // Retrieve the ROD data
160 const ROBF* rob = *it;
161 ATH_MSG_DEBUG("MUCTPI ROB for BCID " << rob->rod_bc_id());
162 const uint32_t ndata = rob->rod_ndata();
163 const uint32_t* const data = rob->rod_data();
164
165 // Initialise monitoring variables
166 Monitored::Scalar<uint32_t> monNumWords{"NumWordsInROD", ndata};
167 std::array<size_t,static_cast<size_t>(LVL1::MuCTPIBits::WordType::MAX)> wordTypeCounts{}; // zero-initialised
168 auto monWordTypeCount = Monitored::Collection("WordTypeCount", wordTypeCounts);
169 auto monWordType = Monitored::Collection("WordType", s_wordTypes);
170 std::vector<int> bcidOffsetsWrtROB; // diffs between BCID in timeslice header and BCID in ROB header
171 auto monBCIDOffsetsWrtROB = Monitored::Collection("BCIDOffsetsWrtROB", bcidOffsetsWrtROB);
172
173 // Check for empty data
174 if (ndata==0) {
175 ATH_MSG_ERROR("Empty ROD data in MUCTPI ROB 0x" << std::hex << sid.code() << std::dec);
176 Monitored::Group(m_monTool, monNumWords);
177 return StatusCode::FAILURE;
178 }
179 ATH_MSG_DEBUG("Starting to decode " << ndata << " ROD words");
180
181 // We don't assume the window size at this point. Instead, we collect the start and size of candidate list for
182 // each time slice and decode them later directly into the right time slice output container.
183 std::vector<std::pair<size_t,size_t>> roiSlices; // v of {start, length}
184 std::vector<std::pair<size_t,size_t>> topoSlices; // v of {start, length}
185
186 // Iterate over ROD words and decode
187 size_t iWord{0};
188 for (const uint32_t word : std::span{data, ndata}) {
189 ATH_MSG_DEBUG("MUCTPI raw word " << iWord << ": 0x" << std::hex << word << std::dec);
191 ++wordTypeCounts[static_cast<size_t>(wordType)];
192
193 switch (wordType) {
195 const auto header = LVL1::MuCTPIBits::timesliceHeader(word);
196 ATH_MSG_DEBUG("This is a timeslice header word with BCID=" << header.bcid
197 << ", NTOB=" << header.tobCount << ", NCAND=" << header.candCount);
198 // create new RoI words slice
199 roiSlices.emplace_back(0,0);
200 // create new Topo words slice
201 topoSlices.emplace_back(0,0);
202 // monitor BCID offset
203 bcidOffsetsWrtROB.push_back(bcidDiff(header.bcid, rob->rod_bc_id()));
204 break;
205 }
207 uint32_t tmNum = LVL1::MuCTPIBits::multiplicityWordNumber(word);
208 ATH_MSG_DEBUG("This is a multiplicity word #" << tmNum);
209 break;
210 }
212 ATH_MSG_DEBUG("This is a RoI candidate word");
213 if (roiSlices.empty()) {
214 ATH_MSG_ERROR("Unexpected data format - found candidate word before any timeslice header");
215 Monitored::Group(m_monTool, monNumWords, monWordType, monWordTypeCount, monBCIDOffsetsWrtROB);
216 return StatusCode::FAILURE;
217 }
218 // advance slice edges
219 std::pair<size_t,size_t>& slice = roiSlices.back();
220 if (slice.first==0) slice.first = iWord;
221 slice.second = iWord - slice.first + 1;
222 break;
223 }
225 ATH_MSG_DEBUG("This is a Topo TOB word");
226 if (not m_doTopo.value()) {break;}
227 if (topoSlices.empty()) {
228 ATH_MSG_ERROR("Unexpected data format - found Topo TOB word before any timeslice header");
229 return StatusCode::FAILURE;
230 }
231 // advance slice edges
232 std::pair<size_t,size_t>& slice = topoSlices.back();
233 if (slice.first==0) slice.first = iWord;
234 slice.second = iWord - slice.first + 1;
235 break;
236 }
238 ATH_MSG_DEBUG("This is a status word");
239 std::vector<size_t> errorBits = LVL1::MuCTPIBits::getDataStatusWordErrors(word);
240 // TODO: Decide on the action in case of errors, ATR-25069
241 if (!errorBits.empty()) {
242 ATH_MSG_DEBUG("MUCTPI ROD data flagged with errors. The data status word is 0x" << std::hex << word << std::dec);
243 for (size_t bit : errorBits) {
244 ATH_MSG_DEBUG("Error bit " << bit << ": " << LVL1::MuCTPIBits::DataStatusWordErrors.at(bit));
245 }
246 auto monErrorBits = Monitored::Collection("DataStatusWordErrors", errorBits);
247 Monitored::Group(m_monTool, monErrorBits);
248 }
249 break;
250 }
251 default: {
252 ATH_MSG_ERROR("The MUCTPI word 0x" << std::hex << word << std::dec << " does not match any known word type");
253 Monitored::Group(m_monTool, monNumWords, monWordType, monWordTypeCount, monBCIDOffsetsWrtROB);
254 return StatusCode::FAILURE;
255 }
256 }
257 ++iWord;
258 } // Loop over all ROD words
259
260 // Fill data format monitoring histograms
261 Monitored::Group(m_monTool, monNumWords, monWordType, monWordTypeCount, monBCIDOffsetsWrtROB);
262
263 // Validate the number of slices and decode the RoI candidate words in each time slice
264 const size_t nSlices{roiSlices.size()};
265 const size_t nOutputSlices{static_cast<size_t>(m_readoutWindow)};
266 if (nSlices > nOutputSlices) {
267 ATH_MSG_ERROR("Found " << nSlices << " time slices, but only " << m_readoutWindow << " outputs are configured");
268 return StatusCode::FAILURE;
269 } else if (nSlices != static_cast<size_t>(rob->rod_detev_type())) {
270 ATH_MSG_ERROR("Found " << nSlices << " time slices, but Detector Event Type word indicates there should be "
271 << rob->rod_detev_type());
272 return StatusCode::FAILURE;
273 } else if (nSlices!=1 && nSlices!=3 && nSlices!=5) {
274 ATH_MSG_ERROR("Expected 1, 3 or 5 time slices but found " << nSlices);
275 return StatusCode::FAILURE;
276 }
277 const size_t outputOffset = nOutputSlices/2 - nSlices/2;
278 ATH_CHECK(decodeRoiSlices(data, roiSlices, roiHandles, outputOffset, eventContext));
279
280 // Validate the number of slices and decode the Topo TOB words in each time slice
281 if (m_doTopo.value()) {
282 const size_t nTopoSlices{topoSlices.size()};
283 const size_t nTopoOutputSlices{static_cast<size_t>(m_readoutWindow)};
284 if (nTopoSlices > nTopoOutputSlices) {
285 ATH_MSG_ERROR("Found " << nTopoSlices << " TOPO TOB time slices, but only " << m_readoutWindow << " outputs are configured");
286 return StatusCode::FAILURE;
287 } else if (nTopoSlices != static_cast<size_t>(rob->rod_detev_type())) {
288 ATH_MSG_ERROR("Found " << nTopoSlices << " time slices, but Detector Event Type word indicates there should be "
289 << rob->rod_detev_type());
290 return StatusCode::FAILURE;
291 } else if (nTopoSlices!=1 && nTopoSlices!=3 && nTopoSlices!=5) {
292 ATH_MSG_ERROR("Expected 1, 3 or 5 time slices but found " << nTopoSlices);
293 return StatusCode::FAILURE;
294 }
295 const size_t topoOutputOffset = nTopoOutputSlices/2 - nTopoSlices/2;
296 ATH_CHECK(decodeTopoSlices(data, topoSlices, topoHandles, topoOutputOffset, eventContext));
297 }
298
299 // Output monitoring
300 short bcOffset{static_cast<short>(5/2 - m_readoutWindow/2 - 2)};
301 auto topoHandleIt = topoHandles.begin();
302 for (auto& roiHandle : roiHandles) {
303 auto& topoHandle = *topoHandleIt;
304 Monitored::Scalar<short> monBCOffset{"BCOffset", bcOffset};
305 Monitored::Scalar<size_t> monNumRoIs{"NumOutputRoIs", roiHandle->size()};
306 if (m_doTopo.value()) {
307 Monitored::Scalar<size_t> monNumTopo{"NumOutputTopoTOBs", topoHandle->size()};
308 Monitored::Scalar<int> monNumDiff{"NumOutputDiffRoITopo", static_cast<int>(monNumRoIs)-static_cast<int>(monNumTopo)};
309 ATH_MSG_DEBUG("Decoded " << monNumRoIs << " RoIs into the " << roiHandle.key() << " container "
310 "and " << monNumTopo << " Topo TOBs into the " << topoHandle.key() << " container");
311 Monitored::Group(m_monTool, monBCOffset, monNumRoIs, monNumTopo, monNumDiff);
312 ++topoHandleIt;
313 } else {
314 ATH_MSG_DEBUG("Decoded " << monNumRoIs << " RoIs into the " << roiHandle.key() << " container");
315 Monitored::Group(m_monTool, monBCOffset, monNumRoIs);
316 }
317 ++bcOffset;
318 }
319
320 return StatusCode::SUCCESS;
321 }
322
323 else{ //Just decode the MUCTPI
324
325 // Create a WriteHandle for L1Topo output
326 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>> topoHandles;
327 if (m_doTopo.value()) {
328 topoHandles = m_MuCTPIL1TopoKeys.makeHandles(eventContext);
329 for (auto& topoHandle : topoHandles) {
330 ATH_CHECK(topoHandle.record(std::make_unique<xAOD::MuonRoIContainer>(),
331 std::make_unique<xAOD::MuonRoIAuxContainer>()));
332 ATH_MSG_DEBUG("Recorded MuCTPIL1Topo with key " << topoHandle.key());
333 }
334 }
335
336 // Find the ROB fragment to decode
337 const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
338 auto it = std::find_if(vrobf.begin(), vrobf.end(), [&sid](const ROBF* rob){return rob->rob_source_id() == sid.code();});
339 if (it == vrobf.end()) {
340 ATH_MSG_DEBUG("No MUCTPI ROB fragment with ID 0x" << std::hex << sid.code() << std::dec
341 << " was found, MuonRoIContainer will be empty");
342 return StatusCode::SUCCESS;
343 }
344
345 // Retrieve the ROD data
346 const ROBF* rob = *it;
347 ATH_MSG_DEBUG("MUCTPI ROB for BCID " << rob->rod_bc_id());
348 const uint32_t ndata = rob->rod_ndata();
349 const uint32_t* const data = rob->rod_data();
350
351 // Initialise monitoring variables
352 Monitored::Scalar<uint32_t> monNumWords{"NumWordsInROD", ndata};
353 std::array<size_t,static_cast<size_t>(LVL1::MuCTPIBits::WordType::MAX)> wordTypeCounts{}; // zero-initialised
354 auto monWordTypeCount = Monitored::Collection("WordTypeCount", wordTypeCounts);
355 auto monWordType = Monitored::Collection("WordType", s_wordTypes);
356 std::vector<int> bcidOffsetsWrtROB; // diffs between BCID in timeslice header and BCID in ROB header
357 auto monBCIDOffsetsWrtROB = Monitored::Collection("BCIDOffsetsWrtROB", bcidOffsetsWrtROB);
358
359 // Check for empty data
360 if (ndata==0) {
361 ATH_MSG_ERROR("Empty ROD data in MUCTPI ROB 0x" << std::hex << sid.code() << std::dec);
362 return StatusCode::FAILURE;
363 }
364 ATH_MSG_DEBUG("Starting to decode " << ndata << " ROD words");
365
366 // We don't assume the window size at this point. Instead, we collect the start and size of candidate list for
367 // each time slice and decode them later directly into the right time slice output container.
368 std::vector<std::pair<size_t,size_t>> roiSlices; // v of {start, length}
369 std::vector<std::pair<size_t,size_t>> topoSlices; // v of {start, length}
370
371 // Iterate over ROD words and decode
372 size_t iWord{0};
373 for (const uint32_t word : CxxUtils::span{data, ndata}) {
374 ATH_MSG_DEBUG("MUCTPI raw word " << iWord << ": 0x" << std::hex << word << std::dec);
376 ++wordTypeCounts[static_cast<size_t>(wordType)];
377
378 switch (wordType) {
380 const auto header = LVL1::MuCTPIBits::timesliceHeader(word);
381 ATH_MSG_DEBUG("This is a timeslice header word with BCID=" << header.bcid
382 << ", NTOB=" << header.tobCount << ", NCAND=" << header.candCount);
383 // create new RoI words slice
384 roiSlices.emplace_back(0,0);
385 // create new Topo words slice
386 topoSlices.emplace_back(0,0);
387 // monitor BCID offset
388 bcidOffsetsWrtROB.push_back(bcidDiff(header.bcid, rob->rod_bc_id()));
389 break;
390 }
392 uint32_t tmNum = LVL1::MuCTPIBits::multiplicityWordNumber(word);
393 ATH_MSG_DEBUG("This is a multiplicity word #" << tmNum);
394 break;
395 }
397 ATH_MSG_DEBUG("This is a RoI candidate word");
398 if (roiSlices.empty()) {
399 ATH_MSG_ERROR("Unexpected data format - found candidate word before any timeslice header");
400 return StatusCode::FAILURE;
401 }
402 // advance slice edges
403 std::pair<size_t,size_t>& slice = roiSlices.back();
404 if (slice.first==0) slice.first = iWord;
405 slice.second = iWord - slice.first + 1;
406 break;
407 }
409 ATH_MSG_DEBUG("This is a Topo TOB word");
410 if (not m_doTopo.value()) {break;}
411 if (topoSlices.empty()) {
412 ATH_MSG_ERROR("Unexpected data format - found Topo TOB word before any timeslice header");
413 return StatusCode::FAILURE;
414 }
415 // advance slice edges
416 std::pair<size_t,size_t>& slice = topoSlices.back();
417 if (slice.first==0) slice.first = iWord;
418 slice.second = iWord - slice.first + 1;
419 break;
420 }
422 ATH_MSG_DEBUG("This is a status word");
423 std::vector<size_t> errorBits = LVL1::MuCTPIBits::getDataStatusWordErrors(word);
424 // TODO: Decide on the action in case of errors, ATR-25069
425 if (!errorBits.empty()) {
426 ATH_MSG_DEBUG("MUCTPI ROD data flagged with errors. The data status word is 0x" << std::hex << word << std::dec);
427 for (size_t bit : errorBits) {
428 ATH_MSG_DEBUG("Error bit " << bit << ": " << LVL1::MuCTPIBits::DataStatusWordErrors.at(bit));
429 }
430 auto monErrorBits = Monitored::Collection("DataStatusWordErrors", errorBits);
431 }
432 break;
433 }
434 default: {
435 ATH_MSG_ERROR("The MUCTPI word 0x" << std::hex << word << std::dec << " does not match any known word type");
436 return StatusCode::FAILURE;
437 }
438 }
439 ++iWord;
440 } // Loop over all ROD words
441
442 // Validate the number of slices and decode the RoI candidate words in each time slice
443 const size_t nSlices{roiSlices.size()};
444 const size_t nOutputSlices{static_cast<size_t>(m_readoutWindow)};
445 if (nSlices > nOutputSlices) {
446 ATH_MSG_ERROR("Found " << nSlices << " time slices, but only " << m_readoutWindow << " outputs are configured");
447 return StatusCode::FAILURE;
448 } else if (nSlices != static_cast<size_t>(rob->rod_detev_type())) {
449 ATH_MSG_ERROR("Found " << nSlices << " time slices, but Detector Event Type word indicates there should be "
450 << rob->rod_detev_type());
451 return StatusCode::FAILURE;
452 } else if (nSlices!=1 && nSlices!=3 && nSlices!=5) {
453 ATH_MSG_ERROR("Expected 1, 3 or 5 time slices but found " << nSlices);
454 return StatusCode::FAILURE;
455 }
456
457 // Validate the number of slices and decode the Topo TOB words in each time slice
458 if (m_doTopo.value()) {
459 const size_t nTopoSlices{topoSlices.size()};
460 const size_t nTopoOutputSlices{static_cast<size_t>(m_readoutWindow)};
461 if (nTopoSlices > nTopoOutputSlices) {
462 ATH_MSG_ERROR("Found " << nTopoSlices << " TOPO TOB time slices, but only " << m_readoutWindow << " outputs are configured");
463 return StatusCode::FAILURE;
464 } else if (nTopoSlices != static_cast<size_t>(rob->rod_detev_type())) {
465 ATH_MSG_ERROR("Found " << nTopoSlices << " time slices, but Detector Event Type word indicates there should be "
466 << rob->rod_detev_type());
467 return StatusCode::FAILURE;
468 } else if (nTopoSlices!=1 && nTopoSlices!=3 && nTopoSlices!=5) {
469 ATH_MSG_ERROR("Expected 1, 3 or 5 time slices but found " << nTopoSlices);
470 return StatusCode::FAILURE;
471 }
472 const size_t topoOutputOffset = nTopoOutputSlices/2 - nTopoSlices/2;
473 ATH_CHECK(decodeTopoSlices(data, topoSlices, topoHandles, topoOutputOffset, eventContext));
474 }
475
476 return StatusCode::SUCCESS;
477 }
478
479}
480
481// -----------------------------------------------------------------------------
482// xAOD->BS conversion
483// -----------------------------------------------------------------------------
484StatusCode MuonRoIByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf,
485 const xAOD::TrigCompositeContainer* /*tc*/,
486 const EventContext& eventContext) {
487 // Retrieve the RoI containers and determine how many time slices will be encoded
488 std::vector<SG::ReadHandle<xAOD::MuonRoIContainer>> handles = m_roiReadKeys.makeHandles(eventContext);
489 int nSlices{0};
490 int iHandle{0};
491 size_t rodSize{0};
492 for (auto& handle : handles) {
493 ATH_CHECK(handle.isValid());
494 if (!handle->empty()) {
495 rodSize += handle->size();
496 nSlices = std::max(nSlices, 1+2*std::abs(m_readoutWindow/2 - iHandle));
497 }
498 ++iHandle;
499 }
500 if (nSlices==0) {
501 ATH_MSG_DEBUG("There are no muon RoIs to encode in this event");
502 // Force at least the triggered BC slice to be encoded
503 nSlices = 1;
504 }
505
506 // Calculate the number of words we need to allocate (candidate words already counted above)
507 rodSize += 4*nSlices + 1; // 1 timeslice header per slice, 3 multiplicity words per slice, 1 status word
508 ATH_MSG_DEBUG("Going to encode " << nSlices << " time slices into " << rodSize << " ROD words");
509
510 // Clear BS data cache and allocate new data array
511 clearCache(eventContext);
512 uint32_t* data = newRodData(eventContext, rodSize); // Owned by the cache
513
514 // Initialise a few monitoring variables
515 Monitored::Scalar<size_t> monNumWords{"NumWordsInROD", rodSize};
516 std::array<size_t,static_cast<size_t>(LVL1::MuCTPIBits::WordType::MAX)> wordTypeCounts{}; // zero-initialised
517 auto monWordTypeCount = Monitored::Collection("WordTypeCount", wordTypeCounts);
518 auto monWordType = Monitored::Collection("WordType", s_wordTypes);
519 std::vector<int> bcidOffsetsWrtROB; // diffs between BCID in timeslice header and BCID in ROB header
520 auto monBCIDOffsetsWrtROB = Monitored::Collection("BCIDOffsetsWrtROB", bcidOffsetsWrtROB);
521 auto monitorCandidate = [](const auto& monTool, const xAOD::MuonRoI& roi){
522 // Fill per-candidate monitoring histograms
523 const uint32_t word = roi.roiWord();
524 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
526 Monitored::Scalar<SubsysID_ut> monSubsysID{"SubsysID", static_cast<SubsysID_ut>(subsysID)};
527 std::string sectorName{s_sectorNames[static_cast<size_t>(subsysID)]};
528 Monitored::Scalar<double> monEta{"roiEta_"+sectorName, roi.eta()};
529 Monitored::Scalar<double> monPhi{"roiPhi_"+sectorName, roi.phi()};
530 Monitored::Group(monTool, monSubsysID, monEta, monPhi);
531 };
532
533 // Fill the data words
534 auto inputIt = handles.begin();
535 std::advance(inputIt, m_readoutWindow/2 - nSlices/2);
536 size_t iWord{0};
537 for (int iSlice=0; iSlice<nSlices; ++iSlice, ++inputIt) {
538 // Timeslice header
539 uint32_t bcid = bcidSum(eventContext.eventID().bunch_crossing_id(), iSlice - nSlices/2);
540 static constexpr uint32_t tobCount = 0; // Filling Topo words not implemented
541 uint32_t candCount = (*inputIt)->size();
542 data[iWord++] = LVL1::MuCTPIBits::timesliceHeader(bcid, tobCount, candCount);
543 ++wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Timeslice)];
544 bcidOffsetsWrtROB.push_back(bcidDiff(bcid, eventContext.eventID().bunch_crossing_id()));
545 ATH_MSG_DEBUG("Added timeslice header word with BCID=" << bcid << ", NTOB=" << tobCount << ", NCAND=" << candCount);
546
547 // Multiplicity words
548 std::array<uint32_t,3> multiplicityWords = LVL1::MuCTPIBits::multiplicityWords(0, 0, false); // Multiplicity words content not implemented
549 for (const uint32_t word : multiplicityWords) {
550 data[iWord++] = word;
551 }
552 wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Multiplicity)] += multiplicityWords.size();
553 ATH_MSG_DEBUG("Added " << multiplicityWords.size() << " multiplicity words");
554
555 // Candidate words
556 for (const xAOD::MuonRoI* roi : **inputIt) {
557 monitorCandidate(m_monTool, *roi);
558 data[iWord++] = roiWordRemoveOfflineRun3Flag(roi->roiWord());
559 ATH_MSG_DEBUG("Added RoI word 0x" << std::hex << roi->roiWord() << std::dec);
560 }
561 wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Candidate)] += (*inputIt)->size();
562 ATH_MSG_DEBUG("Added " << (*inputIt)->size() << " candidate words");
563 }
564
565 // Status word
567 ++wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Status)];
568 ATH_MSG_DEBUG("Added the data status word");
569
570 // Fill data format monitoring histograms
571 Monitored::Group(m_monTool, monNumWords, monWordType, monWordTypeCount, monBCIDOffsetsWrtROB);
572
573 // Check that we filled all words
574 if (iWord!=rodSize) {
575 ATH_MSG_ERROR("Expected to fill " << rodSize << " ROD words but filled " << iWord);
576 return StatusCode::FAILURE;
577 }
578
579 // Create a ROBFragment containing the ROD words
580 const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
581 vrobf.push_back(newRobFragment(eventContext, sid.code(), rodSize, data, nSlices));
582
583 return StatusCode::SUCCESS;
584}
585
586// -----------------------------------------------------------------------------
587// Helper for BS->xAOD conversion of RoI candidate words
588// -----------------------------------------------------------------------------
590 const std::vector<std::pair<size_t,size_t>>& slices,
591 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>>& handles,
592 size_t outputOffset,
593 const EventContext& eventContext) const {
594 auto outputIt = handles.begin();
595 std::advance(outputIt, outputOffset);
596 for (const auto& [sliceStart,sliceSize] : slices) {
597 for (const uint32_t word : std::span{data+sliceStart, sliceSize}) {
598 ATH_MSG_DEBUG("Decoding RoI word 0x" << std::hex << word << std::dec << " into the " << outputIt->key() << " container");
599
600 // Create a new xAOD::MuonRoI object for this candidate in the output container
601 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
602
603 // Decode eta/phi information using the right tool for the subsystem
606 switch (subsysID) {
607 case LVL1::MuCTPIBits::SubsysID::Endcap: // same for Endcap and Forward
609 ATH_MSG_DEBUG("This is an Endcap/Forward candidate, calling the " << m_tgcTool.typeAndName());
610 ATH_CHECK( m_tgcTool->roiData(word,roiData) );
611 break;
612 }
614 ATH_MSG_DEBUG("This is a Barrel candidate, calling the " << m_rpcTool.typeAndName());
615 ATH_CHECK( m_rpcTool->roiData(word,roiData) );
616 break;
617 }
618 default: {
619 ATH_MSG_ERROR("Failed to determine Sector ID from RoI word 0x" << std::hex << word << std::dec);
620 return StatusCode::FAILURE;
621 }
622 }
623
624 // Get the threshold decisions to find the lowest pt threshold passed
625 // This is required by xAOD::MuonRoI::initialize() but not used for HLT seeding (a threshold pattern bit mask is used instead)
626 const std::pair<std::string, double> minThrInfo = m_thresholdTool->getMinThresholdNameAndValue(
627 m_thresholdTool->getThresholdDecisions(word, eventContext),
628 roiData.eta());
629
630 // Fill the xAOD::MuonRoI object
631 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(word),
632 roiData.eta(),
633 roiData.phi(),
634 minThrInfo.first,
635 minThrInfo.second);
636
637 // Fill per-candidate monitoring histograms
638 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
639 Monitored::Scalar<SubsysID_ut> monSubsysID{"SubsysID", static_cast<SubsysID_ut>(subsysID)};
640 std::string sectorName{s_sectorNames[static_cast<size_t>(subsysID)]};
641 Monitored::Scalar<double> monEta{"roiEta_"+sectorName, roiData.eta()};
642 Monitored::Scalar<double> monPhi{"roiPhi_"+sectorName, roiData.phi()};
643 Monitored::Group(m_monTool, monSubsysID, monEta, monPhi);
644 }
645 ++outputIt;
646 } // Loop over RoI candidate time slices
647
648 return StatusCode::SUCCESS;
649}
650
651// -----------------------------------------------------------------------------
652// Helper for BS->transient conversion of Topo TOB words
653// -----------------------------------------------------------------------------
655 const std::vector<std::pair<size_t,size_t>>& slices,
656 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>>& handles,
657 size_t outputOffset,
658 const EventContext& /*eventContext*/) const {
659 int toposliceiterator = -1;
660 int nomBCID_slice = slices.size() / 2 ;
661 int topobcidOffset = 0;
662 unsigned short subsystem = 0;
663
664 float eta=0, phi=0;
665 unsigned int et=0;
666 //in case something is found to not be correctly decoded by the L1Topo group - can clean this extra-debug printouts later if wished
667 constexpr static bool local_topo_debug{true};
668
669 const TrigConf::L1Menu * l1menu = nullptr;
670 ATH_CHECK( detStore()->retrieve(l1menu) );
671
672 const auto & exMU = l1menu->thrExtraInfo().MU();
673 auto tgcPtValues = exMU.knownTgcPtValues();
674
675 auto outputIt = handles.begin();
676 std::advance(outputIt, outputOffset);
677 // Loop over Topo candidate time slices
678 for (const auto& [sliceStart,sliceSize] : slices) {
679 toposliceiterator++;
680 for (const uint32_t word : std::span{data+sliceStart, sliceSize}) {
681 //the cand usage should be optimised!
682 std::stringstream sectorName;
683 subsystem = 0;
684
685 topobcidOffset = toposliceiterator - nomBCID_slice;
686
687 // Create a new xAOD::MuonRoI object for this candidate in the output container
688 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
689
690 ATH_MSG_DEBUG("MuCTPIL1Topo: Decoding Topo word 0x" << std::hex << word << std::dec << " into the " << outputIt->key() << " container");
691
692 // NOTE the convention:
693 // HEMISPHERE 0: C-side (-) / 1: A-side (+)
694 // Det (bits): Barrel: 00 - EC: 1X - FW: 01
695 const auto topoheader = LVL1::MuCTPIBits::topoHeader(word);
696 if (local_topo_debug) {
697 ATH_MSG_DEBUG("MuCTPIL1Topo: TOPOSLICE data: " <<data << " sliceStart: "<<sliceStart<< " sliceSize: " <<sliceSize );
698 ATH_MSG_DEBUG("MuCTPIL1Topo word: 0x" << std::hex << word << std::dec );
699 ATH_MSG_DEBUG("MuCTPIL1Topo word: 0b" << std::bitset<32>(word) );
700 }
701 // Build the sector name
702 // topoheader.det is the direct WORD content, but here later in m_l1topoLUT.getCoordinates the definition is different ... see the subsystem settings below
703 if (topoheader.det == 0) {
704 sectorName<<"B";
705 subsystem = 0;
706 }
707 else if (topoheader.det == 1) {
708 sectorName<<"F";
709 subsystem = 2;
710 }
711 else if (topoheader.det == 2) {
712 sectorName<<"E";
713 subsystem = 1;
714 }
715 if (topoheader.hemi) sectorName << "A";
716 else sectorName<< "C";
717 sectorName << topoheader.sec;
718 // End of: Build the sector name
719
720 if (local_topo_debug) {
721 ATH_MSG_DEBUG("MuCTPIL1Topo det: " << topoheader.det);
722 ATH_MSG_DEBUG("MuCTPIL1Topo hemi: " << topoheader.hemi );
723 ATH_MSG_DEBUG("MuCTPIL1Topo sector: " << sectorName.str() );
724 ATH_MSG_DEBUG("MuCTPIL1Topo etacode: " << topoheader.etacode );
725 ATH_MSG_DEBUG("MuCTPIL1Topo phicode: " << topoheader.phicode );
726 ATH_MSG_DEBUG("MuCTPIL1Topo sec: " << topoheader.sec );
727 ATH_MSG_DEBUG("MuCTPIL1Topo roi: " << topoheader.roi );
728 ATH_MSG_DEBUG("MuCTPIL1Topo pt: " << topoheader.pt );
729 }
730
731 if (subsystem == 0) // Barrel
732 {
733 //for barrel topoheader.roi is always 0, so we need to reconstruct it...
734 unsigned short roi = m_l1topoLUT.getBarrelROI(topoheader.hemi, topoheader.sec, topoheader.barrel_eta_lookup, topoheader.barrel_phi_lookup);
735 LVL1MUCTPIPHASE1::L1TopoCoordinates coord = m_l1topoLUT.getCoordinates(topoheader.hemi ,subsystem ,topoheader.sec ,roi);
736 if (local_topo_debug) {
737 ATH_MSG_DEBUG("MuCTPIL1Topo: Barrel decoding");
738 ATH_MSG_DEBUG("MuCTPIL1Topo barrel_eta_lookup: " << topoheader.barrel_eta_lookup );
739 ATH_MSG_DEBUG("MuCTPIL1Topo barrel_phi_lookup: " << topoheader.barrel_phi_lookup );
740 ATH_MSG_DEBUG("MuCTPIL1Topo eta value: " << coord.eta);
741 ATH_MSG_DEBUG("MuCTPIL1Topo phi value: " << coord.phi);
742 }
743
744 // Documentation / translation for the flag setting below
745 if (local_topo_debug) {
746 ATH_MSG_DEBUG("MuCTPIL1Topo phiOvl(0): " << topoheader.flag0);
747 ATH_MSG_DEBUG("MuCTPIL1Topo is2cand(1):" << topoheader.flag1);
748 }
749
750 // Create RoI Word
751 uint32_t roiWord = 0;
752 roiWord |= (static_cast<uint32_t>(topoheader.pt/2) & RUN3_CAND_PT_MASK) << RUN3_CAND_PT_SHIFT;
753 roiWord |= (static_cast<uint32_t>(topoheader.flag1) & ROI_OVERFLOW_MASK) << RUN3_ROI_OVERFLOW_SHIFT;
754
755 // Fill the xAOD::MuonRoI object
756 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
757 coord.eta,
758 coord.phi,
759 "",
760 tgcPtValues[topoheader.pt]);
761 et = topoheader.pt;
762 eta = coord.eta;
763 phi = coord.phi;
764 } // Barrel
765 else { // EC and FWD
766 LVL1MUCTPIPHASE1::L1TopoCoordinates coord = m_l1topoLUT.getCoordinates(topoheader.hemi ,subsystem ,topoheader.sec ,topoheader.roi);
767 if (local_topo_debug) {
768 ATH_MSG_DEBUG("MuCTPIL1Topo: EC / FWD decoding");
769 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta " << coord.eta);
770 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi " << coord.phi);
771 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta_min " << coord.eta_min);
772 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta_max " << coord.eta_max);
773 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi_min " << coord.phi_min);
774 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi_max " << coord.phi_max);
775 ATH_MSG_DEBUG("MuCTPIL1Topo coord.ieta " << coord.ieta);
776 ATH_MSG_DEBUG("MuCTPIL1Topo coord.iphi " << coord.iphi);
777 }
778
779 // Documentation / translation for the flag setting below
780 if (local_topo_debug) {
781 ATH_MSG_DEBUG("MuCTPIL1Topo charge (0):" << topoheader.flag0);
782 ATH_MSG_DEBUG("MuCTPIL1Topo bw2or3 (1):" << topoheader.flag1);
783 ATH_MSG_DEBUG("MuCTPIL1Topo innerCoin (2):" << topoheader.flag2);
784 ATH_MSG_DEBUG("MuCTPIL1Topo goodMF (3):" << topoheader.flag3);
785 }
786 // Create RoI Word
787 uint32_t roiWord = 0;
788 roiWord |= (static_cast<uint32_t>(topoheader.pt) & RUN3_CAND_PT_MASK) << RUN3_CAND_PT_SHIFT;
789 // Only needed to tell this is TGC
791 if (topoheader.flag0) {roiWord |= (0x1) << RUN3_CAND_TGC_CHARGE_SIGN_SHIFT;}
792 if (topoheader.flag1) {roiWord |= (0x1) << RUN3_CAND_TGC_BW2OR3_SHIFT;}
793 if (topoheader.flag2) {roiWord |= (0x1) << RUN3_CAND_TGC_INNERCOIN_SHIFT;}
794 if (topoheader.flag3) {roiWord |= (0x1) << RUN3_CAND_TGC_GOODMF_SHIFT;}
795
796 // Fill the xAOD::MuonRoI object
797 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
798 coord.eta,
799 coord.phi,
800 "",
801 tgcPtValues[topoheader.pt]);
802
803 et = topoheader.pt;
804 eta = coord.eta;
805 phi = coord.phi;
806 }// EC and FWD
807
808 ATH_MSG_DEBUG("MuCTPIL1Topo: L1Topo output recorded to StoreGate with key " << outputIt->key() << " and bcidOffset: " << topobcidOffset);
809
810 // Fill per-candidate monitoring histograms
811 using SubsysID_t = LVL1::MuCTPIBits::SubsysID;
812 using SubsysID_ut = std::underlying_type_t<SubsysID_t>;
813 static constexpr std::array<SubsysID_t , 3> systems{SubsysID_t::Barrel, SubsysID_t::Endcap, SubsysID_t::Forward};
814 SubsysID_t subsysID = systems[subsystem];
815 Monitored::Scalar<SubsysID_ut> monSubsysID{"topoSubsysID", static_cast<SubsysID_ut>(subsysID)};
816 std::string subsysName{s_sectorNames[static_cast<size_t>(subsysID)]};
817 Monitored::Scalar<float> monEta{"topoEta_"+subsysName, eta};
818 Monitored::Scalar<float> monPhi{"topoPhi_"+subsysName, phi};
819 Monitored::Scalar<unsigned int> monPtThr{"topoPtThreshold_"+subsysName, et};
820 Monitored::Group(m_monTool, monSubsysID, monEta, monPhi, monPtThr);
821 }
822 ++outputIt;
823 } // Loop over Topo candidate time slices
824
825 return StatusCode::SUCCESS;
826}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment ROBF
#define CHECK(...)
Evaluate an expression and check for errors.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
double coord
Type of coordination system.
static Double_t a
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
Simplified version of the C++20 std::span.
Definition span.h:61
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
SG::ReadHandleKeyArray< xAOD::MuonRoIContainer > m_roiReadKeys
MuonRoIByteStreamTool(const std::string &type, const std::string &name, const IInterface *parent)
ToolHandle< LVL1::ITrigThresholdDecisionTool > m_thresholdTool
SG::WriteHandleKeyArray< xAOD::MuonRoIContainer > m_MuCTPIL1TopoKeys
short int m_readoutWindow
Expected readout window size calculated from the size of data handle key arrays, should be 1,...
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const xAOD::TrigCompositeContainer *tc, const EventContext &eventContext) override
xAOD->BS conversion
const std::string m_barrelRoIFile
Gaudi::Property< bool > m_writeDecodedMuonRoIs
SG::WriteHandleKeyArray< xAOD::MuonRoIContainer > m_roiWriteKeys
const std::string m_side0LUTFile
ToolHandle< LVL1::ITrigT1MuonRecRoiTool > m_rpcTool
const std::string m_side1LUTFile
Gaudi::Property< std::vector< uint32_t > > m_robIds
ToolHandle< LVL1::ITrigT1MuonRecRoiTool > m_tgcTool
virtual StatusCode initialize() override
StatusCode decodeRoiSlices(const uint32_t *data, const std::vector< std::pair< size_t, size_t > > &slices, std::vector< SG::WriteHandle< xAOD::MuonRoIContainer > > &handles, size_t outputOffset, const EventContext &eventContext) const
Process raw RoI candidate words in all slices, convert and fill the output EDM.
virtual StatusCode convertFromBS(const std::vector< const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment * > &vrobf, const EventContext &eventContext) const override
BS->xAOD conversion.
ToolHandle< GenericMonitoringTool > m_monTool
StatusCode decodeTopoSlices(const uint32_t *data, const std::vector< std::pair< size_t, size_t > > &slices, std::vector< SG::WriteHandle< xAOD::MuonRoIContainer > > &handles, size_t outputOffset, const EventContext &eventContext) const
Process raw Topo TOB words in all slices, convert and fill the output EDM.
Gaudi::Property< bool > m_doTopo
const std::string m_ecfRoIFile
LVL1MUCTPIPHASE1::L1TopoLUT m_l1topoLUT
Muctpi Topo TOB word lookup table interface: hemi, detector, sector, roi(EC&FWD)/lut-numbers(Barrel) ...
L1 menu configuration.
Definition L1Menu.h:28
static constexpr uint32_t FORWARD_ADDRESS_MASK
Bit in the candidate's address turned on for forward candidates.
Definition MuCTPI_Bits.h:89
constexpr uint32_t multiplicityWordNumber(uint32_t word)
Decode the index of the multitpicity word, which is 1, 2, or 3.
static constexpr uint32_t RUN3_CAND_PT_MASK
Mask for extracting the pT threshold passed by the candidate from the data word.
Definition MuCTPI_Bits.h:62
static constexpr uint32_t RUN3_CAND_TGC_GOODMF_SHIFT
Position of the bit specifying if RoI is in a good b-field region (1=good, 0=bad).
static constexpr std::array< std::string_view, 16 > DataStatusWordErrors
static constexpr uint32_t RUN3_CAND_SECTOR_ADDRESS_SHIFT
Position of the muon candidate's address in the data word.
Definition MuCTPI_Bits.h:82
static constexpr uint32_t ROI_OVERFLOW_MASK
Mask for the bit showing if more than one muon candidates were in the sector RoI.
Definition MuCTPI_Bits.h:31
constexpr auto timesliceHeader(uint32_t word)
Decode timeslice word.
static constexpr uint32_t RUN3_CAND_TGC_INNERCOIN_SHIFT
Position of the bit specifying coincidence with inner detectors.
static constexpr uint32_t RUN3_CAND_PT_SHIFT
Position of the pT threshold bits in the data words.
Definition MuCTPI_Bits.h:65
constexpr WordType getWordType(uint32_t word)
Determine the type of a MUCTPI ROD word.
constexpr uint32_t dataStatusWord(uint16_t status)
Encode the data status word.
static constexpr uint32_t RUN3_CAND_TGC_CHARGE_SIGN_SHIFT
Position of the bit specifying the candidate's sign.
std::vector< size_t > getDataStatusWordErrors(uint32_t word)
Decode the data status word (returns a vector of bit indices for the errors set - empty if no errors)...
static constexpr uint32_t RUN3_ROI_OVERFLOW_SHIFT
Position of the RoI overflow mask.
Definition MuCTPI_Bits.h:33
constexpr std::array< uint32_t, 3 > multiplicityWords(uint64_t multiplicity, uint32_t triggerBits, bool overflow)
Encode the multiplicity words.
static constexpr uint32_t RUN3_CAND_TGC_BW2OR3_SHIFT
Position of the bit specifying 3-station coincidence from the big wheel.
constexpr auto topoHeader(uint32_t word)
Decode topo word :
constexpr SubsysID getSubsysID(uint32_t word)
Decode the subsys ID from RoI candidate word.
static constexpr uint32_t CAND_SECTOR_ADDRESS_MASK
Definition MuCTPI_Bits.h:78
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
eformat::write::ROBFragment ROBFragment
Definition RawEvent.h:33
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
MuonRoI_v1 MuonRoI
Definition MuonRoI.h:15
setEventNumber uint32_t
Extra patterns decribing particle interation process.
MsgStream & msg
Definition testRead.cxx:32