Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
Modules | Namespaces | Functions
DataIO

Writing data, reading configuration files, and reporting data to the Python frontend. More...

Collaboration diagram for DataIO:

Modules

 DataManager
 High-level interface for data writing.
 
 Graph Utilities
 Provides functions which wrap common tasks for writing out data from graphs.
 
 Chunking Utilities
 Provides algorithms for automatically optimize the chunksize in which data is written to the hard disk when writing compressed or extendable hdf5 files.
 
 HDF5
 Low-level interface for using HDF5 with modern C++ and STL.
 
 Monitor
 Interface for monitoring custom quantities for a simulation via standard out.
 
 Config Utilities
 Allows reading configuration entries from YAML files.
 
 Filesystem
 

Namespaces

namespace  Utopia::DataIO::GraphLoad
 
namespace  Utopia::DataIO::GraphUtilsHelper
 

Functions

template<class Exc >
YAML::Exception Utopia::DataIO::improve_yaml_exception (const Exc &e, const Config &node, std::string prefix={})
 Improves yaml-cpp exceptions occurring for a given node.
 
std::string Utopia::DataIO::to_string (const Config &node)
 Given a config node, returns a string representation of it.
 
template<typename CVecT , DimType dim = 0>
CVecT Utopia::DataIO::get_as_arma_vec (const std::string &key, const DataIO::Config &node)
 Retrieve a config entry as Armadillo column vector using get_.
 
template<class T , class Keys = std::list<std::string>>
Config Utopia::_internal::__recursive_setitem (Config d, Keys &&key_sequence, const T &val)
 Helper function for recursive_setitem.
 
Config Utopia::_internal::recursive_getitem (const Config &d, const std::vector< std::string > &key_sequence)
 Recursively retrieve an element from the configuration tree.
 
Config Utopia::_internal::recursive_getitem (const Config &d, const std::string &key_sequence, const std::string &delims=".")
 Overload for recursive_getitem, accepting a string-like key sequence.
 
template<class T >
void Utopia::_internal::recursive_setitem (Config &d, std::list< std::string > key_sequence, const T val)
 Recursively sets an element in a configuration tree.
 
template<class T >
void Utopia::_internal::recursive_setitem (Config &d, const std::string &key_sequence, const T val, const std::string &delims=".")
 Overload for recursive_setitem that splits a string into a key sequence.
 

Detailed Description

Writing data, reading configuration files, and reporting data to the Python frontend.

Function Documentation

◆ __recursive_setitem()

template<class T , class Keys = std::list<std::string>>
Config Utopia::_internal::__recursive_setitem ( Config  d,
Keys &&  key_sequence,
const T &  val 
)

Helper function for recursive_setitem.

Expects an (already deep-copied) node that is then recursively iterated through along the key sequence. For the last key in the sequence, the value is being set. Empty path segments in the key sequence are skipped.

Exceptions
std::invalid_argumentupon trailing empty path segments in the key sequence.
305{
306 // Get the next key
307 std::string key;
308 while (key.empty() and not key_sequence.empty()) {
309 key = key_sequence.front();
310 key_sequence.pop_front();
311 }
312 if (key.empty()) {
313 throw std::invalid_argument(
314 "During recursive_setitem, failed to retrieve a valid key for "
315 "continuing recursion. Make sure the given key sequence ("
316 + join(key_sequence, " -> ") + ") contains no empty elements!"
317 );
318 }
319
320 // Check for end of recursion
321 if (key_sequence.empty()) {
322 if (d.IsScalar()) {
323 // Discard the scalar and replace it with an empty mapping
324 d = Config{};
325 }
326 d[key] = val;
327 return d;
328 }
329
330 // Continue recursion, creating the intermediate node if it does not exist
331 if (not d[key]) {
332 d[key] = Config{};
333 }
334 d[key] = __recursive_setitem(d[key], std::forward<Keys>(key_sequence),
335 val);
336 return d;
337}
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition types.hh:71
Config __recursive_setitem(Config d, Keys &&key_sequence, const T &val)
Helper function for recursive_setitem.
Definition cfg_utils.hh:302
std::string join(const Cont &cont, const std::string &delim=", ")
Joins together the strings in a container.
Definition string.hh:18

◆ get_as_arma_vec()

template<typename CVecT , DimType dim = 0>
CVecT Utopia::DataIO::get_as_arma_vec ( const std::string &  key,
const DataIO::Config node 
)

Retrieve a config entry as Armadillo column vector using get_.

Note
This method is necessary because arma::Col::fixed cannot be constructed from std::vector. In such cases, the target vector is constructed element-wise.
Template Parameters
CVecTThe Armadillo vector type to return
dimThe dimensionality of the vector (only needed for)
229{
230 // Extract the field vector element type; assuming Armadillo interface
231 using element_t = typename CVecT::elem_type;
232
233 // Check if it can be constructed from a vector
234 if constexpr (std::is_constructible< CVecT, std::vector< element_t > >())
235 {
236 return get_as< std::vector< element_t > >(key, node);
237 }
238 else
239 {
240 static_assert(dim > 0,
241 "Need template argument dim given if target type is not "
242 "constructible from std::vector.");
243
244 // Needs to be constructed element-wise
245 CVecT cvec;
246 const auto vec = get_as< std::array< element_t, dim > >(key, node);
247
248 for (DimType i = 0; i < dim; i++)
249 {
250 cvec[i] = vec[i];
251 }
252
253 return cvec;
254 }
255}

◆ improve_yaml_exception()

template<class Exc >
YAML::Exception Utopia::DataIO::improve_yaml_exception ( const Exc e,
const Config node,
std::string  prefix = {} 
)

