file Utils/yaml_options.hpp
[No description available] More…
Namespaces
Name |
---|
Gambit TODO: see if we can use this one: |
Classes
Name | |
---|---|
class | Gambit::Options |
Detailed Description
Author:
- Christoph Weniger (c.weniger@uva.nl)
- Ben Farmer (benjamin.farmer@monash.edu.au)
- Gregory Martinez (gregory.david.martinez@gmail.com)
- Pat Scott (patscott@physics.mcgill.ca)
- Markus Prim (markus.prim@kit.edu)
- Tomas Gonzalo (tomas.gonzalo@monash.edu)
Date:
- 2013 June 2013
- 2013 Dec
- 2014 Feb
- 2014 Mar
- 2020 April
- 2020 June
Declarations for the YAML options class.
Authors (add name and date if you modify):
Source code
// GAMBIT: Global and Modular BSM Inference Tool
// *********************************************
/// \file
///
/// Declarations for the YAML options class.
///
/// *********************************************
///
/// Authors (add name and date if you modify):
///
/// \author Christoph Weniger
/// (c.weniger@uva.nl)
/// \date 2013 June 2013
///
/// \author Ben Farmer
/// (benjamin.farmer@monash.edu.au)
/// \date 2013 Dec
///
/// \author Gregory Martinez
/// (gregory.david.martinez@gmail.com)
/// \date 2014 Feb
///
/// \author Pat Scott
/// (patscott@physics.mcgill.ca)
/// \date 2014 Mar
///
/// \author Markus Prim
/// (markus.prim@kit.edu)
/// \date 2020 April
///
/// \author Tomas Gonzalo
/// (tomas.gonzalo@monash.edu)
/// \date 2020 June
///
/// *********************************************
#ifndef __yaml_options_hpp__
#define __yaml_options_hpp__
#include <vector>
#include <sstream>
#include "gambit/Utils/util_types.hpp"
#include "gambit/Utils/standalone_error_handlers.hpp"
#include "gambit/Utils/yaml_variadic_functions.hpp"
#include "gambit/Utils/yaml_node_utility.hpp"
namespace Gambit
{
/// A small wrapper object for 'options' nodes.
/// These can be extracted from the prior, observable/likelihood and rules sections of the
/// inifile, or set by hand in module standalone mode.
class Options
{
public:
/// Default constructor
Options() {}
/// Copy constructor
Options(const YAML::Node &options) : options(options) {}
/// Move constructor
Options(YAML::Node &&options) : options(std::move(options)) {}
/// Getters for key/value pairs (which is all the options node should contain)
/// @{
template <typename... args>
bool hasKey(const args&... keys) const
{
return getVariadicNode(options, keys...);
}
template<typename TYPE, typename... args>
TYPE getValue(const args&... keys) const
{
const YAML::Node node = getVariadicNode(options, keys...);
TYPE result;
if (not node)
{
std::ostringstream os;
os << "No options entry for [" << stringifyVariadic(keys...) << "]\n Node contents: " << options;
utils_error().raise(LOCAL_INFO,os.str());
result = TYPE();
}
else
{
try
{
result = NodeUtility::getNode<TYPE>(node);
}
catch(YAML::Exception& e)
{
std::string nodestr;
try
{
nodestr = node.as<std::string>();
}
catch(YAML::Exception& e)
{
nodestr = "<Couldn't even convert to string!>";
}
std::ostringstream os;
os << "Error retrieving options entry for [" << stringifyVariadic(keys...)
<< "] as type " << typeid(TYPE).name() << " (template parameter: see below). String form of node value was: "
<< nodestr << std::endl
<< "YAML message follows: " << std::endl
<< e.what();
utils_error().raise(LOCAL_INFO,os.str());
result = TYPE();
}
}
return result;
}
template<typename TYPE, typename... args>
TYPE getValueOrDef(TYPE def, const args&... keys) const
{
const YAML::Node node = getVariadicNode(options, keys...);
TYPE result;
if (not node)
{
result = def;
}
else
{
result = getValue<TYPE>(keys...);
}
return result;
}
/// @}
/// Basic setter, for adding extra options
/// @{
template<typename KEYTYPE, typename VALTYPE>
void setValue(const KEYTYPE &key, const VALTYPE &val)
{
options[key] = val;
return;
}
/// @}
/**
* @brief Get a `std::vector` of a particular type
*
* If the entry is a scalar rather than a vector, try to convert it to a size one
* `std::vector`
*/
template<typename TYPE>
std::vector<TYPE> getVector(std::string key) const
{
if (getNode(key).IsScalar())
{
return {getValue<TYPE>(key)};
}
else
{
return getValue<std::vector<TYPE>>(key);
}
}
/// Retrieve values from key-value pairs in options node.
/// Works for an arbitrary set of input keys (of any type), and returns
/// all values as strings.
template<typename... args>
const std::vector<str> getNames(const args&... keys) const
{
std::vector<str> result;
const YAML::Node node = getVariadicNode(options, keys...);
if (node.IsMap())
{
for (auto it = node.begin(), end = node.end(); it != end; ++it)
{
result.push_back( it->first.as<str>() );
}
}
return result;
}
/// Retrieve values from all key-value pairs in options node.
/// Returns all keys as strings.
const std::vector<str> getNames() const
{
std::vector<str> result;
for (auto it = options.begin(), end = options.end(); it != end; ++it)
{
result.push_back( it->first.as<str>() );
}
return result;
}
/// Recursive options retrieval
template<typename... args>
const Options getOptions(const args&... keys) const
{
const YAML::Node node = getVariadicNode(options, keys...);
if (node["options"])
{
return Options(node["options"]);
}
else
{
return Options(node);
}
}
/// Retrieve raw YAML node
template<typename... args>
YAML::Node getNode(const args&... keys) const
{
const YAML::Node node = getVariadicNode(options, keys...);
if (not node)
{
std::ostringstream os;
os << "No options entry for [" << stringifyVariadic(keys...) << "]\n Node contents: " << options;
utils_error().raise(LOCAL_INFO,os.str());
}
return node;
}
/// Get YAML node from file
template<typename... args>
YAML::Node loadFromFile(const args&... keys) const
{
const YAML::Node node = getVariadicNode(options, keys...);
if (not node)
{
std::ostringstream os;
os << "No options entry for [" << stringifyVariadic(keys...) << "]\n Node contents: " << options;
utils_error().raise(LOCAL_INFO,os.str());
}
return YAML::LoadFile(node.as<std::string>().c_str());
}
/// Return begin and end of options
YAML::const_iterator begin() const { return options.begin(); }
YAML::const_iterator end() const { return options.end(); }
/// Convert to string with some indentation
std::string toString(size_t level) const
{
std::stringstream ss;
for (YAML::const_iterator it = begin(); it != end(); it++)
{
for(size_t i=0; i<level; i++) ss << " ";
ss << it->first.as<std::string>() << " : ";
if(it->second.IsScalar())
ss << it->second << endl;
else if(it->second.IsMap())
ss << endl << Options(it->second).toString(level+1);
else if(it->second.IsSequence())
{
ss << endl;
for (unsigned int j = 0; j<it->second.size(); ++j)
{
for(size_t i=0; i<level+1; i++) ss << " ";
ss << "- " << it->second[j] << endl;
}
}
else
{
std::ostringstream os;
os << "Couldn't convert options to string. YAML type unknown. ";
utils_error().raise(LOCAL_INFO,os.str());
}
}
return ss.str();
}
/// Convert the options node a map
void toMap(map_str_str& map, str header = "") const
{
str head = header;
if(not head.empty()) head += "::";
for(auto node: *this)
{
str key;
if(node.first.IsScalar())
key = node.first.as<str>();
else if(node.first.IsSequence())
{
key = "[";
for(size_t j=0; j<node.first.size()-1; ++j)
key += node.first[j].as<str>() + ",";
key += node.first[node.first.size()-1].as<str>() + "]";
}
if(node.second.IsScalar())
map[head + key] = node.second.as<str>();
else if(node.second.IsMap())
Options(node.second).toMap(map, head + key);
else if(node.second.IsSequence())
{
str val = "[";
for(size_t j=0; j<node.second.size(); ++j)
{
if(node.second[j].IsScalar() and j < node.second.size()-1)
val += node.second[j].as<str>() + ", ";
else if(node.second[j].IsSequence())
{
val += "[";
for(size_t k=0; k<node.second[j].size()-1; ++k)
{
if(node.second[j][k].IsScalar())
val += node.second[j][k].as<str>() + ",";
else
utils_error().raise(LOCAL_INFO, "Options node only allows 2D matrices");
}
val += node.second[j][node.second[j].size()-1].as<str>() + "]";
if(j < node.second.size()-1) val += ",";
}
}
if(node.second[node.second.size()-1].IsScalar())
val += node.second[node.second.size()-1].as<str>();
val += "]";
map[head + key] = val;
}
else
{
std::ostringstream os;
os << "Couldn't convert options to map. YAML type unknown. ";
utils_error().raise(LOCAL_INFO,os.str());
}
}
}
private:
YAML::Node options;
};
}
#endif //#ifndef __yaml_options_hpp__
Updated on 2024-07-18 at 13:53:32 +0000