matplotlibcpp.h 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. #pragma once
  2. #include <vector>
  3. #include <map>
  4. #include <numeric>
  5. #include <algorithm>
  6. #include <stdexcept>
  7. #include <iostream>
  8. #include <cstdint> // <cstdint> requires c++11 support
  9. #include <functional>
  10. #include <Python.h>
  11. #ifndef WITHOUT_NUMPY
  12. # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
  13. # include <numpy/arrayobject.h>
  14. #endif // WITHOUT_NUMPY
  15. #if PY_MAJOR_VERSION >= 3
  16. # define PyString_FromString PyUnicode_FromString
  17. #endif
  18. namespace matplotlibcpp {
  19. namespace detail {
  20. static std::string s_backend;
  21. struct _interpreter {
  22. PyObject *s_python_function_show;
  23. PyObject *s_python_function_close;
  24. PyObject *s_python_function_draw;
  25. PyObject *s_python_function_pause;
  26. PyObject *s_python_function_save;
  27. PyObject *s_python_function_figure;
  28. PyObject *s_python_function_fignum_exists;
  29. PyObject *s_python_function_plot;
  30. PyObject *s_python_function_quiver;
  31. PyObject *s_python_function_semilogx;
  32. PyObject *s_python_function_semilogy;
  33. PyObject *s_python_function_loglog;
  34. PyObject *s_python_function_fill_between;
  35. PyObject *s_python_function_hist;
  36. PyObject *s_python_function_scatter;
  37. PyObject *s_python_function_subplot;
  38. PyObject *s_python_function_legend;
  39. PyObject *s_python_function_xlim;
  40. PyObject *s_python_function_ion;
  41. PyObject *s_python_function_ginput;
  42. PyObject *s_python_function_ylim;
  43. PyObject *s_python_function_title;
  44. PyObject *s_python_function_axis;
  45. PyObject *s_python_function_xlabel;
  46. PyObject *s_python_function_ylabel;
  47. PyObject *s_python_function_xticks;
  48. PyObject *s_python_function_yticks;
  49. PyObject *s_python_function_grid;
  50. PyObject *s_python_function_clf;
  51. PyObject *s_python_function_errorbar;
  52. PyObject *s_python_function_annotate;
  53. PyObject *s_python_function_tight_layout;
  54. PyObject *s_python_empty_tuple;
  55. PyObject *s_python_function_stem;
  56. PyObject *s_python_function_xkcd;
  57. PyObject *s_python_function_text;
  58. PyObject *s_python_function_suptitle;
  59. PyObject *s_python_function_bar;
  60. PyObject *s_python_function_subplots_adjust;
  61. /* For now, _interpreter is implemented as a singleton since its currently not possible to have
  62. multiple independent embedded python interpreters without patching the python source code
  63. or starting a separate process for each.
  64. http://bytes.com/topic/python/answers/793370-multiple-independent-python-interpreters-c-c-program
  65. */
  66. static _interpreter& get() {
  67. static _interpreter ctx;
  68. return ctx;
  69. }
  70. private:
  71. #ifndef WITHOUT_NUMPY
  72. # if PY_MAJOR_VERSION >= 3
  73. void *import_numpy() {
  74. import_array(); // initialize C-API
  75. return NULL;
  76. }
  77. # else
  78. void import_numpy() {
  79. import_array(); // initialize C-API
  80. }
  81. # endif
  82. #endif
  83. _interpreter() {
  84. // optional but recommended
  85. #if PY_MAJOR_VERSION >= 3
  86. wchar_t name[] = L"plotting";
  87. #else
  88. char name[] = "plotting";
  89. #endif
  90. Py_SetProgramName(name);
  91. Py_Initialize();
  92. #ifndef WITHOUT_NUMPY
  93. import_numpy(); // initialize numpy C-API
  94. #endif
  95. PyObject* matplotlibname = PyString_FromString("matplotlib");
  96. PyObject* pyplotname = PyString_FromString("matplotlib.pyplot");
  97. PyObject* pylabname = PyString_FromString("pylab");
  98. if (!pyplotname || !pylabname || !matplotlibname) {
  99. throw std::runtime_error("couldnt create string");
  100. }
  101. PyObject* matplotlib = PyImport_Import(matplotlibname);
  102. Py_DECREF(matplotlibname);
  103. if (!matplotlib) { throw std::runtime_error("Error loading module matplotlib!"); }
  104. // matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
  105. // or matplotlib.backends is imported for the first time
  106. if (!s_backend.empty()) {
  107. PyObject_CallMethod(matplotlib, const_cast<char*>("use"), const_cast<char*>("s"), s_backend.c_str());
  108. }
  109. PyObject* pymod = PyImport_Import(pyplotname);
  110. Py_DECREF(pyplotname);
  111. if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); }
  112. PyObject* pylabmod = PyImport_Import(pylabname);
  113. Py_DECREF(pylabname);
  114. if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); }
  115. s_python_function_show = PyObject_GetAttrString(pymod, "show");
  116. s_python_function_close = PyObject_GetAttrString(pymod, "close");
  117. s_python_function_draw = PyObject_GetAttrString(pymod, "draw");
  118. s_python_function_pause = PyObject_GetAttrString(pymod, "pause");
  119. s_python_function_figure = PyObject_GetAttrString(pymod, "figure");
  120. s_python_function_fignum_exists = PyObject_GetAttrString(pymod, "fignum_exists");
  121. s_python_function_plot = PyObject_GetAttrString(pymod, "plot");
  122. s_python_function_quiver = PyObject_GetAttrString(pymod, "quiver");
  123. s_python_function_semilogx = PyObject_GetAttrString(pymod, "semilogx");
  124. s_python_function_semilogy = PyObject_GetAttrString(pymod, "semilogy");
  125. s_python_function_loglog = PyObject_GetAttrString(pymod, "loglog");
  126. s_python_function_fill_between = PyObject_GetAttrString(pymod, "fill_between");
  127. s_python_function_hist = PyObject_GetAttrString(pymod,"hist");
  128. s_python_function_scatter = PyObject_GetAttrString(pymod,"scatter");
  129. s_python_function_subplot = PyObject_GetAttrString(pymod, "subplot");
  130. s_python_function_legend = PyObject_GetAttrString(pymod, "legend");
  131. s_python_function_ylim = PyObject_GetAttrString(pymod, "ylim");
  132. s_python_function_title = PyObject_GetAttrString(pymod, "title");
  133. s_python_function_axis = PyObject_GetAttrString(pymod, "axis");
  134. s_python_function_xlabel = PyObject_GetAttrString(pymod, "xlabel");
  135. s_python_function_ylabel = PyObject_GetAttrString(pymod, "ylabel");
  136. s_python_function_xticks = PyObject_GetAttrString(pymod, "xticks");
  137. s_python_function_yticks = PyObject_GetAttrString(pymod, "yticks");
  138. s_python_function_grid = PyObject_GetAttrString(pymod, "grid");
  139. s_python_function_xlim = PyObject_GetAttrString(pymod, "xlim");
  140. s_python_function_ion = PyObject_GetAttrString(pymod, "ion");
  141. s_python_function_ginput = PyObject_GetAttrString(pymod, "ginput");
  142. s_python_function_save = PyObject_GetAttrString(pylabmod, "savefig");
  143. s_python_function_annotate = PyObject_GetAttrString(pymod,"annotate");
  144. s_python_function_clf = PyObject_GetAttrString(pymod, "clf");
  145. s_python_function_errorbar = PyObject_GetAttrString(pymod, "errorbar");
  146. s_python_function_tight_layout = PyObject_GetAttrString(pymod, "tight_layout");
  147. s_python_function_stem = PyObject_GetAttrString(pymod, "stem");
  148. s_python_function_xkcd = PyObject_GetAttrString(pymod, "xkcd");
  149. s_python_function_text = PyObject_GetAttrString(pymod, "text");
  150. s_python_function_suptitle = PyObject_GetAttrString(pymod, "suptitle");
  151. s_python_function_bar = PyObject_GetAttrString(pymod,"bar");
  152. s_python_function_subplots_adjust = PyObject_GetAttrString(pymod,"subplots_adjust");
  153. if( !s_python_function_show
  154. || !s_python_function_close
  155. || !s_python_function_draw
  156. || !s_python_function_pause
  157. || !s_python_function_figure
  158. || !s_python_function_fignum_exists
  159. || !s_python_function_plot
  160. || !s_python_function_quiver
  161. || !s_python_function_semilogx
  162. || !s_python_function_semilogy
  163. || !s_python_function_loglog
  164. || !s_python_function_fill_between
  165. || !s_python_function_subplot
  166. || !s_python_function_legend
  167. || !s_python_function_ylim
  168. || !s_python_function_title
  169. || !s_python_function_axis
  170. || !s_python_function_xlabel
  171. || !s_python_function_ylabel
  172. || !s_python_function_grid
  173. || !s_python_function_xlim
  174. || !s_python_function_ion
  175. || !s_python_function_ginput
  176. || !s_python_function_save
  177. || !s_python_function_clf
  178. || !s_python_function_annotate
  179. || !s_python_function_errorbar
  180. || !s_python_function_errorbar
  181. || !s_python_function_tight_layout
  182. || !s_python_function_stem
  183. || !s_python_function_xkcd
  184. || !s_python_function_text
  185. || !s_python_function_suptitle
  186. || !s_python_function_bar
  187. || !s_python_function_subplots_adjust
  188. ) { throw std::runtime_error("Couldn't find required function!"); }
  189. if ( !PyFunction_Check(s_python_function_show)
  190. || !PyFunction_Check(s_python_function_close)
  191. || !PyFunction_Check(s_python_function_draw)
  192. || !PyFunction_Check(s_python_function_pause)
  193. || !PyFunction_Check(s_python_function_figure)
  194. || !PyFunction_Check(s_python_function_fignum_exists)
  195. || !PyFunction_Check(s_python_function_plot)
  196. || !PyFunction_Check(s_python_function_quiver)
  197. || !PyFunction_Check(s_python_function_semilogx)
  198. || !PyFunction_Check(s_python_function_semilogy)
  199. || !PyFunction_Check(s_python_function_loglog)
  200. || !PyFunction_Check(s_python_function_fill_between)
  201. || !PyFunction_Check(s_python_function_subplot)
  202. || !PyFunction_Check(s_python_function_legend)
  203. || !PyFunction_Check(s_python_function_annotate)
  204. || !PyFunction_Check(s_python_function_ylim)
  205. || !PyFunction_Check(s_python_function_title)
  206. || !PyFunction_Check(s_python_function_axis)
  207. || !PyFunction_Check(s_python_function_xlabel)
  208. || !PyFunction_Check(s_python_function_ylabel)
  209. || !PyFunction_Check(s_python_function_grid)
  210. || !PyFunction_Check(s_python_function_xlim)
  211. || !PyFunction_Check(s_python_function_ion)
  212. || !PyFunction_Check(s_python_function_ginput)
  213. || !PyFunction_Check(s_python_function_save)
  214. || !PyFunction_Check(s_python_function_clf)
  215. || !PyFunction_Check(s_python_function_tight_layout)
  216. || !PyFunction_Check(s_python_function_errorbar)
  217. || !PyFunction_Check(s_python_function_stem)
  218. || !PyFunction_Check(s_python_function_xkcd)
  219. || !PyFunction_Check(s_python_function_text)
  220. || !PyFunction_Check(s_python_function_suptitle)
  221. || !PyFunction_Check(s_python_function_bar)
  222. || !PyFunction_Check(s_python_function_subplots_adjust)
  223. ) { throw std::runtime_error("Python object is unexpectedly not a PyFunction."); }
  224. s_python_empty_tuple = PyTuple_New(0);
  225. }
  226. ~_interpreter() {
  227. Py_Finalize();
  228. }
  229. };
  230. } // end namespace detail
  231. // must be called before the first regular call to matplotlib to have any effect
  232. inline void backend(const std::string& name)
  233. {
  234. detail::s_backend = name;
  235. }
  236. inline bool annotate(std::string annotation, double x, double y)
  237. {
  238. PyObject * xy = PyTuple_New(2);
  239. PyObject * str = PyString_FromString(annotation.c_str());
  240. PyTuple_SetItem(xy,0,PyFloat_FromDouble(x));
  241. PyTuple_SetItem(xy,1,PyFloat_FromDouble(y));
  242. PyObject* kwargs = PyDict_New();
  243. PyDict_SetItemString(kwargs, "xy", xy);
  244. PyObject* args = PyTuple_New(1);
  245. PyTuple_SetItem(args, 0, str);
  246. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs);
  247. Py_DECREF(args);
  248. Py_DECREF(kwargs);
  249. if(res) Py_DECREF(res);
  250. return res;
  251. }
  252. #ifndef WITHOUT_NUMPY
  253. // Type selector for numpy array conversion
  254. template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default
  255. template <> struct select_npy_type<double> { const static NPY_TYPES type = NPY_DOUBLE; };
  256. template <> struct select_npy_type<float> { const static NPY_TYPES type = NPY_FLOAT; };
  257. template <> struct select_npy_type<bool> { const static NPY_TYPES type = NPY_BOOL; };
  258. template <> struct select_npy_type<int8_t> { const static NPY_TYPES type = NPY_INT8; };
  259. template <> struct select_npy_type<int16_t> { const static NPY_TYPES type = NPY_SHORT; };
  260. template <> struct select_npy_type<int32_t> { const static NPY_TYPES type = NPY_INT; };
  261. template <> struct select_npy_type<int64_t> { const static NPY_TYPES type = NPY_INT64; };
  262. template <> struct select_npy_type<uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
  263. template <> struct select_npy_type<uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
  264. template <> struct select_npy_type<uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
  265. template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY_UINT64; };
  266. template<typename Numeric>
  267. PyObject* get_array(const std::vector<Numeric>& v)
  268. {
  269. detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
  270. NPY_TYPES type = select_npy_type<Numeric>::type;
  271. if (type == NPY_NOTYPE)
  272. {
  273. std::vector<double> vd(v.size());
  274. npy_intp vsize = v.size();
  275. std::copy(v.begin(),v.end(),vd.begin());
  276. PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data()));
  277. return varray;
  278. }
  279. npy_intp vsize = v.size();
  280. PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));
  281. return varray;
  282. }
  283. #else // fallback if we don't have numpy: copy every element of the given vector
  284. template<typename Numeric>
  285. PyObject* get_array(const std::vector<Numeric>& v)
  286. {
  287. PyObject* list = PyList_New(v.size());
  288. for(size_t i = 0; i < v.size(); ++i) {
  289. PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
  290. }
  291. return list;
  292. }
  293. #endif // WITHOUT_NUMPY
  294. template<typename Numeric>
  295. bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
  296. {
  297. assert(x.size() == y.size());
  298. // using numpy arrays
  299. PyObject* xarray = get_array(x);
  300. PyObject* yarray = get_array(y);
  301. // construct positional args
  302. PyObject* args = PyTuple_New(2);
  303. PyTuple_SetItem(args, 0, xarray);
  304. PyTuple_SetItem(args, 1, yarray);
  305. // construct keyword args
  306. PyObject* kwargs = PyDict_New();
  307. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  308. {
  309. PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
  310. }
  311. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs);
  312. Py_DECREF(args);
  313. Py_DECREF(kwargs);
  314. if(res) Py_DECREF(res);
  315. return res;
  316. }
  317. template<typename Numeric>
  318. bool stem(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
  319. {
  320. assert(x.size() == y.size());
  321. // using numpy arrays
  322. PyObject* xarray = get_array(x);
  323. PyObject* yarray = get_array(y);
  324. // construct positional args
  325. PyObject* args = PyTuple_New(2);
  326. PyTuple_SetItem(args, 0, xarray);
  327. PyTuple_SetItem(args, 1, yarray);
  328. // construct keyword args
  329. PyObject* kwargs = PyDict_New();
  330. for (std::map<std::string, std::string>::const_iterator it =
  331. keywords.begin(); it != keywords.end(); ++it) {
  332. PyDict_SetItemString(kwargs, it->first.c_str(),
  333. PyString_FromString(it->second.c_str()));
  334. }
  335. PyObject* res = PyObject_Call(
  336. detail::_interpreter::get().s_python_function_stem, args, kwargs);
  337. Py_DECREF(args);
  338. Py_DECREF(kwargs);
  339. if (res)
  340. Py_DECREF(res);
  341. return res;
  342. }
  343. template< typename Numeric >
  344. bool fill_between(const std::vector<Numeric>& x, const std::vector<Numeric>& y1, const std::vector<Numeric>& y2, const std::map<std::string, std::string>& keywords)
  345. {
  346. assert(x.size() == y1.size());
  347. assert(x.size() == y2.size());
  348. // using numpy arrays
  349. PyObject* xarray = get_array(x);
  350. PyObject* y1array = get_array(y1);
  351. PyObject* y2array = get_array(y2);
  352. // construct positional args
  353. PyObject* args = PyTuple_New(3);
  354. PyTuple_SetItem(args, 0, xarray);
  355. PyTuple_SetItem(args, 1, y1array);
  356. PyTuple_SetItem(args, 2, y2array);
  357. // construct keyword args
  358. PyObject* kwargs = PyDict_New();
  359. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  360. {
  361. PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
  362. }
  363. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill_between, args, kwargs);
  364. Py_DECREF(args);
  365. Py_DECREF(kwargs);
  366. if(res) Py_DECREF(res);
  367. return res;
  368. }
  369. template< typename Numeric>
  370. bool hist(const std::vector<Numeric>& y, long bins=10,std::string color="b", double alpha=1.0)
  371. {
  372. PyObject* yarray = get_array(y);
  373. PyObject* kwargs = PyDict_New();
  374. PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
  375. PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
  376. PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
  377. PyObject* plot_args = PyTuple_New(1);
  378. PyTuple_SetItem(plot_args, 0, yarray);
  379. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
  380. Py_DECREF(plot_args);
  381. Py_DECREF(kwargs);
  382. if(res) Py_DECREF(res);
  383. return res;
  384. }
  385. template<typename NumericX, typename NumericY>
  386. bool scatter(const std::vector<NumericX>& x,
  387. const std::vector<NumericY>& y,
  388. const double s=1.0) // The marker size in points**2
  389. {
  390. assert(x.size() == y.size());
  391. PyObject* xarray = get_array(x);
  392. PyObject* yarray = get_array(y);
  393. PyObject* kwargs = PyDict_New();
  394. PyDict_SetItemString(kwargs, "s", PyLong_FromLong(s));
  395. PyObject* plot_args = PyTuple_New(2);
  396. PyTuple_SetItem(plot_args, 0, xarray);
  397. PyTuple_SetItem(plot_args, 1, yarray);
  398. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
  399. Py_DECREF(plot_args);
  400. Py_DECREF(kwargs);
  401. if(res) Py_DECREF(res);
  402. return res;
  403. }
  404. template< typename Numeric>
  405. bool bar(const std::vector<Numeric>& y, std::string ec = "black", std::string ls = "-", double lw = 1.0,
  406. const std::map<std::string, std::string>& keywords = {})
  407. {
  408. PyObject* yarray = get_array(y);
  409. std::vector<int> x;
  410. for (int i = 0; i < y.size(); i++)
  411. x.push_back(i);
  412. PyObject* xarray = get_array(x);
  413. PyObject* kwargs = PyDict_New();
  414. PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str()));
  415. PyDict_SetItemString(kwargs, "ls", PyString_FromString(ls.c_str()));
  416. PyDict_SetItemString(kwargs, "lw", PyFloat_FromDouble(lw));
  417. PyObject* plot_args = PyTuple_New(2);
  418. PyTuple_SetItem(plot_args, 0, xarray);
  419. PyTuple_SetItem(plot_args, 1, yarray);
  420. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_bar, plot_args, kwargs);
  421. Py_DECREF(plot_args);
  422. Py_DECREF(kwargs);
  423. if(res) Py_DECREF(res);
  424. return res;
  425. }
  426. inline bool subplots_adjust(const std::map<std::string, double>& keywords = {})
  427. {
  428. PyObject* kwargs = PyDict_New();
  429. for (std::map<std::string, double>::const_iterator it =
  430. keywords.begin(); it != keywords.end(); ++it) {
  431. PyDict_SetItemString(kwargs, it->first.c_str(),
  432. PyFloat_FromDouble(it->second));
  433. }
  434. PyObject* plot_args = PyTuple_New(0);
  435. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_subplots_adjust, plot_args, kwargs);
  436. Py_DECREF(plot_args);
  437. Py_DECREF(kwargs);
  438. if(res) Py_DECREF(res);
  439. return res;
  440. }
  441. template< typename Numeric>
  442. bool named_hist(std::string label,const std::vector<Numeric>& y, long bins=10, std::string color="b", double alpha=1.0)
  443. {
  444. PyObject* yarray = get_array(y);
  445. PyObject* kwargs = PyDict_New();
  446. PyDict_SetItemString(kwargs, "label", PyString_FromString(label.c_str()));
  447. PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
  448. PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
  449. PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
  450. PyObject* plot_args = PyTuple_New(1);
  451. PyTuple_SetItem(plot_args, 0, yarray);
  452. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
  453. Py_DECREF(plot_args);
  454. Py_DECREF(kwargs);
  455. if(res) Py_DECREF(res);
  456. return res;
  457. }
  458. template<typename NumericX, typename NumericY>
  459. bool plot(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
  460. {
  461. assert(x.size() == y.size());
  462. PyObject* xarray = get_array(x);
  463. PyObject* yarray = get_array(y);
  464. PyObject* pystring = PyString_FromString(s.c_str());
  465. PyObject* plot_args = PyTuple_New(3);
  466. PyTuple_SetItem(plot_args, 0, xarray);
  467. PyTuple_SetItem(plot_args, 1, yarray);
  468. PyTuple_SetItem(plot_args, 2, pystring);
  469. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
  470. Py_DECREF(plot_args);
  471. if(res) Py_DECREF(res);
  472. return res;
  473. }
  474. template<typename NumericX, typename NumericY, typename NumericU, typename NumericW>
  475. bool quiver(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::vector<NumericU>& u, const std::vector<NumericW>& w, const std::map<std::string, std::string>& keywords = {})
  476. {
  477. assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size());
  478. PyObject* xarray = get_array(x);
  479. PyObject* yarray = get_array(y);
  480. PyObject* uarray = get_array(u);
  481. PyObject* warray = get_array(w);
  482. PyObject* plot_args = PyTuple_New(4);
  483. PyTuple_SetItem(plot_args, 0, xarray);
  484. PyTuple_SetItem(plot_args, 1, yarray);
  485. PyTuple_SetItem(plot_args, 2, uarray);
  486. PyTuple_SetItem(plot_args, 3, warray);
  487. // construct keyword args
  488. PyObject* kwargs = PyDict_New();
  489. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  490. {
  491. PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
  492. }
  493. PyObject* res = PyObject_Call(
  494. detail::_interpreter::get().s_python_function_quiver, plot_args, kwargs);
  495. Py_DECREF(kwargs);
  496. Py_DECREF(plot_args);
  497. if (res)
  498. Py_DECREF(res);
  499. return res;
  500. }
  501. template<typename NumericX, typename NumericY>
  502. bool stem(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
  503. {
  504. assert(x.size() == y.size());
  505. PyObject* xarray = get_array(x);
  506. PyObject* yarray = get_array(y);
  507. PyObject* pystring = PyString_FromString(s.c_str());
  508. PyObject* plot_args = PyTuple_New(3);
  509. PyTuple_SetItem(plot_args, 0, xarray);
  510. PyTuple_SetItem(plot_args, 1, yarray);
  511. PyTuple_SetItem(plot_args, 2, pystring);
  512. PyObject* res = PyObject_CallObject(
  513. detail::_interpreter::get().s_python_function_stem, plot_args);
  514. Py_DECREF(plot_args);
  515. if (res)
  516. Py_DECREF(res);
  517. return res;
  518. }
  519. template<typename NumericX, typename NumericY>
  520. bool semilogx(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
  521. {
  522. assert(x.size() == y.size());
  523. PyObject* xarray = get_array(x);
  524. PyObject* yarray = get_array(y);
  525. PyObject* pystring = PyString_FromString(s.c_str());
  526. PyObject* plot_args = PyTuple_New(3);
  527. PyTuple_SetItem(plot_args, 0, xarray);
  528. PyTuple_SetItem(plot_args, 1, yarray);
  529. PyTuple_SetItem(plot_args, 2, pystring);
  530. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogx, plot_args);
  531. Py_DECREF(plot_args);
  532. if(res) Py_DECREF(res);
  533. return res;
  534. }
  535. template<typename NumericX, typename NumericY>
  536. bool semilogy(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
  537. {
  538. assert(x.size() == y.size());
  539. PyObject* xarray = get_array(x);
  540. PyObject* yarray = get_array(y);
  541. PyObject* pystring = PyString_FromString(s.c_str());
  542. PyObject* plot_args = PyTuple_New(3);
  543. PyTuple_SetItem(plot_args, 0, xarray);
  544. PyTuple_SetItem(plot_args, 1, yarray);
  545. PyTuple_SetItem(plot_args, 2, pystring);
  546. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogy, plot_args);
  547. Py_DECREF(plot_args);
  548. if(res) Py_DECREF(res);
  549. return res;
  550. }
  551. template<typename NumericX, typename NumericY>
  552. bool loglog(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
  553. {
  554. assert(x.size() == y.size());
  555. PyObject* xarray = get_array(x);
  556. PyObject* yarray = get_array(y);
  557. PyObject* pystring = PyString_FromString(s.c_str());
  558. PyObject* plot_args = PyTuple_New(3);
  559. PyTuple_SetItem(plot_args, 0, xarray);
  560. PyTuple_SetItem(plot_args, 1, yarray);
  561. PyTuple_SetItem(plot_args, 2, pystring);
  562. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_loglog, plot_args);
  563. Py_DECREF(plot_args);
  564. if(res) Py_DECREF(res);
  565. return res;
  566. }
  567. template<typename NumericX, typename NumericY>
  568. bool errorbar(const std::vector<NumericX> &x, const std::vector<NumericY> &y, const std::vector<NumericX> &yerr, const std::map<std::string, std::string> &keywords = {})
  569. {
  570. assert(x.size() == y.size());
  571. PyObject* xarray = get_array(x);
  572. PyObject* yarray = get_array(y);
  573. PyObject* yerrarray = get_array(yerr);
  574. // construct keyword args
  575. PyObject* kwargs = PyDict_New();
  576. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  577. {
  578. PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
  579. }
  580. PyDict_SetItemString(kwargs, "yerr", yerrarray);
  581. PyObject *plot_args = PyTuple_New(2);
  582. PyTuple_SetItem(plot_args, 0, xarray);
  583. PyTuple_SetItem(plot_args, 1, yarray);
  584. PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_errorbar, plot_args, kwargs);
  585. Py_DECREF(kwargs);
  586. Py_DECREF(plot_args);
  587. if (res)
  588. Py_DECREF(res);
  589. else
  590. throw std::runtime_error("Call to errorbar() failed.");
  591. return res;
  592. }
  593. template<typename Numeric>
  594. bool named_plot(const std::string& name, const std::vector<Numeric>& y, const std::string& format = "")
  595. {
  596. PyObject* kwargs = PyDict_New();
  597. PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
  598. PyObject* yarray = get_array(y);
  599. PyObject* pystring = PyString_FromString(format.c_str());
  600. PyObject* plot_args = PyTuple_New(2);
  601. PyTuple_SetItem(plot_args, 0, yarray);
  602. PyTuple_SetItem(plot_args, 1, pystring);
  603. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
  604. Py_DECREF(kwargs);
  605. Py_DECREF(plot_args);
  606. if (res) Py_DECREF(res);
  607. return res;
  608. }
  609. template<typename Numeric>
  610. bool named_plot(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
  611. {
  612. PyObject* kwargs = PyDict_New();
  613. PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
  614. PyObject* xarray = get_array(x);
  615. PyObject* yarray = get_array(y);
  616. PyObject* pystring = PyString_FromString(format.c_str());
  617. PyObject* plot_args = PyTuple_New(3);
  618. PyTuple_SetItem(plot_args, 0, xarray);
  619. PyTuple_SetItem(plot_args, 1, yarray);
  620. PyTuple_SetItem(plot_args, 2, pystring);
  621. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
  622. Py_DECREF(kwargs);
  623. Py_DECREF(plot_args);
  624. if (res) Py_DECREF(res);
  625. return res;
  626. }
  627. template<typename Numeric>
  628. bool named_semilogx(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
  629. {
  630. PyObject* kwargs = PyDict_New();
  631. PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
  632. PyObject* xarray = get_array(x);
  633. PyObject* yarray = get_array(y);
  634. PyObject* pystring = PyString_FromString(format.c_str());
  635. PyObject* plot_args = PyTuple_New(3);
  636. PyTuple_SetItem(plot_args, 0, xarray);
  637. PyTuple_SetItem(plot_args, 1, yarray);
  638. PyTuple_SetItem(plot_args, 2, pystring);
  639. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogx, plot_args, kwargs);
  640. Py_DECREF(kwargs);
  641. Py_DECREF(plot_args);
  642. if (res) Py_DECREF(res);
  643. return res;
  644. }
  645. template<typename Numeric>
  646. bool named_semilogy(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
  647. {
  648. PyObject* kwargs = PyDict_New();
  649. PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
  650. PyObject* xarray = get_array(x);
  651. PyObject* yarray = get_array(y);
  652. PyObject* pystring = PyString_FromString(format.c_str());
  653. PyObject* plot_args = PyTuple_New(3);
  654. PyTuple_SetItem(plot_args, 0, xarray);
  655. PyTuple_SetItem(plot_args, 1, yarray);
  656. PyTuple_SetItem(plot_args, 2, pystring);
  657. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogy, plot_args, kwargs);
  658. Py_DECREF(kwargs);
  659. Py_DECREF(plot_args);
  660. if (res) Py_DECREF(res);
  661. return res;
  662. }
  663. template<typename Numeric>
  664. bool named_loglog(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
  665. {
  666. PyObject* kwargs = PyDict_New();
  667. PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
  668. PyObject* xarray = get_array(x);
  669. PyObject* yarray = get_array(y);
  670. PyObject* pystring = PyString_FromString(format.c_str());
  671. PyObject* plot_args = PyTuple_New(3);
  672. PyTuple_SetItem(plot_args, 0, xarray);
  673. PyTuple_SetItem(plot_args, 1, yarray);
  674. PyTuple_SetItem(plot_args, 2, pystring);
  675. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs);
  676. Py_DECREF(kwargs);
  677. Py_DECREF(plot_args);
  678. if (res) Py_DECREF(res);
  679. return res;
  680. }
  681. template<typename Numeric>
  682. bool plot(const std::vector<Numeric>& y, const std::string& format = "")
  683. {
  684. std::vector<Numeric> x(y.size());
  685. for(size_t i=0; i<x.size(); ++i) x.at(i) = i;
  686. return plot(x,y,format);
  687. }
  688. template<typename Numeric>
  689. bool stem(const std::vector<Numeric>& y, const std::string& format = "")
  690. {
  691. std::vector<Numeric> x(y.size());
  692. for (size_t i = 0; i < x.size(); ++i) x.at(i) = i;
  693. return stem(x, y, format);
  694. }
  695. template<typename Numeric>
  696. void text(Numeric x, Numeric y, const std::string& s = "")
  697. {
  698. PyObject* args = PyTuple_New(3);
  699. PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
  700. PyTuple_SetItem(args, 1, PyFloat_FromDouble(y));
  701. PyTuple_SetItem(args, 2, PyString_FromString(s.c_str()));
  702. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_text, args);
  703. if(!res) throw std::runtime_error("Call to text() failed.");
  704. Py_DECREF(args);
  705. Py_DECREF(res);
  706. }
  707. inline long figure(long number = -1)
  708. {
  709. PyObject *res;
  710. if (number == -1)
  711. res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, detail::_interpreter::get().s_python_empty_tuple);
  712. else {
  713. assert(number > 0);
  714. // Make sure interpreter is initialised
  715. detail::_interpreter::get();
  716. PyObject *args = PyTuple_New(1);
  717. PyTuple_SetItem(args, 0, PyLong_FromLong(number));
  718. res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, args);
  719. Py_DECREF(args);
  720. }
  721. if(!res) throw std::runtime_error("Call to figure() failed.");
  722. PyObject* num = PyObject_GetAttrString(res, "number");
  723. if (!num) throw std::runtime_error("Could not get number attribute of figure object");
  724. const long figureNumber = PyLong_AsLong(num);
  725. Py_DECREF(num);
  726. Py_DECREF(res);
  727. return figureNumber;
  728. }
  729. inline bool fignum_exists(long number)
  730. {
  731. // Make sure interpreter is initialised
  732. detail::_interpreter::get();
  733. PyObject *args = PyTuple_New(1);
  734. PyTuple_SetItem(args, 0, PyLong_FromLong(number));
  735. PyObject *res = PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, args);
  736. if(!res) throw std::runtime_error("Call to fignum_exists() failed.");
  737. bool ret = PyObject_IsTrue(res);
  738. Py_DECREF(res);
  739. Py_DECREF(args);
  740. return ret;
  741. }
  742. inline void figure_size(size_t w, size_t h)
  743. {
  744. const size_t dpi = 100;
  745. PyObject* size = PyTuple_New(2);
  746. PyTuple_SetItem(size, 0, PyFloat_FromDouble((double)w / dpi));
  747. PyTuple_SetItem(size, 1, PyFloat_FromDouble((double)h / dpi));
  748. PyObject* kwargs = PyDict_New();
  749. PyDict_SetItemString(kwargs, "figsize", size);
  750. PyDict_SetItemString(kwargs, "dpi", PyLong_FromSize_t(dpi));
  751. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_figure,
  752. detail::_interpreter::get().s_python_empty_tuple, kwargs);
  753. Py_DECREF(kwargs);
  754. if(!res) throw std::runtime_error("Call to figure_size() failed.");
  755. Py_DECREF(res);
  756. }
  757. inline void legend()
  758. {
  759. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple);
  760. if(!res) throw std::runtime_error("Call to legend() failed.");
  761. Py_DECREF(res);
  762. }
  763. template<typename Numeric>
  764. void ylim(Numeric left, Numeric right)
  765. {
  766. PyObject* list = PyList_New(2);
  767. PyList_SetItem(list, 0, PyFloat_FromDouble(left));
  768. PyList_SetItem(list, 1, PyFloat_FromDouble(right));
  769. PyObject* args = PyTuple_New(1);
  770. PyTuple_SetItem(args, 0, list);
  771. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
  772. if(!res) throw std::runtime_error("Call to ylim() failed.");
  773. Py_DECREF(args);
  774. Py_DECREF(res);
  775. }
  776. template<typename Numeric>
  777. void xlim(Numeric left, Numeric right)
  778. {
  779. PyObject* list = PyList_New(2);
  780. PyList_SetItem(list, 0, PyFloat_FromDouble(left));
  781. PyList_SetItem(list, 1, PyFloat_FromDouble(right));
  782. PyObject* args = PyTuple_New(1);
  783. PyTuple_SetItem(args, 0, list);
  784. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
  785. if(!res) throw std::runtime_error("Call to xlim() failed.");
  786. Py_DECREF(args);
  787. Py_DECREF(res);
  788. }
  789. inline double* xlim()
  790. {
  791. PyObject* args = PyTuple_New(0);
  792. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
  793. PyObject* left = PyTuple_GetItem(res,0);
  794. PyObject* right = PyTuple_GetItem(res,1);
  795. double* arr = new double[2];
  796. arr[0] = PyFloat_AsDouble(left);
  797. arr[1] = PyFloat_AsDouble(right);
  798. if(!res) throw std::runtime_error("Call to xlim() failed.");
  799. Py_DECREF(res);
  800. return arr;
  801. }
  802. inline double* ylim()
  803. {
  804. PyObject* args = PyTuple_New(0);
  805. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
  806. PyObject* left = PyTuple_GetItem(res,0);
  807. PyObject* right = PyTuple_GetItem(res,1);
  808. double* arr = new double[2];
  809. arr[0] = PyFloat_AsDouble(left);
  810. arr[1] = PyFloat_AsDouble(right);
  811. if(!res) throw std::runtime_error("Call to ylim() failed.");
  812. Py_DECREF(res);
  813. return arr;
  814. }
  815. template<typename Numeric>
  816. inline void xticks(const std::vector<Numeric> &ticks, const std::vector<std::string> &labels = {}, const std::map<std::string, std::string>& keywords = {})
  817. {
  818. assert(labels.size() == 0 || ticks.size() == labels.size());
  819. // using numpy array
  820. PyObject* ticksarray = get_array(ticks);
  821. PyObject* args;
  822. if(labels.size() == 0) {
  823. // construct positional args
  824. args = PyTuple_New(1);
  825. PyTuple_SetItem(args, 0, ticksarray);
  826. } else {
  827. // make tuple of tick labels
  828. PyObject* labelstuple = PyTuple_New(labels.size());
  829. for (size_t i = 0; i < labels.size(); i++)
  830. PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
  831. // construct positional args
  832. args = PyTuple_New(2);
  833. PyTuple_SetItem(args, 0, ticksarray);
  834. PyTuple_SetItem(args, 1, labelstuple);
  835. }
  836. // construct keyword args
  837. PyObject* kwargs = PyDict_New();
  838. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  839. {
  840. PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
  841. }
  842. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xticks, args, kwargs);
  843. Py_DECREF(args);
  844. Py_DECREF(kwargs);
  845. if(!res) throw std::runtime_error("Call to xticks() failed");
  846. Py_DECREF(res);
  847. }
  848. template<typename Numeric>
  849. inline void xticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
  850. {
  851. xticks(ticks, {}, keywords);
  852. }
  853. template<typename Numeric>
  854. inline void yticks(const std::vector<Numeric> &ticks, const std::vector<std::string> &labels = {}, const std::map<std::string, std::string>& keywords = {})
  855. {
  856. assert(labels.size() == 0 || ticks.size() == labels.size());
  857. // using numpy array
  858. PyObject* ticksarray = get_array(ticks);
  859. PyObject* args;
  860. if(labels.size() == 0) {
  861. // construct positional args
  862. args = PyTuple_New(1);
  863. PyTuple_SetItem(args, 0, ticksarray);
  864. } else {
  865. // make tuple of tick labels
  866. PyObject* labelstuple = PyTuple_New(labels.size());
  867. for (size_t i = 0; i < labels.size(); i++)
  868. PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
  869. // construct positional args
  870. args = PyTuple_New(2);
  871. PyTuple_SetItem(args, 0, ticksarray);
  872. PyTuple_SetItem(args, 1, labelstuple);
  873. }
  874. // construct keyword args
  875. PyObject* kwargs = PyDict_New();
  876. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  877. {
  878. PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
  879. }
  880. PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_yticks, args, kwargs);
  881. Py_DECREF(args);
  882. Py_DECREF(kwargs);
  883. if(!res) throw std::runtime_error("Call to yticks() failed");
  884. Py_DECREF(res);
  885. }
  886. template<typename Numeric>
  887. inline void yticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
  888. {
  889. yticks(ticks, {}, keywords);
  890. }
  891. inline void subplot(long nrows, long ncols, long plot_number)
  892. {
  893. // construct positional args
  894. PyObject* args = PyTuple_New(3);
  895. PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
  896. PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
  897. PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
  898. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args);
  899. if(!res) throw std::runtime_error("Call to subplot() failed.");
  900. Py_DECREF(args);
  901. Py_DECREF(res);
  902. }
  903. inline void title(const std::string &titlestr)
  904. {
  905. PyObject* pytitlestr = PyString_FromString(titlestr.c_str());
  906. PyObject* args = PyTuple_New(1);
  907. PyTuple_SetItem(args, 0, pytitlestr);
  908. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_title, args);
  909. if(!res) throw std::runtime_error("Call to title() failed.");
  910. Py_DECREF(args);
  911. Py_DECREF(res);
  912. }
  913. inline void suptitle(const std::string &suptitlestr)
  914. {
  915. PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str());
  916. PyObject* args = PyTuple_New(1);
  917. PyTuple_SetItem(args, 0, pysuptitlestr);
  918. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_suptitle, args);
  919. if(!res) throw std::runtime_error("Call to suptitle() failed.");
  920. Py_DECREF(args);
  921. Py_DECREF(res);
  922. }
  923. inline void axis(const std::string &axisstr)
  924. {
  925. PyObject* str = PyString_FromString(axisstr.c_str());
  926. PyObject* args = PyTuple_New(1);
  927. PyTuple_SetItem(args, 0, str);
  928. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_axis, args);
  929. if(!res) throw std::runtime_error("Call to title() failed.");
  930. Py_DECREF(args);
  931. Py_DECREF(res);
  932. }
  933. inline void xlabel(const std::string &str)
  934. {
  935. PyObject* pystr = PyString_FromString(str.c_str());
  936. PyObject* args = PyTuple_New(1);
  937. PyTuple_SetItem(args, 0, pystr);
  938. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlabel, args);
  939. if(!res) throw std::runtime_error("Call to xlabel() failed.");
  940. Py_DECREF(args);
  941. Py_DECREF(res);
  942. }
  943. inline void ylabel(const std::string &str)
  944. {
  945. PyObject* pystr = PyString_FromString(str.c_str());
  946. PyObject* args = PyTuple_New(1);
  947. PyTuple_SetItem(args, 0, pystr);
  948. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylabel, args);
  949. if(!res) throw std::runtime_error("Call to ylabel() failed.");
  950. Py_DECREF(args);
  951. Py_DECREF(res);
  952. }
  953. inline void grid(bool flag)
  954. {
  955. PyObject* pyflag = flag ? Py_True : Py_False;
  956. Py_INCREF(pyflag);
  957. PyObject* args = PyTuple_New(1);
  958. PyTuple_SetItem(args, 0, pyflag);
  959. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_grid, args);
  960. if(!res) throw std::runtime_error("Call to grid() failed.");
  961. Py_DECREF(args);
  962. Py_DECREF(res);
  963. }
  964. inline void show(const bool block = true)
  965. {
  966. PyObject* res;
  967. if(block)
  968. {
  969. res = PyObject_CallObject(
  970. detail::_interpreter::get().s_python_function_show,
  971. detail::_interpreter::get().s_python_empty_tuple);
  972. }
  973. else
  974. {
  975. PyObject *kwargs = PyDict_New();
  976. PyDict_SetItemString(kwargs, "block", Py_False);
  977. res = PyObject_Call( detail::_interpreter::get().s_python_function_show, detail::_interpreter::get().s_python_empty_tuple, kwargs);
  978. Py_DECREF(kwargs);
  979. }
  980. if (!res) throw std::runtime_error("Call to show() failed.");
  981. Py_DECREF(res);
  982. }
  983. inline void close()
  984. {
  985. PyObject* res = PyObject_CallObject(
  986. detail::_interpreter::get().s_python_function_close,
  987. detail::_interpreter::get().s_python_empty_tuple);
  988. if (!res) throw std::runtime_error("Call to close() failed.");
  989. Py_DECREF(res);
  990. }
  991. inline void xkcd() {
  992. PyObject* res;
  993. PyObject *kwargs = PyDict_New();
  994. res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd,
  995. detail::_interpreter::get().s_python_empty_tuple, kwargs);
  996. Py_DECREF(kwargs);
  997. if (!res)
  998. throw std::runtime_error("Call to show() failed.");
  999. Py_DECREF(res);
  1000. }
  1001. inline void draw()
  1002. {
  1003. PyObject* res = PyObject_CallObject(
  1004. detail::_interpreter::get().s_python_function_draw,
  1005. detail::_interpreter::get().s_python_empty_tuple);
  1006. if (!res) throw std::runtime_error("Call to draw() failed.");
  1007. Py_DECREF(res);
  1008. }
  1009. template<typename Numeric>
  1010. inline void pause(Numeric interval)
  1011. {
  1012. PyObject* args = PyTuple_New(1);
  1013. PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
  1014. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_pause, args);
  1015. if(!res) throw std::runtime_error("Call to pause() failed.");
  1016. Py_DECREF(args);
  1017. Py_DECREF(res);
  1018. }
  1019. inline void save(const std::string& filename)
  1020. {
  1021. PyObject* pyfilename = PyString_FromString(filename.c_str());
  1022. PyObject* args = PyTuple_New(1);
  1023. PyTuple_SetItem(args, 0, pyfilename);
  1024. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_save, args);
  1025. if (!res) throw std::runtime_error("Call to save() failed.");
  1026. Py_DECREF(args);
  1027. Py_DECREF(res);
  1028. }
  1029. inline void clf() {
  1030. PyObject *res = PyObject_CallObject(
  1031. detail::_interpreter::get().s_python_function_clf,
  1032. detail::_interpreter::get().s_python_empty_tuple);
  1033. if (!res) throw std::runtime_error("Call to clf() failed.");
  1034. Py_DECREF(res);
  1035. }
  1036. inline void ion() {
  1037. PyObject *res = PyObject_CallObject(
  1038. detail::_interpreter::get().s_python_function_ion,
  1039. detail::_interpreter::get().s_python_empty_tuple);
  1040. if (!res) throw std::runtime_error("Call to ion() failed.");
  1041. Py_DECREF(res);
  1042. }
  1043. inline std::vector<std::array<double, 2>> ginput(const int numClicks = 1, const std::map<std::string, std::string>& keywords = {})
  1044. {
  1045. PyObject *args = PyTuple_New(1);
  1046. PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
  1047. // construct keyword args
  1048. PyObject* kwargs = PyDict_New();
  1049. for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
  1050. {
  1051. PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
  1052. }
  1053. PyObject* res = PyObject_Call(
  1054. detail::_interpreter::get().s_python_function_ginput, args, kwargs);
  1055. Py_DECREF(kwargs);
  1056. Py_DECREF(args);
  1057. if (!res) throw std::runtime_error("Call to ginput() failed.");
  1058. const size_t len = PyList_Size(res);
  1059. std::vector<std::array<double, 2>> out;
  1060. out.reserve(len);
  1061. for (size_t i = 0; i < len; i++) {
  1062. PyObject *current = PyList_GetItem(res, i);
  1063. std::array<double, 2> position;
  1064. position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
  1065. position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
  1066. out.push_back(position);
  1067. }
  1068. Py_DECREF(res);
  1069. return out;
  1070. }
  1071. // Actually, is there any reason not to call this automatically for every plot?
  1072. inline void tight_layout() {
  1073. PyObject *res = PyObject_CallObject(
  1074. detail::_interpreter::get().s_python_function_tight_layout,
  1075. detail::_interpreter::get().s_python_empty_tuple);
  1076. if (!res) throw std::runtime_error("Call to tight_layout() failed.");
  1077. Py_DECREF(res);
  1078. }
  1079. // Support for variadic plot() and initializer lists:
  1080. namespace detail {
  1081. template<typename T>
  1082. using is_function = typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type;
  1083. template<bool obj, typename T>
  1084. struct is_callable_impl;
  1085. template<typename T>
  1086. struct is_callable_impl<false, T>
  1087. {
  1088. typedef is_function<T> type;
  1089. }; // a non-object is callable iff it is a function
  1090. template<typename T>
  1091. struct is_callable_impl<true, T>
  1092. {
  1093. struct Fallback { void operator()(); };
  1094. struct Derived : T, Fallback { };
  1095. template<typename U, U> struct Check;
  1096. template<typename U>
  1097. static std::true_type test( ... ); // use a variadic function to make sure (1) it accepts everything and (2) its always the worst match
  1098. template<typename U>
  1099. static std::false_type test( Check<void(Fallback::*)(), &U::operator()>* );
  1100. public:
  1101. typedef decltype(test<Derived>(nullptr)) type;
  1102. typedef decltype(&Fallback::operator()) dtype;
  1103. static constexpr bool value = type::value;
  1104. }; // an object is callable iff it defines operator()
  1105. template<typename T>
  1106. struct is_callable
  1107. {
  1108. // dispatch to is_callable_impl<true, T> or is_callable_impl<false, T> depending on whether T is of class type or not
  1109. typedef typename is_callable_impl<std::is_class<T>::value, T>::type type;
  1110. };
  1111. template<typename IsYDataCallable>
  1112. struct plot_impl { };
  1113. template<>
  1114. struct plot_impl<std::false_type>
  1115. {
  1116. template<typename IterableX, typename IterableY>
  1117. bool operator()(const IterableX& x, const IterableY& y, const std::string& format)
  1118. {
  1119. // 2-phase lookup for distance, begin, end
  1120. using std::distance;
  1121. using std::begin;
  1122. using std::end;
  1123. auto xs = distance(begin(x), end(x));
  1124. auto ys = distance(begin(y), end(y));
  1125. assert(xs == ys && "x and y data must have the same number of elements!");
  1126. PyObject* xlist = PyList_New(xs);
  1127. PyObject* ylist = PyList_New(ys);
  1128. PyObject* pystring = PyString_FromString(format.c_str());
  1129. auto itx = begin(x), ity = begin(y);
  1130. for(size_t i = 0; i < xs; ++i) {
  1131. PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++));
  1132. PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++));
  1133. }
  1134. PyObject* plot_args = PyTuple_New(3);
  1135. PyTuple_SetItem(plot_args, 0, xlist);
  1136. PyTuple_SetItem(plot_args, 1, ylist);
  1137. PyTuple_SetItem(plot_args, 2, pystring);
  1138. PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
  1139. Py_DECREF(plot_args);
  1140. if(res) Py_DECREF(res);
  1141. return res;
  1142. }
  1143. };
  1144. template<>
  1145. struct plot_impl<std::true_type>
  1146. {
  1147. template<typename Iterable, typename Callable>
  1148. bool operator()(const Iterable& ticks, const Callable& f, const std::string& format)
  1149. {
  1150. if(begin(ticks) == end(ticks)) return true;
  1151. // We could use additional meta-programming to deduce the correct element type of y,
  1152. // but all values have to be convertible to double anyways
  1153. std::vector<double> y;
  1154. for(auto x : ticks) y.push_back(f(x));
  1155. return plot_impl<std::false_type>()(ticks,y,format);
  1156. }
  1157. };
  1158. } // end namespace detail
  1159. // recursion stop for the above
  1160. template<typename... Args>
  1161. bool plot() { return true; }
  1162. template<typename A, typename B, typename... Args>
  1163. bool plot(const A& a, const B& b, const std::string& format, Args... args)
  1164. {
  1165. return detail::plot_impl<typename detail::is_callable<B>::type>()(a,b,format) && plot(args...);
  1166. }
  1167. /*
  1168. * This group of plot() functions is needed to support initializer lists, i.e. calling
  1169. * plot( {1,2,3,4} )
  1170. */
  1171. inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::string& format = "") {
  1172. return plot<double,double>(x,y,format);
  1173. }
  1174. inline bool plot(const std::vector<double>& y, const std::string& format = "") {
  1175. return plot<double>(y,format);
  1176. }
  1177. inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::map<std::string, std::string>& keywords) {
  1178. return plot<double>(x,y,keywords);
  1179. }
  1180. } // end namespace matplotlibcpp