Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SettingsHandler.cc
Go to the documentation of this file.
1 ///
2 /// @file SettingsHandler.cc
3 /// @brief Hammer settings manager class
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include <fstream>
13 
14 #include <boost/algorithm/string.hpp>
15 
16 #include "yaml-cpp/yaml.h"
17 
18 #include "Hammer/Exceptions.hh"
20 
22 #include "Hammer/Tools/Setting.hh"
23 
25 #include "Hammer/Tools/Pdg.hh"
26 #include "Hammer/Tools/Utils.hh"
28 #include "Hammer/Math/Utils.hh"
29 
30 using namespace std;
31 
32 namespace Hammer {
33 
34  void SettingsHandler::reset() {
35  for(auto& elemGroup: _settings) {
36  for(auto& elemPath: elemGroup.second) {
37  for(auto& elemName: elemPath.second) {
38  elemName.second.reset();
39  }
40  }
41  }
42  }
43 
44  Log& SettingsHandler::getLog() const {
45  return Log::getLog("Hammer.SettingsHandler");
46  }
47 
48  Setting* SettingsHandler::cloneSetting(const string& path, const string& name, const Setting& value, WTerm group) {
49  return &(_settings[group][path][name] = value);
50  }
51 
52  Setting* SettingsHandler::cloneSetting(const string& fullName, const Setting& value, WTerm group) {
53  auto pos = fullName.find(":");
54  auto path = fullName.substr(0, pos);
55  auto name = fullName.substr(pos + 1);
56  return cloneSetting(path, name, value, group);
57  }
58 
59  Setting* SettingsHandler::getEntry(const string& path, const string& name, WTerm group) {
60  auto itw = _settings.find(group);
61  if(itw != _settings.end()) {
62  auto itg = itw->second.find(path);
63  if(itg != itw->second.end()) {
64  auto itn = itg->second.find(name);
65  if(itn != itg->second.end()) {
66  return &(itn->second);
67  }
68  }
69  }
70  return nullptr;
71  }
72 
73  Setting* SettingsHandler::resetSetting(const string& path, const string& name, WTerm group) {
74  auto candidate = getEntry(path, name, group);
75  if(candidate != nullptr) {
76  candidate->reset();
77  }
78  return candidate;
79  }
80 
81  Setting* SettingsHandler::resetSetting(const string& fullName, WTerm group) {
82  auto pos = fullName.find(":");
83  auto path = fullName.substr(0, pos);
84  auto name = fullName.substr(pos + 1);
85  return resetSetting(path, name, group);
86  }
87 
88  void SettingsHandler::removeSetting(const string& path, const string& name, WTerm group) {
89  auto itw = _settings.find(group);
90  if(itw != _settings.end()) {
91  auto itg = itw->second.find(path);
92  if(itg != itw->second.end()) {
93  auto itn = itg->second.find(name);
94  if(itn != itg->second.end()) {
95  itg->second.erase(itn);
96  }
97  }
98  }
99  }
100 
101  void SettingsHandler::removeSetting(const string& fullName, WTerm group) {
102  auto pos = fullName.find(":");
103  auto path = fullName.substr(0, pos);
104  auto name = fullName.substr(pos + 1);
105  removeSetting(path, name, group);
106  }
107 
108  set<string> SettingsHandler::getSettings(const string& path, WTerm group) const {
109  set<string> tmp;
110  auto itw = _settings.find(group);
111  if(itw != _settings.end()) {
112  auto itg = itw->second.find(path);
113  if(itg != itw->second.end()) {
114  for(auto& elem: itg->second) {
115  tmp.insert(elem.first);
116  }
117  }
118  }
119  return tmp;
120  }
121 
122  void SettingsHandler::parseSettings(const string& data) {
123  YAML::Node config = YAML::Load(data);
124  processSettings(config);
125  }
126 
127  void SettingsHandler::readSettings(const string& name) {
128  YAML::Node config = YAML::LoadFile(name);
129  processSettings(config);
130  }
131 
132  bool SettingsHandler::isMassWidth(const string& name) const {
133  return (name == "Masses") || (name == "Widths") || boost::starts_with(name, "Masses:") || boost::starts_with(name, "Widths:");
134  }
135 
136  void SettingsHandler::processMassWidth(const string& path, const string& name, double value) const {
137  if(boost::starts_with(path, "Masses")) {
138  PID::instance().setMass(name, value);
139  }
140  else if(boost::starts_with(path, "Widths")) {
141  PID::instance().setWidth(name, value);
142  }
143  }
144 
145  void SettingsHandler::processSetting(const YAML::Node& setting, const string& path, const string& name, WTerm group) {
146  if (group == WTerm::COMMON && isMassWidth(path) && setting.Type() == YAML::NodeType::Scalar) {
147  try {
148  double tmp = setting.as<double>();
149  processMassWidth(path, name, tmp);
150  } catch (YAML::Exception&) {
151  MSG_ERROR("Problem parsing mass settings input");
152  }
153  return;
154  }
155  auto candidate = getEntry(path, name, group);
156  if (candidate == nullptr) {
157  candidate = addSetting(path, name, boost::blank{}, group);
158  }
159  try{
160  candidate->update(setting.as<Setting>());
161  }
162  catch(YAML::Exception&) {
163  MSG_ERROR("Problem parsing settings input");
164  return;
165  }
166  }
167 
168  void SettingsHandler::processSettings(const YAML::Node& config, WTerm group) {
169  for (YAML::const_iterator it = config.begin(); it != config.end(); ++it) {
170  string base = it->first.as<string>();
171  if (it->second.Type() == YAML::NodeType::Map) {
172  YAML::Node subgroup = it->second;
173  if(base == "Numerator" && group != WTerm::DENOMINATOR) {
174  processSettings(subgroup, WTerm::NUMERATOR);
175  }
176  else if(base == "Denominator" && group != WTerm::NUMERATOR) {
177  processSettings(subgroup, WTerm::DENOMINATOR);
178  }
179  else {
180  for (YAML::const_iterator it2 = subgroup.begin(); it2 != subgroup.end(); ++it2) {
181  string optname = it2->first.as<string>();
182  processSetting(it2->second, base, optname, group);
183  }
184  }
185  }
186  else {
187  MSG_ERROR("Problem parsing settings input");
188  }
189  }
190  }
191 
192  map<string, map<string, const Setting*>> SettingsHandler::getEntriesByGroup(WTerm group) const {
193  map<string, map<string, const Setting*>> result;
194  auto itg = _settings.find(group);
195  if(itg != _settings.end()) {
196  for(auto& elem: itg->second) {
197  if(elem.second.size() == 0) continue;
198  auto resp = result.insert({elem.first, NamedDict<const Setting*>{}});
199  for(auto& elem2: elem.second) {
200  (resp.first->second)[elem2.first] = &(elem2.second);
201  }
202  }
203  }
204  return result;
205  }
206 
207  void SettingsHandler::saveSettings(const string& name, bool useDefault) const {
208  ofstream file;
209  YAML::Emitter emitter(file);
210  file.open(name.c_str());
211  if (file.is_open()) {
212  Setting::setEncodeUseDefault(useDefault);
213  emitter << YAML::Comment(version() + string(" configuration settings")) << YAML::Newline;
214  emitter << YAML::BeginMap;
215  writeDict2(emitter, getEntriesByGroup(WTerm::COMMON));
216  auto numeratorEntries = getEntriesByGroup(WTerm::NUMERATOR);
217  if (numeratorEntries.size() > 0) {
218  emitter << YAML::Key << "Numerator";
219  emitter << YAML::Value << YAML::BeginMap;
220  writeDict2(emitter, numeratorEntries);
221  emitter << YAML::EndMap;
222  }
223  auto denominatorEntries = getEntriesByGroup(WTerm::DENOMINATOR);
224  if (denominatorEntries.size() > 0) {
225  emitter << YAML::Key << "Denominator";
226  emitter << YAML::Value << YAML::BeginMap;
227  writeDict2(emitter, denominatorEntries);
228  emitter << YAML::EndMap;
229  }
230  emitter << YAML::EndMap;
231  emitter << YAML::Newline;
232  file.close();
233  }
234  }
235 
236  string SettingsHandler::buildName(const string& path, const string& name, WTerm group) const {
237  return groupToPrefix(group) + path + ":" + name;
238  }
239 
240  tuple<string, string, WTerm> SettingsHandler::parseName(const string& fullName) const {
241  auto pos = fullName.find(":");
242  string path = fullName.substr(0, pos);
243  string name = fullName.substr(pos + 1);
244  WTerm group = WTerm::COMMON;
245  pos = name.find(":");
246  if(pos != string::npos) {
247  group = prefixToGroup(path);
248  path = name.substr(0, pos);
249  name = name.substr(pos + 1);
250  }
251  return tuple<string, string, WTerm>{path, name, group};
252  }
253 
254  void SettingsHandler::write(flatbuffers::FlatBufferBuilder* msgwriter,
255  vector<flatbuffers::Offset<Serial::FBSetting>>* settings) const {
256  size_t numEntries = 0;
257  for (auto& elemGroup : _settings) {
258  for(auto& elemPath: elemGroup.second) {
259  size_t tmp = elemPath.second.size();
260  if(tmp > 0) {
261  numEntries += tmp;
262  settings->reserve(numEntries);
263  }
264  for(auto& elemName: elemPath.second) {
265  if(elemName.second.wasChanged()) {
266  auto serialname = msgwriter->CreateString(buildName(elemPath.first, elemName.first, elemGroup.first));
267  auto serialvalue = elemName.second.write(msgwriter);
268  Serial::FBSettingBuilder serialSetting{*msgwriter};
269  serialSetting.add_name(serialname);
270  serialSetting.add_value_type(serialvalue.second);
271  serialSetting.add_value(serialvalue.first);
272  auto resS = serialSetting.Finish();
273  settings->push_back(resS);
274  }
275  }
276  }
277  }
278  }
279 
280  bool SettingsHandler::read(const Serial::FBHeader* msgreader, bool merge) {
281  auto settings = msgreader->settings();
282  string path;
283  string name;
284  WTerm group = WTerm::COMMON;
285  string fullName;
286  for(unsigned int i = 0; i < settings->size(); ++i) {
287  fullName = settings->Get(i)->name()->c_str();
288  tie(path,name,group) = parseName(settings->Get(i)->name()->c_str());
289  auto setVal = Setting{settings->Get(i)};
290  auto candidate = getEntry(path, name, group);
291  if(merge && candidate != nullptr) {
292  if (!setVal.isSame(*candidate)) {
293  MSG_WARNING("Setting '"+ fullName + "' has different values in the two runs.");
294  }
295  }
296  else {
297  _settings[group][path][name] = setVal;
298  }
299  }
300  return true;
301  }
302 
303  string SettingsHandler::groupToPrefix(WTerm option) const {
304  switch(option) {
305  case WTerm::COMMON:
306  return "";
307  case WTerm::NUMERATOR:
308  return "Numerator:";
309  case WTerm::DENOMINATOR:
310  return "Denominator:";
311  }
312  return "";
313  }
314 
315  WTerm SettingsHandler::prefixToGroup(const string& option) const {
316  if(option.size() <= 1) {
317  return WTerm::COMMON;
318  }
319  else if(option.find("Numerator") == 0ul) {
320  return WTerm::NUMERATOR;
321  }
322  else {
323  return WTerm::DENOMINATOR;
324  }
325  }
326 
327 
328  void SettingsHandler::saveReferences(const string& filename) const {
329  ofstream reffile;
330  reffile.open(filename.c_str());
331  for (auto elem: _references) {
332  reffile << elem.second;
333  reffile << endl;
334  }
335  reffile.close();
336  }
337 
338  bool SettingsHandler::checkReference(const string& bibkey) {
339  return _references.find(bibkey) != _references.end();
340  }
341 
342  void SettingsHandler::addReference(const string& bibkey, const string& bibtex) {
343  if (_references.find(bibkey) == _references.end()) {
344  string tmpval = bibtex;
345  boost::replace_all(tmpval, "\", ", "\",\n ");
346  _references.insert({bibkey, tmpval});
347  }
348  }
349 
350  void SettingsHandler::clearReferences() {
351  _references.clear();
352  }
353 
354 
355 } // namespace Hammer
#define MSG_WARNING(x)
Definition: Logging.hh:366
std::string version()
Definition: Tools/Utils.hh:34
TensorData read(const Serial::FBTensor *msgreader)
Definition: Operations.cc:76
Hammer settings manager class.
Hammer exception definitions.
Logging class.
Definition: Logging.hh:33
container for an Hammer run option
Definition: Setting.hh:39
std::map< std::string, T > NamedDict
Hammer setting class.
Hammer particle data class.
Hammer YaML utility functions.
Various operations on Setting class.
#define MSG_ERROR(x)
Definition: Logging.hh:367
void writeDict2(YAML::Emitter &emitter, std::map< std::string, std::map< std::string, const T * >> dict2)
Definition: HammerYaml.hh:23
Serialization related typedefs and includes.