Project
Loading...
Searching...
No Matches
ASoA.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 "Framework/ASoA.h"
13#include "ArrowDebugHelpers.h"
15#include <arrow/util/key_value_metadata.h>
16#include <arrow/util/config.h>
17#include <TMemFile.h>
18#include <TClass.h>
19#include <TTree.h>
20#include <TH1.h>
21#include <TError.h>
22
23namespace o2::soa
24{
25void accessingInvalidIndexFor(const char* getter)
26{
27 throw o2::framework::runtime_error_f("Accessing invalid index for %s", getter);
28}
29void dereferenceWithWrongType(const char* getter, const char* target)
30{
31 throw o2::framework::runtime_error_f("Trying to dereference index with a wrong type in %s_as<T> for base target \"%s\". Note that if you have several compatible index targets in your process() signature, the last one will be the one actually bound.", getter, target);
32}
34{
35 throw o2::framework::runtime_error_f("Null selection for %d (arg %d), missing Filter declaration?", hash, ai);
36}
37
38void getterNotFound(const char* targetColumnLabel)
39{
40 throw o2::framework::runtime_error_f("Getter for \"%s\" not found", targetColumnLabel);
41}
42
44{
45 throw framework::runtime_error("columnLabel: must not be empty");
46}
47
49{
51 rows.resize(sel->GetNumSlots());
52 for (auto i = 0; i < sel->GetNumSlots(); ++i) {
53 rows[i] = sel->GetIndex(i);
54 }
55 return rows;
56}
57
58SelectionVector sliceSelection(std::span<int64_t const> const& mSelectedRows, int64_t nrows, uint64_t offset)
59{
60 auto start = offset;
61 auto end = start + nrows;
62 auto start_iterator = std::lower_bound(mSelectedRows.begin(), mSelectedRows.end(), start);
63 auto stop_iterator = std::lower_bound(start_iterator, mSelectedRows.end(), end);
64 SelectionVector slicedSelection{start_iterator, stop_iterator};
65 std::ranges::transform(slicedSelection.begin(), slicedSelection.end(), slicedSelection.begin(),
66 [&start](int64_t idx) {
67 return idx - static_cast<int64_t>(start);
68 });
69 return slicedSelection;
70}
71
72namespace
73{
74template <typename T>
75 requires(std::same_as<T, std::string>)
76auto makeString(T const& str)
77{
78 return str.c_str();
79}
80template <typename T>
81 requires(std::same_as<T, const char*>)
82auto makeString(T const& str)
83{
84 return str;
85}
86
87template <typename T>
88void canNotJoin(std::vector<std::shared_ptr<arrow::Table>> const& tables, std::span<T> labels)
89{
90 for (auto i = 0U; i < tables.size() - 1; ++i) {
91 if (tables[i]->num_rows() != tables[i + 1]->num_rows()) {
92 throw o2::framework::runtime_error_f("Tables %s and %s have different sizes (%lld vs %lld) and cannot be joined!",
93 makeString(labels[i]), makeString(labels[i + 1]), (long long)tables[i]->num_rows(), (long long)tables[i + 1]->num_rows());
94 }
95 }
96}
97
98template <typename T>
99void IncompatibleRanges(std::vector<ArrowTableRef> const& tables, std::span<T> labels)
100{
101 auto loc = std::ranges::adjacent_find(tables, [](auto const& l, auto const& r) { return l.range != r.range; });
102 if (loc != std::ranges::cend(tables)) {
103 auto pos = std::distance(tables.begin(), loc);
104 auto next = loc + 1;
105 if (loc->range.size != next->range.size) {
106 if (labels.empty()) {
107 throw o2::framework::runtime_error_f("Tables at positions %d and %d have different sizes (%lld vs %lld) and cannot be joined!",
108 (int)pos, (int)pos + 1, (long long)loc->range.size, (long long)next->range.size);
109 }
110 throw o2::framework::runtime_error_f("Tables %s and %s have different sizes (%lld vs %lld) and cannot be joined!",
111 makeString(labels[pos]), makeString(labels[pos + 1]), (long long)loc->range.size, (long long)next->range.size);
112 }
113 if (labels.empty()) {
114 throw o2::framework::runtime_error_f("Incompatible ranges at %d: (%llu, %lld) vs. (%llu, %lld)",
115 (int)pos, (unsigned long long)loc->range.offset, (long long)loc->range.size, (unsigned long long)next->range.offset, (long long)next->range.size);
116 }
117 throw o2::framework::runtime_error_f("Incompatible ranges at %d between %s and %s: (%llu, %lld) vs. (%llu, %lld)",
118 (int)pos, makeString(labels[pos]), makeString(labels[pos + 1]), (unsigned long long)loc->range.offset, (long long)loc->range.size, (unsigned long long)next->range.offset, (long long)next->range.size);
119 }
120}
121
122std::shared_ptr<arrow::Table> joinTablesImpl(std::ranges::input_range auto tables)
123{
124 std::vector<std::shared_ptr<arrow::Field>> fields;
125 std::vector<std::shared_ptr<arrow::ChunkedArray>> columns;
126 bool notEmpty = (tables.front()->num_rows() != 0);
127 std::ranges::for_each(tables, [&fields, &columns, notEmpty](auto const& t) {
128 std::ranges::copy(t->fields(), std::back_inserter(fields));
129 if (notEmpty) {
130 std::ranges::copy(t->columns(), std::back_inserter(columns));
131 }
132 });
133 auto schema = std::make_shared<arrow::Schema>(fields);
134 return arrow::Table::Make(schema, columns);
135}
136
137template <typename T>
138ArrowTableRef joinTablesImpl(std::ranges::input_range auto tables, std::span<T> labels)
139{
140 if (tables.size() == 1) {
141 return tables.front();
142 }
143 IncompatibleRanges(tables, labels);
144 ArrowRange commonRange{tables.front().range};
145 return {joinTablesImpl(tables), commonRange};
146}
147} // namespace
148
149o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables)
150{
151 std::vector<ArrowTableRef> refs;
152 std::ranges::transform(tables, std::back_inserter(refs), [](auto const& table) { return ArrowTableRef{table}; });
153 return joinTablesImpl(refs, std::span<const char* const>());
154}
155
156o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<o2::soa::ArrowTableRef>&& tables)
157{
158 return joinTablesImpl(tables, std::span<const char* const>());
159}
160
161o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<o2::soa::ArrowTableRef>&& tables, std::span<const char* const> labels)
162{
163 return joinTablesImpl(tables, labels);
164}
165
166o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<o2::soa::ArrowTableRef>&& tables, std::span<const std::string> labels)
167{
168 return joinTablesImpl(tables, labels);
169}
170
171o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables, std::span<const char* const> labels)
172{
173 canNotJoin(tables, labels);
174 return o2::soa::ArrowTableRef{joinTablesImpl(tables)};
175}
176
177o2::soa::ArrowTableRef ArrowHelpers::joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables, std::span<const std::string> labels)
178{
179 canNotJoin(tables, labels);
180 return o2::soa::ArrowTableRef{joinTablesImpl(tables)};
181}
182
183o2::soa::ArrowTableRef ArrowHelpers::concatTables(std::vector<o2::soa::ArrowTableRef>&& tables)
184{
185 if (tables.size() == 1) {
186 return tables.front();
187 }
188 std::vector<std::shared_ptr<arrow::ChunkedArray>> columns;
189 std::vector<std::shared_ptr<arrow::Field>> resultFields = tables.front()->schema()->fields();
190 auto compareFields = [](std::shared_ptr<arrow::Field> const& f1, std::shared_ptr<arrow::Field> const& f2) {
191 // Let's do this with stable sorting.
192 return (!f1->Equals(f2)) && (f1->name() < f2->name());
193 };
194
195 for (auto i = 1; i < tables.size(); ++i) {
196 auto const& fields = tables[i]->fields();
197 std::vector<std::shared_ptr<arrow::Field>> intersection;
198 std::ranges::set_intersection(resultFields, fields, std::back_inserter(intersection), compareFields);
199 resultFields.swap(intersection);
200 }
201
202 for (auto const& field : resultFields) {
203 arrow::ArrayVector chunks;
204 for (auto const& table : tables) {
205 auto ci = table->schema()->GetFieldIndex(field->name());
206 if (ci == -1) {
207 throw framework::runtime_error_f("Unable to find field {}", field->name().c_str());
208 }
209 auto column = table->column(ci);
210 auto otherChunks = column->chunks();
211 chunks.insert(chunks.end(), otherChunks.begin(), otherChunks.end());
212 }
213 columns.push_back(std::make_shared<arrow::ChunkedArray>(chunks));
214 }
215
216 return {arrow::Table::Make(std::make_shared<arrow::Schema>(resultFields), columns)};
217}
218
219arrow::ChunkedArray* getIndexFromLabel(arrow::Table* table, std::string_view label)
220{
221 // Take the exact-match common case first (string_view comparison checks length
222 // then memcmp), and fall back to a case-insensitive scan only when the labels
223 // differ in case.
224 auto field = std::ranges::find_if(table->schema()->fields(), [label](std::shared_ptr<arrow::Field> const& f) {
225 std::string_view name = f->name();
226 return label == name ||
227 std::ranges::equal(label, name, [](char c1, char c2) {
228 return asciiToLower(c1) == asciiToLower(c2);
229 });
230 });
231 if (field == table->schema()->fields().end()) {
232 o2::framework::throw_error(o2::framework::runtime_error_f("Unable to find column with label %s.", label));
233 }
234 return table->column(std::distance(table->schema()->fields().begin(), field)).get();
235}
236
237void notBoundTable(const char* tableName)
238{
239 throw o2::framework::runtime_error_f("Index pointing to %s is not bound! Did you subscribe to the table?", tableName);
240}
241
242void notFoundColumn(const char* label, const char* key)
243{
244 throw o2::framework::runtime_error_f(R"(Preslice not valid: table "%s" (or join based on it) does not have column "%s")", label, key);
245}
246
247void missingOptionalPreslice(const char* label, const char* key)
248{
249 throw o2::framework::runtime_error_f(R"(Optional Preslice with missing binding used: table "%s" (or join based on it) does not have column "%s")", label, key);
250}
251
252void* extractCCDBPayload(char* payload, size_t size, TClass const* cl, const char* what)
253{
254 Int_t previousErrorLevel = gErrorIgnoreLevel;
255 gErrorIgnoreLevel = kFatal;
256 // does it have a flattened headers map attached in the end?
257 TMemFile file("name", (char*)payload, size, "READ");
258 gErrorIgnoreLevel = previousErrorLevel;
259 if (file.IsZombie()) {
260 return nullptr;
261 }
262
263 if (!cl) {
264 return nullptr;
265 }
266 auto object = file.GetObjectChecked(what, cl);
267 if (!object) {
268 // it could be that object was stored with previous convention
269 // where the classname was taken as key
270 std::string objectName(cl->GetName());
271 objectName.erase(std::find_if(objectName.rbegin(), objectName.rend(), [](unsigned char ch) {
272 return !std::isspace(ch);
273 }).base(),
274 objectName.end());
275 objectName.erase(objectName.begin(), std::find_if(objectName.begin(), objectName.end(), [](unsigned char ch) {
276 return !std::isspace(ch);
277 }));
278
279 object = file.GetObjectChecked(objectName.c_str(), cl);
280 LOG(warn) << "Did not find object under expected name " << what;
281 if (!object) {
282 return nullptr;
283 }
284 LOG(warn) << "Found object under deprecated name " << cl->GetName();
285 }
286 auto result = object;
287 // We need to handle some specific cases as ROOT ties them deeply
288 // to the file they are contained in
289 if (cl->IsTObject()) {
290 // make a clone
291 // detach from the file
292 auto tree = dynamic_cast<TTree*>((TObject*)object);
293 if (tree) {
294 tree->LoadBaskets(0x1L << 32); // make tree memory based
295 tree->SetDirectory(nullptr);
296 result = tree;
297 } else {
298 auto h = dynamic_cast<TH1*>((TObject*)object);
299 if (h) {
300 h->SetDirectory(nullptr);
301 result = h;
302 }
303 }
304 }
305 return result;
306}
307
309{
310 return [newOrigin](framework::ConcreteDataMatcher&& m) {
311 if ((m.origin == header::DataOrigin{"AOD"}) && (newOrigin != header::DataOrigin{"AOD"})) {
312 m.origin = newOrigin;
313 }
314 return m;
315 };
316}
317
318} // namespace o2::soa
319
320namespace o2::framework
321{
322std::string cutString(std::string&& str)
323{
324 auto pos = str.find('_');
325 if (pos != std::string::npos) {
326 str.erase(pos);
327 }
328 return str;
329}
330
331std::string strToUpper(std::string&& str)
332{
333 std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::toupper(c); });
334 return str;
335}
336
338{
339 return binding == "[MISSING]";
340}
341
343{
344 return bindingKey;
345}
346
351
356
358{
359 auto [offset_, count] = this->sliceInfo.getSliceFor(value);
360 return input.slice({static_cast<uint64_t>(offset_), count});
361}
362
363std::span<const int64_t> PreslicePolicyGeneral::getSliceFor(int value) const
364{
365 return this->sliceInfo.getSliceFor(value);
366}
367} // namespace o2::framework
uint32_t hash
std::shared_ptr< arrow::Schema > schema
std::vector< std::shared_ptr< arrow::Field > > fields
int32_t i
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
std::vector< o2::MCCompLabel > labels
uint16_t pos
Definition RawData.h:3
uint32_t c
Definition RawData.h:2
XrdCl::ChunkList chunks
StringRef key
Class for time synchronization of RawReader instances.
const GLfloat * m
Definition glcorearb.h:4066
GLint GLsizei count
Definition glcorearb.h:399
GLuint64EXT * result
Definition glcorearb.h:5662
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLuint end
Definition glcorearb.h:469
GLdouble f
Definition glcorearb.h:310
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLintptr offset
Definition glcorearb.h:660
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLuint object
Definition glcorearb.h:4041
std::shared_ptr< gandiva::SelectionVector > Selection
Definition Expressions.h:45
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
RuntimeErrorRef runtime_error(const char *)
void throw_error(RuntimeErrorRef)
std::string strToUpper(std::string &&str)
Definition ASoA.cxx:331
RuntimeErrorRef runtime_error_f(const char *,...)
std::string cutString(std::string &&str)
Definition ASoA.cxx:322
void * extractCCDBPayload(char *payload, size_t size, TClass const *cl, const char *what)
Definition ASoA.cxx:252
SelectionVector selectionToVector(gandiva::Selection const &sel)
Definition ASoA.cxx:48
void notBoundTable(const char *tableName)
Definition ASoA.cxx:237
SelectionVector sliceSelection(std::span< int64_t const > const &mSelectedRows, int64_t nrows, uint64_t offset)
Definition ASoA.cxx:58
std::vector< int64_t > SelectionVector
Definition ASoA.h:444
void missingFilterDeclaration(int hash, int ai)
Definition ASoA.cxx:33
void accessingInvalidIndexFor(const char *getter)
Definition ASoA.cxx:25
void dereferenceWithWrongType(const char *getter, const char *target)
Definition ASoA.cxx:29
void emptyColumnLabel()
Definition ASoA.cxx:43
void getterNotFound(const char *targetColumnLabel)
Definition ASoA.cxx:38
void missingOptionalPreslice(const char *label, const char *key)
Definition ASoA.cxx:247
std::function< framework::ConcreteDataMatcher(framework::ConcreteDataMatcher &&)> originReplacement(header::DataOrigin newOrigin)
Definition ASoA.cxx:308
arrow::ChunkedArray * getIndexFromLabel(arrow::Table *table, std::string_view label)
Definition ASoA.cxx:219
void notFoundColumn(const char *label, const char *key)
Definition ASoA.cxx:242
const std::string binding
Definition ASoA.h:1424
Entry const & getBindingKey() const
Definition ASoA.cxx:342
SliceInfoUnsortedPtr sliceInfo
Definition ASoA.h:1441
std::span< const int64_t > getSliceFor(int value) const
Definition ASoA.cxx:363
void updateSliceInfo(SliceInfoUnsortedPtr &&si)
Definition ASoA.cxx:352
o2::soa::ArrowTableRef getSliceFor(int value, o2::soa::ArrowTableRef const &input) const
Definition ASoA.cxx:357
void updateSliceInfo(SliceInfoPtr &&si)
Definition ASoA.cxx:347
std::pair< int64_t, int64_t > getSliceFor(int value) const
std::span< int64_t const > getSliceFor(int value) const
static o2::soa::ArrowTableRef joinTables(std::vector< std::shared_ptr< arrow::Table > > &&tables)
Definition ASoA.cxx:149
static o2::soa::ArrowTableRef concatTables(std::vector< o2::soa::ArrowTableRef > &&tables)
Definition ASoA.cxx:183
ArrowTableRef slice(ArrowRange newRange) const
Definition ArrowTypes.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::vector< ReadoutWindowData > rows
const std::string str