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