CMS 3D CMS Logo

JetResolutionObject.cc
Go to the documentation of this file.
1 #ifndef STANDALONE
5 
6 #else
7 #include "JetResolutionObject.h"
8 #include "Utilities.h"
9 #include <exception>
10 
11 namespace edm {
12  namespace errors {
13  enum ErrorCode { NotFound = 8026, ConfigFileReadError = 7002, UnimplementedFeature = 8011, FileReadError = 8021 };
14  };
15 }; // namespace edm
16 #endif
17 
18 #include <cmath>
19 #include <iostream>
20 #include <fstream>
21 #include <iomanip>
22 #include <algorithm>
23 
24 namespace JME {
25 
27  size_t first = line.find('{');
28  size_t last = line.find('}');
29 
30  if (first != std::string::npos && last != std::string::npos && first < last)
31  return std::string(line, first + 1, last - first - 1);
32 
33  return "";
34  }
35 
36  void throwException(uint32_t code, const std::string& message) {
37 #ifndef STANDALONE
38  throw edm::Exception(static_cast<edm::errors::ErrorCodes>(code), message);
39 #else
40  std::stringstream error;
41  error << message << " Error code: " << code;
42  throw std::runtime_error(error.str());
43 
44 #endif
45  }
46 
47  const bimap<Binning, std::string> JetParameters::binning_to_string = {{Binning::JetPt, "JetPt"},
48  {Binning::JetEta, "JetEta"},
49  {Binning::JetAbsEta, "JetAbsEta"},
50  {Binning::JetE, "JetE"},
51  {Binning::JetArea, "JetArea"},
52  {Binning::Mu, "Mu"},
53  {Binning::Rho, "Rho"},
54  {Binning::NPV, "NPV"}};
55 
56  JetParameters::JetParameters(JetParameters&& rhs) { m_values = std::move(rhs.m_values); }
57 
58  JetParameters::JetParameters(std::initializer_list<typename value_type::value_type> init) {
59  for (auto& i : init) {
60  set(i.first, i.second);
61  }
62  }
63 
64  JetParameters& JetParameters::setJetPt(float pt) {
65  m_values[Binning::JetPt] = pt;
66  return *this;
67  }
68 
69  JetParameters& JetParameters::setJetEta(float eta) {
70  m_values[Binning::JetEta] = eta;
71  m_values[Binning::JetAbsEta] = fabs(eta);
72  return *this;
73  }
74 
75  JetParameters& JetParameters::setJetE(float e) {
76  m_values[Binning::JetE] = e;
77  return *this;
78  }
79 
80  JetParameters& JetParameters::setJetArea(float area) {
81  m_values[Binning::JetArea] = area;
82  return *this;
83  }
84 
85  JetParameters& JetParameters::setMu(float mu) {
86  m_values[Binning::Mu] = mu;
87  return *this;
88  }
89 
90  JetParameters& JetParameters::setNPV(float npv) {
91  m_values[Binning::NPV] = npv;
92  return *this;
93  }
94 
95  JetParameters& JetParameters::setRho(float rho) {
96  m_values[Binning::Rho] = rho;
97  return *this;
98  }
99 
100  JetParameters& JetParameters::set(const Binning& bin, float value) {
101  m_values.emplace(bin, value);
102 
103  // Special case for eta
104  if (bin == Binning::JetEta) {
105  m_values.emplace(Binning::JetAbsEta, fabs(value));
106  }
107 
108  return *this;
109  }
110 
111  JetParameters& JetParameters::set(const typename value_type::value_type& value) {
112  set(value.first, value.second);
113  return *this;
114  }
115 
116  std::vector<float> JetParameters::createVector(const std::vector<Binning>& binning) const {
117  std::vector<float> values;
118  for (const auto& bin : binning) {
119  const auto& it = m_values.find(bin);
120  if (it == m_values.cend()) {
122  "JER parametrisation depends on '" + JetParameters::binning_to_string.left.at(bin) +
123  "' but no value for this parameter has been specified. Please call the appropriate 'set' "
124  "function of the JME::JetParameters object");
125  }
126 
127  values.push_back(it->second);
128  }
129 
130  return values;
131  }
132 
133  JetResolutionObject::Definition::Definition(const std::string& definition) {
134  std::vector<std::string> tokens = getTokens(definition);
135 
136  // We need at least 3 tokens
137  if (tokens.size() < 3) {
139  "Definition line needs at least three tokens. Please check file format.");
140  }
141 
142  size_t n_bins = std::stoul(tokens[0]);
143 
144  if (tokens.size() < (n_bins + 2)) {
145  throwException(edm::errors::ConfigFileReadError, "Invalid file format. Please check.");
146  }
147 
148  for (size_t i = 0; i < n_bins; i++) {
149  m_bins_name.push_back(tokens[i + 1]);
150  }
151 
152  size_t n_variables = std::stoul(tokens[n_bins + 1]);
153 
154  if (tokens.size() < (1 + n_bins + 1 + n_variables + 1)) {
155  throwException(edm::errors::ConfigFileReadError, "Invalid file format. Please check.");
156  }
157 
158  for (size_t i = 0; i < n_variables; i++) {
159  m_variables_name.push_back(tokens[n_bins + 2 + i]);
160  }
161 
162  m_formula_str = tokens[n_bins + n_variables + 2];
163 
164  std::string formula_str_lower = m_formula_str;
165  std::transform(formula_str_lower.begin(), formula_str_lower.end(), formula_str_lower.begin(), ::tolower);
166 
167  if (formula_str_lower == "none")
168  m_formula_str = "";
169 
170  init();
171  }
172 
174  if (!m_formula_str.empty())
175 #ifndef STANDALONE
176  m_formula = std::make_shared<reco::FormulaEvaluator>(m_formula_str);
177 #else
178  m_formula = std::make_shared<TFormula>("jet_resolution_formula", m_formula_str.c_str());
179 #endif
180  for (const auto& bin : m_bins_name) {
181  const auto& b = JetParameters::binning_to_string.right.find(bin);
182  if (b == JetParameters::binning_to_string.right.cend()) {
183  throwException(edm::errors::UnimplementedFeature, "Bin name not supported: '" + bin + "'");
184  }
185  m_bins.push_back(b->second);
186  }
187 
188  for (const auto& v : m_variables_name) {
189  const auto& var = JetParameters::binning_to_string.right.find(v);
190  if (var == JetParameters::binning_to_string.right.cend()) {
191  throwException(edm::errors::UnimplementedFeature, "Variable name not supported: '" + v + "'");
192  }
193  m_variables.push_back(var->second);
194  }
195  }
196 
197  JetResolutionObject::Record::Record(const std::string& line, const Definition& def) {
198  std::vector<std::string> tokens = getTokens(line);
199 
200  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1)) {
201  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
202  }
203 
204  size_t pos = 0;
205 
206  for (size_t i = 0; i < def.nBins(); i++) {
207  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
208  pos += 2;
209  m_bins_range.push_back(r);
210  }
211 
212  size_t n_parameters = std::stoul(tokens[pos++]);
213 
214  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1 + (n_parameters - def.nVariables() * 2))) {
215  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
216  }
217 
218  for (size_t i = 0; i < def.nVariables(); i++) {
219  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
220  pos += 2;
221  m_variables_range.push_back(r);
222  n_parameters -= 2;
223  }
224 
225  for (size_t i = 0; i < n_parameters; i++) {
226  m_parameters_values.push_back(std::stof(tokens[pos++]));
227  }
228  }
229 
230  JetResolutionObject::JetResolutionObject(const std::string& filename) {
231  // Parse file
232  std::ifstream f(filename);
233 
234  if (!f.good()) {
235  throwException(edm::errors::FileReadError, "Can't read input file '" + filename + "'");
236  }
237 
238  for (std::string line; std::getline(f, line);) {
239  if ((line.empty()) || (line[0] == '#'))
240  continue;
241 
242  std::string definition = getDefinitionLine(line);
243 
244  if (!definition.empty()) {
245  m_definition = Definition(definition);
246  } else {
247  m_records.push_back(Record(line, m_definition));
248  }
249  }
250 
251  m_valid = true;
252  }
253 
254  JetResolutionObject::JetResolutionObject(const JetResolutionObject& object) {
255  m_definition = object.m_definition;
256  m_records = object.m_records;
257  m_valid = object.m_valid;
258 
259  m_definition.init();
260  }
261 
262  JetResolutionObject::JetResolutionObject() {
263  // Empty
264  }
265 
267  std::cout << "Definition: " << std::endl;
268  std::cout << " Number of binning variables: " << m_definition.nBins() << std::endl;
269  std::cout << " ";
270  for (const auto& bin : m_definition.getBinsName()) {
271  std::cout << bin << ", ";
272  }
273  std::cout << std::endl;
274  std::cout << " Number of variables: " << m_definition.nVariables() << std::endl;
275  std::cout << " ";
276  for (const auto& bin : m_definition.getVariablesName()) {
277  std::cout << bin << ", ";
278  }
279  std::cout << std::endl;
280  std::cout << " Formula: " << m_definition.getFormulaString() << std::endl;
281 
282  std::cout << std::endl << "Bin contents" << std::endl;
283 
284  for (const auto& record : m_records) {
285  std::cout << " Bins" << std::endl;
286  size_t index = 0;
287  for (const auto& bin : record.getBinsRange()) {
288  std::cout << " " << m_definition.getBinName(index) << " [" << bin.min << " - " << bin.max << "]"
289  << std::endl;
290  index++;
291  }
292 
293  std::cout << " Variables" << std::endl;
294  index = 0;
295  for (const auto& r : record.getVariablesRange()) {
296  std::cout << " " << m_definition.getVariableName(index) << " [" << r.min << " - " << r.max << "] "
297  << std::endl;
298  index++;
299  }
300 
301  std::cout << " Parameters" << std::endl;
302  index = 0;
303  for (const auto& par : record.getParametersValues()) {
304  std::cout << " Parameter #" << index << " = " << par << std::endl;
305  index++;
306  }
307  }
308  }
309 
311  std::ofstream fout(file);
312  fout.setf(std::ios::right);
313 
314  // Definition
315  fout << "{" << m_definition.nBins();
316 
317  for (auto& bin : m_definition.getBinsName())
318  fout << " " << bin;
319 
320  fout << " " << m_definition.nVariables();
321 
322  for (auto& var : m_definition.getVariablesName())
323  fout << " " << var;
324 
325  fout << " " << (m_definition.getFormulaString().empty() ? "None" : m_definition.getFormulaString())
326  << " Resolution}" << std::endl;
327 
328  // Records
329  for (auto& record : m_records) {
330  for (auto& r : record.getBinsRange()) {
331  fout << std::left << std::setw(15) << r.min << std::setw(15) << r.max << std::setw(15);
332  }
333  fout << (record.nVariables() * 2 + record.nParameters()) << std::setw(15);
334 
335  for (auto& r : record.getVariablesRange()) {
336  fout << r.min << std::setw(15) << r.max << std::setw(15);
337  }
338 
339  for (auto& p : record.getParametersValues()) {
340  fout << p << std::setw(15);
341  }
342 
343  fout << std::endl << std::setw(0);
344  }
345  }
346 
347  const JetResolutionObject::Record* JetResolutionObject::getRecord(const JetParameters& bins_parameters) const {
348  // Find record for bins
349  if (!m_valid)
350  return nullptr;
351 
352  // Create vector of bins value. Throw if some values are missing
353  std::vector<float> bins = bins_parameters.createVector(m_definition.getBins());
354 
355  // Iterate over all records, and find the one for which all bins are valid
356  const Record* good_record = nullptr;
357  for (const auto& record : m_records) {
358  // Iterate over bins
359  size_t valid_bins = 0;
360  size_t current_bin = 0;
361  for (const auto& bin : record.getBinsRange()) {
362  if (bin.is_inside(bins[current_bin]))
363  valid_bins++;
364 
365  current_bin++;
366  }
367 
368  if (valid_bins == m_definition.nBins()) {
369  good_record = &record;
370  break;
371  }
372  }
373 
374  return good_record;
375  }
376 
377  float JetResolutionObject::evaluateFormula(const JetResolutionObject::Record& record,
378  const JetParameters& variables_parameters) const {
379  if (!m_valid)
380  return 1;
381 
382 #ifndef STANDALONE
383  const auto* formula = m_definition.getFormula();
384 #else
385  // Set parameters
386  auto const* pFormula = m_definition.getFormula();
387  if (!pFormula)
388  return 1;
389  auto formula = *pFormula;
390 #endif
391  // Create vector of variables value. Throw if some values are missing
392  std::vector<float> variables = variables_parameters.createVector(m_definition.getVariables());
393 
394  double variables_[4] = {0};
395  for (size_t index = 0; index < m_definition.nVariables(); index++) {
396  variables_[index] =
397  clip(variables[index], record.getVariablesRange()[index].min, record.getVariablesRange()[index].max);
398  }
399  const std::vector<float>& parameters = record.getParametersValues();
400 
401 #ifndef STANDALONE
402  //ArrayAdaptor only takes doubles
403  std::vector<double> parametersD(parameters.begin(), parameters.end());
404  return formula->evaluate(reco::formula::ArrayAdaptor(variables_, m_definition.nVariables()),
405  reco::formula::ArrayAdaptor(parametersD.data(), parametersD.size()));
406 #else
407  for (size_t index = 0; index < parameters.size(); index++) {
408  formula.SetParameter(index, parameters[index]);
409  }
410 
411  return formula.EvalPar(variables_);
412 #endif
413  }
414 } // namespace JME
415 
416 #ifndef STANDALONE
419 #endif
ErrorCode
Error code: whether the classification was successful or failed.
T clip(const T &n, const T &lower, const T &upper)
JetCorrectorParameters::Record record
Definition: classes.h:7
int init
Definition: HydjetWrapper.h:64
const std::vector< Range > & getVariablesRange() const
double f[11][100]
Definition: value.py:1
std::vector< float > createVector(const std::vector< Binning > &binning) const
std::string getDefinitionLine(const std::string &line)
#define TYPELOOKUP_DATA_REG(_dataclass_)
Definition: typelookup.h:102
Definition: init.py:1
const std::vector< float > & getParametersValues() const
Definition: L1GtObject.h:29
double b
Definition: hdecay.h:118
HLT enums.
Definition: errors.py:1
T first(std::pair< T, U > const &p)
JetCorrectorParameters::Definitions def
Definition: classes.h:6
def move(src, dest)
Definition: eostools.py:511
void throwException(uint32_t code, const std::string &message)
unsigned transform(const HcalDetId &id, unsigned transformCode)