MaCh3  2.5.0
Reference Guide
Functions
BinningHandler.cpp File Reference
#include "Samples/BinningHandler.h"
Include dependency graph for BinningHandler.cpp:

Go to the source code of this file.

Functions

auto BinRangeToBinEdges (YAML::Node const &bin_range)
 
auto BuildBinEdgesFromNode (YAML::Node const &bin_edges_node, bool &found_range_specifier)
 Builds a single dimension's bin edges from YAML::Node. More...
 
auto UniformBinEdgeConfigParser (YAML::Node const &bin_edges_node, bool &found_range_specifier)
 Parses YAML node describing multidim uniform binning. More...
 

Function Documentation

◆ BinRangeToBinEdges()

auto BinRangeToBinEdges ( YAML::Node const &  bin_range)

Definition at line 9 of file BinningHandler.cpp.

9  {
10 // ************************************************
11  bool is_lin = true;
12  YAML::Node bin_range_specifier;
13  if (bin_range["linspace"]) {
14  bin_range_specifier = bin_range["linspace"];
15  } else if (bin_range["logspace"]) {
16  is_lin = false;
17  bin_range_specifier = bin_range["logspace"];
18  } else {
19  std::stringstream ss;
20  ss << bin_range;
21  MACH3LOG_ERROR("When parsing binning, expected bin range specifier with "
22  "key linspace or logspace, but found,\n{}",
23  ss.str());
24  throw MaCh3Exception(__FILE__, __LINE__);
25  }
26 
27  auto nb = Get<int>(bin_range_specifier["nb"], __FILE__, __LINE__);
28  auto low = Get<double>(bin_range_specifier["low"], __FILE__, __LINE__);
29  auto up = Get<double>(bin_range_specifier["up"], __FILE__, __LINE__);
30 
31  std::vector<double> edges(nb + 1, low);
32  // force the last bin to be exactly as parsed to avoid numerical instabilities
33  // not quite lining back up with the end of the range, which could
34  // cause spurious errors or infinitesimally small bins for specifications
35  // like: [ { logspace: { nb: 10, 1E-1, 10}, 10, 11} ]
36  edges.back() = up;
37 
38  if (is_lin) {
39  double bw = (up - low) / nb;
40  for (int i = 0; i < (nb - 1); ++i) {
41  edges[i + 1] = edges[i] + bw;
42  }
43  } else {
44  double llow = std::log10(low);
45  double lup = std::log10(up);
46  double lbw = (lup - llow) / nb;
47  for (int i = 0; i < (nb - 1); ++i) {
48  edges[i + 1] = std::pow(10, llow + (i + 1) * lbw);
49  }
50  }
51 
52  return edges;
53 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
Custom exception class used throughout MaCh3.

◆ BuildBinEdgesFromNode()

auto BuildBinEdgesFromNode ( YAML::Node const &  bin_edges_node,
bool &  found_range_specifier 
)

Builds a single dimension's bin edges from YAML::Node.

BinEdges: [ <dim0bin0lowedge>, <dim0bin1upedge>, <dim0bin2upedge>, ... <dim0binNupedge> ] BinEdges: { linspace: { nb: 100, low: 0, up: 10} } BinEdges: { logspace: { nb: 100, low: 1E-1, up: 10} } BinEdges: [ { linspace: { nb: 100, low: 0, up: 10} }, 10, 15, { logspace: { nb: 5, low: 15, up: 100} } ]

Definition at line 63 of file BinningHandler.cpp.

64  {
65 // ************************************************
66  if (bin_edges_node.IsMap()) {
67  found_range_specifier = true;
68  return BinRangeToBinEdges(bin_edges_node);
69  }
70  std::vector<double> edges_builder;
71  if (!bin_edges_node.IsSequence()) {
72  std::stringstream ss;
73  ss << bin_edges_node;
75  "When parsing binning, expected to find a YAML map or sequence, "
76  "but found:\n{}",
77  ss.str());
78  throw MaCh3Exception(__FILE__, __LINE__);
79  }
80  for (auto const &it : bin_edges_node) {
81  if (it.IsScalar()) {
82  edges_builder.push_back(it.as<double>());
83  } else if (it.IsMap()) {
84  found_range_specifier = true;
85  auto range_edges = BinRangeToBinEdges(it);
86  std::copy(range_edges.begin(), range_edges.end(),
87  std::back_inserter(edges_builder));
88  } else {
89  std::stringstream ss;
90  ss << bin_edges_node;
92  "When parsing binning, expected elements in outer sequence to all be "
93  "either scalars or maps, but found:\n{}",
94  ss.str());
95  throw MaCh3Exception(__FILE__, __LINE__);
96  }
97  }
98 
99  // Check for duplicates or out-of-order bins
100  std::vector<double> edges;
101  for (size_t eb_it = 0; eb_it < edges_builder.size(); ++eb_it) {
102  if (edges.size()) {
103  if (edges_builder[eb_it] == edges.back()) { // remove duplicate edges
104  continue;
105  } else if (edges_builder[eb_it] < edges.back()) {
106  std::stringstream ss;
107  ss << "[ ";
108  for(auto const & e : edges_builder){
109  ss << fmt::format("{:.3g} ", e);
110  }
111  ss << "]";
113  "When parsing binning, found edges that were not monotonically "
114  "increasing, problem bin at index: {}:\n{}",
115  eb_it, ss.str());
116  throw MaCh3Exception(__FILE__, __LINE__);
117  }
118  }
119  edges.push_back(edges_builder[eb_it]);
120  }
121 
122  return edges;
123 }
auto BinRangeToBinEdges(YAML::Node const &bin_range)

