ATLAS Offline Software
Loading...
Searching...
No Matches
CpByteStreamV2Tool.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
10#include "GaudiKernel/IInterface.h"
11#include "GaudiKernel/MsgStream.h"
12#include "GaudiKernel/StatusCode.h"
13
15
23
24#include "CmxCpSubBlock.h"
25#include "CmxSubBlock.h"
26#include "CpmSubBlockV2.h"
28#include "L1CaloSrcIdMap.h"
29#include "L1CaloSubBlock.h"
30#include "L1CaloUserHeader.h"
31#include "ModifySlices.h"
32
33#include "CpByteStreamV2Tool.h"
34
35namespace LVL1BS
36{
37
38// Interface ID
39
40static const InterfaceID IID_ICpByteStreamV2Tool("CpByteStreamV2Tool", 1, 1);
41
43{
45}
46
47// Constructor
48
50 const std::string &name,
51 const IInterface *parent)
52 : AthAlgTool(type, name, parent),
53 m_cpmMaps("LVL1::CpmMappingTool/CpmMappingTool"),
54 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
55 m_robDataProvider("ROBDataProviderSvc", name),
56 m_channels(80), m_crates(4), m_modules(14), m_cmxs(2), m_maxTobs(5),
57 m_chips(16), m_locs(4),
58 m_subDetector(eformat::TDAQ_CALO_CLUSTER_PROC_DAQ)
59{
60 declareInterface<CpByteStreamV2Tool>(this);
61
62 declareProperty("CpmMappingTool", m_cpmMaps,
63 "Crate/Module/Channel to Eta/Phi/Layer mapping tool");
64 declareProperty("ErrorTool", m_errorTool,
65 "Tool to collect errors for monitoring");
66
67 declareProperty("CrateOffsetHw", m_crateOffsetHw = 8,
68 "Offset of CP crate numbers in bytestream");
69 declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
70 "Offset of CP crate numbers in RDOs");
71
72 // Properties for reading bytestream only
73 declareProperty("ROBSourceIDs", m_sourceIDsProp,
74 "ROB fragment source identifiers");
75
76 // Properties for writing bytestream only
77 declareProperty("DataVersion", m_version = 2, // <<== CHECK
78 "Format version number in sub-block header");
79 declareProperty("DataFormat", m_dataFormat = 1,
80 "Format identifier (0-1) in sub-block header");
81 declareProperty("SlinksPerCrate", m_slinks = 2,
82 "The number of S-Links per crate");
83 declareProperty("SimulSlices", m_dfltSlices = 1,
84 "The number of slices in the simulation");
85 declareProperty("ForceSlices", m_forceSlices = 0,
86 "If >0, the number of slices in bytestream");
87 declareProperty("CrateMin", m_crateMin = 0,
88 "Minimum crate number, allows partial output");
89 declareProperty("CrateMax", m_crateMax = m_crates - 1,
90 "Maximum crate number, allows partial output");
91
92}
93
94// Destructor
95
99
100// Initialize
101
102
104{
105 ATH_MSG_INFO( "Initializing " << name() );
106
107 CHECK(m_cpmMaps.retrieve());
108 CHECK(m_errorTool.retrieve());
109 CHECK(m_robDataProvider.retrieve());
110 if (m_enableEncoding.value()) {
111 m_byteStreamCnvSvc = serviceLocator()->service("ByteStreamCnvSvc");
112 ATH_CHECK(m_byteStreamCnvSvc.isValid());
113 }
114
115 return StatusCode::SUCCESS;
116}
117
118// Conversion bytestream to CPM towers
120 const EventContext& ctx,
121 const std::string& sgKey,
122 DataVector<LVL1::CPMTower> *const ttCollection) const
123{
124 const std::vector<uint32_t>& vID(sourceIDs());
125 // // get ROB fragments
127 m_robDataProvider->getROBData(ctx, vID, robFrags, "CpByteStreamV2Tool");
128 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
129 return convert(sgKey, robFrags, ttCollection);
130}
131
133 const std::string& sgKey,
134 const IROBDataProviderSvc::VROBFRAG &robFrags,
135 DataVector<LVL1::CPMTower> *const ttCollection) const
136{
137 CpmTowerData data (ttCollection);
138 return convertBs(sgKey, robFrags, data);
139}
140
141// Conversion bytestream to CMX-CP TOBs
143 const EventContext& ctx,
144 const std::string& sgKey,
145 DataVector<LVL1::CMXCPTob> *const tobCollection) const
146{
147 const std::vector<uint32_t>& vID(sourceIDs());
148 // // get ROB fragments
150 m_robDataProvider->getROBData(ctx, vID, robFrags, "CpByteStreamV2Tool");
151 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
152 return convert(sgKey, robFrags, tobCollection);
153}
154
156 const std::string& sgKey,
157 const IROBDataProviderSvc::VROBFRAG &robFrags,
158 DataVector<LVL1::CMXCPTob> *const tobCollection) const
159{
160 CmxCpTobData data (tobCollection);
161 return convertBs(sgKey, robFrags, data);
162}
163
164// Conversion bytestream to CMX-CP hits
166 const EventContext& ctx,
167 const std::string& sgKey,
168 DataVector<LVL1::CMXCPHits> *const hitCollection) const
169{
170 const std::vector<uint32_t>& vID(sourceIDs());
171 // // get ROB fragments
173 m_robDataProvider->getROBData(ctx, vID, robFrags, "CpByteStreamV2Tool");
174 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
175 return convert(sgKey, robFrags, hitCollection);
176}
177
179 const std::string& sgKey,
180 const IROBDataProviderSvc::VROBFRAG &robFrags,
181 DataVector<LVL1::CMXCPHits> *const hitCollection) const
182{
183 CmxCpHitsData data (hitCollection);
184 return convertBs(sgKey, robFrags, data);
185}
186
187// Conversion of CP container to bytestream
188
190{
191 if (not m_enableEncoding.value()) {
192 ATH_MSG_ERROR("Encoding method called while " << m_enableEncoding.name() << "=False");
193 return StatusCode::FAILURE;
194 }
195
196 const bool debug = msgLvl(MSG::DEBUG);
197 if (debug) msg(MSG::DEBUG);
198
199 // Get the event assembler
201 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
202 "CpByteStreamV2") );
203 const uint16_t minorVersion = m_srcIdMap.minorVersion();
204 fea->setRodMinorVersion(minorVersion);
205
206 // Pointer to ROD data vector
207
209
210 LVL1::TriggerTowerKey towerKey;
211
212 // Set up the container maps
213
214 // CPM tower map
215 ConstCpmTowerMap ttMap;
216 setupCpmTowerMap(cp->towers(), ttMap, towerKey);
217
218 // CMX-CP TOB map
219 ConstCmxCpTobMap tobMap;
220 setupCmxCpTobMap(cp->tobs(), tobMap);
221
222 // CMX-CP hits map
223 ConstCmxCpHitsMap hitsMap;
224 setupCmxCpHitsMap(cp->hits(), hitsMap);
225
226 // Loop over data
227
228 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
229 const int modulesPerSlink = m_modules / m_slinks;
230 int timeslices = 1;
231 int trigCpm = 0;
232 int timeslicesNew = 1;
233 int trigCpmNew = 0;
234 for (int crate = m_crateMin; crate <= m_crateMax; ++crate)
235 {
236 const int hwCrate = crate + m_crateOffsetHw;
237
238 // CPM modules are numbered 1 to m_modules
239 for (int module = 1; module <= m_modules; ++module)
240 {
241 const int mod = module - 1;
242
243 // Pack required number of modules per slink
244
245 if (mod % modulesPerSlink == 0)
246 {
247 const int daqOrRoi = 0;
248 const int slink = (m_slinks == 2) ? 2 * (mod / modulesPerSlink)
249 : mod / modulesPerSlink;
250 if (debug)
251 {
252 msg() << "Treating crate " << hwCrate
253 << " slink " << slink << endmsg;
254 }
255 // Get number of CPM slices and triggered slice offset
256 // for this slink
257 if ( ! slinkSlices(crate, module, modulesPerSlink,
258 timeslices, trigCpm,
259 ttMap,
260 tobMap,
261 hitsMap,
262 towerKey))
263 {
264 msg(MSG::ERROR) << "Inconsistent number of slices or "
265 << "triggered slice offsets in data for crate "
266 << hwCrate << " slink " << slink << endmsg;
267 return StatusCode::FAILURE;
268 }
269 timeslicesNew = (m_forceSlices) ? m_forceSlices : timeslices;
270 trigCpmNew = ModifySlices::peak(trigCpm, timeslices, timeslicesNew);
271 if (debug)
272 {
273 msg() << "Data Version/Format: " << m_version
274 << " " << m_dataFormat << endmsg
275 << "Slices/offset: " << timeslices << " " << trigCpm;
276 if (timeslices != timeslicesNew)
277 {
278 msg() << " modified to " << timeslicesNew << " " << trigCpmNew;
279 }
280 msg() << endmsg;
281 }
282 L1CaloUserHeader userHeader;
283 userHeader.setCpm(trigCpmNew);
284 const uint32_t rodIdCpm = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
286 theROD = fea->getRodData(rodIdCpm);
287 theROD->push_back(userHeader.header());
288 }
289 if (debug) msg() << "Module " << module << endmsg;
290
291 // Create a sub-block for each slice (except Neutral format)
292
294 for (int slice = 0; slice < timeslicesNew; ++slice)
295 {
296 CpmSubBlockV2 *const subBlock = new CpmSubBlockV2();
297 subBlock->setCpmHeader(m_version, m_dataFormat, slice,
298 hwCrate, module, timeslicesNew);
299 cpmBlocks.push_back(subBlock);
300 if (neutralFormat) break;
301 }
302
303 // Find CPM towers corresponding to each eta/phi pair and fill
304 // sub-blocks
305
306 for (int chan = 0; chan < m_channels; ++chan)
307 {
308 double eta = 0.;
309 double phi = 0.;
310 int layer = 0;
311 if (m_cpmMaps->mapping(crate, module, chan, eta, phi, layer))
312 {
313 const unsigned int key = towerKey.ttKey(phi, eta);
314 const LVL1::CPMTower *const tt = findCpmTower(key, ttMap);
315 if (tt )
316 {
317 std::vector<int> emData;
318 std::vector<int> hadData;
319 std::vector<int> emError;
320 std::vector<int> hadError;
321 ModifySlices::data(tt->emEnergyVec(), emData, timeslicesNew);
322 ModifySlices::data(tt->hadEnergyVec(), hadData, timeslicesNew);
323 ModifySlices::data(tt->emErrorVec(), emError, timeslicesNew);
324 ModifySlices::data(tt->hadErrorVec(), hadError, timeslicesNew);
325 for (int slice = 0; slice < timeslicesNew; ++slice)
326 {
327 const LVL1::DataError emErrBits(emError[slice]);
328 const LVL1::DataError hadErrBits(hadError[slice]);
329 const int emErr =
330 (emErrBits.get(LVL1::DataError::LinkDown) << 1) |
331 emErrBits.get(LVL1::DataError::Parity);
332 const int hadErr =
333 (hadErrBits.get(LVL1::DataError::LinkDown) << 1) |
334 hadErrBits.get(LVL1::DataError::Parity);
335 const int index = ( neutralFormat ) ? 0 : slice;
336 CpmSubBlockV2 *const subBlock = cpmBlocks[index];
337 subBlock->fillTowerData(slice, chan, emData[slice],
338 hadData[slice], emErr, hadErr);
339 if ((emErrBits.error() >> LVL1::DataError::GLinkParity))
340 {
341 int gLinkParity = emErrBits.get(LVL1::DataError::GLinkParity);
342 int gLinkProtocol = emErrBits.get(LVL1::DataError::GLinkProtocol);
343 int bCNMismatch = emErrBits.get(LVL1::DataError::BCNMismatch);
344 int fIFOOverflow = emErrBits.get(LVL1::DataError::FIFOOverflow);
345 int moduleError = emErrBits.get(LVL1::DataError::ModuleError);
346 int gLinkDown = emErrBits.get(LVL1::DataError::GLinkDown);
347 int gLinkTimeout = emErrBits.get(LVL1::DataError::GLinkTimeout);
348 uint32_t failingBCN = emErrBits.get(LVL1::DataError::FailingBCN);
349 subBlock->setStatus(failingBCN, gLinkTimeout, gLinkDown,
350 moduleError, fIFOOverflow, bCNMismatch,
351 gLinkProtocol, gLinkParity);
352 }
353 }
354 }
355 }
356 }
357
358 // Pack and write the sub-blocks
359
361 for (pos = cpmBlocks.begin(); pos != cpmBlocks.end(); ++pos)
362 {
363 CpmSubBlockV2 *const subBlock = *pos;
364 if ( !subBlock->pack())
365 {
366 msg(MSG::ERROR) << "CPM sub-block packing failed" << endmsg;
367 return StatusCode::FAILURE;
368 }
369 if (debug)
370 {
371 msg() << "CPM sub-block data words: "
372 << subBlock->dataWords() << endmsg;
373 }
374 subBlock->write(theROD);
375 }
376 }
377
378 // Append CMXs to last S-Link of the crate
379
380 for (int cmx = 0; cmx < m_cmxs; ++cmx)
381 {
382
383 // Create a sub-block for each slice (except Neutral format)
384
386 const int summing = (crate == m_crates - 1) ? CmxSubBlock::SYSTEM
388 for (int slice = 0; slice < timeslicesNew; ++slice)
389 {
390 CmxCpSubBlock *const block = new CmxCpSubBlock();
391 block->setCmxHeader(m_version, m_dataFormat, slice, hwCrate,
392 summing, CmxSubBlock::CMX_CP, cmx, timeslicesNew);
393 cmxBlocks.push_back(block);
394 if (neutralFormat) break;
395 }
396
397 // CMX-CP Tobs
398
399 for (int cpm = 1; cpm <= m_modules; ++cpm)
400 {
401 for (int chip = 0; chip < m_chips; ++chip)
402 {
403 for (int loc = 0; loc < m_locs; ++loc)
404 {
405 const int key = tobKey(crate, cmx, cpm, chip, loc);
406 const LVL1::CMXCPTob *const ct = findCmxCpTob(key,
407 tobMap);
408 if ( ct )
409 {
410 std::vector<int> energy;
411 std::vector<int> isolation;
412 std::vector<int> error;
413 std::vector<unsigned int> presence;
414 ModifySlices::data(ct->energyVec(), energy, timeslicesNew);
415 ModifySlices::data(ct->isolationVec(), isolation, timeslicesNew);
416 ModifySlices::data(ct->errorVec(), error, timeslicesNew);
417 ModifySlices::data(ct->presenceMapVec(), presence, timeslicesNew);
418 for (int slice = 0; slice < timeslicesNew; ++slice)
419 {
420 const LVL1::DataError errBits(error[slice]);
421 int err = errBits.get(LVL1::DataError::ParityMerge);
422 err |= (errBits.get(LVL1::DataError::ParityPhase0)) << 1;
423 err |= (errBits.get(LVL1::DataError::ParityPhase1)) << 2;
424 err |= (errBits.get(LVL1::DataError::ParityPhase2)) << 3;
425 err |= (errBits.get(LVL1::DataError::ParityPhase3)) << 4;
426 err |= (errBits.get(LVL1::DataError::Overflow)) << 5;
427 const int index = ( neutralFormat ) ? 0 : slice;
428 CmxCpSubBlock *const subBlock = cmxBlocks[index];
429 subBlock->setTob(slice, cpm, chip, loc, energy[slice],
430 isolation[slice], err);
431 subBlock->setPresenceMap(slice, cpm, presence[slice]);
432 }
433 }
434 }
435 }
436 }
437
438 // CMX-CP Hits
439
440 for (int source = 0; source < LVL1::CMXCPHits::MAXSOURCE; ++source)
441 {
442 const int key = hitsKey(crate, cmx, source);
443 const LVL1::CMXCPHits *const ch = findCmxCpHits(key, hitsMap);
444 if ( ch )
445 {
446 std::vector<unsigned int> hits0;
447 std::vector<unsigned int> hits1;
448 std::vector<int> err0;
449 std::vector<int> err1;
450 ModifySlices::data(ch->hitsVec0(), hits0, timeslicesNew);
451 ModifySlices::data(ch->hitsVec1(), hits1, timeslicesNew);
452 ModifySlices::data(ch->errorVec0(), err0, timeslicesNew);
453 ModifySlices::data(ch->errorVec1(), err1, timeslicesNew);
454 for (int slice = 0; slice < timeslicesNew; ++slice)
455 {
456 const LVL1::DataError err0Bits(err0[slice]);
457 const LVL1::DataError err1Bits(err1[slice]);
458 const int index = ( neutralFormat ) ? 0 : slice;
459 CmxCpSubBlock *const subBlock = cmxBlocks[index];
460 subBlock->setHits(slice, source, 0, hits0[slice], // Assuming CMXCPHits::source == CmxCpSubBlock::source
461 err0Bits.get(LVL1::DataError::Parity));
462 subBlock->setHits(slice, source, 1, hits1[slice],
463 err1Bits.get(LVL1::DataError::Parity));
464 if (neutralFormat) // Neutral format wants RoI overflow bit
465 {
466 subBlock->setRoiOverflow(slice, source,
468 }
469 }
470 }
471 }
472 for (CmxCpSubBlock* subBlock : cmxBlocks)
473 {
474 if ( !subBlock->pack())
475 {
476 msg(MSG::ERROR) << "CMX-Cp sub-block packing failed" << endmsg;
477 return StatusCode::FAILURE;
478 }
479 if (debug)
480 {
481 msg() << "CMX-Cp sub-block data words: "
482 << subBlock->dataWords() << endmsg;
483 }
484 subBlock->write(theROD);
485 }
486 }
487 }
488
489 return StatusCode::SUCCESS;
490}
491
492// Return reference to vector with all possible Source Identifiers
493
494std::vector<uint32_t> CpByteStreamV2Tool::makeSourceIDs() const
495{
496 std::vector<uint32_t> sourceIDs;
497
498 if (!m_sourceIDsProp.empty()) {
500 }
501 else {
502 const int maxCrates = m_crates + m_crateOffsetHw;
503 const int maxSlinks = m_srcIdMap.maxSlinks();
504 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
505 {
506 for (int slink = 0; slink < maxSlinks; ++slink)
507 {
508 const int daqOrRoi = 0;
509 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
511 const uint32_t robId = m_srcIdMap.getRobID(rodId);
512 sourceIDs.push_back(robId);
513 }
514 }
515 }
516 return sourceIDs;
517}
518
519const std::vector<uint32_t> &CpByteStreamV2Tool::sourceIDs() const
520{
521 static const std::vector<uint32_t> sourceIDs = makeSourceIDs();
522 return sourceIDs;
523}
524
525// Convert bytestream to given container type
526
528 const std::string& sgKey,
529 const IROBDataProviderSvc::VROBFRAG &robFrags,
531{
532 LocalData ld;
533
534 ld.coreOverlap = sgKey.ends_with( "Overlap") || sgKey.ends_with ("OverlapAux.");
535
536 const bool debug = msgLvl(MSG::DEBUG);
537 if (debug) msg(MSG::DEBUG);
538
539 CmxCpSubBlock cmxCpSubBlock;
540 CpmSubBlockV2 cpmSubBlock;
541
542 // Loop over ROB fragments
543
544 int robCount = 0;
545 std::set<uint32_t> dupCheck;
546 ROBIterator rob = robFrags.begin();
547 ROBIterator robEnd = robFrags.end();
548 for (; rob != robEnd; ++rob)
549 {
550 ++robCount;
551 ATH_MSG_DEBUG("Treating ROB fragment " << robCount << " source_id = " << std::hex << (*rob)->rob_source_id() << std::dec);
552
553 // Skip fragments with ROB status errors
554
555 const uint32_t robid = (*rob)->source_id();
556 if ((*rob)->nstatus() > 0)
557 {
558 ROBPointer robData;
559 (*rob)->status(robData);
560 if (*robData != 0)
561 {
562 m_errorTool->robError(robid, *robData);
563 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
564 continue;
565 }
566 }
567
568 // Skip duplicate fragments
569
570 if (!dupCheck.insert(robid).second)
571 {
573 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
574 continue;
575 }
576
577 // Unpack ROD data (slinks)
578
579 RODPointer payloadBeg;
580 RODPointer payload;
581 RODPointer payloadEnd;
582 (*rob)->rod_data(payloadBeg);
583 payloadEnd = payloadBeg + (*rob)->rod_ndata();
584 payload = payloadBeg;
585 if (payload == payloadEnd)
586 {
587 if (debug) msg() << "ROB fragment empty" << endmsg;
588 continue;
589 }
590
591 // Check identifier
592 const uint32_t sourceID = (*rob)->rod_source_id();
593 if (m_srcIdMap.getRobID(sourceID) != robid ||
594 m_srcIdMap.subDet(sourceID) != m_subDetector ||
595 m_srcIdMap.daqOrRoi(sourceID) != 0 ||
596 (m_srcIdMap.slink(sourceID) != 0 && m_srcIdMap.slink(sourceID) != 2) ||
597 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
598 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates)
599 {
601 if (debug)
602 {
603 msg() << "Wrong source identifier in data: ROD "
604 << MSG::hex << sourceID << " ROB " << robid
605 << MSG::dec << endmsg;
606 }
607 continue;
608 }
609
610 // Check minor version
611 const int minorVersion = (*rob)->rod_version() & 0xffff;
612
613 if (minorVersion <= m_srcIdMap.minorVersionPreLS1())
614 {
615 if (debug) msg() << "Skipping pre-LS1 data" << endmsg;
616 continue;
617 }
618 const int rodCrate = m_srcIdMap.crate(sourceID);
619 if (debug)
620 {
621 msg() << "Treating crate " << rodCrate
622 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
623 }
624
625 // First word should be User Header
626 if ( !L1CaloUserHeader::isValid(*payload) )
627 {
629 if (debug) msg() << "Invalid or missing user header" << endmsg;
630 continue;
631 }
632 L1CaloUserHeader userHeader(*payload);
633 userHeader.setVersion(minorVersion);
634 const int headerWords = userHeader.words();
635 if (headerWords != 1)
636 {
638 if (debug) msg() << "Unexpected number of user header words: "
639 << headerWords << endmsg;
640 continue;
641 }
642 for (int i = 0; i < headerWords; ++i) ++payload;
643 // triggered slice offset
644 const int trigCpm = userHeader.cpm();
645 if (debug)
646 {
647 msg() << "Minor format version number: " << MSG::hex
648 << minorVersion << MSG::dec << endmsg
649 << "Triggered slice offset: " << trigCpm << endmsg;
650 }
651
652 // Loop over sub-blocks
653
654 ld.rodErr = L1CaloSubBlock::ERROR_NONE;
655 while (payload != payloadEnd)
656 {
658 {
659 if (debug) msg() << "Unexpected data sequence" << endmsg;
661 break;
662 }
663
664 // TODO: (sasha) Comment this check since firmware does not ready
665 // Select right tool by ROD version
666 // if (L1CaloSubBlock::version(*payload) == 1) {
667 // if (debug) msg() << "Skipping pre-LS1 data" << endmsg;
668 // break;
669 // }
670
671 if (CmxSubBlock::cmxBlock(*payload))
672 {
673 // CMX
675 {
676 cmxCpSubBlock.clear();
677 payload = cmxCpSubBlock.read(payload, payloadEnd);
678 if (cmxCpSubBlock.crate() != rodCrate)
679 {
680 if (debug) msg() << "Inconsistent crate number in ROD source ID"
681 << endmsg;
683 break;
684 }
685
686 if (data.m_collection == CMX_CP_TOBS || data.m_collection == CMX_CP_HITS)
687 {
688 decodeCmxCp(&cmxCpSubBlock, trigCpm, data, ld);
689 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
690 {
691 if (debug) msg() << "decodeCmxCp failed" << endmsg;
692 break;
693 }
694 }
695 }
696 else
697 {
698 if (debug) msg() << "Invalid CMX type in module field" << endmsg;
700 break;
701 }
702 }
703 else
704 {
705 // CPM
706 cpmSubBlock.clear();
707 payload = cpmSubBlock.read(payload, payloadEnd);
708 if (cpmSubBlock.crate() != rodCrate)
709 {
710 if (debug) msg() << "Inconsistent crate number in ROD source ID"
711 << endmsg;
713 break;
714 }
715 if (data.m_collection == CPM_TOWERS)
716 {
717 decodeCpm(&cpmSubBlock, trigCpm, static_cast<CpmTowerData&>(data), ld);
718 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
719 {
720 if (debug) msg() << "decodeCpm failed" << endmsg;
721 break;
722 }
723 }
724 }
725 }
726 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
727 {
728 m_errorTool->rodError(robid, ld.rodErr);
729 }
730 }
731 return StatusCode::SUCCESS;
732}
733
734// Unpack CMX-CP sub-block
735
738 LocalData& ld) const
739{
740 const bool debug = msgLvl(MSG::DEBUG);
741 if (debug) msg(MSG::DEBUG);
742
743 const int hwCrate = subBlock->crate();
744 const int cmx = subBlock->cmxPosition();
745 const int firmware = subBlock->cmxFirmware();
746 const int summing = subBlock->cmxSumming();
747 const int timeslices = subBlock->timeslices();
748 const int sliceNum = subBlock->slice();
749 if (debug)
750 {
751 msg() << "CMX-CP: Crate " << hwCrate
752 << " Position " << cmx
753 << " Firmware " << firmware
754 << " Summing " << summing
755 << " Total slices " << timeslices
756 << " Slice " << sliceNum
757 << endmsg;
758 }
759 if (timeslices <= trigCpm)
760 {
761 if (debug) msg() << "Triggered slice from header "
762 << "inconsistent with number of slices: "
763 << trigCpm << ", " << timeslices << endmsg;
765 return;
766 }
767 if (timeslices <= sliceNum)
768 {
769 if (debug) msg() << "Total slices inconsistent with slice number: "
770 << timeslices << ", " << sliceNum << endmsg;
772 return;
773 }
774 // Unpack sub-block
775 if (subBlock->dataWords() && !subBlock->unpack())
776 {
777 if (debug)
778 {
779 std::string errMsg(subBlock->unpackErrorMsg());
780 msg() << "CMX-CP sub-block unpacking failed: " << errMsg << endmsg;
781 }
782 ld.rodErr = subBlock->unpackErrorCode();
783 return;
784 }
785
786 // Retrieve required data
787
788 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
789 LVL1::DataError dErr;
791 const int subStatus = dErr.error();
792 const int crate = hwCrate - m_crateOffsetHw;
793 const int swCrate = crate + m_crateOffsetSw;
794 const int maxSid = CmxCpSubBlock::MAX_SOURCE_ID;
795 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
796 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
797 for (int slice = sliceBeg; slice < sliceEnd; ++slice)
798 {
799
800 if (data.m_collection == CMX_CP_TOBS)
801 {
802 CmxCpTobData& tdata = static_cast<CmxCpTobData&> (data);
803
804 // TOBs
805
806 for (int cpm = 1; cpm <= m_modules; ++cpm)
807 {
808 const unsigned int presenceMap = subBlock->presenceMap(slice, cpm);
809 for (int tob = 0; tob < m_maxTobs; ++tob)
810 {
811 const int energy = subBlock->energy(slice, cpm, tob);
812 const int isolation = subBlock->isolation(slice, cpm, tob);
813 int error = subBlock->tobError(slice, cpm, tob);
814 if (energy == 0 && isolation == 0 && error == 0) break;
815 const int loc = subBlock->localCoord(slice, cpm, tob);
816 const int chip = subBlock->chip(slice, cpm, tob);
817 LVL1::DataError errBits(subStatus);
818 if (error)
819 {
821 errBits.set(LVL1::DataError::ParityPhase1, (error >> 1));
822 errBits.set(LVL1::DataError::ParityPhase2, (error >> 2));
823 errBits.set(LVL1::DataError::ParityPhase3, (error >> 3));
824 errBits.set(LVL1::DataError::Overflow, (error >> 4));
825 errBits.set(LVL1::DataError::ParityMerge, (error >> 5));
826 errBits.set(LVL1::DataError::Parity, (error & 0x2f) ? 1 : 0);
827 }
828 error = errBits.error();
829 const int key = tobKey(crate, cmx, cpm, chip, loc);
830 LVL1::CMXCPTob *tb = findCmxCpTob(tdata, key);
831 if ( ! tb ) // create new CMX TOB
832 {
833 ld.energyVec.assign(timeslices, 0);
834 ld.isolVec.assign(timeslices, 0);
835 ld.errorVec.assign(timeslices, 0);
836 ld.presenceMapVec.assign(timeslices, 0);
837 ld.energyVec[slice] = energy;
838 ld.isolVec[slice] = isolation;
839 ld.errorVec[slice] = error;
840 ld.presenceMapVec[slice] = presenceMap;
841 auto tbp =
842 std::make_unique<LVL1::CMXCPTob>(swCrate, cmx, cpm, chip, loc,
843 ld.energyVec, ld.isolVec, ld.errorVec,
844 ld.presenceMapVec, trigCpm);
845 tdata.m_tobMap.insert(std::make_pair(key, tbp.get()));
846 tdata.m_tobCollection->push_back(std::move(tbp));
847 }
848 else
849 {
850 ld.energyVec = tb->energyVec();
851 ld.isolVec = tb->isolationVec();
852 ld.errorVec = tb->errorVec();
853 ld.presenceMapVec = tb->presenceMapVec();
854 const int nsl = ld.energyVec.size();
855 if (timeslices != nsl)
856 {
857 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
858 << endmsg;
860 return;
861 }
862 if (ld.energyVec[slice] != 0 || ld.isolVec[slice] != 0 ||
863 ld.errorVec[slice] != 0)
864 {
865 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
867 return;
868 }
869 ld.energyVec[slice] = energy;
870 ld.isolVec[slice] = isolation;
871 ld.errorVec[slice] = error;
872 ld.presenceMapVec[slice] = presenceMap;
873 tb->addTob(ld.energyVec, ld.isolVec, ld.errorVec, ld.presenceMapVec);
874 }
875 }
876 }
877
878 }
879 else if (data.m_collection == CMX_CP_HITS)
880 {
881 CmxCpHitsData& hdata = static_cast<CmxCpHitsData&> (data);
882
883 // Hit/Topo counts
884
885 for (int source = 0; source < maxSid; ++source)
886 {
887 if (summing == CmxSubBlock::CRATE &&
888 (source == CmxCpSubBlock::REMOTE_0 ||
889 source == CmxCpSubBlock::REMOTE_1 ||
890 source == CmxCpSubBlock::REMOTE_2 ||
891 source == CmxCpSubBlock::TOTAL)) continue;
892 const unsigned int hits0 = subBlock->hits(slice, source, 0); //low
893 const unsigned int hits1 = subBlock->hits(slice, source, 1); //high
894 int err0 = subBlock->hitsError(slice, source, 0);
895 int err1 = subBlock->hitsError(slice, source, 1);
896 int overflow = subBlock->roiOverflow(slice, source);
897 LVL1::DataError err0Bits(subStatus);
898 err0Bits.set(LVL1::DataError::Parity, err0);
899 err0Bits.set(LVL1::DataError::Overflow, overflow);
900 err0 = err0Bits.error();
901 LVL1::DataError err1Bits(subStatus);
902 err1Bits.set(LVL1::DataError::Parity, err1);
903 err1Bits.set(LVL1::DataError::Overflow, overflow);
904 err1 = err1Bits.error();
905 if (hits0 || hits1 || err0 || err1)
906 {
907 const int key = hitsKey(crate, cmx, source);
908 LVL1::CMXCPHits *ch = findCmxCpHits(hdata, key);
909 if ( ! ch ) // create new CMX hits
910 {
911 ld.hitsVec0.assign(timeslices, 0);
912 ld.hitsVec1.assign(timeslices, 0);
913 ld.errVec0.assign(timeslices, 0);
914 ld.errVec1.assign(timeslices, 0);
915 ld.hitsVec0[slice] = hits0;
916 ld.hitsVec1[slice] = hits1;
917 ld.errVec0[slice] = err0;
918 ld.errVec1[slice] = err1;
919 auto chp =
920 std::make_unique<LVL1::CMXCPHits>(swCrate, cmx, source,
921 ld.hitsVec0, ld.hitsVec1,
922 ld.errVec0, ld.errVec1, trigCpm);
923 hdata.m_hitsMap.insert(std::make_pair(key, chp.get()));
924 hdata.m_hitCollection->push_back(std::move(chp));
925 }
926 else
927 {
928 ld.hitsVec0 = ch->hitsVec0();
929 ld.hitsVec1 = ch->hitsVec1();
930 ld.errVec0 = ch->errorVec0();
931 ld.errVec1 = ch->errorVec1();
932 const int nsl = ld.hitsVec0.size();
933 if (timeslices != nsl)
934 {
935 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
936 << endmsg;
938 return;
939 }
940 if (ld.hitsVec0[slice] != 0 || ld.hitsVec1[slice] != 0 ||
941 ld.errVec0[slice] != 0 || ld.errVec1[slice] != 0)
942 {
943 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
945 return;
946 }
947 ld.hitsVec0[slice] = hits0;
948 ld.hitsVec1[slice] = hits1;
949 ld.errVec0[slice] = err0;
950 ld.errVec1[slice] = err1;
951 ch->addHits(ld.hitsVec0, ld.hitsVec1, ld.errVec0, ld.errVec1);
952 }
953 }
954 }
955 }
956 }
957
958 return;
959}
960
961// Unpack CPM sub-block
962
965 LocalData& ld) const
966{
967 const bool debug = msgLvl(MSG::DEBUG);
968 const bool verbose = msgLvl(MSG::VERBOSE);
969 if (debug) msg(MSG::DEBUG);
970
971 const int hwCrate = subBlock->crate();
972 const int module = subBlock->module();
973 const int timeslices = subBlock->timeslices();
974 const int sliceNum = subBlock->slice();
975 if (debug)
976 {
977 msg() << "CPM: Crate " << hwCrate
978 << " Module " << module
979 << " Total slices " << timeslices
980 << " Slice " << sliceNum << endmsg;
981 }
982 if (module < 1 || module > m_modules)
983 {
984 if (debug) msg() << "Unexpected module number: " << module << endmsg;
986 return;
987 }
988 if (timeslices <= trigCpm)
989 {
990 if (debug) msg() << "Triggered slice from header "
991 << "inconsistent with number of slices: "
992 << trigCpm << ", " << timeslices << endmsg;
994 return;
995 }
996 if (timeslices <= sliceNum)
997 {
998 if (debug) msg() << "Total slices inconsistent with slice number: "
999 << timeslices << ", " << sliceNum << endmsg;
1000 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1001 return;
1002 }
1003 // Unpack sub-block
1004 if (subBlock->dataWords() && !subBlock->unpack())
1005 {
1006 if (debug)
1007 {
1008 std::string errMsg(subBlock->unpackErrorMsg());
1009 msg() << "CPM sub-block unpacking failed: " << errMsg << endmsg;
1010 }
1011 ld.rodErr = subBlock->unpackErrorCode();
1012 return;
1013 }
1014
1015 // Retrieve required data
1016 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
1017 LVL1::DataError dErr;
1018 dErr.set(LVL1::DataError::SubStatusWord, subBlock->subStatus());
1019 const int subStatus = dErr.error();
1020 const int crate = hwCrate - m_crateOffsetHw;
1021 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
1022 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
1023 for (int slice = sliceBeg; slice < sliceEnd; ++slice)
1024 {
1025
1026 // Loop over tower channels and fill CPM towers
1027
1028 for (int chan = 0; chan < m_channels; ++chan)
1029 {
1030 if (!subStatus && !subBlock->anyTowerData(chan)) continue;
1031 const int em = subBlock->emData(slice, chan);
1032 const int had = subBlock->hadData(slice, chan);
1033 const int emErr = subBlock->emError(slice, chan);
1034 const int hadErr = subBlock->hadError(slice, chan);
1035 int emErr1 = subStatus;
1036 if (emErr)
1037 {
1038 LVL1::DataError emErrBits(emErr1);
1039 emErrBits.set(LVL1::DataError::Parity, emErr & 0x1);
1040 emErrBits.set(LVL1::DataError::LinkDown, (emErr >> 1) & 0x1);
1041 emErr1 = emErrBits.error();
1042 }
1043 int hadErr1 = subStatus;
1044 if (hadErr)
1045 {
1046 LVL1::DataError hadErrBits(hadErr1);
1047 hadErrBits.set(LVL1::DataError::Parity, hadErr & 0x1);
1048 hadErrBits.set(LVL1::DataError::LinkDown, (hadErr >> 1) & 0x1);
1049 hadErr1 = hadErrBits.error();
1050 }
1051 if (em || had || emErr1 || hadErr1)
1052 {
1053 double eta = 0.;
1054 double phi = 0.;
1055 int layer = 0;
1056 if (m_cpmMaps->mapping(crate, module, chan, eta, phi, layer))
1057 {
1058 if (layer == ld.coreOverlap)
1059 {
1060 const unsigned int key = ld.towerKey.ttKey(phi, eta);
1061 LVL1::CPMTower *tt = findCpmTower(data, key);
1062 if ( ! tt ) // create new CPM tower
1063 {
1064 ld.emVec.assign(timeslices, 0);
1065 ld.hadVec.assign(timeslices, 0);
1066 ld.emErrVec.assign(timeslices, 0);
1067 ld.hadErrVec.assign(timeslices, 0);
1068 ld.emVec[slice] = em;
1069 ld.hadVec[slice] = had;
1070 ld.emErrVec[slice] = emErr1;
1071 ld.hadErrVec[slice] = hadErr1;
1072 auto ttp =
1073 std::make_unique<LVL1::CPMTower>(phi, eta, ld.emVec, ld.emErrVec,
1074 ld.hadVec, ld.hadErrVec, trigCpm);
1075 data.m_ttMap.insert(std::make_pair(key, ttp.get()));
1076 data.m_ttCollection->push_back(std::move(ttp));
1077 }
1078 else
1079 {
1080 ld.emVec = tt->emEnergyVec();
1081 ld.hadVec = tt->hadEnergyVec();
1082 ld.emErrVec = tt->emErrorVec();
1083 ld.hadErrVec = tt->hadErrorVec();
1084 const int nsl = ld.emVec.size();
1085 if (timeslices != nsl)
1086 {
1087 if (debug)
1088 {
1089 msg() << "Inconsistent number of slices in sub-blocks"
1090 << endmsg;
1091 }
1092 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1093 return;
1094 }
1095 if (ld.emVec[slice] != 0 || ld.hadVec[slice] != 0 ||
1096 ld.emErrVec[slice] != 0 || ld.hadErrVec[slice] != 0)
1097 {
1098 if (debug) msg() << "Duplicate data for slice "
1099 << slice << endmsg;
1101 return;
1102 }
1103 ld.emVec[slice] = em;
1104 ld.hadVec[slice] = had;
1105 ld.emErrVec[slice] = emErr1;
1106 ld.hadErrVec[slice] = hadErr1;
1107 tt->fill(ld.emVec, ld.emErrVec, ld.hadVec, ld.hadErrVec, trigCpm);
1108 }
1109 }
1110 }
1111 else if (verbose && (em || had || emErr || hadErr))
1112 {
1113 msg(MSG::VERBOSE) << "Non-zero data but no channel mapping for channel "
1114 << chan << endmsg;
1115 msg(MSG::DEBUG);
1116 }
1117 }
1118 else if (verbose)
1119 {
1120 msg(MSG::VERBOSE) << "No CPM tower data for channel "
1121 << chan << " slice " << slice << endmsg;
1122 msg(MSG::DEBUG);
1123 }
1124 }
1125 }
1126 return;
1127}
1128
1129// Find a CPM tower for given key
1130
1131const
1133 const ConstCpmTowerMap& ttMap) const
1134{
1135 ConstCpmTowerMap::const_iterator mapIter = ttMap.find(key);
1136 if (mapIter != ttMap.end()) return mapIter->second;
1137 return nullptr;
1138}
1139
1141 const unsigned int key) const
1142{
1143 CpmTowerMap::const_iterator mapIter = data.m_ttMap.find(key);
1144 if (mapIter != data.m_ttMap.end()) return mapIter->second;
1145 return nullptr;
1146}
1147
1148// Find CMX-CP TOB for given key
1149
1150const
1152 const ConstCmxCpTobMap& tobMap) const
1153{
1154 ConstCmxCpTobMap::const_iterator mapIter = tobMap.find(key);
1155 if (mapIter != tobMap.end()) return mapIter->second;
1156 return nullptr;
1157}
1158
1160 const int key) const
1161{
1162 CmxCpTobMap::const_iterator mapIter = data.m_tobMap.find(key);
1163 if (mapIter != data.m_tobMap.end()) return mapIter->second;
1164 return nullptr;
1165}
1166
1167// Find CMX-CP hits for given key
1168
1169const
1171 const ConstCmxCpHitsMap& hitsMap) const
1172{
1173 ConstCmxCpHitsMap::const_iterator mapIter = hitsMap.find(key);
1174 if (mapIter != hitsMap.end()) return mapIter->second;
1175 return nullptr;
1176}
1177
1179 const int key) const
1180{
1181 CmxCpHitsMap::const_iterator mapIter = data.m_hitsMap.find(key);
1182 if (mapIter != data.m_hitsMap.end()) return mapIter->second;
1183 return nullptr;
1184}
1185
1186// Set up CPM tower map
1187
1189 const ttCollection,
1190 ConstCpmTowerMap& ttMap,
1191 LVL1::TriggerTowerKey& towerKey) const
1192{
1193 ttMap.clear();
1194 if (ttCollection)
1195 {
1196 CpmTowerCollection::const_iterator pos = ttCollection->begin();
1197 CpmTowerCollection::const_iterator pose = ttCollection->end();
1198 for (; pos != pose; ++pos)
1199 {
1200 const LVL1::CPMTower *const tt = *pos;
1201 const unsigned int key = towerKey.ttKey(tt->phi(), tt->eta());
1202 ttMap.insert(std::make_pair(key, tt));
1203 }
1204 }
1205}
1206
1207// Set up CMX-CP TOB map
1208
1210 const tobCollection,
1211 ConstCmxCpTobMap& tobMap) const
1212{
1213 tobMap.clear();
1214 if (tobCollection)
1215 {
1216 CmxCpTobCollection::const_iterator pos = tobCollection->begin();
1217 CmxCpTobCollection::const_iterator pose = tobCollection->end();
1218 for (; pos != pose; ++pos)
1219 {
1220 const LVL1::CMXCPTob *const tob = *pos;
1221 const int crate = tob->crate() - m_crateOffsetSw;
1222 const int cmx = tob->cmx();
1223 const int cpm = tob->cpm();
1224 const int chip = tob->chip();
1225 const int loc = tob->location();
1226 const int key = tobKey(crate, cmx, cpm, chip, loc);
1227 tobMap.insert(std::make_pair(key, tob));
1228 }
1229 }
1230}
1231
1232// Set up CMX-CP hits map
1233
1235 const hitCollection,
1236 ConstCmxCpHitsMap& hitsMap) const
1237{
1238 hitsMap.clear();
1239 if (hitCollection)
1240 {
1241 CmxCpHitsCollection::const_iterator pos = hitCollection->begin();
1242 CmxCpHitsCollection::const_iterator pose = hitCollection->end();
1243 for (; pos != pose; ++pos)
1244 {
1245 const LVL1::CMXCPHits *const hits = *pos;
1246 const int crate = hits->crate() - m_crateOffsetSw;
1247 const int cmx = hits->cmx();
1248 const int source = hits->source();
1249 const int key = hitsKey(crate, cmx, source);
1250 hitsMap.insert(std::make_pair(key, hits));
1251 }
1252 }
1253}
1254
1255// Key for TOBs
1256
1257int CpByteStreamV2Tool::tobKey(const int crate, const int cmx, const int cpm,
1258 const int chip, const int loc) const
1259{
1260 return (((((((crate << 1) | cmx) << 4) | cpm) << 4) | chip) << 2) | loc;
1261}
1262
1263// Key for Hits
1264
1265int CpByteStreamV2Tool::hitsKey(const int crate, const int cmx,
1266 const int source) const
1267{
1268 return (((crate << 1) | cmx) << 3) | source;
1269}
1270
1271// Get number of slices and triggered slice offset for next slink
1272
1273bool CpByteStreamV2Tool::slinkSlices(const int crate, const int module,
1274 const int modulesPerSlink, int &timeslices, int &trigCpm,
1275 const ConstCpmTowerMap& ttMap,
1276 const ConstCmxCpTobMap& tobMap,
1277 const ConstCmxCpHitsMap& hitsMap,
1278 LVL1::TriggerTowerKey& towerKey) const
1279{
1280 int slices = -1;
1281 int trigC = m_dfltSlices / 2;
1282 for (int mod = module; mod < module + modulesPerSlink; ++mod)
1283 {
1284 for (int chan = 0; chan < m_channels; ++chan)
1285 {
1286 double eta = 0.;
1287 double phi = 0.;
1288 int layer = 0;
1289 if ( !m_cpmMaps->mapping(crate, mod, chan, eta, phi, layer)) continue;
1290 const unsigned int key = towerKey.ttKey(phi, eta);
1291 const LVL1::CPMTower *const tt = findCpmTower(key, ttMap);
1292 if ( !tt ) continue;
1293 const int numdat = 4;
1294 std::vector<int> sums(numdat);
1295 std::vector<int> sizes(numdat);
1296 sums[0] = std::accumulate((tt->emEnergyVec()).begin(),
1297 (tt->emEnergyVec()).end(), 0);
1298 sums[1] = std::accumulate((tt->hadEnergyVec()).begin(),
1299 (tt->hadEnergyVec()).end(), 0);
1300 sums[2] = std::accumulate((tt->emErrorVec()).begin(),
1301 (tt->emErrorVec()).end(), 0);
1302 sums[3] = std::accumulate((tt->hadErrorVec()).begin(),
1303 (tt->hadErrorVec()).end(), 0);
1304 sizes[0] = (tt->emEnergyVec()).size();
1305 sizes[1] = (tt->hadEnergyVec()).size();
1306 sizes[2] = (tt->emErrorVec()).size();
1307 sizes[3] = (tt->hadErrorVec()).size();
1308 const int peak = tt->peak();
1309 for (int i = 0; i < numdat; ++i)
1310 {
1311 if (sums[i] == 0) continue;
1312 if (slices < 0)
1313 {
1314 slices = sizes[i];
1315 trigC = peak;
1316 }
1317 else if (slices != sizes[i] || trigC != peak) return false;
1318 }
1319 }
1320 }
1321 // CMXs last slink of crate
1322 if (module / modulesPerSlink == m_slinks - 1)
1323 {
1324 for (int cmx = 0; cmx < m_cmxs; ++cmx)
1325 {
1326 for (int cpm = 1; cpm <= m_modules; ++ cpm)
1327 {
1328 for (int chip = 0; chip < m_chips; ++chip)
1329 {
1330 for (int loc = 0; loc < m_locs; ++loc)
1331 {
1332 const int key = tobKey(crate, cmx, cpm, chip, loc);
1333 const LVL1::CMXCPTob *const tob = findCmxCpTob(key,
1334 tobMap);
1335 if (tob)
1336 {
1337 const int numdat = 3;
1338 std::vector<int> sums(numdat);
1339 std::vector<int> sizes(numdat);
1340 sums[0] = std::accumulate((tob->energyVec()).begin(),
1341 (tob->energyVec()).end(), 0);
1342 sums[1] = std::accumulate((tob->isolationVec()).begin(),
1343 (tob->isolationVec()).end(), 0);
1344 sums[2] = std::accumulate((tob->errorVec()).begin(),
1345 (tob->errorVec()).end(), 0);
1346 sizes[0] = (tob->energyVec()).size();
1347 sizes[1] = (tob->isolationVec()).size();
1348 sizes[2] = (tob->errorVec()).size();
1349 const int peak = tob->peak();
1350 for (int i = 0; i < numdat; ++i)
1351 {
1352 if (sums[i] == 0) continue;
1353 if (slices < 0)
1354 {
1355 slices = sizes[i];
1356 trigC = peak;
1357 }
1358 else if (slices != sizes[i] || trigC != peak) return false;
1359 }
1360 }
1361 }
1362 }
1363 }
1364 for (int source = 0; source < LVL1::CMXCPHits::MAXSOURCE; ++source)
1365 {
1366 const int key = hitsKey(crate, cmx, source);
1367
1368 const LVL1::CMXCPHits *const hits = findCmxCpHits(key,
1369 hitsMap);
1370 if (hits)
1371 {
1372 const int numdat = 4;
1373 std::vector<unsigned int> sums(numdat);
1374 std::vector<int> sizes(numdat);
1375 sums[0] = std::accumulate((hits->hitsVec0()).begin(),
1376 (hits->hitsVec0()).end(), 0);
1377 sums[1] = std::accumulate((hits->hitsVec1()).begin(),
1378 (hits->hitsVec1()).end(), 0);
1379 sums[2] = std::accumulate((hits->errorVec0()).begin(),
1380 (hits->errorVec0()).end(), 0);
1381 sums[3] = std::accumulate((hits->errorVec1()).begin(),
1382 (hits->errorVec1()).end(), 0);
1383 sizes[0] = (hits->hitsVec0()).size();
1384 sizes[1] = (hits->hitsVec1()).size();
1385 sizes[2] = (hits->errorVec0()).size();
1386 sizes[3] = (hits->errorVec1()).size();
1387 const int peak = hits->peak();
1388 for (int i = 0; i < numdat; ++i)
1389 {
1390 if (sums[i] == 0) continue;
1391 if (slices < 0)
1392 {
1393 slices = sizes[i];
1394 trigC = peak;
1395 }
1396 else if (slices != sizes[i] || trigC != peak) return false;
1397 }
1398 }
1399 }
1400 }
1401 }
1402 if (slices < 0) slices = m_dfltSlices;
1403 timeslices = slices;
1404 trigCpm = trigC;
1405 return true;
1406}
1407
1408} // end namespace
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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.
DataModel_detail::iterator< DataVector > iterator
Standard iterator.
Definition DataVector.h:842
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.
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
Sub-Block class for CMX-CP data post LS1.
unsigned int hits(int slice, int source, int flag) const
Return hit/topo counts for given source ID and HL flag.
int roiOverflow(int slice, int source) const
Return RoI overflow for given source ID.
void clear()
Clear all data.
int energy(int slice, int cpm, int tob) const
Return energy for given cpm and tob.
bool unpack()
Unpack data.
void setPresenceMap(int slice, int cpm, unsigned int map)
Store presence map.
int hitsError(int slice, int source, int flag) const
Return hit error for given source ID and HL flag.
unsigned int presenceMap(int slice, int cpm) const
Return presence map for given CPM.
void setHits(int slice, int source, int flag, unsigned int hits, int error)
Store hit counts for given source ID and HL flag.
void setRoiOverflow(int slice, int source, int overflow)
Store RoI overflow for given source ID.
int chip(int slice, int cpm, int tob) const
Return chip for given cpm and tob.
int localCoord(int slice, int cpm, int tob) const
Return Local coordinate for given cpm and tob.
int isolation(int slice, int cpm, int tob) const
Return isolation for given cpm and tob.
int tobError(int slice, int cpm, int tob) const
Return error bits for given cpm and tob.
void setTob(int slice, int cpm, int chip, int loc, int energy, int isol, int error)
Store TOB (RoI) data for given CPM, chip, local coord.
static bool cmxBlock(uint32_t word)
Determine if header word corresponds to CMX.
int cmxPosition() const
Definition CmxSubBlock.h:73
int cmxSumming() const
Definition CmxSubBlock.h:63
int cmxFirmware() const
Definition CmxSubBlock.h:68
int timeslices() const
void setCmxHeader(int version, int format, int slice, int crate, int summing, int firmware, int position, int timeslices)
Store CMX header.
static CmxFirmwareCode cmxType(uint32_t word)
CMX differentiation (CMX_CP, CMX_JET, or CMX_ENERGY).
const LVL1::CPMTower * findCpmTower(unsigned int key, const ConstCpmTowerMap &ttMap) const
Find a CPM tower for given key.
const eformat::SubDetector m_subDetector
Sub-detector type.
StatusCode convertBs(const std::string &sgKey, const IROBDataProviderSvc::VROBFRAG &robFrags, CpByteStreamToolData &data) const
Convert bytestream to given container type.
const int m_cmxs
Number of CMXs per crate.
void decodeCmxCp(CmxCpSubBlock *subBlock, int trigCpm, CpByteStreamToolData &data, LocalData &ld) const
Unpack CMX-CP sub-block.
CpByteStreamV2Tool(const std::string &type, const std::string &name, const IInterface *parent)
const LVL1::CMXCPHits * findCmxCpHits(int key, const ConstCmxCpHitsMap &hitsMap) const
Find CMX-CP hits for given key.
void setupCpmTowerMap(const CpmTowerCollection *ttCollection, ConstCpmTowerMap &ttMap, LVL1::TriggerTowerKey &towerKey) const
Set up CPM tower map.
DataVector< LVL1::CPMTower > CpmTowerCollection
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
int hitsKey(int crate, int cmx, int source) const
Key for Hits.
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
const int m_channels
Number of channels per module.
int m_crateMax
Property: Maximum crate number when writing out bytestream.
int m_crateMin
Property: Minimum crate number when writing out bytestream.
const int m_maxTobs
Maximum number of TOBS per module.
std::vector< uint32_t > makeSourceIDs() const
Create list of all source IDs.
const int m_locs
Number of Local coordinates.
int m_version
Property: Sub_block header version.
int m_dataFormat
Property: Data compression format.
const std::vector< uint32_t > & sourceIDs() const
Return reference to vector with all possible Source Identifiers.
DataVector< LVL1::CMXCPHits > CmxCpHitsCollection
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Error collection tool.
int m_forceSlices
Property: Force number of slices in bytestream.
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
SmartIF< IByteStreamCnvSvc > m_byteStreamCnvSvc
const LVL1::CMXCPTob * findCmxCpTob(int key, const ConstCmxCpTobMap &tobMap) const
Find CMX-CP TOB for given key.
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
int m_crateOffsetHw
Property: Hardware crate number offset.
Gaudi::Property< bool > m_enableEncoding
std::map< unsigned int, const LVL1::CPMTower * > ConstCpmTowerMap
DataVector< LVL1::CMXCPTob > CmxCpTobCollection
std::map< int, const LVL1::CMXCPHits * > ConstCmxCpHitsMap
int m_dfltSlices
Property: Default number of slices in simulation.
const int m_chips
Number of chips.
StatusCode convert(const EventContext &ctx, const std::string &sgKey, DataVector< LVL1::CPMTower > *ttCollection) const
Convert ROB fragments to CPM towers.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
void decodeCpm(CpmSubBlockV2 *subBlock, int trigCpm, CpmTowerData &data, LocalData &ld) const
Unpack CPM sub-block.
void setupCmxCpHitsMap(const CmxCpHitsCollection *hitCollection, ConstCmxCpHitsMap &hitsMap) const
Set up CMX-CP hits map.
const int m_modules
Number of CPM modules per crate.
int m_crates
Property: Number of crates.
void setupCmxCpTobMap(const CmxCpTobCollection *tobCollection, ConstCmxCpTobMap &tobMap) const
Set up CMX-CP TOB map.
int m_crateOffsetSw
Property: Software crate number offset.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
ServiceHandle< IROBDataProviderSvc > m_robDataProvider
std::map< int, const LVL1::CMXCPTob * > ConstCmxCpTobMap
std::vector< uint32_t > m_sourceIDsProp
Property: ROB source IDs.
bool slinkSlices(int crate, int module, int modulesPerSlink, int &timeslices, int &trigJem, const ConstCpmTowerMap &ttMap, const ConstCmxCpTobMap &tobMap, const ConstCmxCpHitsMap &hitsMap, LVL1::TriggerTowerKey &towerKey) const
Get number of slices and triggered slice offset for next slink.
int tobKey(int crate, int cmx, int cpm, int chip, int loc) const
Key for TOBs.
virtual StatusCode initialize() override
ToolHandle< LVL1::IL1CaloMappingTool > m_cpmMaps
Channel mapping tool.
Sub-Block class for CPM data post LS1.
int hadData(int slice, int channel) const
Return Had data for given channel.
int hadError(int slice, int channel) const
Return Had error for given channel.
bool pack()
Pack data.
int emError(int slice, int channel) const
Return Em error for given channel.
bool unpack()
Unpack data.
int emData(int slice, int channel) const
Return Em data for given channel.
void clear()
Clear all data.
int timeslices() const
Return number of timeslices.
void fillTowerData(int slice, int channel, int em, int had, int emErr, int hadErr)
Store trigger tower data.
void setCpmHeader(int version, int format, int slice, int crate, int module, int timeslices)
Store CPM header.
bool anyTowerData(int channel) const
Return true if there is tower data for given channel.
void setStatus(uint32_t failingBCN, bool glinkTimeout, bool glinkDown, bool upstreamError, bool daqOverflow, bool bcnMismatch, bool glinkProtocol, bool glinkParity)
Store error status trailer.
int unpackErrorCode() const
Return the unpacking error code.
uint32_t subStatus() const
Return Sub-status word.
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.
static void data(const std::vector< int > &oldVec, std::vector< int > &newVec, int newSlices)
Return modified data vector<int>.
static int peak(int oldPeak, int oldSlices, int newSlices)
Return new triggered slice offset.
Summary of CP (EM/tau) hits produced by the merger modules.
TOB data received by the merger modules.
const std::vector< int > & isolationVec() const
returns isolation
const std::vector< int > & errorVec() const
returns error
const std::vector< int > & energyVec() const
For multi-slice readout.
int chip() const
returns chip number (3 or 4 bits?)
int cmx() const
returns CMX number (0/1)==(Left/Right)==(Tau/Em)
int location() const
returns location (3 or 2 bits?)
Cluster Processor container for writing bytestream.
The CPMTower class contains the TriggerTower information received by the Cluster Processor Modules.
Error data.
Definition DataError.h:27
int error() const
Return the full error word.
Definition DataError.h:78
void set(ErrorBit bit, int value=1)
Set an error bit or data.
Definition DataError.cxx:28
int get(ErrorBit bit) const
Return an error bit or data.
Definition DataError.cxx:48
The TriggerTowerKey object provides the key for each trigger tower depending on its eta-phi coords.
virtual unsigned int ttKey(const TriggerTower &tower)
returns the key of the passed tower
bool verbose
Definition hcg.cxx:75
static const InterfaceID IID_ICpByteStreamV2Tool("CpByteStreamV2Tool", 1, 1)
Definition index.py:1