ATLAS Offline Software
Loading...
Searching...
No Matches
MuonRoIByteStreamTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 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 EventContext& eventContext) {
486 // Retrieve the RoI containers and determine how many time slices will be encoded
487 std::vector<SG::ReadHandle<xAOD::MuonRoIContainer>> handles = m_roiReadKeys.makeHandles(eventContext);
488 int nSlices{0};
489 int iHandle{0};
490 size_t rodSize{0};
491 for (auto& handle : handles) {
492 ATH_CHECK(handle.isValid());
493 if (!handle->empty()) {
494 rodSize += handle->size();
495 nSlices = std::max(nSlices, 1+2*std::abs(m_readoutWindow/2 - iHandle));
496 }
497 ++iHandle;
498 }
499 if (nSlices==0) {
500 ATH_MSG_DEBUG("There are no muon RoIs to encode in this event");
501 // Force at least the triggered BC slice to be encoded
502 nSlices = 1;
503 }
504
505 // Calculate the number of words we need to allocate (candidate words already counted above)
506 rodSize += 4*nSlices + 1; // 1 timeslice header per slice, 3 multiplicity words per slice, 1 status word
507 ATH_MSG_DEBUG("Going to encode " << nSlices << " time slices into " << rodSize << " ROD words");
508
509 // Clear BS data cache and allocate new data array
510 clearCache(eventContext);
511 uint32_t* data = newRodData(eventContext, rodSize); // Owned by the cache
512
513 // Initialise a few monitoring variables
514 Monitored::Scalar<size_t> monNumWords{"NumWordsInROD", rodSize};
515 std::array<size_t,static_cast<size_t>(LVL1::MuCTPIBits::WordType::MAX)> wordTypeCounts{}; // zero-initialised
516 auto monWordTypeCount = Monitored::Collection("WordTypeCount", wordTypeCounts);
517 auto monWordType = Monitored::Collection("WordType", s_wordTypes);
518 std::vector<int> bcidOffsetsWrtROB; // diffs between BCID in timeslice header and BCID in ROB header
519 auto monBCIDOffsetsWrtROB = Monitored::Collection("BCIDOffsetsWrtROB", bcidOffsetsWrtROB);
520 auto monitorCandidate = [](const auto& monTool, const xAOD::MuonRoI& roi){
521 // Fill per-candidate monitoring histograms
522 const uint32_t word = roi.roiWord();
523 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
525 Monitored::Scalar<SubsysID_ut> monSubsysID{"SubsysID", static_cast<SubsysID_ut>(subsysID)};
526 std::string sectorName{s_sectorNames[static_cast<size_t>(subsysID)]};
527 Monitored::Scalar<double> monEta{"roiEta_"+sectorName, roi.eta()};
528 Monitored::Scalar<double> monPhi{"roiPhi_"+sectorName, roi.phi()};
529 Monitored::Group(monTool, monSubsysID, monEta, monPhi);
530 };
531
532 // Fill the data words
533 auto inputIt = handles.begin();
534 std::advance(inputIt, m_readoutWindow/2 - nSlices/2);
535 size_t iWord{0};
536 for (int iSlice=0; iSlice<nSlices; ++iSlice, ++inputIt) {
537 // Timeslice header
538 uint32_t bcid = bcidSum(eventContext.eventID().bunch_crossing_id(), iSlice - nSlices/2);
539 static constexpr uint32_t tobCount = 0; // Filling Topo words not implemented
540 uint32_t candCount = (*inputIt)->size();
541 data[iWord++] = LVL1::MuCTPIBits::timesliceHeader(bcid, tobCount, candCount);
542 ++wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Timeslice)];
543 bcidOffsetsWrtROB.push_back(bcidDiff(bcid, eventContext.eventID().bunch_crossing_id()));
544 ATH_MSG_DEBUG("Added timeslice header word with BCID=" << bcid << ", NTOB=" << tobCount << ", NCAND=" << candCount);
545
546 // Multiplicity words
547 std::array<uint32_t,3> multiplicityWords = LVL1::MuCTPIBits::multiplicityWords(0, 0, false); // Multiplicity words content not implemented
548 for (const uint32_t word : multiplicityWords) {
549 data[iWord++] = word;
550 }
551 wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Multiplicity)] += multiplicityWords.size();
552 ATH_MSG_DEBUG("Added " << multiplicityWords.size() << " multiplicity words");
553
554 // Candidate words
555 for (const xAOD::MuonRoI* roi : **inputIt) {
556 monitorCandidate(m_monTool, *roi);
557 data[iWord++] = roiWordRemoveOfflineRun3Flag(roi->roiWord());
558 ATH_MSG_DEBUG("Added RoI word 0x" << std::hex << roi->roiWord() << std::dec);
559 }
560 wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Candidate)] += (*inputIt)->size();
561 ATH_MSG_DEBUG("Added " << (*inputIt)->size() << " candidate words");
562 }
563
564 // Status word
566 ++wordTypeCounts[static_cast<size_t>(LVL1::MuCTPIBits::WordType::Status)];
567 ATH_MSG_DEBUG("Added the data status word");
568
569 // Fill data format monitoring histograms
570 Monitored::Group(m_monTool, monNumWords, monWordType, monWordTypeCount, monBCIDOffsetsWrtROB);
571
572 // Check that we filled all words
573 if (iWord!=rodSize) {
574 ATH_MSG_ERROR("Expected to fill " << rodSize << " ROD words but filled " << iWord);
575 return StatusCode::FAILURE;
576 }
577
578 // Create a ROBFragment containing the ROD words
579 const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
580 vrobf.push_back(newRobFragment(eventContext, sid.code(), rodSize, data, nSlices));
581
582 return StatusCode::SUCCESS;
583}
584
585// -----------------------------------------------------------------------------
586// Helper for BS->xAOD conversion of RoI candidate words
587// -----------------------------------------------------------------------------
589 const std::vector<std::pair<size_t,size_t>>& slices,
590 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>>& handles,
591 size_t outputOffset,
592 const EventContext& eventContext) const {
593 auto outputIt = handles.begin();
594 std::advance(outputIt, outputOffset);
595 for (const auto& [sliceStart,sliceSize] : slices) {
596 for (const uint32_t word : std::span{data+sliceStart, sliceSize}) {
597 ATH_MSG_DEBUG("Decoding RoI word 0x" << std::hex << word << std::dec << " into the " << outputIt->key() << " container");
598
599 // Create a new xAOD::MuonRoI object for this candidate in the output container
600 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
601
602 // Decode eta/phi information using the right tool for the subsystem
605 switch (subsysID) {
606 case LVL1::MuCTPIBits::SubsysID::Endcap: // same for Endcap and Forward
608 ATH_MSG_DEBUG("This is an Endcap/Forward candidate, calling the " << m_tgcTool.typeAndName());
609 ATH_CHECK( m_tgcTool->roiData(word,roiData) );
610 break;
611 }
613 ATH_MSG_DEBUG("This is a Barrel candidate, calling the " << m_rpcTool.typeAndName());
614 ATH_CHECK( m_rpcTool->roiData(word,roiData) );
615 break;
616 }
617 default: {
618 ATH_MSG_ERROR("Failed to determine Sector ID from RoI word 0x" << std::hex << word << std::dec);
619 return StatusCode::FAILURE;
620 }
621 }
622
623 // Get the threshold decisions to find the lowest pt threshold passed
624 // This is required by xAOD::MuonRoI::initialize() but not used for HLT seeding (a threshold pattern bit mask is used instead)
625 const std::pair<std::string, double> minThrInfo = m_thresholdTool->getMinThresholdNameAndValue(
626 m_thresholdTool->getThresholdDecisions(word, eventContext),
627 roiData.eta());
628
629 // Fill the xAOD::MuonRoI object
630 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(word),
631 roiData.eta(),
632 roiData.phi(),
633 minThrInfo.first,
634 minThrInfo.second);
635
636 // Fill per-candidate monitoring histograms
637 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
638 Monitored::Scalar<SubsysID_ut> monSubsysID{"SubsysID", static_cast<SubsysID_ut>(subsysID)};
639 std::string sectorName{s_sectorNames[static_cast<size_t>(subsysID)]};
640 Monitored::Scalar<double> monEta{"roiEta_"+sectorName, roiData.eta()};
641 Monitored::Scalar<double> monPhi{"roiPhi_"+sectorName, roiData.phi()};
642 Monitored::Group(m_monTool, monSubsysID, monEta, monPhi);
643 }
644 ++outputIt;
645 } // Loop over RoI candidate time slices
646
647 return StatusCode::SUCCESS;
648}
649
650// -----------------------------------------------------------------------------
651// Helper for BS->transient conversion of Topo TOB words
652// -----------------------------------------------------------------------------
654 const std::vector<std::pair<size_t,size_t>>& slices,
655 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>>& handles,
656 size_t outputOffset,
657 const EventContext& /*eventContext*/) const {
658 int toposliceiterator = -1;
659 int nomBCID_slice = slices.size() / 2 ;
660 int topobcidOffset = 0;
661 unsigned short subsystem = 0;
662
663 float eta=0, phi=0;
664 unsigned int et=0;
665 //in case something is found to not be correctly decoded by the L1Topo group - can clean this extra-debug printouts later if wished
666 constexpr static bool local_topo_debug{true};
667
668 const TrigConf::L1Menu * l1menu = nullptr;
669 ATH_CHECK( detStore()->retrieve(l1menu) );
670
671 const auto & exMU = l1menu->thrExtraInfo().MU();
672 auto tgcPtValues = exMU.knownTgcPtValues();
673
674 auto outputIt = handles.begin();
675 std::advance(outputIt, outputOffset);
676 // Loop over Topo candidate time slices
677 for (const auto& [sliceStart,sliceSize] : slices) {
678 toposliceiterator++;
679 for (const uint32_t word : std::span{data+sliceStart, sliceSize}) {
680 //the cand usage should be optimised!
681 std::stringstream sectorName;
682 subsystem = 0;
683
684 topobcidOffset = toposliceiterator - nomBCID_slice;
685
686 // Create a new xAOD::MuonRoI object for this candidate in the output container
687 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
688
689 ATH_MSG_DEBUG("MuCTPIL1Topo: Decoding Topo word 0x" << std::hex << word << std::dec << " into the " << outputIt->key() << " container");
690
691 // NOTE the convention:
692 // HEMISPHERE 0: C-side (-) / 1: A-side (+)
693 // Det (bits): Barrel: 00 - EC: 1X - FW: 01
694 const auto topoheader = LVL1::MuCTPIBits::topoHeader(word);
695 if (local_topo_debug) {
696 ATH_MSG_DEBUG("MuCTPIL1Topo: TOPOSLICE data: " <<data << " sliceStart: "<<sliceStart<< " sliceSize: " <<sliceSize );
697 ATH_MSG_DEBUG("MuCTPIL1Topo word: 0x" << std::hex << word << std::dec );
698 ATH_MSG_DEBUG("MuCTPIL1Topo word: 0b" << std::bitset<32>(word) );
699 }
700 // Build the sector name
701 // topoheader.det is the direct WORD content, but here later in m_l1topoLUT.getCoordinates the definition is different ... see the subsystem settings below
702 if (topoheader.det == 0) {
703 sectorName<<"B";
704 subsystem = 0;
705 }
706 else if (topoheader.det == 1) {
707 sectorName<<"F";
708 subsystem = 2;
709 }
710 else if (topoheader.det == 2) {
711 sectorName<<"E";
712 subsystem = 1;
713 }
714 if (topoheader.hemi) sectorName << "A";
715 else sectorName<< "C";
716 sectorName << topoheader.sec;
717 // End of: Build the sector name
718
719 if (local_topo_debug) {
720 ATH_MSG_DEBUG("MuCTPIL1Topo det: " << topoheader.det);
721 ATH_MSG_DEBUG("MuCTPIL1Topo hemi: " << topoheader.hemi );
722 ATH_MSG_DEBUG("MuCTPIL1Topo sector: " << sectorName.str() );
723 ATH_MSG_DEBUG("MuCTPIL1Topo etacode: " << topoheader.etacode );
724 ATH_MSG_DEBUG("MuCTPIL1Topo phicode: " << topoheader.phicode );
725 ATH_MSG_DEBUG("MuCTPIL1Topo sec: " << topoheader.sec );
726 ATH_MSG_DEBUG("MuCTPIL1Topo roi: " << topoheader.roi );
727 ATH_MSG_DEBUG("MuCTPIL1Topo pt: " << topoheader.pt );
728 }
729
730 if (subsystem == 0) // Barrel
731 {
732 //for barrel topoheader.roi is always 0, so we need to reconstruct it...
733 unsigned short roi = m_l1topoLUT.getBarrelROI(topoheader.hemi, topoheader.sec, topoheader.barrel_eta_lookup, topoheader.barrel_phi_lookup);
734 LVL1MUCTPIPHASE1::L1TopoCoordinates coord = m_l1topoLUT.getCoordinates(topoheader.hemi ,subsystem ,topoheader.sec ,roi);
735 if (local_topo_debug) {
736 ATH_MSG_DEBUG("MuCTPIL1Topo: Barrel decoding");
737 ATH_MSG_DEBUG("MuCTPIL1Topo barrel_eta_lookup: " << topoheader.barrel_eta_lookup );
738 ATH_MSG_DEBUG("MuCTPIL1Topo barrel_phi_lookup: " << topoheader.barrel_phi_lookup );
739 ATH_MSG_DEBUG("MuCTPIL1Topo eta value: " << coord.eta);
740 ATH_MSG_DEBUG("MuCTPIL1Topo phi value: " << coord.phi);
741 }
742
743 // Documentation / translation for the flag setting below
744 if (local_topo_debug) {
745 ATH_MSG_DEBUG("MuCTPIL1Topo phiOvl(0): " << topoheader.flag0);
746 ATH_MSG_DEBUG("MuCTPIL1Topo is2cand(1):" << topoheader.flag1);
747 }
748
749 // Create RoI Word
750 uint32_t roiWord = 0;
751 roiWord |= (static_cast<uint32_t>(topoheader.pt/2) & RUN3_CAND_PT_MASK) << RUN3_CAND_PT_SHIFT;
752 roiWord |= (static_cast<uint32_t>(topoheader.flag1) & ROI_OVERFLOW_MASK) << RUN3_ROI_OVERFLOW_SHIFT;
753
754 // Fill the xAOD::MuonRoI object
755 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
756 coord.eta,
757 coord.phi,
758 "",
759 tgcPtValues[topoheader.pt]);
760 et = topoheader.pt;
761 eta = coord.eta;
762 phi = coord.phi;
763 } // Barrel
764 else { // EC and FWD
765 LVL1MUCTPIPHASE1::L1TopoCoordinates coord = m_l1topoLUT.getCoordinates(topoheader.hemi ,subsystem ,topoheader.sec ,topoheader.roi);
766 if (local_topo_debug) {
767 ATH_MSG_DEBUG("MuCTPIL1Topo: EC / FWD decoding");
768 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta " << coord.eta);
769 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi " << coord.phi);
770 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta_min " << coord.eta_min);
771 ATH_MSG_DEBUG("MuCTPIL1Topo coord.eta_max " << coord.eta_max);
772 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi_min " << coord.phi_min);
773 ATH_MSG_DEBUG("MuCTPIL1Topo coord.phi_max " << coord.phi_max);
774 ATH_MSG_DEBUG("MuCTPIL1Topo coord.ieta " << coord.ieta);
775 ATH_MSG_DEBUG("MuCTPIL1Topo coord.iphi " << coord.iphi);
776 }
777
778 // Documentation / translation for the flag setting below
779 if (local_topo_debug) {
780 ATH_MSG_DEBUG("MuCTPIL1Topo charge (0):" << topoheader.flag0);
781 ATH_MSG_DEBUG("MuCTPIL1Topo bw2or3 (1):" << topoheader.flag1);
782 ATH_MSG_DEBUG("MuCTPIL1Topo innerCoin (2):" << topoheader.flag2);
783 ATH_MSG_DEBUG("MuCTPIL1Topo goodMF (3):" << topoheader.flag3);
784 }
785 // Create RoI Word
786 uint32_t roiWord = 0;
787 roiWord |= (static_cast<uint32_t>(topoheader.pt) & RUN3_CAND_PT_MASK) << RUN3_CAND_PT_SHIFT;
788 // Only needed to tell this is TGC
790 if (topoheader.flag0) {roiWord |= (0x1) << RUN3_CAND_TGC_CHARGE_SIGN_SHIFT;}
791 if (topoheader.flag1) {roiWord |= (0x1) << RUN3_CAND_TGC_BW2OR3_SHIFT;}
792 if (topoheader.flag2) {roiWord |= (0x1) << RUN3_CAND_TGC_INNERCOIN_SHIFT;}
793 if (topoheader.flag3) {roiWord |= (0x1) << RUN3_CAND_TGC_GOODMF_SHIFT;}
794
795 // Fill the xAOD::MuonRoI object
796 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
797 coord.eta,
798 coord.phi,
799 "",
800 tgcPtValues[topoheader.pt]);
801
802 et = topoheader.pt;
803 eta = coord.eta;
804 phi = coord.phi;
805 }// EC and FWD
806
807 ATH_MSG_DEBUG("MuCTPIL1Topo: L1Topo output recorded to StoreGate with key " << outputIt->key() << " and bcidOffset: " << topobcidOffset);
808
809 // Fill per-candidate monitoring histograms
810 using SubsysID_t = LVL1::MuCTPIBits::SubsysID;
811 using SubsysID_ut = std::underlying_type_t<SubsysID_t>;
812 SubsysID_t subsysID{SubsysID_t::Undefined};
813 switch (subsystem) {
814 case 0: {subsysID=SubsysID_t::Barrel; break;}
815 case 1: {subsysID=SubsysID_t::Endcap; break;} // Mind the swap in numbering E<->F, see comments above
816 case 2: {subsysID=SubsysID_t::Forward; break;}
817 default: {break;}
818 }
819 Monitored::Scalar<SubsysID_ut> monSubsysID{"topoSubsysID", static_cast<SubsysID_ut>(subsysID)};
820 std::string subsysName{s_sectorNames[static_cast<size_t>(subsysID)]};
821 Monitored::Scalar<float> monEta{"topoEta_"+subsysName, eta};
822 Monitored::Scalar<float> monPhi{"topoPhi_"+subsysName, phi};
823 Monitored::Scalar<unsigned int> monPtThr{"topoPtThreshold_"+subsysName, et};
824 Monitored::Group(m_monTool, monSubsysID, monEta, monPhi, monPtThr);
825 }
826 ++outputIt;
827 } // Loop over Topo candidate time slices
828
829 return StatusCode::SUCCESS;
830}
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
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,...
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
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const EventContext &eventContext) override
xAOD->BS conversion
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
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
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
MuonRoI_v1 MuonRoI
Definition MuonRoI.h:15
setEventNumber uint32_t
Extra patterns decribing particle interation process.
MsgStream & msg
Definition testRead.cxx:32