ATLAS Offline Software
Loading...
Searching...
No Matches
JepByteStreamV2Tool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6
7
8#include "GaudiKernel/IInterface.h"
9#include "GaudiKernel/MsgStream.h"
10#include "GaudiKernel/StatusCode.h"
11
13
23
24#include "CmxEnergySubBlock.h"
25#include "CmxJetSubBlock.h"
26#include "CmxSubBlock.h"
27#include "JemJetElement.h"
28#include "JemSubBlockV2.h"
30#include "L1CaloSubBlock.h"
31#include "L1CaloUserHeader.h"
32#include "ModifySlices.h"
33
34#include "JepByteStreamV2Tool.h"
35
36#include <numeric>
37#include <set>
38#include <utility>
39
40namespace LVL1BS {
41
42// Interface ID
43
44static const InterfaceID IID_IJepByteStreamV2Tool("JepByteStreamV2Tool", 1, 1);
45
47{
49}
50
51// Constructor
52
54 const std::string& name,
55 const IInterface* parent)
56 : AthAlgTool(type, name, parent),
57 m_robDataProvider("ROBDataProviderSvc", name),
58 m_jemMaps("LVL1::JemMappingTool/JemMappingTool"),
59 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
61 m_maxTobs(4),
62 m_subDetector(eformat::TDAQ_CALO_JET_PROC_DAQ)
63{
64 declareInterface<JepByteStreamV2Tool>(this);
65
66 declareProperty("JemMappingTool", m_jemMaps,
67 "Crate/Module/Channel to Eta/Phi/Layer mapping tool");
68 declareProperty("ErrorTool", m_errorTool,
69 "Tool to collect errors for monitoring");
70
71 declareProperty("CrateOffsetHw", m_crateOffsetHw = 12,
72 "Offset of JEP crate numbers in bytestream");
73 declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
74 "Offset of JEP crate numbers in RDOs");
75 declareProperty("SlinksPerCrate", m_slinks = 4,
76 "The number of S-Links per crate");
77
78 // Properties for reading bytestream only
79 declareProperty("ROBSourceIDs", m_sourceIDsProp,
80 "ROB fragment source identifiers");
81
82 // Properties for writing bytestream only
83 declareProperty("DataVersion", m_version = 2, //<<== CHECK
84 "Format version number in sub-block header");
85 declareProperty("DataFormat", m_dataFormat = 1,
86 "Format identifier (0-1) in sub-block header");
87 declareProperty("SimulSlices", m_dfltSlices = 1,
88 "The number of slices in the simulation");
89 declareProperty("ForceSlices", m_forceSlices = 0,
90 "If >0, the number of slices in bytestream");
91 declareProperty("CrateMin", m_crateMin = 0,
92 "Minimum crate number, allows partial output");
93 declareProperty("CrateMax", m_crateMax = m_crates-1,
94 "Maximum crate number, allows partial output");
95
96}
97
98// Destructor
99
103
104// Initialize
105
106
108{
109 ATH_MSG_INFO ("Initializing " << name());
110
111 ATH_CHECK( m_jemMaps.retrieve() );
112 ATH_CHECK( m_errorTool.retrieve() );
113 if (m_enableEncoding.value()) {
114 m_byteStreamCnvSvc = serviceLocator()->service("ByteStreamCnvSvc");
115 ATH_CHECK(m_byteStreamCnvSvc.isValid());
116 }
117
118 return StatusCode::SUCCESS;
119}
120
121// Finalize
122
124{
125 return StatusCode::SUCCESS;
126}
127
128// Conversion bytestream to jet elements
129
131 const std::string& sgKey,
132 DataVector<LVL1::JetElement>* collection) const
133{
134 const std::vector<uint32_t>& vID(sourceIDs());
135 // // get ROB fragments
137 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "JepByteStreamV2Tool");
138 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
139 return convert(sgKey, robFrags, collection);
140}
141
143 const std::string& sgKey,
144 const IROBDataProviderSvc::VROBFRAG& robFrags,
145 DataVector<LVL1::JetElement>* jeCollection) const
146{
147 JetElementData data (jeCollection);
148 return convertBs(sgKey, robFrags, data);
149}
150
151// Conversion bytestream to energy sums
153 const std::string& sgKey,
154 DataVector<LVL1::JEMEtSums>* collection) const
155{
156 const std::vector<uint32_t>& vID(sourceIDs());
157 // // get ROB fragments
159 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "JepByteStreamV2Tool");
160 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
161 return convert(sgKey, robFrags, collection);
162}
163
165 const std::string& sgKey,
166 const IROBDataProviderSvc::VROBFRAG& robFrags,
167 DataVector<LVL1::JEMEtSums>* etCollection) const
168{
169 EnergySumsData data (etCollection);
170 return convertBs(sgKey, robFrags, data);
171}
172
173// Conversion bytestream to CMX TOBs
175 const std::string& sgKey,
176 DataVector<LVL1::CMXJetTob>* collection) const
177{
178 const std::vector<uint32_t>& vID(sourceIDs());
179 // // get ROB fragments
181 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "JepByteStreamV2Tool");
182 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
183 return convert(sgKey, robFrags, collection);
184}
185
187 const std::string& sgKey,
188 const IROBDataProviderSvc::VROBFRAG& robFrags,
189 DataVector<LVL1::CMXJetTob>* tobCollection) const
190{
191 CmxTobData data (tobCollection);
192 return convertBs(sgKey, robFrags, data);
193}
194
195// Conversion bytestream to CMX hits
197 const std::string& sgKey,
198 DataVector<LVL1::CMXJetHits>* collection) const
199{
200 const std::vector<uint32_t>& vID(sourceIDs());
201 // // get ROB fragments
203 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "JepByteStreamV2Tool");
204 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
205 return convert(sgKey, robFrags, collection);
206}
207
209 const std::string& sgKey,
210 const IROBDataProviderSvc::VROBFRAG& robFrags,
211 DataVector<LVL1::CMXJetHits>* hitCollection) const
212{
213 CmxHitsData data (hitCollection);
214 return convertBs(sgKey, robFrags, data);
215}
216
217// Conversion bytestream to CMX energy sums
218
220 const std::string& sgKey,
221 DataVector<LVL1::CMXEtSums>* collection) const
222{
223 const std::vector<uint32_t>& vID(sourceIDs());
224 // // get ROB fragments
226 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "JepByteStreamV2Tool");
227 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
228 return convert(sgKey, robFrags, collection);
229}
230
232 const std::string& sgKey,
233 const IROBDataProviderSvc::VROBFRAG& robFrags,
234 DataVector<LVL1::CMXEtSums>* etCollection) const
235{
236 CmxSumsData data (etCollection);
237 return convertBs(sgKey, robFrags, data);
238}
239
240// Conversion of JEP container to bytestream
241
243{
244 if (not m_enableEncoding.value()) {
245 ATH_MSG_ERROR("Encoding method called while " << m_enableEncoding.name() << "=False");
246 return StatusCode::FAILURE;
247 }
248
249 const bool debug = msgLvl(MSG::DEBUG);
250 if (debug) msg(MSG::DEBUG);
251
252 // Get the event assembler
254 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
255 "JepByteStreamV2") );
256 const uint16_t minorVersion = m_srcIdMap.minorVersion();
257 fea->setRodMinorVersion(minorVersion);
258
259 // Pointer to ROD data vector
260
262
263 // Jet element key provider
264 LVL1::JetElementKey elementKey;
265
266 // Set up the container maps
267
268 // Jet element map
269 ConstJetElementMap jeMap;
270 setupJeMap(jep->JetElements(), jeMap, elementKey);
271
272 // Energy sums map
273 ConstEnergySumsMap etMap;
274 setupEtMap(jep->EnergySums(), etMap);
275
276 // CMX TOB map
277 ConstCmxTobMap cmxTobMap;
278 setupCmxTobMap(jep->CmxTobs(), cmxTobMap);
279
280 // CMX hits map
281 ConstCmxHitsMap cmxHitsMap;
282 setupCmxHitsMap(jep->CmxHits(), cmxHitsMap);
283
285 ConstCmxSumsMap cmxEtMap;
286 setupCmxEtMap(jep->CmxSums(), cmxEtMap);
287
288 // Loop over data
289
290 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
291 const int modulesPerSlink = m_modules / m_slinks;
292 int timeslices = 1;
293 int trigJem = 0;
294 int timeslicesNew = 1;
295 int trigJemNew = 0;
296 for (int crate = m_crateMin; crate <= m_crateMax; ++crate) {
297 const int hwCrate = crate + m_crateOffsetHw;
298
299 for (int module=0; module < m_modules; ++module) {
300
301 // Pack required number of modules per slink
302
303 if (module%modulesPerSlink == 0) {
304 const int daqOrRoi = 0;
305 const int slink = module/modulesPerSlink;
306 if (debug) {
307 msg() << "Treating crate " << hwCrate
308 << " slink " << slink << endmsg;
309 }
310 // Get number of JEM slices and triggered slice offset
311 // for this slink
312 if ( ! slinkSlices(crate, module, modulesPerSlink,
313 timeslices, trigJem,
314 jeMap,
315 etMap,
316 cmxTobMap,
317 cmxHitsMap,
318 cmxEtMap,
319 elementKey))
320 {
321 msg(MSG::ERROR) << "Inconsistent number of slices or "
322 << "triggered slice offsets in data for crate "
323 << hwCrate << " slink " << slink << endmsg;
324 return StatusCode::FAILURE;
325 }
326 timeslicesNew = (m_forceSlices) ? m_forceSlices : timeslices;
327 trigJemNew = ModifySlices::peak(trigJem, timeslices, timeslicesNew);
328 if (debug) {
329 msg() << "Data Version/Format: " << m_version
330 << " " << m_dataFormat << endmsg
331 << "Slices/offset: " << timeslices << " " << trigJem;
332 if (timeslices != timeslicesNew) {
333 msg() << " modified to " << timeslicesNew << " " << trigJemNew;
334 }
335 msg() << endmsg;
336 }
337 L1CaloUserHeader userHeader;
338 userHeader.setJem(trigJemNew);
339 const uint32_t rodIdJem = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
341 theROD = fea->getRodData(rodIdJem);
342 theROD->push_back(userHeader.header());
343 }
344 if (debug) msg() << "Module " << module << endmsg;
345
346 // Create a sub-block for each slice (except Neutral format)
347
348 // Vector for current JEM sub-blocks
350 for (int slice = 0; slice < timeslicesNew; ++slice) {
351 JemSubBlockV2* const subBlock = new JemSubBlockV2();
352 subBlock->setJemHeader(m_version, m_dataFormat, slice,
353 hwCrate, module, timeslicesNew);
354 jemBlocks.push_back(subBlock);
355 if (neutralFormat) break;
356 }
357
358 // Find jet elements corresponding to each eta/phi pair and fill
359 // sub-blocks
360
361 for (int chan=0; chan < m_channels; ++chan) {
362 double eta = 0.;
363 double phi = 0.;
364 int layer = 0;
365 if (m_jemMaps->mapping(crate, module, chan, eta, phi, layer)) {
366 const LVL1::JetElement* const je = findJetElement(eta, phi, jeMap,
367 elementKey);
368 if (je ) {
369 std::vector<int> emData;
370 std::vector<int> hadData;
371 std::vector<int> emErrors;
372 std::vector<int> hadErrors;
373 ModifySlices::data(je->emEnergyVec(), emData, timeslicesNew);
374 ModifySlices::data(je->hadEnergyVec(), hadData, timeslicesNew);
375 ModifySlices::data(je->emErrorVec(), emErrors, timeslicesNew);
376 ModifySlices::data(je->hadErrorVec(), hadErrors, timeslicesNew);
377 for (int slice = 0; slice < timeslicesNew; ++slice) {
378 const LVL1::DataError emErrBits(emErrors[slice]);
379 const LVL1::DataError hadErrBits(hadErrors[slice]);
380 const int index = ( neutralFormat ) ? 0 : slice;
381 JemSubBlockV2* const subBlock = jemBlocks[index];
382 const JemJetElement jetEle(chan, emData[slice], hadData[slice],
383 emErrBits.get(LVL1::DataError::Parity),
384 hadErrBits.get(LVL1::DataError::Parity),
385 emErrBits.get(LVL1::DataError::LinkDown) +
386 (hadErrBits.get(LVL1::DataError::LinkDown) << 1));
387 subBlock->fillJetElement(slice, jetEle);
388 if ((emErrBits.error() >> LVL1::DataError::GLinkParity)) {
389 int gLinkParity = emErrBits.get(LVL1::DataError::GLinkParity);
390 int gLinkProtocol = emErrBits.get(LVL1::DataError::GLinkProtocol);
391 int bCNMismatch = emErrBits.get(LVL1::DataError::BCNMismatch);
392 int fIFOOverflow = emErrBits.get(LVL1::DataError::FIFOOverflow);
393 int moduleError = emErrBits.get(LVL1::DataError::ModuleError);
394 int gLinkDown = emErrBits.get(LVL1::DataError::GLinkDown);
395 int gLinkTimeout = emErrBits.get(LVL1::DataError::GLinkTimeout);
396 uint32_t failingBCN = emErrBits.get(LVL1::DataError::FailingBCN);
397 subBlock->setStatus(failingBCN, gLinkTimeout, gLinkDown,
398 moduleError, fIFOOverflow, bCNMismatch,
399 gLinkProtocol, gLinkParity);
400 }
401 }
402 }
403 }
404 }
405
406 // Add energy subsums
407
408 const LVL1::JEMEtSums* const et = findEnergySums(crate, module, etMap);
409 if (et) {
410 std::vector<unsigned int> exVec;
411 std::vector<unsigned int> eyVec;
412 std::vector<unsigned int> etVec;
413 ModifySlices::data(et->ExVec(), exVec, timeslicesNew);
414 ModifySlices::data(et->EyVec(), eyVec, timeslicesNew);
415 ModifySlices::data(et->EtVec(), etVec, timeslicesNew);
416 for (int slice = 0; slice < timeslicesNew; ++slice) {
417 const int index = ( neutralFormat ) ? 0 : slice;
418 JemSubBlockV2* const subBlock = jemBlocks[index];
419 subBlock->setEnergySubsums(slice, exVec[slice], eyVec[slice],
420 etVec[slice]);
421 }
422 }
423
424 // Pack and write the sub-blocks
425
427 for (pos = jemBlocks.begin(); pos != jemBlocks.end(); ++pos) {
428 JemSubBlockV2* const subBlock = *pos;
429 if ( !subBlock->pack()) {
430 msg(MSG::ERROR) << "JEM sub-block packing failed" << endmsg;
431 return StatusCode::FAILURE;
432 }
433 if (debug) {
434 msg() << "JEM sub-block data words: "
435 << subBlock->dataWords() << endmsg;
436 }
437 subBlock->write(theROD);
438 }
439 }
440
441 // Append CMXs to last S-Link of the crate
442
443 // Create a sub-block for each slice (except Neutral format)
444
445 // Vector for current CMX-Energy sub-blocks
446 DataVector<CmxEnergySubBlock> cmxEnergyBlocks;
447 // Vector for current CMX-Jet sub-blocks
448 DataVector<CmxJetSubBlock> cmxJetBlocks;
449
450 const int summing = (crate == m_crates - 1) ? CmxSubBlock::SYSTEM
452 for (int slice = 0; slice < timeslicesNew; ++slice) {
453 CmxEnergySubBlock* const enBlock = new CmxEnergySubBlock();
454 const int cmxEnergyVersion = 3; // <<== CHECK Make jo property for each sub-block?
455 enBlock->setCmxHeader(cmxEnergyVersion, m_dataFormat, slice, hwCrate,
457 CmxSubBlock::LEFT, timeslicesNew);
458 cmxEnergyBlocks.push_back(enBlock);
459 CmxJetSubBlock* const jetBlock = new CmxJetSubBlock();
460 jetBlock->setCmxHeader(m_version, m_dataFormat, slice, hwCrate,
461 summing, CmxSubBlock::CMX_JET,
462 CmxSubBlock::RIGHT, timeslicesNew);
463 cmxJetBlocks.push_back(jetBlock);
464 if (neutralFormat) break;
465 }
466
467 // CMX-Energy
468
469 int maxSource = static_cast<int>(LVL1::CMXEtSums::MAX_SOURCE);
470 for (int source = 0; source < maxSource; ++source) {
471 if (source >= m_modules) {
472 if (summing == CmxSubBlock::CRATE &&
474 source != LVL1::CMXEtSums::LOCAL_RESTRICTED) continue;
475 }
476 const LVL1::CMXEtSums* const sums = findCmxSums(crate, source, cmxEtMap);
477 if ( sums ) {
478 std::vector<unsigned int> ex;
479 std::vector<unsigned int> ey;
480 std::vector<unsigned int> et;
481 std::vector<int> exErr;
482 std::vector<int> eyErr;
483 std::vector<int> etErr;
484 ModifySlices::data(sums->ExVec(), ex, timeslicesNew);
485 ModifySlices::data(sums->EyVec(), ey, timeslicesNew);
486 ModifySlices::data(sums->EtVec(), et, timeslicesNew);
487 ModifySlices::data(sums->ExErrorVec(), exErr, timeslicesNew);
488 ModifySlices::data(sums->EyErrorVec(), eyErr, timeslicesNew);
489 ModifySlices::data(sums->EtErrorVec(), etErr, timeslicesNew);
490 for (int slice = 0; slice < timeslicesNew; ++slice) {
491 const LVL1::DataError exErrBits(exErr[slice]);
492 const LVL1::DataError eyErrBits(eyErr[slice]);
493 const LVL1::DataError etErrBits(etErr[slice]);
494 int exError = exErrBits.get(LVL1::DataError::Parity) << 1;
495 int eyError = eyErrBits.get(LVL1::DataError::Parity) << 1;
496 int etError = etErrBits.get(LVL1::DataError::Parity) << 1;
497 if (source >= m_modules) {
498 exError += exErrBits.get(LVL1::DataError::Overflow);
499 eyError += eyErrBits.get(LVL1::DataError::Overflow);
500 etError += etErrBits.get(LVL1::DataError::Overflow);
501 }
502 const int index = ( neutralFormat ) ? 0 : slice;
503 CmxEnergySubBlock* const subBlock = cmxEnergyBlocks[index];
504 if (source < m_modules) {
505 subBlock->setSubsums(slice, source,
506 ex[slice], ey[slice], et[slice],
507 exError, eyError, etError);
508 } else {
512 energySubBlockTypes(source, srcType, sumType, hitType);
513 if (srcType != CmxEnergySubBlock::MAX_SOURCE_TYPE) {
514 subBlock->setSubsums(slice, srcType, sumType,
515 ex[slice], ey[slice], et[slice],
516 exError, eyError, etError);
517 } else if (hitType != CmxEnergySubBlock::MAX_HITS_TYPE) {
518 subBlock->setEtHits(slice, hitType, sumType, et[slice]);
519 }
520 }
521 }
522 }
523 }
525 pos = cmxEnergyBlocks.begin();
526 for (; pos != cmxEnergyBlocks.end(); ++pos) {
527 CmxEnergySubBlock* const subBlock = *pos;
528 if ( !subBlock->pack()) {
529 msg(MSG::ERROR) << "CMX-Energy sub-block packing failed" << endmsg;
530 return StatusCode::FAILURE;
531 }
532 if (debug) {
533 msg() << "CMX-Energy sub-block data words: "
534 << subBlock->dataWords() << endmsg;
535 }
536 subBlock->write(theROD);
537 }
538
539 // CMX-Jet TOBs
540
541 for (int jem = 0; jem < m_modules; ++jem) {
542 for (int frame = 0; frame < m_frames; ++frame) {
543 for (int loc = 0; loc < m_locations; ++loc) {
544 const int key = tobKey(crate, jem, frame, loc);
545 const LVL1::CMXJetTob* const ct = findCmxTob(key, cmxTobMap);
546 if ( ct ) {
547 std::vector<int> energyLarge;
548 std::vector<int> energySmall;
549 std::vector<int> error;
550 std::vector<unsigned int> presence;
551 ModifySlices::data(ct->energyLgVec(), energyLarge, timeslicesNew);
552 ModifySlices::data(ct->energySmVec(), energySmall, timeslicesNew);
553 ModifySlices::data(ct->errorVec(), error, timeslicesNew);
554 ModifySlices::data(ct->presenceMapVec(), presence, timeslicesNew);
555 for (int slice = 0; slice < timeslicesNew; ++slice) {
556 const LVL1::DataError errBits(error[slice]);
557 int err0 = errBits.get(LVL1::DataError::Parity);
558 int err1 = errBits.get(LVL1::DataError::ParityPhase0);
559 err1 |= (errBits.get(LVL1::DataError::ParityPhase1))<<1;
560 err1 |= (errBits.get(LVL1::DataError::ParityPhase2))<<2;
561 err1 |= (errBits.get(LVL1::DataError::ParityPhase3))<<3;
562 const int index = ( neutralFormat ) ? 0 : slice;
563 CmxJetSubBlock* const subBlock = cmxJetBlocks[index];
564 subBlock->setTob(slice, jem, frame, loc, energyLarge[slice],
565 energySmall[slice], err0);
566 subBlock->setParityBits(slice, jem, err1); // for neutral format
567 subBlock->setPresenceMap(slice, jem, presence[slice]);
568 }
569 }
570 }
571 }
572 }
573
574 // CMX-Jet Hits
575
576 maxSource = static_cast<int>(LVL1::CMXJetHits::MAX_SOURCE);
577 for (int source = 0; source < maxSource; ++source) {
578 if (summing == CmxSubBlock::CRATE &&
582 source == LVL1::CMXJetHits::TOTAL_FORWARD)) continue;
583 int sourceId = jetSubBlockSourceId(source);
584 if (sourceId == CmxJetSubBlock::MAX_SOURCE_ID) continue;
585 const LVL1::CMXJetHits* const ch = findCmxHits(crate, source, cmxHitsMap);
586 if ( ch ) {
587 std::vector<unsigned int> hits0;
588 std::vector<unsigned int> hits1;
589 std::vector<int> err0;
590 std::vector<int> err1;
591 ModifySlices::data(ch->hitsVec0(), hits0, timeslicesNew);
592 ModifySlices::data(ch->hitsVec1(), hits1, timeslicesNew);
593 ModifySlices::data(ch->errorVec0(), err0, timeslicesNew);
594 ModifySlices::data(ch->errorVec1(), err1, timeslicesNew);
595 for (int slice = 0; slice < timeslicesNew; ++slice) {
596 int error = 0;
597 if (source != LVL1::CMXJetHits::TOPO_CHECKSUM &&
600 const LVL1::DataError errBits0(err0[slice]);
601 const LVL1::DataError errBits1(err1[slice]);
602 error = (errBits0.get(LVL1::DataError::Overflow) |
603 errBits1.get(LVL1::DataError::Overflow)) << 2;
604 if (source == LVL1::CMXJetHits::REMOTE_MAIN ||
606 error += (errBits0.get(LVL1::DataError::Parity) +
607 (errBits1.get(LVL1::DataError::Parity) << 1));
608 }
609 }
610 const int index = ( neutralFormat ) ? 0 : slice;
611 CmxJetSubBlock* const subBlock = cmxJetBlocks[index];
612 subBlock->setHits(slice, sourceId, 0, hits0[slice], error);
613 if (source != LVL1::CMXJetHits::TOPO_CHECKSUM &&
615 subBlock->setHits(slice, sourceId, 1, hits1[slice], error);
616 }
617 }
618 }
619 }
621 jos = cmxJetBlocks.begin();
622 for (; jos != cmxJetBlocks.end(); ++jos) {
623 CmxJetSubBlock* const subBlock = *jos;
624 if ( !subBlock->pack()) {
625 msg(MSG::ERROR) << "CMX-Jet sub-block packing failed" << endmsg;
626 return StatusCode::FAILURE;
627 }
628 if (debug) {
629 msg() << "CMX-Jet sub-block data words: "
630 << subBlock->dataWords() << endmsg;
631 }
632 subBlock->write(theROD);
633 }
634 }
635
636 return StatusCode::SUCCESS;
637}
638
639// Return reference to vector with all possible Source Identifiers
640
641std::vector<uint32_t> JepByteStreamV2Tool::makeSourceIDs() const
642{
643 std::vector<uint32_t> sourceIDs;
644
645 if (!m_sourceIDsProp.empty()) {
647 }
648 else {
649 const int maxCrates = m_crates + m_crateOffsetHw;
650 const int maxSlinks = m_srcIdMap.maxSlinks();
651 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
652 {
653 for (int slink = 0; slink < maxSlinks; ++slink)
654 {
655 const int daqOrRoi = 0;
656 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
658 const uint32_t robId = m_srcIdMap.getRobID(rodId);
659 sourceIDs.push_back(robId);
660 }
661 }
662 }
663 return sourceIDs;
664}
665
666const std::vector<uint32_t>& JepByteStreamV2Tool::sourceIDs() const
667{
668 static const std::vector<uint32_t> sourceIDs = makeSourceIDs();
669 return sourceIDs;
670}
671
672// Convert bytestream to given container type
673
675 const std::string& sgKey,
676 const IROBDataProviderSvc::VROBFRAG& robFrags,
678{
679 LocalData ld;
680
681 // Check if overlap jet element channels wanted
682 const std::string flag("Overlap");
683 const std::string::size_type pos = sgKey.find(flag);
684 ld.coreOverlap =
685 (pos == std::string::npos || pos != sgKey.length() - flag.length()) ? 0 : 1;
686
687 const bool debug = msgLvl(MSG::DEBUG);
688 if (debug) msg(MSG::DEBUG);
689
690 // JemSubBlock for unpacking
691 JemSubBlockV2 jemSubBlock;
692 // CmxEnergySubBlock for unpacking
693 CmxEnergySubBlock cmxEnergySubBlock;
694 // CmxJetSubBlock for unpacking
695 CmxJetSubBlock cmxJetSubBlock;
696
697 // Loop over ROB fragments
698
699 int robCount = 0;
700 std::set<uint32_t> dupCheck;
701 ROBIterator rob = robFrags.begin();
702 ROBIterator robEnd = robFrags.end();
703 for (; rob != robEnd; ++rob) {
704
705 if (debug) {
706 ++robCount;
707 msg() << "Treating ROB fragment " << robCount << endmsg;
708 }
709
710 // Skip fragments with ROB status errors
711
712 uint32_t robid = (*rob)->source_id();
713 if ((*rob)->nstatus() > 0) {
714 ROBPointer robData;
715 (*rob)->status(robData);
716 if (*robData != 0) {
717 m_errorTool->robError(robid, *robData);
718 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
719 continue;
720 }
721 }
722
723 // Skip duplicate fragments
724
725 if (!dupCheck.insert(robid).second) {
727 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
728 continue;
729 }
730
731 // Unpack ROD data (slinks)
732
733 RODPointer payloadBeg;
734 RODPointer payload;
735 RODPointer payloadEnd;
736 (*rob)->rod_data(payloadBeg);
737 payloadEnd = payloadBeg + (*rob)->rod_ndata();
738 payload = payloadBeg;
739 if (payload == payloadEnd) {
740 if (debug) msg() << "ROB fragment empty" << endmsg;
741 continue;
742 }
743
744 // Check identifier
745 const uint32_t sourceID = (*rob)->rod_source_id();
746 if (m_srcIdMap.getRobID(sourceID) != robid ||
747 m_srcIdMap.subDet(sourceID) != m_subDetector ||
748 m_srcIdMap.daqOrRoi(sourceID) != 0 ||
749 m_srcIdMap.slink(sourceID) >= m_slinks ||
750 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
751 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates) {
753 if (debug) {
754 msg() << "Wrong source identifier in data: ROD "
755 << MSG::hex << sourceID << " ROB " << robid
756 << MSG::dec << endmsg;
757 }
758 continue;
759 }
760
761 // Check minor version
762 const int minorVersion = (*rob)->rod_version() & 0xffff;
763 if (minorVersion <= m_srcIdMap.minorVersionPreLS1()) {
764 if (debug) msg() << "Skipping pre-LS1 data" << endmsg;
765 continue;
766 }
767 const int rodCrate = m_srcIdMap.crate(sourceID);
768 if (debug) {
769 msg() << "Treating crate " << rodCrate
770 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
771 }
772
773 // First word should be User Header
774 if ( !L1CaloUserHeader::isValid(*payload) ) {
776 if (debug) msg() << "Invalid or missing user header" << endmsg;
777 continue;
778 }
779 L1CaloUserHeader userHeader(*payload);
780 userHeader.setVersion(minorVersion);
781 const int headerWords = userHeader.words();
782 if (headerWords != 1) {
784 if (debug) msg() << "Unexpected number of user header words: "
785 << headerWords << endmsg;
786 continue;
787 }
788 for (int i = 0; i < headerWords; ++i) ++payload;
789 // triggered slice offsets
790 int trigJem = userHeader.jem();
791 if (debug) {
792 msg() << "Minor format version number: " << MSG::hex
793 << minorVersion << MSG::dec << endmsg
794 << "JEM triggered slice offset: " << trigJem << endmsg;
795 }
796
797 // Loop over sub-blocks
798
799 ld.rodErr = L1CaloSubBlock::ERROR_NONE;
800 while (payload != payloadEnd) {
801
803 if (debug) msg() << "Unexpected data sequence" << endmsg;
805 break;
806 }
807 if (CmxSubBlock::cmxBlock(*payload)) {
808 // CMXs
810 cmxJetSubBlock.clear();
811 payload = cmxJetSubBlock.read(payload, payloadEnd);
812 if (cmxJetSubBlock.crate() != rodCrate) {
813 if (debug) msg() << "Inconsistent crate number in ROD source ID"
814 << endmsg;
816 break;
817 }
818 if (data.m_collection == CMX_HITS || data.m_collection == CMX_TOBS) {
819 decodeCmxJet(&cmxJetSubBlock, trigJem, data, ld);
820 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {
821 if (debug) msg() << "decodeCmxJet failed" << endmsg;
822 break;
823 }
824 }
825 } else if (CmxSubBlock::cmxType(*payload) == CmxSubBlock::CMX_ENERGY) {
826 cmxEnergySubBlock.clear();
827 payload = cmxEnergySubBlock.read(payload, payloadEnd);
828 if (cmxEnergySubBlock.crate() != rodCrate) {
829 if (debug) msg() << "Inconsistent crate number in ROD source ID"
830 << endmsg;
832 break;
833 }
834 if (data.m_collection == CMX_SUMS) {
835 decodeCmxEnergy(&cmxEnergySubBlock, trigJem, static_cast<CmxSumsData&>(data), ld);
836 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {
837 if (debug) msg() << "decodeCmxEnergy failed" << endmsg;
838 break;
839 }
840 }
841 } else {
842 if (debug) msg() << "Invalid CMX type in module field" << endmsg;
844 break;
845 }
846 } else {
847 // JEM
848 jemSubBlock.clear();
849 payload = jemSubBlock.read(payload, payloadEnd);
850 if (jemSubBlock.crate() != rodCrate) {
851 if (debug) msg() << "Inconsistent crate number in ROD source ID"
852 << endmsg;
854 break;
855 }
856 if (data.m_collection == JET_ELEMENTS || data.m_collection == ENERGY_SUMS) {
857 decodeJem(&jemSubBlock, trigJem, data, ld);
858 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {
859 if (debug) msg() << "decodeJem failed" << endmsg;
860 break;
861 }
862 }
863 }
864 }
865 if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
866 m_errorTool->rodError(robid, ld.rodErr);
867 }
868
869 return StatusCode::SUCCESS;
870}
871
872// Unpack CMX-Energy sub-block
873
875 int trigJem,
877 LocalData& ld) const
878{
879 const bool debug = msgLvl(MSG::DEBUG);
880 if (debug) msg(MSG::DEBUG);
881
882 const int hwCrate = subBlock->crate();
883 const int module = subBlock->cmxPosition();
884 const int firmware = subBlock->cmxFirmware();
885 const int summing = subBlock->cmxSumming();
886 const int timeslices = subBlock->timeslices();
887 const int sliceNum = subBlock->slice();
888 if (debug) {
889 msg() << "CMX-Energy: Crate " << hwCrate
890 << " Module " << module
891 << " Firmware " << firmware
892 << " Summing " << summing
893 << " Total slices " << timeslices
894 << " Slice " << sliceNum << endmsg;
895 }
896 if (timeslices <= trigJem) {
897 if (debug) msg() << "Triggered CMX slice from header "
898 << "inconsistent with number of slices: "
899 << trigJem << ", " << timeslices << endmsg;
901 return;
902 }
903 if (timeslices <= sliceNum) {
904 if (debug) msg() << "Total slices inconsistent with slice number: "
905 << timeslices << ", " << sliceNum << endmsg;
907 return;
908 }
909 // Unpack sub-block
910 if (subBlock->dataWords() && !subBlock->unpack()) {
911 if (debug) {
912 std::string errMsg(subBlock->unpackErrorMsg());
913 msg() << "CMX-Energy sub-block unpacking failed: " << errMsg << endmsg;
914 }
915 ld.rodErr = subBlock->unpackErrorCode();
916 return;
917 }
918
919 // Retrieve required data
920
921 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
922 const int crate = hwCrate - m_crateOffsetHw;
923 const int swCrate = crate + m_crateOffsetSw;
924 const int maxSource = static_cast<int>(LVL1::CMXEtSums::MAX_SOURCE);
925 std::vector<unsigned int>& exVec(ld.uintVec0);
926 std::vector<unsigned int>& eyVec(ld.uintVec1);
927 std::vector<unsigned int>& etVec(ld.uintVec2);
928 std::vector<int>& exErrVec(ld.intVec0);
929 std::vector<int>& eyErrVec(ld.intVec1);
930 std::vector<int>& etErrVec(ld.intVec2);
931 LVL1::DataError derr;
933 const int ssError = derr.error();
934 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
935 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
936 for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
937
938 // Energy sums
939
940 for (int source = 0; source < maxSource; ++source) {
941 if (source >= m_modules && summing == CmxSubBlock::CRATE &&
943 source != LVL1::CMXEtSums::LOCAL_RESTRICTED) continue;
944 unsigned int ex = 0;
945 unsigned int ey = 0;
946 unsigned int et = 0;
947 int exErr = 0;
948 int eyErr = 0;
949 int etErr = 0;
950 LVL1::DataError exErrBits(ssError);
951 LVL1::DataError eyErrBits(ssError);
952 LVL1::DataError etErrBits(ssError);
953 if (source < m_modules) {
954 ex = subBlock->energy(slice, source, CmxEnergySubBlock::ENERGY_EX);
955 ey = subBlock->energy(slice, source, CmxEnergySubBlock::ENERGY_EY);
956 et = subBlock->energy(slice, source, CmxEnergySubBlock::ENERGY_ET);
957 exErr = subBlock->error(slice, source, CmxEnergySubBlock::ENERGY_EX);
958 eyErr = subBlock->error(slice, source, CmxEnergySubBlock::ENERGY_EY);
959 etErr = subBlock->error(slice, source, CmxEnergySubBlock::ENERGY_ET);
960 exErrBits.set(LVL1::DataError::Parity, exErr >> 1);
961 eyErrBits.set(LVL1::DataError::Parity, eyErr >> 1);
962 etErrBits.set(LVL1::DataError::Parity, etErr >> 1);
963 } else {
967 energySubBlockTypes(source, srcType, sumType, hitType);
968 if (srcType != CmxEnergySubBlock::MAX_SOURCE_TYPE) {
969 ex = subBlock->energy(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_EX);
970 ey = subBlock->energy(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_EY);
971 et = subBlock->energy(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_ET);
972 exErr = subBlock->error(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_EX);
973 eyErr = subBlock->error(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_EY);
974 etErr = subBlock->error(slice, srcType, sumType, CmxEnergySubBlock::ENERGY_ET);
975 exErrBits.set(LVL1::DataError::Overflow, exErr);
976 eyErrBits.set(LVL1::DataError::Overflow, eyErr);
977 etErrBits.set(LVL1::DataError::Overflow, etErr);
978 if (srcType == CmxEnergySubBlock::REMOTE) {
979 exErrBits.set(LVL1::DataError::Parity, exErr >> 1);
980 eyErrBits.set(LVL1::DataError::Parity, eyErr >> 1);
981 etErrBits.set(LVL1::DataError::Parity, etErr >> 1);
982 }
983 } else if (hitType != CmxEnergySubBlock::MAX_HITS_TYPE) {
984 ex = subBlock->hits(slice, hitType, sumType);
985 ey = ex;
986 et = ex;
987 }
988 }
989 exErr = exErrBits.error();
990 eyErr = eyErrBits.error();
991 etErr = etErrBits.error();
992 if (ex || ey || et || exErr || eyErr || etErr) {
993 LVL1::CMXEtSums* sums = findCmxSums(data, crate, source);
994 if ( ! sums ) { // create new CMX energy sums
995 exVec.assign(timeslices, 0);
996 eyVec.assign(timeslices, 0);
997 etVec.assign(timeslices, 0);
998 exErrVec.assign(timeslices, 0);
999 eyErrVec.assign(timeslices, 0);
1000 etErrVec.assign(timeslices, 0);
1001 exVec[slice] = ex;
1002 eyVec[slice] = ey;
1003 etVec[slice] = et;
1004 exErrVec[slice] = exErr;
1005 eyErrVec[slice] = eyErr;
1006 etErrVec[slice] = etErr;
1007 auto sumsp =
1008 std::make_unique<LVL1::CMXEtSums>(swCrate, source, etVec, exVec, eyVec,
1009 etErrVec, exErrVec, eyErrVec, trigJem);
1010 const int key = crate*100 + source;
1011 data.m_cmxEtMap.insert(std::make_pair(key, sumsp.get()));
1012 data.m_cmxEtCollection->push_back(std::move(sumsp));
1013 } else {
1014 exVec = sums->ExVec();
1015 eyVec = sums->EyVec();
1016 etVec = sums->EtVec();
1017 exErrVec = sums->ExErrorVec();
1018 eyErrVec = sums->EyErrorVec();
1019 etErrVec = sums->EtErrorVec();
1020 const int nsl = exVec.size();
1021 if (timeslices != nsl) {
1022 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
1023 << endmsg;
1024 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1025 return;
1026 }
1027 if (exVec[slice] != 0 || eyVec[slice] != 0 || etVec[slice] != 0 ||
1028 exErrVec[slice] != 0 || eyErrVec[slice] != 0 ||
1029 etErrVec[slice] != 0) {
1030 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
1032 return;
1033 }
1034 exVec[slice] = ex;
1035 eyVec[slice] = ey;
1036 etVec[slice] = et;
1037 exErrVec[slice] = exErr;
1038 eyErrVec[slice] = eyErr;
1039 etErrVec[slice] = etErr;
1040 sums->addEx(exVec, exErrVec);
1041 sums->addEy(eyVec, eyErrVec);
1042 sums->addEt(etVec, etErrVec);
1043 }
1044 }
1045 }
1046 }
1047
1048 return;
1049}
1050
1051// Unpack CMX-Jet sub-block
1052
1055 LocalData& ld) const
1056{
1057 const bool debug = msgLvl(MSG::DEBUG);
1058 if (debug) msg(MSG::DEBUG);
1059
1060 const int hwCrate = subBlock->crate();
1061 const int module = subBlock->cmxPosition();
1062 const int firmware = subBlock->cmxFirmware();
1063 const int summing = subBlock->cmxSumming();
1064 const int timeslices = subBlock->timeslices();
1065 const int sliceNum = subBlock->slice();
1066 if (debug) {
1067 msg() << "CMX-Jet: Crate " << hwCrate
1068 << " Module " << module
1069 << " Firmware " << firmware
1070 << " Summing " << summing
1071 << " Total slices " << timeslices
1072 << " Slice " << sliceNum << endmsg;
1073 }
1074 if (timeslices <= trigJem) {
1075 if (debug) msg() << "Triggered CMX slice from header "
1076 << "inconsistent with number of slices: "
1077 << trigJem << ", " << timeslices << endmsg;
1078 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1079 return;
1080 }
1081 if (timeslices <= sliceNum) {
1082 if (debug) msg() << "Total slices inconsistent with slice number: "
1083 << timeslices << ", " << sliceNum << endmsg;
1084 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1085 return;
1086 }
1087 // Unpack sub-block
1088 if (subBlock->dataWords() && !subBlock->unpack()) {
1089 if (debug) {
1090 std::string errMsg(subBlock->unpackErrorMsg());
1091 msg() << "CMX-Jet sub-block unpacking failed: " << errMsg << endmsg;
1092 }
1093 ld.rodErr = subBlock->unpackErrorCode();
1094 return;
1095 }
1096
1097 // Retrieve required data
1098
1099 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
1100 const int crate = hwCrate - m_crateOffsetHw;
1101 const int swCrate = crate + m_crateOffsetSw;
1102 const int maxSource = static_cast<int>(LVL1::CMXJetHits::MAX_SOURCE);
1103 std::vector<int>& energyLgVec(ld.intVec0);
1104 std::vector<int>& energySmVec(ld.intVec1);
1105 std::vector<int>& errorVec(ld.intVec2);
1106 std::vector<unsigned int>& presenceMapVec(ld.uintVec0);
1107 std::vector<unsigned int>& hit0Vec(ld.uintVec0);
1108 std::vector<unsigned int>& hit1Vec(ld.uintVec1);
1109 std::vector<int>& err0Vec(ld.intVec0);
1110 std::vector<int>& err1Vec(ld.intVec1);
1111 LVL1::DataError derr;
1112 derr.set(LVL1::DataError::SubStatusWord, subBlock->subStatus());
1113 const int ssError = derr.error();
1114 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
1115 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
1116 for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
1117
1118 // Jet TOBs
1119
1120 if (data.m_collection == CMX_TOBS) {
1121 CmxTobData& tdata = static_cast<CmxTobData&> (data);
1122
1123 for (int jem = 0; jem < m_modules; ++jem) {
1124 const unsigned int presenceMap = subBlock->presenceMap(slice, jem);
1125 for (int tob = 0; tob < m_maxTobs; ++tob) {
1126 const int energyLarge = subBlock->energyLarge(slice, jem, tob);
1127 const int energySmall = subBlock->energySmall(slice, jem, tob);
1128 int error = subBlock->tobError(slice, jem, tob);
1129 if (energyLarge == 0 && energySmall == 0 && error == 0) break;
1130 const int loc = subBlock->localCoord(slice, jem, tob);
1131 const int frame = subBlock->frame(slice, jem, tob);
1132 LVL1::DataError errBits(ssError);
1133 if (error) {
1135 if (neutralFormat) {
1136 const int parity = subBlock->parityBits(slice, jem);
1137 errBits.set(LVL1::DataError::ParityPhase0, parity);
1138 errBits.set(LVL1::DataError::ParityPhase1, (parity>>1));
1139 errBits.set(LVL1::DataError::ParityPhase2, (parity>>2));
1140 errBits.set(LVL1::DataError::ParityPhase3, (parity>>3));
1141 }
1142 }
1143 error = errBits.error();
1144 const int key = tobKey(crate, jem, frame, loc);
1145 LVL1::CMXJetTob* tb = findCmxTob(tdata, key);
1146 if ( ! tb ) { // create new CMX TOB
1147 energyLgVec.assign(timeslices, 0);
1148 energySmVec.assign(timeslices, 0);
1149 errorVec.assign(timeslices, 0);
1150 presenceMapVec.assign(timeslices, 0);
1151 energyLgVec[slice] = energyLarge;
1152 energySmVec[slice] = energySmall;
1153 errorVec[slice] = error;
1154 presenceMapVec[slice] = presenceMap;
1155 auto tbp =
1156 std::make_unique<LVL1::CMXJetTob>(swCrate, jem, frame, loc,
1157 energyLgVec, energySmVec, errorVec,
1158 presenceMapVec, trigJem);
1159 tdata.m_cmxTobMap.insert(std::make_pair(key, tbp.get()));
1160 tdata.m_cmxTobCollection->push_back(std::move(tbp));
1161 } else {
1162 energyLgVec = tb->energyLgVec();
1163 energySmVec = tb->energySmVec();
1164 errorVec = tb->errorVec();
1165 presenceMapVec = tb->presenceMapVec();
1166 const int nsl = energyLgVec.size();
1167 if (timeslices != nsl) {
1168 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
1169 << endmsg;
1170 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1171 return;
1172 }
1173 if (energyLgVec[slice] != 0 || energySmVec[slice] != 0 ||
1174 errorVec[slice] != 0 || presenceMapVec[slice] != 0) {
1175 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
1177 return;
1178 }
1179 energyLgVec[slice] = energyLarge;
1180 energySmVec[slice] = energySmall;
1181 errorVec[slice] = error;
1182 presenceMapVec[slice] = presenceMap;
1183 tb->addTob(energyLgVec, energySmVec, errorVec, presenceMapVec);
1184 }
1185 }
1186 }
1187 }
1188
1189 // Jet hit counts and topo info
1190
1191 else if (data.m_collection == CMX_HITS) {
1192 CmxHitsData& hdata = static_cast<CmxHitsData&> (data);
1193
1194 for (int source = 0; source < maxSource; ++source) {
1195 if (summing == CmxSubBlock::CRATE &&
1196 (source == LVL1::CMXJetHits::REMOTE_MAIN ||
1197 source == LVL1::CMXJetHits::TOTAL_MAIN ||
1199 source == LVL1::CMXJetHits::TOTAL_FORWARD)) continue;
1200 int sourceId = jetSubBlockSourceId(source);
1201 if (sourceId == CmxJetSubBlock::MAX_SOURCE_ID) continue;
1202 const unsigned int hit0 = subBlock->hits(slice, sourceId, 0);
1203 const unsigned int hit1 = subBlock->hits(slice, sourceId, 1);
1204 int err0 = subBlock->hitsError(slice, sourceId, 0);
1205 int err1 = subBlock->hitsError(slice, sourceId, 1);
1206 LVL1::DataError err0Bits(ssError);
1207 LVL1::DataError err1Bits(ssError);
1208 err0Bits.set(LVL1::DataError::Parity, err0);
1209 err1Bits.set(LVL1::DataError::Parity, err1>>1);
1210 err0Bits.set(LVL1::DataError::Overflow, err0>>2);
1211 err1Bits.set(LVL1::DataError::Overflow, err1>>2);
1212 err0 = err0Bits.error();
1213 err1 = err1Bits.error();
1214 if (hit0 || hit1 || err0 || err1) {
1215 LVL1::CMXJetHits* jh = findCmxHits(hdata, crate, source);
1216 if ( ! jh ) { // create new CMX hits
1217 hit0Vec.assign(timeslices, 0);
1218 hit1Vec.assign(timeslices, 0);
1219 err0Vec.assign(timeslices, 0);
1220 err1Vec.assign(timeslices, 0);
1221 hit0Vec[slice] = hit0;
1222 hit1Vec[slice] = hit1;
1223 err0Vec[slice] = err0;
1224 err1Vec[slice] = err1;
1225 auto jhp =
1226 std::make_unique<LVL1::CMXJetHits>(swCrate, source, hit0Vec, hit1Vec,
1227 err0Vec, err1Vec, trigJem);
1228 const int key = crate*100 + source;
1229 hdata.m_cmxHitsMap.insert(std::make_pair(key, jhp.get()));
1230 hdata.m_cmxHitCollection->push_back(std::move(jhp));
1231 } else {
1232 hit0Vec = jh->hitsVec0();
1233 hit1Vec = jh->hitsVec1();
1234 err0Vec = jh->errorVec0();
1235 err1Vec = jh->errorVec1();
1236 const int nsl = hit0Vec.size();
1237 if (timeslices != nsl) {
1238 if (debug) msg() << "Inconsistent number of slices in sub-blocks"
1239 << endmsg;
1240 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1241 return;
1242 }
1243 if (hit0Vec[slice] != 0 || hit1Vec[slice] != 0 ||
1244 err0Vec[slice] != 0 || err1Vec[slice] != 0) {
1245 if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
1247 return;
1248 }
1249 hit0Vec[slice] = hit0;
1250 hit1Vec[slice] = hit1;
1251 err0Vec[slice] = err0;
1252 err1Vec[slice] = err1;
1253 jh->addHits(hit0Vec, hit1Vec, err0Vec, err1Vec);
1254 }
1255 }
1256 }
1257 }
1258 }
1259
1260 return;
1261}
1262
1263// Unpack JEM sub-block
1264
1267 LocalData& ld) const
1268{
1269 const bool debug = msgLvl(MSG::DEBUG);
1270 const bool verbose = msgLvl(MSG::VERBOSE);
1271 if (debug) msg(MSG::DEBUG);
1272
1273 const int hwCrate = subBlock->crate();
1274 const int module = subBlock->module();
1275 const int timeslices = subBlock->timeslices();
1276 const int sliceNum = subBlock->slice();
1277 if (debug) {
1278 msg() << "JEM: Crate " << hwCrate
1279 << " Module " << module
1280 << " Total slices " << timeslices
1281 << " Slice " << sliceNum << endmsg;
1282 }
1283 if (timeslices <= trigJem) {
1284 if (debug) msg() << "Triggered JEM slice from header "
1285 << "inconsistent with number of slices: "
1286 << trigJem << ", " << timeslices << endmsg;
1287 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1288 return;
1289 }
1290 if (timeslices <= sliceNum) {
1291 if (debug) msg() << "Total slices inconsistent with slice number: "
1292 << timeslices << ", " << sliceNum << endmsg;
1293 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1294 return;
1295 }
1296 // Unpack sub-block
1297 if (subBlock->dataWords() && !subBlock->unpack()) {
1298 if (debug) {
1299 std::string errMsg(subBlock->unpackErrorMsg());
1300 msg() << "JEM sub-block unpacking failed: " << errMsg << endmsg;
1301 }
1302 ld.rodErr = subBlock->unpackErrorCode();
1303 return;
1304 }
1305
1306 // Retrieve required data
1307
1308 const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
1309 const int crate = hwCrate - m_crateOffsetHw;
1310 const int swCrate = crate + m_crateOffsetSw;
1311 std::vector<unsigned int>& exVec(ld.uintVec0);
1312 std::vector<unsigned int>& eyVec(ld.uintVec1);
1313 std::vector<unsigned int>& etVec(ld.uintVec2);
1314 LVL1::DataError derr;
1315 derr.set(LVL1::DataError::SubStatusWord, subBlock->subStatus());
1316 const int ssError = derr.error();
1317 std::vector<int> dummy(timeslices);
1318 const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
1319 const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
1320 for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
1321
1322 if (data.m_collection == JET_ELEMENTS) {
1323 JetElementData& jedata = static_cast<JetElementData&> (data);
1324
1325 // Loop over jet element channels and fill jet elements
1326
1327 for (int chan = 0; chan < m_channels; ++chan) {
1328 const JemJetElement jetEle(subBlock->jetElement(slice, chan));
1329 if (jetEle.data() || ssError) {
1330 double eta = 0.;
1331 double phi = 0.;
1332 int layer = 0;
1333 if (m_jemMaps->mapping(crate, module, chan, eta, phi, layer)) {
1334 if (layer == ld.coreOverlap) {
1335 LVL1::JetElement* je = findJetElement(jedata, eta, phi,
1336 ld.elementKey);
1337 if ( ! je ) { // create new jet element
1338 const unsigned int key = ld.elementKey.jeKey(phi, eta);
1339 auto jep =
1340 std::make_unique<LVL1::JetElement>(phi, eta, dummy, dummy, key,
1341 dummy, dummy, dummy, trigJem);
1342 je = jep.get();
1343 jedata.m_jeMap.insert(std::make_pair(key, jep.get()));
1344 jedata.m_jeCollection->push_back(std::move(jep));
1345 } else {
1346 const std::vector<int>& emEnergy(je->emEnergyVec());
1347 const std::vector<int>& hadEnergy(je->hadEnergyVec());
1348 const std::vector<int>& emError(je->emErrorVec());
1349 const std::vector<int>& hadError(je->hadErrorVec());
1350 const int nsl = emEnergy.size();
1351 if (timeslices != nsl) {
1352 if (debug) {
1353 msg() << "Inconsistent number of slices in sub-blocks"
1354 << endmsg;
1355 }
1356 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1357 return;
1358 }
1359 if (emEnergy[slice] != 0 || hadEnergy[slice] != 0 ||
1360 emError[slice] != 0 || hadError[slice] != 0) {
1361 if (debug) msg() << "Duplicate data for slice "
1362 << slice << endmsg;
1364 return;
1365 }
1366 }
1367 LVL1::DataError emErrBits(ssError);
1368 LVL1::DataError hadErrBits(ssError);
1369 const int linkError = jetEle.linkError();
1370 emErrBits.set(LVL1::DataError::Parity, jetEle.emParity());
1371 emErrBits.set(LVL1::DataError::LinkDown, linkError);
1372 hadErrBits.set(LVL1::DataError::Parity, jetEle.hadParity());
1373 hadErrBits.set(LVL1::DataError::LinkDown, linkError >> 1);
1374 je->addSlice(slice, jetEle.emData(), jetEle.hadData(),
1375 emErrBits.error(), hadErrBits.error(),
1376 linkError);
1377 }
1378 } else if (verbose && jetEle.data()) {
1379 msg(MSG::VERBOSE) << "Non-zero data but no channel mapping for channel "
1380 << chan << endmsg;
1381 msg(MSG::DEBUG);
1382 }
1383 } else if (verbose) {
1384 msg(MSG::VERBOSE) << "No jet element data for channel "
1385 << chan << " slice " << slice << endmsg;
1386 msg(MSG::DEBUG);
1387 }
1388 }
1389 } else if (data.m_collection == ENERGY_SUMS) {
1390 EnergySumsData& sumdata = static_cast<EnergySumsData&> (data);
1391
1392 // Get energy subsums
1393
1394 const unsigned int ex = subBlock->ex(slice);
1395 const unsigned int ey = subBlock->ey(slice);
1396 const unsigned int et = subBlock->et(slice);
1397 if (ex | ey | et) {
1398 LVL1::JEMEtSums* sums = findEnergySums(sumdata, crate, module);
1399 if ( ! sums ) { // create new energy sums
1400 exVec.assign(timeslices, 0);
1401 eyVec.assign(timeslices, 0);
1402 etVec.assign(timeslices, 0);
1403 exVec[slice] = ex;
1404 eyVec[slice] = ey;
1405 etVec[slice] = et;
1406 auto sumsp =
1407 std::make_unique<LVL1::JEMEtSums>(swCrate, module, etVec, exVec, eyVec,
1408 trigJem);
1409 sumdata.m_etMap.insert(std::make_pair(crate*m_modules+module, sumsp.get()));
1410 sumdata.m_etCollection->push_back(std::move(sumsp));
1411 } else {
1412 exVec = sums->ExVec();
1413 eyVec = sums->EyVec();
1414 etVec = sums->EtVec();
1415 const int nsl = exVec.size();
1416 if (timeslices != nsl) {
1417 if (debug) {
1418 msg() << "Inconsistent number of slices in sub-blocks"
1419 << endmsg;
1420 }
1421 ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
1422 return;
1423 }
1424 if (exVec[slice] != 0 || eyVec[slice] != 0 || etVec[slice] != 0) {
1425 if (debug) msg() << "Duplicate data for slice "
1426 << slice << endmsg;
1428 return;
1429 }
1430 exVec[slice] = ex;
1431 eyVec[slice] = ey;
1432 etVec[slice] = et;
1433 sums->addEx(exVec);
1434 sums->addEy(eyVec);
1435 sums->addEt(etVec);
1436 }
1437 } else if (verbose) {
1438 msg(MSG::VERBOSE) << "No energy sums data for crate/module/slice "
1439 << hwCrate << "/" << module << "/" << slice
1440 << endmsg;
1441 msg(MSG::DEBUG);
1442 }
1443 }
1444 }
1445 return;
1446}
1447
1448// Find TOB map key for given crate, jem, frame, loc
1449
1450int JepByteStreamV2Tool::tobKey(const int crate, const int jem,
1451 const int frame, const int loc) const
1452{
1453 return ((((((crate<<4)+jem)<<3)+frame)<<2)+loc);
1454}
1455
1456// Find a jet element given eta, phi
1457
1458const
1460 const double phi,
1461 const ConstJetElementMap& jeMap,
1462 LVL1::JetElementKey& elementKey) const
1463{
1464 const unsigned int key = elementKey.jeKey(phi, eta);
1465 ConstJetElementMap::const_iterator mapIter = jeMap.find(key);
1466 if (mapIter != jeMap.end()) return mapIter->second;
1467 return nullptr;
1468}
1469
1471 const double eta,
1472 const double phi,
1473 LVL1::JetElementKey& elementKey) const
1474{
1475 const unsigned int key = elementKey.jeKey(phi, eta);
1476 JetElementMap::const_iterator mapIter = data.m_jeMap.find(key);
1477 if (mapIter != data.m_jeMap.end()) return mapIter->second;
1478 return nullptr;
1479}
1480
1481// Find energy sums for given crate, module
1482
1483const
1485 const int module,
1486 const ConstEnergySumsMap& etMap) const
1487{
1488 ConstEnergySumsMap::const_iterator mapIter = etMap.find(crate*m_modules + module);
1489 if (mapIter != etMap.end()) return mapIter->second;
1490 return nullptr;
1491}
1492
1494 const int crate,
1495 const int module) const
1496{
1497 EnergySumsMap::const_iterator mapIter = data.m_etMap.find(crate*m_modules + module);
1498 if (mapIter != data.m_etMap.end()) return mapIter->second;
1499 return nullptr;
1500}
1501
1502// Find CMX TOB for given crate, jem, frame, loc
1503
1504const
1506 const ConstCmxTobMap& cmxTobMap) const
1507{
1508 ConstCmxTobMap::const_iterator mapIter = cmxTobMap.find(key);
1509 if (mapIter != cmxTobMap.end()) return mapIter->second;
1510 return nullptr;
1511}
1512
1514 const int key) const
1515{
1516 CmxTobMap::const_iterator mapIter = data.m_cmxTobMap.find(key);
1517 if (mapIter != data.m_cmxTobMap.end()) return mapIter->second;
1518 return nullptr;
1519}
1520
1521// Find CMX hits for given crate, source
1522
1523const
1525 const int source,
1526 const ConstCmxHitsMap& cmxHitsMap) const
1527{
1528 ConstCmxHitsMap::const_iterator mapIter = cmxHitsMap.find(crate*100 + source);
1529 if (mapIter != cmxHitsMap.end()) return mapIter->second;
1530 return nullptr;
1531}
1532
1534 const int crate,
1535 const int source) const
1536{
1537 CmxHitsMap::const_iterator mapIter = data.m_cmxHitsMap.find(crate*100 + source);
1538 if (mapIter != data.m_cmxHitsMap.end()) return mapIter->second;
1539 return nullptr;
1540}
1541
1542// Find CMX energy sums for given crate, module, source
1543
1544const
1546 const int source,
1547 const ConstCmxSumsMap& cmxEtMap) const
1548{
1549 ConstCmxSumsMap::const_iterator mapIter = cmxEtMap.find(crate*100 + source);
1550 if (mapIter != cmxEtMap.end()) return mapIter->second;
1551 return nullptr;
1552}
1553
1555 const int crate,
1556 const int source) const
1557{
1558 CmxSumsMap::const_iterator mapIter = data.m_cmxEtMap.find(crate*100 + source);
1559 if (mapIter != data.m_cmxEtMap.end()) return mapIter->second;
1560 return nullptr;
1561}
1562
1563// Set up jet element map
1564
1566 const jeCollection,
1567 ConstJetElementMap& jeMap,
1568 LVL1::JetElementKey& elementKey) const
1569{
1570 jeMap.clear();
1571 if (jeCollection) {
1572 JetElementCollection::const_iterator pos = jeCollection->begin();
1573 JetElementCollection::const_iterator pose = jeCollection->end();
1574 for (; pos != pose; ++pos) {
1575 const LVL1::JetElement* const je = *pos;
1576 const unsigned int key = elementKey.jeKey(je->phi(), je->eta());
1577 jeMap.insert(std::make_pair(key, je));
1578 }
1579 }
1580}
1581
1582// Set up energy sums map
1583
1585 const etCollection,
1586 ConstEnergySumsMap& etMap) const
1587{
1588 etMap.clear();
1589 if (etCollection) {
1590 EnergySumsCollection::const_iterator pos = etCollection->begin();
1591 EnergySumsCollection::const_iterator pose = etCollection->end();
1592 for (; pos != pose; ++pos) {
1593 const LVL1::JEMEtSums* const sums = *pos;
1594 const int crate = sums->crate() - m_crateOffsetSw;
1595 const int key = m_modules * crate + sums->module();
1596 etMap.insert(std::make_pair(key, sums));
1597 }
1598 }
1599}
1600
1601// Set up CMX TOB map
1602
1604 const tobCollection,
1605 ConstCmxTobMap& cmxTobMap) const
1606{
1607 cmxTobMap.clear();
1608 if (tobCollection) {
1609 CmxTobCollection::const_iterator pos = tobCollection->begin();
1610 CmxTobCollection::const_iterator pose = tobCollection->end();
1611 for (; pos != pose; ++pos) {
1612 const LVL1::CMXJetTob* const tob = *pos;
1613 const int crate = tob->crate() - m_crateOffsetSw;
1614 const int jem = tob->jem();
1615 const int frame = tob->frame();
1616 const int loc = tob->location();
1617 const int key = tobKey(crate, jem, frame, loc);
1618 cmxTobMap.insert(std::make_pair(key, tob));
1619 }
1620 }
1621}
1622
1623// Set up CMX hits map
1624
1626 const hitCollection,
1627 ConstCmxHitsMap& cmxHitsMap) const
1628{
1629 cmxHitsMap.clear();
1630 if (hitCollection) {
1631 CmxHitsCollection::const_iterator pos = hitCollection->begin();
1632 CmxHitsCollection::const_iterator pose = hitCollection->end();
1633 for (; pos != pose; ++pos) {
1634 const LVL1::CMXJetHits* const hits = *pos;
1635 const int crate = hits->crate() - m_crateOffsetSw;
1636 const int key = crate*100 + hits->source();
1637 cmxHitsMap.insert(std::make_pair(key, hits));
1638 }
1639 }
1640}
1641
1642// Set up CMX energy sums map
1643
1645 const etCollection,
1646 ConstCmxSumsMap& cmxEtMap) const
1647{
1648 cmxEtMap.clear();
1649 if (etCollection) {
1650 CmxSumsCollection::const_iterator pos = etCollection->begin();
1651 CmxSumsCollection::const_iterator pose = etCollection->end();
1652 for (; pos != pose; ++pos) {
1653 const LVL1::CMXEtSums* const sums = *pos;
1654 const int crate = sums->crate() - m_crateOffsetSw;
1655 const int key = crate*100 + sums->source();
1656 cmxEtMap.insert(std::make_pair(key, sums));
1657 }
1658 }
1659}
1660
1661// Get number of slices and triggered slice offset for next slink
1662
1663bool JepByteStreamV2Tool::slinkSlices(const int crate, const int module,
1664 const int modulesPerSlink,
1665 int& timeslices,
1666 int& trigJem,
1667 const ConstJetElementMap& jeMap,
1668 const ConstEnergySumsMap& etMap,
1669 const ConstCmxTobMap& cmxTobMap,
1670 const ConstCmxHitsMap& cmxHitsMap,
1671 const ConstCmxSumsMap& cmxEtMap,
1672 LVL1::JetElementKey& elementKey) const
1673{
1674 int slices = -1;
1675 int trigJ = m_dfltSlices/2;
1676 for (int mod = module; mod < module + modulesPerSlink; ++mod) {
1677 for (int chan = 0; chan < m_channels; ++chan) {
1678 double eta = 0.;
1679 double phi = 0.;
1680 int layer = 0;
1681 if ( !m_jemMaps->mapping(crate, mod, chan, eta, phi, layer)) continue;
1682 const LVL1::JetElement* const je = findJetElement(eta, phi, jeMap,
1683 elementKey);
1684 if ( !je ) continue;
1685 const int numdat = 5;
1686 std::vector<int> sums(numdat);
1687 std::vector<int> sizes(numdat);
1688 sums[0] = std::accumulate((je->emEnergyVec()).begin(),
1689 (je->emEnergyVec()).end(), 0);
1690 sums[1] = std::accumulate((je->hadEnergyVec()).begin(),
1691 (je->hadEnergyVec()).end(), 0);
1692 sums[2] = std::accumulate((je->emErrorVec()).begin(),
1693 (je->emErrorVec()).end(), 0);
1694 sums[3] = std::accumulate((je->hadErrorVec()).begin(),
1695 (je->hadErrorVec()).end(), 0);
1696 sums[4] = std::accumulate((je->linkErrorVec()).begin(),
1697 (je->linkErrorVec()).end(), 0);
1698 sizes[0] = (je->emEnergyVec()).size();
1699 sizes[1] = (je->hadEnergyVec()).size();
1700 sizes[2] = (je->emErrorVec()).size();
1701 sizes[3] = (je->hadErrorVec()).size();
1702 sizes[4] = (je->linkErrorVec()).size();
1703 const int peak = je->peak();
1704 for (int i = 0; i < numdat; ++i) {
1705 if (sums[i] == 0) continue;
1706 if (slices < 0) {
1707 slices = sizes[i];
1708 trigJ = peak;
1709 } else if (slices != sizes[i] || trigJ != peak) return false;
1710 }
1711 }
1712 const LVL1::JEMEtSums* const et = findEnergySums(crate, mod, etMap);
1713 if (et) {
1714 const int numdat = 3;
1715 std::vector<unsigned int> sums(numdat);
1716 std::vector<int> sizes(numdat);
1717 sums[0] = std::accumulate((et->ExVec()).begin(),
1718 (et->ExVec()).end(), 0);
1719 sums[1] = std::accumulate((et->EyVec()).begin(),
1720 (et->EyVec()).end(), 0);
1721 sums[2] = std::accumulate((et->EtVec()).begin(),
1722 (et->EtVec()).end(), 0);
1723 sizes[0] = (et->ExVec()).size();
1724 sizes[1] = (et->EyVec()).size();
1725 sizes[2] = (et->EtVec()).size();
1726 const int peak = et->peak();
1727 for (int i = 0; i < numdat; ++i) {
1728 if (sums[i] == 0) continue;
1729 if (slices < 0) {
1730 slices = sizes[i];
1731 trigJ = peak;
1732 } else if (slices != sizes[i] || trigJ != peak) return false;
1733 }
1734 }
1735 }
1736 // CMX last slink of crate
1737 if (module/modulesPerSlink == m_slinks - 1) {
1738 for (int jem = module; jem < module + modulesPerSlink; ++jem) {
1739 for (int frame = 0; frame < m_frames; ++frame) {
1740 for (int loc = 0; loc < m_locations; ++loc) {
1741 const int key = tobKey(crate, jem, frame, loc);
1742 const LVL1::CMXJetTob* tob = findCmxTob(key, cmxTobMap);
1743 if (tob) {
1744 const int numdat = 4;
1745 std::vector<int> sums(numdat);
1746 std::vector<int> sizes(numdat);
1747 sums[0] = std::accumulate((tob->energyLgVec()).begin(),
1748 (tob->energyLgVec()).end(), 0);
1749 sums[1] = std::accumulate((tob->energySmVec()).begin(),
1750 (tob->energySmVec()).end(), 0);
1751 sums[2] = std::accumulate((tob->errorVec()).begin(),
1752 (tob->errorVec()).end(), 0);
1753 sums[3] = std::accumulate((tob->presenceMapVec()).begin(),
1754 (tob->presenceMapVec()).end(), 0);
1755 sizes[0] = (tob->energyLgVec()).size();
1756 sizes[1] = (tob->energySmVec()).size();
1757 sizes[2] = (tob->errorVec()).size();
1758 sizes[3] = (tob->presenceMapVec()).size();
1759 const int peak = tob->peak();
1760 for (int i = 0; i < numdat; ++i) {
1761 if (sums[i] == 0) continue;
1762 if (slices < 0) {
1763 slices = sizes[i];
1764 trigJ = peak;
1765 } else if (slices != sizes[i] || trigJ != peak) return false;
1766 }
1767 }
1768 }
1769 }
1770 }
1771 const int maxDataID1 = LVL1::CMXJetHits::MAX_SOURCE;
1772 const int maxDataID2 = LVL1::CMXEtSums::MAX_SOURCE;
1773 const int maxDataID = (maxDataID1 > maxDataID2) ? maxDataID1 : maxDataID2;
1774 for (int source = 0; source < maxDataID; ++source) {
1775 const int numdat = 6;
1776 std::vector<unsigned int> sums(numdat);
1777 std::vector<int> sizes(numdat);
1778 const LVL1::CMXJetHits* hits = 0;
1779 if (source < maxDataID1) hits = findCmxHits(crate, source, cmxHitsMap);
1780 if (hits) {
1781 sums[0] = std::accumulate((hits->hitsVec0()).begin(),
1782 (hits->hitsVec0()).end(), 0);
1783 sums[1] = std::accumulate((hits->hitsVec1()).begin(),
1784 (hits->hitsVec1()).end(), 0);
1785 sums[2] = std::accumulate((hits->errorVec0()).begin(),
1786 (hits->errorVec0()).end(), 0);
1787 sums[3] = std::accumulate((hits->errorVec1()).begin(),
1788 (hits->errorVec1()).end(), 0);
1789 sizes[0] = (hits->hitsVec0()).size();
1790 sizes[1] = (hits->hitsVec1()).size();
1791 sizes[2] = (hits->errorVec0()).size();
1792 sizes[3] = (hits->errorVec1()).size();
1793 const int peak = hits->peak();
1794 for (int i = 0; i < 4; ++i) {
1795 if (sums[i] == 0) continue;
1796 if (slices < 0) {
1797 slices = sizes[i];
1798 trigJ = peak;
1799 } else if (slices != sizes[i] || trigJ != peak) return false;
1800 }
1801 }
1802 const LVL1::CMXEtSums* et = 0; if (source < maxDataID2) et = findCmxSums(crate, source, cmxEtMap);
1803 if (et) {
1804 sums[0] = std::accumulate((et->ExVec()).begin(),
1805 (et->ExVec()).end(), 0);
1806 sums[1] = std::accumulate((et->EyVec()).begin(),
1807 (et->EyVec()).end(), 0);
1808 sums[2] = std::accumulate((et->EtVec()).begin(),
1809 (et->EtVec()).end(), 0);
1810 sums[3] = std::accumulate((et->ExErrorVec()).begin(),
1811 (et->ExErrorVec()).end(), 0);
1812 sums[4] = std::accumulate((et->EyErrorVec()).begin(),
1813 (et->EyErrorVec()).end(), 0);
1814 sums[5] = std::accumulate((et->EtErrorVec()).begin(),
1815 (et->EtErrorVec()).end(), 0);
1816 sizes[0] = (et->ExVec()).size();
1817 sizes[1] = (et->EyVec()).size();
1818 sizes[2] = (et->EtVec()).size();
1819 sizes[3] = (et->ExErrorVec()).size();
1820 sizes[4] = (et->EyErrorVec()).size();
1821 sizes[5] = (et->EtErrorVec()).size();
1822 const int peak = et->peak();
1823 for (int i = 0; i < numdat; ++i) {
1824 if (sums[i] == 0) continue;
1825 if (slices < 0) {
1826 slices = sizes[i];
1827 trigJ = peak;
1828 } else if (slices != sizes[i] || trigJ != peak) return false;
1829 }
1830 }
1831 }
1832 }
1833 if (slices < 0) slices = m_dfltSlices;
1834 timeslices = slices;
1835 trigJem = trigJ;
1836 return true;
1837}
1838
1839// Get energy subBlock types from CMXEtSums source type
1840
1844 CmxEnergySubBlock::HitsType& hitType) const
1845{
1846 switch (source) {
1848 srcType = CmxEnergySubBlock::REMOTE;
1850 break;
1852 srcType = CmxEnergySubBlock::REMOTE;
1854 break;
1856 srcType = CmxEnergySubBlock::LOCAL;
1858 break;
1860 srcType = CmxEnergySubBlock::LOCAL;
1862 break;
1864 srcType = CmxEnergySubBlock::TOTAL;
1866 break;
1868 srcType = CmxEnergySubBlock::TOTAL;
1870 break;
1872 hitType = CmxEnergySubBlock::SUM_ET;
1874 break;
1876 hitType = CmxEnergySubBlock::SUM_ET;
1878 break;
1882 break;
1886 break;
1890 break;
1891 default:
1892 break;
1893 }
1894}
1895
1896// Get jet hits subBlock source ID from CMXJetHits source type
1897
1899{
1900 int sourceId = CmxJetSubBlock::MAX_SOURCE_ID;
1901 switch (source) {
1903 sourceId = CmxJetSubBlock::REMOTE_MAIN;
1904 break;
1906 sourceId = CmxJetSubBlock::LOCAL_MAIN;
1907 break;
1909 sourceId = CmxJetSubBlock::TOTAL_MAIN;
1910 break;
1913 break;
1916 break;
1919 break;
1922 break;
1925 break;
1928 break;
1929 default:
1930 break;
1931 }
1932 return sourceId;
1933}
1934
1935} // 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)
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-Energy data post LS1.
unsigned int hits(int slice, HitsType hType, SumType sType) const
Return hits map for given hits type and sum type.
void setSubsums(int slice, int jem, unsigned int ex, unsigned int ey, unsigned int et, int exError, int eyError, int etError)
Store energy subsums and errors for given JEM.
void setEtHits(int slice, HitsType hType, SumType sType, unsigned int map)
Store hits map for given hits type and sum type.
unsigned int energy(int slice, int jem, EnergyType eType) const
Return energy subsum for given JEM and energy type.
void clear()
Clear all data.
int error(int slice, int jem, EnergyType eType) const
Return energy subsum error for given JEM and energy type.
Sub-Block class for CMX-Jet data post LS1.
int energyLarge(int slice, int jem, int tob) const
Return energy large window size for given jem and tob.
int localCoord(int slice, int jem, int tob) const
Return Local coordinate for given jem and tob.
void setParityBits(int slice, int jem, int parity)
Store parity bits for neutral format.
bool unpack()
Unpack data.
int frame(int slice, int jem, int tob) const
Return frame for given jem and tob.
int energySmall(int slice, int jem, int tob) const
Return energy small window size for given jem and tob.
unsigned int hits(int slice, int source, int flag) const
Return hit/topo counts for given source ID and HL flag.
unsigned int presenceMap(int slice, int jem) const
Return presence map for given JEM.
int parityBits(int slice, int jem) const
Return parity bits for given JEM.
void setHits(int slice, int source, int flag, unsigned int hits, int error)
Store hit counts for given source ID and HL flag.
void setPresenceMap(int slice, int jem, unsigned int map)
Store presence map.
void setTob(int slice, int jem, int frame, int loc, int energyLarge, int energySmall, int error)
Store TOB (RoI) data for given JEM, frame, local coord.
void clear()
Clear all data.
int hitsError(int slice, int source, int flag) const
Return hit error for given source ID and HL flag.
int tobError(int slice, int jem, int tob) const
Return error bit for given jem and tob.
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)
JEM jet element dataword class.
uint32_t data() const
Sub-Block class for JEM data post LS1.
int timeslices() const
Return number of timeslices.
void fillJetElement(int slice, const JemJetElement &jetEle)
Store jet element data.
void clear()
Clear all data.
bool unpack()
Unpack data.
unsigned int ey(int slice) const
Return energy subsum Ey.
void setEnergySubsums(int slice, unsigned int ex, unsigned int ey, unsigned int et)
Store energy subsum data.
unsigned int ex(int slice) const
Return energy subsum Ex.
void setJemHeader(int version, int format, int slice, int crate, int module, int timeslices)
Store JEM header.
unsigned int et(int slice) const
Return energy subsum Et.
bool pack()
Pack data.
JemJetElement jetElement(int slice, int channel) const
Return jet element for given channel.
void decodeCmxJet(CmxJetSubBlock *subBlock, int trigJem, JepByteStreamToolData &data, LocalData &ld) const
Unpack CMX-Jet sub-block.
void energySubBlockTypes(int source, CmxEnergySubBlock::SourceType &srcType, CmxEnergySubBlock::SumType &sumType, CmxEnergySubBlock::HitsType &hitType) const
Get energy subBlock types from CMXEtSums source type.
DataVector< LVL1::CMXJetTob > CmxTobCollection
int m_version
Property:Sub_block header version.
const int m_modules
Number of JEM modules per crate.
DataVector< LVL1::CMXEtSums > CmxSumsCollection
int m_crateMax
Property: Maximum crate number when writing out bytestream.
DataVector< LVL1::JetElement > JetElementCollection
const LVL1::CMXJetHits * findCmxHits(int crate, int source, const ConstCmxHitsMap &cmxHitsMap) const
Find CMX hits for given crate, source.
StatusCode convertBs(const std::string &sgKey, const IROBDataProviderSvc::VROBFRAG &robFrags, JepByteStreamToolData &data) const
Convert bytestream to given container type.
const LVL1::CMXJetTob * findCmxTob(int key, const ConstCmxTobMap &cmxTobMap) const
Find CMX TOB for given key.
virtual StatusCode finalize() override
bool slinkSlices(int crate, int module, int modulesPerSlink, int &timeslices, int &trigJem, const ConstJetElementMap &jeMap, const ConstEnergySumsMap &etMap, const ConstCmxTobMap &cmxTobMap, const ConstCmxHitsMap &cmxHitsMap, const ConstCmxSumsMap &cmxEtMap, LVL1::JetElementKey &elementKey) const
Get number of slices and triggered slice offset for next slink.
SmartIF< IByteStreamCnvSvc > m_byteStreamCnvSvc
std::map< unsigned int, const LVL1::JetElement * > ConstJetElementMap
int m_dataFormat
Property:Data compression format.
std::map< int, const LVL1::CMXJetTob * > ConstCmxTobMap
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
const std::vector< uint32_t > & sourceIDs() const
Return reference to vector with all possible Source Identifiers.
int m_forceSlices
Property: Force number of slices in bytestream.
ToolHandle< LVL1::IL1CaloMappingTool > m_jemMaps
Property: Channel mapping tool.
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Property:Error collection tool.
std::map< int, const LVL1::JEMEtSums * > ConstEnergySumsMap
std::map< int, const LVL1::CMXEtSums * > ConstCmxSumsMap
int m_crateOffsetSw
Property:Software crate number offset.
void setupCmxTobMap(const CmxTobCollection *tobCollection, ConstCmxTobMap &cmxTobMap) const
Set up CMX TOB map.
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
JepByteStreamV2Tool(const std::string &type, const std::string &name, const IInterface *parent)
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
const int m_crates
Number of crates.
virtual StatusCode initialize() override
const int m_locations
Number of RoI locations.
const int m_maxTobs
Maximum number of TOBs per module.
const LVL1::CMXEtSums * findCmxSums(int crate, int source, const ConstCmxSumsMap &cmxEtMap) const
Find CMX energy sums for given crate, source.
const eformat::SubDetector m_subDetector
Sub-detector type.
StatusCode convert(const std::string &name, DataVector< LVL1::JetElement > *jeCollection) const
Convert ROB fragments to jet elements.
void decodeCmxEnergy(CmxEnergySubBlock *subBlock, int trigJem, CmxSumsData &data, LocalData &ld) const
Unpack CMX-Energy sub-block.
std::map< int, const LVL1::CMXJetHits * > ConstCmxHitsMap
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
int jetSubBlockSourceId(int source) const
Get jet hits subBlock source ID from CMXJetHits source type.
void setupJeMap(const JetElementCollection *jeCollection, ConstJetElementMap &jeMap, LVL1::JetElementKey &elementKey) const
Set up jet element map.
void decodeJem(JemSubBlockV2 *subBlock, int trigJem, JepByteStreamToolData &data, LocalData &ld) const
Unpack JEM sub-block.
ServiceHandle< IROBDataProviderSvc > m_robDataProvider
void setupCmxEtMap(const CmxSumsCollection *enCollection, ConstCmxSumsMap &cmxEtMap) const
Set up CMX energy sums map.
int m_dfltSlices
Property: Default number of slices in simulation.
std::vector< uint32_t > makeSourceIDs() const
const LVL1::JEMEtSums * findEnergySums(int crate, int module, const ConstEnergySumsMap &etMap) const
Find energy sums for given crate, module.
void setupEtMap(const EnergySumsCollection *enCollection, ConstEnergySumsMap &etMap) const
Set up energy sums map.
DataVector< LVL1::JEMEtSums > EnergySumsCollection
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
void setupCmxHitsMap(const CmxHitsCollection *hitCollection, ConstCmxHitsMap &cmxHitsMap) const
Set up CMX hits map.
int m_crateMin
Property: Minimum crate number when writing out bytestream.
DataVector< LVL1::CMXJetHits > CmxHitsCollection
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
std::vector< uint32_t > m_sourceIDsProp
Property:ROB source IDs.
int m_crateOffsetHw
Property:Hardware crate number offset.
int tobKey(int crate, int jem, int frame, int loc) const
Find TOB map key for given crate, jem, frame, loc.
const int m_channels
Number of channels per module.
const int m_frames
Number of RoI frames.
Gaudi::Property< bool > m_enableEncoding
const LVL1::JetElement * findJetElement(double eta, double phi, const ConstJetElementMap &jeMap, LVL1::JetElementKey &elementKey) const
Find a jet element given eta, phi.
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.
CMXEtSums object stores Et sums from the Energy CMXs.
const std::vector< unsigned int > & ExVec() const
returns module Ex sum
void addEt(const std::vector< unsigned int > &Et, const std::vector< int > &EtError)
Add data to existing objects.
void addEx(const std::vector< unsigned int > &Ex, const std::vector< int > &ExError)
Update Ex sum.
void addEy(const std::vector< unsigned int > &Ey, const std::vector< int > &EyError)
Update Ey sum.
const std::vector< unsigned int > & EyVec() const
returns module Ey sum
const std::vector< int > & EyErrorVec() const
returns module Ey errors
const std::vector< int > & ExErrorVec() const
returns module Ex errors
const std::vector< int > & EtErrorVec() const
returns module ET errors
const std::vector< unsigned int > & EtVec() const
Access multi-slice data.
Summary of JEP (Jet) hits produced by the merger modules.
const std::vector< int > & errorVec1() const
returns error1
const std::vector< int > & errorVec0() const
returns error0
const std::vector< unsigned int > & hitsVec0() const
For multi-slice readout.
void addHits(const std::vector< unsigned int > &hits0, const std::vector< unsigned int > &hits1, const std::vector< int > &error0, const std::vector< int > &error1)
Add data to existing object.
const std::vector< unsigned int > & hitsVec1() const
returns hits1
TOB data received by the merger modules.
const std::vector< int > & energySmVec() const
returns energy small window
const std::vector< int > & energyLgVec() const
For multi-slice readout.
const std::vector< unsigned int > & presenceMapVec() const
returns presence maps
const std::vector< int > & errorVec() const
returns error
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
int module() const
returns module number
Definition JEMEtSums.cxx:52
const std::vector< unsigned int > & EyVec() const
returns module Ey sum
Definition JEMEtSums.cxx:82
void addEx(const std::vector< unsigned int > &Ex)
Update Ex sum.
Definition JEMEtSums.cxx:97
const std::vector< unsigned int > & ExVec() const
returns module Ex sum
Definition JEMEtSums.cxx:77
void addEt(const std::vector< unsigned int > &Et)
Update ET sum.
Definition JEMEtSums.cxx:92
const std::vector< unsigned int > & EtVec() const
returns module ET sum
Definition JEMEtSums.cxx:72
int crate() const
returns crate number
Definition JEMEtSums.cxx:47
void addEy(const std::vector< unsigned int > &Ey)
Update Ey sum.
Jet/Energy Processor container for writing bytestream post-LS1.
const DataVector< CMXEtSums > * CmxSums() const
Return pointer to CMX energy sums collection.
const DataVector< CMXJetHits > * CmxHits() const
Return pointer to CMX hit sums collection.
const DataVector< CMXJetTob > * CmxTobs() const
Return pointer to CMX TOBs collection.
const DataVector< JEMEtSums > * EnergySums() const
Return pointer to energy sums collection.
const DataVector< JetElement > * JetElements() const
Return pointer to jet element collection.
virtual unsigned int jeKey(const xAOD::TriggerTower &tower)
returns key of passed tower
The JetElementKey object provides the key for each JetElement depending on its eta,...
Jet elements are the inputs to the Jet, ETmiss and ETsum triggers.
double eta() const
Eta of centre of JetElement.
const std::vector< int > & hadEnergyVec() const
return Had energy vector reference (all timeslices)
double phi() const
Phi of centre of JetElement.
const std::vector< int > & linkErrorVec() const
return link error vector reference (all timeslices)
void addSlice(int slice, int emEnergy, int hadEnergy, int emError, int hadError, int linkError)
add data for one timeslice.
const std::vector< int > & emErrorVec() const
return Em error vector reference (all timeslices)
int peak() const
return triggered slice offset
const std::vector< int > & hadErrorVec() const
return Had error vector reference (all timeslices)
const std::vector< int > & emEnergyVec() const
Return data for all slices.
bool verbose
Definition hcg.cxx:73
static const InterfaceID IID_IJepByteStreamV2Tool("JepByteStreamV2Tool", 1, 1)
Definition index.py:1
Extra patterns decribing particle interation process.