MaCh3  2.2.3
Reference Guide
Macros | Functions
YamlHelper.h File Reference

Utility functions for handling YAML nodes. More...

#include <iostream>
#include <fstream>
#include <string>
#include <cxxabi.h>
#include <regex>
#include "Manager/MaCh3Exception.h"
#include "Manager/Core.h"
#include "TMacro.h"
#include "TList.h"
#include "TObjString.h"
#include "yaml-cpp/yaml.h"
Include dependency graph for YamlHelper.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define M3OpenConfig(filename)   LoadYamlConfig((filename), __FILE__, __LINE__)
 Macro to simplify calling LoadYaml with file and line info. More...
 
#define GetBounds(filename)   ParseBounds((filename), __FILE__, __LINE__)
 
#define Get2DBounds(filename)   Parse2DBounds((filename), __FILE__, __LINE__)
 

Functions

template<typename T >
bool CheckNodeExistsHelper (const T &node)
 Use this like this CheckNodeExists(config, "LikelihoodOptions", "TestStatistic"); KS: Base case for recursion. More...
 
template<typename T , typename... Args>
bool CheckNodeExistsHelper (const T &node, const std::string &key, Args... args)
 KS: Recursive function to traverse YAML nodes. More...
 
template<typename... Args>
bool CheckNodeExists (const YAML::Node &node, Args... args)
 KS: Wrapper function to call the recursive helper. More...
 
template<typename T >
FindFromManagerHelper (const YAML::Node &node)
 
template<typename T , typename... Args>
FindFromManagerHelper (const YAML::Node &node, const std::string &key, Args... args)
 Recursive function to traverse YAML nodes. More...
 
template<typename T , typename... Args>
FindFromManager (const YAML::Node &node, Args... args)
 Wrapper function to call the recursive helper. More...
 
YAML::Node STRINGtoYAML (const std::string &yaml_string)
 Function to convert a YAML string to a YAML node. More...
 
std::string YAMLtoSTRING (const YAML::Node &node)
 KS: Convert a YAML node to a string representation. More...
 
std::string TMacroToString (const TMacro &macro)
 KS: Convert a ROOT TMacro object to a string representation. More...
 
YAML::Node TMacroToYAML (const TMacro &macro)
 KS: Convert a ROOT TMacro object to a YAML node. More...
 
TMacro YAMLtoTMacro (const YAML::Node &yaml_node, const std::string &name)
 Convert a YAML node to a ROOT TMacro object. More...
 
bool compareYAMLNodes (const YAML::Node &node1, const YAML::Node &node2)
 Compare if yaml nodes are identical. More...
 
template<typename TValue >
void OverrideConfig (YAML::Node node, std::string const &key, TValue val)
 Overrides the configuration settings based on provided arguments. More...
 
template<typename... Args>
void OverrideConfig (YAML::Node node, std::string const &key, Args... args)
 Overrides the configuration settings based on provided arguments. More...
 
std::string DemangleTypeName (const std::string &mangledName)
 Function to demangle type names. More...
 
template<typename Type >
Type Get (const YAML::Node &node, const std::string File, const int Line)
 Get content of config file. More...
 
template<typename Type >
Type GetFromManager (const YAML::Node &node, Type defval, const std::string File="", const int Line=1)
 Get content of config file if node is not found take default value specified. More...
 
YAML::Node LoadYamlConfig (const std::string &filename, const std::string &File, const int Line)
 Open YAML file. More...
 
const YAML::Node & Cnode (const YAML::Node &n)
 KS: Convenience wrapper to return a YAML node as-is. More...
 
YAML::Node MergeNodes (YAML::Node a, YAML::Node b)
 KS: Recursively merges two YAML nodes. More...
 
std::vector< double > ParseBounds (const YAML::Node &node, const std::string &File, const int Line)
 KS: Get bounds from YAML for example for selection cuts. More...
 
std::vector< std::vector< double > > Parse2DBounds (const YAML::Node &node, const std::string &File, const int Line)
 KS: Get 2D bounds from YAML for example for selection cuts. More...
 

