Project
Loading...
Searching...
No Matches
test_cmv_generator.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
23
25#include "Framework/Task.h"
29#include "Framework/Logger.h"
30#include "Headers/DataHeader.h"
32#include "TPCBase/CRU.h"
33#include "DataFormatsTPC/CMV.h"
41#include <fmt/format.h>
42#include <fmt/ranges.h>
43
44#include <vector>
45#include <chrono>
46#include <thread>
47#include <cmath>
48#include <memory>
49#include <limits>
50#include <random>
51#include <stdexcept>
52#include <string>
53#include <unordered_set>
54
55using namespace o2::framework;
57
58// ─────────────────────────────────────────────────────────────────────────────
59// workflow options
60// ─────────────────────────────────────────────────────────────────────────────
61void customize(std::vector<ConfigParamSpec>& workflowOptions)
62{
63 const std::string cruDefault = "0-" + std::to_string(o2::tpc::CRU::MaxCRU - 1);
64 std::vector<ConfigParamSpec> options{
65 {"crus", VariantType::String, cruDefault.c_str(), {"List of CRUs, comma-separated ranges, e.g. 0-3,7,9-15"}},
66 {"timeframes", VariantType::Int, 100, {"Number of TFs to generate; use -1 to run indefinitely"}},
67 {"delay", VariantType::Bool, false, {"Add delay after sending all CRUs"}},
68 {"delayTime", VariantType::Int, 1, {"Duration of the global per-TF delay in ms (requires --delay true)"}},
69 {"delayEveryN", VariantType::Int, 1, {"Apply the global delay only on average once every N TFs, randomly chosen (1 = every TF, requires --delay true)"}},
70 {"delayCRUs", VariantType::String, "", {"CRUs for which to add an extra per-CRU delay before sending, comma-separated ranges"}},
71 {"delayTimeCRUs", VariantType::Int, 1, {"Duration of the per-CRU delay in ms (requires --delayCRUs)"}},
72 {"dropTFsRandom", VariantType::Int, 0, {"Drop a whole TF randomly: on average one every N TFs (0 = disabled)"}},
73 {"dropTFsRange", VariantType::String, "", {"Drop all TFs in this range, e.g. 10-12"}},
74 {"tfLength", VariantType::Float, 0.f, {"Minimum wall-clock time between consecutively sent TFs in ms (rate limiter); the generator sleeps if a TF is produced faster than this (0 = disabled)"}},
75 {"seed", VariantType::Int, 42, {"RNG seed for CMV value generation"}},
76 {"amplitude", VariantType::Float, 5.0f, {"Amplitude of the sinusoidal CMV signal (ADC units); ignored when --input-file is set"}},
77 {"noise", VariantType::Float, 1.0f, {"Gaussian noise std-dev added per time bin (ADC units); used as the smearing width in --input-file mode"}},
78 {"input-file", VariantType::String, "", {"ROOT file with a CMV 'ccdb_object' tree; the template TF (see --input-entry) is decoded once and re-emitted, smeared per generated TF. Empty = synthetic sinusoidal signal"}},
79 {"input-entry", VariantType::Int, 0, {"Tree entry (TF index) used as the template when --input-file is set"}},
80 {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}};
82 std::swap(workflowOptions, options);
83}
84
86
87// ─────────────────────────────────────────────────────────────────────────────
88// generator device
89// ─────────────────────────────────────────────────────────────────────────────
91{
92 public:
93 static constexpr uint32_t sOrbitsPerPacket = 8;
94
95 CMVGeneratorDevice(const std::vector<uint32_t>& crus,
96 const std::unordered_set<uint32_t>& delayCRUs,
97 unsigned int maxTFs,
98 bool delay,
99 int delayTime,
100 int delayEveryN,
101 int delayTimeCRUs,
102 int dropTFsRandom,
103 const std::vector<int>& rangeTFsDrop,
104 float tfLength,
105 float amplitude,
106 float noise,
107 int seed,
108 const std::string& inputFile,
109 long long inputEntry)
110 : mCRUs(crus), mDelayCRUs(delayCRUs), mMaxTFs(maxTFs), mDelay(delay), mDelayTime(delayTime), mDelayEveryN(delayEveryN), mDelayTimeCRUs(delayTimeCRUs), mDropTFsRandom(dropTFsRandom), mRangeTFsDrop(rangeTFsDrop), mTFLength(tfLength), mAmplitude(amplitude), mNoise(noise), mRng(static_cast<std::mt19937::result_type>(seed)), mInputFileName(inputFile), mInputEntry(inputEntry) {}
111
113 {
114 mTimer100TFs = std::chrono::high_resolution_clock::now();
115 mLastTFTime = std::chrono::high_resolution_clock::now();
116
117 if (!mCRUs.empty()) {
118 LOGP(info, "crus: {}", fmt::join(mCRUs, ", "));
119 }
120 if (!mDelayCRUs.empty()) {
121 const std::vector<uint32_t> delayCRUsSorted(mDelayCRUs.begin(), mDelayCRUs.end());
122 LOGP(info, "delayCRUs: {}", fmt::join(delayCRUsSorted, ", "));
123 }
124
125 mWriteDebug = ic.options().get<bool>("write-debug");
126 if (mWriteDebug) {
127 mDebugStreamFileName = ic.options().get<std::string>("debug-file-name");
128 LOGP(info, "Creating debug stream {}", mDebugStreamFileName);
129 mDebugStream = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugStreamFileName.data(), "recreate");
130 }
131
132 if (!mInputFileName.empty()) {
134 if (!handle.open(mInputFileName)) {
135 throw std::runtime_error("CMV generator: failed to open input file " + mInputFileName);
136 }
137 const auto nEntries = handle.tree->GetEntries();
138 if (mInputEntry < 0 || mInputEntry >= nEntries) {
139 const auto msg = fmt::format("CMV generator: --input-entry {} out of range [0, {}) in {}", mInputEntry, nEntries, mInputFileName);
140 handle.close();
141 throw std::runtime_error(msg);
142 }
143 const o2::tpc::CMVPerTF* tmpl = handle.getEntry(mInputEntry);
144 if (!tmpl) {
145 handle.close();
146 throw std::runtime_error("CMV generator: failed to read/decode entry from " + mInputFileName);
147 }
148 // When noise is enabled we keep the per-CRU float template and re-encode it
149 // (template + noise) every TF. When noise is disabled the output is identical
150 // for every TF, so we encode it once here and just re-snapshot it in run().
151 const bool addNoise = (mNoise > 0.f);
152 if (addNoise) {
153 mBaseCMVFloat.resize(mCRUs.size());
154 for (size_t iCRU = 0; iCRU < mCRUs.size(); ++iCRU) {
155 const auto cru = mCRUs[iCRU];
156 auto& base = mBaseCMVFloat[iCRU];
157 base.resize(o2::tpc::cmv::NTimeBinsPerTF);
158 for (uint32_t tb = 0; tb < o2::tpc::cmv::NTimeBinsPerTF; ++tb) {
159 base[tb] = tmpl->getCMVFloat(static_cast<int>(cru), static_cast<int>(tb));
160 }
161 }
162 } else {
163 mBaseCMVEncoded.resize(mCRUs.size());
164 for (size_t iCRU = 0; iCRU < mCRUs.size(); ++iCRU) {
165 const auto cru = mCRUs[iCRU];
166 auto& enc = mBaseCMVEncoded[iCRU];
167 enc.resize(o2::tpc::cmv::NTimeBinsPerTF);
168 for (uint32_t tb = 0; tb < o2::tpc::cmv::NTimeBinsPerTF; ++tb) {
170 d.setCMVFloat(tmpl->getCMVFloat(static_cast<int>(cru), static_cast<int>(tb)));
171 enc[tb] = d.getCMV();
172 }
173 }
174 }
175 handle.close();
176 mUseInputFile = true;
177 LOGP(info, "Loaded CMV template from {} (entry {}): {} CRUs x {} bins, noise sigma {} ADC ({})",
178 mInputFileName, mInputEntry, mCRUs.size(), o2::tpc::cmv::NTimeBinsPerTF, mNoise,
179 addNoise ? "re-smeared per TF" : "encoded once, replayed verbatim");
180 }
181 }
182
184 {
185 using timer = std::chrono::high_resolution_clock;
187
188 // ── TF dropping ──────────────────────────────────────────────────────────
189 // Note: RangeTokenizer guarantees sorted output, so front()/back() are min/max.
190 if (!mRangeTFsDrop.empty() && tf >= static_cast<uint32_t>(mRangeTFsDrop.front()) && tf <= static_cast<uint32_t>(mRangeTFsDrop.back())) {
191 LOGP(info, "Dropping TF {} (range drop)", tf);
192 return;
193 }
194 if (mDropTFsRandom > 0 && std::uniform_int_distribution<int>{0, mDropTFsRandom - 1}(mRng) == 0) {
195 LOGP(info, "Dropping TF {} (random drop)", tf);
196 return;
197 }
198
199 auto start = timer::now();
200
201 // ── CMV values ───────────────────────────────────────────────────────────
202 // NTimeBinsPerTF = NPacketsPerTFPerCRU (4) * NTimeBinsPerPacket (3564) = 14256
203 // - synthetic mode: shared cmvVec = sinusoidal signal + noise (same for all CRUs)
204 // - input-file mode: per-CRU template + the shared noise vector
205 const bool addNoise = (mNoise > 0.f); // skip all RNG when --noise 0
206 std::normal_distribution<float> noiseDist{0.f, mNoise};
207 std::vector<uint16_t> cmvVec(o2::tpc::cmv::NTimeBinsPerTF);
208 std::vector<float> noiseVec; // only populated in input-file mode when noise is enabled
209 if (mUseInputFile) {
210 if (addNoise) {
211 noiseVec.resize(o2::tpc::cmv::NTimeBinsPerTF);
212 for (auto& n : noiseVec) {
213 n = noiseDist(mRng);
214 }
215 }
216 } else {
217 const float signal = -std::abs(mAmplitude * std::sin(tf * 0.05f));
218 for (auto& v : cmvVec) {
220 d.setCMVFloat(addNoise ? (signal + noiseDist(mRng)) : signal);
221 v = d.getCMV();
222 }
223 }
224
225 // ── Orbit / BC info (same for all CRUs) ──────────────────────────────────
226 // One packed (orbit<<32|bc) entry per CMV packet (4 per TF).
227 // Each packet covers 8 heartbeat orbits (NTimeBinsPerPacket = 3564 = 8 LHC orbits),
228 // so the orbit advances by 8 per packet and by NPacketsPerTFPerCRU*8 = 32 per TF.
229 std::vector<uint64_t> orbitBCVec(o2::tpc::cmv::NPacketsPerTFPerCRU);
230 for (uint32_t pkt = 0; pkt < o2::tpc::cmv::NPacketsPerTFPerCRU; ++pkt) {
231 const uint32_t orbit = static_cast<uint32_t>(tf * o2::tpc::cmv::NPacketsPerTFPerCRU * sOrbitsPerPacket + pkt * sOrbitsPerPacket);
232 orbitBCVec[pkt] = uint64_t(orbit) << 32; // bc = 0
233 }
234
235 for (size_t iCRU = 0; iCRU < mCRUs.size(); ++iCRU) {
236 const auto cru = mCRUs[iCRU];
237 const o2::header::DataHeader::SubSpecificationType subSpec{cru << 7};
238
239 // ── per-CRU delay ────────────────────────────────────────────────────
240 if (mDelayCRUs.count(cru)) {
241 LOGP(info, "Delaying CRU {} by {} ms (TF {})", cru, mDelayTimeCRUs, tf);
242 std::this_thread::sleep_for(std::chrono::milliseconds(mDelayTimeCRUs));
243 }
244
245 // Select the vector to emit: the precomputed template (no noise) is sent
246 // verbatim; otherwise this CRU's template is smeared with the shared noise.
247 std::vector<uint16_t>* out = &cmvVec;
248 if (mUseInputFile && !addNoise) {
249 out = &mBaseCMVEncoded[iCRU]; // encoded once in init(), reused every TF
250 } else if (mUseInputFile) {
251 const auto& base = mBaseCMVFloat[iCRU];
252 for (uint32_t tb = 0; tb < o2::tpc::cmv::NTimeBinsPerTF; ++tb) {
254 d.setCMVFloat(base[tb] + noiseVec[tb]);
255 cmvVec[tb] = d.getCMV();
256 }
257 }
258
259 ctx.outputs().snapshot(Output{gDataOriginTPC, "CMVVECTOR", subSpec}, *out);
260 ctx.outputs().snapshot(Output{gDataOriginTPC, "CMVORBITS", subSpec}, orbitBCVec);
261
262 if (mWriteDebug) {
263 auto& stream = (*mDebugStream) << "cmvs";
264 stream << "cru=" << cru
265 << "tfCounter=" << tf
266 << "nCMVs=" << out->size()
267 << "cmvs=" << *out
268 << "\n";
269 }
270 }
271
272 if (!(tf % 100)) {
273 const auto elapsed100 = std::chrono::duration_cast<std::chrono::milliseconds>(timer::now() - mTimer100TFs).count();
274 LOGP(info, "Generated CMV data for TF {} ({} ms for last 100 TFs)", tf, elapsed100);
275 mTimer100TFs = timer::now();
276 }
277
278 // ── global delay ─────────────────────────────────────────────────────────
279 if (mDelay && (mDelayEveryN <= 1 || std::uniform_int_distribution<int>{0, mDelayEveryN - 1}(mRng) == 0)) {
280 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(timer::now() - start).count();
281 if (elapsed < mDelayTime) {
282 LOGP(info, "Delaying TF {} by {} ms", tf, mDelayTime - elapsed);
283 std::this_thread::sleep_for(std::chrono::milliseconds(mDelayTime - elapsed));
284 }
285 }
286
287 // ── rate limiting ────────────────────────────────────────────────────────
288 // Enforce a minimum wall-clock spacing between consecutively sent TFs.
289 if (mTFLength > 0.f) {
290 const auto elapsedSinceLast = std::chrono::duration_cast<std::chrono::microseconds>(timer::now() - mLastTFTime).count();
291 const auto tfLengthUs = static_cast<int64_t>(mTFLength * 1000.f);
292 if (elapsedSinceLast < tfLengthUs) {
293 const auto waitUs = tfLengthUs - elapsedSinceLast;
294 LOGP(info, "Rate limiting TF {}: waiting {} us (tfLength={} ms)", tf, waitUs, mTFLength);
295 std::this_thread::sleep_for(std::chrono::microseconds(waitUs));
296 }
297 mLastTFTime = timer::now();
298 }
299
300 // endOfStream() propagates the EoS signal to downstream devices (required for source devices).
301 if (mMaxTFs != std::numeric_limits<unsigned int>::max() && tf >= mMaxTFs - 1) {
302 ctx.services().get<ControlService>().endOfStream();
303 ctx.services().get<ControlService>().readyToQuit(QuitRequest::Me);
304 }
305 }
306
307 void endOfStream(o2::framework::EndOfStreamContext&) final { closeFiles(); }
308 void stop() final { closeFiles(); }
309
310 private:
311 void closeFiles()
312 {
313 if (mDebugStream) {
314 auto& stream = (*mDebugStream) << "cmvs";
315 auto& tree = stream.getTree();
316 tree.SetAlias("sector", "int(cru/10)");
317 mDebugStream->Close();
318 mDebugStream.reset(nullptr);
319 }
320 }
321
322 const std::vector<uint32_t> mCRUs{};
323 const std::unordered_set<uint32_t> mDelayCRUs{};
324 const unsigned int mMaxTFs{};
325 const bool mDelay{false};
326 const int mDelayTime{1};
327 const int mDelayEveryN{1};
328 const int mDelayTimeCRUs{1};
329 const int mDropTFsRandom{0};
330 const std::vector<int> mRangeTFsDrop{};
331 const float mTFLength{0.f};
332 const float mAmplitude{5.f};
333 const float mNoise{1.f};
334 std::mt19937 mRng{};
335 const std::string mInputFileName{};
336 const long long mInputEntry{0};
337 bool mUseInputFile{false};
338 std::vector<std::vector<float>> mBaseCMVFloat;
339 std::vector<std::vector<uint16_t>> mBaseCMVEncoded;
340 std::chrono::high_resolution_clock::time_point mTimer100TFs{};
341 std::chrono::high_resolution_clock::time_point mLastTFTime{};
342 bool mWriteDebug{false};
343 std::string mDebugStreamFileName{};
344 std::unique_ptr<o2::utils::TreeStreamRedirector> mDebugStream{};
345};
346
347// ─────────────────────────────────────────────────────────────────────────────
348DataProcessorSpec generateCMVsCRU(const std::vector<uint32_t>& crus,
349 const std::unordered_set<uint32_t>& delayCRUs,
350 unsigned int maxTFs,
351 bool delay,
352 int delayTime,
353 int delayEveryN,
354 int delayTimeCRUs,
355 int dropTFsRandom,
356 const std::vector<int>& rangeTFsDrop,
357 float tfLength,
358 float amplitude,
359 float noise,
360 int seed,
361 const std::string& inputFile,
362 long long inputEntry)
363{
364 std::vector<OutputSpec> outputSpecs;
365 outputSpecs.reserve(crus.size() * 2);
366 for (const auto cru : crus) {
367 const o2::header::DataHeader::SubSpecificationType subSpec{cru << 7};
368 outputSpecs.emplace_back(gDataOriginTPC, "CMVVECTOR", subSpec, Lifetime::Timeframe);
369 outputSpecs.emplace_back(gDataOriginTPC, "CMVORBITS", subSpec, Lifetime::Timeframe);
370 }
371
372 return DataProcessorSpec{
373 "tpc-cmv-generator",
374 Inputs{},
375 outputSpecs,
376 AlgorithmSpec{adaptFromTask<CMVGeneratorDevice>(crus, delayCRUs, maxTFs, delay, delayTime, delayEveryN, delayTimeCRUs, dropTFsRandom, rangeTFsDrop, tfLength, amplitude, noise, seed, inputFile, inputEntry)},
377 Options{
378 {"write-debug", VariantType::Bool, false, {"Write a debug output tree"}},
379 {"debug-file-name", VariantType::String, "./cmv_generator_debug.root", {"Name of the debug output file"}},
380 }};
381}
382
383// ─────────────────────────────────────────────────────────────────────────────
385{
386 const auto tpcCRUs = o2::RangeTokenizer::tokenize<int>(config.options().get<std::string>("crus"));
387 const std::vector<uint32_t> crus(tpcCRUs.begin(), tpcCRUs.end());
388
389 const auto delayCRUsStr = config.options().get<std::string>("delayCRUs");
390 std::unordered_set<uint32_t> delayCRUs;
391 if (!delayCRUsStr.empty()) {
392 for (const auto cru : o2::RangeTokenizer::tokenize<int>(delayCRUsStr)) {
393 delayCRUs.insert(static_cast<uint32_t>(cru));
394 }
395 }
396
397 const auto dropTFsRangeStr = config.options().get<std::string>("dropTFsRange");
398 const auto rangeTFsDrop = dropTFsRangeStr.empty() ? std::vector<int>{} : o2::RangeTokenizer::tokenize<int>(dropTFsRangeStr);
399 const int timeframesInt = config.options().get<int>("timeframes");
400 // -1 means run indefinitely; map to UINT_MAX so the termination check never fires.
401 const auto timeframes = (timeframesInt < 0) ? std::numeric_limits<unsigned int>::max() : static_cast<unsigned int>(timeframesInt);
402 const auto delay = config.options().get<bool>("delay");
403 const auto delayTime = config.options().get<int>("delayTime");
404 const auto delayEveryN = config.options().get<int>("delayEveryN");
405 const auto delayTimeCRUs = config.options().get<int>("delayTimeCRUs");
406 const auto dropTFsRandom = config.options().get<int>("dropTFsRandom");
407 const auto tfLength = config.options().get<float>("tfLength");
408 const auto seed = config.options().get<int>("seed");
409 const auto amplitude = config.options().get<float>("amplitude");
410 const auto noise = config.options().get<float>("noise");
411 const auto inputFile = config.options().get<std::string>("input-file");
412 const auto inputEntry = static_cast<long long>(config.options().get<int>("input-entry"));
413
414 o2::conf::ConfigurableParam::updateFromString(config.options().get<std::string>("configKeyValues"));
415
416 WorkflowSpec workflow;
417 workflow.emplace_back(generateCMVsCRU(crus, delayCRUs, timeframes, delay, delayTime, delayEveryN, delayTimeCRUs, dropTFsRandom, rangeTFsDrop, tfLength, amplitude, noise, seed, inputFile, inputEntry));
418
419 auto& hbfu = o2::raw::HBFUtils::Instance();
420 long startTime = hbfu.startTime > 0 ? hbfu.startTime : std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
421 o2::conf::ConfigurableParam::updateFromString(fmt::format("HBFUtils.startTime={}", startTime).data());
422 o2::conf::ConfigurableParam::updateFromString(fmt::format("HBFUtils.nHBFPerTF={}", hbfu.nHBFPerTF).data());
423 o2::raw::HBFUtilsInitializer hbfIni(config, workflow);
424
425 return workflow;
426}
Structs for storing CMVs to the CCDB.
Helper utilities for reading CMV ROOT files.
Common mode values data format definition.
uint64_t orbit
Definition RawEventData.h:6
unsigned int uint32_t
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events d
CURL * handle
int32_t nEntries
Definition Objects.cxx:40
Helper function to tokenize sequences and ranges of integral numbers.
void init(o2::framework::InitContext &ic) final
CMVGeneratorDevice(const std::vector< uint32_t > &crus, const std::unordered_set< uint32_t > &delayCRUs, unsigned int maxTFs, bool delay, int delayTime, int delayEveryN, int delayTimeCRUs, int dropTFsRandom, const std::vector< int > &rangeTFsDrop, float tfLength, float amplitude, float noise, int seed, const std::string &inputFile, long long inputEntry)
static constexpr uint32_t sOrbitsPerPacket
each CMV packet covers 8 heartbeat orbits
void endOfStream(o2::framework::EndOfStreamContext &) final
This is invoked whenever we have an EndOfStream event.
void stop() final
This is invoked on stop.
void run(o2::framework::ProcessingContext &ctx) final
static void updateFromString(std::string const &)
ConfigParamRegistry & options() const
@ MaxCRU
Definition CRU.h:31
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLboolean * data
Definition glcorearb.h:298
GLuint GLuint stream
Definition glcorearb.h:1806
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:579
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< DataProcessorSpec > WorkflowSpec
std::vector< InputSpec > Inputs
uint32_t getCurrentTF(o2::framework::ProcessingContext &pc)
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::unique_ptr< GPUReconstructionTimeframe > tf
static void addConfigOption(std::vector< o2::framework::ConfigParamSpec > &opts, const std::string &defOpt=std::string(o2::base::NameConf::DIGITIZATIONCONFIGFILE))
float getCMVFloat(const int cru, const int timeBin) const
Return the float CMV value for a given CRU and timebin within this TF.
CMV single data container.
Definition CMV.h:74
DataProcessorSpec generateCMVsCRU(const std::vector< uint32_t > &crus, const std::unordered_set< uint32_t > &delayCRUs, unsigned int maxTFs, bool delay, int delayTime, int delayEveryN, int delayTimeCRUs, int dropTFsRandom, const std::vector< int > &rangeTFsDrop, float tfLength, float amplitude, float noise, int seed, const std::string &inputFile, long long inputEntry)
WorkflowSpec defineDataProcessing(ConfigContext const &config)
This function hooks up the the workflow specifications into the DPL driver.
void customize(std::vector< ConfigParamSpec > &workflowOptions)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
uint64_t const void const *restrict const msg
Definition x9.h:153