ATLAS Offline Software
ITkStripsRodDecoder.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 #include "ITkStripsRodDecoder.h"
6 
11 
13 
14 #include <algorithm>
15 #include <array>
16 #include <utility>
17 
18 // Initialize
19 
21 {
22 
23  // Retrieve cabling tool
24  ATH_CHECK(m_cabling.retrieve());
25  ATH_MSG_DEBUG("Retrieved tool " << m_cabling);
29  ATH_CHECK(m_configTool.retrieve());
30  const InDetDD::SCT_DetectorManager* itkStripsDetManager{nullptr};
31  ATH_CHECK(detStore()->retrieve(itkStripsDetManager, "ITkStrip"));
32  const InDetDD::SiDetectorElementCollection* sctDetElementColl{itkStripsDetManager->getDetectorElementCollection()};
33  for (const InDetDD::SiDetectorElement* element: *sctDetElementColl) {
34  if (element->swapPhiReadoutDirection()) {
35  m_swapPhiReadoutDirection[element->identifyHash()] = true;
36  }
37  }
38  ATH_MSG_DEBUG("Initialization was successful");
39  return StatusCode::SUCCESS;
40 }
41 
42 // fillCollection method
44  SCT_RDO_Container& /*rdoIDCont*/,
45  IDCInDetBSErrContainer& errorsIDC,
46  DataPool<SCT3_RawData>* dataItemsPool,
47  const EventContext& /*ctx*/,
48  const std::vector<IdentifierHash>* vecHash) const
49 {
50  SCT_RodDecoderErrorsHelper errs{errorsIDC}; // on destruction will fill the IDC
51 
52  StatusCode sc{StatusCode::SUCCESS};
53 
55  data.reset();
56 
57  CacheHelper cache; // For the trigger
58  cache.vecHash = vecHash;
59 
61  const unsigned long int vecROBDataSize{robFrag.rod_ndata()};
62 
63  robFrag.rod_data(vecROBData);
64  // Loop over header, hit element, flagged ABCD error, raw data, trailer words
65 
66  const uint8_t* vecROBData_8bits = reinterpret_cast<const uint8_t*>(vecROBData);
67  const size_t total_bytes = vecROBDataSize * sizeof(uint32_t);
68 
69  for (size_t i = 0; i + 9 < total_bytes; i += 10) { // 10 bytes per package
70  //Read Header
71  bool hasError{false};
72  uint16_t header = (vecROBData_8bits[i] << 8) | vecROBData_8bits[i + 1];
73 
74  uint8_t type = (header >> 11) & 0x1F;
75 
76  // Useful information
77  // uint8_t l0tag = (header >> 7) & 0xF;
78  // uint8_t bcid_low = (header >> 4) & 0x7;
79  // uint8_t bcid_xor = header & 0xF;
80 
81  if (type == 0x03) { // PR Header
82  bool breakNow{false};
83  ATH_MSG_DEBUG("PR Packet Found");
84  if (hasError) sc = StatusCode::RECOVERABLE;
85  if (breakNow) break;
86  } else {
87  ATH_MSG_WARNING("Unexpected packet type (not PR): 0x" << std::hex << int(type));
88  continue;
89  }
90  for (int j = 0; j < 4; ++j) {
91  uint16_t cluster = (vecROBData_8bits[i + 2 + j * 2] << 8) | vecROBData_8bits[i + 3 + j * 2];
92  if (cluster == 0x7FFF){
93  ATH_MSG_DEBUG("Cluster [" << j << "] empty ");
94  }
95  }
96  }
97 
98  // Create the last RDO of the last link of the event
99  if (data.isStripValid()) {
100  if (not data.isSaved(false) and data.isOldStripValid()) {
101  const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
102  if (rdoMade == -1) {
103  sc = StatusCode::RECOVERABLE;
104  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
105  }
106  else {
107  data.setSaved(false, rdoMade);
108  }
109  }
110  }
111 
112  for (auto& [hash, rdoColl] : data.rdoCollMap) {
113  if (rdoColl==nullptr) continue; // nullptr means the collection is already filled.
114 
115  if (rdoColl->empty()) { // Empty collection is not filled.
116  rdoColl.reset();
117  errs.removeIfEmpty(hash); // To get the same result as before. Not sure whether we need this.
118  continue;
119  }
120 
121  ATH_CHECK(data.writeHandleMap[hash].addOrDelete(std::move(rdoColl)));
122  }
123 
124  if (sc.isFailure()) ATH_MSG_DEBUG("One or more ByteStream errors found ");
125  return sc;
126 }
127 
128 // makeRDO method
129 
130 int ITkStripsRodDecoder::makeRDO(const bool isOld,
131  SharedData& data,
132  CacheHelper& cache,
133  DataPool<SCT3_RawData>* dataItemsPool) const
134 {
135  // If the link is already decoded, RDO will not be created.
136  SCT_RDO_Collection* rdoColl{data.rdoCollMap[data.linkIDHash].get()};
137  if (rdoColl==nullptr) return 0;
138 
139  int strip{isOld ? data.oldStrip : data.strip};
140  if (((strip & 0x7F) + (data.groupSize-1) >= N_STRIPS_PER_CHIP) or (strip<0) or (strip>=N_STRIPS_PER_SIDE)) {
141  ATH_MSG_WARNING("Cluster with " << data.groupSize << " strips, starting at strip " << strip
142  << " in collection " << data.linkIDHash << " out of range. Will not make RDO");
143  return -1;
144  }
145 
146  // This option is for the trigger, if there is a vecHash* given, test it!
147  if (cache.vecHash) {
148  if (data.linkIDHash == cache.skipHash) {
149  ATH_MSG_VERBOSE("Collection for Hash not to be decoded, skip");
150  return 0;
151  }
152  else if (data.linkIDHash != cache.lastHash) {
153  cache.lastHash = data.linkIDHash;
154  // Maybe the new hash is not in the list, so test it
155  std::vector<IdentifierHash>::const_iterator hashIDIterator{find(cache.vecHash->begin(),
156  cache.vecHash->end(),
157  data.linkIDHash)};
158  if (hashIDIterator == cache.vecHash->end()) {
159  ATH_MSG_VERBOSE("Collection for Hash not to be decoded, skip");
160  // Remember this one, so that we do not find(...) forever
161  cache.skipHash = data.linkIDHash;
162  return 0;
163  }
164  }
165  }
166 
167  // See if strips go from 0 to N_STRIPS_PER_SIDE-1(=767) or vice versa
168  if (m_swapPhiReadoutDirection[data.linkIDHash]) {
170  strip = strip-(data.groupSize-1);
171  }
172 
173  // Get identifier from the hash, this is not nice
174  const Identifier digitID{m_itkStripsID->strip_id(data.collID, strip)};
175  if (not m_itkStripsID->is_sct(digitID)) {
176  ATH_MSG_WARNING("Cluster with invalid Identifier. Will not make RDO");
177  return -1;
178  }
179 
180  const unsigned int rawDataWord{static_cast<unsigned int>(data.groupSize | (strip << 11) | (data.timeBin <<22) | (data.errors << 25))};
181 
182  ATH_MSG_DEBUG("Output Raw Data " << std::hex << " Coll " << data.collID.getString()
183  << ":-> " << m_itkStripsID->print_to_string(digitID) << std::dec);
184 
185  // Now the Collection is there for sure. Create RDO and push it into Collection.
186  m_nRDOs++;
187 
188  if(dataItemsPool){
189  SCT3_RawData* sct_rdo = dataItemsPool->nextElementPtr();
190  (*sct_rdo) = SCT3_RawData(digitID, rawDataWord, &(data.errorHit));
191  rdoColl->push_back(sct_rdo);
192  }else{
193  rdoColl->push_back(std::make_unique<SCT3_RawData>(digitID, rawDataWord, &(data.errorHit)));
194  }
195  return 1;
196 }
197 
198 // addRODError method
199 
201  SCT_RodDecoderErrorsHelper& /*errs*/,
202  const std::unordered_set<IdentifierHash>* /*foundHashes*/) const
203 {
204  return StatusCode::SUCCESS;
205 }
206 
207 // addSingleError method
208 
211  SCT_RodDecoderErrorsHelper& /*errs*/) const
212 {
213  return StatusCode::SUCCESS;
214 }
215 
217  const uint32_t robID,
218  SharedData& data,
219  SCT_RDO_Container& rdoIDCont,
220  DataPool<SCT3_RawData>* dataItemsPool,
221  CacheHelper& cache,
223  bool& hasError,
224  bool& breakNow,
225  const EventContext& ctx) const
226 {
227  StatusCode sc{StatusCode::SUCCESS};
228 
229  data.foundHeader = true;
230  m_headNumber++;
231 
232  // Create the last RDO of the previous link if any
233  if (data.isStripValid()) {
234  if (not data.isSaved(false) and data.isOldStripValid()) {
235 
236  const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
237  if (rdoMade == -1) {
238  hasError = true;
239  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
240  }
241  else {
242  data.setSaved(false, rdoMade);
243  }
244  }
245  }
246 
247  // Everything is set to default for a new hunt of RDO
248  data.reset();
249 
250  // Link Number (or stream) in the ROD fragment
251  const int rodlinkNumber{static_cast<int>(inData & 0x7F)};
252 
253  // This is the real calculation for the offline
254  data.linkNumber = (((rodlinkNumber >>4)&0x7)*12+(rodlinkNumber &0xF));
255  const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
257  if ((onlineID ==0) or (data.linkNumber > 95)) {
258  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
259  hasError = true;
260  ATH_MSG_DEBUG("Header: xxx Link number out of range (skipping following data)"
261  << std::dec << data.linkNumber);
262  breakNow = true;
263  return sc;
264  }
265  else {
266  hash = m_cabling->getHashFromOnlineId(onlineID, ctx);
267  if (hash.is_valid()) {
268  data.setCollection(m_itkStripsID, hash, rdoIDCont, dataItemsPool, errs);
269  }
270  else {
271  std::stringstream msg;
272  msg <<std::hex << onlineID;
273  ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
274  }
275  }
276  // Look for masked off links - bit 7
277  if ((inData >> 7) & 0x1) {
278  ATH_MSG_DEBUG("Masked link " << onlineID << " " << data.linkIDHash);
279  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::MaskedLink, errs));
280  hasError = true;
281  }
282  if (inData & 0x800) {
283  ATH_MSG_DEBUG(" Header: xxx TimeOut Error " << data.linkIDHash);
285  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TimeOutError, errs));
286  hasError = true;
287  }
288 
289  if (inData & 0x1000) {
290  ATH_MSG_DEBUG(" Header: xxx Preamble Error " << data.linkIDHash);
292  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::PreambleError, errs));
293  hasError = true;
294  }
295 
296  if (inData & 0x400) {
297  ATH_MSG_DEBUG(" Header: xxx LVL1 ID Error " << data.linkIDHash);
299  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::LVL1IDError, errs));
300  hasError = true;
301  }
302 
303  if (inData & 0x200) {
304  ATH_MSG_DEBUG(" Header: xxx BCID Error " << data.linkIDHash);
305  m_headErrorBCID++;
307  hasError = true;
308  }
309 
310  if ((inData & 0xF) > 11) {
311  ATH_MSG_DEBUG(" Header: xxx Error in formatter " << data.linkIDHash);
313  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::FormatterError, errs));
314  hasError = true;
315  }
316  if (!hasError and not hash.is_valid()) {
317  std::stringstream msg;
318  msg <<std::hex << onlineID;
319  ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
320  hasError = true;
321  }
322 
323  data.condensedMode = static_cast<bool>(inData & 0x100);
324 
325  return sc;
326 }
327 
329  const uint32_t robID,
330  SharedData& data,
332  bool& hasError) const
333 {
334  StatusCode sc{StatusCode::SUCCESS};
335 
336  if (not data.foundHeader) {
337  ATH_MSG_WARNING(" Missing link header in ROD " << std::hex << robID << std::dec);
338  data.foundMissingLinkHeaderError = true;
340  hasError = true;
341  return sc;
342  }
343 
344  ATH_MSG_DEBUG(" xxx Raw Data Mode " << std::hex << inData << std::dec << ": Config Data Mode ");
345  // Too many errors in the BS for the ROD to decode the data
346  m_configDataBit++;
347  ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::RawError, errs));
348  hasError = true;
349 
350  return sc;
351 }
352 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
ITkStripsRodDecoder::m_headErrorFormatter
std::atomic_uint m_headErrorFormatter
Total number of formatter errors in the header data.
Definition: ITkStripsRodDecoder.h:359
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
ITkStripsRodDecoder::makeRDO
int makeRDO(const bool isOld, SharedData &data, CacheHelper &cache, DataPool< SCT3_RawData > *dataItemsPool) const
Builds RawData RDO and adds to RDO container.
Definition: ITkStripsRodDecoder.cxx:130
ITkStripsRodDecoder::CacheHelper
Temp object to help with trigger caching.
Definition: ITkStripsRodDecoder.h:76
ITkStripsRodDecoder::fillCollection
virtual StatusCode fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &robFrag, SCT_RDO_Container &rdoIDCont, IDCInDetBSErrContainer &errs, DataPool< SCT3_RawData > *dataItemsPool, const EventContext &ctx, const std::vector< IdentifierHash > *vecHash=nullptr) const override
Fill SCT RDO Collection with decoded ROB data.
Definition: ITkStripsRodDecoder.cxx:43
SiliconTech::strip
@ strip
InDetDD::SCT_DetectorManager
Definition: SCT_DetectorManager.h:49
ITkStripsRodDecoder::addSingleError
StatusCode addSingleError(const IdentifierHash &hashID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs) const
Add single eror.
Definition: ITkStripsRodDecoder.cxx:209
header
Definition: hcg.cxx:526
InDetDD::SiDetectorElementCollection
Definition: SiDetectorElementCollection.h:27
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:558
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
AtlasDetectorID::is_sct
bool is_sct(Identifier id) const
Definition: AtlasDetectorID.h:777
IDCInDetBSErrContainer
IDC like storage for BS errors, TODO, customise implementation further so that we store int rather th...
Definition: IDCInDetBSErrContainer.h:19
ITkStripsRodDecoder::processHeader
StatusCode processHeader(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RDO_Container &rdoIDCont, DataPool< SCT3_RawData > *dataItemsPool, CacheHelper &cache, SCT_RodDecoderErrorsHelper &errs, bool &hasError, bool &breakNow, const EventContext &ctx) const
Process header word.
Definition: ITkStripsRodDecoder.cxx:216
ITkStripsRodDecoder::addRODError
StatusCode addRODError(uint32_t rodID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs, const std::unordered_set< IdentifierHash > *foundHashes=nullptr) const
Add an error for each wafer in the problematic ROD.
Definition: ITkStripsRodDecoder.cxx:200
ITkStripsRodDecoder::m_headErrorLvl1ID
std::atomic_uint m_headErrorLvl1ID
Total number of Lvl1ID errors in the header data.
Definition: ITkStripsRodDecoder.h:353
ITkStripsRodDecoder.h
InDetRawDataContainer
Definition: InDetRawDataContainer.h:27
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ITkStripsRodDecoder::m_contextITk
IdContext m_contextITk
"Context" of an expanded identifier (ExpandedIdentifier) for compact or hash versions (Identifier32 o...
Definition: ITkStripsRodDecoder.h:314
SCT_ID::wafer_context
IdContext wafer_context() const
Definition: SCT_ID.h:705
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
ITkStripsRodDecoder::m_headErrorBCID
std::atomic_uint m_headErrorBCID
Total number of BCID errors in the header data.
Definition: ITkStripsRodDecoder.h:350
ITkStripsRodDecoder::m_nRDOs
std::atomic_uint m_nRDOs
Total number of SCT RDOs created.
Definition: ITkStripsRodDecoder.h:395
ITkStripsRodDecoder::m_itkStripsID
const SCT_ID * m_itkStripsID
Identifier helper class for the SCT subdetector that creates compact Identifier objects and Identifie...
Definition: ITkStripsRodDecoder.h:310
OFFLINE_FRAGMENTS_NAMESPACE::PointerType
const DataType * PointerType
Definition: RawEvent.h:25
DataPool::nextElementPtr
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
ITkStripsRodDecoder::CacheHelper::skipHash
IdentifierHash skipHash
Definition: ITkStripsRodDecoder.h:77
SCT_ID::wafer_hash_max
size_type wafer_hash_max() const
Definition: SCT_ID.cxx:646
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:93
ITkStripsRodDecoder::m_cabling
ToolHandle< IITkStripCablingTool > m_cabling
Providing mappings of online and offline identifiers and also serial numbers.
Definition: ITkStripsRodDecoder.h:317
eformat::ROBFragment
Definition: L1CaloBsDecoderUtil.h:12
lumiFormat.i
int i
Definition: lumiFormat.py:85
ITkStripsRodDecoder::N_STRIPS_PER_SIDE
@ N_STRIPS_PER_SIDE
Definition: ITkStripsRodDecoder.h:118
ITkStripsRodDecoder::N_STRIPS_PER_CHIP
@ N_STRIPS_PER_CHIP
Definition: ITkStripsRodDecoder.h:117
SCT3_RawData
Definition: SCT3_RawData.h:24
ITkStripsRodDecoder::SharedData
Struct to hold data shared in methods used in fillCollection method.
Definition: ITkStripsRodDecoder.h:122
ITkStripsRodDecoder::m_numMissingLinkHeader
std::atomic_uint m_numMissingLinkHeader
Total number of missing link headers.
Definition: ITkStripsRodDecoder.h:410
RawEvent.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
ITkStripsRodDecoder::m_headNumber
std::atomic_uint m_headNumber
Total number of decoded header data.
Definition: ITkStripsRodDecoder.h:344
InDetRawDataCollection
Definition: InDetRawDataCollection.h:31
ITkStripsRodDecoder::CacheHelper::vecHash
const std::vector< IdentifierHash > * vecHash
Definition: ITkStripsRodDecoder.h:78
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
TRTByteStreamErrors::BCIDError
@ BCIDError
Definition: ITRT_ByteStream_ConditionsSvc.h:19
ITkStripsRodDecoder::m_configTool
ToolHandle< ISCT_ConfigurationConditionsTool > m_configTool
Service that keeps track of configuration conditions.
Definition: ITkStripsRodDecoder.h:323
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
AtlasDetectorID::print_to_string
std::string print_to_string(Identifier id, const IdContext *context=0) const
or provide the printout in string form
Definition: AtlasDetectorID.cxx:418
IdentifierHash.h
SCT_ByteStreamErrors::ErrorType
ErrorType
SCT byte stream error type enums used in SCT_RodDecoder, SCT_ByteStreamErrorsTool,...
Definition: SCT_ByteStreamErrors.h:178
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
SiDetectorElementCollection.h
SCT_RodDecoderErrorsHelper
allows to accumulate errors in one fillColection call
Definition: ITkStripsRodDecoder.h:38
SiDetectorElement.h
ITkStripsRodDecoder::m_headErrorPreamble
std::atomic_uint m_headErrorPreamble
Total number of preamble errors in the header data.
Definition: ITkStripsRodDecoder.h:362
ITkStripsRodDecoder::m_configDataBit
std::atomic_uint m_configDataBit
Total number of configuration data for raw data.
Definition: ITkStripsRodDecoder.h:374
ITkStripsRodDecoder::CacheHelper::lastHash
IdentifierHash lastHash
Definition: ITkStripsRodDecoder.h:77
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DataPool
a typed memory pool that saves time spent allocation small object. This is typically used by containe...
Definition: DataPool.h:63
ITkStripsRodDecoder::initialize
virtual StatusCode initialize() override
Initialize.
Definition: ITkStripsRodDecoder.cxx:20
SCT_DetectorManager.h
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
ITkStripsRodDecoder::processRawData
StatusCode processRawData(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError) const
Process raw data word.
Definition: ITkStripsRodDecoder.cxx:328
ITkStripsRodDecoder::m_headErrorTimeout
std::atomic_uint m_headErrorTimeout
Total number of timeout errors in the header data.
Definition: ITkStripsRodDecoder.h:356
SCT_ID::strip_id
Identifier strip_id(int barrel_ec, int layer_disk, int phi_module, int eta_module, int side, int strip) const
For an individual strip.
Definition: SCT_ID.h:535
ITkStripsRodDecoder::m_swapPhiReadoutDirection
std::vector< bool > m_swapPhiReadoutDirection
Swap phi readout direction.
Definition: ITkStripsRodDecoder.h:413
Identifier
Definition: IdentifierFieldParser.cxx:14