Detailed Description

Utility functions for handling YAML nodes.

Note
you can read more about Yaml: here
Author
Kamil Skwarczynski
Luke Pickering

Definition in file YamlHelper.h.

Macro Definition Documentation

◆ Get2DBounds

#define Get2DBounds (   filename)    Parse2DBounds((filename), __FILE__, __LINE__)

Definition at line 563 of file YamlHelper.h.

◆ GetBounds

#define GetBounds (   filename)    ParseBounds((filename), __FILE__, __LINE__)

Definition at line 562 of file YamlHelper.h.

◆ M3OpenConfig

#define M3OpenConfig (   filename)    LoadYamlConfig((filename), __FILE__, __LINE__)

Macro to simplify calling LoadYaml with file and line info.

Definition at line 561 of file YamlHelper.h.

Function Documentation

◆ CheckNodeExists()

template<typename... Args>
bool CheckNodeExists ( const YAML::Node &  node,
Args...  args 
)

KS: Wrapper function to call the recursive helper.

Definition at line 55 of file YamlHelper.h.

55  {
56 // **********************
57  return CheckNodeExistsHelper(node, args...);
58 }
bool CheckNodeExistsHelper(const T &node)
Use this like this CheckNodeExists(config, "LikelihoodOptions", "TestStatistic"); KS: Base case for r...
Definition: YamlHelper.h:34

◆ CheckNodeExistsHelper() [1/2]

template<typename T >
bool CheckNodeExistsHelper ( const T &  node)

Use this like this CheckNodeExists(config, "LikelihoodOptions", "TestStatistic"); KS: Base case for recursion.

Definition at line 34 of file YamlHelper.h.

34  {
35 // **********************
36  (void)node;
37  return true; // Node exists, return true
38 }

◆ CheckNodeExistsHelper() [2/2]

template<typename T , typename... Args>
bool CheckNodeExistsHelper ( const T &  node,
const std::string &  key,
Args...  args 
)

KS: Recursive function to traverse YAML nodes.

Definition at line 43 of file YamlHelper.h.

43  {\
44 // **********************
45  if (!node[key]) {
46  //std::cerr << "Node " << key << " doesn't exist." << std::endl;
47  return false;
48  }
49  return CheckNodeExistsHelper(node[key], args...);
50 }

◆ Cnode()

const YAML::Node& Cnode ( const YAML::Node &  n)
inline

KS: Convenience wrapper to return a YAML node as-is.

Parameters
nInput YAML node.
Returns
Reference to the same YAML node.

Definition at line 390 of file YamlHelper.h.

390  {
391 // **********************
392  return n;
393 }

◆ compareYAMLNodes()

bool compareYAMLNodes ( const YAML::Node &  node1,
const YAML::Node &  node2 
)
inline

Compare if yaml nodes are identical.

Parameters
node1The first YAML node to compare.
node2The second YAML node to compare.
Returns
true If the two nodes are equivalent in type and content.
false If the two nodes differ in structure or content.

Definition at line 180 of file YamlHelper.h.

180  {
181 // **********************
182  // Check if the types of the nodes match
183  if (node1.Type() != node2.Type()) {
184  return false;
185  }
186 
187  // Compare scalar types (like strings, numbers)
188  if (node1.IsScalar() && node2.IsScalar()) {
189  return node1.as<std::string>() == node2.as<std::string>();
190  }
191 
192  // Compare sequences (like YAML lists)
193  if (node1.IsSequence() && node2.IsSequence()) {
194  if (node1.size() != node2.size()) {
195  return false;
196  }
197  for (std::size_t i = 0; i < node1.size(); ++i) {
198  if (!compareYAMLNodes(node1[i], node2[i])) {
199  return false;
200  }
201  }
202  return true;
203  }
204 
205  // Compare maps (like YAML dictionaries)
206  if (node1.IsMap() && node2.IsMap()) {
207  if (node1.size() != node2.size()) {
208  return false;
209  }
210  for (auto it1 = node1.begin(); it1 != node1.end(); ++it1) {
211  auto key = it1->first.as<std::string>();
212  if (!node2[key] || !compareYAMLNodes(it1->second, node2[key])) {
213  return false;
214  }
215  }
216  return true;
217  }
218 
219  // Default case: if it's neither scalar, sequence, nor map, consider it unequal
220  return false;
221 }
bool compareYAMLNodes(const YAML::Node &node1, const YAML::Node &node2)
Compare if yaml nodes are identical.
Definition: YamlHelper.h:180

