ATLAS Offline Software
Loading...
Searching...
No Matches
ColumnReaderBranch.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef COLUMNAR_TEST_FIXTURES_COLUMN_READER_BRANCH_H
9#define COLUMNAR_TEST_FIXTURES_COLUMN_READER_BRANCH_H
10
12
13#include <AthLinks/ElementLink.h>
19#include <SGCore/sgkey_t.h>
21
27
28namespace columnar
29{
30 namespace TestUtils
31 {
32 class LinkColumnVector final
33 {
36 public:
37
39
41 {
42 if (!m_unknownKeysAllowedTargets.empty())
43 {
44 std::cout << "found unknown keys for " << m_columnName << ":";
45 for (auto& [key, allowedSet] : m_unknownKeysAllowedTargets)
46 {
47 std::cout << " " << std::hex << key << std::dec << " (allowed targets:";
48 for (auto index : allowedSet)
49 std::cout << " " << m_targetNames.at(index);
50 std::cout << ")";
51 }
52 }
53 }
54
55 [[nodiscard]] std::vector<std::string> connect (const ColumnInfo& columnInfo, const std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& offsetColumns, const std::unordered_map<std::string,ColumnInfo>& requestedColumns)
56 {
57 m_columnName = columnInfo.name;
58 std::vector<std::string> keyColumnNames;
59 if (!columnInfo.soleLinkTargetName.empty())
60 {
61 addTarget (columnInfo.soleLinkTargetName, offsetColumns, columnInfo.soleLinkTargetClid);
62 } else
63 {
64 for (auto& [requestedName, requestedInfo] : requestedColumns)
65 {
66 if (requestedInfo.keyColumnForVariantLink == m_columnName)
67 {
68 keyColumnNames.push_back (requestedName);
69 m_keysColumns.emplace_back();
70 for (const auto& targetName : requestedInfo.variantLinkTargetNames)
71 addTarget (targetName, offsetColumns);
72 }
73 }
74 if (m_keysColumns.empty())
75 throw std::runtime_error ("no key column found for variant link: " + m_columnName);
76 }
77 return keyColumnNames;
78 }
79
80 void clear ()
81 {
82 m_columnData.clear();
83 }
84
85 void checkOffsets (unsigned eventIndex)
86 {
87 for (std::size_t i = 0; i < m_targetNames.size(); ++ i)
88 {
89 auto& targetOffsetColumn = *m_targetOffsetColumns.at(i);
90 if (eventIndex + 1 >= targetOffsetColumn.size())
91 throw std::runtime_error ("target offset column not yet filled for: " + m_targetNames.at(i) + " when checking link column " + m_columnName);
92 }
93 }
94
95 template<typename T>
96 void addLink (const ElementLink<T>& element, unsigned eventIndex)
97 {
98 if (element.isDefault())
99 {
100 addEmptyLink();
101 return;
102 }
103
104 addSplitLink (element.index(), element.key(), eventIndex);
105 }
106
108 {
110 }
111
112 void addSplitLink (std::size_t linkIndex, SG::sgkey_t linkKey, unsigned eventIndex)
113 {
114 if (linkIndex == 0 && linkKey == 0)
115 {
116 addEmptyLink();
117 return;
118 }
119
120 unsigned targetIndex = 0u;
121 while (targetIndex < m_targetKeys.size() && m_targetKeys.at(targetIndex) != linkKey)
122 ++ targetIndex;
123
124 // We didn't find the key, so we try to figure out which of the
125 // targets it could be. The idea is that you wouldn't rely on
126 // this for real tests, but that you then go and fill in those
127 // keys in the central lookup table. It will always record and
128 // report, that means if there is a variant link with extra
129 // targets you didn't declare you will get a diagnostic. This
130 // may be overly cautious, but it gives an extra diagnostic if
131 // maybe you missed a target.
132 if (targetIndex == m_targetKeys.size())
133 {
134 if (!m_unknownKeysAllowedTargets.contains (linkKey))
135 {
136 auto& allowedSet = m_unknownKeysAllowedTargets[linkKey];
137 for (std::size_t i = 0; i < m_targetKeys.size(); ++ i)
138 {
139 if (m_targetKeys.at(i) == 0)
140 allowedSet.insert(i);
141 }
142 }
143 auto& allowedSet = m_unknownKeysAllowedTargets[linkKey];
144 for (auto iter = allowedSet.begin(); iter != allowedSet.end();)
145 {
146 auto index = *iter;
147 auto& targetOffsetColumn = *m_targetOffsetColumns.at(index);
148 if (eventIndex + 1 >= targetOffsetColumn.size())
149 throw std::runtime_error ("target offset column not yet filled for: " + m_targetNames.at(index));
150 if (targetOffsetColumn.at(eventIndex) + linkIndex >= targetOffsetColumn.at(eventIndex + 1))
151 iter = allowedSet.erase(iter);
152 else
153 ++ iter;
154 }
155 // Not quite sure whether it is safer to use or not use one of
156 // the targets from the allowed set in this case. In general
157 // tools are expected to handle invalid links gracefully,
158 // worst case they throw an exception when trying to access
159 // it. So what I came up with is that for variant links we
160 // assume it invalid, but for non-variant links the tool
161 // expects exactly one target and we either found it or throw
162 // an exception.
163 if (m_keysColumns.empty())
164 {
165 if (allowedSet.size() == 1 && m_targetKeys.at(*allowedSet.begin()) == 0 && m_unknownKeysAllowedTargets.size() == 1)
166 targetIndex = *allowedSet.begin();
167 else
168 {
169 std::ostringstream error;
170 error << "target key mismatch: read sgkey " << std::hex << linkKey << std::dec;
171 error << " for column " << m_columnName << " with element index " << linkIndex << " targeting " << m_targetNames.at(0);
172 if (m_targetKeys.at(0) != 0u)
173 {
174 error << ", expected sgkey " << std::hex << m_targetKeys.at(0) << std::dec;
175 } else if (m_unknownKeysAllowedTargets.size() > 1)
176 {
177 error << ", alternate key found for non-variant link:";
178 for (auto& [key, allowedSet] : m_unknownKeysAllowedTargets)
179 {
180 if (key != linkKey)
181 error << " " << std::hex << key << std::dec;
182 }
183 } else
184 {
185 error << ", no expected sgkey configured but the maximum allowed index for the target is " << m_targetOffsetColumns.at(0)->at(eventIndex + 1) - m_targetOffsetColumns.at(0)->at(eventIndex) - 1;
186 }
187 throw std::runtime_error (std::move (error).str());
188 }
189 }
190 }
191
192 if (targetIndex == m_targetKeys.size())
193 {
194 // this creates a link with an unknown key, which the user
195 // will ignore
196 m_columnData.push_back (CM::mergeLinkKeyIndex (0xff, linkIndex));
197 return;
198 }
199
200 auto& targetOffsetColumn = *m_targetOffsetColumns.at(targetIndex);
201 if (eventIndex + 1 >= targetOffsetColumn.size())
202 throw std::runtime_error ("target offset column not yet filled for: " + m_targetNames.at(targetIndex));
203 auto myLinkIndex = linkIndex + targetOffsetColumn.at(eventIndex);
204 if (myLinkIndex >= targetOffsetColumn.at(eventIndex + 1))
205 throw std::runtime_error ("index out of range for link: " + m_columnName + " with element index " + std::to_string(linkIndex) + " targeting " + m_targetNames.at(targetIndex) + " with offset " + std::to_string(targetOffsetColumn.at(eventIndex)) + " and next offset " + std::to_string(targetOffsetColumn.at(eventIndex + 1)));
206
207 m_columnData.push_back (CM::mergeLinkKeyIndex (targetIndex, myLinkIndex));
208 }
209
210 [[nodiscard]] std::size_t size () const noexcept
211 {
212 return m_columnData.size();
213 }
214
215 [[nodiscard]] const typename CM::LinkIndexType* data () const noexcept
216 {
217 return m_columnData.data();
218 }
219
220 [[nodiscard]] auto begin () const noexcept { return m_columnData.begin(); }
221 [[nodiscard]] auto end () const noexcept { return m_columnData.end(); }
222
223 [[nodiscard]] const std::vector<typename CM::LinkKeyType>& keysColumn (std::size_t index) const
224 {
225 return m_keysColumns.at(index);
226 }
227
228
229
232 private:
233
234 std::vector<typename CM::LinkIndexType> m_columnData;
235
236 std::string m_columnName;
237
238 std::vector<std::string> m_targetNames;
239 std::vector<SG::sgkey_t> m_targetKeys;
240 std::vector<const std::vector<ColumnarOffsetType>*> m_targetOffsetColumns;
241
242 // there can be multiple keys-columns, hence this is a vector of
243 // vectors. if this is empty, then it is a single-target link
244 std::vector<std::vector<typename CM::LinkKeyType>> m_keysColumns;
245
246 std::unordered_map<SG::sgkey_t,std::unordered_set<std::size_t>> m_unknownKeysAllowedTargets;
247
248
249
250 void addTarget (const std::string& name, const std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& offsetColumns, std::uint32_t clid = 0)
251 {
252 unsigned targetIndex = 0;
253 while (targetIndex < m_targetNames.size() && m_targetNames.at(targetIndex) != name)
254 ++ targetIndex;
255 if (targetIndex == m_targetNames.size())
256 {
257 m_targetNames.push_back(name);
258 if (auto offsetIter = offsetColumns.find (name); offsetIter != offsetColumns.end())
259 m_targetOffsetColumns.push_back (offsetIter->second);
260 else
261 throw std::runtime_error ("missing offset column: " + name);
262 if (clid != 0)
263 m_targetKeys.push_back (computeSgKey (name, clid));
264 else if (auto keyIter = knownSgKeys.find (name); keyIter != knownSgKeys.end())
265 m_targetKeys.push_back (keyIter->second);
266 else
267 m_targetKeys.push_back (0);
268 }
269 if (!m_keysColumns.empty())
270 m_keysColumns.back().push_back (targetIndex);
271 }
272 };
273
274
275
276 template <typename T, template <typename> class Reader>
278 {
279 Reader<T> branchReader;
282 std::vector<T> outData;
283 unsigned entries = 0;
284
285 explicit ColumnReaderScalar (const std::string& val_branchName)
286 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
287 {
288 outputColumns.push_back ({.name = branchReader.columnName()});
289 }
290
291 virtual bool connect( Backend source, std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& /*offsetColumns*/,std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
292 {
293 auto iter = requestedColumns.find (outputColumns.at(0).name);
294 if (iter == requestedColumns.end())
295 return false;
296 outputColumns.at(0).enabled = true;
297 requestedColumns.erase (iter);
298
299 branchReader.connectTree (source);
300
301 return true;
302 }
303 virtual void clearColumns () override
304 {
305 outData.clear ();
306 }
307
308 virtual void getEntry (Long64_t entry) override
309 {
310 benchmark.startTimer ();
311 const auto& branchData = branchReader.getEntry (entry);
312 benchmark.stopTimer ();
313 benchmarkUnpack.startTimer ();
314 outData.push_back (branchData);
315 benchmarkUnpack.stopTimer ();
316 }
317
318 virtual void setData (ColumnVectorData& columnData) override
319 {
320 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
321 columnData.setColumn (outputColumns.at(0).columnIndex, outData.size(), outData.data());
322 }
323
324 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
325 {
326 BranchPerfData result;
327 result.name = branchReader.columnName();
328 result.timeRead = benchmark.getEntryTime(emptyTime);
329 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
330 benchmark.setSilence();
331 benchmarkUnpack.setSilence();
332 result.entrySize = branchReader.entrySize();
333 result.uncompressedSize = branchReader.uncompressedSize();
334 result.numBaskets = branchReader.numBaskets();
335 result.entries = entries;
336 return result;
337 }
338
339 virtual void collectColumnData () override
340 {
341 entries += outData.size();
342 }
343 };
344
345 template <typename T, template <typename> class Reader>
347 {
348 Reader<std::vector<T>> branchReader;
349 const std::vector<ColumnarOffsetType>* offsetColumn = nullptr;
350 std::vector<ColumnarOffsetType> offsets = {0};
351 std::vector<T> outData;
354 unsigned entries = 0;
355
356 explicit ColumnReaderVector (const std::string& val_branchName)
357 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
358 {
359 outputColumns.push_back ({.name = branchReader.columnName()});
360 outputColumns.push_back ({.name = branchReader.containerName(), .isOffset = true, .primary = false});
361 }
362
363 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
364 {
365 auto iter = requestedColumns.find (outputColumns.at(0).name);
366 if (iter == requestedColumns.end())
367 return false;
368 outputColumns.at(0).enabled = true;
369
370 branchReader.connectTree(source);
371
372 if (iter->second.offsetName != outputColumns.at(1).name)
373 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
374
375 requestedColumns.erase (iter);
376
377 if (auto offsetIter = offsetColumns.find (outputColumns.at(1).name); offsetIter != offsetColumns.end())
378 offsetColumn = offsetIter->second;
379 else
380 offsetColumns.emplace (outputColumns.at(1).name, &offsets);
381
382 iter = requestedColumns.find (outputColumns.at(1).name);
383 if (iter != requestedColumns.end())
384 {
385 requestedColumns.erase (iter);
386 outputColumns.at(1).enabled = true;
387 }
388
389 return true;
390 }
391
392 virtual void clearColumns () override
393 {
394 offsets.clear ();
395 offsets.push_back (0);
396 outData.clear ();
397 }
398
399 virtual void getEntry (Long64_t entry) override
400 {
401 benchmark.startTimer ();
402 const auto& branchData = branchReader.getEntry (entry);
403 benchmark.stopTimer ();
404 benchmarkUnpack.startTimer ();
405 outData.insert (outData.end(), branchData.begin(), branchData.end());
406 offsets.push_back (outData.size());
407 benchmarkUnpack.stopTimer ();
408 }
409
410 virtual void setData (ColumnVectorData& columnData) override
411 {
412 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
413 columnData.setColumn (outputColumns.at(0).columnIndex, outData.size(), outData.data());
414 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
415 columnData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
416 if (offsetColumn)
417 {
418 if (offsetColumn->size() != offsets.size())
419 throw std::runtime_error ("offset column not filled yet: " + outputColumns.at(1).name);
420 if (offsetColumn->back() != offsets.back())
421 throw std::runtime_error ("offset column does not match: " + outputColumns.at(1).name);
422 }
423 }
424
425 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
426 {
427 BranchPerfData result;
428 result.name = branchReader.columnName();
429 result.timeRead = benchmark.getEntryTime(emptyTime);
430 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
431 benchmark.setSilence();
432 benchmarkUnpack.setSilence();
433 result.entrySize = branchReader.entrySize();
434 result.uncompressedSize = branchReader.uncompressedSize();
435 result.numBaskets = branchReader.numBaskets();
436 result.entries = entries;
437 return result;
438 }
439
440 virtual void collectColumnData () override
441 {
442 entries += outData.size();
443 }
444 };
445
446 template <typename T, template <typename> class Reader>
448 {
449 Reader<std::vector<std::vector<T>>> branchReader;
450 std::vector<ColumnarOffsetType> offsets = {0};
451 std::vector<T> columnData;
454 unsigned entries = 0;
455
456 explicit ColumnReaderVectorVector (const std::string& val_branchName)
457 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
458 {
459 outputColumns.push_back ({.name = branchReader.columnName() + ".data"});
460 outputColumns.push_back ({.name = branchReader.columnName() + ".offset", .isOffset = true});
461 }
462
463 virtual bool connect(Backend source, std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& /*offsetColumns*/, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
464 {
465 auto iter = requestedColumns.find (outputColumns.at(0).name);
466 if (iter == requestedColumns.end())
467 return false;
468 outputColumns.at(0).enabled = true;
469
470 branchReader.connectTree(source);
471
472 if (iter->second.offsetName != outputColumns.at(1).name)
473 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
474
475 requestedColumns.erase (iter);
476
477 iter = requestedColumns.find (outputColumns.at(1).name);
478 if (iter == requestedColumns.end())
479 return true;
480 requestedColumns.erase (iter);
481 outputColumns.at(1).enabled = true;
482 return true;
483 }
484
485 virtual void clearColumns () override
486 {
487 columnData.clear();
488 offsets.clear();
489 offsets.push_back (0);
490 }
491
492 virtual void getEntry (Long64_t entry) override
493 {
494 benchmark.startTimer ();
495 const auto& branchData = branchReader.getEntry (entry);
496 benchmark.stopTimer ();
497 benchmarkUnpack.startTimer ();
498 for (auto& data : branchData)
499 {
500 columnData.insert (columnData.end(), data.begin(), data.end());
501 offsets.push_back (columnData.size());
502 }
503 benchmarkUnpack.stopTimer ();
504 }
505
506 virtual void setData (ColumnVectorData& colData) override
507 {
508 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
509 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
510 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
511 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
512 }
513
514 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
515 {
516 BranchPerfData result;
517 result.name = branchReader.columnName();
518 result.timeRead = benchmark.getEntryTime(emptyTime);
519 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
520 benchmark.setSilence();
521 benchmarkUnpack.setSilence();
522 result.entrySize = branchReader.entrySize();
523 result.uncompressedSize = branchReader.uncompressedSize();
524 result.numBaskets = branchReader.numBaskets();
525 result.entries = entries;
526 return result;
527 }
528
529 virtual void collectColumnData () override
530 {
531 entries += columnData.size();
532 }
533 };
534
535 template <typename T, template <typename> class Reader>
537 {
539 Reader<std::vector<std::vector<ElementLink<T>>>> branchReader;
540 std::vector<ColumnarOffsetType> offsets = {0};
541 std::vector<ColumnarOffsetType> eventOffsets = {0};
545 unsigned entries = 0;
546 unsigned nullEntries = 0;
547
548 explicit ColumnReaderVectorVectorLink (const std::string& val_branchName)
549 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
550 {
551 outputColumns.push_back ({.name = branchReader.columnName() + ".data"});
552 outputColumns.push_back ({.name = branchReader.columnName() + ".offset", .isOffset = true});
553 }
554
555 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
556 {
557 auto iter = requestedColumns.find (outputColumns.at(0).name);
558 if (iter == requestedColumns.end())
559 return false;
560 outputColumns.at(0).enabled = true;
561
562 branchReader.connectTree(source);
563
564 if (iter->second.offsetName != outputColumns.at(1).name)
565 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
566 for (const auto & keyColumn : columnData.connect (iter->second, offsetColumns, requestedColumns))
567 {
568 outputColumns.push_back ({.name = keyColumn, .primary = false, .enabled = true});
569 requestedColumns.erase (keyColumn);
570 }
571
572 requestedColumns.erase (iter);
573
574 iter = requestedColumns.find (outputColumns.at(1).name);
575 if (iter == requestedColumns.end())
576 return true;
577 requestedColumns.erase (iter);
578 outputColumns.at(1).enabled = true;
579 return true;
580 }
581
582 virtual void clearColumns () override
583 {
584 columnData.clear();
585 offsets.clear();
586 offsets.push_back (0);
587 eventOffsets.clear();
588 eventOffsets.push_back (0);
589 }
590
591 virtual void getEntry (Long64_t entry) override
592 {
593 benchmark.startTimer ();
594 const auto& branchData = branchReader.getEntry (entry);
595 benchmark.stopTimer ();
596 benchmarkUnpack.startTimer ();
597 columnData.checkOffsets (eventOffsets.size() - 1);
598 for (auto& data : branchData)
599 {
600 for (auto& element : data)
601 {
602 columnData.addLink (element, eventOffsets.size()-1);
603 }
604 offsets.push_back (columnData.size());
605 }
606 eventOffsets.push_back (offsets.size());
607 benchmarkUnpack.stopTimer ();
608 }
609
610 virtual void setData (ColumnVectorData& colData) override
611 {
612 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
613 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
614 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
615 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
616 for (std::size_t i = 2; i < outputColumns.size(); ++ i)
617 {
618 if (outputColumns.at(i).columnIndex != ColumnVectorHeader::nullIndex)
619 colData.setColumn (outputColumns.at(i).columnIndex, columnData.keysColumn(i-2).size(), columnData.keysColumn(i-2).data());
620 }
621 }
622
623 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
624 {
625 BranchPerfData result;
626 result.name = branchReader.columnName();
627 result.timeRead = benchmark.getEntryTime(emptyTime);
628 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
629 benchmark.setSilence();
630 benchmarkUnpack.setSilence();
631 result.entrySize = branchReader.entrySize();
632 result.uncompressedSize = branchReader.uncompressedSize();
633 result.numBaskets = branchReader.numBaskets();
634 result.entries = entries;
635 result.nullEntries = nullEntries;
636 return result;
637 }
638
639 virtual void collectColumnData () override
640 {
641 entries += columnData.size();
642 for (const auto& index : columnData)
643 {
645 nullEntries += 1;
646 }
647 }
648 };
649
650 template <typename T, template <typename> class Reader>
652 {
653 std::string columnName;
654 Reader<std::vector<std::vector<std::vector<T>>>> branchReader;
655 std::vector<ColumnarOffsetType> outerOffsets = {0};
656 std::vector<ColumnarOffsetType> innerOffsets = {0};
657 std::vector<T> columnData;
660 unsigned entries = 0;
661
662 explicit ColumnReaderVectorVectorVector (const std::string& val_branchName)
664 {
665 outputColumns.push_back ({.name = branchReader.columnName() + ".data"});
666 outputColumns.push_back ({.name = branchReader.columnName() + ".innerOffset", .isOffset = true});
667 outputColumns.push_back ({.name = branchReader.columnName() + ".outerOffset", .isOffset = true});
668 }
669
670 virtual bool connect(Backend source, std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& /*offsetColumns*/, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
671 {
672 auto iter = requestedColumns.find (outputColumns.at(0).name);
673 if (iter == requestedColumns.end())
674 return false;
675 outputColumns.at(0).enabled = true;
676
677 branchReader.connectTree(source);
678
679 if (iter->second.offsetName != outputColumns.at(1).name)
680 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
681
682 requestedColumns.erase (iter);
683
684 iter = requestedColumns.find (outputColumns.at(1).name);
685 if (iter == requestedColumns.end())
686 return true;
687 outputColumns.at(1).enabled = true;
688
689 if (iter->second.offsetName != outputColumns.at(2).name)
690 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(2).name);
691
692 requestedColumns.erase (iter);
693
694 iter = requestedColumns.find (outputColumns.at(2).name);
695 if (iter == requestedColumns.end())
696 return true;
697 outputColumns.at(2).enabled = true;
698 requestedColumns.erase (iter);
699 return true;
700 }
701
702 virtual void clearColumns () override
703 {
704 columnData.clear();
705 innerOffsets.clear();
706 innerOffsets.push_back (0);
707 outerOffsets.clear();
708 outerOffsets.push_back (0);
709 }
710
711 virtual void getEntry (Long64_t entry) override
712 {
713 benchmark.startTimer ();
714 const auto& branchData = branchReader.getEntry (entry);
715 benchmark.stopTimer ();
716 benchmarkUnpack.startTimer ();
717 for (auto& outerData : branchData)
718 {
719 for (auto& innerData : outerData)
720 {
721 columnData.insert (columnData.end(), innerData.begin(), innerData.end());
722 innerOffsets.push_back (columnData.size());
723 }
724 outerOffsets.push_back (innerOffsets.size()-1);
725 }
726 benchmarkUnpack.stopTimer ();
727 }
728
729 virtual void setData (ColumnVectorData& colData) override
730 {
731 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
732 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
733 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
734 colData.setColumn (outputColumns.at(1).columnIndex, innerOffsets.size(), innerOffsets.data());
735 if (outputColumns.at(2).columnIndex != ColumnVectorHeader::nullIndex)
736 colData.setColumn (outputColumns.at(2).columnIndex, outerOffsets.size(), outerOffsets.data());
737 }
738
739 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
740 {
741 BranchPerfData result;
742 result.name = branchReader.columnName();
743 result.timeRead = benchmark.getEntryTime(emptyTime);
744 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
745 benchmark.setSilence();
746 benchmarkUnpack.setSilence();
747 result.entrySize = branchReader.entrySize();
748 result.uncompressedSize = branchReader.uncompressedSize();
749 result.numBaskets = branchReader.numBaskets();
750 result.entries = entries;
751 return result;
752 }
753
754 virtual void collectColumnData () override
755 {
756 entries += columnData.size();
757 }
758 };
759
760 template <typename T, template <typename> class Reader>
762 {
764 Reader<std::vector<ElementLink<T>>> branchReader;
765 const std::vector<ColumnarOffsetType>* offsetColumn = nullptr;
766 std::vector<ColumnarOffsetType> offsets = {0};
770 unsigned entries = 0;
771 unsigned nullEntries = 0;
772
773 ColumnReaderVectorLink (const std::string& val_branchName)
774 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
775 {
776 outputColumns.push_back ({.name = branchReader.columnName()});
777 outputColumns.push_back ({.name = branchReader.containerName(), .isOffset = true, .primary = false});
778 }
779
780
781 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
782 {
783 auto iter = requestedColumns.find (outputColumns.at(0).name);
784 if (iter == requestedColumns.end())
785 return false;
786 outputColumns.at(0).enabled = true;
787
788 branchReader.connectTree(source);
789
790 if (iter->second.offsetName != outputColumns.at(1).name)
791 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
792 for (const auto & keyColumn : columnData.connect (iter->second, offsetColumns, requestedColumns))
793 {
794 outputColumns.push_back ({.name = keyColumn, .primary = false, .enabled = true});
795 requestedColumns.erase (keyColumn);
796 }
797
798 requestedColumns.erase (iter);
799
800 if (auto offsetIter = offsetColumns.find (outputColumns.at(1).name); offsetIter != offsetColumns.end())
801 offsetColumn = offsetIter->second;
802 else
803 offsetColumns.emplace (outputColumns.at(1).name, &offsets);
804
805 iter = requestedColumns.find (outputColumns.at(1).name);
806 if (iter != requestedColumns.end())
807 {
808 outputColumns.at(1).enabled = true;
809 requestedColumns.erase (iter);
810 }
811
812 return true;
813 }
814
815 virtual void clearColumns () override
816 {
817 columnData.clear();
818 offsets.clear();
819 offsets.push_back (0);
820 }
821
822 virtual void getEntry (Long64_t entry) override
823 {
824 benchmark.startTimer ();
825 const auto& branchData = branchReader.getEntry (entry);
826 benchmark.stopTimer ();
827 benchmarkUnpack.startTimer ();
828 columnData.checkOffsets (offsets.size() - 1);
829 for (auto& element : branchData)
830 columnData.addLink (element, offsets.size()-1);
831 offsets.push_back (columnData.size());
832 if (offsetColumn)
833 {
834 if (offsetColumn->size() != offsets.size())
835 throw std::runtime_error ("offset column not filled yet: " + outputColumns.at(1).name);
836 if (offsetColumn->back() != offsets.back())
837 throw std::runtime_error ("offset column does not match: " + outputColumns.at(1).name);
838 }
839 benchmarkUnpack.stopTimer ();
840 }
841
842 virtual void setData (ColumnVectorData& colData) override
843 {
844 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
845 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
846 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
847 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
848 for (std::size_t i = 2; i < outputColumns.size(); ++ i)
849 {
850 if (outputColumns.at(i).columnIndex != ColumnVectorHeader::nullIndex)
851 colData.setColumn (outputColumns.at(i).columnIndex, columnData.keysColumn(i-2).size(), columnData.keysColumn(i-2).data());
852 }
853 }
854
855 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
856 {
857 BranchPerfData result;
858 result.name = branchReader.columnName();
859 result.timeRead = benchmark.getEntryTime(emptyTime);
860 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
861 benchmark.setSilence();
862 benchmarkUnpack.setSilence();
863 result.entrySize = branchReader.entrySize();
864 result.uncompressedSize = branchReader.uncompressedSize();
865 result.numBaskets = branchReader.numBaskets();
866 result.entries = entries;
867 result.nullEntries = nullEntries;
868 return result;
869 }
870
871 virtual void collectColumnData () override
872 {
873 entries += columnData.size();
874 for (const auto& index : columnData)
875 {
877 nullEntries += 1;
878 }
879 }
880 };
881
882 template <typename T, template <typename> class Reader>
884 {
886 Reader<std::vector<ElementLink<T>>> branchReader;
887 const std::vector<ColumnarOffsetType>* offsetColumn = nullptr;
888 std::vector<ColumnarOffsetType> offsets = {0};
892 unsigned entries = 0;
893 unsigned nullEntries = 0;
894
895 ColumnReaderVectorRLink(const std::string& val_branchName)
896 : branchReader(val_branchName), benchmarkUnpack(branchReader.columnName() + "(unpack)"), benchmark(branchReader.columnName())
897 {
898 outputColumns.push_back({.name = branchReader.columnName()});
899 outputColumns.push_back({.name = branchReader.containerName(), .isOffset = true, .primary = false});
900 }
901
902 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
903 {
904 auto iter = requestedColumns.find(outputColumns.at(0).name);
905 if (iter == requestedColumns.end())
906 return false;
907 outputColumns.at(0).enabled = true;
908
909 branchReader.connectTree(source);
910 if (iter->second.offsetName != outputColumns.at(1).name)
911 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
912
913 for (const auto & keyColumn : columnData.connect (iter->second, offsetColumns, requestedColumns))
914 {
915 outputColumns.push_back ({.name = keyColumn, .primary = false, .enabled = true});
916 requestedColumns.erase (keyColumn);
917 }
918 requestedColumns.erase (iter);
919
920 if (auto offsetIter = offsetColumns.find (outputColumns.at(1).name); offsetIter != offsetColumns.end())
921 offsetColumn = offsetIter->second;
922 else
923 offsetColumns.emplace (outputColumns.at(1).name, &offsets);
924
925 iter = requestedColumns.find (outputColumns.at(1).name);
926 if (iter != requestedColumns.end())
927 {
928 outputColumns.at(1).enabled = true;
929 requestedColumns.erase (iter);
930 }
931
932 return true;
933 }
934
935 virtual void clearColumns() override
936 {
937 columnData.clear();
938 offsets.clear();
939 offsets.push_back(0);
940 }
941
942 virtual void getEntry(Long64_t entry) override
943 {
944 benchmark.startTimer();
945 const auto& branchData = branchReader.getEntry(entry);
946 benchmark.stopTimer();
947 benchmarkUnpack.startTimer();
948
949 columnData.checkOffsets (offsets.size() - 1);
950 for (const auto& element : branchData)
951 {
952 if (element.isDefault() || element.index() == static_cast<unsigned int>(-1))
953 columnData.addEmptyLink ();
954 else
955 columnData.addSplitLink (element.index(), element.key(), offsets.size()-1);
956 }
957
958 offsets.push_back(columnData.size());
959
960 if (offsetColumn) {
961 if (offsetColumn->size() != offsets.size())
962 {
963 throw std::runtime_error("offset column not filled yet: " + outputColumns.at(1).name);
964 }
965 if (offsetColumn->back() != offsets.back())
966 {
967 throw std::runtime_error("offset column does not match: " + outputColumns.at(1).name);
968 }
969 }
970
971 benchmarkUnpack.stopTimer();
972 }
973
974 virtual void setData(ColumnVectorData& colData) override
975 {
976 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
977 colData.setColumn(outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
978 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
979 colData.setColumn(outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
980 for (std::size_t i = 2; i < outputColumns.size(); ++ i)
981 {
982 if (outputColumns.at(i).columnIndex != ColumnVectorHeader::nullIndex)
983 colData.setColumn (outputColumns.at(i).columnIndex, columnData.keysColumn(i-2).size(), columnData.keysColumn(i-2).data());
984 }
985 }
986
987 [[nodiscard]] virtual BranchPerfData getPerfData(float emptyTime) override
988 {
989 BranchPerfData result;
990 result.name = branchReader.columnName();
991 result.timeRead = benchmark.getEntryTime(emptyTime);
992 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
993 benchmark.setSilence();
994 benchmarkUnpack.setSilence();
995 result.entrySize = branchReader.entrySize();
996 result.uncompressedSize = branchReader.uncompressedSize();
997 result.numBaskets = branchReader.numBaskets();
998 result.entries = entries;
999 result.nullEntries = nullEntries;
1000 return result;
1001 }
1002
1003 virtual void collectColumnData() override
1004 {
1005 entries += columnData.size();
1006 for (const auto& index : columnData)
1007 {
1009 nullEntries += 1;
1010 }
1011 }
1012 };
1013
1014 template <typename T, template <typename> class Reader>
1016 {
1018 Reader<std::vector<std::vector<ElementLink<T>>>> branchReader;
1019 std::vector<ColumnarOffsetType> offsets = {0};
1020 std::vector<ColumnarOffsetType> eventOffsets = {0};
1024 unsigned entries = 0;
1025 unsigned nullEntries = 0;
1026
1027 explicit ColumnReaderVectorVectorVariantLink (const std::string& val_branchName)
1028 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
1029 {
1030 outputColumns.push_back ({.name = branchReader.columnName() + ".data"});
1031 outputColumns.push_back ({.name = branchReader.columnName() + ".offset", .isOffset = true});
1032 }
1033
1034 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
1035 {
1036 auto iter = requestedColumns.find (outputColumns.at(0).name);
1037 if (iter == requestedColumns.end())
1038 return false;
1039 outputColumns.at(0).enabled = true;
1040
1041 branchReader.connectTree(source);
1042
1043 if (iter->second.offsetName != outputColumns.at(1).name)
1044 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
1045
1046 for (const auto & keyColumn : columnData.connect (iter->second, offsetColumns, requestedColumns))
1047 {
1048 outputColumns.push_back ({.name = keyColumn, .primary = false, .enabled = true});
1049 requestedColumns.erase (keyColumn);
1050 }
1051
1052 requestedColumns.erase (iter);
1053
1054 iter = requestedColumns.find (outputColumns.at(1).name);
1055 if (iter != requestedColumns.end())
1056 {
1057 outputColumns.at(1).enabled = true;
1058 requestedColumns.erase (iter);
1059 }
1060
1061 iter = requestedColumns.find (outputColumns.at(2).name);
1062 if (iter != requestedColumns.end())
1063 {
1064 outputColumns.at(2).enabled = true;
1065 requestedColumns.erase (iter);
1066 }
1067 return true;
1068 }
1069
1070 virtual void clearColumns () override
1071 {
1072 columnData.clear();
1073 offsets.clear();
1074 offsets.push_back (0);
1075 eventOffsets.clear();
1076 eventOffsets.push_back (0);
1077 }
1078
1079 virtual void getEntry (Long64_t entry) override
1080 {
1081 benchmark.startTimer ();
1082 const auto& branchData = branchReader.getEntry (entry);
1083 benchmark.stopTimer ();
1084 benchmarkUnpack.startTimer ();
1085 columnData.checkOffsets (eventOffsets.size() - 1);
1086 for (auto& data : branchData)
1087 {
1088 for (auto& element : data)
1089 {
1090 columnData.addLink (element, eventOffsets.size()-1);
1091 }
1092 offsets.push_back (columnData.size());
1093 }
1094 eventOffsets.push_back (offsets.size());
1095 benchmarkUnpack.stopTimer ();
1096 }
1097
1098 virtual void setData (ColumnVectorData& colData) override
1099 {
1100 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
1101 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
1102 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
1103 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
1104 for (std::size_t i = 2; i < outputColumns.size(); ++ i)
1105 {
1106 if (outputColumns.at(i).columnIndex != ColumnVectorHeader::nullIndex)
1107 colData.setColumn (outputColumns.at(i).columnIndex, columnData.keysColumn(i-2).size(), columnData.keysColumn(i-2).data());
1108 }
1109 }
1110
1111 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
1112 {
1113 BranchPerfData result;
1114 result.name = branchReader.columnName();
1115 result.timeRead = benchmark.getEntryTime(emptyTime);
1116 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
1117 benchmark.setSilence();
1118 benchmarkUnpack.setSilence();
1119 result.entrySize = branchReader.entrySize();
1120 result.uncompressedSize = branchReader.uncompressedSize();
1121 result.numBaskets = branchReader.numBaskets();
1122 result.entries = entries;
1123 result.nullEntries = nullEntries;
1124 return result;
1125 }
1126
1127 virtual void collectColumnData () override
1128 {
1129 entries += columnData.size();
1130 for (const auto& index : columnData)
1131 {
1133 nullEntries += 1;
1134 }
1135 }
1136 };
1137
1138 template <template <typename> class Reader>
1140 {
1141 Reader<std::vector<std::string>> branchReader;
1142 std::vector<ColumnarOffsetType> offsets = {0};
1143 std::vector<char> columnData;
1144 std::vector<std::size_t> columnHashData;
1147
1148 ColumnReaderMetNames (const std::string& val_branchName)
1149 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+"(unpack)"), benchmark (branchReader.columnName())
1150 {
1151 outputColumns.push_back ({.name = branchReader.columnName() + ".data"});
1152 outputColumns.push_back ({.name = branchReader.columnName() + ".offset", .isOffset = true});
1153 outputColumns.push_back ({.name = branchReader.columnName() + "Hash"});
1154 }
1155
1156 virtual bool connect(Backend source, std::unordered_map<std::string, const std::vector<ColumnarOffsetType>*>& /*offsetColumns*/, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
1157 {
1158 auto iter = requestedColumns.find (outputColumns.at(0).name);
1159 if (iter == requestedColumns.end())
1160 return false;
1161 outputColumns.at(0).enabled = true;
1162
1163 branchReader.connectTree(source);
1164
1165 if (iter->second.offsetName != outputColumns.at(1).name)
1166 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
1167
1168 requestedColumns.erase (iter);
1169
1170 iter = requestedColumns.find (outputColumns.at(1).name);
1171 if (iter == requestedColumns.end())
1172 {
1173 return true;
1174 }
1175 outputColumns.at(1).enabled = true;
1176 requestedColumns.erase (iter);
1177
1178 iter = requestedColumns.find (outputColumns.at(2).name);
1179 if (iter != requestedColumns.end())
1180 {
1181 outputColumns.at(2).enabled = true;
1182 requestedColumns.erase (iter);
1183 }
1184 return true;
1185 }
1186
1187 virtual void clearColumns () override
1188 {
1189 columnData.clear();
1190 offsets.clear();
1191 offsets.push_back (0);
1192 columnHashData.clear();
1193 }
1194
1195 virtual void getEntry (Long64_t entry) override
1196 {
1197 benchmark.startTimer ();
1198 const auto& branchData = branchReader.getEntry (entry);
1199 benchmark.stopTimer ();
1200 benchmarkUnpack.startTimer ();
1201 for (auto& data : branchData)
1202 {
1203 columnData.insert (columnData.end(), data.begin(), data.end());
1204 offsets.push_back (columnData.size());
1205 columnHashData.push_back (std::hash<std::string> () (data));
1206 }
1207 benchmarkUnpack.stopTimer ();
1208 }
1209
1210 virtual void setData (ColumnVectorData& colData) override
1211 {
1212 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
1213 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
1214 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
1215 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
1216 if (outputColumns.at(2).columnIndex != ColumnVectorHeader::nullIndex)
1217 colData.setColumn (outputColumns.at(2).columnIndex, columnHashData.size(), columnHashData.data());
1218 }
1219
1220 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
1221 {
1222 BranchPerfData result;
1223 result.name = branchReader.columnName();
1224 result.timeRead = benchmark.getEntryTime(emptyTime);
1225 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
1226 benchmark.setSilence();
1227 benchmarkUnpack.setSilence();
1228 result.entrySize = branchReader.entrySize();
1229 result.uncompressedSize = branchReader.uncompressedSize();
1230 result.numBaskets = branchReader.numBaskets();
1231 return result;
1232 }
1233
1234 virtual void collectColumnData () override
1235 {}
1236 };
1237
1238 template <template <typename> class Reader>
1240 {
1241 Reader<xAOD::CaloClusterContainer> branchReader;
1242 std::vector<ColumnarOffsetType> offsets = {0};
1243 std::vector<std::uint32_t> columnData;
1246 unsigned entries = 0;
1247
1248 ColumnReaderSamplingPattern (const std::string& val_branchName)
1249 : branchReader (val_branchName), benchmarkUnpack (branchReader.columnName()+".samplingPattern(fallback)(unpack)"), benchmark (branchReader.columnName() + ".samplingPattern(fallback)")
1250 {
1251 outputColumns.push_back ({.name = branchReader.columnName() + ".samplingPattern"});
1252 outputColumns.push_back ({.name = branchReader.columnName(), .isOffset = true, .primary = false});
1253 }
1254
1255 virtual bool connect(Backend source, std::unordered_map<std::string,const std::vector<ColumnarOffsetType>*>& /*offsetColumns*/, std::unordered_map<std::string, ColumnInfo>& requestedColumns) override
1256 {
1257 auto iter = requestedColumns.find (outputColumns.at(0).name);
1258 if (iter == requestedColumns.end())
1259 return false;
1260 outputColumns.at(0).enabled = true;
1261
1262 branchReader.connectTree(source);
1263 if (iter->second.offsetName != outputColumns.at(1).name)
1264 throw std::runtime_error ("offset name mismatch: " + iter->second.offsetName + " != " + outputColumns.at(1).name);
1265
1266 requestedColumns.erase (iter);
1267
1268 iter = requestedColumns.find (outputColumns.at(1).name);
1269 if (iter == requestedColumns.end())
1270 {
1271 return true;
1272 }
1273 outputColumns.at(1).enabled = true;
1274 requestedColumns.erase (iter);
1275 return true;
1276 }
1277
1278 virtual void clearColumns () override
1279 {
1280 columnData.clear();
1281 offsets.clear();
1282 offsets.push_back (0);
1283 }
1284
1285 virtual void getEntry (Long64_t entry) override
1286 {
1287 benchmark.startTimer ();
1288 const auto& branchData = branchReader.getEntry (entry);
1289 benchmark.stopTimer ();
1290 benchmarkUnpack.startTimer ();
1291 for (auto data : branchData)
1292 {
1293 columnData.push_back (data->samplingPattern());
1294 }
1295 offsets.push_back (columnData.size());
1296 benchmarkUnpack.stopTimer ();
1297 }
1298
1299 virtual void setData (ColumnVectorData& colData) override
1300 {
1301 if (outputColumns.at(0).columnIndex != ColumnVectorHeader::nullIndex)
1302 colData.setColumn (outputColumns.at(0).columnIndex, columnData.size(), columnData.data());
1303 if (outputColumns.at(1).columnIndex != ColumnVectorHeader::nullIndex)
1304 colData.setColumn (outputColumns.at(1).columnIndex, offsets.size(), offsets.data());
1305 }
1306
1307 [[nodiscard]] virtual BranchPerfData getPerfData (float emptyTime) override
1308 {
1309 BranchPerfData result;
1310 result.name = branchReader.columnName() + "(fallback)";
1311 result.timeRead = benchmark.getEntryTime(emptyTime);
1312 result.timeUnpack = benchmarkUnpack.getEntryTime(emptyTime);
1313 benchmark.setSilence();
1314 benchmarkUnpack.setSilence();
1315 result.entrySize = branchReader.entrySize();
1316 result.uncompressedSize = branchReader.uncompressedSize();
1317 result.numBaskets = branchReader.numBaskets();
1318 result.entries = entries;
1319 return result;
1320 }
1321
1322 virtual void collectColumnData () override
1323 {
1324 entries += columnData.size();
1325 }
1326 };
1327 }
1328}
1329
1330#endif // COLUMNAR_TEST_FIXTURES_COLUMN_READER_BRANCH_H
bool isDefault() const
Test to see if this link is in the default state.
a class that holds the columnar data for a single call
void setColumn(std::size_t columnIndex, std::size_t size, CT *dataPtr)
set the data for the given column
static constexpr std::size_t nullIndex
the index used for an invalid index (always has to be 0)
this is a simple benchmarking helper class wrapping timers from std::chrono
Definition Benchmark.h:51
std::vector< OutputColumnInfo > outputColumns
std::vector< SG::sgkey_t > m_targetKeys
std::vector< typename CM::LinkIndexType > m_columnData
const CM::LinkIndexType * data() const noexcept
std::vector< std::string > m_targetNames
void addLink(const ElementLink< T > &element, unsigned eventIndex)
std::vector< const std::vector< ColumnarOffsetType > * > m_targetOffsetColumns
void addTarget(const std::string &name, const std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::uint32_t clid=0)
std::vector< std::vector< typename CM::LinkKeyType > > m_keysColumns
void addSplitLink(std::size_t linkIndex, SG::sgkey_t linkKey, unsigned eventIndex)
std::unordered_map< SG::sgkey_t, std::unordered_set< std::size_t > > m_unknownKeysAllowedTargets
const std::vector< typename CM::LinkKeyType > & keysColumn(std::size_t index) const
std::vector< std::string > connect(const ColumnInfo &columnInfo, const std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, const std::unordered_map< std::string, ColumnInfo > &requestedColumns)
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
std::variant< TTree *, RNTupleBackend * > Backend
const std::unordered_map< std::string, SG::sgkey_t > knownSgKeys
lookup table from container name to its sgkey hash
Definition KnownSgKeys.h:32
SG::sgkey_t computeSgKey(const std::string &name, std::uint32_t clid)
compute the StoreGate hashed key for a container
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
Definition index.py:1
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:36
std::string soleLinkTargetName
for simple link columns: the name of the target container
Definition ColumnInfo.h:132
std::uint32_t soleLinkTargetClid
for simple link columns: the CLID of the target container
Definition ColumnInfo.h:146
std::string name
the name of the column
Definition ColumnInfo.h:43
std::size_t LinkIndexType
the type used for columns that represent element links
static LinkIndexType mergeLinkKeyIndex(LinkIndexType key, LinkIndexType index)
merge a key and index value into a link value
the performance data for reading a single branch/column
virtual void getEntry(Long64_t entry) override
virtual void setData(ColumnVectorData &colData) override
std::vector< ColumnarOffsetType > offsets
Reader< std::vector< std::string > > branchReader
virtual BranchPerfData getPerfData(float emptyTime) override
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
ColumnReaderMetNames(const std::string &val_branchName)
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void setData(ColumnVectorData &colData) override
ColumnReaderSamplingPattern(const std::string &val_branchName)
Reader< xAOD::CaloClusterContainer > branchReader
virtual void getEntry(Long64_t entry) override
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void setData(ColumnVectorData &columnData) override
virtual void getEntry(Long64_t entry) override
virtual BranchPerfData getPerfData(float emptyTime) override
ColumnReaderScalar(const std::string &val_branchName)
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void setData(ColumnVectorData &colData) override
ColumnReaderVectorVectorVector(const std::string &val_branchName)
virtual void getEntry(Long64_t entry) override
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
Reader< std::vector< std::vector< std::vector< T > > > > branchReader
virtual BranchPerfData getPerfData(float emptyTime) override
ColumnReaderVectorVector(const std::string &val_branchName)
Reader< std::vector< std::vector< T > > > branchReader
virtual void getEntry(Long64_t entry) override
virtual BranchPerfData getPerfData(float emptyTime) override
std::vector< ColumnarOffsetType > offsets
virtual void setData(ColumnVectorData &colData) override
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void getEntry(Long64_t entry) override
ColumnReaderVector(const std::string &val_branchName)
virtual void setData(ColumnVectorData &columnData) override
virtual bool connect(Backend source, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual BranchPerfData getPerfData(float emptyTime) override
const std::vector< ColumnarOffsetType > * offsetColumn
std::vector< ColumnarOffsetType > offsets