Project
Loading...
Searching...
No Matches
ZSSpec.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 "TPCWorkflow/ZSSpec.h"
13#include "Headers/DataHeader.h"
14#include "Framework/WorkflowSpec.h" // o2::framework::mergeInputs
25#include "GPUDataTypes.h"
26#include "GPUHostDataTypes.h"
28#include "TPCBase/Sector.h"
29#include "Algorithm/Parser.h"
30#include <fairlogger/Logger.h>
31#include <memory> // for make_shared
32#include <vector>
33#include <iomanip>
34#include <stdexcept>
35#include <array>
36#include <unistd.h>
37#include <atomic>
38#include "GPUO2InterfaceUtils.h"
42#include "TPCBase/RDHUtils.h"
50
51using namespace o2::framework;
52using namespace o2::header;
53using namespace o2::gpu;
54using namespace o2::base;
55
56namespace o2
57{
58namespace tpc
59{
60
61DataProcessorSpec getZSEncoderSpec(std::vector<int> const& tpcSectors, bool outRaw = false, unsigned long tpcSectorMask = 0xFFFFFFFFF)
62{
63 std::string processorName = "tpc-zsEncoder";
64 constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR;
65 constexpr static size_t NEndpoints = o2::gpu::GPUTrackingInOutZS::NENDPOINTS;
66 using DigitArray = std::array<gsl::span<const o2::tpc::Digit>, NSectors>;
67
68 struct ProcessAttributes {
69 std::unique_ptr<uint64_t[]> zsoutput;
70 std::unique_ptr<IonTailCorrection> itcorr;
71 std::vector<unsigned int> sizes;
72 std::vector<int> tpcSectors;
74 GPUSettingsO2 globalConfig;
75 bool verify = false;
76 int verbosity = 1;
77 bool finished = false;
78 };
79
80 auto initFunction = [tpcSectors, outRaw, tpcSectorMask](InitContext& ic) {
81 auto processAttributes = std::make_shared<ProcessAttributes>();
82 auto& zsoutput = processAttributes->zsoutput;
83 processAttributes->tpcSectors = tpcSectors;
84 auto& verify = processAttributes->verify;
85 auto& sizes = processAttributes->sizes;
86 auto& verbosity = processAttributes->verbosity;
87 processAttributes->globalConfig = processAttributes->config.ReadConfigurableParam();
88 if (processAttributes->globalConfig.zsOnTheFlyDigitsFilter) {
89 processAttributes->itcorr.reset(new IonTailCorrection);
90 }
91 auto processingFct = [processAttributes, outRaw, tpcSectorMask](
93 if (processAttributes->finished) {
94 return;
95 }
96
97 auto& zsoutput = processAttributes->zsoutput;
98 auto& verify = processAttributes->verify;
99 auto& sizes = processAttributes->sizes;
100 auto& verbosity = processAttributes->verbosity;
101
102 processAttributes->config.configGRP.solenoidBzNominalGPU = 5.00668;
103 std::function<void(std::vector<o2::tpc::Digit>&)> digitsFilter = nullptr;
104 if (processAttributes->globalConfig.zsOnTheFlyDigitsFilter) {
105 digitsFilter = [processAttributes](std::vector<o2::tpc::Digit>& digits) {
106 LOG(info) << "Running TPC digits IonTail filter";
107 static std::atomic_flag lock = ATOMIC_FLAG_INIT;
108 while (lock.test_and_set()) {
109 }
110 processAttributes->itcorr->filterDigitsDirect(digits);
111 lock.clear();
112 };
113 }
114
115 const auto& inputs = getWorkflowTPCInput(pc, 0, false, false, tpcSectorMask, true);
116 sizes.resize(NSectors * NEndpoints);
117 o2::InteractionRecord ir{0, pc.services().get<o2::framework::TimingInfo>().firstTForbit};
118 o2::gpu::GPUO2InterfaceUtils::RunZSEncoder<DigitArray>(inputs->inputDigits, &zsoutput, sizes.data(), nullptr, &ir, processAttributes->config, 4, verify, false, digitsFilter);
119 ZeroSuppressedContainer8kb* page = reinterpret_cast<ZeroSuppressedContainer8kb*>(zsoutput.get());
120 unsigned int offset = 0;
121 for (unsigned int i = 0; i < NSectors; i++) {
122 unsigned int pageSector = 0;
123 for (unsigned int j = 0; j < NEndpoints; j++) {
124 if (sizes[i * NEndpoints + j] != 0) {
125 pageSector += sizes[i * NEndpoints + j];
126 }
127 }
128 offset += pageSector;
129 }
131 gsl::span<ZeroSuppressedContainer8kb> outp(&page[0], offset);
132 pc.outputs().snapshot(Output{gDataOriginTPC, "TPCZS", 0, sh}, outp);
133 pc.outputs().snapshot(Output{gDataOriginTPC, "ZSSIZES", 0, sh}, sizes);
134
135 if (outRaw) {
136 // ===| set up raw writer |===================================================
137 std::string inputGRP = o2::base::NameConf::getGRPFileName();
138 const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
139 o2::raw::RawFileWriter writer{"TPC"}; // to set the RDHv6.sourceID if V6 is used
140 writer.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::TPC)); // must be set explicitly
141 uint32_t rdhV = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>();
142 writer.useRDHVersion(rdhV);
143 writer.doLazinessCheck(false); // LazinessCheck is not thread-safe
144 std::string outDir = "./";
145 const unsigned int defaultLink = 0;
146 enum LinksGrouping { All,
147 Sector,
148 Link };
149 auto useGrouping = Sector;
150
151 for (unsigned int i = 0; i < NSectors; i++) {
152 for (unsigned int j = 0; j < NEndpoints; j++) {
153 const unsigned int cruInSector = j / 2;
154 const unsigned int cruID = i * 10 + cruInSector;
155 const rdh_utils::FEEIDType feeid = rdh_utils::getFEEID(cruID, j & 1, defaultLink);
156 std::string outfname;
157 if (useGrouping == LinksGrouping::All) { // single file for all links
158 outfname = fmt::format("{}tpc_all.raw", outDir);
159 } else if (useGrouping == LinksGrouping::Sector) { // file per sector
160 outfname = fmt::format("{}tpc_sector{}.raw", outDir, i);
161 } else if (useGrouping == LinksGrouping::Link) { // file per link
162 outfname = fmt::format("{}cru{}_{}.raw", outDir, cruID, j & 1);
163 }
164 writer.registerLink(feeid, cruID, defaultLink, j & 1, outfname);
165 }
166 }
167 if (useGrouping != LinksGrouping::Link) {
168 writer.useCaching();
169 }
171 o2::gpu::GPUO2InterfaceUtils::RunZSEncoder(inputs->inputDigits, nullptr, nullptr, &writer, &ir, processAttributes->config, 4, false, false, digitsFilter);
172 writer.writeConfFile("TPC", "RAWDATA", fmt::format("{}tpcraw.cfg", outDir));
173 }
174 zsoutput.reset(nullptr);
175 sizes = {};
176 };
177 return processingFct;
178 };
179
180 auto createInputSpecs = [tpcSectors]() {
181 Inputs inputs;
182 // inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe});
183 inputs.emplace_back(InputSpec{"input", gDataOriginTPC, "DIGITS", 0, Lifetime::Timeframe});
184 return std::move(mergeInputs(inputs, tpcSectors.size(),
185 [tpcSectors](InputSpec& input, size_t index) {
186 // using unique input names for the moment but want to find
187 // an input-multiplicity-agnostic way of processing
188 input.binding += std::to_string(tpcSectors[index]);
189 DataSpecUtils::updateMatchingSubspec(input, tpcSectors[index]);
190 }));
191 return inputs;
192 };
193
194 auto createOutputSpecs = []() {
195 std::vector<OutputSpec> outputSpecs = {};
196 OutputLabel label{"TPCZS"};
197 constexpr o2::header::DataDescription datadesc("TPCZS");
198 OutputLabel label2{"sizes"};
199 constexpr o2::header::DataDescription datadesc2("ZSSIZES");
200 outputSpecs.emplace_back(label, gDataOriginTPC, datadesc, 0, Lifetime::Timeframe);
201 outputSpecs.emplace_back(label2, gDataOriginTPC, datadesc2, 0, Lifetime::Timeframe);
202 return std::move(outputSpecs);
203 };
204
205 return DataProcessorSpec{"tpc-zsEncoder",
206 {createInputSpecs()},
207 {createOutputSpecs()},
208 AlgorithmSpec(initFunction)};
209} // spec end
210
211DataProcessorSpec getZStoDigitsSpec(std::vector<int> const& tpcSectors)
212{
213 std::string processorName = "tpc-zs-to-Digits";
214 constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR;
215 constexpr static size_t NEndpoints = o2::gpu::GPUTrackingInOutZS::NENDPOINTS;
216
217 struct ProcessAttributes {
218 std::array<std::vector<Digit>, NSectors> outDigits;
219 std::unique_ptr<unsigned long[]> zsinput;
220 std::vector<unsigned int> sizes;
221 std::unique_ptr<o2::tpc::ZeroSuppress> decoder;
222 std::vector<int> tpcSectors;
223 bool verify = false;
224 int verbosity = 1;
225 bool finished = false;
226
228 void sortDigits()
229 {
230 // sort digits
231 for (auto& digits : outDigits) {
232 std::sort(digits.begin(), digits.end(), [](const auto& a, const auto& b) {
233 if (a.getTimeStamp() < b.getTimeStamp()) {
234 return true;
235 }
236 if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) {
237 return true;
238 }
239 return false;
240 });
241 }
242 }
243 };
244
245 auto initFunction = [tpcSectors](InitContext& ic) {
246 auto processAttributes = std::make_shared<ProcessAttributes>();
247 processAttributes->tpcSectors = tpcSectors;
248 auto& outDigits = processAttributes->outDigits;
249 auto& decoder = processAttributes->decoder;
250 decoder = std::make_unique<o2::tpc::ZeroSuppress>();
251 auto& verbosity = processAttributes->verbosity;
252
253 auto processingFct = [processAttributes](
254 ProcessingContext& pc) {
255 if (processAttributes->finished) {
256 return;
257 }
258 std::array<unsigned int, NEndpoints * NSectors> sizes;
259 gsl::span<const ZeroSuppressedContainer8kb> inputZS;
260 std::array<gsl::span<const ZeroSuppressedContainer8kb>, NSectors> inputZSSector;
261 auto& outDigits = processAttributes->outDigits;
262 auto& decoder = processAttributes->decoder;
263 auto& verbosity = processAttributes->verbosity;
264 unsigned int firstOrbit = 0;
265
266 for (unsigned int i = 0; i < NSectors; i++) {
267 outDigits[i].clear();
268 }
270 firstOrbit = ir.orbit;
271 std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}};
272 for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) {
273 const o2::header::DataHeader* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
274 const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(ref);
275 o2::framework::RawParser parser(raw.data(), raw.size());
276
277 const unsigned char* ptr = nullptr;
278 int cruID = 0;
279 rdh_utils::FEEIDType FEEID = -1;
280 size_t totalSize = 0;
281 for (auto it = parser.begin(); it != parser.end(); it++) {
282 const unsigned char* current = it.raw();
283 const o2::header::RAWDataHeader* rdh = (const o2::header::RAWDataHeader*)current;
284 if (it.size() == 0) {
285 ptr = nullptr;
286 continue;
287 } else {
288 ptr = current;
289 FEEID = o2::raw::RDHUtils::getFEEID(*rdh);
290 cruID = int(o2::raw::RDHUtils::getCRUID(*rdh));
291 unsigned int sector = cruID / 10;
292 gsl::span<const ZeroSuppressedContainer8kb> z0in(reinterpret_cast<const ZeroSuppressedContainer8kb*>(ptr), 1);
293 decoder->DecodeZSPages(&z0in, &outDigits[sector], firstOrbit);
294 }
295 }
296 }
297 for (int i = 0; i < NSectors; i++) {
298 LOG(info) << "digits in sector " << i << " : " << outDigits[i].size();
300 pc.outputs().snapshot(Output{gDataOriginTPC, "DIGITS", (unsigned int)i, sh}, outDigits[i]);
301 }
302 };
303 return processingFct;
304 };
305
306 auto createInputSpecs = []() {
307 Inputs inputs;
308 inputs.emplace_back(InputSpec{"zsraw", ConcreteDataTypeMatcher{"TPC", "RAWDATA"}, Lifetime::Timeframe});
309
310 return std::move(inputs);
311 };
312
313 auto createOutputSpecs = []() {
314 std::vector<OutputSpec> outputSpecs = {};
315 OutputLabel label{"tpcdigits"};
316 constexpr o2::header::DataDescription datadesc("DIGITS");
317 for (int i = 0; i < NSectors; i++) {
318 outputSpecs.emplace_back(gDataOriginTPC, "DIGITS", i, Lifetime::Timeframe);
319 }
320 return std::move(outputSpecs);
321 };
322
323 return DataProcessorSpec{"decode-zs-to-digits",
324 {createInputSpecs()},
325 {createOutputSpecs()},
326 AlgorithmSpec(initFunction)};
327} // spec end
328
329} // namespace tpc
330} // namespace o2
#define verbosity
A raw page parser for DPL input.
Definition of the TPC Digit.
Helper class for memory management of TPC Data Formats, external from the actual data type classes to...
int32_t i
Header of the General Run Parameters object.
A helper class to iteratate over all parts of all input routes.
Implementation of the ion tail correction from TPC digits.
Definition of the Names Generator class.
Utilities for parsing of data sequences.
uint32_t j
Definition RawData.h:0
Utility class to write detectors data to (multiple) raw data file(s) respecting CRU format.
TBranch * ptr
Helper class to obtain TPC clusters / digits / labels from DPL.
Definitions of TPC Zero Suppression Data Headers.
static std::string getGRPFileName(const std::string_view prefix=STANDARDSIMPREFIX)
Definition NameConf.cxx:58
static constexpr ID TPC
Definition DetID.h:64
A helper class to iteratate over all parts of all input routes.
static void RunZSEncoder(const S &in, std::unique_ptr< uint64_t[]> *outBuffer, uint32_t *outSizes, o2::raw::RawFileWriter *raw, const o2::InteractionRecord *ir, int32_t version, bool verify, float threshold=0.f, bool padding=false, std::function< void(std::vector< o2::tpc::Digit > &)> digitsFilter=nullptr)
static GRPObject * loadFrom(const std::string &grpFileName="")
static constexpr int MAXSECTOR
Definition Sector.h:44
std::array< gsl::span< const o2::tpc::Digit >, Sector::MAXSECTOR > DigitArray
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
Definition glcorearb.h:2595
GLuint index
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLintptr offset
Definition glcorearb.h:660
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint ref
Definition glcorearb.h:291
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:576
constexpr int NSectors
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
Inputs mergeInputs(InputSpec original, size_t maxIndex, std::function< void(InputSpec &, size_t)> amendCallback)
std::vector< InputSpec > Inputs
O2 data header classes and API, v0.1.
Definition DetID.h:49
uint16_t FEEIDType
Definition RDHUtils.h:26
framework::DataProcessorSpec getZSEncoderSpec(std::vector< int > const &tpcSectors, bool outRaw, unsigned long tpcSectorMask)
create a processor spec
Definition ZSSpec.cxx:61
framework::DataProcessorSpec getZStoDigitsSpec(std::vector< int > const &tpcSectors)
Definition ZSSpec.cxx:211
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
uint32_t orbit
LHC orbit.
static constexpr uint32_t NENDPOINTS
the main header struct
Definition DataHeader.h:618
IR getFirstSampledTFIR() const
get TF and HB (abs) for this IR
Definition HBFUtils.h:74
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
std::vector< Digit > digits