◆ DemangleTypeName()

std::string DemangleTypeName ( const std::string &  mangledName)
inline

Function to demangle type names.

Definition at line 253 of file YamlHelper.h.

253  {
254 // **********************
255  int status = 0;
256  char* demangledName = abi::__cxa_demangle(mangledName.c_str(), nullptr, nullptr, &status);
257  std::string result = (status == 0) ? demangledName : mangledName;
258  free(demangledName);
259  return result;
260 }

◆ FindFromManager()

template<typename T , typename... Args>
T FindFromManager ( const YAML::Node &  node,
Args...  args 
)

Wrapper function to call the recursive helper.

Definition at line 84 of file YamlHelper.h.

84  {
85 // **********************
86  return FindFromManagerHelper<T>(node, args...);
87 }

◆ FindFromManagerHelper() [1/2]

template<typename T >
T FindFromManagerHelper ( const YAML::Node &  node)

Use this like this FindFromManager<std::string>(config, "LikelihoodOptions", "TestStatistic"); Base case for recursion

Definition at line 64 of file YamlHelper.h.

64  {
65 // **********************
66  return node.as<T>(); // Convert YAML node to the specified type
67 }

◆ FindFromManagerHelper() [2/2]

template<typename T , typename... Args>
T FindFromManagerHelper ( const YAML::Node &  node,
const std::string &  key,
Args...  args 
)

Recursive function to traverse YAML nodes.

Definition at line 72 of file YamlHelper.h.