◆ UniformBinEdgeConfigParser()

auto UniformBinEdgeConfigParser ( YAML::Node const &  bin_edges_node,
bool &  found_range_specifier 
)

Parses YAML node describing multidim uniform binning.

dimensional list implicit for 1D binnings

BinEdges: [<dim0bin0lowedge>, <dim0bin1upedge>, <dim0bin2upedge>, ... <dim0binNupedge>]

BinEdges: [ [<dim0bin0lowedge>, <dim0bin1upedge>, <dim0bin2upedge>, ... <dim0binNupedge>], ... [<dimNbin0lowedge>, <dimNbin1upedge>, <dimNbin2upedge>, ... <dimNbinNupedge>] ]

bin edge list implicit for 1D range-only binnings

BinEdges: { linspace: { nb: 100, low: 0, up: 10} }

mixed syntax binnings allowed

BinEdges: [ { linspace: { nb: 100, low: 0, up: 10} }, 10, 15, { logspace: { nb: 5, low: 15, up: 100} } ] # for ND range-only binnings, lists are required to disambiguate 1D mixed specifier binnings from ND binnings BinEdges: [ [ { linspace: { nb: 100, low: 0, up: 10} } ], ... [<dimNbin0lowedge>, <dimNbin1upedge>, <dimNbin2upedge>, ... <dimNbinNupedge>] ] BinEdges: [ [ { linspace: { nb: 100, low: 0, up: 10} }, 10, 15, { logspace: { nb: 5, low: 15, up: 100} } ], ... [<dimNbin0lowedge>, <dimNbin1upedge>, <dimNbin2upedge>, ... <dimNbinNupedge>] ]

Definition at line 153 of file BinningHandler.cpp.

154  {
155 // ************************************************
156  if (bin_edges_node.IsMap()) {
157  found_range_specifier = true;
158  return std::vector<std::vector<double>>{
159  BinRangeToBinEdges(bin_edges_node),
160  };
161  } else if (bin_edges_node.IsSequence()) {
162  if (!bin_edges_node.size()) {
163  std::stringstream ss;
164  ss << bin_edges_node;
165  MACH3LOG_ERROR("When parsing binning, found an empty sequence:\n{}",
166  ss.str());
167  throw MaCh3Exception(__FILE__, __LINE__);
168  }
169  auto const &first_el = bin_edges_node[0];
170  if (first_el.IsScalar() || first_el.IsMap()) { // 1D binning
171  return std::vector<std::vector<double>>{
172  BuildBinEdgesFromNode(bin_edges_node, found_range_specifier),
173  };
174  }
175  // ND binning
176  std::vector<std::vector<double>> dims;
177  for (auto const &dim_node : bin_edges_node) {
178  dims.push_back(BuildBinEdgesFromNode(dim_node, found_range_specifier));
179  }
180  return dims;
181  } else {
182  std::stringstream ss;
183  ss << bin_edges_node;
185  "When parsing binning, expected to find a YAML map or sequence, "
186  "but found:\n{}",
187  ss.str());
188  throw MaCh3Exception(__FILE__, __LINE__);
189  }
190 }
auto BuildBinEdgesFromNode(YAML::Node const &bin_edges_node, bool &found_range_specifier)
Builds a single dimension's bin edges from YAML::Node.