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...
unsigned int uint32_t
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:59
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
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:579
uint8_t int statusCode int
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:51
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.
the main header struct
Definition DataHeader.h:623
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