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