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 
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 
66  return *this;
67  }
68 
72  return *this;
73  }
74 
77  return *this;
78  }
79 
82  return *this;
83  }
84 
87  return *this;
88  }
89 
91  m_values[Binning::NPV] = npv;
92  return *this;
93  }
94 
96  m_values[Binning::Rho] = rho;
97  return *this;
98  }
99 
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 
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 
119  for (const auto& bin : binning) {
120  const auto& it = m_values.find(bin);
121  if (it == m_values.cend()) {
123  "JER parametrisation depends on '" + JetParameters::binning_to_string.left.at(bin) +
124  "' but no value for this parameter has been specified. Please call the appropriate 'set' "
125  "function of the JME::JetParameters object");
126  }
127 
128  values.push_back(it->second);
129  }
130 
131  return values;
132  }
133 
134  std::vector<float> JetParameters::createVector(const std::vector<std::string>& binname) const {
135  std::vector<float> values;
136 
137  for (const auto& name : binname) {
138  Binning bi = binning_to_string.right.find(name)->second;
139 
140  const auto& it = m_values.find(bi);
141  if (it == m_values.cend()) {
142  edm::LogPrint("JPM") << "Bin name " << name << " not found!";
144  "JER parametrisation depends on '" + JetParameters::binning_to_string.left.at(bi) +
145  "' but no value for this parameter has been specified. Please call the appropriate 'set' "
146  "function of the JME::JetParameters object");
147  }
148 
149  values.push_back(it->second);
150  }
151 
152  return values;
153  }
154 
156  std::vector<std::string> tokens = getTokens(definition);
157 
158  // We need at least 3 tokens
159  if (tokens.size() < 3) {
161  "Definition line needs at least three tokens. Please check file format.");
162  }
163 
164  size_t n_bins = std::stoul(tokens[0]);
165 
166  if (tokens.size() < (n_bins + 2)) {
167  throwException(edm::errors::ConfigFileReadError, "Invalid file format. Please check.");
168  }
169 
170  for (size_t i = 0; i < n_bins; i++) {
171  m_bins_name.push_back(tokens[i + 1]);
172  }
173 
174  size_t n_variables = std::stoul(tokens[n_bins + 1]);
175 
176  if (tokens.size() < (1 + n_bins + 1 + n_variables + 1)) {
177  throwException(edm::errors::ConfigFileReadError, "Invalid file format. Please check.");
178  }
179 
180  for (size_t i = 0; i < n_variables; i++) {
181  m_variables_name.push_back(tokens[n_bins + 2 + i]);
182  }
183 
184  m_formula_str = tokens[n_bins + n_variables + 2];
185 
186  std::string formula_str_lower = m_formula_str;
187  std::transform(formula_str_lower.begin(), formula_str_lower.end(), formula_str_lower.begin(), ::tolower);
188 
189  if (formula_str_lower == "none") {
190  m_formula_str = "";
191 
192  if ((tokens.size() > n_bins + n_variables + 3) && (std::atoi(tokens[n_bins + n_variables + 3].c_str()))) {
193  size_t n_parameters = std::stoul(tokens[n_bins + n_variables + 3]);
194 
195  if (tokens.size() < (1 + n_bins + 1 + n_variables + 1 + 1 + n_parameters)) {
196  throwException(edm::errors::ConfigFileReadError, "Invalid file format. Please check.");
197  }
198 
199  for (size_t i = 0; i < n_parameters; i++) {
200  m_formula_str += tokens[n_bins + n_variables + 4 + i] + " ";
201  }
202  }
203  }
204 
205  init();
206  }
207 
209  if (!m_formula_str.empty()) {
210  if (m_formula_str.find(' ') == std::string::npos)
211 #ifndef STANDALONE
212  m_formula = std::make_shared<reco::FormulaEvaluator>(m_formula_str);
213 #else
214  m_formula = std::make_shared<TFormula>("jet_resolution_formula", m_formula_str.c_str());
215 #endif
216  else
217  m_parameters_name = getTokens(m_formula_str);
218  }
219  for (const auto& bin : m_bins_name) {
220  const auto& b = JetParameters::binning_to_string.right.find(bin);
221  if (b == JetParameters::binning_to_string.right.cend()) {
222  throwException(edm::errors::UnimplementedFeature, "Bin name not supported: '" + bin + "'");
223  }
224  m_bins.push_back(b->second);
225  }
226 
227  for (const auto& v : m_variables_name) {
228  const auto& var = JetParameters::binning_to_string.right.find(v);
229  if (var == JetParameters::binning_to_string.right.cend()) {
230  throwException(edm::errors::UnimplementedFeature, "Variable name not supported: '" + v + "'");
231  }
232  m_variables.push_back(var->second);
233  }
234  }
235 
237  std::vector<std::string> tokens = getTokens(line);
238 
239  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1)) {
240  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
241  }
242 
243  size_t pos = 0;
244 
245  for (size_t i = 0; i < def.nBins(); i++) {
246  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
247  pos += 2;
248  m_bins_range.push_back(r);
249  }
250 
251  size_t n_parameters = std::stoul(tokens[pos++]);
252 
253  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1 + (n_parameters - def.nVariables() * 2))) {
254  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
255  }
256 
257  for (size_t i = 0; i < def.nVariables(); i++) {
258  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
259  pos += 2;
260  m_variables_range.push_back(r);
261  n_parameters -= 2;
262  }
263 
264  for (size_t i = 0; i < n_parameters; i++) {
265  m_parameters_values.push_back(std::stof(tokens[pos++]));
266  }
267  }
268 
270  // Parse file
271  std::ifstream f(filename);
272 
273  if (!f.good()) {
274  throwException(edm::errors::FileReadError, "Can't read input file '" + filename + "'");
275  }
276 
277  for (std::string line; std::getline(f, line);) {
278  if ((line.empty()) || (line[0] == '#'))
279  continue;
280 
281  std::string definition = getDefinitionLine(line);
282 
283  if (!definition.empty()) {
284  m_definition = Definition(definition);
285  } else {
286  m_records.push_back(Record(line, m_definition));
287  }
288  }
289 
290  m_valid = true;
291  }
292 
294  m_definition = object.m_definition;
295  m_records = object.m_records;
296  m_valid = object.m_valid;
297 
298  m_definition.init();
299  }
300 
302  // Empty
303  }
304 
306  std::cout << "Definition: " << std::endl;
307  std::cout << " Number of binning variables: " << m_definition.nBins() << std::endl;
308  std::cout << " ";
309  for (const auto& bin : m_definition.getBinsName()) {
310  std::cout << bin << ", ";
311  }
312  std::cout << std::endl;
313  std::cout << " Number of variables: " << m_definition.nVariables() << std::endl;
314  std::cout << " ";
315  for (const auto& bin : m_definition.getVariablesName()) {
316  std::cout << bin << ", ";
317  }
318  std::cout << std::endl;
319  std::cout << " Formula: " << m_definition.getFormulaString() << std::endl;
320 
321  std::cout << std::endl << "Bin contents" << std::endl;
322 
323  for (const auto& record : m_records) {
324  std::cout << " Bins" << std::endl;
325  size_t index = 0;
326  for (const auto& bin : record.getBinsRange()) {
327  std::cout << " " << m_definition.getBinName(index) << " [" << bin.min << " - " << bin.max << "]"
328  << std::endl;
329  index++;
330  }
331 
332  std::cout << " Variables" << std::endl;
333  index = 0;
334  for (const auto& r : record.getVariablesRange()) {
335  std::cout << " " << m_definition.getVariableName(index) << " [" << r.min << " - " << r.max << "] "
336  << std::endl;
337  index++;
338  }
339 
340  std::cout << " Parameters" << std::endl;
341  index = 0;
342  for (const auto& par : record.getParametersValues()) {
343  std::cout << " Parameter #" << index << " = " << par << std::endl;
344  index++;
345  }
346  }
347  }
348 
350  std::ofstream fout(file);
351  fout.setf(std::ios::right);
352 
353  // Definition
354  fout << "{" << m_definition.nBins();
355 
356  for (auto& bin : m_definition.getBinsName())
357  fout << " " << bin;
358 
359  fout << " " << m_definition.nVariables();
360 
361  for (auto& var : m_definition.getVariablesName())
362  fout << " " << var;
363 
364  fout << " " << (m_definition.getFormulaString().empty() ? "None" : m_definition.getFormulaString())
365  << " Resolution}" << std::endl;
366 
367  // Records
368  for (auto& record : m_records) {
369  for (auto& r : record.getBinsRange()) {
370  fout << std::left << std::setw(15) << r.min << std::setw(15) << r.max << std::setw(15);
371  }
372  fout << (record.nVariables() * 2 + record.nParameters()) << std::setw(15);
373 
374  for (auto& r : record.getVariablesRange()) {
375  fout << r.min << std::setw(15) << r.max << std::setw(15);
376  }
377 
378  for (auto& p : record.getParametersValues()) {
379  fout << p << std::setw(15);
380  }
381 
382  fout << std::endl << std::setw(0);
383  }
384  }
385 
387  // Find record for bins
388  if (!m_valid)
389  return nullptr;
390 
391  // Create vector of bins value. Throw if some values are missing
392  std::vector<float> bins = bins_parameters.createVector(m_definition.getBinsName());
393 
394  // Iterate over all records, and find the one for which all bins are valid
395  const Record* good_record = nullptr;
396  for (const auto& record : m_records) {
397  // Iterate over bins
398  size_t valid_bins = 0;
399  size_t current_bin = 0;
400  for (const auto& bin : record.getBinsRange()) {
401  if (bin.is_inside(bins[current_bin])) {
402  valid_bins++;
403  }
404 
405  current_bin++;
406  }
407 
408  if (valid_bins == m_definition.nBins()) {
409  good_record = &record;
410  break;
411  }
412  }
413 
414  return good_record;
415  }
416 
418  const JetParameters& variables_parameters) const {
419  if (!m_valid)
420  return 1;
421 
422 #ifndef STANDALONE
424 #else
425  // Set parameters
426  auto const* pFormula = m_definition.getFormula();
427  if (!pFormula)
428  return 1;
429  auto formula = *pFormula;
430 #endif
431  // Create vector of variables value. Throw if some values are missing
432  std::vector<float> variables = variables_parameters.createVector(m_definition.getVariablesName());
433 
434  double variables_[4] = {0};
435  for (size_t index = 0; index < m_definition.nVariables(); index++) {
436  variables_[index] =
437  clip(variables[index], record.getVariablesRange()[index].min, record.getVariablesRange()[index].max);
438  }
439 
440  const std::vector<float>& parameters = record.getParametersValues();
441 
442 #ifndef STANDALONE
443  //ArrayAdaptor only takes doubles
444  std::vector<double> parametersD(parameters.begin(), parameters.end());
445  return formula.evaluate(reco::formula::ArrayAdaptor(variables_, m_definition.nVariables()),
446  reco::formula::ArrayAdaptor(parametersD.data(), parametersD.size()));
447 #else
448  for (size_t index = 0; index < parameters.size(); index++) {
449  formula.SetParameter(index, parameters[index]);
450  }
451 
452  return formula.EvalPar(variables_);
453 #endif
454  }
455 } // namespace JME
456 
457 #ifndef STANDALONE
460 #endif
int def(FILE *, FILE *, int)
const reco::FormulaEvaluator * getFormula() const
ErrorCode
Error code: whether the classification was successful or failed.
JetParameters & setJetEta(float eta)
std::vector< float > createVector(const std::vector< Binning > &binning) const
std::string getVariableName(size_t variable) const
JetParameters & setRho(float rho)
T clip(const T &n, const T &lower, const T &upper)
JetParameters & set(const Binning &bin, float value)
const std::vector< std::string > & getVariablesName() const
const std::vector< std::string > & getBinsName() const
std::vector< std::string > m_variables_name
std::vector< std::string > m_bins_name
double f[11][100]
Definition: value.py:1
Log< level::Warning, true > LogPrint
std::string getDefinitionLine(const std::string &line)
right_type right
Definition: init.py:1
const Record * getRecord(const JetParameters &bins) const
JetParameters & setJetE(float e)
double b
Definition: hdecay.h:120
JetParameters & setMu(float mu)
void saveToFile(const std::string &file) const
HLT enums.
#define TYPELOOKUP_DATA_REG(_dataclass_)
Definition: typelookup.h:102
Definition: errors.py:1
JetParameters & setJetPt(float pt)
std::vector< Record > m_records
float evaluateFormula(const Record &record, const JetParameters &variables) const
def move(src, dest)
Definition: eostools.py:511
void throwException(uint32_t code, const std::string &message)
JetParameters & setNPV(float npv)
JetParameters()=default
std::string getBinName(size_t bin) const
JetParameters & setJetArea(float area)
static const bimap< Binning, std::string > binning_to_string
unsigned transform(const HcalDetId &id, unsigned transformCode)