ATLAS Offline Software
Loading...
Searching...
No Matches
L1TriggerResultByteStreamCnv.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// Trigger includes
9
10// Athena includes
15
16// Gaudi includes
17#include "GaudiKernel/IRegistry.h"
18#include "GaudiKernel/ThreadLocalContext.h"
19
20// TDAQ includes
21#include "eformat/Issue.h"
22#include "eformat/SourceIdentifier.h"
23
25
26// =============================================================================
27// Standard constructor
28// =============================================================================
30 Converter(storageType(), classID(), svcLoc),
31 AthMessaging(msgSvc(), "L1TriggerResultByteStreamCnv") {}
32
33// =============================================================================
34// Standard destructor
35// =============================================================================
37
38// =============================================================================
39// Implementation of Converter::initialize
40// =============================================================================
42 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
44
45 // Check one property of the encoder tools to determine if the tools are configured in the job
46 const bool doMuon = not serviceLocator()->getOptsSvc().get("ToolSvc.L1MuonBSEncoderTool.ROBIDs").empty();
47 ATH_MSG_DEBUG("MUCTPI BS encoding is " << (doMuon ? "enabled" : "disabled"));
48 ATH_CHECK(m_muonEncoderTool.retrieve(EnableTool(doMuon)));
49
50 const bool doMuonDaq = not serviceLocator()->getOptsSvc().get("ToolSvc.L1MuonBSEncoderToolDAQ.ROBIDs").empty();
51 ATH_MSG_DEBUG("MUCTPI DAQ ROB encoding is " << (doMuonDaq ? "enabled" : "disabled"));
52 ATH_CHECK(m_muonEncoderToolDaq.retrieve(EnableTool(doMuonDaq)));
53
54 const bool doCTP = not serviceLocator()->getOptsSvc().get("ToolSvc.CTPResultBSEncoderTool.ROBIDs").empty();
55 ATH_MSG_DEBUG("CTP BS encoding is " << (doCTP ? "enabled" : "disabled"));
56 ATH_CHECK(m_ctpResultEncoderTool.retrieve(EnableTool(doCTP)));
57
58 const bool doEfex = not serviceLocator()->getOptsSvc().get("ToolSvc.eFexBSEncoderTool.ROBIDs").empty();
59 ATH_MSG_DEBUG("eFex BS encoding is " << (doEfex ? "enabled" : "disabled"));
60 ATH_CHECK(m_efexEncoderTool.retrieve(EnableTool(doEfex)));
61
62 const bool doJfex = not serviceLocator()->getOptsSvc().get("ToolSvc.jFexBSEncoderTool.ROBIDs").empty();
63 ATH_MSG_DEBUG("jFex BS encoding is " << (doJfex ? "enabled" : "disabled"));
64 ATH_CHECK(m_jfexEncoderTool.retrieve(EnableTool(doJfex)));
65
66 const bool doGfex = not serviceLocator()->getOptsSvc().get("ToolSvc.gFexBSEncoderTool.ROBIDs").empty();
67 ATH_MSG_DEBUG("gFex BS encoding is " << (doGfex ? "enabled" : "disabled"));
68 ATH_CHECK(m_gfexEncoderTool.retrieve(EnableTool(doGfex)));
69
70 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
71 return StatusCode::SUCCESS;
72}
73
74// =============================================================================
75// Implementation of Converter::finalize
76// =============================================================================
78 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
79 if (m_ByteStreamEventAccess.release().isFailure())
80 ATH_MSG_WARNING("Failed to release service " << m_ByteStreamEventAccess.typeAndName());
81 if (m_muonEncoderTool.isEnabled() && m_muonEncoderTool.release().isFailure())
82 ATH_MSG_WARNING("Failed to release tool " << m_muonEncoderTool.typeAndName());
83 if (m_muonEncoderToolDaq.isEnabled() && m_muonEncoderToolDaq.release().isFailure())
84 ATH_MSG_WARNING("Failed to release tool " << m_muonEncoderToolDaq.typeAndName());
85 if (m_ctpResultEncoderTool.isEnabled() && m_ctpResultEncoderTool.release().isFailure())
86 ATH_MSG_WARNING("Failed to release tool " << m_ctpResultEncoderTool.typeAndName());
87 if (m_efexEncoderTool.isEnabled() && m_efexEncoderTool.release().isFailure())
88 ATH_MSG_WARNING("Failed to release tool " << m_efexEncoderTool.typeAndName());
89 if (m_jfexEncoderTool.isEnabled() && m_jfexEncoderTool.release().isFailure())
90 ATH_MSG_WARNING("Failed to release tool " << m_jfexEncoderTool.typeAndName());
91 if (m_gfexEncoderTool.isEnabled() && m_gfexEncoderTool.release().isFailure())
92 ATH_MSG_WARNING("Failed to release tool " << m_gfexEncoderTool.typeAndName());
93 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
94 return StatusCode::SUCCESS;
95}
96
97// =============================================================================
98// Implementation of Converter::createObj
99// =============================================================================
100StatusCode L1TriggerResultByteStreamCnv::createObj(IOpaqueAddress* /*pAddr*/, DataObject*& /*pObj*/) {
101 ATH_MSG_ERROR("L1TriggerResult cannot be created directly from ByteStream!"
102 << " Use the L1TriggerResultMaker algorithm instead");
103 return StatusCode::FAILURE;
104}
105
106// =============================================================================
107// Implementation of Converter::createRep
108// =============================================================================
109StatusCode L1TriggerResultByteStreamCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
110 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
111
112 const EventContext& ctx = Gaudi::Hive::currentContext();
113
114 // Cast the DataObject to L1TriggerResult
115 xAOD::TrigCompositeContainer* l1TriggerResult = nullptr;
116 bool castSuccessful = SG::fromStorable(pObj, l1TriggerResult);
117 if (!castSuccessful || !l1TriggerResult) {
118 ATH_MSG_ERROR("Failed to convert DataObject to xAOD::TrigCompositeContainer for L1TriggerResult");
119 return StatusCode::FAILURE;
120 }
121
122 // Obtain the RawEventWrite (aka eformat::write::FullEventFragment) pointer
123 RawEventWrite* re = m_ByteStreamEventAccess->getRawEvent();
124 if (!re) {
125 ATH_MSG_ERROR("Failed to obtain a pointer to RawEventWrite");
126 return StatusCode::FAILURE;
127 }
128 ATH_MSG_VERBOSE("Obtained RawEventWrite pointer = " << re);
129
130 // ===== CTPResult encoding =================
131
132 // Only perform encoding if tool was enabled, hence only when xAOD::CTPResult is used instead of ROIB::CTPResult (as part of ROIB::RoIBResult)
133 if (m_ctpResultEncoderTool.isEnabled()) {
134
135 // Extract the CTPResult SG key stored as a detail of the TrigComposite
136 const xAOD::TrigComposite* l1tr = l1TriggerResult->at(0);
137 std::string ctpKey;
138 l1tr->getDetail<std::string>("CTPResultKey", ctpKey);
139
140 // Use the retrieved key to read the CTPResult from the event store
141 SG::ReadHandle<xAOD::CTPResult> result(ctpKey, ctx);
142 ATH_CHECK(result.isValid());
143
144 // Helpful lambda function to convert from vectors of 32-bit words to bitsets
145 auto wordsToBitset = [](const std::vector<uint32_t>& words) {
146 std::bitset<512> out;
147 for (size_t i = 0; i < words.size(); ++i) {
148 uint32_t w = words[i];
149 for (size_t b = 0; b < 32; ++b) {
150 if (w & (1u << b)) {
151 out.set(i * 32 + b);
152 }
153 }
154 }
155 return out;
156 };
157
158 std::bitset<512> tbp = wordsToBitset(result->getTBPWords());
159 std::bitset<512> tap = wordsToBitset(result->getTAPWords());
160 std::bitset<512> tav = wordsToBitset(result->getTAVWords());
161
162 // Number of L1 words computed from TBP/TAP/TAV
163 constexpr size_t wordSize = 32;
164 constexpr size_t wordsPerSet = 512 / wordSize;
165 constexpr size_t numWords = 3 * wordsPerSet;
166
167 // Allocate per-event storage
168 std::vector<uint32_t> l1BitsData(numWords, 0);
169
170 // Fill l1BitsData from TBP/TAP/TAV
171 size_t iset{0};
172 for (const std::bitset<512>& bset : {tbp, tap, tav}) {
173 const std::string sbits = bset.to_string();
174 const size_t iWordOutputStart = wordsPerSet * iset;
175 for (size_t iWordInSet = 0; iWordInSet < wordsPerSet; ++iWordInSet) {
176 const size_t bwordPos = 512 - (iWordInSet + 1) * wordSize;
177 std::bitset<wordSize> bword{sbits.substr(bwordPos, wordSize)};
178 l1BitsData[iWordOutputStart + iWordInSet] = static_cast<uint32_t>(bword.to_ulong());
179 }
180 ++iset;
181 }
182 const uint32_t triggerType = result->triggerType();
183
184 // Update RawEventWrite
185 re->lvl1_trigger_info(l1BitsData.size(), l1BitsData.data());
186 re->lvl1_trigger_type(static_cast<uint8_t>(triggerType & 0xFF));
187
188 // Check there is no CTPResult ReadHandleKey in the L1TriggerResult when CTP bytestream encoding tool is not enabled
189 } else {
190 const xAOD::TrigComposite* l1tr = l1TriggerResult->at(0);
191 std::string ctpKey;
192 if (l1tr->getDetail<std::string>("CTPResultKey", ctpKey)) {
193 ATH_MSG_WARNING("L1TriggerResult contains CTPResult ReadHandleKey but CTP bytestream encoding tool is not enabled");
194 }
195 }
196
197 // ===== MuonRoI + eFex encoding =================
198
199 for (ToolHandle<IL1TriggerByteStreamTool>& tool : {std::reference_wrapper(m_muonEncoderTool), std::reference_wrapper(m_muonEncoderToolDaq), std::reference_wrapper(m_efexEncoderTool), std::reference_wrapper(m_jfexEncoderTool), std::reference_wrapper(m_gfexEncoderTool), std::reference_wrapper(m_ctpResultEncoderTool)}) {
200 if (not tool.isEnabled()) {continue;}
201 std::vector<WROBF*> muon_robs;
202 ATH_CHECK(tool->convertToBS(muon_robs, l1TriggerResult, ctx)); // TODO: find a way to avoid ThreadLocalContext
203 ATH_MSG_DEBUG(tool.name() << " created " << muon_robs.size() << " L1Muon ROB Fragments");
204 for (WROBF* rob : muon_robs) {
205 printRob(*rob);
206 // Set LVL1 Trigger Type from the full event
207 rob->rod_lvl1_type(re->lvl1_trigger_type());
208 // Set LVL1 ID from the full event
209 rob->rod_lvl1_id(re->lvl1_id());
210 // Add the ROBFragment to the full event
211 re->append(rob);
212 ATH_MSG_DEBUG("Added ROB fragment 0x" << MSG::hex << rob->source_id() << MSG::dec << " to the output raw event");
213 }
214 }
215
216 // Placeholder for other systems: L1Topo, gFEX
217
218 // Create a ByteStreamAddress for L1TriggerResult
219 if ( pAddr != nullptr ) pAddr->release();
220 ByteStreamAddress* bsAddr = new ByteStreamAddress(classID(), pObj->registry()->name(), "");
221 pAddr = static_cast<IOpaqueAddress*>(bsAddr);
222 pAddr->addRef();
223
224 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
225 return StatusCode::SUCCESS;
226}
227
228// =============================================================================
229// Debug print helper
230// =============================================================================
232 if (not msgLvl(MSG::DEBUG)) {return;}
233 const uint32_t ndata = rob.rod_ndata();
234 const uint32_t* data = rob.rod_data();
235 ATH_MSG_DEBUG("This ROB has " << ndata << " data words");
236 for (uint32_t i=0; i<ndata; ++i, ++data) {
237 ATH_MSG_DEBUG("--- 0x" << MSG::hex << *data << MSG::dec);
238 }
239}
240
241// =============================================================================
242// CLID / storageType
243// =============================================================================
247
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
a traits class that associates a CLID to a type T It also detects whether T inherits from Gaudi DataO...
uint32_t CLID
The Class ID type.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::FullEventFragment RawEventWrite
data type for writing raw event
Definition RawEvent.h:39
convert to and from a SG storable
#define sbits(u, n)
Intrinsic functions which do not work correctly due to differences in byte ordering.
bool msgLvl(const MSG::Level lvl) const
Test the output level.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
IOpaqueAddress for ByteStreamCnvSvc, with ROB ids.
static constexpr long storageType()
const T * at(size_type n) const
Access an element, as an rvalue.
static CLID classID()
CLID of the class of the L1TriggerResult converted by this converter (xAOD::TrigCompositeContainer).
void printRob(const OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment &rob) const
Helper method for debug printouts.
ToolHandle< IL1TriggerByteStreamTool > m_ctpResultEncoderTool
Encoder tool for CTP result.
virtual StatusCode createRep(DataObject *pObj, IOpaqueAddress *&pAddr) override
Create ByteStream from xAOD (L1TriggerResult).
static long storageType()
Storage type used by this converter.
ToolHandle< IL1TriggerByteStreamTool > m_efexEncoderTool
eFEX tool
virtual StatusCode finalize() override
ToolHandle< IL1TriggerByteStreamTool > m_muonEncoderTool
Encoder tools for L1Muon RoIs (one writing RoIB ROB, one writing DAQ ROB).
ToolHandle< IL1TriggerByteStreamTool > m_jfexEncoderTool
jFEX tool
ServiceHandle< IByteStreamEventAccess > m_ByteStreamEventAccess
Helper to obtain the RawEvent pointer.
virtual ~L1TriggerResultByteStreamCnv()
Standard destructor.
virtual StatusCode initialize() override
ToolHandle< IL1TriggerByteStreamTool > m_gfexEncoderTool
gFEX tool
ToolHandle< IL1TriggerByteStreamTool > m_muonEncoderToolDaq
L1TriggerResultByteStreamCnv(ISvcLocator *svcLoc)
Standard constructor.
virtual StatusCode createObj(IOpaqueAddress *pAddr, DataObject *&pObj) override
Create xAOD (L1TriggerResult) from ByteStream.
bool getDetail(const std::string &name, TYPE &value) const
Get an TYPE detail from the object.
eformat::write::ROBFragment ROBFragment
Definition RawEvent.h:33
bool fromStorable(DataObject *pDObj, T *&pTrans, bool quiet=false, IRegisterTransient *irt=0, bool isConst=true)
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.