Project
Loading...
Searching...
No Matches
RawToDigitsSpec.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.
11
18
19#include <random>
20#include <iostream>
21#include <fstream>
22#include <stdexcept>
23#include <array>
24#include <functional>
25#include <vector>
26#include <algorithm>
27
30
31#include "TTree.h"
32#include "TFile.h"
33
34#include <gsl/span>
35
36#include "Framework/InputSpec.h"
41#include "Framework/Lifetime.h"
42#include "Framework/Output.h"
43#include "Framework/Task.h"
45#include "Framework/Logger.h"
47
51
53
56#include "HMPIDBase/Geo.h"
59
60namespace o2
61{
62namespace hmpid
63{
64
65using namespace o2;
66using namespace o2::framework;
68using namespace o2::hmpid::raw;
69
70//=======================
71// Data decoder
73{
74 LOG(info) << "[HMPID Write Root File From Raw Files - init()]";
75
76 // get line command options
77 mOutRootFileName = ic.options().get<std::string>("out-file");
78 mBaseFileName = ic.options().get<std::string>("base-file");
79 mInputRawFileName = ic.options().get<std::string>("in-file");
80 mFastAlgorithm = ic.options().get<bool>("fast-decode");
81 mDigitsReceived = 0;
82 mFramesReceived = 0;
83
87 mReader.addFile(mInputRawFileName);
88 mReader.init();
89
91 mDecod->init();
92
93 mExTimer.start();
94 return;
95}
96
98{
99 bool isInLoop = true;
100 int tfID;
101 std::vector<char> dataBuffer; // where to put extracted data
102
103 if (mReader.getNTimeFrames() == 0) {
104 parseNoTF();
105 isInLoop = false;
106 }
107
108 while (isInLoop) {
109 tfID = mReader.getNextTFToRead();
110 if (tfID >= mReader.getNTimeFrames()) {
111 LOG(info) << "nothing left to read after " << tfID << " TFs read";
112 break;
113 }
114 for (int il = 0; il < mReader.getNLinks(); il++) {
115 auto& link = mReader.getLink(il);
116 LOG(info) << "Decoding link " << il;
117 auto sz = link.getNextTFSize(); // size in char needed for the next TF of this link
118 dataBuffer.resize(sz);
119 link.readNextTF(dataBuffer.data());
120 link.rewindToTF(tfID);
121 int nhbf = link.getNHBFinTF();
122 LOG(debug) << " Number of HBF " << nhbf;
123 for (int ib = 0; ib < nhbf; ib++) {
124 auto zs = link.getNextHBFSize(); // size in char needed for the next TF of this link
125 dataBuffer.resize(zs);
126 link.readNextHBF(dataBuffer.data());
127 // Parse
128 uint32_t* ptrBuffer = (uint32_t*)dataBuffer.data();
129 uint32_t* ptrBufferEnd = ptrBuffer + zs / 4;
130 mDecod->setUpStream(ptrBuffer, zs);
131 while (ptrBuffer < ptrBufferEnd) {
132 try {
133 if (mFastAlgorithm) {
134 mDecod->decodePageFast(&ptrBuffer);
135 } else {
136 mDecod->decodePage(&ptrBuffer);
137 }
138 } catch (int e) {
139 // The stream end !
140 LOG(debug) << "End Page decoding !";
141 }
142 int first = mAccumulateDigits.size();
143 mAccumulateDigits.insert(mAccumulateDigits.end(), mDecod->mDigits.begin(), mDecod->mDigits.end());
144 int last = mAccumulateDigits.size();
145 if (last > first) {
146 mEvents.emplace_back(o2::hmpid::Trigger{mDecod->mIntReco, first, last - first});
147 mDigitsReceived += mDecod->mDigits.size();
148 }
149 mFramesReceived++;
150 LOG(debug) << "run() Digits received =" << mDigitsReceived << " frames = " << mFramesReceived << " size=" << sz << " F-L " << first << "," << last << " " << mDecod->mIntReco;
151 mDecod->mDigits.clear();
152 }
153 }
154 }
155 mReader.setNextTFToRead(++tfID);
156 }
157 mTotalDigits += mDigitsReceived;
158 mTotalFrames += mFramesReceived;
159
160 mExTimer.logMes("End of Decoding ! Digits = " + std::to_string(mTotalDigits) + " Frames received = " + std::to_string(mTotalFrames));
161
162 writeResults();
163
164 // pc.services().get<ControlService>().endOfStream();
166 mExTimer.stop();
167 return;
168}
169
171{
172 mExTimer.logMes("Received an End Of Stream !");
173 return;
174}
175
176void RawToDigitsTask::parseNoTF()
177{
178 std::vector<char> dataBuffer; // where to put extracted data
179
180 for (int il = 0; il < mReader.getNLinks(); il++) {
181 auto& link = mReader.getLink(il);
182 LOG(info) << "Decoding link " << il;
183 auto sz = link.getNextTFSize(); // size in char needed for the next TF of this link
184 LOG(info) << " Size TF " << sz;
185 dataBuffer.resize(sz);
186 link.readNextTF(dataBuffer.data());
187
188 uint32_t* ptrBuffer = (uint32_t*)dataBuffer.data();
189 uint32_t* ptrBufferEnd = ptrBuffer + sz / 4;
190 mDecod->setUpStream(ptrBuffer, sz);
191 while (ptrBuffer < ptrBufferEnd) {
192 try {
193 if (mFastAlgorithm) {
194 mDecod->decodePageFast(&ptrBuffer);
195 } else {
196 mDecod->decodePage(&ptrBuffer);
197 }
198 } catch (int e) {
199 // The stream end !
200 LOG(debug) << "End Fast Page decoding !";
201 }
202 int first = mAccumulateDigits.size();
203 mAccumulateDigits.insert(mAccumulateDigits.end(), mDecod->mDigits.begin(), mDecod->mDigits.end());
204 int last = mAccumulateDigits.size();
205 if (last > first) {
206 mEvents.emplace_back(mDecod->mIntReco, first, last - first);
207 mDigitsReceived += mDecod->mDigits.size();
208 }
209 mFramesReceived++;
210 LOG(info) << "run() Digits received =" << mDigitsReceived << " frames = " << mFramesReceived << " size=" << sz << " F-L " << first << "," << last << " " << mDecod->mIntReco;
211 mDecod->mDigits.clear();
212 }
213 }
214 return;
215}
216
217void RawToDigitsTask::writeResults()
218{
219 int numEqui = mDecod->getNumberOfEquipments(); // Update the Stat for the Decoding
220 for (int i = 0; i < numEqui; i++) {
221 if (mDecod->mTheEquipments[i]->mNumberOfEvents > 0) {
222 mDecod->updateStatistics(mDecod->mTheEquipments[i]);
223 }
224 }
225 if (mEvents.size() == 0) { // check if no evwnts
226 LOG(info) << "There are not Event recorded ! Abort. ";
227 mExTimer.stop();
228 return;
229 }
230 for (int i = mEvents.size() - 1; i >= 0; i--) { // remove events that are (0,0) trigger
231 if (mEvents[i].getTriggerID() == 0) {
232 mEvents.erase(mEvents.begin() + i);
233 }
234 }
235 sort(mEvents.begin(), mEvents.end()); // sort the events
236 mExTimer.logMes("Sorted Events = " + std::to_string(mEvents.size()));
237
238 // ---------- ROOT file version 2 ---------------
239 TString filename;
240 TString tit;
241
242 std::vector<o2::hmpid::Digit> digitVec;
243 std::vector<o2::hmpid::Trigger> eventVec;
244
245 filename = TString::Format("%s", mOutRootFileName.c_str());
246 LOG(info) << "Create the ROOT file " << filename.Data();
247 TFile mfileOut(TString::Format("%s", filename.Data()), "RECREATE");
248 tit = TString::Format("HMPID Raw File Decoding");
249 TTree* theTree = new TTree("o2hmp", tit);
250
251 theTree->Branch("InteractionRecords", &eventVec);
252 theTree->Branch("HMPIDDigits", &digitVec);
253
254 // builds the two arranged vectors of objects
255 o2::hmpid::Trigger prevEvent = mEvents[0];
256 uint32_t theFirstDigit = 0;
257 uint32_t theLastDigit = 0;
258 for (int e = 0; e < mEvents.size(); e++) {
259 LOG(debug) << "Manage event " << mEvents[e];
260 if (prevEvent != mEvents[e]) { // changes the event Flush It
261 eventVec.emplace_back(o2::InteractionRecord(prevEvent.getBc(), prevEvent.getOrbit()), theFirstDigit, theLastDigit - theFirstDigit);
262 theFirstDigit = theLastDigit;
263 prevEvent = mEvents[e];
264 }
265 int first = mEvents[e].getFirstEntry();
266 int last = mEvents[e].getLastEntry();
267 for (int idx = first; idx <= last; idx++) {
268 digitVec.push_back(mAccumulateDigits[idx]);
269 theLastDigit++;
270 }
271 }
272 eventVec.emplace_back(o2::InteractionRecord(prevEvent.getBc(), prevEvent.getOrbit()), theFirstDigit, theLastDigit - theFirstDigit);
273 theTree->Fill();
274 theTree->Write();
275 mfileOut.Close();
276 mExTimer.logMes("Register Tree ! ");
277
278 // ---------- Records the statistics -----------------
279 float avgEventSize; //[o2::hmpid::Geo::MAXEQUIPMENTS];
280 float avgBusyTime; //[o2::hmpid::Geo::MAXEQUIPMENTS];
281 float numOfSamples; //[o2::hmpid::Geo::N_MODULES][o2::hmpid::Geo::N_YCOLS][o2::hmpid::Geo::N_XROWS];
282 float sumOfCharges; //[o2::hmpid::Geo::N_MODULES][o2::hmpid::Geo::N_YCOLS][o2::hmpid::Geo::N_XROWS];
283 float squareOfCharges; //[o2::hmpid::Geo::N_MODULES][o2::hmpid::Geo::N_YCOLS][o2::hmpid::Geo::N_XROWS];
284 float xb;
285 float yb;
286
287 filename = TString::Format("%s_stat.root", mBaseFileName.c_str());
288 LOG(info) << "Create the ROOT file " << filename.Data();
289 TFile mfileOutStat(TString::Format("%s", filename.Data()), "RECREATE");
290 TTree* theObj[Geo::N_MODULES + 1];
291 for (int i = 0; i < Geo::N_MODULES; i++) { // Create the TTree array
292 tit = TString::Format("HMPID Data Decoding Statistic results Mod=%d", i);
293 theObj[i] = new TTree("o2hmp", tit);
294 theObj[i]->Branch("x", &xb, "s");
295 theObj[i]->Branch("y", &yb, "s");
296 theObj[i]->Branch("Samples", &numOfSamples, "i");
297 theObj[i]->Branch("Sum_of_charges", &sumOfCharges, "l");
298 theObj[i]->Branch("Sum_of_square", &squareOfCharges, "l");
299 }
300 theObj[Geo::N_MODULES] = new TTree("o2hmp", "HMPID Data Decoding Statistic results");
301 theObj[Geo::N_MODULES]->Branch("Average_Event_Size", &avgEventSize, "F");
302 theObj[Geo::N_MODULES]->Branch("Average_Busy_Time", &avgBusyTime, "F");
303
304 char summaryFileName[254];
305 snprintf(summaryFileName, 254, "%s_stat.txt", mBaseFileName.c_str());
306 mDecod->writeSummaryFile(summaryFileName);
307 for (int e = 0; e < numEqui; e++) {
308 avgEventSize = mDecod->getAverageEventSize(e);
309 avgBusyTime = mDecod->getAverageBusyTime(e);
310 theObj[Geo::N_MODULES]->Fill();
311 }
312 for (int m = 0; m < o2::hmpid::Geo::N_MODULES; m++) {
313 for (int y = 0; y < o2::hmpid::Geo::N_YCOLS; y++) {
314 for (int x = 0; x < o2::hmpid::Geo::N_XROWS; x++) {
315 xb = x;
316 yb = y;
317 numOfSamples = mDecod->getPadSamples(m, x, y);
318 sumOfCharges = mDecod->getPadSum(m, x, y);
319 squareOfCharges = mDecod->getPadSquares(m, x, y);
320 theObj[m]->Fill();
321 }
322 }
323 }
324 for (int i = 0; i <= Geo::N_MODULES; i++) {
325 theObj[i]->Write();
326 }
327
328 mExTimer.logMes("End storing results ! Digits = " + std::to_string(mTotalDigits) + " Frames received = " + std::to_string(mTotalFrames));
329 return;
330}
331
332//_________________________________________________________________________________________________
334{
335 std::vector<o2::framework::InputSpec> inputs;
336 std::vector<o2::framework::OutputSpec> outputs;
337
338 return DataProcessorSpec{
339 "HMP-RawToDigits",
340 inputs,
341 outputs,
342 AlgorithmSpec{adaptFromTask<RawToDigitsTask>()},
343 Options{{"in-file", VariantType::String, "hmpidRaw.raw", {"name of the input Raw file"}},
344 {"fast-decode", VariantType::Bool, false, {"Use the fast algorithm. (error 0.8%)"}},
345 {"out-file", VariantType::String, "hmpReco.root", {"name of the output file"}},
346 {"base-file", VariantType::String, "hmpDecode", {"base name for statistical output file"}}}};
347}
348
349} // namespace hmpid
350} // end namespace o2
A raw page parser for DPL input.
std::ostringstream debug
int32_t i
A helper class to iteratate over all parts of all input routes.
Configurable generator for RootTreeWriter processor spec.
Definition of the RAW Data Header.
Reader for (multiple) raw data files.
ConfigParamRegistry const & options()
Definition InitContext.h:33
ServiceRegistryRef services()
The services registry associated with this processing context.
void stop()
stop : stops the timer
Definition Common.h:73
void start()
start : starts the timer
Definition Common.h:64
void logMes(std::string const message)
Definition Common.h:81
static constexpr int N_XROWS
Definition Geo.h:88
static constexpr int N_MODULES
Definition Geo.h:87
static constexpr int N_YCOLS
Definition Geo.h:89
static constexpr int MAXEQUIPMENTS
Definition Geo.h:79
float getAverageEventSize(int Equipment)
void decodePageFast(uint32_t **streamBuf)
void init()
Init all the members variables.
std::vector< o2::hmpid::Digit > mDigits
void decodePage(uint32_t **streamBuffer)
o2::InteractionRecord mIntReco
bool setUpStream(void *Buffer, long BufferLen)
void writeSummaryFile(char *summaryFileName)
double getPadSum(int Module, int Row, int Column)
HmpidEquipment * mTheEquipments[Geo::MAXEQUIPMENTS]
uint16_t getPadSamples(int Module, int Row, int Column)
void updateStatistics(HmpidEquipment *eq)
float getAverageBusyTime(int Equipment)
double getPadSquares(int Module, int Row, int Column)
void init(framework::InitContext &ic) final
void endOfStream(framework::EndOfStreamContext &ec) override
This is invoked whenever we have an EndOfStream event.
void run(framework::ProcessingContext &pc) final
HMPID Trigger declaration.
Definition Trigger.h:32
uint16_t getBc() const
Definition Trigger.h:44
uint32_t getOrbit() const
Definition Trigger.h:43
uint32_t getNextTFToRead() const
void setNextTFToRead(uint32_t tf)
void setDefaultDataDescription(const std::string &desc)
void setDefaultDataOrigin(const std::string &orig)
uint32_t getNTimeFrames() const
const LinkData & getLink(int i) const
void setDefaultReadoutCardType(ReadoutCardType t=CRU)
bool addFile(const std::string &sname, o2::header::DataOrigin origin, o2::header::DataDescription desc, ReadoutCardType t=CRU)
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLint first
Definition glcorearb.h:399
GLint y
Definition glcorearb.h:270
constexpr o2::header::DataOrigin gDataOriginHMP
Definition DataHeader.h:569
constexpr o2::header::DataDescription gDataDescriptionRawData
Definition DataHeader.h:598
Defining PrimaryVertex explicitly as messageable.
@ Me
Only quit this data processor.
std::vector< ConfigParamSpec > Options
o2::framework::DataProcessorSpec getRawToDigitsSpec(std::string inputSpec="HMP/RAWDATA")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::string filename()
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"