Project
Loading...
Searching...
No Matches
digits-random-generator-workflow.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
15#include "DigitIOBaseTask.h"
21#include "Framework/Lifetime.h"
22#include "Framework/Logger.h"
23#include "Framework/Output.h"
24#include "Framework/Task.h"
27#include "ProgOptions.h"
28#include <array>
29#include <chrono>
30#include <cstring>
31#include <fmt/format.h>
32#include <fstream>
33#include <iostream>
34#include <random>
35#include <stdexcept>
36#include <vector>
37
43using namespace o2::framework;
44
45using namespace o2::mch;
46
47namespace
48{
49std::array<int, 156> getDeIds()
50{
51 static std::array<int, 156> deids;
52 static bool first = true;
53 if (first) {
54 int i{0};
56 deids[i++] = deid;
57 });
58 first = false;
59 }
60 return deids;
61}
62
63std::array<int, 156> getNofPads()
64{
65 static bool first = true;
66 static std::array<int, 156> npads;
67 if (first) {
68 int i{0};
69 auto deids = getDeIds();
70 for (auto deid : deids) {
72 int16_t nofPads = static_cast<int16_t>(seg.nofPads());
73 npads[i++] = nofPads;
74 }
75 first = false;
76 }
77 return npads;
78}
79} // namespace
80
81constexpr const char* OPTNAME_NOF_ROFS_PER_TF = "nof-rofs-per-tf";
82constexpr const char* OPTNAME_OCCUPANCY = "occupancy";
83constexpr const char* OPTNAME_SEED = "seed";
84
86{
87 public:
88 void init(InitContext& ic)
89 {
90 io::DigitIOBaseTask::init(ic); // init common options
91 mOccupancy = ic.options().get<float>(OPTNAME_OCCUPANCY);
92 if (mOccupancy <= 0.0 || mOccupancy > 1.0) {
93 throw std::invalid_argument("occupancy must be between >0 and <=1");
94 }
95 mNofRofPerTimeFrame = ic.options().get<int>(OPTNAME_NOF_ROFS_PER_TF);
96 mSeed = ic.options().get<int>(OPTNAME_SEED);
97
98 if (!mSeed) {
99 std::random_device rd;
100 mSeed = rd();
101 }
102 mMersenneTwister.seed(mSeed);
103
104 LOGP(info,
105 "Will generate {:7.2f}% of pads in {:4d} ROFs "
106 "per timeframe, for {:4d} timeframes",
107 mOccupancy * 100.0, mNofRofPerTimeFrame, mMaxNofTimeFrames);
108 }
109
111 {
113 pc.services().get<ControlService>().endOfStream();
114 return;
115 }
116
117 if (shouldProcess()) {
119 std::vector<Digit> digits;
120 std::vector<ROFRecord> rofs;
121 int ndigits{0};
122
123 for (auto i = 0; i < mNofRofPerTimeFrame; i++) {
124 auto n = generateRandomDigits(mOccupancy, digits);
125 o2::InteractionRecord ir{mBC, mOrbit};
126 rofs.emplace_back(ir, ndigits, n);
127 ndigits += n;
128 mOrbit++;
129 }
130 pc.outputs().snapshot(OutputRef{"rofs"}, rofs);
131 pc.outputs().snapshot(OutputRef{"digits"}, digits);
132 printSummary(digits, rofs);
133 printFull(digits, rofs);
134 }
135 incTFid();
136 }
137
153 int generateRandomDigits(float occupancy,
154 std::vector<Digit>& digits)
155 {
156 int n{0};
157 std::uniform_int_distribution<int32_t> adc{0, 1024 * 1024};
158 std::uniform_int_distribution<int32_t> tfTime{0, 512 * 3564};
159 std::uniform_int_distribution<int32_t> nofSamples{0, 1023};
160 std::uniform_real_distribution<float> sat{0.0, 1.0};
161
162 auto deids = getDeIds();
163 auto nofPadsPerDe = getNofPads();
164 auto& mt = mMersenneTwister;
165
166 for (auto i = 0; i < deids.size(); i++) {
167 auto deid = deids[i];
168 int16_t nofPads = static_cast<int16_t>(nofPadsPerDe[i]);
169 std::uniform_int_distribution<int16_t> padid{0, nofPads};
170 int nch = nofPads * occupancy;
171 for (int i = 0; i < nch; i++) {
172 auto p = padid(mt);
173 bool isSaturated = (sat(mt) > 0.9);
174 digits.emplace_back(deid, p, tfTime(mt), adc(mt), nofSamples(mt), isSaturated);
175 ++n;
176 }
177 }
178 return n;
179 }
180
181 private:
182 float mOccupancy = 1.0;
183 uint16_t mBC = 0;
184 uint32_t mOrbit = 0;
185 int mNofRofPerTimeFrame = 100;
186 int mSeed = 0;
187 std::mt19937 mMersenneTwister;
188};
189
191
192using namespace o2::mch;
193
195{
196 auto commonOptions = o2::mch::io::getCommonOptions();
197 auto options = Options{
198 {OPTNAME_OCCUPANCY, VariantType::Float, 0.01f, {"occupancy (fraction of fired pad per DE per ROF)"}},
199 {OPTNAME_SEED, VariantType::Int, 0, {"seed for number generator (if 0 use default_seed)"}},
200 {OPTNAME_NOF_ROFS_PER_TF, VariantType::Int, 100, {"number of ROFs per timeframe"}}};
201 options.insert(options.end(), commonOptions.begin(), commonOptions.end());
202
203 return WorkflowSpec{
205 "mch-digits-random-generator",
206 Inputs{},
207 Outputs{OutputSpec{{"digits"}, "MCH", "DIGITS", 0, Lifetime::Timeframe},
208 OutputSpec{{"rofs"}, "MCH", "DIGITROFS", 0, Lifetime::Timeframe}},
209 AlgorithmSpec{adaptFromTask<DigitGenerator>()},
210 options}};
211}
o2::mch::mapping::CathodeSegmentation seg
int32_t i
Definition of the MCH ROFrame record.
void run(ProcessingContext &pc)
int generateRandomDigits(float occupancy, std::vector< Digit > &digits)
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
ServiceRegistryRef services()
The services registry associated with this processing context.
void printFull(gsl::span< const Digit > digits, gsl::span< const ROFRecord > rofs) const
void printSummary(gsl::span< const Digit > digits, gsl::span< const ROFRecord > rofs, const char *suffix="") const
void init(o2::framework::InitContext &ic)
A Segmentation lets you find pads of a detection element and then inspect those pads.
WorkflowSpec defineDataProcessing(const ConfigContext &cc)
constexpr const char * OPTNAME_OCCUPANCY
constexpr const char * OPTNAME_NOF_ROFS_PER_TF
constexpr const char * OPTNAME_SEED
GLdouble n
Definition glcorearb.h:1982
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< DataProcessorSpec > WorkflowSpec
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
std::vector< ConfigParamSpec > getCommonOptions()
void forEachDetectionElement(CALLABLE &&func)
std::vector< o2::mch::ChannelCode > cc
o2::InteractionRecord ir(0, 0)
std::random_device rd
std::vector< Digit > digits
ArrayADC adc