ATLAS Offline Software
Loading...
Searching...
No Matches
CpmRoiByteStreamV2Tool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 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 std::string& sgKey,
104 DataVector<LVL1::CPMTobRoI> *const collection) const
105{
106 const std::vector<uint32_t>& vID(sourceIDs(sgKey));
107 // // get ROB fragments
109 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "CpmRoiByteStreamV2Tool");
110 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
111 return convert(robFrags, collection);
112}
113
115 const IROBDataProviderSvc::VROBFRAG &robFrags,
116 DataVector<LVL1::CPMTobRoI> *const roiCollection) const
117{
118 const bool debug = msgLvl(MSG::DEBUG);
119 if (debug) msg(MSG::DEBUG);
120
121 // Sub-block for neutral format
122 CpmRoiSubBlockV2 subBlock;
123
124 // Loop over ROB fragments
125
126 int robCount = 0;
127 std::set<uint32_t> dupCheck;
128 std::set<uint32_t> dupRoiCheck;
129 ROBIterator rob = robFrags.begin();
130 ROBIterator robEnd = robFrags.end();
131 for (; rob != robEnd; ++rob)
132 {
133
134 if (debug)
135 {
136 ++robCount;
137 msg() << "Treating ROB fragment " << robCount << endmsg;
138 }
139
140 // Skip fragments with ROB status errors
141
142 uint32_t robid = (*rob)->source_id();
143 if ((*rob)->nstatus() > 0)
144 {
145 ROBPointer robData;
146 (*rob)->status(robData);
147 if (*robData != 0)
148 {
149 m_errorTool->robError(robid, *robData);
150 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
151 continue;
152 }
153 }
154
155 // Skip duplicate fragments
156
157 if (!dupCheck.insert(robid).second)
158 {
160 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
161 continue;
162 }
163
164 // Unpack ROD data (slinks)
165
166 RODPointer payloadBeg;
167 RODPointer payload;
168 RODPointer payloadEnd;
169 (*rob)->rod_data(payloadBeg);
170 payloadEnd = payloadBeg + (*rob)->rod_ndata();
171 payload = payloadBeg;
172 if (payload == payloadEnd)
173 {
174 if (debug) msg() << "ROB fragment empty" << endmsg;
175 continue;
176 }
177
178 // Check identifier
179 const uint32_t sourceID = (*rob)->rod_source_id();
180 if (m_srcIdMap.getRobID(sourceID) != robid ||
181 m_srcIdMap.subDet(sourceID) != m_subDetector ||
182 m_srcIdMap.daqOrRoi(sourceID) != 1 ||
183 (m_srcIdMap.slink(sourceID) != 0 && m_srcIdMap.slink(sourceID) != 2) ||
184 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
185 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates)
186 {
188 if (debug)
189 {
190 msg() << "Wrong source identifier in data: "
191 << MSG::hex << sourceID << MSG::dec << endmsg;
192 }
193 continue;
194 }
195
196 // Check minor version
197 const int minorVersion = (*rob)->rod_version() & 0xffff;
198 if (minorVersion <= m_srcIdMap.minorVersionPreLS1())
199 {
200 if (debug) msg() << "Skipping pre-LS1 data" << endmsg;
201 continue;
202 }
203 const int rodCrate = m_srcIdMap.crate(sourceID);
204 if (debug)
205 {
206 msg() << "Treating crate " << rodCrate
207 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
208 }
209
210 // First word may be User Header
211 if (L1CaloUserHeader::isValid(*payload))
212 {
213 L1CaloUserHeader userHeader(*payload);
214 userHeader.setVersion(minorVersion);
215 const int headerWords = userHeader.words();
216 if (headerWords != 1 )
217 {
219 if (debug) msg() << "Unexpected number of user header words: "
220 << headerWords << endmsg;
221 continue;
222 }
223 for (int i = 0; i < headerWords; ++i) ++payload;
224 }
225
226 // Loop over sub-blocks if there are any
227
228 unsigned int rodErr = L1CaloSubBlock::ERROR_NONE;
229 while (payload != payloadEnd)
230 {
231
233 {
234 subBlock.clear();
235 payload = subBlock.read(payload, payloadEnd);
236 if (debug)
237 {
238 msg() << "CPM RoI sub-block: Crate " << subBlock.crate()
239 << " Module " << subBlock.module() << endmsg;
240 }
241 // Unpack sub-block
242 if (subBlock.dataWords() && !subBlock.unpack())
243 {
244 if (debug)
245 {
246 std::string errMsg(subBlock.unpackErrorMsg());
247 msg() << "CPM RoI sub-block unpacking failed: " << errMsg << endmsg;
248 }
249 rodErr = subBlock.unpackErrorCode();
250 break;
251 }
252 const int numChips = 8;
253 const int numLocs = 2;
254 const int numTypes = 2;
255 for (int chip = 0; chip < numChips; ++chip)
256 {
257 for (int loc = 0; loc < numLocs; ++loc)
258 {
259 for (int type = 0; type < numTypes; ++type)
260 {
261 const LVL1::CPMTobRoI roi = subBlock.roi(chip, loc, type);
262 if (roi.energy() || roi.isolation())
263 {
264 roiCollection->push_back(new LVL1::CPMTobRoI(roi));
265 }
266 }
267 }
268 }
269 }
270 else
271 {
272 // Just RoI word
273 LVL1::CPMTobRoI roi;
274 uint32_t roiWord = *payload;
275 if (m_isM7Format)
276 roiWord |= 0x80000000;
277
278 if (roi.setRoiWord(roiWord))
279 {
280 if (roi.crate() != rodCrate - m_crateOffsetHw)
281 {
282 if (debug) msg() << "Inconsistent RoI crate number: "
283 << roi.crate() << endmsg;
285 break;
286 }
287 if (roi.cpm() == 0 || roi.cpm() > m_modules)
288 {
289 if (debug) msg() << "Invalid CPM number: "
290 << roi.cpm() << endmsg;
292 break;
293 }
294 const uint32_t location = roiWord & 0xffff0000;
295 if (dupRoiCheck.insert(location).second)
296 {
297 if (roi.energy() || roi.isolation())
298 {
299 roiCollection->push_back(new LVL1::CPMTobRoI(roiWord));
300 }
301 }
302 else
303 {
304 if (debug) msg() << "Duplicate RoI word "
305 << MSG::hex << roiWord << MSG::dec << endmsg;
307 break;
308 }
309 }
310 else
311 {
312 if (debug) msg() << "Invalid RoI word "
313 << MSG::hex << roiWord << MSG::dec << endmsg;
315 break;
316 }
317 ++payload;
318 }
319 }
320 if (rodErr != L1CaloSubBlock::ERROR_NONE)
321 m_errorTool->rodError(robid, rodErr);
322 }
323 if (debug)
324 {
325 msg() << "Number of RoIs read = " << roiCollection->size() << endmsg;
326 }
327
328 return StatusCode::SUCCESS;
329}
330
331// Convert CPM RoI to bytestream
332
334 const DataVector<LVL1::CPMTobRoI> *const roiCollection) const
335{
336 const bool debug = msgLvl(MSG::DEBUG);
337 if (debug) msg(MSG::DEBUG);
338
339 // Get the event assembler
341 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
342 "CpmRoiByteStreamV2") );
343 const uint16_t minorVersion = m_srcIdMap.minorVersion();
344 fea->setRodMinorVersion(minorVersion);
345
346 // Pointer to ROD data vector
347
349
350 // Sub-block for neutral format
351 CpmRoiSubBlockV2 subBlock;
352
353 // Set up the container map
354
355 // CPM RoI map
356 CpmRoiMap roiMap;
357 setupCpmRoiMap(roiCollection, roiMap);
358
359 if (debug)
360 {
361 msg() << "Number of RoIs to be written = " << roiCollection->size()
362 << " (collection), " << roiMap.size() << " (map)"
363 << endmsg;
364 }
365 int count = 0;
366 CpmRoiMap::const_iterator mapIter = roiMap.begin();
367 CpmRoiMap::const_iterator mapIterEnd = roiMap.end();
368
369 // Loop over data
370
371 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
372 const int modulesPerSlink = m_modules / m_slinks;
373 for (int crate = m_crateMin; crate <= m_crateMax; ++crate)
374 {
375 const int hwCrate = crate + m_crateOffsetHw;
376
377 // CPM modules are numbered 1 to m_modules
378 for (int module = 1; module <= m_modules; ++module)
379 {
380 const int mod = module - 1;
381
382 // Pack required number of modules per slink
383
384 if (mod % modulesPerSlink == 0)
385 {
386 const int daqOrRoi = 1;
387 const int slink = (m_slinks == 2) ? 2 * (mod / modulesPerSlink)
388 : mod / modulesPerSlink;
389 if (debug)
390 {
391 msg() << "Treating crate " << hwCrate
392 << " slink " << slink << endmsg
393 << "Data Version/Format: " << m_version
394 << " " << m_dataFormat << endmsg;
395 }
396 const uint32_t rodIdCpm = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
398 theROD = fea->getRodData(rodIdCpm);
399 if (neutralFormat)
400 {
401 const L1CaloUserHeader userHeader;
402 theROD->push_back(userHeader.header());
403 }
404 }
405 if (debug) msg() << "Module " << module << endmsg;
406
407 // Create a sub-block (Neutral format only)
408
409 if (neutralFormat)
410 {
411 subBlock.clear();
412 subBlock.setRoiHeader(m_version, hwCrate, module);
413 }
414
415 // Find CPM RoIs for this module
416
417 for (; mapIter != mapIterEnd; ++mapIter)
418 {
419 const LVL1::CPMTobRoI *const roi = mapIter->second;
420 if (roi->crate() < crate) continue;
421 if (roi->crate() > crate) break;
422 if (roi->cpm() < module) continue;
423 if (roi->cpm() > module) break;
424 if (roi->energy() || roi->isolation())
425 {
426 if (neutralFormat) subBlock.fillRoi(*roi);
427 else theROD->push_back(roi->roiWord());
428 ++count;
429 }
430 }
431
432 // Pack and write the sub-block
433
434 if (neutralFormat)
435 {
436 if ( !subBlock.pack())
437 {
438 msg(MSG::ERROR) << "CPMTobRoI sub-block packing failed" << endmsg;
439 return StatusCode::FAILURE;
440 }
441 if (debug)
442 {
443 msg() << "CPMTobRoI sub-block data words: "
444 << subBlock.dataWords() << endmsg;
445 }
446 subBlock.write(theROD);
447 }
448 }
449 }
450 if (debug)
451 {
452 msg() << "Number of RoIs written = " << count << endmsg;
453 }
454
455 if (debug) msg() << MSG::dec; // fill seems to leave it in hex
456
457 return StatusCode::SUCCESS;
458}
459
460// Return reference to vector with all possible Source Identifiers
461
462std::vector<uint32_t> CpmRoiByteStreamV2Tool::makeSourceIDs (bool roiDaq) const
463{
464 std::vector<uint32_t> sourceIDs;
465
466 if (roiDaq) {
468 }
469 else {
471 }
472
473 if (sourceIDs.empty()) {
474 const int maxCrates = m_crates + m_crateOffsetHw;
475 const int maxSlinks = m_srcIdMap.maxSlinks();
476 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
477 {
478 for (int slink = 0; slink < maxSlinks; ++slink)
479 {
480 const int daqOrRoi = 1;
481 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
483 const uint32_t robId = m_srcIdMap.getRobID(rodId);
484 if (roiDaq)
485 {
486 if (slink < 2) sourceIDs.push_back(robId);
487 }
488 else if (slink >= 2) sourceIDs.push_back(robId);
489 }
490 }
491
492 }
493 return sourceIDs;
494}
495
496const std::vector<uint32_t> &CpmRoiByteStreamV2Tool::sourceIDs(
497 const std::string &sgKey) const
498{
499 const std::string flag("RoIB");
500 const std::string::size_type pos = sgKey.find(flag);
501 const bool roiDaq =
502 (pos == std::string::npos || pos != sgKey.length() - flag.length());
503
504 if (roiDaq) {
505 static const std::vector<uint32_t> sourceIDs = makeSourceIDs(roiDaq);
506 return sourceIDs;
507 }
508 else {
509 static const std::vector<uint32_t> sourceIDsRoIB = makeSourceIDs(roiDaq);
510 return sourceIDsRoIB;
511 }
512}
513
514// Set up CPM RoI map
515
517 const roiCollection,
518 CpmRoiMap& roiMap) const
519{
520 roiMap.clear();
521 if (roiCollection)
522 {
523 CpmRoiCollection::const_iterator pos = roiCollection->begin();
524 CpmRoiCollection::const_iterator pose = roiCollection->end();
525 for (; pos != pose; ++pos)
526 {
527 const LVL1::CPMTobRoI *const roi = *pos;
528 const int type = roi->type();
529 const int crate = roi->crate();
530 const int cpm = roi->cpm();
531 const int chip = roi->chip();
532 const int loc = roi->location() >> 2;
533 const uint32_t key = (((((((crate << 4) | cpm) << 3) | chip) << 1) | loc) << 1) | type;
534 roiMap.insert(std::make_pair(key, roi));
535 }
536 }
537}
538
539} // 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.
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
StatusCode convert(const std::string &robFrags, DataVector< LVL1::CPMTobRoI > *roiCollection) const
Convert ROB fragments to CPM RoIs.
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 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:146
static const InterfaceID IID_ICpmRoiByteStreamV2Tool("CpmRoiByteStreamV2Tool", 1, 1)