ATLAS Offline Software
Loading...
Searching...
No Matches
TableUtils.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef TABLE_UTILS_H
5#define TABLE_UTILS_H
6
7#include <array>
8#include <string>
9#include <string_view>
10#include <cassert>
11#include <iomanip>
12#include <ostream>
13#include <stdexcept>
14#include <vector>
15#include <utility>
16#include <limits>
17
18class MsgStream;
19
20// Utility class to wrap a constant variable length array interface over static sized arrays
21// This avoid duplication of compiled code for arrays which only differ
22// by the number of elements.
23// The interface is sufficient to allow using the wrapped arrays in range based for loops,
24// and for random access.
25namespace TableUtils {
26 template <typename T>
27 struct Range {
28 const T *m_ptr = nullptr;
29 std::size_t m_size = 0u;
30 std::size_t m_offset = 1u;
31
33 const_iterator &operator++() { m_ptr += m_offset; return *this; }
34 const T &operator*() const { return *m_ptr; }
35 bool operator!=(const const_iterator &other) const { return m_ptr != other.m_ptr; }
36 const T *m_ptr;
37 std::size_t m_offset;
38 };
40 return const_iterator{ m_ptr, m_offset };
41 }
43 assert( (m_size % m_offset) == 0 );
45 }
46 const T &operator[](std::size_t index) const { assert(index<m_size && m_ptr); return m_ptr[index]; }
47
48 std::size_t size() const { return m_size; }
49
50 operator bool() const { return m_ptr != nullptr && m_size>0; }
51 template <typename T_Other>
52 bool equalSize(const T_Other &other_range) {
53 return m_size == other_range.m_size;
54 }
55 };
56
57 // Utility class to wrap a constant two dimensional variable length array interface over static sized arrays
58 // This avoid duplication of compiled code for arrays which only differ
59 // by the number of elements in the two dimensions.
60 // The interface is sufficient to allow using the wrapped arrays in range based for loops,
61 // and for random access.
62 template <typename T>
63 struct Range2D {
64 const T *m_ptr = nullptr;
65 std::size_t m_rows = 0u;
66 std::size_t m_columns = 0u;
67 std::size_t m_columnOffset = 0u;
68 std::size_t m_firstColumnIndex = 0u;
69 std::size_t m_offset = 1u;
70
74 bool operator!=(const const_iterator &other) const { return m_ptr != other.m_ptr; }
75 const T *m_ptr;
76 std::size_t m_columns;
77 std::size_t m_columnOffset;
78 std::size_t m_firstColumnIndex;
79 std::size_t m_offset;
80 };
81
88 Range<T> operator[](std::size_t index) const {
89 assert(index<m_rows && m_ptr);
91 }
92
93 std::size_t nColumns() const { return m_columns; }
94 std::size_t nRows() const { return m_rows; }
95
96 operator bool() { return m_ptr != nullptr && m_columns>0; }
97 template <typename T_Other>
98 bool equalSize(const T_Other &other_range) {
99 return m_rows == other_range.m_size;
100 }
101 };
102
103 // Helper method to print wrapped static arrays in table form to an output stream
104 // The table will be composed of one column for row labels and one column for the data
105 template <class T_Stream, typename T_Counter>
106 T_Stream &dumpTable(T_Stream &out,
107 Range<T_Counter> counter,
109 const std::string &label_prefix,
110 const std::size_t column_width,
111 const std::size_t min_label_width,
112 const bool dump_footer,
113 const bool separate_last_row,
114 const unsigned int precision) {
115 if (counter && label && counter.equalSize(label)) {
116 std::size_t max_size =min_label_width;
117 for (const std::string &name : label ) {
118 max_size = std::max(max_size, name.size());
119 }
120 const std::size_t total_size =max_size+3+2*2+column_width;
121 std::string line(total_size, '-');
122 std::array<std::size_t,3> vertical_line_pos{0u, max_size+3, line.size()-1};
123 for (std::size_t pos : vertical_line_pos) {
124 line[pos]='|';
125 }
126 out << line << std::endl;
127 std::size_t idx=0;
128 std::string empty;
129 auto default_precision = out.precision();
130 for (const T_Counter &a : counter) {
131 if (separate_last_row && idx+1 == label.size()) {
132 out << line << std::endl;
133 }
134 assert( idx < label.size());
135 out << "| " << (label_prefix.empty() ? std::left : std::right)
136 << std::setw(label_prefix.size()) << ( idx==0 ? label_prefix : empty)
137 << std::setw(max_size-label_prefix.size()) << label[idx] << std::right
138 << std::setprecision( precision != std::numeric_limits<unsigned int>::max() ? precision : default_precision)
139 << " | " << std::setw(column_width) << a << " |" << std::endl;
140 ++idx;
141 }
142 out << std::setprecision(default_precision);
143 if (dump_footer) {
144 out << line << std::endl;
145 }
146 }
147 return out;
148 }
149
150 // Helper method to print wrapped static two dimensional arrays in table form to an output stream
151 // The table will be composed of a header showing column labels, one column for row labels and
152 // then column for each data item. The array is expected in row major order.
153 template <class T_Stream, typename T_Counter>
154 T_Stream &dumpTable(T_Stream &out,
155 Range2D<T_Counter> counter,
156 const Range<std::string>& row_label,
157 const Range<std::string>& column_label,
158 std::string_view top_left_label,
159 const std::string &label_prefix,
160 const std::size_t column_width,
161 const std::size_t min_label_width,
162 const bool dump_header,
163 const bool dump_footer,
164 const bool separate_last_row,
165 const std::vector<unsigned int> &precision) {
166 if (counter && row_label && column_label
167 && counter.equalSize(row_label)
168 && counter.nColumns() == column_label.size()) {
169 std::size_t max_size =std::max(top_left_label.size(), static_cast<std::size_t>(min_label_width));
170 for (const std::string &name : row_label ) {
171 max_size = std::max(max_size, name.size() + label_prefix.size());
172 }
173 std::size_t the_width = column_width;
174 for (const std::string &name : column_label ) {
175 the_width = std::max(the_width, name.size());
176 }
177 std::size_t total_size =max_size+2*2;
178 for (std::size_t column_i=0; column_i<column_label.size(); ++column_i) {
179 total_size += the_width + 3;
180 }
181 std::string line(total_size, '-');
182 std::size_t pos=0;
183 line[pos]='|';
184 pos += max_size+3;
185 for (std::size_t column_i=0; column_i<column_label.size(); ++column_i) {
186 line[pos]='|';
187 pos += the_width + 3;
188 }
189 line[line.size()-1]='|';
190 if (dump_header) {
191 out << line << std::endl << "| " << std::setw(max_size) << top_left_label << " |" << std::left;
192 for (const std::string &header : column_label ) {
193 out << " " << std::setw(the_width) << header << " |";
194 }
195 out << std::right << std::endl;
196 }
197 out << line << std::endl;
198 std::size_t idx=0;
199 std::string empty;
200 auto default_precision = out.precision();
201 for (const Range<T_Counter> &a_row : counter) {
202 if (separate_last_row && idx+1 == row_label.size()) {
203 out << line << std::endl;
204 }
205 assert( idx < row_label.size());
206 out << "| " << (label_prefix.empty() ? std::left : std::right)
207 << std::setw(label_prefix.size()) << ( idx==0 ? label_prefix : empty)
208 << std::setw(max_size-label_prefix.size()) << row_label[idx] << std::right << " |";
209 unsigned int col_i=0;
210 for (const T_Counter &a : a_row) {
211 out << " "
212 << std::setprecision( (col_i < precision.size()
213 && precision[col_i] != std::numeric_limits<unsigned int>::max())
214 ? precision[col_i]
215 : default_precision)
216 << std::setw(the_width) << a << " |";
217 ++col_i;
218 }
219 out << std::endl;
220 ++idx;
221 }
222 out << std::setprecision(default_precision);
223 if (dump_footer) {
224 out << line;
225 }
226 }
227 return out;
228 }
229
230 // Helper struct to wrap data that should be dumped in table from to an output stream
231 template <typename T>
232 struct StatTable {
235 StatTable &columnWidth(std::size_t value) { m_columnWidth=value; return *this;}
236 StatTable &minLabelWidth(std::size_t value) { m_minLabelWidth=value; return *this;}
237 StatTable &dumpHeader(bool value=true) { m_dumpHeader=value; return *this;}
238 StatTable &dumpFooter(bool value=true) { m_dumpFooter=value; return *this;}
239 StatTable &separateLastRow(bool value=true) { m_separateLastRow=value; return *this;}
240 StatTable &labelPrefix(const std::string& value) { m_labelPrefix=value; return *this;}
241 StatTable &precision(unsigned int precision) { m_precision=precision; return *this;}
242
243 std::string m_labelPrefix {};
244 std::size_t m_columnWidth=12;
245 std::size_t m_minLabelWidth=0;
246 unsigned int m_precision = std::numeric_limits<unsigned int>::max();
247 bool m_dumpHeader=true;
248 bool m_dumpFooter=true;
250 };
251 // Helper struct to wrap two dimensional data that should be dumped in table from to an output stream
252 template <typename T>
257 std::string m_topLeftLable;
258 MultiColumnTable &columnWidth(std::size_t value) { m_columnWidth=value; return *this;}
259 MultiColumnTable &minLabelWidth(std::size_t value) { m_minLabelWidth=value; return *this;}
260 MultiColumnTable &dumpHeader(bool value=true) { m_dumpHeader=value; return *this;}
261 MultiColumnTable &dumpFooter(bool value=true) { m_dumpFooter=value; return *this;}
262 MultiColumnTable &separateLastRow(bool value=true) { m_separateLastRow=value; return *this;}
263 MultiColumnTable &labelPrefix(const std::string& value) { m_labelPrefix=value; return *this;}
264 MultiColumnTable &precision(std::vector<unsigned int> &&precision) { m_precision=std::move(precision); return *this;}
265
266 std::string m_labelPrefix {};
267 std::size_t m_columnWidth=12;
268 std::size_t m_minLabelWidth=0;
269 std::vector<unsigned int> m_precision{};
270 bool m_dumpHeader=true;
271 bool m_dumpFooter=true;
273
274 // convenience method to dump wrapped two dimensional arrays in table form to a std output stream
275 // Usage: out << makeTable( array2d, row_labels, column_labels);
276
277 friend inline std::ostream &operator<<(std::ostream &out,
278 const MultiColumnTable &stat) {
279 return dumpTable(out,
280 stat.m_counter,
281 stat.m_rowLabel,
282 stat.m_columnLabel,
283 stat.m_topLeftLable,
284 stat.m_labelPrefix,
285 stat.m_columnWidth,
286 stat.m_minLabelWidth,
287 stat.m_dumpHeader,
288 stat.m_dumpFooter,
289 stat.m_separateLastRow,
290 stat.m_precision);
291 }
292
293 };
294
295 template <typename T_index, class T_string>
296 std::vector<std::string> makeLabelVector(T_index n_entries,
297 std::initializer_list<std::pair<T_index, T_string> > a_list)
298 {
299 std::vector<std::string> labels;
300 labels.resize( n_entries );
301 if (a_list.size() != n_entries) {
302 throw std::logic_error("Expected number of entries and elements in the initializer lists do not match.");
303 }
304 for ( auto elm : a_list) {
305 labels.at(elm.first) = std::move(elm.second);
306 }
307 return labels;
308 }
309
310 template<class T_Collection>
311 std::size_t maxLabelWidth( const T_Collection &col) {
312 std::size_t max_width=0u;
313 for (const auto &elm : col ) {
314 max_width = std::max( max_width, elm.size());
315 }
316 return max_width;
317 }
318
319
320 constexpr inline std::size_t categoryStride([[maybe_unused]] const std::size_t categories,
321 [[maybe_unused]] const std::size_t sub_categories,
322 [[maybe_unused]] const std::size_t n_counter) {
323 return 1;
324 }
325 constexpr inline std::size_t subCategoryStride([[maybe_unused]] const std::size_t categories,
326 [[maybe_unused]] const std::size_t sub_categories,
327 [[maybe_unused]] const std::size_t n_counter) {
328 return (categories+1) * n_counter;
329 }
330 constexpr inline std::size_t counterStride([[maybe_unused]] const std::size_t categories,
331 [[maybe_unused]] const std::size_t sub_categories,
332 [[maybe_unused]] const std::size_t n_counter) {
333 return (categories+1);
334 }
335
336
337 // change order of input statistics counter and compute projections
338 // - order: change from array[category*category_stride+sub_category][counter]
339 // to array[sub_category*sub_category_stride+counter*counter_stride+category]
340 // - projections: sum numbers in direction of category and sub_category direction, respectively.
341 // - dimension of the resulting vector: (categories+1) * (sub_categories+1) * N
342 template< typename T_Output, typename T_Input, const std::size_t N>
343 std::vector<T_Output> createCounterArrayWithProjections( const std::size_t categories,
344 const std::size_t sub_categories,
345 const std::vector< std::array<T_Input, N> > &input_counts) {
346 if (categories*sub_categories!= input_counts.size()) {
347 std::stringstream msg;
348 msg << "Category dimensions (" << categories << " * " << sub_categories << "="
349 << (categories * sub_categories) << ") and input counter container size "
350 << input_counts.size() << " do not match.";
351 throw std::logic_error(msg.str());
352 }
353 std::vector<T_Output> output_counts;
354 output_counts.resize((categories+1) * (sub_categories+1) * N);
355 const std::size_t sub_category_stride = subCategoryStride(categories, sub_categories, N);
356 const std::size_t counter_stride = counterStride(categories, sub_categories, N);
357 const std::size_t category_stride = categoryStride(categories, sub_categories, N);
358 // project seeds
359 for (std::size_t sub_category_i=0;
360 sub_category_i < sub_categories;
361 ++sub_category_i) {
362 for (std::size_t category_i=0; category_i<categories; ++category_i) {
363 std::size_t src_idx = category_i * sub_categories + sub_category_i;
364 std::size_t dest_idx_base = sub_category_i * sub_category_stride + 0 * counter_stride;
365 std::size_t dest_idx_project_categories_base = dest_idx_base;
366 dest_idx_base += category_i * category_stride;
367 dest_idx_project_categories_base += categories * category_stride;
368
369 for (std::size_t counter_i=0; counter_i<N; ++counter_i) {
370 std::size_t dest_idx=dest_idx_base + counter_i * counter_stride;
371 assert( src_idx < input_counts.size() && counter_i < input_counts[src_idx].size());
372 assert( dest_idx < output_counts.size());
373 output_counts[dest_idx] = input_counts[src_idx][counter_i];
374 assert( dest_idx_project_categories_base + counter_i * counter_stride < output_counts.size());
375 output_counts[dest_idx_project_categories_base + counter_i * counter_stride] += output_counts[dest_idx];
376 }
377 }
378 }
379 // project eta bins
380 for (std::size_t category_i=0; category_i<=categories; ++category_i) {
381 for (std::size_t counter_i=0; counter_i<N; ++counter_i) {
382 std::size_t dest_idx_base = 0 * sub_category_stride + counter_i * counter_stride + category_i;
383 std::size_t dest_idx_project_sub_categories = sub_categories * sub_category_stride + dest_idx_base;
384 assert( dest_idx_project_sub_categories < output_counts.size() );
385 for (std::size_t sub_category_i=0;
386 sub_category_i<sub_categories;
387 ++sub_category_i) {
388 std::size_t sub_category_idx = dest_idx_base + sub_category_i * sub_category_stride;
389 assert( sub_category_idx < output_counts.size() );
390 output_counts[dest_idx_project_sub_categories] += output_counts[sub_category_idx];
391 }
392 }
393 }
394 return output_counts;
395 }
396
397 using SummandDefinition = std::pair<std::size_t, int>;
398 using RatioDefinition = std::pair< std::vector< SummandDefinition >,
399 std::vector< SummandDefinition > >;
400
401 // helper to create the sum definitions for the ratio of single counters
402 // this will lead to the computation of the simple ratio defined by counter[numerator] / counter[denominatpr]
403 template <typename T>
404 inline RatioDefinition
405 defineSimpleRatio(T numerator, T denominator) {
406 return std::make_pair( std::vector< SummandDefinition > { std::make_pair(static_cast<std::size_t>(numerator),1)},
407 std::vector< SummandDefinition > { std::make_pair(static_cast<std::size_t>(denominator),1)});
408 }
409
410 // helper to create a named ratio definition for a ratio of two single counters
411 template <typename T>
412 inline std::tuple< std::string, RatioDefinition >
413 defineSimpleRatio(std::string &&name, T numerator, T denominator) {
414 return std::make_pair( std::move(name), defineSimpleRatio(numerator, denominator) );
415 }
416
417
418 // helper to create a single summand definition to be used in a ratio definition
419 // @param counter_idx the index of a counter
420 // @param multiplier a multiplier to be applied to the value of the referenced counter e.g. +1 or -1.
421 // @return the definition of a single summand to be appended to a vector
422 template <typename T>
423 inline SummandDefinition defineSummand(T counter_idx, int multiplier) {
424 return std::make_pair(static_cast<std::size_t>(counter_idx), multiplier) ;
425 }
426
427 // compute the sum : sum_j stat[ eta_bin][stat_j][seed] * multiplier_j
428 // where the index stat_j is the first element of the pair, and the second element is multiplier_j
429 std::size_t computeSum( const std::vector< SummandDefinition > &sum_def,
430 std::size_t eta_offset,
431 std::size_t row_stride,
432 std::size_t seed_i,
433 const std::vector<std::size_t> &stat);
434
435 inline float computeRatio(std::size_t numerator, std::size_t denominator) {
436 return denominator!=0 ? static_cast<float>(numerator/static_cast<double>(denominator)) : 0.f;
437 }
438
439 // compute the ratio of two sums;
440 // @param ratio_def vectors which define summands for the numerator and denominator
441 // The first element of the pair defines the numberator, which is computed by summing the referenced
442 // counters (first element of the inner pair is the counter index) after multiplying them by the
443 // multiplier (second element of the inner pair). The second elment defines the denominator of
444 // the ratio.
445 inline float computeRatio( const RatioDefinition &ratio_def,
446 std::size_t eta_offset,
447 std::size_t row_stride,
448 std::size_t seed_i,
449 const std::vector<std::size_t> &stat) {
450 std::size_t numerator=computeSum(ratio_def.first, eta_offset, row_stride, seed_i, stat);
451 std::size_t denominator=!ratio_def.second.empty()
452 ? computeSum(ratio_def.second, eta_offset, row_stride, seed_i, stat)
453 : 1;
454 return computeRatio(numerator,denominator);
455 }
456
457
458 // helper function to define a named ratio
459 inline std::tuple< std::string, RatioDefinition> makeRatioDefinition(std::string &&name,
460 std::vector< SummandDefinition >&&numerator,
461 std::vector< SummandDefinition >&&denominator) {
462 return std::make_tuple(std::move(name),
463 std::make_pair(std::move(numerator),
464 std::move(denominator)));
465 }
466
467 // helper function to split a list of named ratio definitions into a vector of labels and ratio definitions
468 inline std::tuple<std::vector<std::string>, std::vector<RatioDefinition> >
469 splitRatioDefinitionsAndLabels(std::initializer_list<std::tuple<std::string, RatioDefinition> > a_ratio_list)
470 {
471 std::tuple< std::vector<std::string>, std::vector<RatioDefinition> > splitted;
472 std::get<0>(splitted).reserve( a_ratio_list.size() );
473 for ( auto a_ratio : a_ratio_list) {
474 std::get<0>(splitted).emplace_back( std::move(std::get<0>(a_ratio)) );
475 }
476 std::get<1>(splitted).reserve( a_ratio_list.size() );
477 for ( auto a_ratio : a_ratio_list) {
478 std::get<1>(splitted).emplace_back( std::move(std::get<1>(a_ratio)) );
479 }
480 return splitted;
481 }
482
483
484 constexpr inline std::size_t categoryStride([[maybe_unused]] const std::size_t categories,
485 [[maybe_unused]] const std::size_t sub_categories,
486 [[maybe_unused]] const std::vector<RatioDefinition> &ratio_def) {
487 return 1;
488 }
489 inline std::size_t subCategoryStride([[maybe_unused]] const std::size_t categories,
490 [[maybe_unused]] const std::size_t sub_categories,
491 [[maybe_unused]] const std::vector<RatioDefinition> &ratio_def) {
492 return (categories) * ratio_def.size();
493 }
494 constexpr inline std::size_t ratioStride([[maybe_unused]] const std::size_t categories,
495 [[maybe_unused]] const std::size_t sub_categories,
496 [[maybe_unused]] const std::vector<RatioDefinition> &ratio_def) {
497 return (categories);
498 }
499
500
501 std::vector<float> computeRatios(const std::vector<RatioDefinition> &ratio_def,
502 const std::size_t categories,
503 const std::size_t sub_categories,
504 const std::vector< std::size_t> &counter);
505
506 inline std::string makeBinLabel(const std::string &variable_name,
507 const std::vector<float> &bins,
508 std::size_t bin_i,
509 bool abs_value=false,
510 int precision=1) {
511 std::stringstream range_label;
512 range_label << std::fixed << std::setprecision(precision);
513 if (bin_i==bins.size()+1) {
514 range_label << " All " << variable_name;
515 }
516 else {
517 if (bin_i==0) {
518 std::stringstream value_str;
519 value_str << std::fixed << std::setprecision(precision) << 0.;
520 range_label << std::setw(4) << (abs_value ? value_str.str().c_str() : "-inf") << "-";
521 }
522 else {
523 range_label << std::setw(4) << bins.at(bin_i-1) <<"-";
524 }
525 if (bin_i>=bins.size()) {
526 range_label << std::setw(4) << "+inf";
527 }
528 else {
529 range_label << std::setw(4) << bins.at(bin_i);
530 }
531 }
532 return range_label.str();
533 }
534
535 inline std::string makeEtaBinLabel(const std::vector<float> &eta_bins,
536 std::size_t eta_bin_i,
537 bool abs_eta=false) {
538 return TableUtils::makeBinLabel("eta",eta_bins, eta_bin_i,abs_eta, 1);
539 }
540}
541// Helper method to wrap data that should be dumped in table form to an output stream
542// Usage: out << makeTable( array, labels);
543template <typename T, std::size_t N>
544TableUtils::StatTable<T> makeTable(const std::array<T, N> &counter,
545 const std::array<std::string, N> &label) {
547 TableUtils::Range<T> {counter.data(), counter.size()},
549 };
550}
551
552// Helper method to wrap two dimensional data that should be dumped in table form to an output stream
553template <typename T, std::size_t Nrows, std::size_t Ncolumns>
554TableUtils::MultiColumnTable<T> makeTable(const std::array<std::array<T, Ncolumns>, Nrows> &counter,
555 const std::array<std::string, Nrows> &row_label,
556 const std::array<std::string, Ncolumns> &column_label,
557 std::string_view top_left_label="") {
559 TableUtils::Range2D<T> {!counter.empty() ? counter[0].data() : nullptr,
560 counter.size(), column_label.size(),
561 !counter.empty() ? static_cast<std::size_t>(&counter[1][0] - &counter[0][0]) : 0u,
562 0u, // index of first column
563 1u}, // offset between columns
564 TableUtils::Range<std::string> {row_label.data(), row_label.size(), 1u},
565 TableUtils::Range<std::string> {column_label.data(), column_label.size(),1u},
566 std::string{top_left_label}
567 };
568}
569
570// Helper method to wrap two dimensional data that should be dumped in table form to an output stream
571template <typename T>
572TableUtils::MultiColumnTable<T> makeTable(const std::vector<T> &counter,
573 std::size_t start_idx,
574 std::size_t row_stride,
575 const std::vector<std::string> &row_label,
576 const std::vector<std::string> &column_label,
577 std::string_view top_left_label="") {
578 if (start_idx + (row_label.size()-1) * row_stride >= counter.size() || row_stride < column_label.size()) {
579 std::stringstream msg;
580 msg << "Counter dimension and label dimensions (" << row_label.size() << " * " << column_label.size()
581 << ") do not match: [" << start_idx << ", "
582 << start_idx << " + " << (row_label.size()-1) << " * " << row_stride << " = "
583 << (start_idx + (row_label.size()-1) * row_stride)
584 << " !< " << counter.size();
585 msg << " [row_labels:";
586 for (const std::string &label : row_label) {
587 msg << " " << label;
588 }
589 msg << "; column_labels:";
590 for (const std::string &label : column_label) {
591 msg << " " << label;
592 }
593 msg << "]";
594 throw std::logic_error(msg.str());
595 }
597 TableUtils::Range2D<T> {!counter.empty() ? &counter[start_idx] : nullptr,
598 row_label.size(), // n-rows
599 column_label.size(), // n-columns
600 row_stride, // offset between rows
601 0u, // first column index
602 1u}, // offset between columns
603 TableUtils::Range<std::string> {row_label.data(), row_label.size() },
604 TableUtils::Range<std::string> {column_label.data(), column_label.size()},
605 std::string{top_left_label}
606 };
607}
608
609template <typename T, std::size_t N>
610TableUtils::MultiColumnTable<T> makeTable(const std::vector<std::array<T,N> > &counter,
611 std::size_t start_row_idx,
612 std::size_t row_stride,
613 std::size_t start_column_idx,
614 std::size_t column_stride,
615 const std::vector<std::string> &row_label,
616 const std::vector<std::string> &column_label,
617 std::string_view top_left_label="") {
618 if (start_row_idx + (row_label.size()-1) * row_stride >= counter.size()*N
619 || start_column_idx + (column_label.size()-1) * column_stride >= counter.size()*N
620 || (row_stride*row_label.size()>column_stride && column_stride*column_label.size()>row_stride) ) {
621 std::stringstream msg;
622 msg << "Counter dimension and label dimensions (" << row_label.size() << " * " << column_label.size()
623 << ") do not match: [" << start_row_idx << ", "
624 << start_row_idx << " + " << (row_label.size()-1) << " * " << row_stride << " = "
625 << (start_row_idx + (row_label.size()-1) * row_stride)
626 << " or "
627 << start_column_idx << " + " << (column_label.size()-1) << " * " << column_stride << " = "
628 << (start_column_idx + (column_label.size()-1) * column_stride)
629 << " !< " << counter.size()
630 << std::endl
631 << (start_row_idx + (row_label.size()-1) * row_stride) << " >= " << (counter.size()*N)
632 << " || " << (start_column_idx + (column_label.size()-1) * column_stride) << " >= " << (counter.size()*N)
633 << " || ( " << (row_stride*row_label.size()) << " > " << column_stride << " && " << (column_stride*column_label.size()) << " > " << (row_stride)
634 << ")";
635 msg << " [row_labels:";
636 for (const std::string &label : row_label) {
637 msg << " " << label;
638 }
639 msg << "; column_labels:";
640 for (const std::string &label : column_label) {
641 msg << " " << label;
642 }
643 msg << "]";
644 throw std::logic_error(msg.str());
645 }
647 TableUtils::Range2D<T> {!counter.empty() && N>0 ? counter[start_row_idx].data() : nullptr,
648 row_label.size(), // n-rows
649 column_label.size(), // n-columns
650 row_stride, // offset between rows
651 start_column_idx, // first column index
652 column_stride}, // offset between columns
653 TableUtils::Range<std::string> {row_label.data(), row_label.size() },
654 TableUtils::Range<std::string> {column_label.data(), column_label.size()},
655 std::string{top_left_label}};
656}
657
658
659// Helper method to wrap two dimensional data that should be dumped in table form to an output stream
660template <typename T>
661TableUtils::MultiColumnTable<T> makeTable(const std::vector<T> &counter,
662 const std::vector<std::string> &row_label,
663 const std::vector<std::string> &column_label,
664 std::string_view top_left_label="") {
665 return makeTable(counter, 0u, column_label.size(), row_label, column_label, top_left_label);
666}
667
668
669// convenience method to dump wrapped arrays in table form to a MsgStream
670// Usage: msg(MSG::INFO) << makeTable( array, labels);
671// ATH_MSG_INFO( makeTable( array, labels) );
672template <typename T>
673inline MsgStream &operator<<(MsgStream &out,
674 const TableUtils::StatTable<T> &stat)
675{
676 return dumpTable(out,
677 stat.m_counter,
678 stat.m_label,
679 stat.m_labelPrefix,
680 stat.m_columnWidth,
681 stat.m_minLabelWidth,
682 stat.m_dumpFooter,
683 stat.m_separateLastRow,
684 stat.m_precision);
685}
686
687// convenience method to dump wrapped two dimensional arrays in table form to a MsgStream
688// Usage: msg(MSG::INFO) << makeTable( array2d, row_labels, column_labels);
689// ATH_MSG_INFO( makeTable( array2d, row_labels, column_labels) );
690template <typename T>
691inline MsgStream &operator<<(MsgStream &out,
693{
694 return dumpTable(out,
695 stat.m_counter,
696 stat.m_rowLabel,
697 stat.m_columnLabel,
698 stat.m_topLeftLable,
699 stat.m_labelPrefix,
700 stat.m_columnWidth,
701 stat.m_minLabelWidth,
702 stat.m_dumpHeader,
703 stat.m_dumpFooter,
704 stat.m_separateLastRow,
705 stat.m_precision);
706}
707
708
709// convenience method to dump wrapped two dimensional arrays in table form to a std output stream
710// Usage: out << makeTable( array2d, row_labels, column_labels);
711template <typename T>
712inline std::ostream &operator<<(std::ostream &out,
713 const TableUtils::StatTable<T> &stat)
714{
715 return dumpTable(out,
716 stat.m_counter,
717 stat.m_label,
718 stat.m_labelPrefix,
719 stat.m_columnWidth,
720 stat.m_minLabelWidth,
721 stat.m_dumpFooter,
722 stat.m_separateLastRow,
723 stat.m_precision);
724}
725
726
727
728#endif
static Double_t a
static const std::vector< std::string > bins
MsgStream & operator<<(MsgStream &out, const TableUtils::StatTable< T > &stat)
Definition TableUtils.h:673
TableUtils::StatTable< T > makeTable(const std::array< T, N > &counter, const std::array< std::string, N > &label)
Definition TableUtils.h:544
static const Attributes_t empty
std::string label(const std::string &format, int i)
Definition label.h:19
std::tuple< std::vector< std::string >, std::vector< RatioDefinition > > splitRatioDefinitionsAndLabels(std::initializer_list< std::tuple< std::string, RatioDefinition > > a_ratio_list)
Definition TableUtils.h:469
SummandDefinition defineSummand(T counter_idx, int multiplier)
Definition TableUtils.h:423
constexpr std::size_t categoryStride(const std::size_t categories, const std::size_t sub_categories, const std::size_t n_counter)
Definition TableUtils.h:320
float computeRatio(std::size_t numerator, std::size_t denominator)
Definition TableUtils.h:435
T_Stream & dumpTable(T_Stream &out, Range< T_Counter > counter, const Range< std::string > &label, const std::string &label_prefix, const std::size_t column_width, const std::size_t min_label_width, const bool dump_footer, const bool separate_last_row, const unsigned int precision)
Definition TableUtils.h:106
std::size_t maxLabelWidth(const T_Collection &col)
Definition TableUtils.h:311
RatioDefinition defineSimpleRatio(T numerator, T denominator)
Definition TableUtils.h:405
std::size_t computeSum(const std::vector< SummandDefinition > &sum_def, std::size_t eta_offset, std::size_t row_stride, std::size_t seed_i, const std::vector< std::size_t > &stat)
Definition TableUtils.cxx:8
std::vector< std::string > makeLabelVector(T_index n_entries, std::initializer_list< std::pair< T_index, T_string > > a_list)
Definition TableUtils.h:296
constexpr std::size_t subCategoryStride(const std::size_t categories, const std::size_t sub_categories, const std::size_t n_counter)
Definition TableUtils.h:325
constexpr std::size_t counterStride(const std::size_t categories, const std::size_t sub_categories, const std::size_t n_counter)
Definition TableUtils.h:330
std::string makeEtaBinLabel(const std::vector< float > &eta_bins, std::size_t eta_bin_i, bool abs_eta=false)
Definition TableUtils.h:535
std::tuple< std::string, RatioDefinition > makeRatioDefinition(std::string &&name, std::vector< SummandDefinition > &&numerator, std::vector< SummandDefinition > &&denominator)
Definition TableUtils.h:459
std::pair< std::vector< SummandDefinition >, std::vector< SummandDefinition > > RatioDefinition
Definition TableUtils.h:398
std::string makeBinLabel(const std::string &variable_name, const std::vector< float > &bins, std::size_t bin_i, bool abs_value=false, int precision=1)
Definition TableUtils.h:506
std::vector< float > computeRatios(const std::vector< RatioDefinition > &ratio_def, const std::size_t categories, const std::size_t sub_categories, const std::vector< std::size_t > &counter)
constexpr std::size_t ratioStride(const std::size_t categories, const std::size_t sub_categories, const std::vector< RatioDefinition > &ratio_def)
Definition TableUtils.h:494
std::vector< T_Output > createCounterArrayWithProjections(const std::size_t categories, const std::size_t sub_categories, const std::vector< std::array< T_Input, N > > &input_counts)
Definition TableUtils.h:343
std::pair< std::size_t, int > SummandDefinition
Definition TableUtils.h:397
Definition index.py:1
MultiColumnTable & dumpFooter(bool value=true)
Definition TableUtils.h:261
Range< std::string > m_columnLabel
Definition TableUtils.h:256
friend std::ostream & operator<<(std::ostream &out, const MultiColumnTable &stat)
Definition TableUtils.h:277
MultiColumnTable & separateLastRow(bool value=true)
Definition TableUtils.h:262
MultiColumnTable & columnWidth(std::size_t value)
Definition TableUtils.h:258
MultiColumnTable & minLabelWidth(std::size_t value)
Definition TableUtils.h:259
Range< std::string > m_rowLabel
Definition TableUtils.h:255
std::vector< unsigned int > m_precision
Definition TableUtils.h:269
MultiColumnTable & precision(std::vector< unsigned int > &&precision)
Definition TableUtils.h:264
MultiColumnTable & dumpHeader(bool value=true)
Definition TableUtils.h:260
MultiColumnTable & labelPrefix(const std::string &value)
Definition TableUtils.h:263
bool operator!=(const const_iterator &other) const
Definition TableUtils.h:74
std::size_t m_offset
Definition TableUtils.h:69
const_iterator begin() const
Definition TableUtils.h:82
std::size_t m_columns
Definition TableUtils.h:66
const_iterator end() const
Definition TableUtils.h:85
std::size_t m_rows
Definition TableUtils.h:65
bool equalSize(const T_Other &other_range)
Definition TableUtils.h:98
std::size_t nRows() const
Definition TableUtils.h:94
std::size_t m_columnOffset
Definition TableUtils.h:67
std::size_t nColumns() const
Definition TableUtils.h:93
std::size_t m_firstColumnIndex
Definition TableUtils.h:68
Range< T > operator[](std::size_t index) const
Definition TableUtils.h:88
const_iterator & operator++()
Definition TableUtils.h:33
bool operator!=(const const_iterator &other) const
Definition TableUtils.h:35
bool equalSize(const T_Other &other_range)
Definition TableUtils.h:52
std::size_t size() const
Definition TableUtils.h:48
const_iterator begin() const
Definition TableUtils.h:39
const T & operator[](std::size_t index) const
Definition TableUtils.h:46
const_iterator end() const
Definition TableUtils.h:42
const T * m_ptr
Definition TableUtils.h:28
std::size_t m_offset
Definition TableUtils.h:30
std::size_t m_size
Definition TableUtils.h:29
StatTable & precision(unsigned int precision)
Definition TableUtils.h:241
Range< std::string > m_label
Definition TableUtils.h:234
unsigned int m_precision
Definition TableUtils.h:246
StatTable & minLabelWidth(std::size_t value)
Definition TableUtils.h:236
StatTable & separateLastRow(bool value=true)
Definition TableUtils.h:239
StatTable & dumpFooter(bool value=true)
Definition TableUtils.h:238
StatTable & columnWidth(std::size_t value)
Definition TableUtils.h:235
StatTable & labelPrefix(const std::string &value)
Definition TableUtils.h:240
std::size_t m_columnWidth
Definition TableUtils.h:244
StatTable & dumpHeader(bool value=true)
Definition TableUtils.h:237
std::size_t m_minLabelWidth
Definition TableUtils.h:245
std::string m_labelPrefix
Definition TableUtils.h:243
MsgStream & msg
Definition testRead.cxx:32