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