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