128 const EventContext& eventContext)
const {
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());
140 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>> topoHandles;
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());
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;
160 const ROBF* rob = *it;
162 const uint32_t ndata = rob->rod_ndata();
163 const uint32_t*
const data = rob->rod_data();
170 std::vector<int> bcidOffsetsWrtROB;
175 ATH_MSG_ERROR(
"Empty ROD data in MUCTPI ROB 0x" << std::hex << sid.code() << std::dec);
177 return StatusCode::FAILURE;
179 ATH_MSG_DEBUG(
"Starting to decode " << ndata <<
" ROD words");
183 std::vector<std::pair<size_t,size_t>> roiSlices;
184 std::vector<std::pair<size_t,size_t>> topoSlices;
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)];
197 <<
", NTOB=" <<
header.tobCount <<
", NCAND=" <<
header.candCount);
199 roiSlices.emplace_back(0,0);
201 topoSlices.emplace_back(0,0);
203 bcidOffsetsWrtROB.push_back(bcidDiff(
header.bcid, rob->rod_bc_id()));
213 if (roiSlices.empty()) {
214 ATH_MSG_ERROR(
"Unexpected data format - found candidate word before any timeslice header");
216 return StatusCode::FAILURE;
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;
227 if (topoSlices.empty()) {
228 ATH_MSG_ERROR(
"Unexpected data format - found Topo TOB word before any timeslice header");
229 return StatusCode::FAILURE;
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;
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) {
252 ATH_MSG_ERROR(
"The MUCTPI word 0x" << std::hex << word << std::dec <<
" does not match any known word type");
254 return StatusCode::FAILURE;
264 const size_t nSlices{roiSlices.size()};
266 if (nSlices > nOutputSlices) {
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;
277 const size_t outputOffset = nOutputSlices/2 - nSlices/2;
282 const size_t nTopoSlices{topoSlices.size()};
284 if (nTopoSlices > nTopoOutputSlices) {
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;
295 const size_t topoOutputOffset = nTopoOutputSlices/2 - nTopoSlices/2;
301 auto topoHandleIt = topoHandles.begin();
302 for (
auto& roiHandle : roiHandles) {
303 auto& topoHandle = *topoHandleIt;
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");
314 ATH_MSG_DEBUG(
"Decoded " << monNumRoIs <<
" RoIs into the " << roiHandle.key() <<
" container");
320 return StatusCode::SUCCESS;
326 std::vector<SG::WriteHandle<xAOD::MuonRoIContainer>> topoHandles;
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());
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;
346 const ROBF* rob = *it;
348 const uint32_t ndata = rob->rod_ndata();
349 const uint32_t*
const data = rob->rod_data();
356 std::vector<int> bcidOffsetsWrtROB;
361 ATH_MSG_ERROR(
"Empty ROD data in MUCTPI ROB 0x" << std::hex << sid.code() << std::dec);
362 return StatusCode::FAILURE;
364 ATH_MSG_DEBUG(
"Starting to decode " << ndata <<
" ROD words");
368 std::vector<std::pair<size_t,size_t>> roiSlices;
369 std::vector<std::pair<size_t,size_t>> topoSlices;
374 ATH_MSG_DEBUG(
"MUCTPI raw word " << iWord <<
": 0x" << std::hex << word << std::dec);
376 ++wordTypeCounts[
static_cast<size_t>(wordType)];
382 <<
", NTOB=" <<
header.tobCount <<
", NCAND=" <<
header.candCount);
384 roiSlices.emplace_back(0,0);
386 topoSlices.emplace_back(0,0);
388 bcidOffsetsWrtROB.push_back(bcidDiff(
header.bcid, rob->rod_bc_id()));
398 if (roiSlices.empty()) {
399 ATH_MSG_ERROR(
"Unexpected data format - found candidate word before any timeslice header");
400 return StatusCode::FAILURE;
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;
411 if (topoSlices.empty()) {
412 ATH_MSG_ERROR(
"Unexpected data format - found Topo TOB word before any timeslice header");
413 return StatusCode::FAILURE;
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;
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) {
435 ATH_MSG_ERROR(
"The MUCTPI word 0x" << std::hex << word << std::dec <<
" does not match any known word type");
436 return StatusCode::FAILURE;
443 const size_t nSlices{roiSlices.size()};
445 if (nSlices > nOutputSlices) {
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;
459 const size_t nTopoSlices{topoSlices.size()};
461 if (nTopoSlices > nTopoOutputSlices) {
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;
472 const size_t topoOutputOffset = nTopoOutputSlices/2 - nTopoSlices/2;
476 return StatusCode::SUCCESS;
486 const EventContext& eventContext) {
488 std::vector<SG::ReadHandle<xAOD::MuonRoIContainer>> handles =
m_roiReadKeys.makeHandles(eventContext);
492 for (
auto& handle : handles) {
494 if (!handle->empty()) {
495 rodSize += handle->size();
496 nSlices = std::max(nSlices, 1+2*std::abs(
m_readoutWindow/2 - iHandle));
501 ATH_MSG_DEBUG(
"There are no muon RoIs to encode in this event");
507 rodSize += 4*nSlices + 1;
508 ATH_MSG_DEBUG(
"Going to encode " << nSlices <<
" time slices into " << rodSize <<
" ROD words");
511 clearCache(eventContext);
512 uint32_t*
data = newRodData(eventContext, rodSize);
519 std::vector<int> bcidOffsetsWrtROB;
521 auto monitorCandidate = [](
const auto& monTool,
const xAOD::MuonRoI& roi){
523 const uint32_t word = roi.roiWord();
524 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
527 std::string sectorName{s_sectorNames[
static_cast<size_t>(subsysID)]};
534 auto inputIt = handles.begin();
537 for (
int iSlice=0; iSlice<nSlices; ++iSlice, ++inputIt) {
539 uint32_t bcid = bcidSum(eventContext.eventID().bunch_crossing_id(), iSlice - nSlices/2);
540 static constexpr uint32_t tobCount = 0;
541 uint32_t candCount = (*inputIt)->size();
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);
550 data[iWord++] = word;
558 data[iWord++] = roiWordRemoveOfflineRun3Flag(roi->roiWord());
559 ATH_MSG_DEBUG(
"Added RoI word 0x" << std::hex << roi->roiWord() << std::dec);
562 ATH_MSG_DEBUG(
"Added " << (*inputIt)->size() <<
" candidate words");
574 if (iWord!=rodSize) {
575 ATH_MSG_ERROR(
"Expected to fill " << rodSize <<
" ROD words but filled " << iWord);
576 return StatusCode::FAILURE;
580 const eformat::helper::SourceIdentifier sid(
m_robIds.value().at(0));
581 vrobf.push_back(newRobFragment(eventContext, sid.code(), rodSize,
data, nSlices));
583 return StatusCode::SUCCESS;
590 const std::vector<std::pair<size_t,size_t>>& slices,
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");
601 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
619 ATH_MSG_ERROR(
"Failed to determine Sector ID from RoI word 0x" << std::hex << word << std::dec);
620 return StatusCode::FAILURE;
626 const std::pair<std::string, double> minThrInfo =
m_thresholdTool->getMinThresholdNameAndValue(
631 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(word),
638 using SubsysID_ut = std::underlying_type_t<LVL1::MuCTPIBits::SubsysID>;
640 std::string sectorName{s_sectorNames[
static_cast<size_t>(subsysID)]};
648 return StatusCode::SUCCESS;
655 const std::vector<std::pair<size_t,size_t>>& slices,
658 const EventContext& )
const {
659 int toposliceiterator = -1;
660 int nomBCID_slice = slices.size() / 2 ;
661 int topobcidOffset = 0;
662 unsigned short subsystem = 0;
667 constexpr static bool local_topo_debug{
true};
670 ATH_CHECK( detStore()->retrieve(l1menu) );
672 const auto & exMU = l1menu->thrExtraInfo().MU();
673 auto tgcPtValues = exMU.knownTgcPtValues();
675 auto outputIt = handles.begin();
676 std::advance(outputIt, outputOffset);
678 for (
const auto& [sliceStart,sliceSize] : slices) {
680 for (
const uint32_t word : std::span{
data+sliceStart, sliceSize}) {
682 std::stringstream sectorName;
685 topobcidOffset = toposliceiterator - nomBCID_slice;
688 (*outputIt)->push_back(std::make_unique<xAOD::MuonRoI>());
690 ATH_MSG_DEBUG(
"MuCTPIL1Topo: Decoding Topo word 0x" << std::hex << word << std::dec <<
" into the " << outputIt->key() <<
" container");
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) );
703 if (topoheader.det == 0) {
707 else if (topoheader.det == 1) {
711 else if (topoheader.det == 2) {
715 if (topoheader.hemi) sectorName <<
"A";
716 else sectorName<<
"C";
717 sectorName << topoheader.sec;
720 if (local_topo_debug) {
724 ATH_MSG_DEBUG(
"MuCTPIL1Topo etacode: " << topoheader.etacode );
725 ATH_MSG_DEBUG(
"MuCTPIL1Topo phicode: " << topoheader.phicode );
734 unsigned short roi =
m_l1topoLUT.getBarrelROI(topoheader.hemi, topoheader.sec, topoheader.barrel_eta_lookup, topoheader.barrel_phi_lookup);
736 if (local_topo_debug) {
738 ATH_MSG_DEBUG(
"MuCTPIL1Topo barrel_eta_lookup: " << topoheader.barrel_eta_lookup );
739 ATH_MSG_DEBUG(
"MuCTPIL1Topo barrel_phi_lookup: " << topoheader.barrel_phi_lookup );
745 if (local_topo_debug) {
746 ATH_MSG_DEBUG(
"MuCTPIL1Topo phiOvl(0): " << topoheader.flag0);
747 ATH_MSG_DEBUG(
"MuCTPIL1Topo is2cand(1):" << topoheader.flag1);
751 uint32_t roiWord = 0;
756 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
760 tgcPtValues[topoheader.pt]);
767 if (local_topo_debug) {
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);
787 uint32_t roiWord = 0;
797 (*outputIt)->back()->initialize(roiWordAddOfflineRun3Flag(roiWord),
801 tgcPtValues[topoheader.pt]);
808 ATH_MSG_DEBUG(
"MuCTPIL1Topo: L1Topo output recorded to StoreGate with key " << outputIt->key() <<
" and bcidOffset: " << topobcidOffset);
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];
816 std::string subsysName{s_sectorNames[
static_cast<size_t>(subsysID)]};
825 return StatusCode::SUCCESS;