ATLAS Offline Software
Loading...
Searching...
No Matches
CpByteStreamV1Tool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6#include <numeric>
7#include <set>
8#include <utility>
9
10#include "GaudiKernel/IInterface.h"
11#include "GaudiKernel/MsgStream.h"
12#include "GaudiKernel/StatusCode.h"
13
15
23
24#include "CmmCpSubBlock.h"
25#include "CmmSubBlock.h"
26#include "CpmSubBlockV1.h"
28#include "L1CaloSubBlock.h"
29#include "L1CaloUserHeader.h"
30#include "ModifySlices.h"
31
32#include "CpByteStreamV1Tool.h"
33
34namespace LVL1BS {
35
36// Interface ID
37
38static const InterfaceID IID_ICpByteStreamV1Tool("CpByteStreamV1Tool", 1, 1);
39
41{
43}
44
45// Constructor
46
48 const std::string& name,
49 const IInterface* parent)
50 : AthAlgTool(type, name, parent),
51 m_cpmMaps("LVL1::CpmMappingTool/CpmMappingTool"),
52 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
53 m_channels(80), m_crates(4), m_modules(14),
54 m_subDetector(eformat::TDAQ_CALO_CLUSTER_PROC_DAQ)
55{
56 declareInterface<CpByteStreamV1Tool>(this);
57
58 declareProperty("CpmMappingTool", m_cpmMaps,
59 "Crate/Module/Channel to Eta/Phi/Layer mapping tool");
60 declareProperty("ErrorTool", m_errorTool,
61 "Tool to collect errors for monitoring");
62
63 declareProperty("CrateOffsetHw", m_crateOffsetHw = 8,
64 "Offset of CP crate numbers in bytestream");
65 declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
66 "Offset of CP crate numbers in RDOs");
67
68 // Properties for reading bytestream only
69 declareProperty("ROBSourceIDs", m_sourceIDsProp,
70 "ROB fragment source identifiers");
71
72 // Properties for writing bytestream only
73 declareProperty("DataVersion", m_version = 1,
74 "Format version number in sub-block header");
75 declareProperty("DataFormat", m_dataFormat = 1,
76 "Format identifier (0-1) in sub-block header");
77 declareProperty("SlinksPerCrate", m_slinks = 2,
78 "The number of S-Links per crate");
79 declareProperty("SimulSlices", m_dfltSlices = 1,
80 "The number of slices in the simulation");
81 declareProperty("ForceSlices", m_forceSlices = 0,
82 "If >0, the number of slices in bytestream");
83 declareProperty("CrateMin", m_crateMin = 0,
84 "Minimum crate number, allows partial output");
85 declareProperty("CrateMax", m_crateMax = m_crates-1,
86 "Maximum crate number, allows partial output");
87
88}
89
90// Destructor
91
95
96// Initialize
97
98
100{
101 ATH_MSG_INFO( "Initializing " << name() );
102
103 ATH_CHECK( m_cpmMaps.retrieve() );
104 ATH_CHECK( m_errorTool.retrieve() );
105 ATH_CHECK( m_byteStreamCnvSvc.retrieve() );
106
107 return StatusCode::SUCCESS;
108}
109
110// Conversion bytestream to CPM towers
111
113 const std::string& sgKey,
114 const IROBDataProviderSvc::VROBFRAG& robFrags,
115 DataVector<LVL1::CPMTower>* const ttCollection) const
116{
117 CpmTowerData data (ttCollection);
118 return convertBs(sgKey, robFrags, data);
119}
120
121// Conversion bytestream to CPM hits
122
124 const std::string& sgKey,
125 const IROBDataProviderSvc::VROBFRAG& robFrags,
126 DataVector<LVL1::CPMHits>* const hitCollection) const
127{
128 CpmHitsData data (hitCollection);
129 return convertBs(sgKey, robFrags, data);
130}
131
132// Conversion bytestream to CMM-CP hits
133
135 const std::string& sgKey,
136 const IROBDataProviderSvc::VROBFRAG& robFrags,
137 DataVector<LVL1::CMMCPHits>* const hitCollection) const
138{
139 CmmHitsData data (hitCollection);
140 return convertBs(sgKey, robFrags, data);
141}
142
143// Conversion of CP container to bytestream
144
146{
147 const bool debug = msgLvl(MSG::DEBUG);
148 if (debug) msg(MSG::DEBUG);
149
150 // Get the event assembler
152 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
153 "CpByteStreamV1") );
154 const uint16_t minorVersion = m_srcIdMap.minorVersionPreLS1();
155 fea->setRodMinorVersion(minorVersion);
156
157 // Pointer to ROD data vector
158
160
161 // Set up the container maps
162
163 LVL1::TriggerTowerKey towerKey;
164
165 // CPM tower map
166 ConstCpmTowerMap ttMap;
167 setupCpmTowerMap(cp->towers(), ttMap, towerKey);
168
169 // CPM hits map
170 ConstCpmHitsMap hitsMap;
171 setupCpmHitsMap(cp->hits(), hitsMap);
172
173 // CMM-CP hits map
174 ConstCmmCpHitsMap cmmHitsMap;
175 setupCmmCpHitsMap(cp->cmmHits(), cmmHitsMap);
176
177 // Loop over data
178
179 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
180 const int modulesPerSlink = m_modules / m_slinks;
181 int timeslices = 1;
182 int trigCpm = 0;
183 int timeslicesNew = 1;
184 int trigCpmNew = 0;
185 for (int crate = m_crateMin; crate <= m_crateMax; ++crate) {
186 const int hwCrate = crate + m_crateOffsetHw;
187
188 // CPM modules are numbered 1 to m_modules
189 for (int module=1; module <= m_modules; ++module) {
190 const int mod = module - 1;
191
192 // Pack required number of modules per slink
193
194 if (mod%modulesPerSlink == 0) {
195 const int daqOrRoi = 0;
196 const int slink = (m_slinks == 2) ? 2*(mod/modulesPerSlink)
197 : mod/modulesPerSlink;
198 if (debug) {
199 msg() << "Treating crate " << hwCrate
200 << " slink " << slink << endmsg;
201 }
202 // Get number of CPM slices and triggered slice offset
203 // for this slink
204 if ( ! slinkSlices(crate, module, modulesPerSlink,
205 timeslices, trigCpm,
206 ttMap,
207 hitsMap,
208 cmmHitsMap,
209 towerKey)) {
210 msg(MSG::ERROR) << "Inconsistent number of slices or "
211 << "triggered slice offsets in data for crate "
212 << hwCrate << " slink " << slink << endmsg;
213 return StatusCode::FAILURE;
214 }
215 timeslicesNew = (m_forceSlices) ? m_forceSlices : timeslices;
216 trigCpmNew = ModifySlices::peak(trigCpm, timeslices, timeslicesNew);
217 if (debug) {
218 msg() << "Data Version/Format: " << m_version
219 << " " << m_dataFormat << endmsg
220 << "Slices/offset: " << timeslices << " " << trigCpm;
221 if (timeslices != timeslicesNew) {
222 msg() << " modified to " << timeslicesNew << " " << trigCpmNew;
223 }
224 msg() << endmsg;
225 }
226 L1CaloUserHeader userHeader;
227 userHeader.setCpm(trigCpmNew);
228 const uint32_t rodIdCpm = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
230 theROD = fea->getRodData(rodIdCpm);
231 theROD->push_back(userHeader.header());
232 }
233 if (debug) msg() << "Module " << module << endmsg;
234
235 // Create a sub-block for each slice (except Neutral format)
236
237 // Vector for current CPM sub-blocks
239
240 for (int slice = 0; slice < timeslicesNew; ++slice) {
241 CpmSubBlockV1* const subBlock = new CpmSubBlockV1();
242 subBlock->setCpmHeader(m_version, m_dataFormat, slice,
243 hwCrate, module, timeslicesNew);
244 cpmBlocks.push_back(subBlock);
245 if (neutralFormat) break;
246 }
247
248 // Find CPM towers corresponding to each eta/phi pair and fill
249 // sub-blocks
250
251 for (int chan=0; chan < m_channels; ++chan) {
252 double eta = 0.;
253 double phi = 0.;
254 int layer = 0;
255 if (m_cpmMaps->mapping(crate, module, chan, eta, phi, layer)) {
256 const unsigned int key = towerKey.ttKey(phi, eta);
257 const LVL1::CPMTower* const tt = findCpmTower(key, ttMap);
258 if (tt ) {
259 std::vector<int> emData;
260 std::vector<int> hadData;
261 std::vector<int> emError;
262 std::vector<int> hadError;
263 ModifySlices::data(tt->emEnergyVec(), emData, timeslicesNew);
264 ModifySlices::data(tt->hadEnergyVec(), hadData, timeslicesNew);
265 ModifySlices::data(tt->emErrorVec(), emError, timeslicesNew);
266 ModifySlices::data(tt->hadErrorVec(), hadError, timeslicesNew);
267 for (int slice = 0; slice < timeslicesNew; ++slice) {
268 const LVL1::DataError emErrBits(emError[slice]);
269 const LVL1::DataError hadErrBits(hadError[slice]);
270 const int emErr =
271 (emErrBits.get(LVL1::DataError::LinkDown) << 1) |
272 emErrBits.get(LVL1::DataError::Parity);
273 const int hadErr =
274 (hadErrBits.get(LVL1::DataError::LinkDown) << 1) |
275 hadErrBits.get(LVL1::DataError::Parity);
276 const int index = ( neutralFormat ) ? 0 : slice;
277 CpmSubBlockV1* const subBlock = cpmBlocks[index];
278 subBlock->fillTowerData(slice, chan, emData[slice],
279 hadData[slice], emErr, hadErr);
280 }
281 }
282 }
283 }
284
285 // Add CPM hits
286
287 const LVL1::CPMHits* const hits = findCpmHits(crate, module, hitsMap);
288 if (hits) {
289 std::vector<unsigned int> vec0;
290 std::vector<unsigned int> vec1;
291 ModifySlices::data(hits->HitsVec0(), vec0, timeslicesNew);
292 ModifySlices::data(hits->HitsVec1(), vec1, timeslicesNew);
293 for (int slice = 0; slice < timeslicesNew; ++slice) {
294 const int index = ( neutralFormat ) ? 0 : slice;
295 CpmSubBlockV1* const subBlock = cpmBlocks[index];
296 subBlock->setHits(slice, vec0[slice], vec1[slice]);
297 }
298 }
299
300 // Pack and write the sub-blocks
301
303 for (pos = cpmBlocks.begin(); pos != cpmBlocks.end(); ++pos) {
304 CpmSubBlockV1* const subBlock = *pos;
305 if ( !subBlock->pack()) {
306 msg(MSG::ERROR) << "CPM sub-block packing failed" << endmsg;
307 return StatusCode::FAILURE;
308 }
309 if (debug) {
310 msg() << "CPM sub-block data words: "
311 << subBlock->dataWords() << endmsg;
312 }
313 subBlock->write(theROD);
314 }
315 }
316
317 // Append CMMs to last S-Link of the crate
318
319 // Create a sub-block for each slice (except Neutral format)
320
322 DataVector<CmmCpSubBlock> cmmHit0Blocks;
324 DataVector<CmmCpSubBlock> cmmHit1Blocks;
325
326 const int summing = (crate == m_crates - 1) ? CmmSubBlock::SYSTEM
328 for (int slice = 0; slice < timeslicesNew; ++slice) {
329 CmmCpSubBlock* const h0Block = new CmmCpSubBlock();
330 h0Block->setCmmHeader(m_version, m_dataFormat, slice, hwCrate,
331 summing, CmmSubBlock::CMM_CP,
332 CmmSubBlock::RIGHT, timeslicesNew);
333 cmmHit0Blocks.push_back(h0Block);
334 CmmCpSubBlock* const h1Block = new CmmCpSubBlock();
335 h1Block->setCmmHeader(m_version, m_dataFormat, slice, hwCrate,
336 summing, CmmSubBlock::CMM_CP,
337 CmmSubBlock::LEFT, timeslicesNew);
338 cmmHit1Blocks.push_back(h1Block);
339 if (neutralFormat) break;
340 }
341
342 // CMM-CP
343
344 const int maxDataID = LVL1::CMMCPHits::MAXID;
345 for (int dataID = 1; dataID < maxDataID; ++dataID) {
346 int source = dataID;
347 if (dataID > m_modules) {
348 if (summing == CmmSubBlock::CRATE &&
349 dataID != LVL1::CMMCPHits::LOCAL) continue;
350 switch (dataID) {
352 source = CmmCpSubBlock::LOCAL;
353 break;
356 break;
359 break;
362 break;
364 source = CmmCpSubBlock::TOTAL;
365 break;
366 default:
367 continue;
368 }
369 }
370 const LVL1::CMMCPHits* const ch = findCmmCpHits(crate, dataID, cmmHitsMap);
371 if ( ch ) {
372 std::vector<unsigned int> hits0;
373 std::vector<unsigned int> hits1;
374 std::vector<int> err0;
375 std::vector<int> err1;
376 ModifySlices::data(ch->HitsVec0(), hits0, timeslicesNew);
377 ModifySlices::data(ch->HitsVec1(), hits1, timeslicesNew);
378 ModifySlices::data(ch->ErrorVec0(), err0, timeslicesNew);
379 ModifySlices::data(ch->ErrorVec1(), err1, timeslicesNew);
380 for (int slice = 0; slice < timeslicesNew; ++slice) {
381 const LVL1::DataError err0Bits(err0[slice]);
382 const LVL1::DataError err1Bits(err1[slice]);
383 const int index = ( neutralFormat ) ? 0 : slice;
384 CmmCpSubBlock* subBlock = cmmHit0Blocks[index];
385 subBlock->setHits(slice, source, hits0[slice],
386 err0Bits.get(LVL1::DataError::Parity));
387 subBlock = cmmHit1Blocks[index];
388 subBlock->setHits(slice, source, hits1[slice],
389 err1Bits.get(LVL1::DataError::Parity));
390 }
391 }
392 }
393 DataVector<CmmCpSubBlock>::iterator cos = cmmHit0Blocks.begin();
394 for (; cos != cmmHit0Blocks.end(); ++cos) {
395 CmmCpSubBlock* const subBlock = *cos;
396 if ( !subBlock->pack()) {
397 msg(MSG::ERROR) << "CMM-Cp sub-block packing failed" << endmsg;
398 return StatusCode::FAILURE;
399 }
400 if (debug) {
401 msg() << "CMM-Cp sub-block data words: "
402 << subBlock->dataWords() << endmsg;
403 }
404 subBlock->write(theROD);
405 }
406 cos = cmmHit1Blocks.begin();
407 for (; cos != cmmHit1Blocks.end(); ++cos) {
408 CmmCpSubBlock* const subBlock = *cos;
409 if ( !subBlock->pack()) {
410 msg(MSG::ERROR) << "CMM-Cp sub-block packing failed" << endmsg;
411 return StatusCode::FAILURE;
412 }
413 if (debug) {
414 msg() << "CMM-Cp sub-block data words: "
415 << subBlock->dataWords() << endmsg;
416 }
417 subBlock->write(theROD);
418 }
419 }
420
421 return StatusCode::SUCCESS;
422}
423
424// Return reference to vector with all possible Source Identifiers
425
426std::vector<uint32_t> CpByteStreamV1Tool::makeSourceIDs() const
427{
428 std::vector<uint32_t> sourceIDs;
429
430 if (!m_sourceIDsProp.empty()) {
432 }
433 else {
434 const int maxCrates = m_crates + m_crateOffsetHw;
435 const int maxSlinks = m_srcIdMap.maxSlinks();
436 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
437 {
438 for (int slink = 0; slink < maxSlinks; ++slink)
439 {
440 const int daqOrRoi = 0;
441 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
443 const uint32_t robId = m_srcIdMap.getRobID(rodId);
444 sourceIDs.push_back(robId);
445 }
446 }
447 }
448 return sourceIDs;
449}
450
451const std::vector<uint32_t>& CpByteStreamV1Tool::sourceIDs() const
452{
453 static const std::vector<uint32_t> sourceIDs = makeSourceIDs();
454 return sourceIDs;
455}
456
457// Convert bytestream to given container type
458
460 const std::string& sgKey,
461 const IROBDataProviderSvc::VROBFRAG& robFrags,
463{
464 LocalData ld;
465
466 const static std::string flag("Overlap");
467 const std::string::size_type pos = sgKey.find(flag);
468 ld.coreOverlap =
469 (pos == std::string::npos || pos != sgKey.length() - flag.length()) ? 0 : 1;
470
471 const bool debug = msgLvl(MSG::DEBUG);
472 if (debug) msg(MSG::DEBUG);
473
474 CmmCpSubBlock cmmCpSubBlock;
475 CpmSubBlockV1 cpmSubBlock;
476
477 // Loop over ROB fragments
478
479 int robCount = 0;
480 std::set<uint32_t> dupCheck;
481 ROBIterator rob = robFrags.begin();
482 ROBIterator robEnd = robFrags.end();
483 for (; rob != robEnd; ++rob) {
484
485 if (debug) {
486 ++robCount;
487 msg() << "Treating ROB fragment " << robCount << endmsg;
488 }
489
490 // Skip fragments with ROB status errors
491
492 uint32_t robid = (*rob)->source_id();
493 if ((*rob)->nstatus() > 0) {
494 ROBPointer robData;
495 (*rob)->status(robData);
496 if (*robData != 0) {
497 m_errorTool->robError(robid, *robData);
498 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
499 continue;
500 }
501 }
502
503 // Skip duplicate fragments
504
505 if (!dupCheck.insert(robid).second) {
507 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
508 continue;
509 }
510
511 // Unpack ROD data (slinks)
512
513 RODPointer payloadBeg;
514 RODPointer payload;
515 RODPointer payloadEnd;
516 (*rob)->rod_data(payloadBeg);
517 payloadEnd = payloadBeg + (*rob)->rod_ndata();
518 payload = payloadBeg;
519 if (payload == payloadEnd) {
520 if (debug) msg() << "ROB fragment empty" << endmsg;
521 continue;
522 }
523
524 // Check identifier
525 const uint32_t sourceID = (*rob)->rod_source_id();
526 if (m_srcIdMap.getRobID(sourceID) != robid ||
527 m_srcIdMap.subDet(sourceID) != m_subDetector ||
528 m_srcIdMap.daqOrRoi(sourceID) != 0 ||
529 (m_srcIdMap.slink(sourceID) != 0 && m_srcIdMap.slink(sourceID) != 2) ||
530 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
531 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates) {
533 if (debug) {
534 msg() << "Wrong source identifier in data: ROD "
535 << MSG::hex << sourceID << " ROB " << robid
536 << MSG::dec << endmsg;
537 }
538 continue;
539 }
540
541 // Check minor version
542 const int minorVersion = (*rob)->rod_version() & 0xffff;
543 if (minorVersion > m_srcIdMap.minorVersionPreLS1()) {
544 if (debug) msg() << "Skipping post-LS1 data" << endmsg;
545 continue;
546 }
547 const int rodCrate = m_srcIdMap.crate(sourceID);
548 if (debug) {
549 msg() << "Treating crate " << rodCrate
550 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
551 }
552
553 // First word should be User Header
554 if ( !L1CaloUserHeader::isValid(*payload) ) {
556 if (debug) msg() << "Invalid or missing user header" << endmsg;
557 continue;
558 }
559 L1CaloUserHeader userHeader(*payload);
560 userHeader.setVersion(minorVersion);
561 const int headerWords = userHeader.words();
562 if (headerWords != 1) {
564 if (debug) msg() << "Unexpected number of user header words: "
565 << headerWords << endmsg;
566 continue;
567 }
568 for (int i = 0; i < headerWords; ++i) ++payload;
569 // triggered slice offsets
570 int trigCpm = userHeader.cpm();
571 int trigCmm = userHeader.cpCmm();
572 if (debug) {
573 msg() << "Minor format version number: " << MSG::hex
574 << minorVersion << MSG::dec << endmsg
575 << "CPM triggered slice offset: " << trigCpm << endmsg
576 << "CMM triggered slice offset: " << trigCmm << endmsg;
577 }
578 if (trigCpm != trigCmm) {
579 const int newTrig = (trigCpm > trigCmm) ? trigCpm : trigCmm;
580 trigCpm = newTrig;
581 trigCmm = newTrig;
582 if (debug) msg() << "Changed both offsets to " << newTrig << endmsg;
583 }
584
585 // Loop over sub-blocks
586
587 ld.rodErr = L1CaloSubBlock::ERROR_NONE;
588 while (payload != payloadEnd) {
589
591 if (debug) msg() << "Unexpected data sequence" << endmsg;
593 break;
594 }
595 if (L1CaloSubBlock::version(*payload) != 1) { // <<== CHECK
596 if (debug) msg() << "Skipping post-LS1 data" << endmsg;
597 break;
598 }
599 if (CmmSubBlock::cmmBlock(*payload)) {
600 // CMM
601 if (CmmSubBlock::cmmType(*payload) == CmmSubBlock::CMM_CP) {
602 cmmCpSubBlock.clear();
603 payload = cmmCpSubBlock.read(payload, payloadEnd);
604 if (cmmCpSubBlock.crate() != rodCrate) {
605 if (debug) msg() << "Inconsistent crate number in ROD source ID"
606 << endmsg;
608 break;
609 }
610 if (data.m_collection == CMM_CP_HITS) {
611 decodeCmmCp(&cmmCpSubBlock, trigCmm, static_cast<CmmHitsData&>(data),
612 ld);
613 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {
614 if (debug) msg() << "decodeCmmCp failed" << endmsg;
615 break;
616 }
617 }
618 } else {
619 if (debug) msg() << "Invalid CMM type in module field" << endmsg;
621 break;
622 }
623 } else {
624 // CPM
625 cpmSubBlock.clear();
626 payload = cpmSubBlock.read(payload, payloadEnd);
627 if (cpmSubBlock.crate() != rodCrate) {
628 if (debug) msg() << "Inconsistent crate number in ROD source ID"
629 << endmsg;
631 break;
632 }
633 if (data.m_collection == CPM_TOWERS || data.m_collection == CPM_HITS) {
634 decodeCpm(&cpmSubBlock, trigCpm, data, ld);
635 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {
636 if (debug) msg() << "decodeCpm failed" << endmsg;
637 break;
638 }
639 }
640 }
641 }
642 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
643 m_errorTool->rodError(robid, ld.rodErr);
644 }
645
646 return StatusCode::SUCCESS;
647}
648
649// Unpack CMM-CP sub-block
650
653 LocalData& ld) const
654{
655 const bool debug = msgLvl(MSG::DEBUG);
656 if (debug) msg(MSG::DEBUG);
657
658 const int hwCrate = subBlock->crate();
659 const int module = subBlock->cmmPosition();
660 const int firmware = subBlock->cmmFirmware();
661 const int summing = subBlock->cmmSumming();
662 const int timeslices = subBlock->timeslices();
663 const int sliceNum = subBlock->slice();
664 if (debug) {
665 msg() << "CMM-CP: Crate " << hwCrate
666 << " Module " << module
667 << " Firmware " << firmware
668 << " Summing " << summing
669 << " Total slices " << timeslices
670 << " Slice " << sliceNum << endmsg;
671 }
672 if (timeslices <= trigCmm) {
673 if (debug) msg() << "Triggered CMM slice from header "
674 << "inconsistent with number of slices: "
675 << trigCmm << ", " << timeslices << endmsg;
677 return;
678 }
679 if (timeslices <= sliceNum) {
680 if (debug) msg() << "Total slices inconsistent with slice number: "
681 << timeslices << ", " << sliceNum << endmsg;
683 return;
684 }
685 // Unpack sub-block
686 if (subBlock->dataWords() && !subBlock->unpack()) {
687 if (debug) {
688 std::string errMsg(subBlock->unpackErrorMsg());
689 msg() << "CMM-CP sub-block unpacking failed: " << errMsg << endmsg;
690 }
691 ld.rodErr = subBlock->unpackErrorCode();
692 return;
693 }
694
695 // Retrieve required data
696
697 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
698 const uint32_t subStatus = subBlock->subStatus();
699 const int crate = hwCrate - m_crateOffsetHw;
700 const int swCrate = crate + m_crateOffsetSw;
701 const int maxSid = CmmCpSubBlock::MAX_SOURCE_ID;
702 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
703 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
704 for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
705
706 // Jet hit counts
707
708 for (int source = 1; source < maxSid; ++source) {
709 int dataID = source;
710 if (source > m_modules) {
711 if (summing == CmmSubBlock::CRATE &&
712 source != CmmCpSubBlock::LOCAL) continue;
713 switch (source) {
715 dataID = LVL1::CMMCPHits::LOCAL;
716 break;
719 break;
722 break;
725 break;
727 dataID = LVL1::CMMCPHits::TOTAL;
728 break;
729 default:
730 continue;
731 }
732 }
733 const unsigned int hits = subBlock->hits(slice, source);
734 int err = subBlock->hitsError(slice, source);
735 LVL1::DataError errorBits;
736 errorBits.set(LVL1::DataError::Parity, err & 0x1);
737 errorBits.set(LVL1::DataError::SubStatusWord, subStatus);
738 err = errorBits.error();
739 if (hits || err) {
740 LVL1::CMMCPHits* ch = findCmmCpHits(data, crate, dataID);
741 if ( ! ch ) { // create new CMM hits
742 ld.hitsVec0.assign(timeslices, 0);
743 ld.hitsVec1.assign(timeslices, 0);
744 ld.errVec0.assign(timeslices, 0);
745 ld.errVec1.assign(timeslices, 0);
746 if (module == CmmSubBlock::RIGHT) {
747 ld.hitsVec0[slice] = hits;
748 ld.errVec0[slice] = err;
749 } else {
750 ld.hitsVec1[slice] = hits;
751 ld.errVec1[slice] = err;
752 }
753 auto chp =
754 std::make_unique<LVL1::CMMCPHits>(swCrate, dataID, ld.hitsVec0, ld.hitsVec1,
755 ld.errVec0, ld.errVec1, trigCmm);
756 const int key = crate*100 + dataID;
757 data.m_cmmHitsMap.insert(std::make_pair(key, chp.get()));
758 data.m_cmmHitCollection->push_back(std::move(chp));
759 } else {
760 ld.hitsVec0 = ch->HitsVec0();
761 ld.hitsVec1 = ch->HitsVec1();
762 ld.errVec0 = ch->ErrorVec0();
763 ld.errVec1 = ch->ErrorVec1();
764 const int nsl = ld.hitsVec0.size();
765 if (timeslices != nsl) {
766 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
767 << endmsg;
769 return;
770 }
771 if ((module == CmmSubBlock::RIGHT && (ld.hitsVec0[slice] != 0 ||
772 ld.errVec0[slice] != 0)) || (module == CmmSubBlock::LEFT &&
773 (ld.hitsVec1[slice] != 0 || ld.errVec1[slice] != 0))) {
774 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
776 return;
777 }
778 if (module == CmmSubBlock::RIGHT) {
779 ld.hitsVec0[slice] = hits;
780 ld.errVec0[slice] = err;
781 } else {
782 ld.hitsVec1[slice] = hits;
783 ld.errVec1[slice] = err;
784 }
785 ch->addHits(ld.hitsVec0, ld.hitsVec1, ld.errVec0, ld.errVec1);
786 }
787 }
788 }
789 }
790
791 return;
792}
793
794// Unpack CPM sub-block
795
797 int trigCpm, CpByteStreamToolData& data,
798 LocalData& ld) const
799{
800 const bool debug = msgLvl(MSG::DEBUG);
801 const bool verbose = msgLvl(MSG::VERBOSE);
802 if (debug) msg(MSG::DEBUG);
803
804 const int hwCrate = subBlock->crate();
805 const int module = subBlock->module();
806 const int timeslices = subBlock->timeslices();
807 const int sliceNum = subBlock->slice();
808 if (debug) {
809 msg() << "CPM: Crate " << hwCrate
810 << " Module " << module
811 << " Total slices " << timeslices
812 << " Slice " << sliceNum << endmsg;
813 }
814 if (module < 1 || module > m_modules) {
815 if (debug) msg() << "Unexpected module number: " << module << endmsg;
817 return;
818 }
819 if (timeslices <= trigCpm) {
820 if (debug) msg() << "Triggered CPM slice from header "
821 << "inconsistent with number of slices: "
822 << trigCpm << ", " << timeslices << endmsg;
824 return;
825 }
826 if (timeslices <= sliceNum) {
827 if (debug) msg() << "Total slices inconsistent with slice number: "
828 << timeslices << ", " << sliceNum << endmsg;
830 return;
831 }
832 // Unpack sub-block
833 if (subBlock->dataWords() && !subBlock->unpack()) {
834 if (debug) {
835 std::string errMsg(subBlock->unpackErrorMsg());
836 msg() << "CPM sub-block unpacking failed: " << errMsg << endmsg;
837 }
838 ld.rodErr = subBlock->unpackErrorCode();
839 return;
840 }
841
842 // Retrieve required data
843
844 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
845 LVL1::DataError dErr;
847 const int ssError = dErr.error();
848 const int crate = hwCrate - m_crateOffsetHw;
849 const int swCrate = crate + m_crateOffsetSw;
850 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
851 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
852 for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
853
854 if (data.m_collection == CPM_TOWERS) {
855 CpmTowerData& tdata = static_cast<CpmTowerData&> (data);
856
857 // Loop over tower channels and fill CPM towers
858
859 for (int chan = 0; chan < m_channels; ++chan) {
860 if (!ssError && !subBlock->anyTowerData(chan)) continue;
861 const int em = subBlock->emData(slice, chan);
862 const int had = subBlock->hadData(slice, chan);
863 const int emErr = subBlock->emError(slice, chan);
864 const int hadErr = subBlock->hadError(slice, chan);
865 int emErr1 = ssError;
866 if (emErr) {
867 LVL1::DataError emErrBits(emErr1);
868 emErrBits.set(LVL1::DataError::Parity, emErr & 0x1);
869 emErrBits.set(LVL1::DataError::LinkDown, (emErr >> 1) & 0x1);
870 emErr1 = emErrBits.error();
871 }
872 int hadErr1 = ssError;
873 if (hadErr) {
874 LVL1::DataError hadErrBits(hadErr1);
875 hadErrBits.set(LVL1::DataError::Parity, hadErr & 0x1);
876 hadErrBits.set(LVL1::DataError::LinkDown, (hadErr >> 1) & 0x1);
877 hadErr1 = hadErrBits.error();
878 }
879 if (em || had || emErr1 || hadErr1) {
880 double eta = 0.;
881 double phi = 0.;
882 int layer = 0;
883 if (m_cpmMaps->mapping(crate, module, chan, eta, phi, layer)) {
884 if (layer == ld.coreOverlap) {
885 const unsigned int key = ld.towerKey.ttKey(phi, eta);
886 LVL1::CPMTower* tt = findCpmTower(tdata, key);
887 if ( ! tt ) { // create new CPM tower
888 ld.emVec.assign(timeslices, 0);
889 ld.hadVec.assign(timeslices, 0);
890 ld.emErrVec.assign(timeslices, 0);
891 ld.hadErrVec.assign(timeslices, 0);
892 ld.emVec[slice] = em;
893 ld.hadVec[slice] = had;
894 ld.emErrVec[slice] = emErr1;
895 ld.hadErrVec[slice] = hadErr1;
896 auto ttp =
897 std::make_unique<LVL1::CPMTower>(phi, eta, ld.emVec, ld.emErrVec,
898 ld.hadVec, ld.hadErrVec, trigCpm);
899 tdata.m_ttMap.insert(std::make_pair(key, ttp.get()));
900 tdata.m_ttCollection->push_back(std::move(ttp));
901 } else {
902 ld.emVec = tt->emEnergyVec();
903 ld.hadVec = tt->hadEnergyVec();
904 ld.emErrVec = tt->emErrorVec();
905 ld.hadErrVec = tt->hadErrorVec();
906 const int nsl = ld.emVec.size();
907 if (timeslices != nsl) {
908 if (debug) {
909 msg() << "Inconsistent number of slices in sub-blocks"
910 << endmsg;
911 }
913 return;
914 }
915 if (ld.emVec[slice] != 0 || ld.hadVec[slice] != 0 ||
916 ld.emErrVec[slice] != 0 || ld.hadErrVec[slice] != 0) {
917 if (debug) msg() << "Duplicate data for slice "
918 << slice << endmsg;
920 return;
921 }
922 ld.emVec[slice] = em;
923 ld.hadVec[slice] = had;
924 ld.emErrVec[slice] = emErr1;
925 ld.hadErrVec[slice] = hadErr1;
926 tt->fill(ld.emVec, ld.emErrVec, ld.hadVec, ld.hadErrVec, trigCpm);
927 }
928 }
929 } else if (verbose && (em || had || emErr || hadErr)) {
930 msg(MSG::VERBOSE) << "Non-zero data but no channel mapping for channel "
931 << chan << endmsg;
932 msg(MSG::DEBUG);
933 }
934 } else if (verbose) {
935 msg(MSG::VERBOSE) << "No CPM tower data for channel "
936 << chan << " slice " << slice << endmsg;
937 msg(MSG::DEBUG);
938 }
939 }
940 } else if (data.m_collection == CPM_HITS) {
941 CpmHitsData& hdata = static_cast<CpmHitsData&> (data);
942
943 // Get CPM hits
944
945 const unsigned int hits0 = subBlock->hits0(slice);
946 const unsigned int hits1 = subBlock->hits1(slice);
947 if (hits0 || hits1) {
948 LVL1::CPMHits* ch = findCpmHits(hdata, crate, module);
949 if ( ! ch ) { // create new CPM hits
950 ld.hitsVec0.assign(timeslices, 0);
951 ld.hitsVec1.assign(timeslices, 0);
952 ld.hitsVec0[slice] = hits0;
953 ld.hitsVec1[slice] = hits1;
954 auto chp =
955 std::make_unique<LVL1::CPMHits>(swCrate, module, ld.hitsVec0, ld.hitsVec1, trigCpm);
956 hdata.m_hitsMap.insert(std::make_pair(crate*m_modules+module-1, chp.get()));
957 hdata.m_hitCollection->push_back(std::move(chp));
958 } else {
959 ld.hitsVec0 = ch->HitsVec0();
960 ld.hitsVec1 = ch->HitsVec1();
961 const int nsl = ld.hitsVec0.size();
962 if (timeslices != nsl) {
963 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
964 << endmsg;
966 return;
967 }
968 if (ld.hitsVec0[slice] != 0 || ld.hitsVec1[slice] != 0) {
969 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
971 return;
972 }
973 ld.hitsVec0[slice] = hits0;
974 ld.hitsVec1[slice] = hits1;
975 ch->addHits(ld.hitsVec0, ld.hitsVec1);
976 }
977 } else if (verbose) {
978 msg(MSG::VERBOSE) << "No CPM hits data for crate/module/slice "
979 << hwCrate << "/" << module << "/" << slice
980 << endmsg;
981 msg(MSG::DEBUG);
982 }
983 }
984 }
985 return;
986}
987
988// Find a CPM tower for given key
989
990const
992 const ConstCpmTowerMap& ttMap) const
993{
994 ConstCpmTowerMap::const_iterator mapIter = ttMap.find(key);
995 if (mapIter != ttMap.end()) return mapIter->second;
996 return nullptr;
997}
998
1000 const unsigned int key) const
1001{
1002 CpmTowerMap::const_iterator mapIter = data.m_ttMap.find(key);
1003 if (mapIter != data.m_ttMap.end()) return mapIter->second;
1004 return nullptr;
1005}
1006
1007// Find CPM hits for given crate, module
1008
1009const
1011 const int module,
1012 const ConstCpmHitsMap& hitsMap) const
1013{
1014 ConstCpmHitsMap::const_iterator mapIter =
1015 hitsMap.find(crate*m_modules + module - 1);
1016 if (mapIter != hitsMap.end()) return mapIter->second;
1017 return nullptr;
1018}
1019
1021 const int crate, const int module) const
1022{
1023 CpmHitsMap::const_iterator mapIter =
1024 data.m_hitsMap.find(crate*m_modules + module - 1);
1025 if (mapIter != data.m_hitsMap.end()) return mapIter->second;
1026 return nullptr;
1027}
1028
1029// Find CMM-CP hits for given crate, dataID
1030
1031const
1033 const int dataID,
1034 const ConstCmmCpHitsMap& cmmHitsMap) const
1035{
1036 ConstCmmCpHitsMap::const_iterator mapIter = cmmHitsMap.find(crate*100 + dataID);
1037 if (mapIter != cmmHitsMap.end()) return mapIter->second;
1038 return nullptr;
1039}
1040
1042 const int crate,
1043 const int dataID) const
1044{
1045 CmmCpHitsMap::const_iterator mapIter = data.m_cmmHitsMap.find(crate*100 + dataID);
1046 if (mapIter != data.m_cmmHitsMap.end()) return mapIter->second;
1047 return nullptr;
1048}
1049
1050// Set up CPM tower map
1051
1053 ConstCpmTowerMap& ttMap,
1054 LVL1::TriggerTowerKey& towerKey) const
1055{
1056 ttMap.clear();
1057 if (ttCollection) {
1058 CpmTowerCollection::const_iterator pos = ttCollection->begin();
1059 CpmTowerCollection::const_iterator pose = ttCollection->end();
1060 for (; pos != pose; ++pos) {
1061 const LVL1::CPMTower* const tt = *pos;
1062 const unsigned int key = towerKey.ttKey(tt->phi(), tt->eta());
1063 ttMap.insert(std::make_pair(key, tt));
1064 }
1065 }
1066}
1067
1068// Set up CPM hits map
1069
1071 const hitCollection,
1072 ConstCpmHitsMap& hitsMap) const
1073{
1074 hitsMap.clear();
1075 if (hitCollection) {
1076 CpmHitsCollection::const_iterator pos = hitCollection->begin();
1077 CpmHitsCollection::const_iterator pose = hitCollection->end();
1078 for (; pos != pose; ++pos) {
1079 const LVL1::CPMHits* const hits = *pos;
1080 const int crate = hits->crate() - m_crateOffsetSw;
1081 const int key = m_modules * crate + hits->module() - 1;
1082 hitsMap.insert(std::make_pair(key, hits));
1083 }
1084 }
1085}
1086
1087// Set up CMM-CP hits map
1088
1090 const hitCollection,
1091 ConstCmmCpHitsMap& cmmHitsMap) const
1092{
1093 cmmHitsMap.clear();
1094 if (hitCollection) {
1095 CmmCpHitsCollection::const_iterator pos = hitCollection->begin();
1096 CmmCpHitsCollection::const_iterator pose = hitCollection->end();
1097 for (; pos != pose; ++pos) {
1098 const LVL1::CMMCPHits* const hits = *pos;
1099 const int crate = hits->crate() - m_crateOffsetSw;
1100 const int key = crate*100 + hits->dataID();
1101 cmmHitsMap.insert(std::make_pair(key, hits));
1102 }
1103 }
1104}
1105
1106// Get number of slices and triggered slice offset for next slink
1107
1108bool CpByteStreamV1Tool::slinkSlices(const int crate, const int module,
1109 const int modulesPerSlink,
1110 int& timeslices,
1111 int& trigCpm,
1112 const ConstCpmTowerMap& ttMap,
1113 const ConstCpmHitsMap& hitsMap,
1114 const ConstCmmCpHitsMap& cmmHitsMap,
1115 LVL1::TriggerTowerKey& towerKey) const
1116{
1117 int slices = -1;
1118 int trigC = m_dfltSlices/2;
1119 for (int mod = module; mod < module + modulesPerSlink; ++mod) {
1120 for (int chan = 0; chan < m_channels; ++chan) {
1121 double eta = 0.;
1122 double phi = 0.;
1123 int layer = 0;
1124 if ( !m_cpmMaps->mapping(crate, mod, chan, eta, phi, layer)) continue;
1125 const unsigned int key = towerKey.ttKey(phi, eta);
1126 const LVL1::CPMTower* const tt = findCpmTower(key, ttMap);
1127 if ( !tt ) continue;
1128 const int numdat = 4;
1129 std::vector<int> sums(numdat);
1130 std::vector<int> sizes(numdat);
1131 sums[0] = std::accumulate((tt->emEnergyVec()).begin(),
1132 (tt->emEnergyVec()).end(), 0);
1133 sums[1] = std::accumulate((tt->hadEnergyVec()).begin(),
1134 (tt->hadEnergyVec()).end(), 0);
1135 sums[2] = std::accumulate((tt->emErrorVec()).begin(),
1136 (tt->emErrorVec()).end(), 0);
1137 sums[3] = std::accumulate((tt->hadErrorVec()).begin(),
1138 (tt->hadErrorVec()).end(), 0);
1139 sizes[0] = (tt->emEnergyVec()).size();
1140 sizes[1] = (tt->hadEnergyVec()).size();
1141 sizes[2] = (tt->emErrorVec()).size();
1142 sizes[3] = (tt->hadErrorVec()).size();
1143 const int peak = tt->peak();
1144 for (int i = 0; i < numdat; ++i) {
1145 if (sums[i] == 0) continue;
1146 if (slices < 0) {
1147 slices = sizes[i];
1148 trigC = peak;
1149 } else if (slices != sizes[i] || trigC != peak) return false;
1150 }
1151 }
1152 const LVL1::CPMHits* const hits = findCpmHits(crate, mod, hitsMap);
1153 if (hits) {
1154 const int numdat = 2;
1155 std::vector<unsigned int> sums(numdat);
1156 std::vector<int> sizes(numdat);
1157 sums[0] = std::accumulate((hits->HitsVec0()).begin(),
1158 (hits->HitsVec0()).end(), 0);
1159 sums[1] = std::accumulate((hits->HitsVec1()).begin(),
1160 (hits->HitsVec1()).end(), 0);
1161 sizes[0] = (hits->HitsVec0()).size();
1162 sizes[1] = (hits->HitsVec1()).size();
1163 const int peak = hits->peak();
1164 for (int i = 0; i < numdat; ++i) {
1165 if (sums[i] == 0) continue;
1166 if (slices < 0) {
1167 slices = sizes[i];
1168 trigC = peak;
1169 } else if (slices != sizes[i] || trigC != peak) return false;
1170 }
1171 }
1172 }
1173 // CMM last slink of crate
1174 if (module/modulesPerSlink == m_slinks - 1) {
1175 const int maxDataID = LVL1::CMMCPHits::MAXID;
1176 for (int dataID = 0; dataID < maxDataID; ++dataID) {
1177 const int numdat = 4;
1178 std::vector<unsigned int> sums(numdat);
1179 std::vector<int> sizes(numdat);
1180 const LVL1::CMMCPHits* const hits = findCmmCpHits(crate, dataID, cmmHitsMap);
1181 if (hits) {
1182 sums[0] = std::accumulate((hits->HitsVec0()).begin(),
1183 (hits->HitsVec0()).end(), 0);
1184 sums[1] = std::accumulate((hits->HitsVec1()).begin(),
1185 (hits->HitsVec1()).end(), 0);
1186 sums[2] = std::accumulate((hits->ErrorVec0()).begin(),
1187 (hits->ErrorVec0()).end(), 0);
1188 sums[3] = std::accumulate((hits->ErrorVec1()).begin(),
1189 (hits->ErrorVec1()).end(), 0);
1190 sizes[0] = (hits->HitsVec0()).size();
1191 sizes[1] = (hits->HitsVec1()).size();
1192 sizes[2] = (hits->ErrorVec0()).size();
1193 sizes[3] = (hits->ErrorVec1()).size();
1194 const int peak = hits->peak();
1195 for (int i = 0; i < numdat; ++i) {
1196 if (sums[i] == 0) continue;
1197 if (slices < 0) {
1198 slices = sizes[i];
1199 trigC = peak;
1200 } else if (slices != sizes[i] || trigC != peak) return false;
1201 }
1202 }
1203 }
1204 }
1205 if (slices < 0) slices = m_dfltSlices;
1206 timeslices = slices;
1207 trigCpm = trigC;
1208 return true;
1209}
1210
1211} // 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_INFO(x)
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 CMM-CP data.
bool unpack()
Unpack data.
void clear()
Clear all data.
unsigned int hits(int slice, int source) const
Return hit counts for given CPM or source ID.
void setHits(int slice, int source, unsigned int hits, int error)
Store hit counts for given CPM or source ID.
int hitsError(int slice, int source) const
Return hit error for given CPM or source ID.
bool pack()
Pack data.
static bool cmmBlock(uint32_t word)
Determine if header word corresponds to CMM.
int timeslices() const
int cmmPosition() const
Definition CmmSubBlock.h:73
void setCmmHeader(int version, int format, int slice, int crate, int summing, int firmware, int position, int timeslices)
Store CMM header.
int cmmFirmware() const
Definition CmmSubBlock.h:68
static CmmFirmwareCode cmmType(uint32_t word)
CMM differentiation (CMM_CP, CMM_JET, or CMM_ENERGY)
int cmmSumming() const
Definition CmmSubBlock.h:63
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
CpByteStreamV1Tool(const std::string &type, const std::string &name, const IInterface *parent)
int m_dfltSlices
Property: Default number of slices in simulation.
int m_crates
Property: Number of crates.
void setupCpmHitsMap(const CpmHitsCollection *hitCollection, ConstCpmHitsMap &hitsMap) const
Set up CPM hits map.
ServiceHandle< IByteStreamCnvSvc > m_byteStreamCnvSvc
bool slinkSlices(int crate, int module, int modulesPerSlink, int &timeslices, int &trigJem, const ConstCpmTowerMap &ttMap, const ConstCpmHitsMap &hitsMap, const ConstCmmCpHitsMap &cmmHitsMap, LVL1::TriggerTowerKey &towerKey) const
Get number of slices and triggered slice offset for next slink.
std::map< int, const LVL1::CPMHits * > ConstCpmHitsMap
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
int m_crateOffsetSw
Property: Software crate number offset.
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
std::map< int, const LVL1::CMMCPHits * > ConstCmmCpHitsMap
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
int m_forceSlices
Property: Force number of slices in bytestream.
const LVL1::CPMHits * findCpmHits(int crate, int module, const ConstCpmHitsMap &hitsMap) const
Find CPM hits for given crate, module.
void setupCmmCpHitsMap(const CmmCpHitsCollection *hitCollection, ConstCmmCpHitsMap &cmmHitsMap) const
Set up CMM-CP hits map.
std::vector< uint32_t > m_sourceIDsProp
Property: ROB source IDs.
void setupCpmTowerMap(const CpmTowerCollection *ttCollection, ConstCpmTowerMap &ttMap, LVL1::TriggerTowerKey &towerKey) const
Set up CPM tower map.
int m_version
Property: Sub_block header version.
std::vector< uint32_t > makeSourceIDs() const
Create list of all source IDs.
StatusCode convertBs(const std::string &sgKey, const IROBDataProviderSvc::VROBFRAG &robFrags, CpByteStreamToolData &data) const
Convert bytestream to given container type.
DataVector< LVL1::CPMHits > CpmHitsCollection
const LVL1::CPMTower * findCpmTower(unsigned int key, const ConstCpmTowerMap &ttMap) const
Find a CPM tower for given key.
std::map< unsigned int, const LVL1::CPMTower * > ConstCpmTowerMap
int m_crateMin
Property: Minimum crate number when writing out bytestream.
ToolHandle< LVL1::IL1CaloMappingTool > m_cpmMaps
Channel mapping tool.
const std::vector< uint32_t > & sourceIDs() const
Return reference to vector with all possible Source Identifiers.
StatusCode convert(const std::string &sgKey, const IROBDataProviderSvc::VROBFRAG &robFrags, DataVector< LVL1::CPMTower > *ttCollection) const
Convert ROB fragments to CPM towers.
int m_dataFormat
Property: Data compression format.
const int m_channels
Number of channels per module.
const LVL1::CMMCPHits * findCmmCpHits(int crate, int dataID, const ConstCmmCpHitsMap &cmmHitsMap) const
Find CMM-CP hits for given crate, data ID.
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Error collection tool.
int m_crateOffsetHw
Property: Hardware crate number offset.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
void decodeCmmCp(CmmCpSubBlock *subBlock, int trigCmm, CmmHitsData &data, LocalData &ld) const
Unpack CMM-CP sub-block.
int m_crateMax
Property: Maximum crate number when writing out bytestream.
virtual StatusCode initialize() override
const eformat::SubDetector m_subDetector
Sub-detector type.
void decodeCpm(CpmSubBlockV1 *subBlock, int trigCpm, CpByteStreamToolData &data, LocalData &ld) const
Unpack CPM sub-block.
DataVector< LVL1::CMMCPHits > CmmCpHitsCollection
DataVector< LVL1::CPMTower > CpmTowerCollection
const int m_modules
Number of CPM modules per crate.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
Sub-Block class for CPM data.
unsigned int hits0(int slice) const
Return e/gamma hit counts.
void setHits(int slice, unsigned int hit0, unsigned int hit1)
Store hit counts.
unsigned int hits1(int slice) const
Return tau hit counts.
bool pack()
Pack data.
int emData(int slice, int channel) const
Return Em data for given channel.
void clear()
Clear all data.
int emError(int slice, int channel) const
Return Em error for given channel.
void setCpmHeader(int version, int format, int slice, int crate, int module, int timeslices)
Store CPM header.
void fillTowerData(int slice, int channel, int em, int had, int emErr, int hadErr)
Store trigger tower data.
int hadError(int slice, int channel) const
Return Had error for given channel.
int timeslices() const
Return number of timeslices.
bool unpack()
Unpack data.
bool anyTowerData(int channel) const
Return true if there is tower data for given channel.
int hadData(int slice, int channel) const
Return Had data for given channel.
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 received by the merger modules.
Cluster Processor container for writing bytestream.
The CPMHits object contains the hit data produced by a given Cluster Processor Module,...
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_ICpByteStreamV1Tool("CpByteStreamV1Tool", 1, 1)
Definition index.py:1