19#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
20#include <numpy/arrayobject.h>
23#include <opencv2/opencv.hpp>
30#if CV_MAJOR_VERSION > 3
31#define CV_BGR2RGB cv::COLOR_BGR2RGB
32#define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA
36#if PY_MAJOR_VERSION >= 3
37#define PyString_FromString PyUnicode_FromString
38#define PyInt_FromLong PyLong_FromLong
39#define PyString_FromString PyUnicode_FromString
42namespace matplotlibcpp {
45static std::string s_backend;
48 PyObject* s_python_function_arrow;
49 PyObject* s_python_function_show;
50 PyObject* s_python_function_close;
51 PyObject* s_python_function_draw;
52 PyObject* s_python_function_pause;
53 PyObject* s_python_function_save;
54 PyObject* s_python_function_figure;
55 PyObject* s_python_function_fignum_exists;
56 PyObject* s_python_function_plot;
57 PyObject* s_python_function_quiver;
58 PyObject* s_python_function_contour;
59 PyObject* s_python_function_semilogx;
60 PyObject* s_python_function_semilogy;
61 PyObject* s_python_function_loglog;
62 PyObject* s_python_function_fill;
63 PyObject* s_python_function_fill_between;
64 PyObject* s_python_function_hist;
65 PyObject* s_python_function_imshow;
66 PyObject* s_python_function_scatter;
67 PyObject* s_python_function_boxplot;
68 PyObject* s_python_function_subplot;
69 PyObject* s_python_function_subplot2grid;
70 PyObject* s_python_function_legend;
71 PyObject* s_python_function_xlim;
72 PyObject* s_python_function_ion;
73 PyObject* s_python_function_ginput;
74 PyObject* s_python_function_ylim;
75 PyObject* s_python_function_title;
76 PyObject* s_python_function_axis;
77 PyObject* s_python_function_axhline;
78 PyObject* s_python_function_axvline;
79 PyObject* s_python_function_axvspan;
80 PyObject* s_python_function_xlabel;
81 PyObject* s_python_function_ylabel;
82 PyObject* s_python_function_gca;
83 PyObject* s_python_function_xticks;
84 PyObject* s_python_function_yticks;
85 PyObject* s_python_function_margins;
86 PyObject* s_python_function_tick_params;
87 PyObject* s_python_function_grid;
88 PyObject* s_python_function_cla;
89 PyObject* s_python_function_clf;
90 PyObject* s_python_function_errorbar;
91 PyObject* s_python_function_annotate;
92 PyObject* s_python_function_tight_layout;
93 PyObject* s_python_colormap;
94 PyObject* s_python_empty_tuple;
95 PyObject* s_python_function_stem;
96 PyObject* s_python_function_xkcd;
97 PyObject* s_python_function_text;
98 PyObject* s_python_function_suptitle;
99 PyObject* s_python_function_bar;
100 PyObject* s_python_function_barh;
101 PyObject* s_python_function_colorbar;
102 PyObject* s_python_function_subplots_adjust;
103 PyObject* s_python_function_rcparams;
104 PyObject* s_python_function_spy;
119 static _interpreter& get() {
return interkeeper(
false); }
121 static _interpreter& kill() {
return interkeeper(
true); }
124 static _interpreter& interkeeper(
bool should_kill) {
125 static _interpreter ctx;
131 PyObject* safe_import(PyObject* module, std::string fname) {
132 PyObject* fn = PyObject_GetAttrString(module, fname.c_str());
135 throw std::runtime_error(std::string(
"Couldn't find required function: ") + fname);
137 if (!PyFunction_Check(fn))
138 throw std::runtime_error(fname + std::string(
" is unexpectedly not a PyFunction."));
145#if PY_MAJOR_VERSION >= 3
147 void* import_numpy() {
154 void import_numpy() {
164#if PY_MAJOR_VERSION >= 3
165 wchar_t name[] = L
"plotting";
167 char name[] =
"plotting";
169 Py_SetProgramName(name);
172 wchar_t const* dummy_args[] = {
174 wchar_t const** argv = dummy_args;
175 int argc =
sizeof(dummy_args) /
sizeof(dummy_args[0]) - 1;
177#if PY_MAJOR_VERSION >= 3
178 PySys_SetArgv(argc,
const_cast<wchar_t**
>(argv));
180 PySys_SetArgv(argc, (
char**)(argv));
187 PyObject* matplotlibname = PyString_FromString(
"matplotlib");
188 PyObject* pyplotname = PyString_FromString(
"matplotlib.pyplot");
189 PyObject* cmname = PyString_FromString(
"matplotlib.cm");
190 PyObject* pylabname = PyString_FromString(
"pylab");
191 if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
192 throw std::runtime_error(
"couldnt create string");
195 PyObject* matplotlib = PyImport_Import(matplotlibname);
197 Py_DECREF(matplotlibname);
200 throw std::runtime_error(
"Error loading module matplotlib!");
205 if (!s_backend.empty()) {
206 PyObject_CallMethod(matplotlib,
const_cast<char*
>(
"use"),
const_cast<char*
>(
"s"),
210 PyObject* pymod = PyImport_Import(pyplotname);
211 Py_DECREF(pyplotname);
213 throw std::runtime_error(
"Error loading module matplotlib.pyplot!");
216 s_python_colormap = PyImport_Import(cmname);
218 if (!s_python_colormap) {
219 throw std::runtime_error(
"Error loading module matplotlib.cm!");
222 PyObject* pylabmod = PyImport_Import(pylabname);
223 Py_DECREF(pylabname);
225 throw std::runtime_error(
"Error loading module pylab!");
228 s_python_function_arrow = safe_import(pymod,
"arrow");
229 s_python_function_show = safe_import(pymod,
"show");
230 s_python_function_close = safe_import(pymod,
"close");
231 s_python_function_draw = safe_import(pymod,
"draw");
232 s_python_function_pause = safe_import(pymod,
"pause");
233 s_python_function_figure = safe_import(pymod,
"figure");
234 s_python_function_fignum_exists = safe_import(pymod,
"fignum_exists");
235 s_python_function_plot = safe_import(pymod,
"plot");
236 s_python_function_quiver = safe_import(pymod,
"quiver");
237 s_python_function_contour = safe_import(pymod,
"contour");
238 s_python_function_semilogx = safe_import(pymod,
"semilogx");
239 s_python_function_semilogy = safe_import(pymod,
"semilogy");
240 s_python_function_loglog = safe_import(pymod,
"loglog");
241 s_python_function_fill = safe_import(pymod,
"fill");
242 s_python_function_fill_between = safe_import(pymod,
"fill_between");
243 s_python_function_hist = safe_import(pymod,
"hist");
244 s_python_function_scatter = safe_import(pymod,
"scatter");
245 s_python_function_boxplot = safe_import(pymod,
"boxplot");
246 s_python_function_subplot = safe_import(pymod,
"subplot");
247 s_python_function_subplot2grid = safe_import(pymod,
"subplot2grid");
248 s_python_function_legend = safe_import(pymod,
"legend");
249 s_python_function_xlim = safe_import(pymod,
"xlim");
250 s_python_function_ylim = safe_import(pymod,
"ylim");
251 s_python_function_title = safe_import(pymod,
"title");
252 s_python_function_axis = safe_import(pymod,
"axis");
253 s_python_function_axhline = safe_import(pymod,
"axhline");
254 s_python_function_axvline = safe_import(pymod,
"axvline");
255 s_python_function_axvspan = safe_import(pymod,
"axvspan");
256 s_python_function_xlabel = safe_import(pymod,
"xlabel");
257 s_python_function_ylabel = safe_import(pymod,
"ylabel");
258 s_python_function_gca = safe_import(pymod,
"gca");
259 s_python_function_xticks = safe_import(pymod,
"xticks");
260 s_python_function_yticks = safe_import(pymod,
"yticks");
261 s_python_function_margins = safe_import(pymod,
"margins");
262 s_python_function_tick_params = safe_import(pymod,
"tick_params");
263 s_python_function_grid = safe_import(pymod,
"grid");
264 s_python_function_ion = safe_import(pymod,
"ion");
265 s_python_function_ginput = safe_import(pymod,
"ginput");
266 s_python_function_save = safe_import(pylabmod,
"savefig");
267 s_python_function_annotate = safe_import(pymod,
"annotate");
268 s_python_function_cla = safe_import(pymod,
"cla");
269 s_python_function_clf = safe_import(pymod,
"clf");
270 s_python_function_errorbar = safe_import(pymod,
"errorbar");
271 s_python_function_tight_layout = safe_import(pymod,
"tight_layout");
272 s_python_function_stem = safe_import(pymod,
"stem");
273 s_python_function_xkcd = safe_import(pymod,
"xkcd");
274 s_python_function_text = safe_import(pymod,
"text");
275 s_python_function_suptitle = safe_import(pymod,
"suptitle");
276 s_python_function_bar = safe_import(pymod,
"bar");
277 s_python_function_barh = safe_import(pymod,
"barh");
278 s_python_function_colorbar = PyObject_GetAttrString(pymod,
"colorbar");
279 s_python_function_subplots_adjust = safe_import(pymod,
"subplots_adjust");
280 s_python_function_rcparams = PyObject_GetAttrString(pymod,
"rcParams");
281 s_python_function_spy = PyObject_GetAttrString(pymod,
"spy");
283 s_python_function_imshow = safe_import(pymod,
"imshow");
285 s_python_empty_tuple = PyTuple_New(0);
288 ~_interpreter() { Py_Finalize(); }
303inline void backend(
const std::string& name) {
304 detail::s_backend = name;
307inline bool annotate(std::string annotation,
double x,
double y) {
308 detail::_interpreter::get();
310 PyObject* xy = PyTuple_New(2);
311 PyObject* str = PyString_FromString(annotation.c_str());
313 PyTuple_SetItem(xy, 0, PyFloat_FromDouble(x));
314 PyTuple_SetItem(xy, 1, PyFloat_FromDouble(y));
316 PyObject* kwargs = PyDict_New();
317 PyDict_SetItemString(kwargs,
"xy", xy);
319 PyObject* args = PyTuple_New(1);
320 PyTuple_SetItem(args, 0, str);
323 PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs);
339 const static NPY_TYPES type = NPY_NOTYPE;
342 const static NPY_TYPES type = NPY_DOUBLE;
345 const static NPY_TYPES type = NPY_FLOAT;
348 const static NPY_TYPES type = NPY_BOOL;
351 const static NPY_TYPES type = NPY_INT8;
354 const static NPY_TYPES type = NPY_SHORT;
357 const static NPY_TYPES type = NPY_INT;
360 const static NPY_TYPES type = NPY_INT64;
363 const static NPY_TYPES type = NPY_UINT8;
366 const static NPY_TYPES type = NPY_USHORT;
369 const static NPY_TYPES type = NPY_ULONG;
372 const static NPY_TYPES type = NPY_UINT64;
377static_assert(
sizeof(
long long) == 8);
379 const static NPY_TYPES type = NPY_INT64;
381static_assert(
sizeof(
unsigned long long) == 8);
383 const static NPY_TYPES type = NPY_UINT64;
386template <
typename Numeric> PyObject* get_array(
const std::vector<Numeric>& v) {
387 npy_intp vsize = v.size();
388 NPY_TYPES
type = select_npy_type<Numeric>::type;
389 if (
type == NPY_NOTYPE) {
390 size_t memsize = v.size() *
sizeof(double);
391 double* dp =
static_cast<double*
>(::malloc(memsize));
392 for (
size_t i = 0; i < v.size(); ++i)
394 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, dp);
395 PyArray_UpdateFlags(
reinterpret_cast<PyArrayObject*
>(varray), NPY_ARRAY_OWNDATA);
399 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (
void*)(v.data()));
403template <
typename Numeric> PyObject* get_2darray(
const std::vector<::std::vector<Numeric>>& v) {
405 throw std::runtime_error(
"get_2d_array v too small");
407 npy_intp vsize[2] = {
static_cast<npy_intp
>(v.size()),
static_cast<npy_intp
>(v[0].size())};
409 PyArrayObject* varray = (PyArrayObject*)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
411 double* vd_begin =
static_cast<double*
>(PyArray_DATA(varray));
413 for (const ::std::vector<Numeric>& v_row : v) {
414 if (v_row.size() !=
static_cast<size_t>(vsize[1]))
415 throw std::runtime_error(
"Missmatched array size");
416 std::copy(v_row.begin(), v_row.end(), vd_begin);
417 vd_begin += vsize[1];
420 return reinterpret_cast<PyObject*
>(varray);
425template <
typename Numeric> PyObject* get_array(
const std::vector<Numeric>& v) {
426 PyObject* list = PyList_New(v.size());
427 for (
size_t i = 0; i < v.size(); ++i) {
428 PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
436inline PyObject* get_array(
const std::vector<std::string>& strings) {
437 PyObject* list = PyList_New(strings.size());
438 for (std::size_t i = 0; i < strings.size(); ++i) {
439 PyList_SetItem(list, i, PyString_FromString(strings[i].c_str()));
445template <
typename Numeric> PyObject* get_listlist(
const std::vector<std::vector<Numeric>>& ll) {
446 PyObject* listlist = PyList_New(ll.size());
447 for (std::size_t i = 0; i < ll.size(); ++i) {
448 PyList_SetItem(listlist, i, get_array(ll[i]));
458template <
typename Numeric>
459bool plot(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
460 const std::map<std::string, std::string>& keywords) {
461 assert(x.size() == y.size());
463 detail::_interpreter::get();
466 PyObject* xarray = detail::get_array(x);
467 PyObject* yarray = detail::get_array(y);
470 PyObject* args = PyTuple_New(2);
471 PyTuple_SetItem(args, 0, xarray);
472 PyTuple_SetItem(args, 1, yarray);
475 PyObject* kwargs = PyDict_New();
476 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
477 it != keywords.end(); ++it) {
478 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
481 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs);
494template <
typename Numeric>
496 const std::vector<::std::vector<Numeric>>& x,
const std::vector<::std::vector<Numeric>>& y,
497 const std::vector<::std::vector<Numeric>>& z,
498 const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>(),
499 const long fig_number = 0) {
500 detail::_interpreter::get();
506 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
507 if (!mpl_toolkitsmod) {
508 detail::_interpreter::get();
510 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
511 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
512 if (!mpl_toolkits || !axis3d) {
513 throw std::runtime_error(
"couldnt create string");
516 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
517 Py_DECREF(mpl_toolkits);
518 if (!mpl_toolkitsmod) {
519 throw std::runtime_error(
"Error loading module mpl_toolkits!");
522 axis3dmod = PyImport_Import(axis3d);
525 throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!");
529 assert(x.size() == y.size());
530 assert(y.size() == z.size());
533 PyObject* xarray = detail::get_2darray(x);
534 PyObject* yarray = detail::get_2darray(y);
535 PyObject* zarray = detail::get_2darray(z);
538 PyObject* args = PyTuple_New(3);
539 PyTuple_SetItem(args, 0, xarray);
540 PyTuple_SetItem(args, 1, yarray);
541 PyTuple_SetItem(args, 2, zarray);
544 PyObject* kwargs = PyDict_New();
545 PyDict_SetItemString(kwargs,
"rstride", PyInt_FromLong(1));
546 PyDict_SetItemString(kwargs,
"cstride", PyInt_FromLong(1));
548 PyObject* python_colormap_coolwarm =
549 PyObject_GetAttrString(detail::_interpreter::get().s_python_colormap,
"coolwarm");
551 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
553 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
554 it != keywords.end(); ++it) {
555 if (it->first ==
"linewidth" || it->first ==
"alpha") {
556 PyDict_SetItemString(kwargs, it->first.c_str(),
557 PyFloat_FromDouble(std::stod(it->second)));
559 PyDict_SetItemString(kwargs, it->first.c_str(),
560 PyString_FromString(it->second.c_str()));
564 PyObject* fig_args = PyTuple_New(1);
565 PyObject* fig =
nullptr;
566 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
567 PyObject* fig_exists =
568 PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
569 if (!PyObject_IsTrue(fig_exists)) {
570 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
571 detail::_interpreter::get().s_python_empty_tuple);
573 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, fig_args);
575 Py_DECREF(fig_exists);
577 throw std::runtime_error(
"Call to figure() failed.");
579 PyObject* gca_kwargs = PyDict_New();
580 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
582 PyObject* gca = PyObject_GetAttrString(fig,
"gca");
584 throw std::runtime_error(
"No gca");
587 PyObject_Call(gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
590 throw std::runtime_error(
"No axis");
594 Py_DECREF(gca_kwargs);
596 PyObject* plot_surface = PyObject_GetAttrString(axis,
"plot_surface");
598 throw std::runtime_error(
"No surface");
599 Py_INCREF(plot_surface);
600 PyObject* res = PyObject_Call(plot_surface, args, kwargs);
602 throw std::runtime_error(
"failed surface");
603 Py_DECREF(plot_surface);
612template <
typename Numeric>
613void contour(
const std::vector<::std::vector<Numeric>>& x,
614 const std::vector<::std::vector<Numeric>>& y,
615 const std::vector<::std::vector<Numeric>>& z,
616 const std::map<std::string, std::string>& keywords = {}) {
617 detail::_interpreter::get();
620 PyObject* xarray = detail::get_2darray(x);
621 PyObject* yarray = detail::get_2darray(y);
622 PyObject* zarray = detail::get_2darray(z);
625 PyObject* args = PyTuple_New(3);
626 PyTuple_SetItem(args, 0, xarray);
627 PyTuple_SetItem(args, 1, yarray);
628 PyTuple_SetItem(args, 2, zarray);
631 PyObject* kwargs = PyDict_New();
633 PyObject* python_colormap_coolwarm =
634 PyObject_GetAttrString(detail::_interpreter::get().s_python_colormap,
"coolwarm");
636 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
638 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
639 it != keywords.end(); ++it) {
640 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
644 PyObject_Call(detail::_interpreter::get().s_python_function_contour, args, kwargs);
646 throw std::runtime_error(
"failed contour");
654template <
typename Numeric>
655void spy(
const std::vector<::std::vector<Numeric>>& x,
656 const double markersize = -1,
657 const std::map<std::string, std::string>& keywords = {}) {
658 detail::_interpreter::get();
660 PyObject* xarray = detail::get_2darray(x);
662 PyObject* kwargs = PyDict_New();
663 if (markersize != -1) {
664 PyDict_SetItemString(kwargs,
"markersize", PyFloat_FromDouble(markersize));
666 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
667 it != keywords.end(); ++it) {
668 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
671 PyObject* plot_args = PyTuple_New(1);
672 PyTuple_SetItem(plot_args, 0, xarray);
675 PyObject_Call(detail::_interpreter::get().s_python_function_spy, plot_args, kwargs);
677 Py_DECREF(plot_args);
684template <
typename Numeric>
686 const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::vector<Numeric>& z,
687 const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>(),
688 const long fig_number = 0) {
689 detail::_interpreter::get();
695 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
696 if (!mpl_toolkitsmod) {
697 detail::_interpreter::get();
699 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
700 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
701 if (!mpl_toolkits || !axis3d) {
702 throw std::runtime_error(
"couldnt create string");
705 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
706 Py_DECREF(mpl_toolkits);
707 if (!mpl_toolkitsmod) {
708 throw std::runtime_error(
"Error loading module mpl_toolkits!");
711 axis3dmod = PyImport_Import(axis3d);
714 throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!");
718 assert(x.size() == y.size());
719 assert(y.size() == z.size());
721 PyObject* xarray = detail::get_array(x);
722 PyObject* yarray = detail::get_array(y);
723 PyObject* zarray = detail::get_array(z);
726 PyObject* args = PyTuple_New(3);
727 PyTuple_SetItem(args, 0, xarray);
728 PyTuple_SetItem(args, 1, yarray);
729 PyTuple_SetItem(args, 2, zarray);
732 PyObject* kwargs = PyDict_New();
734 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
735 it != keywords.end(); ++it) {
736 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
739 PyObject* fig_args = PyTuple_New(1);
740 PyObject* fig =
nullptr;
741 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
742 PyObject* fig_exists =
743 PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
744 if (!PyObject_IsTrue(fig_exists)) {
745 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
746 detail::_interpreter::get().s_python_empty_tuple);
748 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, fig_args);
751 throw std::runtime_error(
"Call to figure() failed.");
753 PyObject* gca_kwargs = PyDict_New();
754 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
756 PyObject* gca = PyObject_GetAttrString(fig,
"gca");
758 throw std::runtime_error(
"No gca");
761 PyObject_Call(gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
764 throw std::runtime_error(
"No axis");
768 Py_DECREF(gca_kwargs);
770 PyObject* plot3 = PyObject_GetAttrString(axis,
"plot");
772 throw std::runtime_error(
"No 3D line plot");
774 PyObject* res = PyObject_Call(plot3, args, kwargs);
776 throw std::runtime_error(
"Failed 3D line plot");
786template <
typename Numeric>
787bool stem(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
788 const std::map<std::string, std::string>& keywords) {
789 assert(x.size() == y.size());
791 detail::_interpreter::get();
794 PyObject* xarray = detail::get_array(x);
795 PyObject* yarray = detail::get_array(y);
798 PyObject* args = PyTuple_New(2);
799 PyTuple_SetItem(args, 0, xarray);
800 PyTuple_SetItem(args, 1, yarray);
803 PyObject* kwargs = PyDict_New();
804 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
805 it != keywords.end(); ++it) {
806 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
809 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_stem, args, kwargs);
819template <
typename Numeric>
820bool fill(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
821 const std::map<std::string, std::string>& keywords) {
822 assert(x.size() == y.size());
824 detail::_interpreter::get();
827 PyObject* xarray = detail::get_array(x);
828 PyObject* yarray = detail::get_array(y);
831 PyObject* args = PyTuple_New(2);
832 PyTuple_SetItem(args, 0, xarray);
833 PyTuple_SetItem(args, 1, yarray);
836 PyObject* kwargs = PyDict_New();
837 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
838 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
841 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill, args, kwargs);
852template <
typename Numeric>
853bool fill_between(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y1,
854 const std::vector<Numeric>& y2,
855 const std::map<std::string, std::string>& keywords) {
856 assert(x.size() == y1.size());
857 assert(x.size() == y2.size());
859 detail::_interpreter::get();
862 PyObject* xarray = detail::get_array(x);
863 PyObject* y1array = detail::get_array(y1);
864 PyObject* y2array = detail::get_array(y2);
867 PyObject* args = PyTuple_New(3);
868 PyTuple_SetItem(args, 0, xarray);
869 PyTuple_SetItem(args, 1, y1array);
870 PyTuple_SetItem(args, 2, y2array);
873 PyObject* kwargs = PyDict_New();
874 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
875 it != keywords.end(); ++it) {
876 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
880 PyObject_Call(detail::_interpreter::get().s_python_function_fill_between, args, kwargs);
890template <
typename Numeric>
891bool arrow(Numeric x, Numeric y, Numeric end_x, Numeric end_y,
const std::string& fc =
"r",
892 const std::string ec =
"k", Numeric head_length = 0.25, Numeric head_width = 0.1625) {
893 PyObject* obj_x = PyFloat_FromDouble(x);
894 PyObject* obj_y = PyFloat_FromDouble(y);
895 PyObject* obj_end_x = PyFloat_FromDouble(end_x);
896 PyObject* obj_end_y = PyFloat_FromDouble(end_y);
898 PyObject* kwargs = PyDict_New();
899 PyDict_SetItemString(kwargs,
"fc", PyString_FromString(fc.c_str()));
900 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
901 PyDict_SetItemString(kwargs,
"head_width", PyFloat_FromDouble(head_width));
902 PyDict_SetItemString(kwargs,
"head_length", PyFloat_FromDouble(head_length));
904 PyObject* plot_args = PyTuple_New(4);
905 PyTuple_SetItem(plot_args, 0, obj_x);
906 PyTuple_SetItem(plot_args, 1, obj_y);
907 PyTuple_SetItem(plot_args, 2, obj_end_x);
908 PyTuple_SetItem(plot_args, 3, obj_end_y);
911 PyObject_Call(detail::_interpreter::get().s_python_function_arrow, plot_args, kwargs);
913 Py_DECREF(plot_args);
921template <
typename Numeric>
922bool hist(
const std::vector<Numeric>& y,
long bins = 10, std::string color =
"b",
923 double alpha = 1.0,
bool cumulative =
false) {
924 detail::_interpreter::get();
926 PyObject* yarray = detail::get_array(y);
928 PyObject* kwargs = PyDict_New();
929 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
930 PyDict_SetItemString(kwargs,
"color", PyString_FromString(color.c_str()));
931 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
932 PyDict_SetItemString(kwargs,
"cumulative", cumulative ? Py_True : Py_False);
934 PyObject* plot_args = PyTuple_New(1);
936 PyTuple_SetItem(plot_args, 0, yarray);
939 PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
941 Py_DECREF(plot_args);
952inline void imshow(
void* ptr,
const NPY_TYPES
type,
const int rows,
const int columns,
953 const int colors,
const std::map<std::string, std::string>& keywords,
955 assert(
type == NPY_UINT8 ||
type == NPY_FLOAT);
956 assert(colors == 1 || colors == 3 || colors == 4);
958 detail::_interpreter::get();
961 npy_intp dims[3] = {rows, columns, colors};
962 PyObject* args = PyTuple_New(1);
963 PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims,
type, ptr));
966 PyObject* kwargs = PyDict_New();
967 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
968 it != keywords.end(); ++it) {
969 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
973 PyObject_Call(detail::_interpreter::get().s_python_function_imshow, args, kwargs);
977 throw std::runtime_error(
"Call to imshow() failed");
986inline void imshow(
const unsigned char* ptr,
const int rows,
const int columns,
const int colors,
987 const std::map<std::string, std::string>& keywords = {},
988 PyObject** out =
nullptr) {
989 detail::imshow((
void*)ptr, NPY_UINT8, rows, columns, colors, keywords, out);
992inline void imshow(
const float* ptr,
const int rows,
const int columns,
const int colors,
993 const std::map<std::string, std::string>& keywords = {},
994 PyObject** out =
nullptr) {
995 detail::imshow((
void*)ptr, NPY_FLOAT, rows, columns, colors, keywords, out);
999void imshow(
const cv::Mat& image,
const std::map<std::string, std::string>& keywords = {}) {
1002 NPY_TYPES npy_type = NPY_UINT8;
1003 switch (image.type() & CV_MAT_DEPTH_MASK) {
1009 npy_type = NPY_FLOAT;
1012 image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
1016 switch (image2.channels()) {
1018 cv::cvtColor(image2, image2, CV_BGR2RGB);
1021 cv::cvtColor(image2, image2, CV_BGRA2RGBA);
1024 detail::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords);
1029template <
typename NumericX,
typename NumericY>
1030bool scatter(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1031 const double s = 1.0,
1032 const std::map<std::string, std::string>& keywords = {}) {
1033 detail::_interpreter::get();
1035 assert(x.size() == y.size());
1037 PyObject* xarray = detail::get_array(x);
1038 PyObject* yarray = detail::get_array(y);
1040 PyObject* kwargs = PyDict_New();
1041 PyDict_SetItemString(kwargs,
"s", PyLong_FromLong(s));
1042 for (
const auto& it : keywords) {
1043 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1046 PyObject* plot_args = PyTuple_New(2);
1047 PyTuple_SetItem(plot_args, 0, xarray);
1048 PyTuple_SetItem(plot_args, 1, yarray);
1051 PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
1053 Py_DECREF(plot_args);
1061template <
typename NumericX,
typename NumericY,
typename NumericColors>
1062bool scatter_colored(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1063 const std::vector<NumericColors>& colors,
1064 const double s = 1.0,
1065 const std::map<std::string, std::string>& keywords = {}) {
1066 detail::_interpreter::get();
1068 assert(x.size() == y.size());
1070 PyObject* xarray = detail::get_array(x);
1071 PyObject* yarray = detail::get_array(y);
1072 PyObject* colors_array = detail::get_array(colors);
1074 PyObject* kwargs = PyDict_New();
1075 PyDict_SetItemString(kwargs,
"s", PyLong_FromLong(s));
1076 PyDict_SetItemString(kwargs,
"c", colors_array);
1078 for (
const auto& it : keywords) {
1079 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1082 PyObject* plot_args = PyTuple_New(2);
1083 PyTuple_SetItem(plot_args, 0, xarray);
1084 PyTuple_SetItem(plot_args, 1, yarray);
1087 PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
1089 Py_DECREF(plot_args);
1097template <
typename NumericX,
typename NumericY,
typename NumericZ>
1098bool scatter(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1099 const std::vector<NumericZ>& z,
1100 const double s = 1.0,
1101 const std::map<std::string, std::string>& keywords = {},
const long fig_number = 0) {
1102 detail::_interpreter::get();
1108 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
1109 if (!mpl_toolkitsmod) {
1110 detail::_interpreter::get();
1112 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
1113 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
1114 if (!mpl_toolkits || !axis3d) {
1115 throw std::runtime_error(
"couldnt create string");
1118 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1119 Py_DECREF(mpl_toolkits);
1120 if (!mpl_toolkitsmod) {
1121 throw std::runtime_error(
"Error loading module mpl_toolkits!");
1124 axis3dmod = PyImport_Import(axis3d);
1127 throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!");
1131 assert(x.size() == y.size());
1132 assert(y.size() == z.size());
1134 PyObject* xarray = detail::get_array(x);
1135 PyObject* yarray = detail::get_array(y);
1136 PyObject* zarray = detail::get_array(z);
1139 PyObject* args = PyTuple_New(3);
1140 PyTuple_SetItem(args, 0, xarray);
1141 PyTuple_SetItem(args, 1, yarray);
1142 PyTuple_SetItem(args, 2, zarray);
1145 PyObject* kwargs = PyDict_New();
1147 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1148 it != keywords.end(); ++it) {
1149 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1151 PyObject* fig_args = PyTuple_New(1);
1152 PyObject* fig =
nullptr;
1153 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
1154 PyObject* fig_exists =
1155 PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
1156 if (!PyObject_IsTrue(fig_exists)) {
1157 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
1158 detail::_interpreter::get().s_python_empty_tuple);
1160 fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, fig_args);
1162 Py_DECREF(fig_exists);
1164 throw std::runtime_error(
"Call to figure() failed.");
1166 PyObject* gca_kwargs = PyDict_New();
1167 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
1169 PyObject* gca = PyObject_GetAttrString(fig,
"gca");
1171 throw std::runtime_error(
"No gca");
1174 PyObject_Call(gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
1177 throw std::runtime_error(
"No axis");
1181 Py_DECREF(gca_kwargs);
1183 PyObject* plot3 = PyObject_GetAttrString(axis,
"scatter");
1185 throw std::runtime_error(
"No 3D line plot");
1187 PyObject* res = PyObject_Call(plot3, args, kwargs);
1189 throw std::runtime_error(
"Failed 3D line plot");
1201template <
typename Numeric>
1202bool boxplot(
const std::vector<std::vector<Numeric>>& data,
1203 const std::vector<std::string>& labels = {},
1204 const std::map<std::string, std::string>& keywords = {}) {
1205 detail::_interpreter::get();
1207 PyObject* listlist = detail::get_listlist(data);
1208 PyObject* args = PyTuple_New(1);
1209 PyTuple_SetItem(args, 0, listlist);
1211 PyObject* kwargs = PyDict_New();
1214 if (!labels.empty() && labels.size() == data.size()) {
1215 PyDict_SetItemString(kwargs,
"labels", detail::get_array(labels));
1219 for (
const auto& it : keywords) {
1220 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1224 PyObject_Call(detail::_interpreter::get().s_python_function_boxplot, args, kwargs);
1235template <
typename Numeric>
1236bool boxplot(
const std::vector<Numeric>& data,
1237 const std::map<std::string, std::string>& keywords = {}) {
1238 detail::_interpreter::get();
1240 PyObject* vector = detail::get_array(data);
1241 PyObject* args = PyTuple_New(1);
1242 PyTuple_SetItem(args, 0, vector);
1244 PyObject* kwargs = PyDict_New();
1245 for (
const auto& it : keywords) {
1246 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1250 PyObject_Call(detail::_interpreter::get().s_python_function_boxplot, args, kwargs);
1261template <
typename Numeric>
1262bool bar(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y, std::string ec =
"black",
1263 std::string ls =
"-",
double lw = 1.0,
1264 const std::map<std::string, std::string>& keywords = {}) {
1265 detail::_interpreter::get();
1267 PyObject* xarray = detail::get_array(x);
1268 PyObject* yarray = detail::get_array(y);
1270 PyObject* kwargs = PyDict_New();
1272 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
1273 PyDict_SetItemString(kwargs,
"ls", PyString_FromString(ls.c_str()));
1274 PyDict_SetItemString(kwargs,
"lw", PyFloat_FromDouble(lw));
1276 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1277 it != keywords.end(); ++it) {
1278 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1281 PyObject* plot_args = PyTuple_New(2);
1282 PyTuple_SetItem(plot_args, 0, xarray);
1283 PyTuple_SetItem(plot_args, 1, yarray);
1286 PyObject_Call(detail::_interpreter::get().s_python_function_bar, plot_args, kwargs);
1288 Py_DECREF(plot_args);
1296template <
typename Numeric>
1297bool bar(
const std::vector<Numeric>& y, std::string ec =
"black", std::string ls =
"-",
1298 double lw = 1.0,
const std::map<std::string, std::string>& keywords = {}) {
1299 using T =
typename std::remove_reference<
decltype(y)>::type::value_type;
1301 detail::_interpreter::get();
1304 for (std::size_t i = 0; i < y.size(); i++) {
1308 return bar(x, y, ec, ls, lw, keywords);
1311template <
typename Numeric>
1312bool barh(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y, std::string ec =
"black",
1313 std::string ls =
"-",
double lw = 1.0,
1314 const std::map<std::string, std::string>& keywords = {}) {
1315 PyObject* xarray = detail::get_array(x);
1316 PyObject* yarray = detail::get_array(y);
1318 PyObject* kwargs = PyDict_New();
1320 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
1321 PyDict_SetItemString(kwargs,
"ls", PyString_FromString(ls.c_str()));
1322 PyDict_SetItemString(kwargs,
"lw", PyFloat_FromDouble(lw));
1324 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1325 it != keywords.end(); ++it) {
1326 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1329 PyObject* plot_args = PyTuple_New(2);
1330 PyTuple_SetItem(plot_args, 0, xarray);
1331 PyTuple_SetItem(plot_args, 1, yarray);
1334 PyObject_Call(detail::_interpreter::get().s_python_function_barh, plot_args, kwargs);
1336 Py_DECREF(plot_args);
1344inline bool subplots_adjust(
const std::map<std::string, double>& keywords = {}) {
1345 detail::_interpreter::get();
1347 PyObject* kwargs = PyDict_New();
1348 for (std::map<std::string, double>::const_iterator it = keywords.begin(); it != keywords.end();
1350 PyDict_SetItemString(kwargs, it->first.c_str(), PyFloat_FromDouble(it->second));
1353 PyObject* plot_args = PyTuple_New(0);
1355 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_subplots_adjust,
1358 Py_DECREF(plot_args);
1366template <
typename Numeric>
1367bool named_hist(std::string label,
const std::vector<Numeric>& y,
long bins = 10,
1368 std::string color =
"b",
double alpha = 1.0) {
1369 detail::_interpreter::get();
1371 PyObject* yarray = detail::get_array(y);
1373 PyObject* kwargs = PyDict_New();
1374 PyDict_SetItemString(kwargs,
"label", PyString_FromString(label.c_str()));
1375 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
1376 PyDict_SetItemString(kwargs,
"color", PyString_FromString(color.c_str()));
1377 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
1379 PyObject* plot_args = PyTuple_New(1);
1380 PyTuple_SetItem(plot_args, 0, yarray);
1383 PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
1385 Py_DECREF(plot_args);
1393template <
typename NumericX,
typename NumericY>
1394bool plot(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1395 const std::string& s =
"") {
1396 assert(x.size() == y.size());
1398 detail::_interpreter::get();
1400 PyObject* xarray = detail::get_array(x);
1401 PyObject* yarray = detail::get_array(y);
1403 PyObject* pystring = PyString_FromString(s.c_str());
1405 PyObject* plot_args = PyTuple_New(3);
1406 PyTuple_SetItem(plot_args, 0, xarray);
1407 PyTuple_SetItem(plot_args, 1, yarray);
1408 PyTuple_SetItem(plot_args, 2, pystring);
1411 PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
1413 Py_DECREF(plot_args);
1420template <
typename NumericX,
typename NumericY,
typename NumericZ>
1421bool contour(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1422 const std::vector<NumericZ>& z,
1423 const std::map<std::string, std::string>& keywords = {}) {
1424 assert(x.size() == y.size() && x.size() == z.size());
1426 PyObject* xarray = detail::get_array(x);
1427 PyObject* yarray = detail::get_array(y);
1428 PyObject* zarray = detail::get_array(z);
1430 PyObject* plot_args = PyTuple_New(3);
1431 PyTuple_SetItem(plot_args, 0, xarray);
1432 PyTuple_SetItem(plot_args, 1, yarray);
1433 PyTuple_SetItem(plot_args, 2, zarray);
1436 PyObject* kwargs = PyDict_New();
1437 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1438 it != keywords.end(); ++it) {
1439 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1443 PyObject_Call(detail::_interpreter::get().s_python_function_contour, plot_args, kwargs);
1446 Py_DECREF(plot_args);
1453template <
typename NumericX,
typename NumericY,
typename NumericU,
typename NumericW>
1454bool quiver(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1455 const std::vector<NumericU>& u,
const std::vector<NumericW>& w,
1456 const std::map<std::string, std::string>& keywords = {}) {
1457 assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size());
1459 detail::_interpreter::get();
1461 PyObject* xarray = detail::get_array(x);
1462 PyObject* yarray = detail::get_array(y);
1463 PyObject* uarray = detail::get_array(u);
1464 PyObject* warray = detail::get_array(w);
1466 PyObject* plot_args = PyTuple_New(4);
1467 PyTuple_SetItem(plot_args, 0, xarray);
1468 PyTuple_SetItem(plot_args, 1, yarray);
1469 PyTuple_SetItem(plot_args, 2, uarray);
1470 PyTuple_SetItem(plot_args, 3, warray);
1473 PyObject* kwargs = PyDict_New();
1474 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1475 it != keywords.end(); ++it) {
1476 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1480 PyObject_Call(detail::_interpreter::get().s_python_function_quiver, plot_args, kwargs);
1483 Py_DECREF(plot_args);
1490template <
typename NumericX,
typename NumericY,
typename NumericZ,
typename NumericU,
1491 typename NumericW,
typename NumericV>
1492bool quiver(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1493 const std::vector<NumericZ>& z,
const std::vector<NumericU>& u,
1494 const std::vector<NumericW>& w,
const std::vector<NumericV>& v,
1495 const std::map<std::string, std::string>& keywords = {}) {
1497 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
1498 if (!mpl_toolkitsmod) {
1499 detail::_interpreter::get();
1501 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
1502 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
1503 if (!mpl_toolkits || !axis3d) {
1504 throw std::runtime_error(
"couldnt create string");
1507 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1508 Py_DECREF(mpl_toolkits);
1509 if (!mpl_toolkitsmod) {
1510 throw std::runtime_error(
"Error loading module mpl_toolkits!");
1513 axis3dmod = PyImport_Import(axis3d);
1516 throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!");
1521 assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size() &&
1522 x.size() == z.size() && x.size() == v.size() && u.size() == v.size());
1525 detail::_interpreter::get();
1527 PyObject* xarray = detail::get_array(x);
1528 PyObject* yarray = detail::get_array(y);
1529 PyObject* zarray = detail::get_array(z);
1530 PyObject* uarray = detail::get_array(u);
1531 PyObject* warray = detail::get_array(w);
1532 PyObject* varray = detail::get_array(v);
1534 PyObject* plot_args = PyTuple_New(6);
1535 PyTuple_SetItem(plot_args, 0, xarray);
1536 PyTuple_SetItem(plot_args, 1, yarray);
1537 PyTuple_SetItem(plot_args, 2, zarray);
1538 PyTuple_SetItem(plot_args, 3, uarray);
1539 PyTuple_SetItem(plot_args, 4, warray);
1540 PyTuple_SetItem(plot_args, 5, varray);
1543 PyObject* kwargs = PyDict_New();
1544 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1545 it != keywords.end(); ++it) {
1546 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1550 PyObject* fig = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
1551 detail::_interpreter::get().s_python_empty_tuple);
1553 throw std::runtime_error(
"Call to figure() failed.");
1555 PyObject* gca_kwargs = PyDict_New();
1556 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
1558 PyObject* gca = PyObject_GetAttrString(fig,
"gca");
1560 throw std::runtime_error(
"No gca");
1563 PyObject_Call(gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
1566 throw std::runtime_error(
"No axis");
1569 Py_DECREF(gca_kwargs);
1572 PyObject* plot3 = PyObject_GetAttrString(axis,
"quiver");
1574 throw std::runtime_error(
"No 3D line plot");
1576 PyObject* res = PyObject_Call(plot3, plot_args, kwargs);
1578 throw std::runtime_error(
"Failed 3D plot");
1582 Py_DECREF(plot_args);
1589template <
typename NumericX,
typename NumericY>
1590bool stem(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1591 const std::string& s =
"") {
1592 assert(x.size() == y.size());
1594 detail::_interpreter::get();
1596 PyObject* xarray = detail::get_array(x);
1597 PyObject* yarray = detail::get_array(y);
1599 PyObject* pystring = PyString_FromString(s.c_str());
1601 PyObject* plot_args = PyTuple_New(3);
1602 PyTuple_SetItem(plot_args, 0, xarray);
1603 PyTuple_SetItem(plot_args, 1, yarray);
1604 PyTuple_SetItem(plot_args, 2, pystring);
1607 PyObject_CallObject(detail::_interpreter::get().s_python_function_stem, plot_args);
1609 Py_DECREF(plot_args);
1616template <
typename NumericX,
typename NumericY>
1617bool semilogx(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1618 const std::string& s =
"") {
1619 assert(x.size() == y.size());
1621 detail::_interpreter::get();
1623 PyObject* xarray = detail::get_array(x);
1624 PyObject* yarray = detail::get_array(y);
1626 PyObject* pystring = PyString_FromString(s.c_str());
1628 PyObject* plot_args = PyTuple_New(3);
1629 PyTuple_SetItem(plot_args, 0, xarray);
1630 PyTuple_SetItem(plot_args, 1, yarray);
1631 PyTuple_SetItem(plot_args, 2, pystring);
1634 PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogx, plot_args);
1636 Py_DECREF(plot_args);
1643template <
typename NumericX,
typename NumericY>
1644bool semilogy(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1645 const std::string& s =
"") {
1646 assert(x.size() == y.size());
1648 detail::_interpreter::get();
1650 PyObject* xarray = detail::get_array(x);
1651 PyObject* yarray = detail::get_array(y);
1653 PyObject* pystring = PyString_FromString(s.c_str());
1655 PyObject* plot_args = PyTuple_New(3);
1656 PyTuple_SetItem(plot_args, 0, xarray);
1657 PyTuple_SetItem(plot_args, 1, yarray);
1658 PyTuple_SetItem(plot_args, 2, pystring);
1661 PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogy, plot_args);
1663 Py_DECREF(plot_args);
1670template <
typename NumericX,
typename NumericY>
1671bool loglog(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1672 const std::string& s =
"") {
1673 assert(x.size() == y.size());
1675 detail::_interpreter::get();
1677 PyObject* xarray = detail::get_array(x);
1678 PyObject* yarray = detail::get_array(y);
1680 PyObject* pystring = PyString_FromString(s.c_str());
1682 PyObject* plot_args = PyTuple_New(3);
1683 PyTuple_SetItem(plot_args, 0, xarray);
1684 PyTuple_SetItem(plot_args, 1, yarray);
1685 PyTuple_SetItem(plot_args, 2, pystring);
1688 PyObject_CallObject(detail::_interpreter::get().s_python_function_loglog, plot_args);
1690 Py_DECREF(plot_args);
1697template <
typename NumericX,
typename NumericY>
1698bool errorbar(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
1699 const std::vector<NumericX>& yerr,
1700 const std::map<std::string, std::string>& keywords = {}) {
1701 assert(x.size() == y.size());
1703 detail::_interpreter::get();
1705 PyObject* xarray = detail::get_array(x);
1706 PyObject* yarray = detail::get_array(y);
1707 PyObject* yerrarray = detail::get_array(yerr);
1710 PyObject* kwargs = PyDict_New();
1711 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1712 it != keywords.end(); ++it) {
1713 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1716 PyDict_SetItemString(kwargs,
"yerr", yerrarray);
1718 PyObject* plot_args = PyTuple_New(2);
1719 PyTuple_SetItem(plot_args, 0, xarray);
1720 PyTuple_SetItem(plot_args, 1, yarray);
1723 PyObject_Call(detail::_interpreter::get().s_python_function_errorbar, plot_args, kwargs);
1726 Py_DECREF(plot_args);
1731 throw std::runtime_error(
"Call to errorbar() failed.");
1736template <
typename Numeric>
1737bool named_plot(
const std::string& name,
const std::vector<Numeric>& y,
1738 const std::string& format =
"") {
1739 detail::_interpreter::get();
1741 PyObject* kwargs = PyDict_New();
1742 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1744 PyObject* yarray = detail::get_array(y);
1746 PyObject* pystring = PyString_FromString(format.c_str());
1748 PyObject* plot_args = PyTuple_New(2);
1750 PyTuple_SetItem(plot_args, 0, yarray);
1751 PyTuple_SetItem(plot_args, 1, pystring);
1754 PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1757 Py_DECREF(plot_args);
1764template <
typename NumericX,
typename NumericY>
1765bool named_plot(
const std::string& name,
const std::vector<NumericX>& x,
1766 const std::vector<NumericY>& y,
const std::string& format =
"") {
1767 detail::_interpreter::get();
1769 PyObject* kwargs = PyDict_New();
1770 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1772 PyObject* xarray = detail::get_array(x);
1773 PyObject* yarray = detail::get_array(y);
1775 PyObject* pystring = PyString_FromString(format.c_str());
1777 PyObject* plot_args = PyTuple_New(3);
1778 PyTuple_SetItem(plot_args, 0, xarray);
1779 PyTuple_SetItem(plot_args, 1, yarray);
1780 PyTuple_SetItem(plot_args, 2, pystring);
1783 PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1786 Py_DECREF(plot_args);
1793template <
typename NumericX,
typename NumericY>
1794bool named_semilogx(
const std::string& name,
const std::vector<NumericX>& x,
1795 const std::vector<NumericY>& y,
const std::string& format =
"") {
1796 detail::_interpreter::get();
1798 PyObject* kwargs = PyDict_New();
1799 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1801 PyObject* xarray = detail::get_array(x);
1802 PyObject* yarray = detail::get_array(y);
1804 PyObject* pystring = PyString_FromString(format.c_str());
1806 PyObject* plot_args = PyTuple_New(3);
1807 PyTuple_SetItem(plot_args, 0, xarray);
1808 PyTuple_SetItem(plot_args, 1, yarray);
1809 PyTuple_SetItem(plot_args, 2, pystring);
1812 PyObject_Call(detail::_interpreter::get().s_python_function_semilogx, plot_args, kwargs);
1815 Py_DECREF(plot_args);
1822template <
typename NumericX,
typename NumericY>
1823bool named_semilogy(
const std::string& name,
const std::vector<NumericX>& x,
1824 const std::vector<NumericY>& y,
const std::string& format =
"") {
1825 detail::_interpreter::get();
1827 PyObject* kwargs = PyDict_New();
1828 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1830 PyObject* xarray = detail::get_array(x);
1831 PyObject* yarray = detail::get_array(y);
1833 PyObject* pystring = PyString_FromString(format.c_str());
1835 PyObject* plot_args = PyTuple_New(3);
1836 PyTuple_SetItem(plot_args, 0, xarray);
1837 PyTuple_SetItem(plot_args, 1, yarray);
1838 PyTuple_SetItem(plot_args, 2, pystring);
1841 PyObject_Call(detail::_interpreter::get().s_python_function_semilogy, plot_args, kwargs);
1844 Py_DECREF(plot_args);
1851template <
typename NumericX,
typename NumericY>
1852bool named_loglog(
const std::string& name,
const std::vector<NumericX>& x,
1853 const std::vector<NumericY>& y,
const std::string& format =
"") {
1854 detail::_interpreter::get();
1856 PyObject* kwargs = PyDict_New();
1857 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1859 PyObject* xarray = detail::get_array(x);
1860 PyObject* yarray = detail::get_array(y);
1862 PyObject* pystring = PyString_FromString(format.c_str());
1864 PyObject* plot_args = PyTuple_New(3);
1865 PyTuple_SetItem(plot_args, 0, xarray);
1866 PyTuple_SetItem(plot_args, 1, yarray);
1867 PyTuple_SetItem(plot_args, 2, pystring);
1869 PyObject_Call(detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs);
1872 Py_DECREF(plot_args);
1879template <
typename Numeric>
1880bool plot(
const std::vector<Numeric>& y,
const std::string& format =
"") {
1881 std::vector<Numeric> x(y.size());
1882 for (
size_t i = 0; i < x.size(); ++i)
1884 return plot(x, y, format);
1887template <
typename Numeric>
1888bool plot(
const std::vector<Numeric>& y,
const std::map<std::string, std::string>& keywords) {
1889 std::vector<Numeric> x(y.size());
1890 for (
size_t i = 0; i < x.size(); ++i)
1892 return plot(x, y, keywords);
1895template <
typename Numeric>
1896bool stem(
const std::vector<Numeric>& y,
const std::string& format =
"") {
1897 std::vector<Numeric> x(y.size());
1898 for (
size_t i = 0; i < x.size(); ++i)
1900 return stem(x, y, format);
1903template <
typename Numeric>
void text(Numeric x, Numeric y,
const std::string& s =
"") {
1904 detail::_interpreter::get();
1906 PyObject* args = PyTuple_New(3);
1907 PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
1908 PyTuple_SetItem(args, 1, PyFloat_FromDouble(y));
1909 PyTuple_SetItem(args, 2, PyString_FromString(s.c_str()));
1911 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_text, args);
1913 throw std::runtime_error(
"Call to text() failed.");
1919inline void colorbar(PyObject* mappable = NULL,
const std::map<std::string, float>& keywords = {}) {
1920 if (mappable == NULL)
1921 throw std::runtime_error(
"Must call colorbar with PyObject* returned from "
1922 "an image, contour, surface, etc.");
1924 detail::_interpreter::get();
1926 PyObject* args = PyTuple_New(1);
1927 PyTuple_SetItem(args, 0, mappable);
1929 PyObject* kwargs = PyDict_New();
1930 for (std::map<std::string, float>::const_iterator it = keywords.begin(); it != keywords.end();
1932 PyDict_SetItemString(kwargs, it->first.c_str(), PyFloat_FromDouble(it->second));
1936 PyObject_Call(detail::_interpreter::get().s_python_function_colorbar, args, kwargs);
1938 throw std::runtime_error(
"Call to colorbar() failed.");
1945inline long figure(
long number = -1) {
1946 detail::_interpreter::get();
1950 res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
1951 detail::_interpreter::get().s_python_empty_tuple);
1956 detail::_interpreter::get();
1958 PyObject* args = PyTuple_New(1);
1959 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1960 res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, args);
1965 throw std::runtime_error(
"Call to figure() failed.");
1967 PyObject* num = PyObject_GetAttrString(res,
"number");
1969 throw std::runtime_error(
"Could not get number attribute of figure object");
1970 const long figureNumber = PyLong_AsLong(num);
1975 return figureNumber;
1978inline bool fignum_exists(
long number) {
1979 detail::_interpreter::get();
1981 PyObject* args = PyTuple_New(1);
1982 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1984 PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, args);
1986 throw std::runtime_error(
"Call to fignum_exists() failed.");
1988 bool ret = PyObject_IsTrue(res);
1995inline void figure_size(
size_t w,
size_t h) {
1996 detail::_interpreter::get();
1998 const size_t dpi = 100;
1999 PyObject* size = PyTuple_New(2);
2000 PyTuple_SetItem(size, 0, PyFloat_FromDouble((
double)w / dpi));
2001 PyTuple_SetItem(size, 1, PyFloat_FromDouble((
double)h / dpi));
2003 PyObject* kwargs = PyDict_New();
2004 PyDict_SetItemString(kwargs,
"figsize", size);
2005 PyDict_SetItemString(kwargs,
"dpi", PyLong_FromSize_t(dpi));
2007 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_figure,
2008 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2013 throw std::runtime_error(
"Call to figure_size() failed.");
2017inline void legend() {
2018 detail::_interpreter::get();
2020 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_legend,
2021 detail::_interpreter::get().s_python_empty_tuple);
2023 throw std::runtime_error(
"Call to legend() failed.");
2028inline void legend(
const std::map<std::string, std::string>& keywords) {
2029 detail::_interpreter::get();
2032 PyObject* kwargs = PyDict_New();
2033 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2034 it != keywords.end(); ++it) {
2035 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2038 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_legend,
2039 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2041 throw std::runtime_error(
"Call to legend() failed.");
2047template <
typename Numeric>
inline void set_aspect(Numeric ratio) {
2048 detail::_interpreter::get();
2050 PyObject* args = PyTuple_New(1);
2051 PyTuple_SetItem(args, 0, PyFloat_FromDouble(ratio));
2052 PyObject* kwargs = PyDict_New();
2054 PyObject* ax = PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2055 detail::_interpreter::get().s_python_empty_tuple);
2057 throw std::runtime_error(
"Call to gca() failed.");
2060 PyObject* set_aspect = PyObject_GetAttrString(ax,
"set_aspect");
2062 throw std::runtime_error(
"Attribute set_aspect not found.");
2063 Py_INCREF(set_aspect);
2065 PyObject* res = PyObject_Call(set_aspect, args, kwargs);
2067 throw std::runtime_error(
"Call to set_aspect() failed.");
2068 Py_DECREF(set_aspect);
2075inline void set_aspect_equal() {
2077 detail::_interpreter::get();
2079 PyObject* args = PyTuple_New(1);
2080 PyTuple_SetItem(args, 0, PyString_FromString(
"equal"));
2081 PyObject* kwargs = PyDict_New();
2083 PyObject* ax = PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2084 detail::_interpreter::get().s_python_empty_tuple);
2086 throw std::runtime_error(
"Call to gca() failed.");
2089 PyObject* set_aspect = PyObject_GetAttrString(ax,
"set_aspect");
2091 throw std::runtime_error(
"Attribute set_aspect not found.");
2092 Py_INCREF(set_aspect);
2094 PyObject* res = PyObject_Call(set_aspect, args, kwargs);
2096 throw std::runtime_error(
"Call to set_aspect() failed.");
2097 Py_DECREF(set_aspect);
2104template <
typename Numeric>
void ylim(Numeric left, Numeric right) {
2105 detail::_interpreter::get();
2107 PyObject* list = PyList_New(2);
2108 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
2109 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
2111 PyObject* args = PyTuple_New(1);
2112 PyTuple_SetItem(args, 0, list);
2114 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
2116 throw std::runtime_error(
"Call to ylim() failed.");
2122template <
typename Numeric>
void xlim(Numeric left, Numeric right) {
2123 detail::_interpreter::get();
2125 PyObject* list = PyList_New(2);
2126 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
2127 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
2129 PyObject* args = PyTuple_New(1);
2130 PyTuple_SetItem(args, 0, list);
2132 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
2134 throw std::runtime_error(
"Call to xlim() failed.");
2140inline std::array<double, 2> xlim() {
2141 PyObject* args = PyTuple_New(0);
2142 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
2145 throw std::runtime_error(
"Call to xlim() failed.");
2149 PyObject* left = PyTuple_GetItem(res, 0);
2150 PyObject* right = PyTuple_GetItem(res, 1);
2151 return {PyFloat_AsDouble(left), PyFloat_AsDouble(right)};
2154inline std::array<double, 2> ylim() {
2155 PyObject* args = PyTuple_New(0);
2156 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
2159 throw std::runtime_error(
"Call to ylim() failed.");
2163 PyObject* left = PyTuple_GetItem(res, 0);
2164 PyObject* right = PyTuple_GetItem(res, 1);
2165 return {PyFloat_AsDouble(left), PyFloat_AsDouble(right)};
2168template <
typename Numeric>
2169inline void xticks(
const std::vector<Numeric>& ticks,
const std::vector<std::string>& labels = {},
2170 const std::map<std::string, std::string>& keywords = {}) {
2171 assert(labels.size() == 0 || ticks.size() == labels.size());
2173 detail::_interpreter::get();
2176 PyObject* ticksarray = detail::get_array(ticks);
2179 if (labels.size() == 0) {
2181 args = PyTuple_New(1);
2182 PyTuple_SetItem(args, 0, ticksarray);
2185 PyObject* labelstuple = PyTuple_New(labels.size());
2186 for (
size_t i = 0; i < labels.size(); i++)
2187 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
2190 args = PyTuple_New(2);
2191 PyTuple_SetItem(args, 0, ticksarray);
2192 PyTuple_SetItem(args, 1, labelstuple);
2196 PyObject* kwargs = PyDict_New();
2197 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2198 it != keywords.end(); ++it) {
2199 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2203 PyObject_Call(detail::_interpreter::get().s_python_function_xticks, args, kwargs);
2208 throw std::runtime_error(
"Call to xticks() failed");
2213template <
typename Numeric>
2214inline void xticks(
const std::vector<Numeric>& ticks,
2215 const std::map<std::string, std::string>& keywords) {
2216 xticks(ticks, {}, keywords);
2219template <
typename Numeric>
2220inline void yticks(
const std::vector<Numeric>& ticks,
const std::vector<std::string>& labels = {},
2221 const std::map<std::string, std::string>& keywords = {}) {
2222 assert(labels.size() == 0 || ticks.size() == labels.size());
2224 detail::_interpreter::get();
2227 PyObject* ticksarray = detail::get_array(ticks);
2230 if (labels.size() == 0) {
2232 args = PyTuple_New(1);
2233 PyTuple_SetItem(args, 0, ticksarray);
2236 PyObject* labelstuple = PyTuple_New(labels.size());
2237 for (
size_t i = 0; i < labels.size(); i++)
2238 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
2241 args = PyTuple_New(2);
2242 PyTuple_SetItem(args, 0, ticksarray);
2243 PyTuple_SetItem(args, 1, labelstuple);
2247 PyObject* kwargs = PyDict_New();
2248 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2249 it != keywords.end(); ++it) {
2250 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2254 PyObject_Call(detail::_interpreter::get().s_python_function_yticks, args, kwargs);
2259 throw std::runtime_error(
"Call to yticks() failed");
2264template <
typename Numeric>
2265inline void yticks(
const std::vector<Numeric>& ticks,
2266 const std::map<std::string, std::string>& keywords) {
2267 yticks(ticks, {}, keywords);
2270template <
typename Numeric>
inline void margins(Numeric margin) {
2272 PyObject* args = PyTuple_New(1);
2273 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin));
2276 PyObject_CallObject(detail::_interpreter::get().s_python_function_margins, args);
2278 throw std::runtime_error(
"Call to margins() failed.");
2284template <
typename Numeric>
inline void margins(Numeric margin_x, Numeric margin_y) {
2286 PyObject* args = PyTuple_New(2);
2287 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin_x));
2288 PyTuple_SetItem(args, 1, PyFloat_FromDouble(margin_y));
2291 PyObject_CallObject(detail::_interpreter::get().s_python_function_margins, args);
2293 throw std::runtime_error(
"Call to margins() failed.");
2299inline void tick_params(
const std::map<std::string, std::string>& keywords,
2300 const std::string axis =
"both") {
2301 detail::_interpreter::get();
2305 args = PyTuple_New(1);
2306 PyTuple_SetItem(args, 0, PyString_FromString(axis.c_str()));
2309 PyObject* kwargs = PyDict_New();
2310 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2311 it != keywords.end(); ++it) {
2312 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2316 PyObject_Call(detail::_interpreter::get().s_python_function_tick_params, args, kwargs);
2321 throw std::runtime_error(
"Call to tick_params() failed");
2326inline void subplot(
long nrows,
long ncols,
long plot_number) {
2327 detail::_interpreter::get();
2330 PyObject* args = PyTuple_New(3);
2331 PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
2332 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
2333 PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
2336 PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args);
2338 throw std::runtime_error(
"Call to subplot() failed.");
2344inline void subplot2grid(
long nrows,
long ncols,
long rowid = 0,
long colid = 0,
long rowspan = 1,
2346 detail::_interpreter::get();
2348 PyObject* shape = PyTuple_New(2);
2349 PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows));
2350 PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols));
2352 PyObject* loc = PyTuple_New(2);
2353 PyTuple_SetItem(loc, 0, PyLong_FromLong(rowid));
2354 PyTuple_SetItem(loc, 1, PyLong_FromLong(colid));
2356 PyObject* args = PyTuple_New(4);
2357 PyTuple_SetItem(args, 0, shape);
2358 PyTuple_SetItem(args, 1, loc);
2359 PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan));
2360 PyTuple_SetItem(args, 3, PyLong_FromLong(colspan));
2363 PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot2grid, args);
2365 throw std::runtime_error(
"Call to subplot2grid() failed.");
2373inline void title(
const std::string& titlestr,
2374 const std::map<std::string, std::string>& keywords = {}) {
2375 detail::_interpreter::get();
2377 PyObject* pytitlestr = PyString_FromString(titlestr.c_str());
2378 PyObject* args = PyTuple_New(1);
2379 PyTuple_SetItem(args, 0, pytitlestr);
2381 PyObject* kwargs = PyDict_New();
2382 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2383 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2387 PyObject_Call(detail::_interpreter::get().s_python_function_title, args, kwargs);
2389 throw std::runtime_error(
"Call to title() failed.");
2396inline void suptitle(
const std::string& suptitlestr,
2397 const std::map<std::string, std::string>& keywords = {}) {
2398 detail::_interpreter::get();
2400 PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str());
2401 PyObject* args = PyTuple_New(1);
2402 PyTuple_SetItem(args, 0, pysuptitlestr);
2404 PyObject* kwargs = PyDict_New();
2405 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2406 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2410 PyObject_Call(detail::_interpreter::get().s_python_function_suptitle, args, kwargs);
2412 throw std::runtime_error(
"Call to suptitle() failed.");
2419inline void axis(
const std::string& axisstr) {
2420 detail::_interpreter::get();
2422 PyObject* str = PyString_FromString(axisstr.c_str());
2423 PyObject* args = PyTuple_New(1);
2424 PyTuple_SetItem(args, 0, str);
2426 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_axis, args);
2428 throw std::runtime_error(
"Call to title() failed.");
2435axhline(
double y,
double xmin = 0.,
double xmax = 1.,
2436 const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>()) {
2437 detail::_interpreter::get();
2440 PyObject* args = PyTuple_New(3);
2441 PyTuple_SetItem(args, 0, PyFloat_FromDouble(y));
2442 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmin));
2443 PyTuple_SetItem(args, 2, PyFloat_FromDouble(xmax));
2446 PyObject* kwargs = PyDict_New();
2447 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2448 it != keywords.end(); ++it) {
2449 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2453 PyObject_Call(detail::_interpreter::get().s_python_function_axhline, args, kwargs);
2463axvline(
double x,
double ymin = 0.,
double ymax = 1.,
2464 const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>()) {
2465 detail::_interpreter::get();
2468 PyObject* args = PyTuple_New(3);
2469 PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
2470 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ymin));
2471 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymax));
2474 PyObject* kwargs = PyDict_New();
2475 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2476 it != keywords.end(); ++it) {
2477 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2481 PyObject_Call(detail::_interpreter::get().s_python_function_axvline, args, kwargs);
2491axvspan(
double xmin,
double xmax,
double ymin = 0.,
double ymax = 1.,
2492 const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>()) {
2494 PyObject* args = PyTuple_New(4);
2495 PyTuple_SetItem(args, 0, PyFloat_FromDouble(xmin));
2496 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmax));
2497 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymin));
2498 PyTuple_SetItem(args, 3, PyFloat_FromDouble(ymax));
2501 PyObject* kwargs = PyDict_New();
2502 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2503 if (it->first ==
"linewidth" || it->first ==
"alpha") {
2504 PyDict_SetItemString(kwargs, it->first.c_str(),
2505 PyFloat_FromDouble(std::stod(it->second)));
2507 PyDict_SetItemString(kwargs, it->first.c_str(),
2508 PyString_FromString(it->second.c_str()));
2513 PyObject_Call(detail::_interpreter::get().s_python_function_axvspan, args, kwargs);
2521inline void xlabel(
const std::string& str,
2522 const std::map<std::string, std::string>& keywords = {}) {
2523 detail::_interpreter::get();
2525 PyObject* pystr = PyString_FromString(str.c_str());
2526 PyObject* args = PyTuple_New(1);
2527 PyTuple_SetItem(args, 0, pystr);
2529 PyObject* kwargs = PyDict_New();
2530 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2531 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2535 PyObject_Call(detail::_interpreter::get().s_python_function_xlabel, args, kwargs);
2537 throw std::runtime_error(
"Call to xlabel() failed.");
2544inline void ylabel(
const std::string& str,
2545 const std::map<std::string, std::string>& keywords = {}) {
2546 detail::_interpreter::get();
2548 PyObject* pystr = PyString_FromString(str.c_str());
2549 PyObject* args = PyTuple_New(1);
2550 PyTuple_SetItem(args, 0, pystr);
2552 PyObject* kwargs = PyDict_New();
2553 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2554 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2558 PyObject_Call(detail::_interpreter::get().s_python_function_ylabel, args, kwargs);
2560 throw std::runtime_error(
"Call to ylabel() failed.");
2567inline void set_zlabel(
const std::string& str,
2568 const std::map<std::string, std::string>& keywords = {}) {
2569 detail::_interpreter::get();
2575 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
2576 if (!mpl_toolkitsmod) {
2577 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
2578 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
2579 if (!mpl_toolkits || !axis3d) {
2580 throw std::runtime_error(
"couldnt create string");
2583 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
2584 Py_DECREF(mpl_toolkits);
2585 if (!mpl_toolkitsmod) {
2586 throw std::runtime_error(
"Error loading module mpl_toolkits!");
2589 axis3dmod = PyImport_Import(axis3d);
2592 throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!");
2596 PyObject* pystr = PyString_FromString(str.c_str());
2597 PyObject* args = PyTuple_New(1);
2598 PyTuple_SetItem(args, 0, pystr);
2600 PyObject* kwargs = PyDict_New();
2601 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2602 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2605 PyObject* ax = PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2606 detail::_interpreter::get().s_python_empty_tuple);
2608 throw std::runtime_error(
"Call to gca() failed.");
2611 PyObject* zlabel = PyObject_GetAttrString(ax,
"set_zlabel");
2613 throw std::runtime_error(
"Attribute set_zlabel not found.");
2616 PyObject* res = PyObject_Call(zlabel, args, kwargs);
2618 throw std::runtime_error(
"Call to set_zlabel() failed.");
2628inline void grid(
bool flag) {
2629 detail::_interpreter::get();
2631 PyObject* pyflag = flag ? Py_True : Py_False;
2634 PyObject* args = PyTuple_New(1);
2635 PyTuple_SetItem(args, 0, pyflag);
2637 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_grid, args);
2639 throw std::runtime_error(
"Call to grid() failed.");
2645inline void show(
const bool block =
true) {
2646 detail::_interpreter::get();
2650 res = PyObject_CallObject(detail::_interpreter::get().s_python_function_show,
2651 detail::_interpreter::get().s_python_empty_tuple);
2653 PyObject* kwargs = PyDict_New();
2654 PyDict_SetItemString(kwargs,
"block", Py_False);
2655 res = PyObject_Call(detail::_interpreter::get().s_python_function_show,
2656 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2661 throw std::runtime_error(
"Call to show() failed.");
2666inline void close() {
2667 detail::_interpreter::get();
2669 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_close,
2670 detail::_interpreter::get().s_python_empty_tuple);
2673 throw std::runtime_error(
"Call to close() failed.");
2679 detail::_interpreter::get();
2682 PyObject* kwargs = PyDict_New();
2684 res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd,
2685 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2690 throw std::runtime_error(
"Call to show() failed.");
2696 detail::_interpreter::get();
2698 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_draw,
2699 detail::_interpreter::get().s_python_empty_tuple);
2702 throw std::runtime_error(
"Call to draw() failed.");
2707template <
typename Numeric>
inline void pause(Numeric interval) {
2708 detail::_interpreter::get();
2710 PyObject* args = PyTuple_New(1);
2711 PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
2713 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_pause, args);
2715 throw std::runtime_error(
"Call to pause() failed.");
2721inline void save(
const std::string& filename,
const int dpi = 0) {
2722 detail::_interpreter::get();
2724 PyObject* pyfilename = PyString_FromString(filename.c_str());
2726 PyObject* args = PyTuple_New(1);
2727 PyTuple_SetItem(args, 0, pyfilename);
2729 PyObject* kwargs = PyDict_New();
2732 PyDict_SetItemString(kwargs,
"dpi", PyLong_FromLong(dpi));
2735 PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_save, args, kwargs);
2737 throw std::runtime_error(
"Call to save() failed.");
2744inline void rcparams(
const std::map<std::string, std::string>& keywords = {}) {
2745 detail::_interpreter::get();
2746 PyObject* args = PyTuple_New(0);
2747 PyObject* kwargs = PyDict_New();
2748 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2749 if (
"text.usetex" == it->first)
2750 PyDict_SetItemString(kwargs, it->first.c_str(),
2751 PyLong_FromLong(std::stoi(it->second.c_str())));
2753 PyDict_SetItemString(kwargs, it->first.c_str(),
2754 PyString_FromString(it->second.c_str()));
2758 PyObject_GetAttrString(detail::_interpreter::get().s_python_function_rcparams,
"update");
2759 PyObject* res = PyObject_Call(update, args, kwargs);
2761 throw std::runtime_error(
"Call to rcParams.update() failed.");
2769 detail::_interpreter::get();
2771 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_clf,
2772 detail::_interpreter::get().s_python_empty_tuple);
2775 throw std::runtime_error(
"Call to clf() failed.");
2781 detail::_interpreter::get();
2783 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_cla,
2784 detail::_interpreter::get().s_python_empty_tuple);
2787 throw std::runtime_error(
"Call to cla() failed.");
2793 detail::_interpreter::get();
2795 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ion,
2796 detail::_interpreter::get().s_python_empty_tuple);
2799 throw std::runtime_error(
"Call to ion() failed.");
2804inline std::vector<std::array<double, 2>>
2805ginput(
const int numClicks = 1,
const std::map<std::string, std::string>& keywords = {}) {
2806 detail::_interpreter::get();
2808 PyObject* args = PyTuple_New(1);
2809 PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
2812 PyObject* kwargs = PyDict_New();
2813 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2814 it != keywords.end(); ++it) {
2815 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2819 PyObject_Call(detail::_interpreter::get().s_python_function_ginput, args, kwargs);
2824 throw std::runtime_error(
"Call to ginput() failed.");
2826 const size_t len = PyList_Size(res);
2827 std::vector<std::array<double, 2>> out;
2829 for (
size_t i = 0; i < len; i++) {
2830 PyObject* current = PyList_GetItem(res, i);
2831 std::array<double, 2> position;
2832 position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
2833 position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
2834 out.push_back(position);
2842inline void tight_layout() {
2843 detail::_interpreter::get();
2845 PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_tight_layout,
2846 detail::_interpreter::get().s_python_empty_tuple);
2849 throw std::runtime_error(
"Call to tight_layout() failed.");
2858template <
typename T>
2859using is_function =
typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type;
2864 typedef is_function<T> type;
2875 template <
typename U>
2876 static std::true_type test(...);
2879 template <
typename U>
static std::false_type test(
Check<
void (
Fallback::*)(), &U::operator()>*);
2882 typedef decltype(test<Derived>(
nullptr)) type;
2883 typedef decltype(&Fallback::operator()) dtype;
2884 static constexpr bool value = type::value;
2896 template <
typename IterableX,
typename IterableY>
2897 bool operator()(
const IterableX& x,
const IterableY& y,
const std::string& format) {
2898 detail::_interpreter::get();
2902 using std::distance;
2905 auto xs = distance(begin(x), end(x));
2906 auto ys = distance(begin(y), end(y));
2907 assert(xs == ys &&
"x and y data must have the same number of elements!");
2909 PyObject* xlist = PyList_New(xs);
2910 PyObject* ylist = PyList_New(ys);
2911 PyObject* pystring = PyString_FromString(format.c_str());
2913 auto itx = begin(x), ity = begin(y);
2914 for (
size_t i = 0; i < xs; ++i) {
2915 PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++));
2916 PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++));
2919 PyObject* plot_args = PyTuple_New(3);
2920 PyTuple_SetItem(plot_args, 0, xlist);
2921 PyTuple_SetItem(plot_args, 1, ylist);
2922 PyTuple_SetItem(plot_args, 2, pystring);
2925 PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
2927 Py_DECREF(plot_args);
2936 template <
typename Iterable,
typename Callable>
2937 bool operator()(
const Iterable& ticks,
const Callable& f,
const std::string& format) {
2938 if (begin(ticks) == end(ticks))
2943 std::vector<double> y;
2944 for (
auto x : ticks)
2953template <
typename... Args>
bool plot() {
2957template <
typename A,
typename B,
typename... Args>
2958bool plot(
const A& a,
const B& b,
const std::string& format, Args... args) {
2959 return detail::plot_impl<typename detail::is_callable<B>::type>()(a, b, format) &&
2967inline bool plot(
const std::vector<double>& x,
const std::vector<double>& y,
2968 const std::string& format =
"") {
2969 return plot<double, double>(x, y, format);
2972inline bool plot(
const std::vector<double>& y,
const std::string& format =
"") {
2973 return plot<double>(y, format);
2976inline bool plot(
const std::vector<double>& x,
const std::vector<double>& y,
2977 const std::map<std::string, std::string>& keywords) {
2978 return plot<double>(x, y, keywords);
2988 template <
typename Numeric>
2989 Plot(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
2990 const std::string& format =
"") {
2991 detail::_interpreter::get();
2993 assert(x.size() == y.size());
2995 PyObject* kwargs = PyDict_New();
2997 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
2999 PyObject* xarray = detail::get_array(x);
3000 PyObject* yarray = detail::get_array(y);
3002 PyObject* pystring = PyString_FromString(format.c_str());
3004 PyObject* plot_args = PyTuple_New(3);
3005 PyTuple_SetItem(plot_args, 0, xarray);
3006 PyTuple_SetItem(plot_args, 1, yarray);
3007 PyTuple_SetItem(plot_args, 2, pystring);
3010 PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
3013 Py_DECREF(plot_args);
3016 line = PyList_GetItem(res, 0);
3019 set_data_fct = PyObject_GetAttrString(line,
"set_data");
3028 Plot(
const std::string& name =
"",
const std::string& format =
"")
3029 : Plot(name, std::vector<double>(), std::vector<double>(), format) {}
3031 template <
typename Numeric>
3032 bool update(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y) {
3033 assert(x.size() == y.size());
3035 PyObject* xarray = detail::get_array(x);
3036 PyObject* yarray = detail::get_array(y);
3038 PyObject* plot_args = PyTuple_New(2);
3039 PyTuple_SetItem(plot_args, 0, xarray);
3040 PyTuple_SetItem(plot_args, 1, yarray);
3042 PyObject* res = PyObject_CallObject(set_data_fct, plot_args);
3051 bool clear() {
return update(std::vector<double>(), std::vector<double>()); }
3056 auto remove_fct = PyObject_GetAttrString(line,
"remove");
3057 PyObject* args = PyTuple_New(0);
3058 PyObject* res = PyObject_CallObject(remove_fct, args);
3065 ~Plot() { decref(); }
3072 Py_DECREF(set_data_fct);
3075 PyObject* line =
nullptr;
3076 PyObject* set_data_fct =
nullptr;
Definition matplotlibcpp.h:2873
Definition matplotlibcpp.h:2871
Definition matplotlibcpp.h:2868
Definition matplotlibcpp.h:2887
Definition matplotlibcpp.h:2893
Definition matplotlibcpp.h:338