Improves yaml-cpp exceptions occurring for a given node.

75 {})
76{
77 // The string stream for the new, improved error message
78 std::stringstream e_msg;
79 e_msg << prefix << " ";
80 e_msg << "Got " << boost::core::demangle(typeid(e).name()) << ". ";
81
82 // Create a custom error message depending on whether the node is a
83 // zombie or a mark is available
84 if (not node)
85 {
86 // Was a zombie
87 e_msg << "The given node was a Zombie! Check that the key you are "
88 "trying to read from actually exists. ";
89 }
90 else if (not node.Mark().is_null())
91 {
92 // A mark is available to use as a hint
93 // NOTE Mark() provides the line and column in the config file, if
94 // available, i.e.: if not a zombie node
95 e_msg << "Check that the corresponding line of the config file "
96 "matches the desired read operation or type conversion. ";
97 }
98
99 // Give some information on the node's content:
100 e_msg << "The content of the node is:" << std::endl << YAML::Dump(node);
101
102 // Return the custom exception object; can be thrown on other side
103 return YAML::Exception(node.Mark(), e_msg.str());
104}

◆ recursive_getitem() [1/2]

Config Utopia::_internal::recursive_getitem ( const Config d,
const std::string &  key_sequence,
const std::string &  delims = "." 
)

Overload for recursive_getitem, accepting a string-like key sequence.

Returns the configuration node at the path specified by the key sequence.

Parameters
dThe configuration tree to retrieve the element from
key_sequenceA string denoting the path within the tree to get the item from. The path is split into segments using Utopia::split
delimsDelimiters (plural!) that split the string into a key sequence.
Returns
Config The configuration tree element at the given path.
Warning
Any character in the delims sequence acts as separator. See Utopia::split for more information on behaviour of the delims argument.
401{
402 return recursive_getitem(d, split(key_sequence, delims));
403}
Config recursive_getitem(const Config &d, const std::vector< std::string > &key_sequence)
Recursively retrieve an element from the configuration tree.
Definition cfg_utils.hh:360
SeqCont split(const std::string &s, const std::string &delims=" ")
Splits a string and returns a container of string segments.
Definition string.hh:45

◆ recursive_getitem() [2/2]

Config Utopia::_internal::recursive_getitem ( const Config d,
const std::vector< std::string > &  key_sequence 
)

Recursively retrieve an element from the configuration tree.

Actually uses a loop internally to avoid recursion... ¯_(ツ)_/¯

Note
Only works with string-like keys, i.e. can't access sequences.
Warning
Due to yaml-cpp quirks, creates a deep copy of the given config to keep clear of any mutability side effects. Subsequently, this function should not be used in performance-critical code. Furthermore, to set an element in the configuration tree, the recursive_setitem functionality should be used – assigning a value to the returned Config object will not lead to a change in the tree provided via the d argument.
Parameters
dThe configuration tree to retrieve the element from
key_sequenceA key sequence denoting the path within the tree to get the item from.
Returns
Config The configuration tree element at the given path.
362{
363 using Utopia::KeyError;
364 using Utopia::join;
365
366 Config rv = YAML::Clone(d);
367 for (const auto& key : key_sequence ) {
368 try {
369 rv = get_as<Config>(key, rv);
370 }
371 catch (KeyError& err) {
372 throw KeyError(
373 key, rv,
374 "recursive_getitem failed for key or key sequence '"
375 + join(key_sequence, " -> ") + "'!"
376 );
377 }
378 }
379 return rv;
380}
For access to a dict-like structure with a bad key.
Definition exceptions.hh:67

◆ recursive_setitem() [1/2]

template<class T >
void Utopia::_internal::recursive_setitem ( Config d,
const std::string &  key_sequence,
const val,
const std::string &  delims = "." 
)

Overload for recursive_setitem that splits a string into a key sequence.

Parameters
dThe configuration tree to set the entry in.
key_sequenceA string to split into a sequence of keys to walk along inside the tree.
valThe value to assign to the element of the tree specified by the key sequence.
delimsDelimiters to generate a key sequence from the given string key_sequence.
Warning
Any character in the delims sequence acts as separator. See Utopia::split for more information on behaviour of the delims argument.
453{
455 d, split<std::list<std::string>>(key_sequence, delims), val
456 );
457}
void recursive_setitem(Config &d, std::list< std::string > key_sequence, const T val)
Recursively sets an element in a configuration tree.
Definition cfg_utils.hh:422

◆ recursive_setitem() [2/2]

template<class T >
void Utopia::_internal::recursive_setitem ( Config d,
std::list< std::string >  key_sequence,
const val 
)

Recursively sets an element in a configuration tree.

This also creates all intermediate segments that may be missing.

As the YAML::Node::operator[] does not return references, this internally has to create a (deep) copy of the given node d. After recursing through it and setting the value, it will finally assign to the d reference.

Note
Only works with string-like keys, i.e. can't access sequences.
Parameters
dThe configuration tree to set the entry in.
key_sequenceA container with a sequence of keys to walk along inside the tree.
valThe value to assign to the element of the tree specified by the key sequence.
425{
426 if (key_sequence.empty()) {
427 throw std::invalid_argument(
428 "Key sequence for recursive_setitem may not be empty!"
429 );
430 }
431 d = __recursive_setitem(YAML::Clone(d), std::move(key_sequence), val);
432}

◆ to_string()

std::string Utopia::DataIO::to_string ( const Config node)

Given a config node, returns a string representation of it.

This is done by dumping the config node into an std::stringstream.

111{
112 std::stringstream s;
113 s << YAML::Dump(node);
114 return s.str();
115}