Lemma is an Electromagnetics API
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

helper.h 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* This file is part of Lemma, a geophysical modelling and inversion API.
  2. * More information is available at http://lemmasoftware.org
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file
  10. * @date 10/02/2014 02:49:55 PM
  11. * @version $Id$
  12. * @author Trevor Irons (ti)
  13. * @email Trevor.Irons@xri-geo.com
  14. * @copyright Copyright (c) 2014, XRI Geophysics, LLC
  15. * @copyright Copyright (c) 2014, Trevor Irons
  16. */
  17. #pragma once
  18. #ifndef HELPER_INC
  19. #define HELPER_INC
  20. #include "lemma.h"
  21. #ifdef HAVE_YAMLCPP
  22. #include "yaml-cpp/yaml.h"
  23. #endif
  24. namespace Lemma {
  25. template <class T>
  26. inline std::string to_string (const T& t) {
  27. std::stringstream ss;
  28. ss << t;
  29. return ss.str();
  30. }
  31. // handy little way to convert enums, saves repeated code useful for YAML serializing
  32. std::string enum2String(const FREQUENCYUNITS& Units);
  33. std::string enum2String(const TIMEUNITS& Units);
  34. std::string enum2String(const MAGUNITS& Units);
  35. std::string enum2String(const TEMPUNITS& Units);
  36. std::string enum2String(const FEMCOILORIENTATION& Units);
  37. std::string enum2String(const ORIENTATION& Units);
  38. std::string enum2String(const FIELDCOMPONENT& Comp);
  39. std::string enum2String(const HANKELTRANSFORMTYPE& Htype);
  40. std::string enum2String(const FIELDCALCULATIONS& Htype);
  41. // other way around is a template, where template argument lets us know
  42. // which specialisation to use.
  43. template <typename T>
  44. T string2Enum( const std::string& str );
  45. // Handy little class that indents a stream.
  46. // Based on solution provided here, todo may need to add to some managing class which keeps
  47. // track of nesting levels? But perhaps not. A Lemma class will contain pointers to other Lemma
  48. // classes. But those are not specifically listed out.
  49. // http://stackoverflow.com/questions/9599807/how-to-add-indention-to-the-stream-operator
  50. class IndentingOStreambuf : public std::streambuf {
  51. std::streambuf* myDest;
  52. bool myIsAtStartOfLine;
  53. std::string myIndent;
  54. std::ostream* myOwner;
  55. protected:
  56. virtual int overflow( int ch )
  57. {
  58. if ( myIsAtStartOfLine && ch != '\n' ) {
  59. myDest->sputn( myIndent.data(), myIndent.size() );
  60. }
  61. myIsAtStartOfLine = ch == '\n';
  62. return myDest->sputc( ch );
  63. }
  64. public:
  65. explicit IndentingOStreambuf(
  66. std::streambuf* dest, int indent = 4 )
  67. : myDest( dest )
  68. , myIsAtStartOfLine( true )
  69. , myIndent( indent, ' ' )
  70. , myOwner( NULL )
  71. {
  72. }
  73. explicit IndentingOStreambuf(
  74. std::ostream& dest, int indent = 4 )
  75. : myDest( dest.rdbuf() )
  76. , myIsAtStartOfLine( true )
  77. , myIndent( indent, ' ' )
  78. , myOwner( &dest )
  79. {
  80. myOwner->rdbuf( this );
  81. }
  82. virtual ~IndentingOStreambuf()
  83. {
  84. if ( myOwner != NULL ) {
  85. myOwner->rdbuf( myDest );
  86. }
  87. }
  88. };
  89. } // end namespace Lemma
  90. #ifdef HAVE_YAMLCPP
  91. ///////////////////////////////////////////////////////
  92. // YAML Serializing helper functions. Can we move this into helper.h
  93. namespace YAML {
  94. template<>
  95. struct convert<Lemma::Complex> {
  96. static Node encode(const Lemma::Complex& rhs) {
  97. Node node;
  98. node["real"] = rhs.real();
  99. node["imag"] = rhs.imag();
  100. // No labels
  101. //node.push_back(rhs.real());
  102. //node.push_back(rhs.imag());
  103. node.SetTag( "Complex" ); // too verbose?
  104. return node;
  105. }
  106. static bool decode(const Node& node, Lemma::Complex& rhs) {
  107. // Disabled due to overly verbose output. Just believe...
  108. if( node.Tag() != "Complex" ) {
  109. return false;
  110. }
  111. rhs = Lemma::Complex( node["real"].as<Lemma::Real>(), node["imag"].as<Lemma::Real>() );
  112. // no label style
  113. //rhs = Lemma::Complex( node[0].as<Lemma::Real>(), node[1].as<Lemma::Real>() );
  114. return true;
  115. }
  116. };
  117. template<>
  118. struct convert<Lemma::Vector3Xr> {
  119. static Node encode(const Lemma::Vector3Xr& rhs) {
  120. Node node;
  121. node["size"] = rhs.cols();
  122. //node["rows"] = rhs.rows(); // == 3
  123. for (int ic=0; ic<rhs.cols(); ++ic) {
  124. node[ic].push_back( rhs(0, ic) );
  125. node[ic].push_back( rhs(1, ic) );
  126. node[ic].push_back( rhs(2, ic) );
  127. }
  128. node.SetTag( "Vector3Xr" );
  129. return node;
  130. }
  131. static bool decode(const Node& node, Lemma::Vector3Xr& rhs) {
  132. if( node.Tag() != "Vector3Xr" ) {
  133. return false;
  134. }
  135. rhs.resize( Eigen::NoChange, node["size"].as<int>() );
  136. for (unsigned int ic=0; ic<node.size(); ++ic) {
  137. int ir=0;
  138. for(YAML::const_iterator it=node[ic].begin();it!=node[ic].end();++it) {
  139. rhs(ir, ic) = it->as<Lemma::Real>();
  140. ++ir;
  141. }
  142. }
  143. return true;
  144. }
  145. };
  146. template<>
  147. struct convert<Lemma::VectorXr> {
  148. static Node encode(const Lemma::VectorXr& rhs) {
  149. Node node;
  150. node["size"] = rhs.size();
  151. for (int ic=0; ic<rhs.size(); ++ic) {
  152. node["data"].push_back( rhs(ic) );
  153. }
  154. node.SetTag( "VectorXr" );
  155. return node;
  156. }
  157. static bool decode(const Node& node, Lemma::VectorXr& rhs) {
  158. if( node.Tag() != "VectorXr" ) {
  159. return false;
  160. }
  161. rhs.resize( node["size"].as<int>() );
  162. int ir=0;
  163. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  164. rhs(ir) = it->as<Lemma::Real>();
  165. ++ir;
  166. }
  167. return true;
  168. }
  169. };
  170. template<>
  171. struct convert<Lemma::VectorXcr> {
  172. static Node encode(const Lemma::VectorXcr& rhs) {
  173. Node node;
  174. node["size"] = rhs.size();
  175. for (int ic=0; ic<rhs.size(); ++ic) {
  176. node["data"].push_back( rhs(ic) );
  177. }
  178. node.SetTag( "VectorXcr" );
  179. return node;
  180. }
  181. static bool decode(const Node& node, Lemma::VectorXcr& rhs) {
  182. if( node.Tag() != "VectorXcr" ) {
  183. return false;
  184. }
  185. rhs.resize( node["size"].as<int>() );
  186. int ir=0;
  187. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  188. rhs(ir) = it->as<Lemma::Complex>();
  189. ++ir;
  190. }
  191. return true;
  192. }
  193. };
  194. template<>
  195. struct convert<Lemma::VectorXi> {
  196. static Node encode(const Lemma::VectorXi& rhs) {
  197. Node node;
  198. node["size"] = rhs.size();
  199. for (int ic=0; ic<rhs.size(); ++ic) {
  200. node["data"].push_back( rhs(ic) );
  201. }
  202. node.SetTag( "VectorXi" );
  203. return node;
  204. }
  205. static bool decode(const Node& node, Lemma::VectorXi& rhs) {
  206. if( node.Tag() != "VectorXi" ) {
  207. return false;
  208. }
  209. rhs.resize( node["size"].as<int>() );
  210. int ir=0;
  211. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  212. rhs(ir) = it->as<int>();
  213. ++ir;
  214. }
  215. return true;
  216. }
  217. };
  218. template<>
  219. struct convert<Lemma::Vector3r> {
  220. static Node encode(const Lemma::Vector3r& rhs) {
  221. Node node;
  222. for (int ic=0; ic<rhs.size(); ++ic) {
  223. node[0].push_back( rhs(ic) );
  224. }
  225. node.SetTag( "Vector3r" );
  226. return node;
  227. }
  228. static bool decode(const Node& node, Lemma::Vector3r& rhs) {
  229. if( node.Tag() != "Vector3r" ) {
  230. return false;
  231. }
  232. int ir=0;
  233. for(YAML::const_iterator it=node[0].begin(); it!=node[0].end(); ++it) {
  234. rhs(ir) = it->as<Lemma::Real>();
  235. ++ir;
  236. }
  237. return true;
  238. }
  239. };
  240. }
  241. #endif //HAVE_YAMLCPP
  242. #endif // ----- #ifndef HELPER_INC -----