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 "GPUDataTypesIO.h"
26#include "GPUHostDataTypes.h"
28#include "TPCBase/Sector.h"
29#include <fairlogger/Logger.h>
30#include <memory> // for make_shared
31#include <vector>
32#include <iomanip>
33#include <stdexcept>
34#include <array>
35#include <unistd.h>
36#include <atomic>
37#include "GPUO2InterfaceUtils.h"
41#include "TPCBase/RDHUtils.h"
49
50using namespace o2::framework;
51using namespace o2::header;
52using namespace o2::gpu;
53using namespace o2::base;
54
55namespace o2
56{
57namespace tpc
58{
59
60DataProcessorSpec getZSEncoderSpec(std::vector<int> const& tpcSectors, bool outRaw = false, unsigned long tpcSectorMask = 0xFFFFFFFFF)
61{
62 std::string processorName = "tpc-zsEncoder";
63 constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR;
64 constexpr static size_t NEndpoints = o2::gpu::GPUTrackingInOutZS::NENDPOINTS;
65 using DigitArray = std::array<gsl::span<const o2::tpc::Digit>, NSectors>;
66
67 struct ProcessAttributes {
68 std::unique_ptr<uint64_t[]> zsoutput;
69 std::unique_ptr<IonTailCorrection> itcorr;
70 std::vector<unsigned int> sizes;
71 std::vector<int> tpcSectors;
73 GPUSettingsO2 globalConfig;
74 bool verify = false;
75 int verbosity = 1;
76 bool finished = false;
77 };
78
79 auto initFunction = [tpcSectors, outRaw, tpcSectorMask](InitContext& ic) {
80 auto processAttributes = std::make_shared<ProcessAttributes>();
81 auto& zsoutput = processAttributes->zsoutput;
82 processAttributes->tpcSectors = tpcSectors;
83 auto& verify = processAttributes->verify;
84 auto& sizes = processAttributes->sizes;
85 auto& verbosity = processAttributes->verbosity;
86 processAttributes->globalConfig = processAttributes->config.ReadConfigurableParam();
87 if (processAttributes->globalConfig.zsOnTheFlyDigitsFilter) {
88 processAttributes->itcorr.reset(new IonTailCorrection);
89 }
90 auto processingFct = [processAttributes, outRaw, tpcSectorMask](
92 if (processAttributes->finished) {
93 return;
94 }
95
96 auto& zsoutput = processAttributes->zsoutput;
97 auto& verify = processAttributes->verify;
98 auto& sizes = processAttributes->sizes;
99 auto& verbosity = processAttributes->verbosity;
100
101 processAttributes->config.configGRP.solenoidBzNominalGPU = 5.00668;
102 std::function<void(std::vector<o2::tpc::Digit>&)> digitsFilter = nullptr;
103 if (processAttributes->globalConfig.zsOnTheFlyDigitsFilter) {
104 digitsFilter = [processAttributes](std::vector<o2::tpc::Digit>& digits) {
105 LOG(info) << "Running TPC digits IonTail filter";
106 static std::atomic_flag lock = ATOMIC_FLAG_INIT;
107 while (lock.test_and_set()) {
108 }
109 processAttributes->itcorr->filterDigitsDirect(digits);
110 lock.clear();
111 };
112 }
113
114 const auto& inputs = getWorkflowTPCInput(pc, 0, false, false, tpcSectorMask, true);
115 sizes.resize(NSectors * NEndpoints);
116 o2::InteractionRecord ir{0, pc.services().get<o2::framework::TimingInfo>().firstTForbit};
117 o2::gpu::GPUO2InterfaceUtils::RunZSEncoder<DigitArray>(inputs->inputDigits, &zsoutput, sizes.data(), nullptr, &ir, processAttributes->config, 4, verify, false, digitsFilter);
118 ZeroSuppressedContainer8kb* page = reinterpret_cast<ZeroSuppressedContainer8kb*>(zsoutput.get());
119 unsigned int offset = 0;
120 for (unsigned int i = 0; i < NSectors; i++) {
121 unsigned int pageSector = 0;
122 for (unsigned int j = 0; j < NEndpoints; j++) {
123 if (sizes[i * NEndpoints + j] != 0) {
124 pageSector += sizes[i * NEndpoints + j];
125 }
126 }
127 offset += pageSector;
128 }
130 gsl::span<ZeroSuppressedContainer8kb> outp(&page[0], offset);
131 pc.outputs().snapshot(Output{gDataOriginTPC, "TPCZS", 0, sh}, outp);
132 pc.outputs().snapshot(Output{gDataOriginTPC, "ZSSIZES", 0, sh}, sizes);
133
134 if (outRaw) {
135 // ===| set up raw writer |===================================================
136 std::string inputGRP = o2::base::NameConf::getGRPFileName();
137 const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
138 o2::raw::RawFileWriter writer{"TPC"}; // to set the RDHv6.sourceID if V6 is used
139 writer.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::TPC)); // must be set explicitly
140 uint32_t rdhV = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>();
141 writer.useRDHVersion(rdhV);
142 writer.doLazinessCheck(false); // LazinessCheck is not thread-safe
143 std::string outDir = "./";
144 const unsigned int defaultLink = 0;
145 enum LinksGrouping { All,
146 Sector,
147 Link };
148 auto useGrouping = Sector;
149
150 for (unsigned int i = 0; i < NSectors; i++) {
151 for (unsigned int j = 0; j < NEndpoints; j++) {
152 const unsigned int cruInSector = j / 2;
153 const unsigned int cruID = i * 10 + cruInSector;
154 const rdh_utils::FEEIDType feeid = rdh_utils::getFEEID(cruID, j & 1, defaultLink);
155 std::string outfname;
156 if (useGrouping == LinksGrouping::All) { // single file for all links
157 outfname = fmt::format("{}tpc_all.raw", outDir);
158 } else if (useGrouping == LinksGrouping::Sector) { // file per sector
159 outfname = fmt::format("{}tpc_sector{}.raw", outDir, i);
160 } else if (useGrouping == LinksGrouping::Link) { // file per link
161 outfname = fmt::format("{}cru{}_{}.raw", outDir, cruID, j & 1);
162 }
163 writer.registerLink(feeid, cruID, defaultLink, j & 1, outfname);
164 }
165 }
166 if (useGrouping != LinksGrouping::Link) {
167 writer.useCaching();
168 }
170 o2::gpu::GPUO2InterfaceUtils::RunZSEncoder(inputs->inputDigits, nullptr, nullptr, &writer, &ir, processAttributes->config, 4, false, false, digitsFilter);
171 writer.writeConfFile("TPC", "RAWDATA", fmt::format("{}tpcraw.cfg", outDir));
172 }
173 zsoutput.reset(nullptr);
174 sizes = {};
175 };
176 return processingFct;
177 };
178
179 auto createInputSpecs = [tpcSectors]() {
180 Inputs inputs;
181 // inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe});
182 inputs.emplace_back(InputSpec{"input", gDataOriginTPC, "DIGITS", 0, Lifetime::Timeframe});
183 return std::move(mergeInputs(inputs, tpcSectors.size(),
184 [tpcSectors](InputSpec& input, size_t index) {
185 // using unique input names for the moment but want to find
186 // an input-multiplicity-agnostic way of processing
187 input.binding += std::to_string(tpcSectors[index]);
188 DataSpecUtils::updateMatchingSubspec(input, tpcSectors[index]);
189 }));
190 return inputs;
191 };
192
193 auto createOutputSpecs = []() {
194 std::vector<OutputSpec> outputSpecs = {};
195 OutputLabel label{"TPCZS"};
196 constexpr o2::header::DataDescription datadesc("TPCZS");
197 OutputLabel label2{"sizes"};
198 constexpr o2::header::DataDescription datadesc2("ZSSIZES");
199 outputSpecs.emplace_back(label, gDataOriginTPC, datadesc, 0, Lifetime::Timeframe);
200 outputSpecs.emplace_back(label2, gDataOriginTPC, datadesc2, 0, Lifetime::Timeframe);
201 return std::move(outputSpecs);
202 };
203
204 return DataProcessorSpec{"tpc-zsEncoder",
205 {createInputSpecs()},
206 {createOutputSpecs()},
207 AlgorithmSpec(initFunction)};
208} // spec end
209
210DataProcessorSpec getZStoDigitsSpec(std::vector<int> const& tpcSectors)
211{
212 std::string processorName = "tpc-zs-to-Digits";
213 constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR;
214 constexpr static size_t NEndpoints = o2::gpu::GPUTrackingInOutZS::NENDPOINTS;
215
216 struct ProcessAttributes {
217 std::array<std::vector<Digit>, NSectors> outDigits;
218 std::unique_ptr<unsigned long[]> zsinput;
219 std::vector<unsigned int> sizes;
220 std::unique_ptr<o2::tpc::ZeroSuppress> decoder;
221 std::vector<int> tpcSectors;
222 bool verify = false;
223 int verbosity = 1;
224 bool finished = false;
225
227 void sortDigits()
228 {
229 // sort digits
230 for (auto& digits : outDigits) {
231 std::sort(digits.begin(), digits.end(), [](const auto& a, const auto& b) {
232 if (a.getTimeStamp() < b.getTimeStamp()) {
233 return true;
234 }
235 if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) {
236 return true;
237 }
238 return false;
239 });
240 }
241 }
242 };
243
244 auto initFunction = [tpcSectors](InitContext& ic) {
245 auto processAttributes = std::make_shared<ProcessAttributes>();
246 processAttributes->tpcSectors = tpcSectors;
247 auto& outDigits = processAttributes->outDigits;
248 auto& decoder = processAttributes->decoder;
249 decoder = std::make_unique<o2::tpc::ZeroSuppress>();
250 auto& verbosity = processAttributes->verbosity;
251
252 auto processingFct = [processAttributes](
253 ProcessingContext& pc) {
254 if (processAttributes->finished) {
255 return;
256 }
257 std::array<unsigned int, NEndpoints * NSectors> sizes;
258 gsl::span<const ZeroSuppressedContainer8kb> inputZS;
259 std::array<gsl::span<const ZeroSuppressedContainer8kb>, NSectors> inputZSSector;
260 auto& outDigits = processAttributes->outDigits;
261 auto& decoder = processAttributes->decoder;
262 auto& verbosity = processAttributes->verbosity;
263 unsigned int firstOrbit = 0;
264
265 for (unsigned int i = 0; i < NSectors; i++) {
266 outDigits[i].clear();
267 }
269 firstOrbit = ir.orbit;
270 std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}};
271 for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) {
272 const o2::header::DataHeader* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
273 const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(ref);
274 o2::framework::RawParser parser(raw.data(), raw.size());
275
276 const unsigned char* ptr = nullptr;
277 int cruID = 0;
278 rdh_utils::FEEIDType FEEID = -1;
279 size_t totalSize = 0;
280 for (auto it = parser.begin(); it != parser.end(); it++) {
281 const unsigned char* current = it.raw();
282 const o2::header::RAWDataHeader* rdh = (const o2::header::RAWDataHeader*)current;
283 if (it.size() == 0) {
284 ptr = nullptr;
285 continue;
286 } else {
287 ptr = current;
288 FEEID = o2::raw::RDHUtils::getFEEID(*rdh);
289 cruID = int(o2::raw::RDHUtils::getCRUID(*rdh));
290 unsigned int sector = cruID / 10;
291 gsl::span<const ZeroSuppressedContainer8kb> z0in(reinterpret_cast<const ZeroSuppressedContainer8kb*>(ptr), 1);
292 decoder->DecodeZSPages(&z0in, &outDigits[sector], firstOrbit);
293 }
294 }
295 }
296 for (int i = 0; i < NSectors; i++) {
297 LOG(info) << "digits in sector " << i << " : " << outDigits[i].size();
299 pc.outputs().snapshot(Output{gDataOriginTPC, "DIGITS", (unsigned int)i, sh}, outDigits[i]);
300 }
301 };
302 return processingFct;
303 };
304
305 auto createInputSpecs = []() {
306 Inputs inputs;
307 inputs.emplace_back(InputSpec{"zsraw", ConcreteDataTypeMatcher{"TPC", "RAWDATA"}, Lifetime::Timeframe});
308
309 return std::move(inputs);
310 };
311
312 auto createOutputSpecs = []() {
313 std::vector<OutputSpec> outputSpecs = {};
314 OutputLabel label{"tpcdigits"};
315 constexpr o2::header::DataDescription datadesc("DIGITS");
316 for (int i = 0; i < NSectors; i++) {
317 outputSpecs.emplace_back(gDataOriginTPC, "DIGITS", i, Lifetime::Timeframe);
318 }
319 return std::move(outputSpecs);
320 };
321
322 return DataProcessorSpec{"decode-zs-to-digits",
323 {createInputSpecs()},
324 {createOutputSpecs()},
325 AlgorithmSpec(initFunction)};
326} // spec end
327
328} // namespace tpc
329} // 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
zsPage * page
o2::raw::RawFileWriter * raw
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.
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 ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
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:60
framework::DataProcessorSpec getZStoDigitsSpec(std::vector< int > const &tpcSectors)
Definition ZSSpec.cxx:210
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:620
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