Project
Loading...
Searching...
No Matches
RawWriterFIT.h
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// file RawWriterFIT.h Base class for RAW data writing
13//
14// Artur.Furs
15// afurs@cern.ch
16
17#ifndef ALICEO2_FIT_RAWREADERBASEFIT_H_
18#define ALICEO2_FIT_RAWREADERBASEFIT_H_
19#include <iostream>
20#include <vector>
21#include <cstdlib>
22#include <Rtypes.h>
23#include <TStopwatch.h>
24#include <boost/program_options.hpp>
25#include <gsl/span>
26#include <fmt/format.h>
27
28#include "FITRaw/DataBlockFIT.h"
31#include <Framework/Logger.h>
39
40namespace o2
41{
42namespace fit
43{
44// Raw writer for FIT, based on RawReader
45template <typename DigitBlockFITtype, typename DataBlockPMtype, typename DataBlockTCMtype, typename = typename std::enable_if_t<DataBlockPMtype::sIsPadded == DataBlockTCMtype::sIsPadded>>
47{
48 public:
49 typedef DigitBlockFITtype DigitBlockFIT_t;
50 typedef typename DigitBlockFIT_t::LookupTable_t LookupTable_t;
51 typedef typename LookupTable_t::Topo_t Topo_t;
52 typedef DataBlockPMtype DataBlockPM_t;
53 typedef DataBlockTCMtype DataBlockTCM_t;
56 RawWriterFIT() = default;
57 ~RawWriterFIT() = default;
59 void setFileFor(const std::string& fileFor) { mFileFor = fileFor; }
60 void setFlpName(const std::string& flpName) { mFlpName = flpName; }
61 bool getFilePerLink() const { return mOutputPerLink; }
62 void setStatusEmu(MetricStatus_t statusEmu) { mStatusEmu = statusEmu; }
63 void setRandomEmu(bool isRandomStatusEmu) { mIsRandomStatusEmu = isRandomStatusEmu; }
64
65 void setVerbosity(int verbosityLevel) { mVerbosity = verbosityLevel; }
66 void setCCDBurl(const std::string& ccdbPath) { LookupTable_t::setCCDBurl(ccdbPath); }
67 void setLUTpath(const std::string& lutPath) { LookupTable_t::setLUTpath(lutPath); }
68 int getVerbosity() const { return mVerbosity; }
69 int carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data,
70 const char* ptr, int maxSize, int splitID,
71 std::vector<char>& trailer, std::vector<char>& header) const
72 {
73 return 0; // do not split, always start new CRU page
74 }
75 void convertDigitsToRaw(const std::string& outputDir, const std::string& filenameDigits, long timestamp = -1)
76 {
77 LOG(info) << "Converting Digits to Raw data...";
78 if (mStatusEmu > 0 || mIsRandomStatusEmu) {
79 LOG(warning) << "Raw data metric emulation applied: isRandom " << mIsRandomStatusEmu << "; metricStatus: " << static_cast<uint16_t>(mStatusEmu);
80 if (mStatusEmu == 0) {
81 LOG(warning) << "Metric status is not specified, all bits will be randomly generated";
83 }
84 }
86 LookupTable_t::Instance(nullptr, timestamp).printFullMap();
87 // Preparing topo2FEEmetadata map
89 mMapTopo2FEEmetadata = LookupTable_t::Instance().template makeMapFEEmetadata<o2::header::RAWDataHeader, RDHUtils>();
90 // Preparing filenames
91 std::string detName = LookupTable_t::sDetectorName;
92 auto makeFilename = [&](const o2::header::RAWDataHeader& rdh) -> std::string {
93 std::string maskName{};
94 if (mFileFor != "all") { // single file for all links
95 maskName += fmt::format("_{}", mFlpName);
96 if (mFileFor != "flp") {
97 maskName += fmt::format("_cru{}_{}", RDHUtils::getCRUID(rdh), RDHUtils::getEndPointID(rdh));
98 if (mFileFor != "cruendpoint") {
99 maskName += fmt::format("_lnk{}_feeid{}", RDHUtils::getLinkID(rdh), RDHUtils::getFEEID(rdh));
100 if (mFileFor != "link") {
101 throw std::runtime_error("invalid option provided for file grouping");
102 }
103 }
104 }
105 }
106 std::string outputFilename = o2::utils::Str::concat_string(outputDir, detName, maskName, ".raw");
107 return outputFilename;
108 };
109 // Registering links
110 for (const auto& metadataPair : mMapTopo2FEEmetadata) {
111 const auto& rdh = metadataPair.second;
112 const auto outputFilename = makeFilename(rdh);
113 mWriter.registerLink(RDHUtils::getFEEID(rdh), RDHUtils::getCRUID(rdh), RDHUtils::getLinkID(rdh), RDHUtils::getEndPointID(rdh), outputFilename);
114 }
115 // Processing digits into raw data
116 TFile* inputFile = TFile::Open(filenameDigits.c_str());
117 assert(inputFile != nullptr);
118 LOG(info) << "Source file: " << filenameDigits;
119 TTree* inputTree = dynamic_cast<TTree*>(inputFile->Get("o2sim"));
120 DigitBlockFIT_t::processDigitBlocks(inputTree, *this);
121 delete inputTree;
122 inputFile->Close();
123 delete inputFile;
124 }
125 void processDigitBlockPerTF(const std::vector<DigitBlockFIT_t>& vecDigitBlock) // Is used in DigitBlockFIT_t::processDigitBlocks for each TF (TTree entry)
126 {
127 for (const auto& digitBlock : vecDigitBlock) {
128 MetricStatus_t statusEmu{mStatusEmu};
129 // Processing PM data
130 if (mIsRandomStatusEmu) {
131 statusEmu = static_cast<MetricStatus_t>(std::rand()) & mStatusEmu;
132 }
133 const auto mapDataBlockPM = digitBlock.template decomposeDigits<DataBlockPM_t>(statusEmu);
134 if (mVerbosity > 0) {
135 digitBlock.print();
136 }
137 for (const auto& dataBlockPair : mapDataBlockPM) {
138 const auto& topo = dataBlockPair.first;
139 const auto& dataBlock = dataBlockPair.second;
140 const auto& itRdh = mMapTopo2FEEmetadata.find(topo);
141 if (itRdh == mMapTopo2FEEmetadata.end()) {
142 LOG(warning) << "No CRU entry in map! Data block: ";
143 dataBlock.print();
144 continue;
145 }
146 if (mVerbosity > 0) {
147 dataBlock.print();
148 }
149 const auto& rdh = itRdh->second;
150 auto data = dataBlock.serialize();
151 mWriter.addData(RDHUtils::getFEEID(rdh), RDHUtils::getCRUID(rdh), RDHUtils::getLinkID(rdh), RDHUtils::getEndPointID(rdh), dataBlock.getInteractionRecord(), data);
152 }
153 // Processing TCM data
154 if (mIsRandomStatusEmu) {
155 statusEmu = static_cast<MetricStatus_t>(std::rand()) & mStatusEmu;
156 }
157 const auto dataBlockPair = digitBlock.template decomposeDigits<DataBlockTCM_t>(statusEmu);
158 const auto& topo = dataBlockPair.first;
159 const auto& dataBlock = dataBlockPair.second;
160 const auto& itRdh = mMapTopo2FEEmetadata.find(topo);
161 if (itRdh == mMapTopo2FEEmetadata.end()) {
162 LOG(warning) << "No CRU entry in map! Data block: ";
163 dataBlock.print();
164 continue;
165 }
166 if (mVerbosity > 0) {
167 dataBlock.print();
168 }
169 const auto& rdh = itRdh->second;
170 auto data = dataBlock.serialize();
171 mWriter.addData(RDHUtils::getFEEID(rdh), RDHUtils::getCRUID(rdh), RDHUtils::getLinkID(rdh), RDHUtils::getEndPointID(rdh), dataBlock.getInteractionRecord(), data);
172 }
173 }
174 static constexpr auto getDetID() { return LookupTable_t::sDetID; };
176 std::string mFlpName{};
177 std::string mFileFor{};
178 MetricStatus_t mStatusEmu{}; // for metrics emulation, contains bits RawDataMetric::EStatusBits
179 bool mIsRandomStatusEmu{false}; // to use status bits randomly
180 int mDataFormat{0}; // RDH::dataFormat field, 0 - padded, 2 - no padding
181 std::map<Topo_t, o2::header::RAWDataHeader> mMapTopo2FEEmetadata;
182 // const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance();
183 bool mOutputPerLink = false;
184 int mVerbosity = 0;
185};
186
187/*
188 * Special configurator for digit2raw executables
189 */
190namespace bpo = boost::program_options;
192 using VariablesMap = typename boost::program_options::variables_map;
193 using OptionsDescription = typename boost::program_options::options_description;
196 {
198 }
199 DigitToRawConfig() = default; // careful, data format should be then checked via adjustDataFormat()
201 {
202 mVerbosity = vm["verbosity"].as<int>();
203 mInputFile = vm["input-file"].as<std::string>();
204 mOutputDir = vm["output-dir"].as<std::string>();
205 mFileFor = vm["file-for"].as<std::string>();
206 mFlpName = vm["flp-name"].as<std::string>();
207 mConfigKeyValues = vm["configKeyValues"].as<std::string>();
208
209 mRdhVersion = vm["rdh-version"].as<uint32_t>();
210 mNoEmptyHBF = vm["no-empty-hbf"].as<bool>();
211 mConfDig = vm["hbfutils-config"].as<std::string>();
212 mEnablePadding = vm["enable-padding"].as<bool>();
213 mCcdbPath = vm["ccdb-path"].as<std::string>();
214 mChannelMapPath = vm["lut-path"].as<std::string>();
215
216 mMetricStatusEmu = static_cast<MetricStatus_t>(vm["emu-rawdata-metrics"].as<uint64_t>());
217 mIsRandomMetric = vm["emu-rawdata-metrics-random"].as<bool>();
218
220 }
221 static void configureExecOptions(OptionsDescription& opt_general, const std::string& defaultInputFilename, const std::string& defaultFLP_name)
222 {
223 auto add_option = opt_general.add_options();
224 // common configs
225 add_option("verbosity,v", bpo::value<int>()->default_value(0), "verbosity level");
226 add_option("input-file,i", bpo::value<std::string>()->default_value(defaultInputFilename), "input digits file");
227 add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data");
228 add_option("flp-name", bpo::value<std::string>()->default_value(defaultFLP_name), "single file per: all,flp,cru,link");
229 add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,flp,cruendpoint,link");
230 add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues");
231 // raw data configs
232 uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>();
233 add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use");
234 add_option("no-empty-hbf,e", bpo::value<bool>()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)");
235 add_option("hbfutils-config,u", bpo::value<std::string>()->default_value(std::string(o2::base::NameConf::DIGITIZATIONCONFIGFILE)), "config file for HBFUtils (or none)");
236 add_option("enable-padding", bpo::value<bool>()->default_value(false)->implicit_value(true), "enable GBT word padding to 128 bits even for RDH V7");
237 add_option("ccdb-path", bpo::value<std::string>()->default_value(""), "CCDB url which contains LookupTable");
238 add_option("lut-path", bpo::value<std::string>()->default_value(""), "LookupTable path");
239 // raw data metric emulation mode
240 add_option("emu-rawdata-metrics", bpo::value<uint64_t>()->default_value(0), "Raw data metric emulation, specify 1-byte status word with o2::fit::RawDataMetric::EStatusBits");
241 add_option("emu-rawdata-metrics-random", bpo::value<bool>()->default_value(false)->implicit_value(true), "Raw data metric emulation, randomly specifies 1-byte status word with o2::fit::RawDataMetric::EStatusBits. If --emu-rawdata-metrics is not specified then all bits will be on and randomly will be taken");
242 }
244 { // adjust DataFormat, with or w/o padding
245 if (mRdhVersion < 7 && !mEnablePadding) {
246 mEnablePadding = true;
247 LOG(info) << "padding is always ON for RDH version " << mRdhVersion;
248 }
249 mDataFormat = mEnablePadding ? 0 : 2;
250 }
251 // common configs
253 std::string mInputFile{"detdigits.root"}; // put det name before "digits"
254 std::string mOutputDir{"./"};
255 std::string mFlpName{"alio2-cr1-flpnode"}; // put node number after "flp"
256 std::string mFileFor{"all"};
257 std::string mConfigKeyValues{""};
258 // raw data configs
259 uint32_t mRdhVersion{o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>()};
260 bool mNoEmptyHBF{false};
262 bool mEnablePadding{false}; // will be adjusted(if false) wrt to RDH version
263 std::string mCcdbPath{""};
264 std::string mChannelMapPath{""};
265 // raw data metric emulation
266 MetricStatus_t mMetricStatusEmu{}; // status bit for raw data metric emulation
267 bool mIsRandomMetric{false}; // use random bits for metric emulation
268 // misc field
269 uint32_t mDataFormat;
270};
271
272/*
273 * Wrapper for digit2raw executables
274 */
275template <typename RawWriterFIT_Type>
277 DigitToRawDevice() = default;
278 DigitToRawDevice(const DigitToRawConfig& config) { setConfig(config); }
279 RawWriterFIT_Type mRawWriterFIT{};
281 void setConfig(const DigitToRawConfig& config)
282 {
283 mConfig = config;
285 }
287 {
288 // global config
289 if (!cfg.mConfDig.empty() && cfg.mConfDig != "none") {
291 }
293 // configuring FIT raw writer
294 mRawWriterFIT.setFileFor(cfg.mFileFor);
295 mRawWriterFIT.setFlpName(cfg.mFlpName);
296 mRawWriterFIT.setVerbosity(cfg.mVerbosity);
297 if (cfg.mCcdbPath != "") {
298 mRawWriterFIT.setCCDBurl(cfg.mCcdbPath);
299 }
300 if (cfg.mChannelMapPath != "") {
301 mRawWriterFIT.setLUTpath(cfg.mChannelMapPath);
302 }
303 // raw data metric emulation
304 mRawWriterFIT.setRandomEmu(cfg.mIsRandomMetric);
305 mRawWriterFIT.setStatusEmu(cfg.mMetricStatusEmu);
306 // configuring common raw writer
307 auto& rawWriter = mRawWriterFIT.getWriter();
308 std::string inputGRP = o2::base::NameConf::getGRPFileName();
309 const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
310 rawWriter.setContinuousReadout(grp->isDetContinuousReadOut(RawWriterFIT_Type::getDetID())); // must be set explicitly
311 const int superPageSizeInB = 1024 * 1024;
312 rawWriter.setSuperPageSize(superPageSizeInB);
313 rawWriter.useRDHVersion(cfg.mRdhVersion);
314 rawWriter.setDontFillEmptyHBF(cfg.mNoEmptyHBF);
315 rawWriter.useRDHDataFormat(cfg.mDataFormat);
316 if (!cfg.mEnablePadding) { // CRU page alignment padding is used only if no GBT word padding is used
317 rawWriter.setAlignmentSize(16); // change to constexpr static field from class?
318 rawWriter.setAlignmentPaddingFiller(0xff);
319 }
320 }
321 void run()
322 {
323 run(mConfig);
324 }
325 void run(const DigitToRawConfig& cfg)
326 {
327 // dst path preparations
329 std::string outDirName(cfg.mOutputDir);
330 if (outDirName.back() != '/') {
331 outDirName += '/';
332 }
333 // start timestamp preparations
334 const auto& hbfu = o2::raw::HBFUtils::Instance();
335 long startTime = hbfu.startTime > 0 ? hbfu.startTime : std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
336 // convertation digit->raw
337 mRawWriterFIT.convertDigitsToRaw(outDirName, cfg.mInputFile, startTime);
338 // config with output info
339 auto& rawWriter = mRawWriterFIT.getWriter();
340 rawWriter.writeConfFile(rawWriter.getOrigin().str, "RAWDATA", o2::utils::Str::concat_string(outDirName, rawWriter.getOrigin().str, "raw.cfg"));
341 }
342
343 static void digit2raw(const DigitToRawConfig& cfg)
344 {
345 TStopwatch swTot;
346 swTot.Start();
347 // configurating
348 DigitToRawDevice<RawWriterFIT_Type> digitToRawDevice(cfg);
349 // running
350 digitToRawDevice.run();
351 //
352 swTot.Stop();
353 swTot.Print();
354 }
355};
356
357} // namespace fit
358} // namespace o2
359
360#endif
Header of the General Run Parameters object.
std::string ccdbPath(const std::string badChannelType)
Definition of the Names Generator class.
Definition of the RAW Data Header.
Utility class to write detectors data to (multiple) raw data file(s) respecting CRU format.
TBranch * ptr
static std::string getGRPFileName(const std::string_view prefix=STANDARDSIMPREFIX)
Definition NameConf.cxx:58
static constexpr std::string_view DIGITIZATIONCONFIGFILE
Definition NameConf.h:89
static void updateFromFile(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
static void updateFromString(std::string const &)
void setStatusEmu(MetricStatus_t statusEmu)
DigitBlockFITtype DigitBlockFIT_t
int getVerbosity() const
bool getFilePerLink() const
void convertDigitsToRaw(const std::string &outputDir, const std::string &filenameDigits, long timestamp=-1)
RawDataMetric::Status_t MetricStatus_t
o2::raw::RawFileWriter & getWriter()
void setFileFor(const std::string &fileFor)
void processDigitBlockPerTF(const std::vector< DigitBlockFIT_t > &vecDigitBlock)
MetricStatus_t mStatusEmu
void setLUTpath(const std::string &lutPath)
DataBlockPMtype DataBlockPM_t
void setVerbosity(int verbosityLevel)
std::map< Topo_t, o2::header::RAWDataHeader > mMapTopo2FEEmetadata
void setFlpName(const std::string &flpName)
LookupTable_t::Topo_t Topo_t
void setRandomEmu(bool isRandomStatusEmu)
DigitBlockFIT_t::LookupTable_t LookupTable_t
void setCCDBurl(const std::string &ccdbPath)
int carryOverMethod(const header::RDHAny *rdh, const gsl::span< char > data, const char *ptr, int maxSize, int splitID, std::vector< char > &trailer, std::vector< char > &header) const
static constexpr auto getDetID()
DataBlockTCMtype DataBlockTCM_t
o2::raw::RawFileWriter mWriter
static GRPObject * loadFrom(const std::string &grpFileName="")
void setCarryOverCallBack(const T *t)
void addData(uint16_t feeid, uint16_t cru, uint8_t lnk, uint8_t endpoint, const IR &ir, const gsl::span< char > data, bool preformatted=false, uint32_t trigger=0, uint32_t detField=0)
LinkData & registerLink(uint16_t fee, uint16_t cru, uint8_t link, uint8_t endpoint, std::string_view outFileName)
GLboolean * data
Definition glcorearb.h:298
TFitResultPtr fit(const size_t nBins, const T *arr, const T xMin, const T xMax, TF1 &func, std::string_view option="")
Definition fit.h:59
void assertOutputDirectory(std::string_view outDirName)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static void configureExecOptions(OptionsDescription &opt_general, const std::string &defaultInputFilename, const std::string &defaultFLP_name)
typename RawDataMetric::Status_t MetricStatus_t
typename boost::program_options::options_description OptionsDescription
typename boost::program_options::variables_map VariablesMap
DigitToRawConfig(const VariablesMap &vm)
MetricStatus_t mMetricStatusEmu
void setFromExecOptions(const VariablesMap &vm)
void run(const DigitToRawConfig &cfg)
DigitToRawDevice(const DigitToRawConfig &config)
void configure(const DigitToRawConfig &cfg)
static void digit2raw(const DigitToRawConfig &cfg)
RawWriterFIT_Type mRawWriterFIT
DigitToRawConfig mConfig
void setConfig(const DigitToRawConfig &config)
static Status_t getAllBitsActivated()
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"