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