AliPhysics  4646b6b (4646b6b)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AliYAMLConfiguration.h
Go to the documentation of this file.
1 #ifndef ALIYAMLCONFIGURATION_H
2 #define ALIYAMLCONFIGURATION_H
3 
4 // CINT can't handle the yaml header because it has c++11!
5 #if !(defined(__CINT__) || defined(__MAKECINT__))
6 #include <yaml-cpp/yaml.h>
7 #endif
8 
9 #include <string>
10 #include <vector>
11 #include <ostream>
12 
13 #include <TObject.h>
14 
15 #include <AliLog.h>
16 
111 // operator<< has to be forward declared carefully to stay in the global namespace so that it works with CINT.
112 // For generally how to keep the operator in the global namespace, See: https://stackoverflow.com/a/38801633
113 namespace PWG { namespace Tools { class AliYAMLConfiguration; } }
114 std::ostream & operator<< (std::ostream &in, const PWG::Tools::AliYAMLConfiguration &myTask);
115 
116 namespace PWG {
117 namespace Tools {
118 
120  public:
121  AliYAMLConfiguration(const std::string prefixString = "AliEmcalCorrection", const std::string delimiterCharacter = ":");
123 
127  bool Initialize();
128  bool Reinitialize();
134  int AddEmptyConfiguration(const std::string & configurationName);
136  int AddConfiguration(std::string configurationFilename, std::string configurationName = "");
137  #if !(defined(__CINT__) || defined(__MAKECINT__))
138  int AddConfiguration(const YAML::Node node, std::string configurationName = "");
144  bool DoesConfigurationExist(const int i) const { return i >= 0 && static_cast<const unsigned int>(i) < fConfigurations.size(); }
145  bool DoesConfigurationExist(const std::string & name) const { return DoesConfigurationExist(GetConfigurationIndexFromName(name, fConfigurations)); }
146  const std::pair<std::string, YAML::Node> & GetConfiguration(const int i) const { return fConfigurations.at(i); }
147  const std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) const { return GetConfiguration(GetConfigurationIndexFromName(name, fConfigurations)); }
148  std::pair<std::string, YAML::Node> & GetConfiguration(const int i) { return fConfigurations.at(i); }
149  std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) { return GetConfiguration(GetConfigurationIndexFromName(name, fConfigurations)); }
155  std::string GetConfigurationNameFromIndex(const unsigned int i) const { return fConfigurations.at(i).first; }
156  int GetConfigurationIndexFromName(const std::string & name) const { return GetConfigurationIndexFromName(name, fConfigurations); }
162  bool RemoveConfiguration(const unsigned int i);
169  // Helper functions to retrieve property values
170  template<typename T>
171  bool GetProperty(std::vector<std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const;
172  template<typename T>
173  bool GetProperty(const std::vector<std::string> propertyPath, T & property, const bool requiredProperty) const;
174  // Retrieve property driver function.
175  template<typename T>
176  bool GetProperty(std::string propertyName, T & property, const bool requiredProperty = true) const;
182  // Write property driver function.
183  template<typename T>
184  bool WriteProperty(std::string propertyName, T & property, std::string configurationName = "");
186  #endif
187 
191  bool WriteConfiguration(const std::string & filename, const unsigned int i) const;
192  bool WriteConfiguration(const std::string & filename, const std::string & configurationName) const;
198  bool CompareConfigurations(const int config1, const int config2) const;
199  bool CompareConfigurations(const int config1, const std::string & config2) const { return CompareConfigurations(config1, GetConfigurationIndexFromName(config2, fConfigurations)); }
200  bool CompareConfigurations(const std::string & config1, const std::string & config2) const { return CompareConfigurations(GetConfigurationIndexFromName(config1, fConfigurations), GetConfigurationIndexFromName(config2, fConfigurations)); }
201 
207  std::string toString(const int index = -1) const;
208  std::ostream & Print(std::ostream &in, const int index = -1) const;
209  std::ostream & Print(std::ostream &in, const std::string & configurationName) const;
210  friend std::ostream & ::operator<< (std::ostream &in, const AliYAMLConfiguration &myTask);
211  void Print(Option_t* /* opt */ = "") const;
214  protected:
215 
216  // Utility functions
217  // File utilities
218  inline bool DoesFileExist(const std::string & filename) const;
219  void SetupReadingConfigurationFilePath(std::string & filename, const std::string & fileIdentifier) const;
220  void WriteConfigurationToFilePath(const std::string & localFilename, std::string filename) const;
221  #if !(defined(__CINT__) || defined(__MAKECINT__))
222  // Printing
223  void PrintConfiguration(std::ostream & stream, const std::pair<std::string, YAML::Node> & configPair) const;
224  #endif
225  // Configuration utilities
226  template<typename T>
227  unsigned int GetConfigurationIndexFromName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const;
228 
229  bool IsSharedValue(std::string & value) const;
230  #if !(defined(__CINT__) || defined(__MAKECINT__))
231  template<typename T>
232  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void());
233  template<typename T>
234  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void());
235  template<typename T>
236  void PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const;
237  template<typename T>
238  void PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const;
239 
240  template<typename T>
241  bool GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const;
242  template<typename T>
243  bool GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const;
244 
245  template<typename T>
246  void WriteValue(YAML::Node & node, std::string propertyName, T & proeprty);
247 
248  std::vector<std::pair<std::string, YAML::Node> > fConfigurations;
249  #endif
250  std::vector<std::pair<std::string, std::string> > fConfigurationsStrings;
251 
253  std::string fPrefixString;
254  std::string fDelimiter;
255 
257  ClassDef(AliYAMLConfiguration, 1); // YAML Configuration
259 };
260 
261 #if !(defined(__CINT__) || defined(__MAKECINT__))
262 
272 template<typename T>
273 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void())
274 {
275  tempMessage << " with value \"" << property << "\"";
276 }
277 
286 template<typename T>
287 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void())
288 {
289  tempMessage << " with value(s):";
290  for (auto it = property.begin(); it != property.end(); it++) {
291  tempMessage << "\n\t- " << *it;
292  }
293 }
294 
306 template<typename T>
307 void AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const
308 {
309  // Cannot easily print these types, so just note that is the case!
310  tempMessage << " with a value that cannot be trivially printed";
311 }
312 
324 template<typename T>
325 void AliYAMLConfiguration::PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const
326 {
327  // By passing zero, it will first lookup the int, and then the long
329 }
330 
340 template<typename T>
341 bool AliYAMLConfiguration::GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const
342 {
343  if (node[propertyName])
344  {
345  property = node[propertyName].as<T>();
346  return true;
347  }
348  return false;
349 }
350 
362 template<typename T>
363 bool AliYAMLConfiguration::GetProperty(std::vector <std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const
364 {
365  propertyPath.push_back(propertyName);
366  return GetProperty(propertyPath, property, requiredProperty);
367 }
368 
379 template<typename T>
380 bool AliYAMLConfiguration::GetProperty(const std::vector <std::string> propertyPath, T & property, const bool requiredProperty) const
381 {
382  // Combine the requested names together
383  std::string requestedName = "";
384  for (auto & str : propertyPath)
385  {
386  if (requestedName.length() > 0) {
387  requestedName += ":" + str;
388  }
389  else {
390  requestedName = str;
391  }
392  }
393 
394  // Pass on the properly requested call
395  return GetProperty(requestedName, property, requiredProperty);
396 }
397 
409 template<typename T>
410 bool AliYAMLConfiguration::GetProperty(std::string propertyName, T & property, const bool requiredProperty) const
411 {
412  // Remove the prefix string if in name
413  std::size_t prefixStringLocation = propertyName.find(fPrefixString);
414  if (prefixStringLocation != std::string::npos)
415  {
416  // Remove the prefix string
417  propertyName.erase(prefixStringLocation, prefixStringLocation + fPrefixString.length());
418  }
419 
420  bool setProperty = false;
421  for (auto configPair : fConfigurations)
422  {
423  if (setProperty == true) {
424  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Property \"" << propertyName << "\" found!\n";
425  break;
426  }
427 
428  // IsNull checks is a node is empty. A node is empty if it is created.
429  // IsDefined checks if the node that was requested was not actually created.
430  if (configPair.second.IsNull() != true)
431  {
432  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Looking for parameter \"" << propertyName << "\" in \"" << configPair.first << "\" configuration\n";
433  // NOTE: This may not exist, but that is entirely fine.
434  YAML::Node sharedParameters = configPair.second["sharedParameters"];
435  setProperty = GetProperty(configPair.second, sharedParameters, configPair.first, propertyName, property);
436  }
437  }
438 
439  if (setProperty != true && requiredProperty == true)
440  {
441  std::stringstream message;
442  message << "Failed to retrieve required property \""
443  << propertyName << "\" from available configurations!" << std::endl;
444  AliFatalGeneral("AliYAMLConfiguration", message.str().c_str());
445  }
446 
447  // Return whether the value was actually set
448  return setProperty;
449 }
450 
473 template<typename T>
474 bool AliYAMLConfiguration::GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const
475 {
476  // Used as a buffer for printing complicated messages
477  std::stringstream tempMessage;
478 
479  bool returnValue = false;
480 
481  const std::string specializationDelimiter = "_";
482  size_t delimiterPosition = 0;
483  std::string tempPropertyName = propertyName;
484 
485  if ((delimiterPosition = tempPropertyName.find(fDelimiter)) != std::string::npos)
486  {
487  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
488  tempPropertyName.erase(0, delimiterPosition + fDelimiter.length());
489 
490  // Attempt to use the node name
491  if (node[nodeName].IsDefined() == true)
492  {
493  // Retrieve node and then recurse
494  YAML::Node tempNode = node[nodeName];
495  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper with node \"" << nodeName << "\".\n";
496  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
497  }
498 
499  // Check for the specialization if the nodeName is undefined.
500  // Alternatively, if the value was not returned successfully, we should also check for the specialization
501  // such as inheritnace for input objects.
502  if (node[nodeName].IsDefined() == false || returnValue == false)
503  {
504  // Check for specialization
505  if ((delimiterPosition = nodeName.find(specializationDelimiter)) != std::string::npos)
506  {
507  std::string specializationNodeName = nodeName.substr(0, delimiterPosition);
508  YAML::Node tempNode = node[specializationNodeName];
509  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper through dropping the specializtion and using node \"" << specializationNodeName << "\".\n";
510  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
511  }
512  else {
513  returnValue = false;
514  }
515  }
516  }
517  else
518  {
519  // Check if node exists!
520  if (node[propertyName])
521  {
522  // Handle shared parameters
523  bool isShared = false;
524  // Will contain the name of the property in the sharedParameters section that should be retrieved
525  // if it is requested through the user configuration.
526  std::string sharedValueName = "";
527  // Necessary because it fails on vectors and other complex objects that are YAML sequences.
528  if (std::is_arithmetic<T>::value || std::is_same<T, std::string>::value || std::is_same<T, bool>::value)
529  {
530  // Retrieve value as string to check for shared value
531  sharedValueName = node[propertyName].as<std::string>();
532  // Check for a shared value
533  isShared = IsSharedValue(sharedValueName);
534  }
535 
536  // Setup printable message
537  tempMessage.str("");
538  tempMessage << "property \""
539  << propertyName
540  << "\" using " << ( isShared ? "\"sharedParameters:" + sharedValueName + "\" in " : "" )
541  << "values from the " << configurationName << " configuration";
542 
543  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Retrieveing " << tempMessage.str() << "\n";
544 
545  // Retrieve result
546  bool retrievalResult = false;
547  if (isShared == true) {
548  // Retrieve from the shared parameter node directly.
549  retrievalResult = GetPropertyFromNode(sharedParametersNode, sharedValueName, property);
550  }
551  else {
552  retrievalResult = GetPropertyFromNode(node, propertyName, property);
553  }
554 
555  // Inform about the result
556  if (retrievalResult == true) {
557  // Add the retrieved value to the message (only if trivially printable)
559  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Succeeded in retrieveing " << tempMessage.str() << "\n";
560  returnValue = true;
561  }
562  else {
563  returnValue = false;
564  }
565  }
566  }
567 
568  return returnValue;
569 }
570 
581 template<typename T>
582 bool AliYAMLConfiguration::WriteProperty(std::string propertyName, T & property, std::string configurationName)
583 {
584  unsigned int configurationIndex = 0;
585  if (configurationName != "")
586  {
587  configurationIndex = GetConfigurationIndexFromName(configurationName, fConfigurations);
588  }
589 
590  if (fConfigurations.size() == 0) {
591  AliErrorStream() << "No configurations available! Property will not be written!\n";
592  return false;
593  }
594 
595  std::pair<std::string, YAML::Node> & configPair = fConfigurations.at(configurationIndex);
596 
597  WriteValue(configPair.second, propertyName, property);
598  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Final Node:\n" << configPair.second << "\n";
599 
600  return true;
601 }
602 
610 template<typename T>
611 void AliYAMLConfiguration::WriteValue(YAML::Node & node, std::string propertyName, T & property)
612 {
613  // Find the node name we are interested in
614  // Derived from: https://stackoverflow.com/a/14266139
615  const std::string delimiter = ":";
616  size_t delimiterPosition = 0;
617  std::string tempPropertyName = propertyName;
618 
619  if ((delimiterPosition = tempPropertyName.find(delimiter)) != std::string::npos)
620  {
621  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
622  tempPropertyName.erase(0, delimiterPosition + delimiter.length());
623  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "nodeName: " << nodeName << "\n";
624  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node Before:\n" << node << "\n";
625  if (node[nodeName].IsDefined()) {
626  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Using existing node\n";
627  YAML::Node tempNode = node[nodeName];
628  WriteValue(tempNode, tempPropertyName, property);
629  }
630  else {
631  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Creating new node\n";
632  YAML::Node tempNode;
633  node[nodeName] = tempNode;
634  WriteValue(tempNode, tempPropertyName, property);
635  }
636  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node After:\n" << node << "\n";
637  }
638  else {
639  // We have finished the recursion. Now we need to save the actual property.
640  node[propertyName] = property;
641  }
642 }
643 
644 #endif
645 
655 template<typename T>
656 unsigned int AliYAMLConfiguration::GetConfigurationIndexFromName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const
657 {
658  int index = -1;
659  for (const auto & configPair : configurations)
660  {
661  if (configPair.first == name) {
662  // Retrieve index
663  // See: https://stackoverflow.com/a/10962459
664  index = std::addressof(configPair) - std::addressof(configurations[0]);
665  break;
666  }
667  }
668 
669  return index;
670 }
671 
672 } // namespace Tools
673 } // namespace PWG
674 
675 #endif /* ALIYAMLCONFIGURATION_H */
bool RemoveConfiguration(const std::string &name)
const char * filename
Definition: TestFCM.C:1
bool CompareConfigurations(const int config1, const std::string &config2) const
bool CompareConfigurations(const int config1, const int config2) const
bool WriteConfiguration(const std::string &filename, const unsigned int i) const
const std::pair< std::string, YAML::Node > & GetConfiguration(const int i) const
void WriteConfigurationToFilePath(const std::string &localFilename, std::string filename) const
bool GetProperty(std::vector< std::string > propertyPath, const std::string &propertyName, T &property, const bool requiredProperty) const
bool fInitialized
True if the configurations have been initialized.
void SetupReadingConfigurationFilePath(std::string &filename, const std::string &fileIdentifier) const
bool DoesConfigurationExist(const int i) const
int GetConfigurationIndexFromName(const std::string &name) const
UShort_t T(UShort_t m, UShort_t t)
Definition: RingBits.C:60
const std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name) const
std::string fDelimiter
Delimiter character to separate each level of the request.
void PrintConfiguration(std::ostream &stream, const std::pair< std::string, YAML::Node > &configPair) const
bool DoesConfigurationExist(const std::string &name) const
std::ostream & operator<<(std::ostream &in, const PWG::Tools::AliYAMLConfiguration &myTask)
bool IsSharedValue(std::string &value) const
std::ostream & Print(std::ostream &in, const int index=-1) const
std::string fPrefixString
Contains the prefix of any names base node names which should be removed.
int AddEmptyConfiguration(const std::string &configurationName)
Add YAML configuration at configurationFilename to available configurations.
std::vector< std::pair< std::string, YAML::Node > > fConfigurations
! Contains all YAML configurations. The first element has the highest precedence. ...
bool CompareConfigurations(const std::string &config1, const std::string &config2) const
auto PrintRetrievedPropertyValueImpl(std::stringstream &tempMessage, const T &property, int) const -> decltype(tempMessage<< property, void())
std::pair< std::string, YAML::Node > & GetConfiguration(const int i)
AliYAMLConfiguration(const std::string prefixString="AliEmcalCorrection", const std::string delimiterCharacter=":")
std::vector< std::pair< std::string, std::string > > fConfigurationsStrings
Contains all YAML configurations as strings so that they can be streamed.
YAML configuration class for AliPhysics.
bool GetPropertyFromNode(const YAML::Node &node, std::string propertyName, T &property) const
bool WriteProperty(std::string propertyName, T &property, std::string configurationName="")
bool RemoveConfiguration(const unsigned int i)
void WriteValue(YAML::Node &node, std::string propertyName, T &proeprty)
int AddConfiguration(std::string configurationFilename, std::string configurationName="")
const char Option_t
Definition: External.C:48
bool DoesFileExist(const std::string &filename) const
std::string toString(const int index=-1) const
void PrintRetrievedPropertyValue(std::stringstream &tempMessage, const T &property) const
std::string GetConfigurationNameFromIndex(const unsigned int i) const
std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name)