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  init();
176  }
177 
179  if (!m_formula_str.empty())
180 #ifndef STANDALONE
181  m_formula = std::make_shared<reco::FormulaEvaluator>(m_formula_str);
182 #else
183  m_formula = std::make_shared<TFormula>("jet_resolution_formula", m_formula_str.c_str());
184 #endif
185  for (const auto& bin: m_bins_name) {
186  const auto& b = JetParameters::binning_to_string.right.find(bin);
187  if (b == JetParameters::binning_to_string.right.cend()) {
188  throwException(edm::errors::UnimplementedFeature, "Bin name not supported: '" + bin + "'");
189  }
190  m_bins.push_back(b->second);
191  }
192 
193  for (const auto& v: m_variables_name) {
194  const auto& var = JetParameters::binning_to_string.right.find(v);
195  if (var == JetParameters::binning_to_string.right.cend()) {
196  throwException(edm::errors::UnimplementedFeature, "Variable name not supported: '" + v + "'");
197  }
198  m_variables.push_back(var->second);
199  }
200  }
201 
202  JetResolutionObject::Record::Record(const std::string& line, const Definition& def) {
203 
204  std::vector<std::string> tokens = getTokens(line);
205 
206  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1)) {
207  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
208  }
209 
210  size_t pos = 0;
211 
212  for (size_t i = 0; i < def.nBins(); i++) {
213  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
214  pos += 2;
215  m_bins_range.push_back(r);
216  }
217 
218  size_t n_parameters = std::stoul(tokens[pos++]);
219 
220  if (tokens.size() < (def.nBins() * 2 + def.nVariables() * 2 + 1 + (n_parameters - def.nVariables() * 2))) {
221  throwException(edm::errors::ConfigFileReadError, "Invalid record. Please check file format. Record: " + line);
222  }
223 
224  for (size_t i = 0; i < def.nVariables(); i++) {
225  Range r(std::stof(tokens[pos]), std::stof(tokens[pos + 1]));
226  pos += 2;
227  m_variables_range.push_back(r);
228  n_parameters -= 2;
229  }
230 
231  for (size_t i = 0; i < n_parameters; i++) {
232  m_parameters_values.push_back(std::stof(tokens[pos++]));
233  }
234  }
235 
236  JetResolutionObject::JetResolutionObject(const std::string& filename) {
237 
238  // Parse file
239  std::ifstream f(filename);
240 
241  if (! f.good()) {
242  throwException(edm::errors::FileReadError, "Can't read input file '" + filename + "'");
243  }
244 
245  for (std::string line; std::getline(f, line); ) {
246  if ((line.empty()) || (line[0] == '#'))
247  continue;
248 
249  std::string definition = getDefinitionLine(line);
250 
251  if (!definition.empty()) {
252  m_definition = Definition(definition);
253  } else {
254  m_records.push_back(Record(line, m_definition));
255  }
256  }
257 
258  m_valid = true;
259  }
260 
261  JetResolutionObject::JetResolutionObject(const JetResolutionObject& object) {
262  m_definition = object.m_definition;
263  m_records = object.m_records;
264  m_valid = object.m_valid;
265 
266  m_definition.init();
267  }
268 
269  JetResolutionObject::JetResolutionObject() {
270  // Empty
271  }
272 
273 
275  std::cout << "Definition: " << std::endl;
276  std::cout << " Number of binning variables: " << m_definition.nBins() << std::endl;
277  std::cout << " ";
278  for (const auto& bin: m_definition.getBinsName()) {
279  std::cout << bin << ", ";
280  }
281  std::cout << std::endl;
282  std::cout << " Number of variables: " << m_definition.nVariables() << std::endl;
283  std::cout << " ";
284  for (const auto& bin: m_definition.getVariablesName()) {
285  std::cout << bin << ", ";
286  }
287  std::cout << std::endl;
288  std::cout << " Formula: " << m_definition.getFormulaString() << std::endl;
289 
290  std::cout << std::endl << "Bin contents" << std::endl;
291 
292  for (const auto& record: m_records) {
293  std::cout << " Bins" << std::endl;
294  size_t index = 0;
295  for (const auto& bin: record.getBinsRange()) {
296  std::cout << " " << m_definition.getBinName(index) << " [" << bin.min << " - " << bin.max << "]" << std::endl;
297  index++;
298  }
299 
300  std::cout << " Variables" << std::endl;
301  index = 0;
302  for (const auto& r: record.getVariablesRange()) {
303  std::cout << " " << m_definition.getVariableName(index) << " [" << r.min << " - " << r.max << "] " << std::endl;
304  index++;
305  }
306 
307  std::cout << " Parameters" << std::endl;
308  index = 0;
309  for (const auto& par: record.getParametersValues()) {
310  std::cout << " Parameter #" << index << " = " << par << std::endl;
311  index++;
312  }
313  }
314  }
315 
316  void JetResolutionObject::saveToFile(const std::string& file) const {
317 
318  std::ofstream fout(file);
319  fout.setf(std::ios::right);
320 
321  // Definition
322  fout << "{" << m_definition.nBins();
323 
324  for (auto& bin: m_definition.getBinsName())
325  fout << " " << bin;
326 
327  fout << " " << m_definition.nVariables();
328 
329  for (auto& var: m_definition.getVariablesName())
330  fout << " " << var;
331 
332  fout << " " << (m_definition.getFormulaString().empty() ? "None" : m_definition.getFormulaString()) << " Resolution}" << std::endl;
333 
334  // Records
335  for (auto& record: m_records) {
336  for (auto& r: record.getBinsRange()) {
337  fout << std::left << std::setw(15) << r.min << std::setw(15) << r.max << std::setw(15);
338  }
339  fout << (record.nVariables() * 2 + record.nParameters()) << std::setw(15);
340 
341  for (auto& r: record.getVariablesRange()) {
342  fout << r.min << std::setw(15) << r.max << std::setw(15);
343  }
344 
345  for (auto& p: record.getParametersValues()) {
346  fout << p << std::setw(15);
347  }
348 
349  fout << std::endl << std::setw(0);
350  }
351 
352  }
353 
354  const JetResolutionObject::Record* JetResolutionObject::getRecord(const JetParameters& bins_parameters) const {
355  // Find record for bins
356  if (! m_valid)
357  return nullptr;
358 
359  // Create vector of bins value. Throw if some values are missing
360  std::vector<float> bins = bins_parameters.createVector(m_definition.getBins());
361 
362  // Iterate over all records, and find the one for which all bins are valid
363  const Record* good_record = nullptr;
364  for (const auto& record: m_records) {
365 
366  // Iterate over bins
367  size_t valid_bins = 0;
368  size_t current_bin = 0;
369  for (const auto& bin: record.getBinsRange()) {
370  if (bin.is_inside(bins[current_bin]))
371  valid_bins++;
372 
373  current_bin++;
374  }
375 
376  if (valid_bins == m_definition.nBins()) {
377  good_record = &record;
378  break;
379  }
380  }
381 
382  return good_record;
383  }
384 
385  float JetResolutionObject::evaluateFormula(const JetResolutionObject::Record& record, const JetParameters& variables_parameters) const {
386 
387  if (! m_valid)
388  return 1;
389 
390 #ifndef STANDALONE
391  const auto* formula = m_definition.getFormula();
392 #else
393  // Set parameters
394  auto const* pFormula = m_definition.getFormula();
395  if (! pFormula)
396  return 1;
397  auto formula = *pFormula;
398 #endif
399  // Create vector of variables value. Throw if some values are missing
400  std::vector<float> variables = variables_parameters.createVector(m_definition.getVariables());
401 
402  double variables_[4] = {0};
403  for (size_t index = 0; index < m_definition.nVariables(); index++) {
404  variables_[index] = clip(variables[index], record.getVariablesRange()[index].min, record.getVariablesRange()[index].max);
405  }
406  const std::vector<float>& parameters = record.getParametersValues();
407 
408 #ifndef STANDALONE
409  //ArrayAdaptor only takes doubles
410  std::vector<double> parametersD(parameters.begin(),parameters.end());
411  return formula->evaluate(
412  reco::formula::ArrayAdaptor(variables_,m_definition.nVariables()),
413  reco::formula::ArrayAdaptor(parametersD.data(),parametersD.size())
414  );
415 #else
416  for (size_t index = 0; index < parameters.size(); index++) {
417  formula.SetParameter(index, parameters[index]);
418  }
419 
420  return formula.EvalPar(variables_);
421 #endif
422  }
423 }
424 
425 #ifndef STANDALONE
428 #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)