ATLAS Offline Software
Loading...
Searching...
No Matches
CpmRoiByteStreamV2Tool.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
6#include <numeric>
7#include <set>
8#include <utility>
9
11
12#include "GaudiKernel/IInterface.h"
13#include "GaudiKernel/MsgStream.h"
14#include "GaudiKernel/StatusCode.h"
15
17
18#include "CpmRoiSubBlockV2.h"
20#include "L1CaloSrcIdMap.h"
21#include "L1CaloUserHeader.h"
22
24
25namespace LVL1BS
26{
27
28// Interface ID
29
30static const InterfaceID IID_ICpmRoiByteStreamV2Tool("CpmRoiByteStreamV2Tool",
31 1, 1);
32
37
38// Constructor
39
41 const std::string &name,
42 const IInterface *parent)
43 : AthAlgTool(type, name, parent),
44 m_robDataProvider("ROBDataProviderSvc", name),
45 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
46 m_crates(4), m_modules(14),
47 m_subDetector (eformat::TDAQ_CALO_CLUSTER_PROC_ROI)
48{
49 declareInterface<CpmRoiByteStreamV2Tool>(this);
50
51 declareProperty("ErrorTool", m_errorTool,
52 "Tool to collect errors for monitoring");
53 declareProperty("CrateOffsetHw", m_crateOffsetHw = 8,
54 "Offset of CP crate numbers in bytestream");
55 declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
56 "Offset of CP crate numbers in RDOs");
57
58 // Properties for reading bytestream only
59 declareProperty("ROBSourceIDs", m_sourceIDsProp,
60 "ROB fragment source identifiers");
61 declareProperty("ROBSourceIDsRoIB", m_sourceIDsRoIBProp,
62 "ROB fragment source identifiers for RoIBs");
63
64 // Properties for writing bytestream only
65 declareProperty("DataVersion", m_version = 2,
66 "Format version number in sub-block header");
67 declareProperty("DataFormat", m_dataFormat = 1,
68 "Format identifier (0-1) in sub-block header");
69 declareProperty("SlinksPerCrate", m_slinks = 1,
70 "The number of S-Links per crate");
71 declareProperty("CrateMin", m_crateMin = 0,
72 "Minimum crate number, allows partial output");
73 declareProperty("CrateMax", m_crateMax = m_crates - 1,
74 "Maximum crate number, allows partial output");
75
76 declareProperty("IsM7Format", m_isM7Format = false,
77 "Set it for M7 raw data");
78
79}
80
81// Destructor
82
86
87// Initialize
88
89
91{
92 ATH_MSG_INFO ("Initializing " << name());
93
94 ATH_CHECK( m_errorTool.retrieve() );
95 ATH_CHECK( m_byteStreamCnvSvc.retrieve() );
96
97 return StatusCode::SUCCESS;
98}
99
100// Convert ROB fragments to CPM RoIs
101
103 const EventContext& ctx,
104 const std::string& sgKey,
105 DataVector<LVL1::CPMTobRoI> *const collection) const
106{
107 const std::vector<uint32_t>& vID(sourceIDs(sgKey));
108 // // get ROB fragments
110 m_robDataProvider->getROBData(ctx, vID, robFrags, "CpmRoiByteStreamV2Tool");
111 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
112 return convert(robFrags, collection);
113}
114
116 const IROBDataProviderSvc::VROBFRAG &robFrags,
117 DataVector<LVL1::CPMTobRoI> *const roiCollection) const
118{
119 const bool debug = msgLvl(MSG::DEBUG);
120 if (debug) msg(MSG::DEBUG);
121
122 // Sub-block for neutral format
123 CpmRoiSubBlockV2 subBlock;
124
125 // Loop over ROB fragments
126
127 int robCount = 0;
128 std::set<uint32_t> dupCheck;
129 std::set<uint32_t> dupRoiCheck;
130 ROBIterator rob = robFrags.begin();
131 ROBIterator robEnd = robFrags.end();
132 for (; rob != robEnd; ++rob)
133 {
134
135 if (debug)
136 {
137 ++robCount;
138 msg() << "Treating ROB fragment " << robCount << endmsg;
139 }
140
141 // Skip fragments with ROB status errors
142
143 uint32_t robid = (*rob)->source_id();
144 if ((*rob)->nstatus() > 0)
145 {
146 ROBPointer robData;
147 (*rob)->status(robData);
148 if (*robData != 0)
149 {
150 m_errorTool->robError(robid, *robData);
151 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
152 continue;
153 }
154 }
155
156 // Skip duplicate fragments
157
158 if (!dupCheck.insert(robid).second)
159 {
161 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
162 continue;
163 }
164
165 // Unpack ROD data (slinks)
166
167 RODPointer payloadBeg;
168 RODPointer payload;
169 RODPointer payloadEnd;
170 (*rob)->rod_data(payloadBeg);
171 payloadEnd = payloadBeg + (*rob)->rod_ndata();
172 payload = payloadBeg;
173 if (payload == payloadEnd)
174 {
175 if (debug) msg() << "ROB fragment empty" << endmsg;
176 continue;
177 }
178
179 // Check identifier
180 const uint32_t sourceID = (*rob)->rod_source_id();
181 if (m_srcIdMap.getRobID(sourceID) != robid ||
182 m_srcIdMap.subDet(sourceID) != m_subDetector ||
183 m_srcIdMap.daqOrRoi(sourceID) != 1 ||
184 (m_srcIdMap.slink(sourceID) != 0 && m_srcIdMap.slink(sourceID) != 2) ||
185 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
186 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates)
187 {
189 if (debug)
190 {
191 msg() << "Wrong source identifier in data: "
192 << MSG::hex << sourceID << MSG::dec << endmsg;
193 }
194 continue;
195 }
196
197 // Check minor version
198 const int minorVersion = (*rob)->rod_version() & 0xffff;
199 if (minorVersion <= m_srcIdMap.minorVersionPreLS1())
200 {
201 if (debug) msg() << "Skipping pre-LS1 data" << endmsg;
202 continue;
203 }
204 const int rodCrate = m_srcIdMap.crate(sourceID);
205 if (debug)
206 {
207 msg() << "Treating crate " << rodCrate
208 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
209 }
210
211 // First word may be User Header
212 if (L1CaloUserHeader::isValid(*payload))
213 {
214 L1CaloUserHeader userHeader(*payload);
215 userHeader.setVersion(minorVersion);
216 const int headerWords = userHeader.words();
217 if (headerWords != 1 )
218 {
220 if (debug) msg() << "Unexpected number of user header words: "
221 << headerWords << endmsg;
222 continue;
223 }
224 for (int i = 0; i < headerWords; ++i) ++payload;
225 }
226
227 // Loop over sub-blocks if there are any
228
229 unsigned int rodErr = L1CaloSubBlock::ERROR_NONE;
230 while (payload != payloadEnd)
231 {
232
234 {
235 subBlock.clear();
236 payload = subBlock.read(payload, payloadEnd);
237 if (debug)
238 {
239 msg() << "CPM RoI sub-block: Crate " << subBlock.crate()
240 << " Module " << subBlock.module() << endmsg;
241 }
242 // Unpack sub-block
243 if (subBlock.dataWords() && !subBlock.unpack())
244 {
245 if (debug)
246 {
247 std::string errMsg(subBlock.unpackErrorMsg());
248 msg() << "CPM RoI sub-block unpacking failed: " << errMsg << endmsg;
249 }
250 rodErr = subBlock.unpackErrorCode();
251 break;
252 }
253 const int numChips = 8;
254 const int numLocs = 2;
255 const int numTypes = 2;
256 for (int chip = 0; chip < numChips; ++chip)
257 {
258 for (int loc = 0; loc < numLocs; ++loc)
259 {
260 for (int type = 0; type < numTypes; ++type)
261 {
262 const LVL1::CPMTobRoI roi = subBlock.roi(chip, loc, type);
263 if (roi.energy() || roi.isolation())
264 {
265 roiCollection->push_back(new LVL1::CPMTobRoI(roi));
266 }
267 }
268 }
269 }
270 }
271 else
272 {
273 // Just RoI word
274 LVL1::CPMTobRoI roi;
275 uint32_t roiWord = *payload;
276 if (m_isM7Format)
277 roiWord |= 0x80000000;
278
279 if (roi.setRoiWord(roiWord))
280 {
281 if (roi.crate() != rodCrate - m_crateOffsetHw)
282 {
283 if (debug) msg() << "Inconsistent RoI crate number: "
284 << roi.crate() << endmsg;
286 break;
287 }
288 if (roi.cpm() == 0 || roi.cpm() > m_modules)
289 {
290 if (debug) msg() << "Invalid CPM number: "
291 << roi.cpm() << endmsg;
293 break;
294 }
295 const uint32_t location = roiWord & 0xffff0000;
296 if (dupRoiCheck.insert(location).second)
297 {
298 if (roi.energy() || roi.isolation())
299 {
300 roiCollection->push_back(new LVL1::CPMTobRoI(roiWord));
301 }
302 }
303 else
304 {
305 if (debug) msg() << "Duplicate RoI word "
306 << MSG::hex << roiWord << MSG::dec << endmsg;
308 break;
309 }
310 }
311 else
312 {
313 if (debug) msg() << "Invalid RoI word "
314 << MSG::hex << roiWord << MSG::dec << endmsg;
316 break;
317 }
318 ++payload;
319 }
320 }
321 if (rodErr != L1CaloSubBlock::ERROR_NONE)
322 m_errorTool->rodError(robid, rodErr);
323 }
324 if (debug)
325 {
326 msg() << "Number of RoIs read = " << roiCollection->size() << endmsg;
327 }
328
329 return StatusCode::SUCCESS;
330}
331
332// Convert CPM RoI to bytestream
333
335 const DataVector<LVL1::CPMTobRoI> *const roiCollection) const
336{
337 const bool debug = msgLvl(MSG::DEBUG);
338 if (debug) msg(MSG::DEBUG);
339
340 // Get the event assembler
342 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
343 "CpmRoiByteStreamV2") );
344 const uint16_t minorVersion = m_srcIdMap.minorVersion();
345 fea->setRodMinorVersion(minorVersion);
346
347 // Pointer to ROD data vector
348
350
351 // Sub-block for neutral format
352 CpmRoiSubBlockV2 subBlock;
353
354 // Set up the container map
355
356 // CPM RoI map
357 CpmRoiMap roiMap;
358 setupCpmRoiMap(roiCollection, roiMap);
359
360 if (debug)
361 {
362 msg() << "Number of RoIs to be written = " << roiCollection->size()
363 << " (collection), " << roiMap.size() << " (map)"
364 << endmsg;
365 }
366 int count = 0;
367 CpmRoiMap::const_iterator mapIter = roiMap.begin();
368 CpmRoiMap::const_iterator mapIterEnd = roiMap.end();
369
370 // Loop over data
371
372 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
373 const int modulesPerSlink = m_modules / m_slinks;
374 for (int crate = m_crateMin; crate <= m_crateMax; ++crate)
375 {
376 const int hwCrate = crate + m_crateOffsetHw;
377
378 // CPM modules are numbered 1 to m_modules
379 for (int module = 1; module <= m_modules; ++module)
380 {
381 const int mod = module - 1;
382
383 // Pack required number of modules per slink
384
385 if (mod % modulesPerSlink == 0)
386 {
387 const int daqOrRoi = 1;
388 const int slink = (m_slinks == 2) ? 2 * (mod / modulesPerSlink)
389 : mod / modulesPerSlink;
390 if (debug)
391 {
392 msg() << "Treating crate " << hwCrate
393 << " slink " << slink << endmsg
394 << "Data Version/Format: " << m_version
395 << " " << m_dataFormat << endmsg;
396 }
397 const uint32_t rodIdCpm = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
399 theROD = fea->getRodData(rodIdCpm);
400 if (neutralFormat)
401 {
402 const L1CaloUserHeader userHeader;
403 theROD->push_back(userHeader.header());
404 }
405 }
406 if (debug) msg() << "Module " << module << endmsg;
407
408 // Create a sub-block (Neutral format only)
409
410 if (neutralFormat)
411 {
412 subBlock.clear();
413 subBlock.setRoiHeader(m_version, hwCrate, module);
414 }
415
416 // Find CPM RoIs for this module
417
418 for (; mapIter != mapIterEnd; ++mapIter)
419 {
420 const LVL1::CPMTobRoI *const roi = mapIter->second;
421 if (roi->crate() < crate) continue;
422 if (roi->crate() > crate) break;
423 if (roi->cpm() < module) continue;
424 if (roi->cpm() > module) break;
425 if (roi->energy() || roi->isolation())
426 {
427 if (neutralFormat) subBlock.fillRoi(*roi);
428 else theROD->push_back(roi->roiWord());
429 ++count;
430 }
431 }
432
433 // Pack and write the sub-block
434
435 if (neutralFormat)
436 {
437 if ( !subBlock.pack())
438 {
439 msg(MSG::ERROR) << "CPMTobRoI sub-block packing failed" << endmsg;
440 return StatusCode::FAILURE;
441 }
442 if (debug)
443 {
444 msg() << "CPMTobRoI sub-block data words: "
445 << subBlock.dataWords() << endmsg;
446 }
447 subBlock.write(theROD);
448 }
449 }
450 }
451 if (debug)
452 {
453 msg() << "Number of RoIs written = " << count << endmsg;
454 }
455
456 if (debug) msg() << MSG::dec; // fill seems to leave it in hex
457
458 return StatusCode::SUCCESS;
459}
460
461// Return reference to vector with all possible Source Identifiers
462
463std::vector<uint32_t> CpmRoiByteStreamV2Tool::makeSourceIDs (bool roiDaq) const
464{
465 std::vector<uint32_t> sourceIDs;
466
467 if (roiDaq) {
469 }
470 else {
472 }
473
474 if (sourceIDs.empty()) {
475 const int maxCrates = m_crates + m_crateOffsetHw;
476 const int maxSlinks = m_srcIdMap.maxSlinks();
477 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
478 {
479 for (int slink = 0; slink < maxSlinks; ++slink)
480 {
481 const int daqOrRoi = 1;
482 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
484 const uint32_t robId = m_srcIdMap.getRobID(rodId);
485 if (roiDaq)
486 {
487 if (slink < 2) sourceIDs.push_back(robId);
488 }
489 else if (slink >= 2) sourceIDs.push_back(robId);
490 }
491 }
492
493 }
494 return sourceIDs;
495}
496
497const std::vector<uint32_t> &CpmRoiByteStreamV2Tool::sourceIDs(
498 const std::string &sgKey) const
499{
500 const std::string flag("RoIB");
501 const std::string::size_type pos = sgKey.find(flag);
502 const bool roiDaq =
503 (pos == std::string::npos || pos != sgKey.length() - flag.length());
504
505 if (roiDaq) {
506 static const std::vector<uint32_t> sourceIDs = makeSourceIDs(roiDaq);
507 return sourceIDs;
508 }
509 else {
510 static const std::vector<uint32_t> sourceIDsRoIB = makeSourceIDs(roiDaq);
511 return sourceIDsRoIB;
512 }
513}
514
515// Set up CPM RoI map
516
518 const roiCollection,
519 CpmRoiMap& roiMap) const
520{
521 roiMap.clear();
522 if (roiCollection)
523 {
524 CpmRoiCollection::const_iterator pos = roiCollection->begin();
525 CpmRoiCollection::const_iterator pose = roiCollection->end();
526 for (; pos != pose; ++pos)
527 {
528 const LVL1::CPMTobRoI *const roi = *pos;
529 const int type = roi->type();
530 const int crate = roi->crate();
531 const int cpm = roi->cpm();
532 const int chip = roi->chip();
533 const int loc = roi->location() >> 2;
534 const uint32_t key = (((((((crate << 4) | cpm) << 3) | chip) << 1) | loc) << 1) | type;
535 roiMap.insert(std::make_pair(key, roi));
536 }
537 }
538}
539
540} // end namespace
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
const bool debug
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
Template class for assembling a full atlas raw event from subfragments.
void setRodMinorVersion(uint16_t m)
change the ROD minor version
std::vector< uint32_t > RODDATA
ROD data as a vector of unsigned int.
RODDATA * getRodData(uint32_t id)
get a block of ROD data
std::vector< const ROBF * > VROBFRAG
const eformat::SubDetector m_subDetector
Sub-detector type.
void setupCpmRoiMap(const CpmRoiCollection *roiCollection, CpmRoiMap &roiMap) const
Set up CPM RoI map.
int m_crateOffsetHw
Property: Hardware crate number offset.
int m_crateMin
Property: Minimum crate number when writing out bytestream.
ServiceHandle< IROBDataProviderSvc > m_robDataProvider
int m_crateOffsetSw
Property: Software crate number offset.
virtual StatusCode initialize() override
std::vector< uint32_t > m_sourceIDsRoIBProp
Property: ROB source IDs for RoIB.
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
DataVector< LVL1::CPMTobRoI > CpmRoiCollection
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
int m_version
Property: Sub_block header version.
CpmRoiByteStreamV2Tool(const std::string &type, const std::string &name, const IInterface *parent)
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Property: Error collection tool.
StatusCode convert(const EventContext &ctx, const std::string &robFrags, DataVector< LVL1::CPMTobRoI > *roiCollection) const
Convert ROB fragments to CPM RoIs.
std::map< uint32_t, const LVL1::CPMTobRoI * > CpmRoiMap
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
const int m_modules
Number of CPM modules per crate.
int m_crateMax
Property: Maximum crate number when writing out bytestream.
int m_dataFormat
Property: Data compression format.
ServiceHandle< IByteStreamCnvSvc > m_byteStreamCnvSvc
std::vector< uint32_t > makeSourceIDs(bool roiDaq) const
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
const int m_crates
Number of crates.
const std::vector< uint32_t > & sourceIDs(const std::string &sgKey) const
Return reference to vector with all possible Source Identifiers.
std::vector< uint32_t > m_sourceIDsProp
Property: ROB source IDs.
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
Sub-Block class for CPM RoI data (neutral format) post LS1.
void clear()
Clear all data.
void setRoiHeader(int version, int crate, int module)
Store header.
void fillRoi(LVL1::CPMTobRoI roi)
Store RoI.
LVL1::CPMTobRoI roi(int chip, int loc, int type) const
Return RoI for given chip and location (left/right) and type (em/tau).
int unpackErrorCode() const
Return the unpacking error code.
int dataWords() const
Return number of data words.
static SubBlockWordType wordType(uint32_t word)
Word identification.
void write(FullEventAssembler< L1CaloSrcIdMap >::RODDATA *theROD) const
Output complete packed sub-block to ROD vector.
std::string unpackErrorMsg() const
Return the unpacking error message for printing.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType read(const OFFLINE_FRAGMENTS_NAMESPACE::PointerType beg, const OFFLINE_FRAGMENTS_NAMESPACE::PointerType end)
Input complete packed sub-block from ROD array.
L1Calo User Header class.
static bool isValid(uint32_t word)
Test for valid header word.
void setVersion(int minorVersion)
Set version flag.
int words() const
Return number of header words (should be one).
uint32_t header() const
Return packed header.
uint32_t roiWord() const
Return packed RoI word.
int chip() const
Return CP chip number (0-7).
int location() const
Return location (RoI local coords) (0-7).
bool setRoiWord(uint32_t roiWord)
Set RoI word with ID check.
Definition CPMTobRoI.cxx:57
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
static const InterfaceID IID_ICpmRoiByteStreamV2Tool("CpmRoiByteStreamV2Tool", 1, 1)