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