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