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.
11
12#include <string>
13#include <fairlogger/Logger.h>
24
25using namespace o2::ctp::reco_workflow;
26
28{
29 mDecodeinputs = ctx.options().get<bool>("ctpinputs-decoding");
30 mDecoder.setDecodeInps(mDecodeinputs);
31 mNTFToIntegrate = ctx.options().get<int>("ntf-to-average");
32 mVerbose = ctx.options().get<bool>("use-verbose-mode");
33 int maxerrors = ctx.options().get<int>("print-errors-num");
34 mDecoder.setVerbose(mVerbose);
35 mDecoder.setDoLumi(mDoLumi);
36 mDecoder.setDoDigits(mDoDigits);
37 mDecoder.setMAXErrors(maxerrors);
38 std::string lumiinp1 = ctx.options().get<std::string>("lumi-inp1");
39 std::string lumiinp2 = ctx.options().get<std::string>("lumi-inp2");
40 int inp1 = mDecoder.setLumiInp(1, lumiinp1);
41 int inp2 = mDecoder.setLumiInp(2, lumiinp2);
42 mOutputLumiInfo.inp1 = inp1;
43 mOutputLumiInfo.inp2 = inp2;
44 mMaxInputSize = ctx.options().get<int>("max-input-size");
45 mMaxInputSizeFatal = ctx.options().get<bool>("max-input-size-fatal");
46 LOG(info) << "CTP reco init done. Inputs decoding here:" << mDecodeinputs << " DoLumi:" << mDoLumi << " DoDigits:" << mDoDigits << " NTF:" << mNTFToIntegrate << " Lumi inputs:" << lumiinp1 << ":" << inp1 << " " << lumiinp2 << ":" << inp2 << " Max errors:" << maxerrors << " Max input size:" << mMaxInputSize << " MaxInputSizeFatal:" << mMaxInputSizeFatal;
47 // mOutputLumiInfo.printInputs();
48}
50{
51 auto& TFOrbits = mDecoder.getTFOrbits();
52 std::sort(TFOrbits.begin(), TFOrbits.end());
53 size_t l = TFOrbits.size();
54 uint32_t o0 = 0;
55 if (l) {
56 o0 = TFOrbits[0];
57 }
58 int nmiss = 0;
59 int nprt = 0;
60 std::cout << "Missing orbits:";
61 for (int i = 1; i < l; i++) {
62 if ((TFOrbits[i] - o0) > 0x20) {
63 if (nprt < 20) {
64 std::cout << " " << o0 << "-" << TFOrbits[i];
65 }
66 nmiss += (TFOrbits[i] - o0) / 0x20;
67 nprt++;
68 }
69 o0 = TFOrbits[i];
70 }
71 std::cout << std::endl;
72 LOG(info) << " Lost due to the shift:" << mDecoder.getLostDueToShift();
73 LOG(info) << "Number of missing TF:" << nmiss << std::endl;
74 if (mDecoder.getErrorIR() || mDecoder.getErrorTCR()) {
75 LOG(error) << "# of IR errors:" << mDecoder.getErrorIR() << " TCR errors:" << mDecoder.getErrorTCR() << std::endl;
76 }
77 std::array<uint64_t, o2::ctp::CTP_NCLASSES> clsA = mDecoder.getClassCountersA();
78 std::array<uint64_t, o2::ctp::CTP_NCLASSES> clsB = mDecoder.getClassCountersB();
79 std::array<uint64_t, o2::ctp::CTP_NCLASSES> clsEA = mDecoder.getClassErrorsA();
80 std::array<uint64_t, o2::ctp::CTP_NCLASSES> clsEB = mDecoder.getClassErrorsB();
81
82 for (int i = 0; i < o2::ctp::CTP_NCLASSES; i++) {
83 bool print = clsA[i] > 0 || clsB[i] > 0 || clsEA[i] > 0 || clsEB[i] > 0;
84 if (clsEA[i]) {
85 LOG(error) << " Class without inputs:";
86 }
87 LOG(important) << "CLASS:" << i << " Cls=>Inp:" << clsA[i] << " Inp=>Cls:" << clsB[i] << " ErrorsCls=>Inps:" << clsEA[i] << " MissingInps=>Cls:" << clsEB[i];
88 }
89}
91{
93 mOutputDigits.clear();
94 std::map<o2::InteractionRecord, CTPDigit> digits;
98 // setUpDummyLink
99 auto& inputs = ctx.inputs();
100 auto dummyOutput = [&ctx, this]() {
101 if (this->mDoDigits) {
102 ctx.outputs().snapshot(o2::framework::Output{"CTP", "DIGITS", 0}, this->mOutputDigits);
103 }
104 if (this->mDoLumi) {
105 ctx.outputs().snapshot(o2::framework::Output{"CTP", "LUMI", 0}, this->mOutputLumiInfo);
106 }
107 };
108 // if we see requested data type input with 0xDEADBEEF subspec and 0 payload this means that the "delayed message"
109 // mechanism created it in absence of real data from upstream. Processor should send empty output to not block the workflow
110 {
111 static size_t contDeadBeef = 0; // number of times 0xDEADBEEF was seen continuously
112 std::vector<InputSpec> dummy{InputSpec{"dummy", o2::framework::ConcreteDataMatcher{"CTP", "RAWDATA", 0xDEADBEEF}}};
113 for (const auto& ref : o2::framework::InputRecordWalker(inputs, dummy)) {
114 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
116 if (payloadSize == 0) {
118 if (++contDeadBeef <= maxWarn) {
119 LOGP(alarm, "Found input [{}/{}/{:#x}] TF#{} 1st_orbit:{} Payload {} : assuming no payload for all links in this TF{}",
120 dh->dataOrigin.str, dh->dataDescription.str, dh->subSpecification, dh->tfCounter, dh->firstTForbit, payloadSize,
121 contDeadBeef == maxWarn ? fmt::format(". {} such inputs in row received, stopping reporting", contDeadBeef) : "");
122 }
123 dummyOutput();
124 return;
125 }
126 }
127 contDeadBeef = 0; // if good data, reset the counter
128 }
129 //
130 std::vector<LumiInfo> lumiPointsHBF1;
131 std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{"CTP", "RAWDATA"}, Lifetime::Timeframe}};
132 bool fatal_flag = 0;
133 if (mMaxInputSize > 0) {
134 size_t payloadSize = 0;
135 for (const auto& ref : o2::framework::InputRecordWalker(inputs, filter)) {
136 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
138 }
139 if (payloadSize > (size_t)mMaxInputSize) {
140 if (mMaxInputSizeFatal) {
141 fatal_flag = 1;
142 LOG(error) << "Input data size bigger than threshold: " << mMaxInputSize << " < " << payloadSize << " decoding TF and exiting.";
143 // LOG(fatal) << "Input data size:" << payloadSize; - fatal issued in decoder
144 } else {
145 LOG(error) << "Input data size:" << payloadSize << " sending dummy output";
146 dummyOutput();
147 return;
148 }
149 }
150 }
151 int ret = 0;
152 if (fatal_flag) {
153 ret = mDecoder.decodeRawFatal(inputs, filter);
154 } else {
155 ret = mDecoder.decodeRaw(inputs, filter, mOutputDigits, lumiPointsHBF1);
156 }
157 if (ret == 1) {
158 dummyOutput();
159 return;
160 }
161 if (mDoDigits) {
162 LOG(info) << "[CTPRawToDigitConverter - run] Writing " << mOutputDigits.size() << " digits. IR rejected:" << mDecoder.getIRRejected() << " TCR rejected:" << mDecoder.getTCRRejected();
163 ctx.outputs().snapshot(o2::framework::Output{"CTP", "DIGITS", 0}, mOutputDigits);
164 }
165 if (mDoLumi) {
166 uint32_t tfCountsT = 0;
167 uint32_t tfCountsV = 0;
168 for (auto const& lp : lumiPointsHBF1) {
169 tfCountsT += lp.counts;
170 tfCountsV += lp.countsFV0;
171 }
172 // LOG(info) << "Lumi rate:" << tfCounts/(128.*88e-6);
173 // FT0
174 mHistoryT.push_back(tfCountsT);
175 mCountsT += tfCountsT;
176 if (mHistoryT.size() <= mNTFToIntegrate) {
177 mNHBIntegratedT += lumiPointsHBF1.size();
178 } else {
179 mCountsT -= mHistoryT.front();
180 mHistoryT.pop_front();
181 }
182 // FV0
183 mHistoryV.push_back(tfCountsV);
184 mCountsV += tfCountsV;
185 if (mHistoryV.size() <= mNTFToIntegrate) {
186 mNHBIntegratedV += lumiPointsHBF1.size();
187 } else {
188 mCountsV -= mHistoryV.front();
189 mHistoryV.pop_front();
190 }
191 //
192 if (mNHBIntegratedT || mNHBIntegratedV) {
193 mOutputLumiInfo.orbit = lumiPointsHBF1[0].orbit;
194 }
195 mOutputLumiInfo.counts = mCountsT;
196
197 mOutputLumiInfo.countsFV0 = mCountsV;
198 mOutputLumiInfo.nHBFCounted = mNHBIntegratedT;
199 mOutputLumiInfo.nHBFCountedFV0 = mNHBIntegratedV;
200 if (mVerbose) {
201 mOutputLumiInfo.printInputs();
202 LOGP(info, "Orbit {}: {}/{} counts inp1/inp2 in {}/{} HBFs -> lumi_inp1 = {:.3e}+-{:.3e} lumi_inp2 = {:.3e}+-{:.3e}", mOutputLumiInfo.orbit, mCountsT, mCountsV, mNHBIntegratedT, mNHBIntegratedV, mOutputLumiInfo.getLumi(), mOutputLumiInfo.getLumiError(), mOutputLumiInfo.getLumiFV0(), mOutputLumiInfo.getLumiFV0Error());
203 }
204 ctx.outputs().snapshot(o2::framework::Output{"CTP", "LUMI", 0}, mOutputLumiInfo);
205 }
206}
208{
209 if (!digits && !lumi) {
210 throw std::runtime_error("all outputs were disabled");
211 }
212 std::vector<o2::framework::InputSpec> inputs;
213 inputs.emplace_back("TF", o2::framework::ConcreteDataTypeMatcher{"CTP", "RAWDATA"}, o2::framework::Lifetime::Timeframe);
214 if (askDISTSTF) {
215 inputs.emplace_back("stdDist", "FLP", "DISTSUBTIMEFRAME", 0, o2::framework::Lifetime::Timeframe);
216 }
217
218 std::vector<o2::framework::OutputSpec> outputs;
219 inputs.emplace_back("ctpconfig", "CTP", "CTPCONFIG", 0, o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec("CTP/Config/Config", 1));
220 inputs.emplace_back("trigoffset", "CTP", "Trig_Offset", 0, o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec("CTP/Config/TriggerOffsets"));
221 if (digits) {
222 outputs.emplace_back("CTP", "DIGITS", 0, o2::framework::Lifetime::Timeframe);
223 }
224 if (lumi) {
225 outputs.emplace_back("CTP", "LUMI", 0, o2::framework::Lifetime::Timeframe);
226 }
228 "ctp-raw-decoder",
229 inputs,
230 outputs,
231 o2::framework::AlgorithmSpec{o2::framework::adaptFromTask<o2::ctp::reco_workflow::RawDecoderSpec>(digits, lumi)},
233 {"ntf-to-average", o2::framework::VariantType::Int, 90, {"Time interval for averaging luminosity in units of TF"}},
234 {"print-errors-num", o2::framework::VariantType::Int, 3, {"Max number of errors to print"}},
235 {"lumi-inp1", o2::framework::VariantType::String, "TVX", {"The first input used for online lumi. Name in capital."}},
236 {"lumi-inp2", o2::framework::VariantType::String, "VBA", {"The second input used for online lumi. Name in capital."}},
237 {"use-verbose-mode", o2::framework::VariantType::Bool, false, {"Verbose logging"}},
238 {"max-input-size", o2::framework::VariantType::Int, 0, {"Do not process input if bigger than max size, 0 - do not check"}},
239 {"max-input-size-fatal", o2::framework::VariantType::Bool, false, {"If true issue fatal error otherwise error on;y"}},
240 {"ctpinputs-decoding", o2::framework::VariantType::Bool, false, {"Inputs alignment: true - raw decoder - has to be compatible with CTF decoder: allowed options: 10,01,00"}}}};
241}
243{
245 pc.inputs().get<o2::ctp::TriggerOffsetsParam*>("trigoffset");
246 const auto& trigOffsParam = o2::ctp::TriggerOffsetsParam::Instance();
247 LOG(info) << "updateing TroggerOffsetsParam: inputs L0_L1:" << trigOffsParam.L0_L1 << " classes L0_L1:" << trigOffsParam.L0_L1_classes;
248 const auto ctpcfg = pc.inputs().get<o2::ctp::CTPConfiguration*>("ctpconfig");
249 if (ctpcfg != nullptr) {
250 mDecoder.setCTPConfig(*ctpcfg);
251 LOG(info) << "ctpconfig for run done:" << mDecoder.getCTPConfig().getRunNumber();
252 }
253 }
254}
definition of CTPConfiguration and related CTP structures
void print() const
int32_t i
A helper class to iteratate over all parts of all input routes.
std::array< uint64_t, o2::ctp::CTP_NCLASSES > getClassCountersA()
uint32_t getTCRRejected() const
std::array< uint64_t, o2::ctp::CTP_NCLASSES > getClassErrorsA()
std::array< uint64_t, o2::ctp::CTP_NCLASSES > getClassCountersB()
std::vector< uint32_t > & getTFOrbits()
void setCTPConfig(CTPConfiguration cfg)
int setLumiInp(int lumiinp, std::string inp)
void setDoDigits(bool digi)
int decodeRaw(o2::framework::InputRecord &inputs, std::vector< o2::framework::InputSpec > &filter, o2::pmr::vector< CTPDigit > &digits, std::vector< LumiInfo > &lumiPointsHBF1)
std::array< uint64_t, o2::ctp::CTP_NCLASSES > getClassErrorsB()
CTPConfiguration & getCTPConfig()
void setDecodeInps(bool decodeinps)
void setDoLumi(bool lumi)
int decodeRawFatal(o2::framework::InputRecord &inputs, std::vector< o2::framework::InputSpec > &filter)
uint32_t getIRRejected() const
void endOfStream(o2::framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void updateTimeDependentParams(framework::ProcessingContext &pc)
void init(framework::InitContext &ctx) final
Initializing the RawDecoderSpec.
void run(framework::ProcessingContext &ctx) final
Run conversion of raw data to cells.
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.
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
o2::framework::DataProcessorSpec getRawDecoderSpec(bool askSTFDist, bool digits, bool lumi)
Creating DataProcessorSpec for the CTP.
Lifetime
Possible Lifetime of objects being exchanged by the DPL.
Definition Lifetime.h:18
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
void printInputs() const
Definition LumiInfo.cxx:20
uint64_t countsFV0
Definition LumiInfo.h:29
uint64_t counts
Definition LumiInfo.h:28
uint32_t nHBFCounted
Definition LumiInfo.h:26
float getLumiFV0Error() const
Definition LumiInfo.h:36
uint32_t nHBFCountedFV0
Definition LumiInfo.h:27
float getLumiError() const
Definition LumiInfo.h:35
float getLumi() const
Definition LumiInfo.h:32
float getLumiFV0() const
Definition LumiInfo.h:33
uint32_t orbit
Definition LumiInfo.h:25
static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef &ref)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
LumiInfo lumi
std::vector< Digit > digits