Project
Loading...
Searching...
No Matches
RawDecoderSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
16#include "Framework/Logger.h"
23
24#include <iostream>
25#include <sstream>
26#include <set>
27
28using namespace o2::focal::reco_workflow;
29
31{
32 if (ctx.options().get<bool>("filterIncomplete")) {
33 LOG(info) << "Enabling filtering of incomplete events in the pixel data";
34 mFilterIncomplete = true;
35 }
36 if (ctx.options().get<bool>("displayInconsistent")) {
37 LOG(info) << "Display additional information in case of inconsistency between pixel links";
38 mDisplayInconsistent = true;
39 }
40 auto mappingfile = ctx.options().get<std::string>("pixelmapping");
42 auto chiptype = ctx.options().get<std::string>("pixeltype");
43 if (chiptype == "IB") {
44 LOG(info) << "Using mapping type: IB";
46 } else if (chiptype == "OB") {
47 LOG(info) << "Using mapping type: OB";
49 } else {
50 LOG(fatal) << "Unkown mapping type for pixels: " << chiptype;
51 }
52 if (mappingfile == "default") {
53 LOG(info) << "Using default pixel mapping for pixel type " << chiptype;
54 mPixelMapping = std::make_unique<PixelMapper>(mappingtype);
55 } else {
56 LOG(info) << "Using user-defined mapping: " << mappingfile;
57 mPixelMapping = std::make_unique<PixelMapper>(PixelMapper::MappingType_t::MAPPING_UNKNOWN);
58 mPixelMapping->setMappingFile(mappingfile, mappingtype);
59 }
60}
61
63{
64 LOG(info) << "Running FOCAL decoding";
65 resetContainers();
66 mTimeframeHasPadData = false;
67 mTimeframeHasPixelData = false;
68
69 int inputs = 0;
70 std::vector<char> rawbuffer;
71 uint16_t currentfee = 0;
72 o2::InteractionRecord currentIR;
73 std::unordered_map<int, int> numHBFFEE, numEventsFEE;
74 std::unordered_map<int, std::vector<int>> numEventsHBFFEE;
75 int numHBFPadsTF = 0, numEventsPadsTF = 0;
76 std::vector<int> expectFEEs;
77 for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) {
78 if (rawData.header != nullptr && rawData.payload != nullptr) {
79 const auto payloadSize = o2::framework::DataRefUtils::getPayloadSize(rawData);
80 auto header = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(rawData);
81 LOG(debug) << "Channel " << header->dataOrigin.str << "/" << header->dataDescription.str << "/" << header->subSpecification;
82
83 gsl::span<const char> databuffer(rawData.payload, payloadSize);
84 int currentpos = 0;
85 bool firstHBF = true;
86 while (currentpos < databuffer.size()) {
87 auto rdh = reinterpret_cast<const o2::header::RDHAny*>(databuffer.data() + currentpos);
88 if (mDebugMode) {
90 }
91
92 if (o2::raw::RDHUtils::getMemorySize(rdh) > o2::raw::RDHUtils::getHeaderSize(rdh)) {
93 // non-0 payload size:
94 auto payloadsize = o2::raw::RDHUtils::getMemorySize(rdh) - o2::raw::RDHUtils::getHeaderSize(rdh);
95 int endpoint = static_cast<int>(o2::raw::RDHUtils::getEndPointID(rdh));
96 auto fee = o2::raw::RDHUtils::getFEEID(rdh);
97 LOG(debug) << "Next RDH: ";
98 LOG(debug) << "Found fee 0x" << std::hex << fee << std::dec << " (System " << (fee == 0xcafe ? "Pads" : "Pixels") << ")";
99 LOG(debug) << "Found trigger BC: " << o2::raw::RDHUtils::getTriggerBC(rdh);
100 LOG(debug) << "Found trigger Oribt: " << o2::raw::RDHUtils::getTriggerOrbit(rdh);
101 LOG(debug) << "Found payload size: " << payloadsize;
102 LOG(debug) << "Found offset to next: " << o2::raw::RDHUtils::getOffsetToNext(rdh);
103 LOG(debug) << "Stop bit: " << (o2::raw::RDHUtils::getStop(rdh) ? "yes" : "no");
104 LOG(debug) << "Number of GBT words: " << (payloadsize * sizeof(char) / (fee == 0xcafe ? sizeof(o2::focal::PadGBTWord) : sizeof(o2::itsmft::GBTWord)));
105 auto page_payload = databuffer.subspan(currentpos + o2::raw::RDHUtils::getHeaderSize(rdh), payloadsize);
106 std::copy(page_payload.begin(), page_payload.end(), std::back_inserter(rawbuffer));
107 }
108
109 auto trigger = o2::raw::RDHUtils::getTriggerType(rdh);
110 if (trigger & o2::trigger::HB) {
111 // HB trigger received
112 if (o2::raw::RDHUtils::getStop(rdh)) {
113 LOG(debug) << "Stop bit received - processing payload";
114 // Data ready
115 if (rawbuffer.size()) {
116 // Only process if we actually have payload (skip empty HBF)
117 if (currentfee == 0xcafe) { // Use FEE ID 0xcafe for PAD data
118 // Pad data
119 if (mUsePadData) {
120 LOG(debug) << "Processing PAD data";
121 auto nEventsPads = decodePadData(rawbuffer, currentIR);
122 mTimeframeHasPadData = true;
123 auto found = mNumEventsHBFPads.find(nEventsPads);
124 if (found != mNumEventsHBFPads.end()) {
125 found->second += 1;
126 } else {
127 mNumEventsHBFPads.insert(std::pair<int, int>{nEventsPads, 1});
128 }
129 numEventsPadsTF += nEventsPads;
130 numHBFPadsTF++;
131 }
132 } else { // All other FEEs are pixel FEEs
133 // Pixel data
134 if (mUsePixelData) {
135 auto feeID = o2::raw::RDHUtils::getFEEID(rdh);
136 if (firstHBF) {
137 auto found = std::find(expectFEEs.begin(), expectFEEs.end(), feeID);
138 if (found == expectFEEs.end()) {
139 expectFEEs.emplace_back(feeID);
140 }
141 firstHBF = false;
142 }
143 LOG(debug) << "Processing Pixel data from FEE " << feeID;
144 auto neventsPixels = decodePixelData(rawbuffer, currentIR, feeID);
145 mTimeframeHasPixelData = true;
146 auto found = numHBFFEE.find(feeID);
147 if (found != numHBFFEE.end()) {
148 found->second++;
149 } else {
150 numHBFFEE.insert(std::pair<int, int>{feeID, 1});
151 }
152 auto evFound = numEventsFEE.find(feeID);
153 if (evFound != numEventsFEE.end()) {
154 evFound->second += neventsPixels;
155 } else {
156 numEventsFEE.insert(std::pair<int, int>{feeID, neventsPixels});
157 }
158 auto evHBFFound = numEventsHBFFEE.find(feeID);
159 if (evHBFFound != numEventsHBFFEE.end()) {
160 evHBFFound->second.push_back(neventsPixels);
161 } else {
162 std::vector<int> evbuffer;
163 evbuffer.push_back(neventsPixels);
164 numEventsHBFFEE.insert(std::pair<int, std::vector<int>>{feeID, evbuffer});
165 }
166 }
167 }
168 } else {
169 LOG(debug) << "Payload size 0 - skip empty HBF";
170 }
171 rawbuffer.clear();
172 } else {
173 // Get interaction record for HBF
174 currentIR.bc = o2::raw::RDHUtils::getTriggerBC(rdh);
175 currentIR.orbit = o2::raw::RDHUtils::getTriggerOrbit(rdh);
176 currentfee = o2::raw::RDHUtils::getFEEID(rdh);
177 LOG(debug) << "New HBF " << currentIR.orbit << " / " << currentIR.bc << ", FEE 0x" << std::hex << currentfee << std::dec;
178 }
179 }
180
181 currentpos += o2::raw::RDHUtils::getOffsetToNext(rdh);
182 }
183 } else {
184 LOG(error) << "Input " << inputs << ": Either header or payload is nullptr";
185 }
186 inputs++;
187 }
188
189 int numHBFPixelsTF = 0;
190 if (mTimeframeHasPixelData) {
191 // Consistency check PixelEvents
192 if (!consistencyCheckPixelFEE(numHBFFEE)) {
193 LOG(alarm) << "Mismatch in number of HBF / TF between pixel FEEs";
194 if (mDisplayInconsistent) {
195 printCounters(numHBFFEE);
196 }
197 mNumInconsistencyPixelHBF++;
198 }
199 numHBFPixelsTF = maxCounter(numHBFFEE);
200 mNumHBFPixels += numHBFPixelsTF;
201 if (!consistencyCheckPixelFEE(numEventsFEE)) {
202 LOG(alarm) << "Mismatch in number of events / TF between pixel FEEs";
203 if (mDisplayInconsistent) {
204 printCounters(numEventsFEE);
205 }
206 mNumInconsistencyPixelEvent++;
207 }
208 mNumEventsPixels += maxCounter(numEventsFEE);
209 if (!checkEventsHBFConsistency(numEventsHBFFEE)) {
210 LOG(alarm) << "Mistmatch number of events / HBF between pixel FEEs";
211 if (mDisplayInconsistent) {
212 printEvents(numEventsHBFFEE);
213 }
214 mNumInconsistencyPixelEventHBF++;
215 }
216 fillPixelEventHBFCount(numEventsHBFFEE);
217
218 if (mFilterIncomplete) {
219 LOG(debug) << "Filtering incomplete pixel events";
220 for (auto& hbf : mHBFs) {
221 auto numErased = filterIncompletePixelsEventsHBF(hbf.second, expectFEEs);
222 mNumEventsPixels -= numErased;
223 }
224 }
225 }
226
227 LOG(info) << "Found " << mHBFs.size() << " HBFs in timeframe";
228
229 LOG(debug) << "EventBuilder: Pixels: " << (mTimeframeHasPixelData ? "yes" : "no");
230 LOG(debug) << "EventBuilder: Pads: " << (mTimeframeHasPadData ? "yes" : "no");
231 buildEvents();
232
233 LOG(info) << "Found " << mOutputTriggerRecords.size() << " events in timeframe";
234
235 sendOutput(ctx);
236 mNumEventsPads += numEventsPadsTF;
237 mNumHBFPads += numHBFPadsTF;
238 mNumTimeframes++;
239 auto foundHBFperTFPads = mNumHBFperTFPads.find(numHBFPadsTF);
240 if (foundHBFperTFPads != mNumHBFperTFPads.end()) {
241 foundHBFperTFPads->second++;
242 } else {
243 mNumHBFperTFPads.insert(std::pair<int, int>{numHBFPadsTF, 1});
244 }
245 auto foundHBFperTFPixels = mNumHBFperTFPixels.find(numHBFPixelsTF);
246 if (foundHBFperTFPixels != mNumHBFperTFPixels.end()) {
247 foundHBFperTFPixels->second++;
248 } else {
249 mNumHBFperTFPixels.insert(std::pair<int, int>{numHBFPixelsTF, 1});
250 }
251}
252
254{
255 std::cout << "Number of timeframes: " << mNumTimeframes << std::endl;
256 std::cout << "Number of pad HBFs: " << mNumHBFPads << std::endl;
257 std::cout << "Number of pixel HBFs: " << mNumHBFPixels << std::endl;
258 for (auto& [hbfs, tfs] : mNumHBFperTFPads) {
259 std::cout << "Pads - Number of TFs with " << hbfs << " HBFs: " << tfs << std::endl;
260 }
261 for (auto& [hbfs, tfs] : mNumHBFperTFPixels) {
262 std::cout << "Pixels - Number of TFs with " << hbfs << " HBFs: " << tfs << std::endl;
263 }
264 std::cout << "Number of pad events: " << mNumEventsPads << std::endl;
265 std::cout << "Number of pixel events: " << mNumEventsPixels << std::endl;
266 for (auto& [nevents, nHBF] : mNumEventsHBFPads) {
267 std::cout << "Number of HBFs with " << nevents << " pad events: " << nHBF << std::endl;
268 }
269 for (auto& [nevents, nHBF] : mNumEventsHBFPixels) {
270 std::cout << "Number of HBFs with " << nevents << " pixel events: " << nHBF << std::endl;
271 }
272 std::cout << "Number of inconsistencies between pixel FEEs: " << mNumInconsistencyPixelHBF << " HBFs, " << mNumInconsistencyPixelEvent << " events, " << mNumInconsistencyPixelEventHBF << " events / HBF" << std::endl;
273}
274
275void RawDecoderSpec::sendOutput(framework::ProcessingContext& ctx)
276{
277 ctx.outputs().snapshot(framework::Output{o2::header::gDataOriginFOC, "PADLAYERS", mOutputSubspec}, mOutputPadLayers);
278 ctx.outputs().snapshot(framework::Output{o2::header::gDataOriginFOC, "PIXELHITS", mOutputSubspec}, mOutputPixelHits);
279 ctx.outputs().snapshot(framework::Output{o2::header::gDataOriginFOC, "PIXELCHIPS", mOutputSubspec}, mOutputPixelChips);
280 ctx.outputs().snapshot(framework::Output{o2::header::gDataOriginFOC, "TRIGGERS", mOutputSubspec}, mOutputTriggerRecords);
281}
282
283void RawDecoderSpec::resetContainers()
284{
285 mHBFs.clear();
286 mOutputPadLayers.clear();
287 mOutputPixelChips.clear();
288 mOutputPixelHits.clear();
289 mOutputTriggerRecords.clear();
290}
291
292int RawDecoderSpec::decodePadData(const gsl::span<const char> padWords, o2::InteractionRecord& hbIR)
293{
294 LOG(debug) << "Decoding pad data for Orbit " << hbIR.orbit << ", BC " << hbIR.bc;
295 constexpr std::size_t EVENTSIZEPADGBT = 1180,
296 EVENTSIZECHAR = EVENTSIZEPADGBT * sizeof(PadGBTWord) / sizeof(char);
297 auto nevents = padWords.size() / (EVENTSIZECHAR);
298 for (int ievent = 0; ievent < nevents; ievent++) {
299 decodePadEvent(padWords.subspan(EVENTSIZECHAR * ievent, EVENTSIZECHAR), hbIR);
300 }
301 return nevents;
302}
303
304void RawDecoderSpec::decodePadEvent(const gsl::span<const char> padWords, o2::InteractionRecord& hbIR)
305{
306 gsl::span<const PadGBTWord> padWordsGBT(reinterpret_cast<const PadGBTWord*>(padWords.data()), padWords.size() / sizeof(PadGBTWord));
307 mPadDecoder.reset();
308 mPadDecoder.decodeEvent(padWordsGBT);
309 std::map<o2::InteractionRecord, HBFData>::iterator foundHBF = mHBFs.find(hbIR);
310 if (foundHBF == mHBFs.end()) {
311 // New event, create new entry
312 HBFData nexthbf;
313 auto res = mHBFs.insert({hbIR, nexthbf});
314 foundHBF = res.first;
315 }
316 foundHBF->second.mPadEvents.push_back(createPadLayerEvent(mPadDecoder.getData()));
317}
318
319int RawDecoderSpec::decodePixelData(const gsl::span<const char> pixelWords, o2::InteractionRecord& hbIR, int feeID)
320{
321 LOG(debug) << "Decoding pixel data for Orbit " << hbIR.orbit << ", BC " << hbIR.bc;
322
323 gsl::span<const o2::itsmft::GBTWord> pixelpayload(reinterpret_cast<const o2::itsmft::GBTWord*>(pixelWords.data()), pixelWords.size() / sizeof(o2::itsmft::GBTWord));
324 LOG(debug) << pixelWords.size() << " Bytes -> " << pixelpayload.size() << " GBT words";
325 mPixelDecoder.reset();
326 mPixelDecoder.decodeEvent(pixelpayload);
327
328 std::map<o2::InteractionRecord, HBFData>::iterator foundHBF = mHBFs.end();
329
330 int nevents = 0;
331 for (auto& [trigger, chipdata] : mPixelDecoder.getChipData()) {
332 LOG(debug) << "Found trigger orbit " << trigger.orbit << ", BC " << trigger.bc;
333 if (trigger.orbit != hbIR.orbit) {
334 LOG(debug) << "FEE 0x" << std::hex << feeID << std::dec << ": Discarding spurious trigger with Orbit " << trigger.orbit << " (HB " << hbIR.orbit << ")";
335 continue;
336 }
337 int nhits = 0;
338 // set fee for all chips
339 for (auto& chip : chipdata) {
340 nhits += chip.mHits.size();
341 }
342 // std::cout << "FEE 0x" << std::hex << feeID << std::dec << " (fee " << fee << ", branch " << branch << ", layer " << layer << "): Found " << chipdata.size() << " chips with " << nhits << " hits (total) for Orbit " << trigger.orbit << ", BC " << trigger.bc << std::endl;
343 // for (const auto& chip : chipdata) {
344 // std::cout << "Chip " << static_cast<int>(chip.mChipID) << ", lane " << static_cast<int>(chip.mLaneID) << ": " << chip.mHits.size() << " hits ... (Dataframe "
345 // << (chip.isDataframe() ? "yes" : "no") << ", Emptyframe " << (chip.isEmptyframe() ? "yes" : "no") << ", Busy on " << (chip.isBusyOn() ? "yes" : "no") << ", Busy off " << (chip.isBusyOff() ? "yes" : "no") << ")" << std::endl;
346 // }
347 if (foundHBF == mHBFs.end()) {
348 // take HBF from the first trigger as BC in RDH for pixel data is unreliable
349 foundHBF = mHBFs.find(hbIR);
350 if (foundHBF == mHBFs.end()) {
351 // New event, create new entry
352 HBFData nexthbf;
353 auto res = mHBFs.insert({hbIR, nexthbf});
354 foundHBF = res.first;
355 }
356 }
357 // check if the trigger already exists
358 auto triggerfound = std::find(foundHBF->second.mPixelTriggers.begin(), foundHBF->second.mPixelTriggers.end(), trigger);
359 if (triggerfound != foundHBF->second.mPixelTriggers.end()) {
360 //
361 auto index = triggerfound - foundHBF->second.mPixelTriggers.begin();
362 for (const auto& chip : chipdata) {
363 try {
364 auto chipPosition = mPixelMapping->getPosition(feeID, chip);
365 fillChipToLayer(foundHBF->second.mPixelEvent[index][chipPosition.mLayer], chip, feeID);
367 LOG(warning) << e;
368 }
369 }
370 foundHBF->second.mFEEs[index].push_back(feeID);
371 } else {
372 // new trigger
373 std::array<PixelLayerEvent, constants::PIXELS_NLAYERS> nextevent;
374 foundHBF->second.mPixelEvent.push_back(nextevent);
375 foundHBF->second.mPixelTriggers.push_back(trigger);
376 auto& current = foundHBF->second.mPixelEvent.back();
377 for (const auto& chip : chipdata) {
378 try {
379 auto chipPosition = mPixelMapping->getPosition(feeID, chip);
380 fillChipToLayer(current[chipPosition.mLayer], chip, feeID);
382 LOG(warning) << e;
383 }
384 }
385 foundHBF->second.mFEEs.push_back({feeID});
386 }
387 nevents++;
388 }
389 return nevents;
390}
391
392std::array<o2::focal::PadLayerEvent, o2::focal::constants::PADS_NLAYERS> RawDecoderSpec::createPadLayerEvent(const o2::focal::PadData& data) const
393{
394 std::array<PadLayerEvent, constants::PADS_NLAYERS> result;
395 std::array<uint8_t, 8> triggertimes;
396 for (std::size_t ilayer = 0; ilayer < constants::PADS_NLAYERS; ilayer++) {
397 auto& asic = data.getDataForASIC(ilayer).getASIC();
398 int bc[2];
399 for (std::size_t ihalf = 0; ihalf < constants::PADLAYER_MODULE_NHALVES; ihalf++) {
400 auto header = asic.getHeader(ihalf);
401 bc[ihalf] = header.mBCID;
402 auto calib = asic.getCalib(ihalf);
403 auto cmn = asic.getCMN(ihalf);
404 result[ilayer].setHeader(ihalf, header.getHeader(), header.getBCID(), header.getWadd(), header.getFourbit(), header.getTrailer());
405 result[ilayer].setCalib(ihalf, calib.getADC(), calib.getTOA(), calib.getTOT());
406 result[ilayer].setCMN(ihalf, cmn.getADC(), cmn.getTOA(), cmn.getTOT());
407 }
408 for (std::size_t ichannel = 0; ichannel < constants::PADLAYER_MODULE_NCHANNELS; ichannel++) {
409 auto channel = asic.getChannel(ichannel);
410 result[ilayer].setChannel(ichannel, channel.getADC(), channel.getTOA(), channel.getTOT());
411 }
412 auto triggers = data.getDataForASIC(ilayer).getTriggerWords();
413 for (std::size_t window = 0; window < constants::PADLAYER_WINDOW_LENGTH; window++) {
414 std::fill(triggertimes.begin(), triggertimes.end(), 0);
415 triggertimes[0] = triggers[window].mTrigger0;
416 triggertimes[1] = triggers[window].mTrigger1;
417 triggertimes[2] = triggers[window].mTrigger2;
418 triggertimes[3] = triggers[window].mTrigger3;
419 triggertimes[4] = triggers[window].mTrigger4;
420 triggertimes[5] = triggers[window].mTrigger5;
421 triggertimes[6] = triggers[window].mTrigger6;
422 triggertimes[7] = triggers[window].mTrigger7;
423 result[ilayer].setTrigger(window, triggers[window].mHeader0, triggers[window].mHeader1, triggertimes);
424 }
425 }
426
427 return result;
428}
429
430void RawDecoderSpec::fillChipToLayer(o2::focal::PixelLayerEvent& pixellayer, const o2::focal::PixelChip& chipData, int feeID)
431{
432 int nhitsBefore = 0;
433 int nchipsBefore = pixellayer.getChips().size();
434 for (auto& chip : pixellayer.getChips()) {
435 nhitsBefore += chip.mHits.size();
436 }
437 pixellayer.addChip(feeID, chipData.mLaneID, chipData.mChipID, chipData.mStatusCode, chipData.mHits);
438 int nhitsAfter = 0;
439 int nchipsAfter = pixellayer.getChips().size();
440 for (auto& chip : pixellayer.getChips()) {
441 nhitsAfter += chip.mHits.size();
442 }
443 // std::cout << "Adding to pixel layer: Chips before " << nchipsBefore << " / after " << nchipsAfter << ", hits before " << nhitsBefore << " / after " << nhitsAfter << std::endl;
444}
445
446void RawDecoderSpec::fillEventPixeHitContainer(std::vector<PixelHit>& eventHits, std::vector<PixelChipRecord>& eventChips, const PixelLayerEvent& pixelLayer, int layerIndex)
447{
448 for (auto& chip : pixelLayer.getChips()) {
449 auto starthits = eventHits.size();
450 auto& chipHits = chip.mHits;
451 std::copy(chipHits.begin(), chipHits.end(), std::back_inserter(eventHits));
452 eventChips.emplace_back(layerIndex, chip.mFeeID, chip.mLaneID, chip.mChipID, chip.mStatusCode, starthits, chipHits.size());
453 }
454}
455
456void RawDecoderSpec::buildEvents()
457{
458 LOG(debug) << "Start building events" << std::endl;
459 for (const auto& [hbir, hbf] : mHBFs) {
460 if (mTimeframeHasPadData && mTimeframeHasPixelData) {
461 LOG(debug) << "Processing HBF with IR: " << hbir.orbit << " / " << hbir.bc << std::endl;
462 // check consistency in number of events between triggers, pixels and pads
463 // in case all events are in the stream
464 if ((hbf.mPadEvents.size() != hbf.mPixelEvent.size()) || (hbf.mPadEvents.size() != hbf.mPixelTriggers.size()) || (hbf.mPixelEvent.size() != hbf.mPixelTriggers.size())) {
465 LOG(error) << "Inconsistent number of events in HBF for pads (" << hbf.mPadEvents.size() << ") and pixels (" << hbf.mPixelEvent.size() << ") - " << hbf.mPixelTriggers.size() << " triggers";
466 continue;
467 }
468 LOG(debug) << "HBF: " << hbf.mPixelTriggers.size() << " triggers, " << hbf.mPadEvents.size() << " pad events, " << hbf.mPixelEvent.size() << " pixel events" << std::endl;
469 for (std::size_t itrg = 0; itrg < hbf.mPixelTriggers.size(); itrg++) {
470 auto startPads = mOutputPadLayers.size(),
471 startHits = mOutputPixelHits.size(),
472 startChips = mOutputPixelChips.size();
473 for (std::size_t ilayer = 0; ilayer < constants::PADS_NLAYERS; ilayer++) {
474 mOutputPadLayers.push_back(hbf.mPadEvents[itrg][ilayer]);
475 }
476 std::vector<PixelHit> eventHits;
477 std::vector<PixelChipRecord> eventPixels;
478 for (std::size_t ilayer = 0; ilayer < constants::PIXELS_NLAYERS; ilayer++) {
479 fillEventPixeHitContainer(eventHits, eventPixels, hbf.mPixelEvent[itrg][ilayer], ilayer);
480 }
481 std::copy(eventHits.begin(), eventHits.end(), std::back_inserter(mOutputPixelHits));
482 std::copy(eventPixels.begin(), eventPixels.end(), std::back_inserter(mOutputPixelChips));
483 // std::cout << "Orbit " << hbf.mPixelTriggers[itrg].orbit << ", BC " << hbf.mPixelTriggers[itrg].bc << ": " << eventPixels.size() << " chips with " << eventHits.size() << " hits ..." << std::endl;
484 mOutputTriggerRecords.emplace_back(hbf.mPixelTriggers[itrg], startPads, constants::PADS_NLAYERS, startChips, eventPixels.size(), startHits, eventHits.size());
485 }
486 } else if (mTimeframeHasPixelData) {
487 // only pixel data available, merge pixel layers and interaction record
488 if (!(hbf.mPixelEvent.size() == hbf.mPixelTriggers.size())) {
489 LOG(error) << "Inconsistent number of pixel events (" << hbf.mPixelEvent.size() << ") and triggers (" << hbf.mPixelTriggers.size() << ") in HBF";
490 continue;
491 }
492 for (std::size_t itrg = 0; itrg < hbf.mPixelTriggers.size(); itrg++) {
493 auto startPads = mOutputPadLayers.size(),
494 startHits = mOutputPixelHits.size(),
495 startChips = mOutputPixelChips.size();
496 std::vector<PixelHit> eventHits;
497 std::vector<PixelChipRecord> eventPixels;
498 for (std::size_t ilayer = 0; ilayer < constants::PIXELS_NLAYERS; ilayer++) {
499 fillEventPixeHitContainer(eventHits, eventPixels, hbf.mPixelEvent[itrg][ilayer], ilayer);
500 }
501 std::copy(eventHits.begin(), eventHits.end(), std::back_inserter(mOutputPixelHits));
502 std::copy(eventPixels.begin(), eventPixels.end(), std::back_inserter(mOutputPixelChips));
503 mOutputTriggerRecords.emplace_back(hbf.mPixelTriggers[itrg], startPads, 0, startChips, eventPixels.size(), startHits, eventHits.size());
504 }
505 } else if (mTimeframeHasPadData) {
506 // only pad data available, set pad layers and use IR of the HBF
507 for (std::size_t itrg = 0; itrg < hbf.mPadEvents.size(); itrg++) {
508 auto startPads = mOutputPadLayers.size(),
509 startHits = mOutputPixelHits.size(),
510 startChips = mOutputPixelChips.size();
512 fakeBC.orbit = hbir.orbit;
513 fakeBC.bc = hbir.bc + itrg;
514 for (std::size_t ilayer = 0; ilayer < constants::PADS_NLAYERS; ilayer++) {
515 mOutputPadLayers.push_back(hbf.mPadEvents[itrg][ilayer]);
516 }
517 mOutputTriggerRecords.emplace_back(hbir, startPads, constants::PADS_NLAYERS, startChips, 0, startHits, 0);
518 }
519 }
520 }
521}
522
523int RawDecoderSpec::filterIncompletePixelsEventsHBF(HBFData& data, const std::vector<int>& expectFEEs)
524{
525 auto same = [](const std::vector<int>& lhs, const std::vector<int>& rhs) -> bool {
526 bool missing = false;
527 for (auto entry : lhs) {
528 if (std::find(rhs.begin(), rhs.end(), entry) == rhs.end()) {
529 missing = true;
530 break;
531 }
532 }
533 if (!missing) {
534 for (auto entry : rhs) {
535 if (std::find(lhs.begin(), lhs.end(), entry) == lhs.end()) {
536 missing = true;
537 break;
538 }
539 }
540 }
541 return missing;
542 };
543 std::vector<int> indexIncomplete;
544 for (auto index = 0; index < data.mFEEs.size(); index++) {
545 if (data.mFEEs[index].size() != expectFEEs.size()) {
546 indexIncomplete.emplace_back(index);
547 continue;
548 }
549 if (!same(data.mFEEs[index], expectFEEs)) {
550 indexIncomplete.emplace_back(index);
551 }
552 }
553 if (indexIncomplete.size()) {
554 std::sort(indexIncomplete.begin(), indexIncomplete.end(), std::less<>());
555 // start removing from the end, since erase will impact the indexing
556 for (auto indexIter = indexIncomplete.rbegin(); indexIter != indexIncomplete.rend(); indexIter++) {
557 auto iterPixelEvent = data.mPixelEvent.begin() + *indexIter;
558 auto iterTrigger = data.mPixelTriggers.begin() + *indexIter;
559 auto iterFEEs = data.mFEEs.begin() + *indexIter;
560 data.mPixelEvent.erase(iterPixelEvent);
561 data.mPixelTriggers.erase(iterTrigger);
562 data.mFEEs.erase(iterFEEs);
563 }
564 }
565 return indexIncomplete.size();
566}
567
568bool RawDecoderSpec::consistencyCheckPixelFEE(const std::unordered_map<int, int>& counters) const
569{
570 bool initialized = false;
571 bool discrepancy = false;
572 int current = -1;
573 for (auto& [fee, value] : counters) {
574 if (!initialized) {
575 current = value;
576 initialized = true;
577 }
578 if (value != current) {
579 discrepancy = true;
580 break;
581 }
582 }
583
584 return !discrepancy;
585}
586
587bool RawDecoderSpec::checkEventsHBFConsistency(const std::unordered_map<int, std::vector<int>>& counters) const
588{
589 bool initialized = false;
590 bool discrepancy = false;
591 std::vector<int> current;
592 for (auto& [fee, events] : counters) {
593 if (!initialized) {
594 current = events;
595 initialized = true;
596 }
597 if (events != current) {
598 discrepancy = true;
599 }
600 }
601 return !discrepancy;
602}
603
604int RawDecoderSpec::maxCounter(const std::unordered_map<int, int>& counters) const
605{
606 int maxCounter = 0;
607 for (auto& [fee, counter] : counters) {
608 if (counter > maxCounter) {
609 maxCounter = counter;
610 }
611 }
612
613 return maxCounter;
614}
615
616void RawDecoderSpec::printCounters(const std::unordered_map<int, int>& counters) const
617{
618 for (auto& [fee, counter] : counters) {
619 LOG(info) << " FEE 0x" << std::hex << fee << std::dec << ": " << counter << " counts ...";
620 }
621}
622
623void RawDecoderSpec::printEvents(const std::unordered_map<int, std::vector<int>>& counters) const
624{
625 for (auto& [fee, events] : counters) {
626 std::stringstream stringbuilder;
627 bool first = true;
628 for (auto ev : events) {
629 if (first) {
630 first = false;
631 } else {
632 stringbuilder << ", ";
633 }
634 stringbuilder << ev;
635 }
636 LOG(info) << " FEE 0x" << std::hex << fee << std::dec << ": " << stringbuilder.str() << " events ...";
637 }
638}
639
640void RawDecoderSpec::fillPixelEventHBFCount(const std::unordered_map<int, std::vector<int>>& counters)
641{
642 // take FEE with the max number of events - expecting other FEEs might miss events
643 int maxFEE = 0;
644 int current = -1;
645 for (auto& [fee, events] : counters) {
646 int sum = 0;
647 for (auto ev : events) {
648 sum += ev;
649 }
650 if (sum > current) {
651 maxFEE = fee;
652 current = sum;
653 }
654 }
655 auto en = counters.find(maxFEE);
656 if (en != counters.end()) {
657 for (auto nEventsPixels : en->second) {
658 auto found = mNumEventsHBFPixels.find(nEventsPixels);
659 if (found != mNumEventsHBFPixels.end()) {
660 found->second += 1;
661 } else {
662 mNumEventsHBFPixels.insert(std::pair<int, int>{nEventsPixels, 1});
663 }
664 }
665 }
666}
667
668o2::framework::DataProcessorSpec o2::focal::reco_workflow::getRawDecoderSpec(bool askDISTSTF, uint32_t outputSubspec, bool usePadData, bool usePixelData, bool debugMode)
669{
670 constexpr auto originFOC = o2::header::gDataOriginFOC;
671 std::vector<o2::framework::OutputSpec> outputs;
672
673 outputs.emplace_back(originFOC, "PADLAYERS", outputSubspec, o2::framework::Lifetime::Timeframe);
674 outputs.emplace_back(originFOC, "PIXELHITS", outputSubspec, o2::framework::Lifetime::Timeframe);
675 outputs.emplace_back(originFOC, "PIXELCHIPS", outputSubspec, o2::framework::Lifetime::Timeframe);
676 outputs.emplace_back(originFOC, "TRIGGERS", outputSubspec, o2::framework::Lifetime::Timeframe);
677
678 std::vector<o2::framework::InputSpec> inputs{{"stf", o2::framework::ConcreteDataTypeMatcher{originFOC, o2::header::gDataDescriptionRawData}, o2::framework::Lifetime::Timeframe}};
679 if (askDISTSTF) {
680 inputs.emplace_back("stdDist", "FLP", "DISTSUBTIMEFRAME", 0, o2::framework::Lifetime::Timeframe);
681 }
682
683 return o2::framework::DataProcessorSpec{"FOCALRawDecoderSpec",
684 inputs,
685 outputs,
686 o2::framework::adaptFromTask<o2::focal::reco_workflow::RawDecoderSpec>(outputSubspec, usePadData, usePixelData, debugMode),
688 {"filterIncomplete", o2::framework::VariantType::Bool, false, {"Filter incomplete pixel events"}},
689 {"displayInconsistent", o2::framework::VariantType::Bool, false, {"Display information about inconsistent timeframes"}},
690 {"pixeltype", o2::framework::VariantType::String, "OB", {"Pixel mapping type"}},
691 {"pixelmapping", o2::framework::VariantType::String, "default", {"File with pixel mapping"}}}};
692}
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
uint64_t bc
Definition RawEventData.h:5
A helper class to iteratate over all parts of all input routes.
uint8_t endpoint
Definition RawData.h:0
uint32_t res
Definition RawData.h:0
std::ostringstream debug
const PadData & getData() const
Definition PadDecoder.h:37
void decodeEvent(gsl::span< const PadGBTWord > padpayload)
void decodeEvent(gsl::span< const o2::itsmft::GBTWord > payload)
const std::vector< PixelChip > & getChips() const
Definition Event.h:85
void addChip(const PixelChip &chip)
Definition Event.cxx:262
void endOfStream(o2::framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void init(framework::InitContext &ctx) final
void run(framework::ProcessingContext &ctx) final
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
A helper class to iteratate over all parts of all input routes.
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint entry
Definition glcorearb.h:5735
GLint GLint GLsizei GLuint * counters
Definition glcorearb.h:3985
GLuint index
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLboolean * data
Definition glcorearb.h:298
GLuint counter
Definition glcorearb.h:3987
constexpr o2::header::DataOrigin gDataOriginFOC
Definition DataHeader.h:583
constexpr o2::header::DataDescription gDataDescriptionRawData
Definition DataHeader.h:597
constexpr int PADLAYER_MODULE_NCHANNELS
Definition Constants.h:16
constexpr int PADLAYER_MODULE_NHALVES
Definition Constants.h:17
constexpr int PIXELS_NLAYERS
Definition Constants.h:19
constexpr int PADLAYER_WINDOW_LENGTH
Definition Constants.h:20
constexpr int PADS_NLAYERS
Definition Constants.h:18
framework::DataProcessorSpec getRawDecoderSpec(bool askDISTSTF, uint32_t outputSubspec, bool usePadData, bool usePixelData, bool debugMode)
std::vector< ConfigParamSpec > Options
D const SVectorGPU< T, D > & rhs
Definition SMatrixGPU.h:191
constexpr uint32_t HB
Definition Triggers.h:27
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
std::vector< PixelHit > mHits
Definition PixelChip.h:33
static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef &ref)
static void printRDH(const RDHv4 &rdh)
Definition RDHUtils.cxx:26
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"