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 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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) 2017, University of Utah
  15. * @copyright Copyright (c) 2014, XRI Geophysics, LLC
  16. * @copyright Copyright (c) 2014, Trevor Irons
  17. */
  18. #pragma once
  19. #ifndef HELPER_INC
  20. #define HELPER_INC
  21. #include "lemma.h"
  22. #include "yaml-cpp/yaml.h"
  23. namespace Lemma {
  24. /** \addtogroup LemmaCore
  25. * @{
  26. */
  27. /**
  28. * Convenience function for string conversion
  29. * @param[in] t input value to be converted to string
  30. * @return string representation of input value
  31. */
  32. template <class T>
  33. inline std::string to_string (const T& t) {
  34. std::stringstream ss;
  35. ss << t;
  36. return ss.str();
  37. }
  38. /// convert enums to string saves repeated code useful for YAML serializing
  39. std::string enum2String(const FREQUENCYUNITS& Units);
  40. /// convert enums to string saves repeated code useful for YAML serializing
  41. std::string enum2String(const TIMEUNITS& Units);
  42. /// convert enums to string saves repeated code useful for YAML serializing
  43. std::string enum2String(const MAGUNITS& Units);
  44. /// convert enums to string saves repeated code useful for YAML serializing
  45. std::string enum2String(const TEMPUNITS& Units);
  46. /// convert enums to string saves repeated code useful for YAML serializing
  47. std::string enum2String(const FEMCOILORIENTATION& Units);
  48. /// convert enums to string saves repeated code useful for YAML serializing
  49. std::string enum2String(const ORIENTATION& Units);
  50. /// convert enums to string saves repeated code useful for YAML serializing
  51. std::string enum2String(const FIELDCOMPONENT& Comp);
  52. /// convert enums to string saves repeated code useful for YAML serializing
  53. std::string enum2String(const HANKELTRANSFORMTYPE& Htype);
  54. /// convert enums to string saves repeated code useful for YAML serializing
  55. std::string enum2String(const FIELDCALCULATIONS& Htype);
  56. /// convert enums to string saves repeated code useful for YAML serializing
  57. std::string enum2String(const WINDOWTYPE& Wtype);
  58. // other way around is a template, where template argument lets us know
  59. // which specialisation to use.
  60. template <typename T>
  61. T string2Enum( const std::string& str );
  62. // Handy little class that indents a stream.
  63. // Based on solution provided here, todo may need to add to some managing class which keeps
  64. // track of nesting levels? But perhaps not. A Lemma class will contain pointers to other Lemma
  65. // classes. But those are not specifically listed out.
  66. // http://stackoverflow.com/questions/9599807/how-to-add-indention-to-the-stream-operator
  67. class IndentingOStreambuf : public std::streambuf {
  68. std::streambuf* myDest;
  69. bool myIsAtStartOfLine;
  70. std::string myIndent;
  71. std::ostream* myOwner;
  72. protected:
  73. virtual int overflow( int ch )
  74. {
  75. if ( myIsAtStartOfLine && ch != '\n' ) {
  76. myDest->sputn( myIndent.data(), myIndent.size() );
  77. }
  78. myIsAtStartOfLine = ch == '\n';
  79. return myDest->sputc( ch );
  80. }
  81. public:
  82. explicit IndentingOStreambuf(
  83. std::streambuf* dest, int indent = 4 )
  84. : myDest( dest )
  85. , myIsAtStartOfLine( true )
  86. , myIndent( indent, ' ' )
  87. , myOwner( NULL )
  88. {
  89. }
  90. explicit IndentingOStreambuf(
  91. std::ostream& dest, int indent = 4 )
  92. : myDest( dest.rdbuf() )
  93. , myIsAtStartOfLine( true )
  94. , myIndent( indent, ' ' )
  95. , myOwner( &dest )
  96. {
  97. myOwner->rdbuf( this );
  98. }
  99. virtual ~IndentingOStreambuf()
  100. {
  101. if ( myOwner != NULL ) {
  102. myOwner->rdbuf( myDest );
  103. }
  104. }
  105. };
  106. /** @}*/
  107. } // end namespace Lemma
  108. ///////////////////////////////////////////////////////
  109. // YAML Serializing helper functions. Can we move this into helper.h
  110. namespace YAML {
  111. template<>
  112. struct convert<Lemma::Complex> {
  113. static Node encode(const Lemma::Complex& rhs) {
  114. Node node;
  115. node["real"] = rhs.real();
  116. node["imag"] = rhs.imag();
  117. // No labels
  118. //node.push_back(rhs.real());
  119. //node.push_back(rhs.imag());
  120. node.SetTag( "Complex" ); // too verbose?
  121. return node;
  122. }
  123. static bool decode(const Node& node, Lemma::Complex& rhs) {
  124. // Disabled due to overly verbose output. Just believe...
  125. if( node.Tag() != "Complex" ) {
  126. return false;
  127. }
  128. rhs = Lemma::Complex( node["real"].as<Lemma::Real>(), node["imag"].as<Lemma::Real>() );
  129. // no label style
  130. //rhs = Lemma::Complex( node[0].as<Lemma::Real>(), node[1].as<Lemma::Real>() );
  131. return true;
  132. }
  133. };
  134. template<>
  135. struct convert<Lemma::Vector3Xr> {
  136. static Node encode(const Lemma::Vector3Xr& rhs) {
  137. Node node;
  138. node["size"] = rhs.cols();
  139. //node["rows"] = rhs.rows(); // == 3
  140. for (int ic=0; ic<rhs.cols(); ++ic) {
  141. node[ic].push_back( rhs(0, ic) );
  142. node[ic].push_back( rhs(1, ic) );
  143. node[ic].push_back( rhs(2, ic) );
  144. }
  145. node.SetTag( "Vector3Xr" );
  146. return node;
  147. }
  148. static bool decode(const Node& node, Lemma::Vector3Xr& rhs) {
  149. if( node.Tag() != "Vector3Xr" ) {
  150. return false;
  151. }
  152. rhs.resize( Eigen::NoChange, node["size"].as<int>() );
  153. for (unsigned int ic=0; ic<node.size(); ++ic) {
  154. int ir=0;
  155. for(YAML::const_iterator it=node[ic].begin();it!=node[ic].end();++it) {
  156. rhs(ir, ic) = it->as<Lemma::Real>();
  157. ++ir;
  158. }
  159. }
  160. return true;
  161. }
  162. };
  163. /**
  164. * \brief Serializes and Deserializes VectorXr arrays
  165. */
  166. template<>
  167. struct convert<Lemma::VectorXr> {
  168. static Node encode(const Lemma::VectorXr& rhs) {
  169. Node node;
  170. node["size"] = rhs.size();
  171. for (int ic=0; ic<rhs.size(); ++ic) {
  172. node["data"].push_back( rhs(ic) );
  173. }
  174. node.SetTag( "VectorXr" );
  175. return node;
  176. }
  177. static bool decode(const Node& node, Lemma::VectorXr& rhs) {
  178. if( node.Tag() != "VectorXr" ) {
  179. return false;
  180. }
  181. rhs.resize( node["size"].as<int>() );
  182. int ir=0;
  183. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  184. rhs(ir) = it->as<Lemma::Real>();
  185. ++ir;
  186. }
  187. return true;
  188. }
  189. };
  190. template<>
  191. struct convert<Lemma::VectorXcr> {
  192. static Node encode(const Lemma::VectorXcr& rhs) {
  193. Node node;
  194. node["size"] = rhs.size();
  195. for (int ic=0; ic<rhs.size(); ++ic) {
  196. node["data"].push_back( rhs(ic) );
  197. }
  198. node.SetTag( "VectorXcr" );
  199. return node;
  200. }
  201. static bool decode(const Node& node, Lemma::VectorXcr& rhs) {
  202. if( node.Tag() != "VectorXcr" ) {
  203. return false;
  204. }
  205. rhs.resize( node["size"].as<int>() );
  206. int ir=0;
  207. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  208. rhs(ir) = it->as<Lemma::Complex>();
  209. ++ir;
  210. }
  211. return true;
  212. }
  213. };
  214. template<>
  215. struct convert<Lemma::VectorXi> {
  216. static Node encode(const Lemma::VectorXi& rhs) {
  217. Node node;
  218. node["size"] = rhs.size();
  219. for (int ic=0; ic<rhs.size(); ++ic) {
  220. node["data"].push_back( rhs(ic) );
  221. }
  222. node.SetTag( "VectorXi" );
  223. return node;
  224. }
  225. static bool decode(const Node& node, Lemma::VectorXi& rhs) {
  226. if( node.Tag() != "VectorXi" ) {
  227. return false;
  228. }
  229. rhs.resize( node["size"].as<int>() );
  230. int ir=0;
  231. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  232. rhs(ir) = it->as<int>();
  233. ++ir;
  234. }
  235. return true;
  236. }
  237. };
  238. template<>
  239. struct convert<Lemma::Vector3r> {
  240. static Node encode(const Lemma::Vector3r& rhs) {
  241. Node node;
  242. for (int ic=0; ic<rhs.size(); ++ic) {
  243. node["data"].push_back( rhs(ic) );
  244. }
  245. node.SetTag( "Vector3r" );
  246. return node;
  247. }
  248. static bool decode(const Node& node, Lemma::Vector3r& rhs) {
  249. if( node.Tag() != "Vector3r" ) {
  250. return false;
  251. }
  252. int ir=0;
  253. for(YAML::const_iterator it=node["data"].begin(); it!=node["data"].end(); ++it) {
  254. rhs(ir) = it->as<Lemma::Real>();
  255. ++ir;
  256. }
  257. return true;
  258. }
  259. };
  260. template<>
  261. struct convert<Lemma::MatrixXr> {
  262. static Node encode(const Lemma::MatrixXr& rhs) {
  263. Node node;
  264. node["rows"] = rhs.rows();
  265. node["cols"] = rhs.cols();
  266. for (int ir=0; ir<rhs.rows(); ++ir) {
  267. for (int ic=0; ic<rhs.cols(); ++ic) {
  268. node["data"][ir][ic] = rhs(ir,ic);
  269. }
  270. node["data"][ir].SetStyle(YAML::EmitterStyle::Flow);
  271. }
  272. //node.SetStyle(YAML::EmitterStyle::Block);
  273. node.SetTag( "MatrixXr" );
  274. return node;
  275. }
  276. static bool decode(const Node& node, Lemma::MatrixXr& rhs) {
  277. if( node.Tag() != "MatrixXr" ) {
  278. return false;
  279. }
  280. int nc = node["cols"].as<int>();
  281. int nr = node["rows"].as<int>();
  282. rhs.resize(nr, nc);
  283. for (int ir=0; ir<nr; ++ir) {
  284. int ic=0;
  285. for(YAML::const_iterator it=node["data"][ir].begin(); it!=node["data"][ir].end(); ++it) {
  286. rhs(ir,ic) = it->as<Lemma::Real>();
  287. ++ic;
  288. }
  289. }
  290. return true;
  291. }
  292. };
  293. template<>
  294. struct convert<Lemma::MatrixXcr> {
  295. static Node encode(const Lemma::MatrixXcr& rhs) {
  296. Node node;
  297. node["rows"] = rhs.rows();
  298. node["cols"] = rhs.cols();
  299. for (int ir=0; ir<rhs.rows(); ++ir) {
  300. for (int ic=0; ic<rhs.cols(); ++ic) {
  301. node["data"][ir][ic] = rhs(ir,ic);
  302. }
  303. node["data"][ir].SetStyle(YAML::EmitterStyle::Flow);
  304. }
  305. //node.SetStyle(YAML::EmitterStyle::Block);
  306. node.SetTag( "MatrixXcr" );
  307. return node;
  308. }
  309. static bool decode(const Node& node, Lemma::MatrixXcr& rhs) {
  310. if( node.Tag() != "MatrixXcr" ) {
  311. return false;
  312. }
  313. int nc = node["cols"].as<int>();
  314. int nr = node["rows"].as<int>();
  315. rhs.resize(nr, nc);
  316. for (int ir=0; ir<nr; ++ir) {
  317. int ic=0;
  318. for(YAML::const_iterator it=node["data"][ir].begin(); it!=node["data"][ir].end(); ++it) {
  319. rhs(ir,ic) = it->as<Lemma::Complex>();
  320. ++ic;
  321. }
  322. }
  323. return true;
  324. }
  325. };
  326. }
  327. #endif // ----- #ifndef HELPER_INC -----