72  {
73  // **********************
74  if (!node[key]) {
75  MACH3LOG_ERROR("Node {} doesn't exist.", key);
76  throw;
77  return T();
78  }
79  return FindFromManagerHelper<T>(node[key], args...); // Recursive call
80 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27

◆ Get()

template<typename Type >
Type Get ( const YAML::Node &  node,
const std::string  File,
const int  Line 
)

Get content of config file.

Parameters
nodeYaml node

Definition at line 266 of file YamlHelper.h.

266  {
267 // **********************
268  try {
269  // Attempt to convert the node to the expected type
270  return node.as<Type>();
271  } catch (const YAML::BadConversion& e) {
272  const std::string nodeAsString = YAMLtoSTRING(node);
273  MACH3LOG_ERROR("YAML type mismatch: {}", e.what());
274  MACH3LOG_ERROR("While trying to access variable {}", nodeAsString);
275  throw MaCh3Exception(File , Line );
276  } catch (const YAML::InvalidNode& e) {
277  std::string key = "<unknown>";
278  const std::string msg = e.what();
279  const std::string search = "first invalid key: \"";
280  auto start = msg.find(search);
281  if (start != std::string::npos) {
282  start += search.length();
283  auto end = msg.find("\"", start);
284  if (end != std::string::npos) {
285  key = msg.substr(start, end - start);
286  }
287  }
288  MACH3LOG_ERROR("Invalid YAML node: {}", e.what());
289  MACH3LOG_ERROR("While trying to access key: {}", key);
290  throw MaCh3Exception(File , Line );
291  }
292 }
std::string YAMLtoSTRING(const YAML::Node &node)
KS: Convert a YAML node to a string representation.
Definition: YamlHelper.h:107
Custom exception class for MaCh3 errors.

◆ GetFromManager()

template<typename Type >
Type GetFromManager ( const YAML::Node &  node,
Type  defval,
const std::string  File = "",
const int  Line = 1 
)

Get content of config file if node is not found take default value specified.

Parameters
nodeYaml node
defvalDefault value which will be used in case node doesn't exist

Definition at line 299 of file YamlHelper.h.

299  {
300 // **********************
301  if (!node) {
302  return defval;
303  }
304  try {
305  // Attempt to convert the node to the expected type
306  return node.as<Type>();
307  } catch (const YAML::BadConversion& e) {
308  const std::string nodeAsString = YAMLtoSTRING(node);
309  MACH3LOG_ERROR("YAML type mismatch: {}", e.what());
310  MACH3LOG_ERROR("While trying to access variable {}", nodeAsString);
311  //const std::string expectedType = DemangleTypeName(typeid(Type).name());
312  //MACH3LOG_ERROR("Expected argument is {}", expectedType);
313  if(File == "") {
314  throw MaCh3Exception(__FILE__ , __LINE__);
315  } else {
316  throw MaCh3Exception(File , Line );
317  }
318  }
319 }

◆ LoadYamlConfig()

YAML::Node LoadYamlConfig ( const std::string &  filename,
const std::string &  File,
const int  Line 
)
inline

Open YAML file.

Parameters
filenamename of filename to open
Filename of file where function is called
Linenumber where function is called

Definition at line 326 of file YamlHelper.h.

326  {
327 // **********************
328  // KS: YAML can be dumb and not throw error if you pass toml for example...
329  if (!(filename.length() >= 5 && filename.compare(filename.length() - 5, 5, ".yaml") == 0) &&
330  !(filename.length() >= 4 && filename.compare(filename.length() - 4, 4, ".yml") == 0)) {
331  MACH3LOG_ERROR("Invalid file extension: {}\n", filename);
332  throw MaCh3Exception(File, Line);
333  }
334 
335  try {
336  YAML::Node yamlNode = YAML::LoadFile(filename);
337 
338  // Convert the YAML file to string
339  std::ifstream fileStream(filename);
340  std::stringstream buffer;
341  buffer << fileStream.rdbuf();
342  std::string fileContent = buffer.str();
343 
344  // Use regex to find any line starting with `-` but not followed by space, digit, or dot
345  // This excludes valid numeric negative values like -1760.0
346  std::regex linePattern(R"(^\s*-(?![\d\s\.]).*)");
347 
348  std::istringstream contentStream(fileContent);
349  std::string lineconfig;
350  int lineNumber = 1;
351 
352  // KS: Instead of boolean, track flow-style list nesting depth
353  int flowListDepth = 0;
354 
355  while (std::getline(contentStream, lineconfig)) {
356  // Ignore YAML document separator
357  if (lineconfig.find("---") != std::string::npos) {
358  lineNumber++;
359  continue;
360  }
361 
362  // Update flow list depth (increment for each '[' and decrement for each ']')
363  for (char c : lineconfig) {
364  if (c == '[') flowListDepth++;
365  else if (c == ']') flowListDepth = std::max(0, flowListDepth - 1);
366  }
367 
368  // Check lines only outside flow-style lists
369  if (flowListDepth == 0 && std::regex_match(lineconfig, linePattern)) {
370  MACH3LOG_ERROR("Warning: Missing space or tab after '-' at line {}: {}\n", lineNumber, lineconfig);
371  throw MaCh3Exception(File, Line);
372  }
373 
374  lineNumber++;
375  }
376 
377  return yamlNode;
378 
379  } catch (const std::exception& e) {
380  MACH3LOG_ERROR("{}\n", e.what());
381  MACH3LOG_ERROR("Can't open file {}\n", filename);
382  throw MaCh3Exception(File, Line);
383  }
384 }

◆ MergeNodes()

YAML::Node MergeNodes ( YAML::Node  a,
YAML::Node  b 
)
inline

KS: Recursively merges two YAML nodes.

If both nodes are maps, their keys are merged. Scalar or null values in b will override those in a. If b is null, a is returned unchanged.

Note
Based on https://stackoverflow.com/a/41337824
Parameters
aThe base YAML node.
bThe YAML node to merge into a.
Returns
A new YAML node representing the merged result.

Definition at line 406 of file YamlHelper.h.

406  {
407 // **********************
408  if (!b.IsMap()) {
409  // If b is not a map, merge result is b, unless b is null
410  return b.IsNull() ? a : b;
411  }
412  if (!a.IsMap()) {
413  // If a is not a map, merge result is b
414  return b;
415  }
416  if (!b.size()) {
417  // If a is a map, and b is an empty map, return a
418  return a;
419  }
420  // Create a new map 'c' with the same mappings as a, merged with b
421  auto c = YAML::Node(YAML::NodeType::Map);
422  for (auto n : a) {
423  if (n.first.IsScalar()) {
424  const std::string & key = n.first.Scalar();
425  auto t = (Cnode(b)[key]);
426  if (t) {
427  c[n.first] = MergeNodes(n.second, t);
428  continue;
429  }
430  }
431  c[n.first] = n.second;
432  }
433  // Add the mappings from 'b' not already in 'c'
434  for (auto n : b) {
435  if (!n.first.IsScalar() || !Cnode(c)[n.first.Scalar()]) {
436  c[n.first] = n.second;
437  }
438  }
439  return c;
440 }
YAML::Node MergeNodes(YAML::Node a, YAML::Node b)
KS: Recursively merges two YAML nodes.
Definition: YamlHelper.h:406
const YAML::Node & Cnode(const YAML::Node &n)
KS: Convenience wrapper to return a YAML node as-is.
Definition: YamlHelper.h:390

◆ OverrideConfig() [1/2]

template<typename... Args>
void OverrideConfig ( YAML::Node  node,
std::string const &  key,
Args...  args 
)

Overrides the configuration settings based on provided arguments.

This function allows you to set configuration options in a nested YAML node.

Parameters
nodeYAML node that will be modified
argsThe arguments to override the configuration. The last argument will be used as the value
Note
Example usage:
OverrideConfig(config, "General", "OutputFile", "Wooimbouttamakeanameformyselfere.root");
OverrideConfig(config, "General", "MyDouble", 5.3);
std::string config
Definition: ProcessMCMC.cpp:29
void OverrideConfig(YAML::Node node, std::string const &key, TValue val)
Overrides the configuration settings based on provided arguments.
Definition: YamlHelper.h:227

Definition at line 246 of file YamlHelper.h.

246  {
247 // **********************
248  OverrideConfig(node[key], args...);
249 }

◆ OverrideConfig() [2/2]

template<typename TValue >
void OverrideConfig ( YAML::Node  node,
std::string const &  key,
TValue  val 
)

Overrides the configuration settings based on provided arguments.

Parameters
nodeYAML node that will be modified

Definition at line 227 of file YamlHelper.h.

227  {
228 // **********************
229  node[key] = val;
230 }

◆ Parse2DBounds()

std::vector<std::vector<double> > Parse2DBounds ( const YAML::Node &  node,
const std::string &  File,
const int  Line 
)
inline

KS: Get 2D bounds from YAML for example for selection cuts.

Parses a YAML node representing 2D selection bounds. Each element in the node must be a sequence of 1 or 2 scalar values. If a single value is given, it is interpreted as the center of a bin and expanded to [value - 0.5, value + 0.5]. If two values are given, they are used as-is. If an element is empty or null, default bounds are used.

This function is useful for interpreting kinematic or classification bounds specified in YAML configuration files.

Example YAML input:

bounds2D:
- [1]
- [0.2, 0.8]
- ["", "2.0"]

Resulting vector:

[ [0.5, 1.5],
[0.2, 0.8],
constexpr static const double KinematicLowBound
When parameter has no bound this serves as it. Lowest possible value the system.
Definition: Core.h:68
Parameters
nodeThe YAML node containing a sequence of bounds (each being a 1- or 2-element sequence).
FileThe name of the file calling this function (for error reporting).
LineThe line number in the file calling this function (for error reporting).
Returns
std::vector<std::vector<double>> A list of bound pairs for each selection region.

Definition at line 539 of file YamlHelper.h.

539  {
540 // **********************
541  std::vector<std::vector<double>> bounds;
542  if (!node || !node.IsSequence()) {
543  MACH3LOG_ERROR("Expected a sequence node for 2D bounds");
544  throw MaCh3Exception(File, Line);
545  }
546 
547  // Case 1: Single pair like [0.25, 0.5]
548  if (node.size() == 2 && node[0].IsScalar()) {
549  bounds.push_back(ParseBounds(node, File, Line));
550  } else { // Case 2: List of pairs like [[0.25, 0.5], [0.75, 1.0]]
551  for (std::size_t i = 0; i < node.size(); ++i) {
552  const YAML::Node& subnode = node[i];
553  bounds.push_back(ParseBounds(subnode, File, Line));
554  }
555  }
556 
557  return bounds;
558 }
std::vector< double > ParseBounds(const YAML::Node &node, const std::string &File, const int Line)
KS: Get bounds from YAML for example for selection cuts.
Definition: YamlHelper.h:455

◆ ParseBounds()

std::vector<double> ParseBounds ( const YAML::Node &  node,
const std::string &  File,
const int  Line 
)
inline

KS: Get bounds from YAML for example for selection cuts.

This function expects a YAML node of exactly two elements. If any of the elements is an empty string or null, it is replaced with a default kinematic bound. If the element is a non-empty string and cannot be converted to a double, an exception is thrown.

Parameters
nodeThe YAML node containing the bounds.
FileThe name of the file calling this function (for error context).
LineThe line number in the file calling this function.
Returns
std::vector<double> A vector of size 2 with the parsed bounds.

Definition at line 455 of file YamlHelper.h.

455  {
456 // **********************
457  std::vector<double> bounds;
458 
459  if (!node || !node.IsSequence() || (node.size() != 1 && node.size() != 2)) {
460  MACH3LOG_ERROR("Bounds must be a sequence of 1 or 2 elements, got size {}", static_cast<int>(node.size()));
461  throw MaCh3Exception(File, Line);
462  }
463 
464  if (node.size() == 1) {
465  const YAML::Node& val = node[0];
466 
467  if (!val || val.IsNull() || (val.IsScalar() && val.Scalar().empty())) {
468  MACH3LOG_ERROR("Single-element bounds must contain a valid numeric value.");
469  throw MaCh3Exception(File, Line);
470  } else if (val.IsScalar()) {
471  try {
472  const double center = val.as<double>();
473  if (std::floor(center) != center) {
474  MACH3LOG_ERROR("Invalid center value in Bounds[0]: '{}'. Expected an integer (e.g., 0 or 1).", static_cast<std::string>(val.Scalar()));
475  throw MaCh3Exception(File, Line);
476  }
477  bounds = {center - 0.5, center + 0.5};
478  } catch (const YAML::BadConversion& e) {
479  MACH3LOG_ERROR("Invalid value in Bounds[0]: '{}'. Expected a number.", static_cast<std::string>(val.Scalar()));
480  throw MaCh3Exception(File, Line);
481  }
482  } else {
483  MACH3LOG_ERROR("Invalid type in Bounds[0]");
484  throw MaCh3Exception(File, Line);
485  }
486  } else {
487  for (std::size_t i = 0; i < 2; ++i) {
488  const YAML::Node& val = node[i];
489 
490  if (!val || val.IsNull() || (val.IsScalar() && val.Scalar().empty())) {
491  bounds.push_back(i == 0 ? M3::KinematicLowBound : M3::KinematicUpBound);
492  } else if (val.IsScalar()) {
493  try {
494  bounds.push_back(val.as<double>());
495  } catch (const YAML::BadConversion& e) {
496  MACH3LOG_ERROR("Invalid value in Bounds[{}]: '{}'. Expected a number or empty string.",
497  static_cast<int>(i), static_cast<std::string>(val.Scalar()));
498  throw MaCh3Exception(File, Line);
499  }
500  } else {
501  MACH3LOG_ERROR("Invalid type in Bounds[{}]", static_cast<int>(i));
502  throw MaCh3Exception(File, Line);
503  }
504  }
505  }
506  return bounds;
507 }
constexpr static const double KinematicUpBound
When parameter has no bound this serves as it. Highest possible value the system.
Definition: Core.h:70

◆ STRINGtoYAML()

YAML::Node STRINGtoYAML ( const std::string &  yaml_string)
inline

Function to convert a YAML string to a YAML node.

Parameters
yaml_stringString which will be converted to yaml node

Definition at line 92 of file YamlHelper.h.

92  {
93 // **********************
94  try {
95  return YAML::Load(yaml_string);
96  } catch (const YAML::ParserException& e) {
97  MACH3LOG_ERROR("Error parsing YAML string: {}", e.what());
98  return YAML::Node();
99  }
100 }

◆ TMacroToString()

std::string TMacroToString ( const TMacro &  macro)
inline

KS: Convert a ROOT TMacro object to a string representation.

Parameters
macroThe ROOT TMacro object to convert.
Returns
std::string The string representation of the TMacro object.

Definition at line 118 of file YamlHelper.h.

118  {
119 // **********************
120  std::stringstream ss;
121 
122  // Retrieve lines from TMacro
123  TList* linesList = macro.GetListOfLines();
124  if (!linesList) {
125  MACH3LOG_ERROR("Failed to retrieve lines from TMacro.");
126  return "";
127  }
128 
129  TIter nextLine(linesList);
130  TObject *obj = nullptr;
131  while ((obj = nextLine())) {
132  TObjString* line = dynamic_cast<TObjString*>(obj);
133  if (!line) {
134  MACH3LOG_ERROR("Failed to cast object to TObjString.");
135  continue;
136  }
137  ss << line->GetString() << std::endl;
138  }
139 
140  return ss.str();
141 }

◆ TMacroToYAML()

YAML::Node TMacroToYAML ( const TMacro &  macro)
inline

KS: Convert a ROOT TMacro object to a YAML node.

Parameters
macroThe ROOT TMacro object to convert.
Returns
YAML::Node The YAML node representing the TMacro object.

Definition at line 147 of file YamlHelper.h.

147  {
148 // **********************
149  std::string yaml_string = TMacroToString(macro);
150 
151  // Convert the YAML string to a YAML node
152  YAML::Node yaml_node = STRINGtoYAML(yaml_string);
153 
154  return yaml_node;
155 }
YAML::Node STRINGtoYAML(const std::string &yaml_string)
Function to convert a YAML string to a YAML node.
Definition: YamlHelper.h:92
std::string TMacroToString(const TMacro &macro)
KS: Convert a ROOT TMacro object to a string representation.
Definition: YamlHelper.h:118

◆ YAMLtoSTRING()

std::string YAMLtoSTRING ( const YAML::Node &  node)
inline

KS: Convert a YAML node to a string representation.

Parameters
nodeThe YAML node to convert to a string.
Returns
std::string The string representation of the YAML node.
Warning
YAML is weird and drops " " for string so output may not be identical to yaml you provided

Definition at line 107 of file YamlHelper.h.

107  {
108 // **********************
109  YAML::Emitter emitter;
110  emitter << node;
111  return emitter.c_str();
112 }

◆ YAMLtoTMacro()

TMacro YAMLtoTMacro ( const YAML::Node &  yaml_node,
const std::string &  name 
)
inline

Convert a YAML node to a ROOT TMacro object.

Parameters
yaml_nodeThe YAML node to convert to a TMacro.
nameName of TMacro that will be saved
Returns
TMacro The TMacro object constructed from the YAML node.

Definition at line 162 of file YamlHelper.h.

162  {
163 // **********************
164  // Convert the YAML node to a string representation
165  std::string macro_string = YAMLtoSTRING(yaml_node);
166 
167  // Create a TMacro object with the collected lines
168  TMacro macro(name.c_str(), name.c_str());
169  macro.AddLine(macro_string.c_str());
170 
171  return macro;
172 }