CP3-llbb Framework
BinnedValues.h
1 #pragma once
2 
3 #include <cp3_llbb/Framework/interface/Histogram.h>
4 
5 #include <memory>
6 #include <unordered_map>
7 #include <sstream>
8 
9 #include <TFormula.h>
10 
11 enum Variation {
12  Nominal = 0,
13  Down = 1,
14  Up = 2
15 };
16 
17 template <typename T, typename U>
18 struct bimap {
19  typedef std::unordered_map<T, U> left_type;
20  typedef std::unordered_map<U, T> right_type;
21 
22  left_type left;
23  right_type right;
24 
25  bimap(std::initializer_list<typename left_type::value_type> l) {
26  for (auto& v: l) {
27  left.insert(v);
28  right.insert(typename right_type::value_type(v.second, v.first));
29  }
30  }
31 
32  bimap() {
33  // Empty
34  }
35 
36  bimap(bimap&& rhs) {
37  left = std::move(rhs.left);
38  right = std::move(rhs.right);
39  }
40 };
41 
45 enum class BinningVariable {
46  Pt,
47  Eta,
48  AbsEta,
49  BTagDiscri
50 };
51 
52 // Hash function for BinningVariable enum class
53 namespace std {
54  template<>
55  struct hash<BinningVariable> {
56  typedef BinningVariable argument_type;
57  typedef std::size_t result_type;
58 
59  hash<uint8_t> int_hash;
60 
61  result_type operator()(argument_type const& s) const {
62  return int_hash(static_cast<uint8_t>(s));
63  }
64  };
65 };
66 
67 class Parameters {
68  public:
69  typedef std::unordered_map<BinningVariable, float> value_type;
70 
71  Parameters() = default;
72  Parameters(Parameters&& rhs);
73  Parameters(std::initializer_list<typename value_type::value_type> init);
74 
75 
76  Parameters& setPt(float pt);
77  Parameters& setEta(float eta);
78  Parameters& setBTagDiscri(float d);
79  Parameters& set(const BinningVariable& bin, float value);
80  Parameters& set(const typename value_type::value_type& value);
81 
82  std::vector<float> toArray(const std::vector<BinningVariable>&) const;
83 
84  private:
85  value_type m_values;
86 };
87 
88 class BinnedValues {
89 
90  public:
92  static const mapping_bimap variable_to_string_mapping;
93 
100  enum class ErrorType {
101  ABSOLUTE,
102  RELATIVE,
103  VARIATED
104  };
105 
106  friend class BinnedValuesJSONParser;
107 
108  BinnedValues(BinnedValues&& rhs) = default;
109 
110  BinnedValues() = default;
111 
112  private:
113  template <typename _Value>
114  std::vector<_Value> get(Histogram<_Value, float>& h, const std::vector<float>& bins, bool& outOfRange) const {
115  std::size_t bin = h.findClosestBin(bins, &outOfRange);
116  if (bin == 0) {
117  std::stringstream msg;
118  msg << "Failed to found the right bin for a scale-factor. This should not happend. Bins: [";
119  for (float b: bins) {
120  msg << b << ", ";
121  }
122 
123  msg.seekp(msg.tellp() - 2l);
124  msg << "]";
125 
126  throw std::runtime_error(msg.str());
127  }
128 
129  return {h.getBinContent(bin), h.getBinErrorLow(bin), h.getBinErrorHigh(bin)};
130  }
131 
132  void setVariables(const std::vector<std::string>&);
133 
134  // List of variables used in the binning. First entry is the X variable, second one Y, etc.
135  std::vector<BinningVariable> binning_variables;
136 
137  bool use_formula = false;
138 
139  // Binned data
140  std::shared_ptr<Histogram<float>> binned;
141 
142  // Formula data
143  std::shared_ptr<Histogram<std::shared_ptr<TFormula>, float>> formula;
144 
145  ErrorType error_type;
146  size_t formula_variable_index = -1; // Only used in formula mode
147 
148  float maximum;
149  float minimum;
150 
154  std::vector<float> relative_errors_to_absolute(const std::vector<float>& array) const {
155  std::vector<float> result(3);
156  result[Nominal] = array[Nominal];
157  result[Up] = array[Nominal] * array[Up];
158  result[Down] = array[Nominal] * array[Down];
159 
160  return result;
161  };
162 
166  std::vector<float> variated_errors_to_absolute(const std::vector<float>& array) const {
167  std::vector<float> result(3);
168  result[Nominal] = array[Nominal];
169  result[Up] = std::abs(array[Up] - array[Nominal]);
170  result[Down] = std::abs(array[Nominal] - array[Down]);
171 
172  return result;
173  };
174 
175  std::vector<float> convert_errors(const std::vector<float>& array) const {
176  switch (error_type) {
177  case ErrorType::ABSOLUTE:
178  return array;
179 
180  case ErrorType::RELATIVE:
181  return relative_errors_to_absolute(array);
182 
183  case ErrorType::VARIATED:
184  return variated_errors_to_absolute(array);
185  }
186 
187  throw std::runtime_error("Invalid error type");
188  }
189 
194  void clamp(std::vector<float>& array) const {
195  if ((array[Nominal] + array[Up]) > maximum) {
196  array[Up] = maximum - array[Nominal];
197  }
198 
199  if ((array[Nominal] - array[Down]) < minimum) {
200  array[Down] = -(minimum - array[Nominal]);
201  }
202  }
203 
204  public:
205  virtual std::vector<float> get(const Parameters& parameters) const {
206  static auto double_errors = [](std::vector<float>& values) {
207  values[Up] *= 2;
208  values[Down] *= 2;
209  };
210 
211  std::vector<float> variables = parameters.toArray(binning_variables);
212 
213  bool outOfRange = false;
214 
215  if (!use_formula) {
216  if (! binned.get())
217  return {0., 0., 0.};
218 
219  std::vector<float> values = convert_errors(get<float>(*binned.get(), variables, outOfRange));
220 
221  if (outOfRange)
222  double_errors(values);
223 
224  clamp(values);
225 
226  return values;
227  } else {
228  if (! formula.get())
229  return {0., 0., 0.};
230 
231  std::vector<std::shared_ptr<TFormula>> formulas = get<std::shared_ptr<TFormula>>(*formula.get(), variables, outOfRange);
232  std::vector<float> values;
233 
234  // Ensure variables are not outside the validity range
235  variables = formula->clamp(variables);
236 
237  for (auto& formula: formulas) {
238  values.push_back(formula->Eval(variables[formula_variable_index]));
239  }
240 
241  values = convert_errors(values);
242 
243  if (outOfRange)
244  double_errors(values);
245 
246  clamp(values);
247 
248  return values;
249  }
250  }
251 
252 };
Definition: BinnedValuesJSONParser.h:12
Definition: BinnedValues.h:88
ErrorType
Definition: BinnedValues.h:100
Definition: Histogram.h:7
Definition: BinnedValues.h:67
Definition: BinnedValues.h:18