ATLAS Offline Software
CTPResultByteStreamTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Local include(s):
7 
8 // TDAQ include(s):
9 #include "eformat/SourceIdentifier.h"
10 #include "CTPfragment/CTPfragment.h"
11 #include "CTPfragment/CTPdataformat.h"
12 #include "CTPfragment/CTPdataformatVersion.h"
13 
14 // Trigger include(s):
15 #include "xAODTrigger/CTPResult.h"
18 
19 // Athena includes
20 #include "CxxUtils/span.h"
21 
25 
26 // -----------------------------------------------------------------------------
27 // Initialisation
28 // -----------------------------------------------------------------------------
30  ConversionMode mode = getConversionMode(m_inKeyCTPResult, m_outKeyCTPResult, msg());
33  ATH_CHECK(m_inKeyCTPResult.initialize(mode==ConversionMode::Encoding));
34  ATH_MSG_DEBUG((mode==ConversionMode::Encoding ? "Encoding" : "Decoding") << " ROB IDs: "
35  << MSG::hex << m_robIds.value() << MSG::dec);
36  if (m_robIds.value().size() != 1) {
37  ATH_MSG_ERROR("This tool implementation assumes there is exactly one CTP ROB, but "
38  << m_robIds.size() << " were configured");
39  return StatusCode::SUCCESS;
40  }
41  return StatusCode::SUCCESS;
42 }
43 
44 // -----------------------------------------------------------------------------
45 // BS->xAOD conversion
46 // -----------------------------------------------------------------------------
47 StatusCode CTPResultByteStreamTool::convertFromBS(const std::vector<const ROBF*>& vrobf, const EventContext& eventContext) const {
48 
49  //
50  // Find the ROB fragment to decode
51  //
52  const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
53  auto it = std::find_if(vrobf.begin(), vrobf.end(), [&sid](const ROBF* rob){return rob->rob_source_id() == sid.code();});
54  if (it == vrobf.end()) {
55  ATH_MSG_ERROR("No CTP ROB fragment with ID 0x" << std::hex << sid.code() << std::dec << " was found!");
56  return StatusCode::FAILURE;
57  }
58  ATH_MSG_VERBOSE("Found CTP ROD with source ID 0x" << MSG::hex << sid.code() << MSG::dec);
59 
60  //
61  // Retrieve the ROD data
62  //
63  const ROBF* rob = *it;
64  DataType it_data;
65  rob->rod_data( it_data );
66  const uint32_t ndata = rob->rod_ndata();
67 
68  //
69  // Header information
70  //
71  uint32_t headerMarker = eformat::ROD;
72  uint32_t formatVersion = rob->rod_version();
73  uint32_t L1ID = rob->rod_lvl1_id();
74  uint32_t sourceID = rob->rod_source_id();
75 
76  //
77  // Trailer information
78  //
79  DataStatus dataStatus;
80  dataStatus.rob_error = false;
81  dataStatus.rod_error = false;
82  dataStatus.status_word = 0;
83  dataStatus.status_info = 0;
84 
85  try {
86  if (rob->check_rob()) ATH_MSG_VERBOSE("ROB fragment checked ok");
87  }
88  catch (std::exception const & ex) {
89  ATH_MSG_WARNING("ROB fragment not valid: " << ex.what());
90  dataStatus.rob_error = true;
91  }
92 
93  try {
94  if (rob->check_rod()) ATH_MSG_VERBOSE("ROD fragment checked ok");
95  }
96  catch (std::exception const & ex) {
97  ATH_MSG_WARNING("ROD fragment not valid: " << ex.what());
98  dataStatus.rod_error = true;
99  }
100 
101  // Process the status words
103  rob->rod_status(status);
104  uint32_t nstatus = rob->rod_nstatus();
105  if (msgLvl(MSG::VERBOSE)) {
106  ATH_MSG_VERBOSE("Number of status words: " << nstatus);
107  for (uint32_t i=0; i<nstatus; ++i, ++status) {
108  ATH_MSG_VERBOSE(" Status word: 0x" << MSG::hex << std::setw(8) << std::setfill('0') << *status);
109  }
110  }
111  rob->rod_status(status);
112 
113  if(nstatus > 0) dataStatus.status_word = static_cast<uint32_t>(*status);
114  if(nstatus > 1) {
115  ++status;
116  dataStatus.status_info = static_cast<uint32_t>(*status);
117  }
118 
119  uint32_t errStatus = dataStatus.status_word; // error status
120  uint32_t statInfo = dataStatus.status_info; // status info
121 
122  //
123  // Payload information
124  //
125  std::vector<uint32_t> vDataWords;
126  vDataWords.reserve(ndata);
127  if (msgLvl(MSG::VERBOSE)) {
128  ATH_MSG_VERBOSE(" Dumping xAOD::CTPResult Words:");
129  for (const uint32_t word : CxxUtils::span{it_data, ndata}) {
130  ATH_MSG_VERBOSE(" 0x" << MSG::hex << std::setfill('0') << std::setw(8) << word << MSG::dec);
131  }
132  }
133  vDataWords.assign(CxxUtils::span{it_data, ndata}.begin(), CxxUtils::span{it_data, ndata}.end());
134 
135  uint32_t nExtraWords=0;
136  nExtraWords=CTPfragment::numberExtraPayloadWords(rob);
137  unsigned int ctpVersionNumber = CTPfragment::ctpFormatVersion(rob);
138 
139  //
140  // Create xAOD
141  //
142  auto result = std::make_unique<xAOD::CTPResult>();
143  auto resultAux = std::make_unique<xAOD::CTPResultAuxInfo>();
144  result->setStore(resultAux.get());
145 
146  // Initialize takes care of the most payload info
147  CTPResultUtils::initialize(*result, ctpVersionNumber, vDataWords, nExtraWords);
148 
149  // Initialize the remaining words
150  result->setHeader(headerMarker, formatVersion, sourceID, L1ID); // Header words
151  result->setTrailer(ndata, errStatus, statInfo); // Trailer words
152  result->setL1AcceptBunchPosition(CTPfragment::lvl1AcceptBunch(rob)); // L1A bunch position
153  result->setTurnCounter(CTPfragment::turnCounter(rob)); // Turn counter
154 
155  // Record result
156  SG::WriteHandle<xAOD::CTPResult> ctpResultWriteHandle = SG::makeHandle( m_outKeyCTPResult, eventContext );
157  ATH_CHECK( ctpResultWriteHandle.record( std::move(result), std::move(resultAux) ));
158  ATH_MSG_DEBUG("Created xAOD::CTPResult from bytestream");
159 
160  return StatusCode::SUCCESS;
161 }
162 
163 
164 // -----------------------------------------------------------------------------
165 // xAOD->BS conversion
166 // -----------------------------------------------------------------------------
167 StatusCode CTPResultByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf, const EventContext& eventContext) {
168 
169  // Retrieve the xAOD::CTPResult object
170  SG::ReadHandle<xAOD::CTPResult> result = SG::makeHandle<xAOD::CTPResult>(m_inKeyCTPResult, eventContext);
171  ATH_CHECK(result.isValid());
172 
173  // Get CTP version
174  unsigned int ctpVersionNumber = result->ctpVersionNumber();
175  CTPdataformatVersion ctpDataFormat(ctpVersionNumber);
176 
177  // Compute rodSize from object content
178  size_t totalPerBunchWords = 0;
179  for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
180  totalPerBunchWords += result->getTIPWords(bunch).size();
181  totalPerBunchWords += result->getTBPWords(bunch).size();
182  totalPerBunchWords += result->getTAPWords(bunch).size();
183  totalPerBunchWords += result->getTAVWords(bunch).size();
184  }
185 
186  size_t rodSize = ctpDataFormat.getNumberTimeWords() // time words
187  + totalPerBunchWords // TIP/TBP/TAP/TAV words
188  + result->additionalWords().size(); // extra words
189 
190  // Allocate memory
191  clearCache(eventContext);
192  uint32_t* data = newRodData(eventContext, rodSize);
193  std::vector<uint32_t> vDataWords(rodSize, 0);
194 
195  size_t idx = 0;
196 
197  // Time words
198  if (ctpDataFormat.getNumberTimeWords() >= 2) {
199  vDataWords[idx++] = result->timeNanoSec();
200  vDataWords[idx++] = result->timeSec();
201  } else {
202  ATH_MSG_WARNING("Unexpected number of time words: " << ctpDataFormat.getNumberTimeWords());
203  }
204 
205  // TIP/TBP/TAP/TAV words per bunch
206  for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
207 
208  // Helper lambda function
209  auto copyWords = [&](const std::vector<uint32_t>& words, const char* tag) -> StatusCode {
210  for (size_t i = 0; i < words.size(); ++i) {
211  if (idx >= vDataWords.size()) {
212  ATH_MSG_ERROR(tag << " write out-of-bounds: idx = " << idx << " >= ROD size = " << vDataWords.size());
213  return StatusCode::FAILURE;
214  }
215  vDataWords[idx++] = words[i];
216  }
217  return StatusCode::SUCCESS;
218  };
219 
220  ATH_CHECK(copyWords(result->getTIPWords(bunch), "TIP"));
221  ATH_CHECK(copyWords(result->getTBPWords(bunch), "TBP"));
222  ATH_CHECK(copyWords(result->getTAPWords(bunch), "TAP"));
223  ATH_CHECK(copyWords(result->getTAVWords(bunch), "TAV"));
224  }
225 
226  // Additional words
227  for (size_t i = 0; i < result->additionalWords().size(); ++i) {
228  if (idx >= vDataWords.size()) {
229  ATH_MSG_ERROR("Additional word write out-of-bounds at idx = " << idx);
230  return StatusCode::FAILURE;
231  }
232  vDataWords[idx++] = result->additionalWords()[i];
233  }
234 
235  // Sanity check that all words accounted for given xAOD::CTPResult object
236  ATH_CHECK(idx == rodSize);
237 
238  // Fill ROD
239  for (size_t i = 0; i < rodSize; ++i) {
240  data[i] = vDataWords[i];
241  }
242 
243  // Create ROB fragment
244  vrobf.push_back(newRobFragment(eventContext, result->sourceID(), rodSize, data, m_detEvType));
246  rob->rod_minor_version(result->headerFormatVersion() & 0xffffu);
247 
248  ATH_MSG_DEBUG("Encoded xAOD::CTPResult to bytestream");
249 
250  return StatusCode::SUCCESS;
251 }
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
CTPResultByteStreamTool.h
OFFLINE_FRAGMENTS_NAMESPACE::PointerType
const DataType * PointerType
Definition: RawEvent.h:25
CxxUtils::span::begin
constexpr iterator begin() noexcept
Return a begin iterator.
CTPResult.h
Undefined
@ Undefined
Definition: MaterialTypes.h:8
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
CxxUtils::span::end
U * end
Definition: span.h:102
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
CTPResultByteStreamTool::convertToBS
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const EventContext &eventContext) override
Definition: CTPResultByteStreamTool.cxx:167
CTPResultByteStreamTool::DataStatus
Definition: CTPResultByteStreamTool.h:46
CTPResultByteStreamTool::convertFromBS
virtual StatusCode convertFromBS(const std::vector< const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment * > &vrobf, const EventContext &eventContext) const override
Definition: CTPResultByteStreamTool.cxx:47
skel.it
it
Definition: skel.GENtoEVGEN.py:407
CTPResultUtils.h
CTPResultByteStreamTool::m_inKeyCTPResult
SG::ReadHandleKey< xAOD::CTPResult > m_inKeyCTPResult
Definition: CTPResultByteStreamTool.h:54
PixelByteStreamErrors::Decoding
@ Decoding
Definition: PixelByteStreamErrors.h:14
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
python.CTPfragment.numberExtraPayloadWords
def numberExtraPayloadWords(rob)
Definition: CTPfragment.py:90
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment
eformat::ROBFragment< PointerType > ROBFragment
Definition: RawEvent.h:27
CxxUtils::span
Simplified version of the C++20 std::span.
Definition: span.h:61
CTPResultByteStreamTool::DataStatus::status_info
uint32_t status_info
Definition: CTPResultByteStreamTool.h:50
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
span.h
Simplified version of the C++20 std::span.
CTPResultAuxInfo.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
calibdata.exception
exception
Definition: calibdata.py:495
CTPResultByteStreamTool::m_detEvType
Gaudi::Property< uint16_t > m_detEvType
Definition: CTPResultByteStreamTool.h:59
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Preparation.mode
mode
Definition: Preparation.py:107
CTPResultByteStreamTool::DataStatus::rod_error
bool rod_error
Definition: CTPResultByteStreamTool.h:48
ROBF
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment ROBF
Definition: ByteStreamMergeOutputSvc.cxx:16
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment
eformat::write::ROBFragment ROBFragment
Definition: RawEvent.h:33
CTPResultByteStreamTool::m_outKeyCTPResult
SG::WriteHandleKey< xAOD::CTPResult > m_outKeyCTPResult
Definition: CTPResultByteStreamTool.h:55
PlotCalibFromCool.words
words
Definition: PlotCalibFromCool.py:51
python.CTPfragment.ctpFormatVersion
def ctpFormatVersion(rob)
Definition: CTPfragment.py:61
CTPResultUtils::initialize
void initialize(xAOD::CTPResult &ctpRes, const uint32_t ctpVersionNumber, std::vector< uint32_t > &data, const uint32_t nExtraWords)
Initialize the object using xAOD::Header, xAOD::Trailer, and the payload data.
Definition: CTPResultUtils.cxx:23
python.CTPfragment.lvl1AcceptBunch
def lvl1AcceptBunch(rob)
Definition: CTPfragment.py:147
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
CTPResultByteStreamTool::initialize
virtual StatusCode initialize() override
Definition: CTPResultByteStreamTool.cxx:29
WROBF
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
Definition: eFexByteStreamTool.cxx:27
CTPResultByteStreamTool::DataStatus::status_word
uint32_t status_word
Definition: CTPResultByteStreamTool.h:49
DataType
OFFLINE_FRAGMENTS_NAMESPACE::PointerType DataType
Definition: CTPResultByteStreamTool.cxx:22
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
CTPResultByteStreamTool::DataStatus::rob_error
bool rob_error
Definition: CTPResultByteStreamTool.h:47
merge.status
status
Definition: merge.py:16
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:23
CTPResultByteStreamTool::m_robIds
Gaudi::Property< std::vector< uint32_t > > m_robIds
Definition: CTPResultByteStreamTool.h:58
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7