14 #include <boost/algorithm/string.hpp>
16 #include "yaml-cpp/yaml.h"
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();
44 Log& SettingsHandler::getLog()
const {
45 return Log::getLog(
"Hammer.SettingsHandler");
48 Setting* SettingsHandler::cloneSetting(
const string& path,
const string& name,
const Setting& value,
WTerm group) {
49 return &(_settings[group][path][name] = value);
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);
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);
73 Setting* SettingsHandler::resetSetting(
const string& path,
const string& name,
WTerm group) {
74 auto candidate = getEntry(path, name, group);
75 if(candidate !=
nullptr) {
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);
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);
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);
108 set<string> SettingsHandler::getSettings(
const string& path,
WTerm group)
const {
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);
122 void SettingsHandler::parseSettings(
const string& data) {
123 YAML::Node config = YAML::Load(data);
124 processSettings(config);
127 void SettingsHandler::readSettings(
const string& name) {
128 YAML::Node config = YAML::LoadFile(name);
129 processSettings(config);
132 bool SettingsHandler::isMassWidth(
const string& name)
const {
133 return (name ==
"Masses") || (name ==
"Widths") || boost::starts_with(name,
"Masses:") || boost::starts_with(name,
"Widths:");
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);
140 else if(boost::starts_with(path,
"Widths")) {
141 PID::instance().setWidth(name, value);
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) {
148 double tmp = setting.as<
double>();
149 processMassWidth(path, name, tmp);
150 }
catch (YAML::Exception&) {
151 MSG_ERROR(
"Problem parsing mass settings input");
155 auto candidate = getEntry(path, name, group);
156 if (candidate ==
nullptr) {
157 candidate = addSetting(path, name, boost::blank{}, group);
160 candidate->update(setting.as<
Setting>());
162 catch(YAML::Exception&) {
163 MSG_ERROR(
"Problem parsing settings input");
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);
176 else if(base ==
"Denominator" && group != WTerm::NUMERATOR) {
177 processSettings(subgroup, WTerm::DENOMINATOR);
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);
187 MSG_ERROR(
"Problem parsing settings input");
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;
199 for(
auto& elem2: elem.second) {
200 (resp.first->second)[elem2.first] = &(elem2.second);
207 void SettingsHandler::saveSettings(
const string& name,
bool useDefault)
const {
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;
221 emitter << YAML::EndMap;
223 auto denominatorEntries = getEntriesByGroup(WTerm::DENOMINATOR);
224 if (denominatorEntries.size() > 0) {
225 emitter << YAML::Key <<
"Denominator";
226 emitter << YAML::Value << YAML::BeginMap;
228 emitter << YAML::EndMap;
230 emitter << YAML::EndMap;
231 emitter << YAML::Newline;
236 string SettingsHandler::buildName(
const string& path,
const string& name,
WTerm group)
const {
237 return groupToPrefix(group) + path +
":" + name;
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);
251 return tuple<string, string, WTerm>{path, name, group};
254 void SettingsHandler::write(flatbuffers::FlatBufferBuilder* msgwriter,
256 size_t numEntries = 0;
257 for (
auto& elemGroup : _settings) {
258 for(
auto& elemPath: elemGroup.second) {
259 size_t tmp = elemPath.second.size();
262 settings->reserve(numEntries);
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);
281 auto settings = msgreader->settings();
284 WTerm group = WTerm::COMMON;
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.");
297 _settings[group][path][name] = setVal;
303 string SettingsHandler::groupToPrefix(
WTerm option)
const {
307 case WTerm::NUMERATOR:
309 case WTerm::DENOMINATOR:
310 return "Denominator:";
315 WTerm SettingsHandler::prefixToGroup(
const string& option)
const {
316 if(option.size() <= 1) {
317 return WTerm::COMMON;
319 else if(option.find(
"Numerator") == 0ul) {
320 return WTerm::NUMERATOR;
323 return WTerm::DENOMINATOR;
328 void SettingsHandler::saveReferences(
const string& filename)
const {
330 reffile.open(filename.c_str());
331 for (
auto elem: _references) {
332 reffile << elem.second;
338 bool SettingsHandler::checkReference(
const string& bibkey) {
339 return _references.find(bibkey) != _references.end();
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});
350 void SettingsHandler::clearReferences() {
TensorData read(const Serial::FBTensor *msgreader)
Hammer settings manager class.
Hammer exception definitions.
container for an Hammer run option
std::map< std::string, T > NamedDict
Hammer particle data class.
Hammer YaML utility functions.
Various operations on Setting class.
void writeDict2(YAML::Emitter &emitter, std::map< std::string, std::map< std::string, const T * >> dict2)
Serialization related typedefs and includes.