41 #include "TBTK/Visualization/MatPlotLib/Interpreter.h"
56 # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
57 # include <numpy/arrayobject.h>
60 # include <opencv2/opencv.hpp>
61 # endif // WITH_OPENCV
67 # if CV_MAJOR_VERSION > 3
68 # define CV_BGR2RGB cv::COLOR_BGR2RGB
69 # define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA
71 #endif // WITHOUT_NUMPY
73 #if PY_MAJOR_VERSION >= 3
74 # define PyString_FromString PyUnicode_FromString
75 # define PyInt_FromLong PyLong_FromLong
76 # define PyString_FromString PyUnicode_FromString
81 namespace Visualization {
82 namespace MatPlotLib {
83 namespace matplotlibcpp {
86 inline void backend(
const std::string& name)
88 detail::s_backend = name;
91 inline bool annotate(std::string annotation,
double x,
double y)
93 PyObject * xy = PyTuple_New(2);
94 PyObject * str = PyString_FromString(annotation.c_str());
96 PyTuple_SetItem(xy,0,PyFloat_FromDouble(x));
97 PyTuple_SetItem(xy,1,PyFloat_FromDouble(y));
99 PyObject* kwargs = PyDict_New();
100 PyDict_SetItemString(kwargs,
"xy", xy);
102 PyObject* args = PyTuple_New(1);
103 PyTuple_SetItem(args, 0, str);
105 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_annotate, args, kwargs);
110 if(res) Py_DECREF(res);
115 #ifndef WITHOUT_NUMPY
117 template <
typename T>
struct select_npy_type {
const static NPY_TYPES type = NPY_NOTYPE; };
118 template <>
struct select_npy_type<double> {
const static NPY_TYPES type = NPY_DOUBLE; };
119 template <>
struct select_npy_type<float> {
const static NPY_TYPES type = NPY_FLOAT; };
120 template <>
struct select_npy_type<bool> {
const static NPY_TYPES type = NPY_BOOL; };
121 template <>
struct select_npy_type<int8_t> {
const static NPY_TYPES type = NPY_INT8; };
122 template <>
struct select_npy_type<int16_t> {
const static NPY_TYPES type = NPY_SHORT; };
123 template <>
struct select_npy_type<int32_t> {
const static NPY_TYPES type = NPY_INT; };
124 template <>
struct select_npy_type<int64_t> {
const static NPY_TYPES type = NPY_INT64; };
125 template <>
struct select_npy_type<uint8_t> {
const static NPY_TYPES type = NPY_UINT8; };
126 template <>
struct select_npy_type<uint16_t> {
const static NPY_TYPES type = NPY_USHORT; };
127 template <>
struct select_npy_type<uint32_t> {
const static NPY_TYPES type = NPY_ULONG; };
128 template <>
struct select_npy_type<uint64_t> {
const static NPY_TYPES type = NPY_UINT64; };
130 template<
typename Numeric>
131 PyObject* get_array(
const std::vector<Numeric>& v)
133 detail::Interpreter::get();
134 NPY_TYPES type = select_npy_type<Numeric>::type;
135 if (type == NPY_NOTYPE)
137 std::vector<double> vd(v.size());
138 npy_intp vsize = v.size();
139 std::copy(v.begin(),v.end(),vd.begin());
140 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (
void*)(vd.data()));
144 npy_intp vsize = v.size();
145 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (
void*)(v.data()));
149 template<
typename Numeric>
150 PyObject* get_2darray(
const std::vector<::std::vector<Numeric>>& v)
152 detail::Interpreter::get();
153 if (v.size() < 1)
throw std::runtime_error(
"get_2d_array v too small");
155 npy_intp vsize[2] = {
static_cast<npy_intp
>(v.size()),
156 static_cast<npy_intp
>(v[0].size())};
158 PyArrayObject *varray =
159 (PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
161 double *vd_begin =
static_cast<double *
>(PyArray_DATA(varray));
163 for (const ::std::vector<Numeric> &v_row : v) {
164 if (v_row.size() !=
static_cast<size_t>(vsize[1]))
165 throw std::runtime_error(
"Missmatched array size");
166 std::copy(v_row.begin(), v_row.end(), vd_begin);
167 vd_begin += vsize[1];
170 return reinterpret_cast<PyObject *
>(varray);
173 template<
typename Numeric>
174 PyObject* get_3darray(
const std::vector<std::vector<::std::vector<Numeric>>>& v)
176 detail::Interpreter::get();
177 if (v.size() < 1)
throw std::runtime_error(
"get_3d_array v too small");
178 if (v[0].size() < 1)
throw std::runtime_error(
"get_3d_array v too small");
179 for(
unsigned int n = 0; n < v.size(); n++)
180 if (v[n].size() != v[0].size())
throw std::runtime_error(
"get_3d_array v too small");
182 npy_intp vsize[3] = {
183 static_cast<npy_intp
>(v.size()),
184 static_cast<npy_intp
>(v[0].size()),
185 static_cast<npy_intp
>(v[0][0].size())
188 PyArrayObject *varray =
189 (PyArrayObject *)PyArray_SimpleNew(3, vsize, NPY_DOUBLE);
191 double *vd_begin =
static_cast<double *
>(PyArray_DATA(varray));
193 for (const ::std::vector<::std::vector<Numeric>> &v_x : v) {
194 if (v_x.size() !=
static_cast<size_t>(vsize[1]))
195 throw std::runtime_error(
"Missmatched array size");
196 for (const ::std::vector<Numeric> &v_y : v_x) {
197 std::copy(v_y.begin(), v_y.end(), vd_begin);
198 vd_begin += vsize[2];
202 return reinterpret_cast<PyObject *
>(varray);
205 #else // fallback if we don't have numpy: copy every element of the given vector
207 template<
typename Numeric>
208 PyObject* get_array(
const std::vector<Numeric>& v)
210 PyObject* list = PyList_New(v.size());
211 for(
size_t i = 0; i < v.size(); ++i) {
212 PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
217 #endif // WITHOUT_NUMPY
219 template<
typename Numeric>
220 bool plot(
const std::vector<Numeric> &x,
const std::vector<Numeric> &y,
const std::map<std::string, std::string>& keywords)
222 assert(x.size() == y.size());
225 PyObject* xarray = get_array(x);
226 PyObject* yarray = get_array(y);
229 PyObject* args = PyTuple_New(2);
230 PyTuple_SetItem(args, 0, xarray);
231 PyTuple_SetItem(args, 1, yarray);
234 PyObject* kwargs = PyDict_New();
235 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
237 if(it->first.compare(
"linewidth") == 0){
238 char value[it->second.size()+1];
239 for(
unsigned int n = 0; n < it->second.size(); n++)
240 value[n] = it->second[n];
241 value[it->second.size()] =
'\0';
242 PyDict_SetItemString(kwargs, it->first.c_str(), PyInt_FromString(value,
nullptr, 0));
245 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
249 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_plot, args, kwargs);
253 if(res) Py_DECREF(res);
260 #ifndef WITHOUT_NUMPY
261 template <
typename Numeric>
262 void plot_surface(
const std::vector<::std::vector<Numeric>> &x,
263 const std::vector<::std::vector<Numeric>> &y,
264 const std::vector<::std::vector<Numeric>> &z,
265 const std::map<std::string, std::string> &keywords =
266 std::map<std::string, std::string>())
288 detail::Interpreter::get().initializeMPLToolkits();
290 assert(x.size() == y.size());
291 assert(y.size() == z.size());
294 PyObject *xarray = get_2darray(x);
295 PyObject *yarray = get_2darray(y);
296 PyObject *zarray = get_2darray(z);
299 PyObject *args = PyTuple_New(3);
300 PyTuple_SetItem(args, 0, xarray);
301 PyTuple_SetItem(args, 1, yarray);
302 PyTuple_SetItem(args, 2, zarray);
305 PyObject *kwargs = PyDict_New();
306 PyDict_SetItemString(kwargs,
"rstride", PyInt_FromLong(1));
307 PyDict_SetItemString(kwargs,
"cstride", PyInt_FromLong(1));
309 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
310 detail::Interpreter::get().s_python_colormap,
"coolwarm");
312 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
314 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
315 it != keywords.end(); ++it) {
316 PyDict_SetItemString(kwargs, it->first.c_str(),
317 PyString_FromString(it->second.c_str()));
322 PyObject_CallObject(detail::Interpreter::get().s_python_function_figure,
323 detail::Interpreter::get().s_python_empty_tuple);
324 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
326 PyObject *gca_kwargs = PyDict_New();
327 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
329 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
330 if (!gca)
throw std::runtime_error(
"No gca");
332 PyObject *axis = PyObject_Call(
333 gca, detail::Interpreter::get().s_python_empty_tuple, gca_kwargs);
335 if (!axis)
throw std::runtime_error(
"No axis");
339 Py_DECREF(gca_kwargs);
341 PyObject *plot_surface = PyObject_GetAttrString(axis,
"plot_surface");
342 if (!plot_surface)
throw std::runtime_error(
"No surface");
343 Py_INCREF(plot_surface);
344 PyObject *res = PyObject_Call(plot_surface, args, kwargs);
345 if (!res)
throw std::runtime_error(
"failed surface");
346 Py_DECREF(plot_surface);
351 if (res) Py_DECREF(res);
354 template <
typename Numeric>
356 const std::vector<std::vector<::std::vector<Numeric>>> &x,
357 const std::vector<std::vector<::std::vector<Numeric>>> &y,
358 const std::vector<std::vector<::std::vector<Numeric>>> &z,
359 const std::vector<std::vector<::std::vector<Numeric>>> &u,
360 const std::vector<std::vector<::std::vector<Numeric>>> &v,
361 const std::vector<std::vector<::std::vector<Numeric>>> &w,
362 const std::map<std::string, std::string> &keywords =
363 std::map<std::string, std::string>()
369 detail::Interpreter::get().initializeMPLToolkits();
371 assert(x.size() == y.size());
372 assert(x.size() == z.size());
373 assert(x.size() == u.size());
374 assert(x.size() == v.size());
375 assert(x.size() == z.size());
376 for(
unsigned int n = 0; n < x.size(); n++){
377 assert(x[0].size() == x[n].size());
378 assert(x[0].size() == y[n].size());
379 assert(x[0].size() == z[n].size());
380 assert(x[0].size() == u[n].size());
381 assert(x[0].size() == v[n].size());
382 assert(x[0].size() == w[n].size());
383 for(
unsigned int c = 0; c < x[0].size(); c++){
384 assert(x[n][0].size() == x[n][c].size());
385 assert(x[n][0].size() == y[n][c].size());
386 assert(x[n][0].size() == z[n][c].size());
387 assert(x[n][0].size() == u[n][c].size());
388 assert(x[n][0].size() == v[n][c].size());
389 assert(x[n][0].size() == w[n][c].size());
394 PyObject *xarray = get_3darray(x);
395 PyObject *yarray = get_3darray(y);
396 PyObject *zarray = get_3darray(z);
397 PyObject *uarray = get_3darray(u);
398 PyObject *varray = get_3darray(v);
399 PyObject *warray = get_3darray(w);
402 PyObject *args = PyTuple_New(6);
403 PyTuple_SetItem(args, 0, xarray);
404 PyTuple_SetItem(args, 1, yarray);
405 PyTuple_SetItem(args, 2, zarray);
406 PyTuple_SetItem(args, 3, uarray);
407 PyTuple_SetItem(args, 4, varray);
408 PyTuple_SetItem(args, 5, warray);
411 PyObject *kwargs = PyDict_New();
420 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
421 it != keywords.end(); ++it) {
422 if(it->first.compare(
"length") == 0){
423 char value[it->second.size()+1];
424 for(
unsigned int n = 0; n < it->second.size(); n++)
425 value[n] = it->second[n];
426 value[it->second.size()] =
'\0';
427 PyDict_SetItemString(
430 PyFloat_FromString(PyString_FromString(value))
434 PyDict_SetItemString(
437 PyString_FromString(it->second.c_str())
444 PyObject_CallObject(detail::Interpreter::get().s_python_function_figure,
445 detail::Interpreter::get().s_python_empty_tuple);
446 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
448 PyObject *gca_kwargs = PyDict_New();
449 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
451 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
452 if (!gca)
throw std::runtime_error(
"No gca");
454 PyObject *axis = PyObject_Call(
455 gca, detail::Interpreter::get().s_python_empty_tuple, gca_kwargs);
457 if (!axis)
throw std::runtime_error(
"No axis");
461 Py_DECREF(gca_kwargs);
463 PyObject *quiver = PyObject_GetAttrString(axis,
"quiver");
464 if (!quiver)
throw std::runtime_error(
"No quiver");
466 PyObject *res = PyObject_Call(quiver, args, kwargs);
467 if (!res)
throw std::runtime_error(
"failed quiver");
473 if (res) Py_DECREF(res);
477 inline void view_init(
478 const std::map<std::string, std::string> &keywords =
479 std::map<std::string, std::string>())
481 PyObject *axis = PyObject_CallObject(
482 detail::Interpreter::get().s_python_function_gca,
483 detail::Interpreter::get().s_python_empty_tuple
486 PyObject *view_init_kwargs = PyDict_New();
487 std::string elev = keywords.at(
"elev");
488 std::string azim = keywords.at(
"azim");
489 PyDict_SetItemString(view_init_kwargs,
"elev", PyInt_FromString((
char*)elev.c_str(),
nullptr, 0));
490 PyDict_SetItemString(view_init_kwargs,
"azim", PyInt_FromString((
char*)azim.c_str(),
nullptr, 0));
492 PyObject *view_init = PyObject_GetAttrString(axis,
"view_init");
493 if (!view_init)
throw std::runtime_error(
"No view_init");
494 Py_INCREF(view_init);
495 PyObject *res = PyObject_Call(
497 detail::Interpreter::get().s_python_empty_tuple,
500 if (!res)
throw std::runtime_error(
"failed view_init");
501 Py_DECREF(view_init);
502 if (res) Py_DECREF(res);
506 #endif // WITHOUT_NUMPY
508 template <
typename Numeric>
510 const std::vector<::std::vector<Numeric>> &x,
511 const std::vector<::std::vector<Numeric>> &y,
512 const std::vector<::std::vector<Numeric>> &z,
513 unsigned int levels = 8,
514 const std::map<std::string, std::string> &keywords =
515 std::map<std::string, std::string>()
517 assert(x.size() == y.size());
518 assert(y.size() == z.size());
521 PyObject *xarray = get_2darray(x);
522 PyObject *yarray = get_2darray(y);
523 PyObject *zarray = get_2darray(z);
526 PyObject *args = PyTuple_New(4);
527 PyTuple_SetItem(args, 0, xarray);
528 PyTuple_SetItem(args, 1, yarray);
529 PyTuple_SetItem(args, 2, zarray);
530 PyTuple_SetItem(args, 3, PyInt_FromLong(levels));
533 PyObject *kwargs = PyDict_New();
534 PyDict_SetItemString(kwargs,
"rstride", PyInt_FromLong(1));
535 PyDict_SetItemString(kwargs,
"cstride", PyInt_FromLong(1));
537 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
538 detail::Interpreter::get().s_python_colormap,
"coolwarm");
540 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
542 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
543 it != keywords.end(); ++it) {
544 PyDict_SetItemString(kwargs, it->first.c_str(),
545 PyString_FromString(it->second.c_str()));
550 PyObject_CallObject(detail::Interpreter::get().s_python_function_figure,
551 detail::Interpreter::get().s_python_empty_tuple);
552 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
554 PyObject *gca_kwargs = PyDict_New();
557 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
558 if (!gca)
throw std::runtime_error(
"No gca");
560 PyObject *axis = PyObject_Call(
561 gca, detail::Interpreter::get().s_python_empty_tuple, gca_kwargs);
563 if (!axis)
throw std::runtime_error(
"No axis");
567 Py_DECREF(gca_kwargs);
569 PyObject *contourf = PyObject_GetAttrString(axis,
"contourf");
570 if (!contourf)
throw std::runtime_error(
"No surface");
572 PyObject *res = PyObject_Call(contourf, args, kwargs);
573 if (!res)
throw std::runtime_error(
"failed surface");
575 PyObject *colorbar_kwargs = PyDict_New();
576 PyDict_SetItemString(colorbar_kwargs,
"mappable", res);
577 PyDict_SetItemString(colorbar_kwargs,
"ax", axis);
578 PyObject *colorbar = PyObject_GetAttrString(fig,
"colorbar");
579 if(!colorbar)
throw std::runtime_error(
"No colorbar");
581 PyObject *res2 = PyObject_Call(
583 detail::Interpreter::get().s_python_empty_tuple,
586 if(!res2)
throw std::runtime_error(
"failed colorbar");
595 if (res) Py_DECREF(res);
598 template<
typename Numeric>
599 bool stem(
const std::vector<Numeric> &x,
const std::vector<Numeric> &y,
const std::map<std::string, std::string>& keywords)
601 assert(x.size() == y.size());
604 PyObject* xarray = get_array(x);
605 PyObject* yarray = get_array(y);
608 PyObject* args = PyTuple_New(2);
609 PyTuple_SetItem(args, 0, xarray);
610 PyTuple_SetItem(args, 1, yarray);
613 PyObject* kwargs = PyDict_New();
614 for (std::map<std::string, std::string>::const_iterator it =
615 keywords.begin(); it != keywords.end(); ++it) {
616 PyDict_SetItemString(kwargs, it->first.c_str(),
617 PyString_FromString(it->second.c_str()));
620 PyObject* res = PyObject_Call(
621 detail::Interpreter::get().s_python_function_stem, args, kwargs);
631 template<
typename Numeric >
632 bool fill(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::map<std::string, std::string>& keywords)
634 assert(x.size() == y.size());
637 PyObject* xarray = get_array(x);
638 PyObject* yarray = get_array(y);
641 PyObject* args = PyTuple_New(2);
642 PyTuple_SetItem(args, 0, xarray);
643 PyTuple_SetItem(args, 1, yarray);
646 PyObject* kwargs = PyDict_New();
647 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
648 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
651 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_fill, args, kwargs);
656 if (res) Py_DECREF(res);
661 template<
typename Numeric >
662 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)
664 assert(x.size() == y1.size());
665 assert(x.size() == y2.size());
668 PyObject* xarray = get_array(x);
669 PyObject* y1array = get_array(y1);
670 PyObject* y2array = get_array(y2);
673 PyObject* args = PyTuple_New(3);
674 PyTuple_SetItem(args, 0, xarray);
675 PyTuple_SetItem(args, 1, y1array);
676 PyTuple_SetItem(args, 2, y2array);
679 PyObject* kwargs = PyDict_New();
680 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it) {
681 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
684 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_fill_between, args, kwargs);
688 if(res) Py_DECREF(res);
693 template<
typename Numeric>
694 bool hist(
const std::vector<Numeric>& y,
long bins=10,std::string color=
"b",
695 double alpha=1.0,
bool cumulative=
false)
698 PyObject* yarray = get_array(y);
700 PyObject* kwargs = PyDict_New();
701 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
702 PyDict_SetItemString(kwargs,
"color", PyString_FromString(color.c_str()));
703 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
704 PyDict_SetItemString(kwargs,
"cumulative", cumulative ? Py_True : Py_False);
706 PyObject* plot_args = PyTuple_New(1);
708 PyTuple_SetItem(plot_args, 0, yarray);
711 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_hist, plot_args, kwargs);
714 Py_DECREF(plot_args);
716 if(res) Py_DECREF(res);
721 #ifndef WITHOUT_NUMPY
723 inline void imshow(
void *ptr,
const NPY_TYPES type,
const int rows,
const int columns,
const int colors,
const std::map<std::string, std::string> &keywords)
725 assert(type == NPY_UINT8 || type == NPY_FLOAT);
726 assert(colors == 1 || colors == 3 || colors == 4);
728 detail::Interpreter::get();
731 npy_intp dims[3] = { rows, columns, colors };
732 PyObject *args = PyTuple_New(1);
733 PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims, type, ptr));
736 PyObject* kwargs = PyDict_New();
737 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
739 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
742 PyObject *res = PyObject_Call(detail::Interpreter::get().s_python_function_imshow, args, kwargs);
746 throw std::runtime_error(
"Call to imshow() failed");
751 inline void imshow(
const unsigned char *ptr,
const int rows,
const int columns,
const int colors,
const std::map<std::string, std::string> &keywords = {})
753 internal::imshow((
void *) ptr, NPY_UINT8, rows, columns, colors, keywords);
756 inline void imshow(
const float *ptr,
const int rows,
const int columns,
const int colors,
const std::map<std::string, std::string> &keywords = {})
758 internal::imshow((
void *) ptr, NPY_FLOAT, rows, columns, colors, keywords);
762 void imshow(
const cv::Mat &image,
const std::map<std::string, std::string> &keywords = {})
766 NPY_TYPES npy_type = NPY_UINT8;
767 switch (image.type() & CV_MAT_DEPTH_MASK) {
773 npy_type = NPY_FLOAT;
776 image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
780 switch (image2.channels()) {
782 cv::cvtColor(image2, image2, CV_BGR2RGB);
785 cv::cvtColor(image2, image2, CV_BGRA2RGBA);
788 internal::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords);
790 #endif // WITH_OPENCV
791 #endif // WITHOUT_NUMPY
793 template<
typename NumericX,
typename NumericY>
794 bool scatter(
const std::vector<NumericX>& x,
795 const std::vector<NumericY>& y,
798 assert(x.size() == y.size());
800 PyObject* xarray = get_array(x);
801 PyObject* yarray = get_array(y);
803 PyObject* kwargs = PyDict_New();
804 PyDict_SetItemString(kwargs,
"s", PyLong_FromLong(s));
806 PyObject* plot_args = PyTuple_New(2);
807 PyTuple_SetItem(plot_args, 0, xarray);
808 PyTuple_SetItem(plot_args, 1, yarray);
810 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_scatter, plot_args, kwargs);
812 Py_DECREF(plot_args);
814 if(res) Py_DECREF(res);
819 template <
typename Numeric>
820 bool bar(
const std::vector<Numeric> & x,
821 const std::vector<Numeric> & y,
822 std::string ec =
"black",
823 std::string ls =
"-",
825 const std::map<std::string, std::string> & keywords = {}) {
826 PyObject * xarray = get_array(x);
827 PyObject * yarray = get_array(y);
829 PyObject * kwargs = PyDict_New();
831 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
832 PyDict_SetItemString(kwargs,
"ls", PyString_FromString(ls.c_str()));
833 PyDict_SetItemString(kwargs,
"lw", PyFloat_FromDouble(lw));
835 for (std::map<std::string, std::string>::const_iterator it =
837 it != keywords.end();
839 PyDict_SetItemString(
840 kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
843 PyObject * plot_args = PyTuple_New(2);
844 PyTuple_SetItem(plot_args, 0, xarray);
845 PyTuple_SetItem(plot_args, 1, yarray);
847 PyObject * res = PyObject_Call(
848 detail::Interpreter::get().s_python_function_bar, plot_args, kwargs);
850 Py_DECREF(plot_args);
852 if (res) Py_DECREF(res);
857 template <
typename Numeric>
858 bool bar(
const std::vector<Numeric> & y,
859 std::string ec =
"black",
860 std::string ls =
"-",
862 const std::map<std::string, std::string> & keywords = {}) {
863 using T =
typename std::remove_reference<decltype(y)>::type::value_type;
866 for (std::size_t i = 0; i < y.size(); i++) { x.push_back(i); }
868 return bar(x, y, ec, ls, lw, keywords);
871 inline bool subplots_adjust(
const std::map<std::string, double>& keywords = {})
874 PyObject* kwargs = PyDict_New();
875 for (std::map<std::string, double>::const_iterator it =
876 keywords.begin(); it != keywords.end(); ++it) {
877 PyDict_SetItemString(kwargs, it->first.c_str(),
878 PyFloat_FromDouble(it->second));
882 PyObject* plot_args = PyTuple_New(0);
884 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_subplots_adjust, plot_args, kwargs);
886 Py_DECREF(plot_args);
888 if(res) Py_DECREF(res);
893 template<
typename Numeric>
894 bool named_hist(std::string label,
const std::vector<Numeric>& y,
long bins=10, std::string color=
"b",
double alpha=1.0)
896 PyObject* yarray = get_array(y);
898 PyObject* kwargs = PyDict_New();
899 PyDict_SetItemString(kwargs,
"label", PyString_FromString(label.c_str()));
900 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
901 PyDict_SetItemString(kwargs,
"color", PyString_FromString(color.c_str()));
902 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
905 PyObject* plot_args = PyTuple_New(1);
906 PyTuple_SetItem(plot_args, 0, yarray);
908 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_hist, plot_args, kwargs);
910 Py_DECREF(plot_args);
912 if(res) Py_DECREF(res);
917 template<
typename NumericX,
typename NumericY>
918 bool plot(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
const std::string& s =
"")
920 assert(x.size() == y.size());
922 PyObject* xarray = get_array(x);
923 PyObject* yarray = get_array(y);
925 PyObject* pystring = PyString_FromString(s.c_str());
927 PyObject* plot_args = PyTuple_New(3);
928 PyTuple_SetItem(plot_args, 0, xarray);
929 PyTuple_SetItem(plot_args, 1, yarray);
930 PyTuple_SetItem(plot_args, 2, pystring);
932 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_plot, plot_args);
934 Py_DECREF(plot_args);
935 if(res) Py_DECREF(res);
940 template<
typename NumericX,
typename NumericY,
typename NumericU,
typename NumericW>
941 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 = {})
943 assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size());
945 PyObject* xarray = get_array(x);
946 PyObject* yarray = get_array(y);
947 PyObject* uarray = get_array(u);
948 PyObject* warray = get_array(w);
950 PyObject* plot_args = PyTuple_New(4);
951 PyTuple_SetItem(plot_args, 0, xarray);
952 PyTuple_SetItem(plot_args, 1, yarray);
953 PyTuple_SetItem(plot_args, 2, uarray);
954 PyTuple_SetItem(plot_args, 3, warray);
957 PyObject* kwargs = PyDict_New();
958 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
960 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
963 PyObject* res = PyObject_Call(
964 detail::Interpreter::get().s_python_function_quiver, plot_args, kwargs);
967 Py_DECREF(plot_args);
974 template<
typename NumericX,
typename NumericY>
975 bool stem(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
const std::string& s =
"")
977 assert(x.size() == y.size());
979 PyObject* xarray = get_array(x);
980 PyObject* yarray = get_array(y);
982 PyObject* pystring = PyString_FromString(s.c_str());
984 PyObject* plot_args = PyTuple_New(3);
985 PyTuple_SetItem(plot_args, 0, xarray);
986 PyTuple_SetItem(plot_args, 1, yarray);
987 PyTuple_SetItem(plot_args, 2, pystring);
989 PyObject* res = PyObject_CallObject(
990 detail::Interpreter::get().s_python_function_stem, plot_args);
992 Py_DECREF(plot_args);
999 template<
typename NumericX,
typename NumericY>
1000 bool semilogx(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
const std::string& s =
"")
1002 assert(x.size() == y.size());
1004 PyObject* xarray = get_array(x);
1005 PyObject* yarray = get_array(y);
1007 PyObject* pystring = PyString_FromString(s.c_str());
1009 PyObject* plot_args = PyTuple_New(3);
1010 PyTuple_SetItem(plot_args, 0, xarray);
1011 PyTuple_SetItem(plot_args, 1, yarray);
1012 PyTuple_SetItem(plot_args, 2, pystring);
1014 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_semilogx, plot_args);
1016 Py_DECREF(plot_args);
1017 if(res) Py_DECREF(res);
1022 template<
typename NumericX,
typename NumericY>
1023 bool semilogy(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
const std::string& s =
"")
1025 assert(x.size() == y.size());
1027 PyObject* xarray = get_array(x);
1028 PyObject* yarray = get_array(y);
1030 PyObject* pystring = PyString_FromString(s.c_str());
1032 PyObject* plot_args = PyTuple_New(3);
1033 PyTuple_SetItem(plot_args, 0, xarray);
1034 PyTuple_SetItem(plot_args, 1, yarray);
1035 PyTuple_SetItem(plot_args, 2, pystring);
1037 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_semilogy, plot_args);
1039 Py_DECREF(plot_args);
1040 if(res) Py_DECREF(res);
1045 template<
typename NumericX,
typename NumericY>
1046 bool loglog(
const std::vector<NumericX>& x,
const std::vector<NumericY>& y,
const std::string& s =
"")
1048 assert(x.size() == y.size());
1050 PyObject* xarray = get_array(x);
1051 PyObject* yarray = get_array(y);
1053 PyObject* pystring = PyString_FromString(s.c_str());
1055 PyObject* plot_args = PyTuple_New(3);
1056 PyTuple_SetItem(plot_args, 0, xarray);
1057 PyTuple_SetItem(plot_args, 1, yarray);
1058 PyTuple_SetItem(plot_args, 2, pystring);
1060 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_loglog, plot_args);
1062 Py_DECREF(plot_args);
1063 if(res) Py_DECREF(res);
1068 template<
typename NumericX,
typename NumericY>
1069 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 = {})
1071 assert(x.size() == y.size());
1073 PyObject* xarray = get_array(x);
1074 PyObject* yarray = get_array(y);
1075 PyObject* yerrarray = get_array(yerr);
1078 PyObject* kwargs = PyDict_New();
1079 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1081 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1084 PyDict_SetItemString(kwargs,
"yerr", yerrarray);
1086 PyObject *plot_args = PyTuple_New(2);
1087 PyTuple_SetItem(plot_args, 0, xarray);
1088 PyTuple_SetItem(plot_args, 1, yarray);
1090 PyObject *res = PyObject_Call(detail::Interpreter::get().s_python_function_errorbar, plot_args, kwargs);
1093 Py_DECREF(plot_args);
1098 throw std::runtime_error(
"Call to errorbar() failed.");
1103 template<
typename Numeric>
1104 bool named_plot(
const std::string& name,
const std::vector<Numeric>& y,
const std::string& format =
"")
1106 PyObject* kwargs = PyDict_New();
1107 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1109 PyObject* yarray = get_array(y);
1111 PyObject* pystring = PyString_FromString(format.c_str());
1113 PyObject* plot_args = PyTuple_New(2);
1115 PyTuple_SetItem(plot_args, 0, yarray);
1116 PyTuple_SetItem(plot_args, 1, pystring);
1118 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_plot, plot_args, kwargs);
1121 Py_DECREF(plot_args);
1122 if (res) Py_DECREF(res);
1127 template<
typename Numeric>
1128 bool named_plot(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::string& format =
"")
1130 PyObject* kwargs = PyDict_New();
1131 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1133 PyObject* xarray = get_array(x);
1134 PyObject* yarray = get_array(y);
1136 PyObject* pystring = PyString_FromString(format.c_str());
1138 PyObject* plot_args = PyTuple_New(3);
1139 PyTuple_SetItem(plot_args, 0, xarray);
1140 PyTuple_SetItem(plot_args, 1, yarray);
1141 PyTuple_SetItem(plot_args, 2, pystring);
1143 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_plot, plot_args, kwargs);
1146 Py_DECREF(plot_args);
1147 if (res) Py_DECREF(res);
1152 template<
typename Numeric>
1153 bool named_semilogx(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::string& format =
"")
1155 PyObject* kwargs = PyDict_New();
1156 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1158 PyObject* xarray = get_array(x);
1159 PyObject* yarray = get_array(y);
1161 PyObject* pystring = PyString_FromString(format.c_str());
1163 PyObject* plot_args = PyTuple_New(3);
1164 PyTuple_SetItem(plot_args, 0, xarray);
1165 PyTuple_SetItem(plot_args, 1, yarray);
1166 PyTuple_SetItem(plot_args, 2, pystring);
1168 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_semilogx, plot_args, kwargs);
1171 Py_DECREF(plot_args);
1172 if (res) Py_DECREF(res);
1177 template<
typename Numeric>
1178 bool named_semilogy(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::string& format =
"")
1180 PyObject* kwargs = PyDict_New();
1181 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1183 PyObject* xarray = get_array(x);
1184 PyObject* yarray = get_array(y);
1186 PyObject* pystring = PyString_FromString(format.c_str());
1188 PyObject* plot_args = PyTuple_New(3);
1189 PyTuple_SetItem(plot_args, 0, xarray);
1190 PyTuple_SetItem(plot_args, 1, yarray);
1191 PyTuple_SetItem(plot_args, 2, pystring);
1193 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_semilogy, plot_args, kwargs);
1196 Py_DECREF(plot_args);
1197 if (res) Py_DECREF(res);
1202 template<
typename Numeric>
1203 bool named_loglog(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::string& format =
"")
1205 PyObject* kwargs = PyDict_New();
1206 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1208 PyObject* xarray = get_array(x);
1209 PyObject* yarray = get_array(y);
1211 PyObject* pystring = PyString_FromString(format.c_str());
1213 PyObject* plot_args = PyTuple_New(3);
1214 PyTuple_SetItem(plot_args, 0, xarray);
1215 PyTuple_SetItem(plot_args, 1, yarray);
1216 PyTuple_SetItem(plot_args, 2, pystring);
1217 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_loglog, plot_args, kwargs);
1220 Py_DECREF(plot_args);
1221 if (res) Py_DECREF(res);
1226 template<
typename Numeric>
1227 bool plot(
const std::vector<Numeric>& y,
const std::string& format =
"")
1229 std::vector<Numeric> x(y.size());
1230 for(
size_t i=0; i<x.size(); ++i) x.at(i) = i;
1231 return plot(x,y,format);
1234 template<
typename Numeric>
1235 bool plot(
const std::vector<Numeric>& y,
const std::map<std::string, std::string>& keywords)
1237 std::vector<Numeric> x(y.size());
1238 for(
size_t i=0; i<x.size(); ++i) x.at(i) = i;
1239 return plot(x,y,keywords);
1242 template<
typename Numeric>
1243 bool stem(
const std::vector<Numeric>& y,
const std::string& format =
"")
1245 std::vector<Numeric> x(y.size());
1246 for (
size_t i = 0; i < x.size(); ++i) x.at(i) = i;
1247 return stem(x, y, format);
1250 template<
typename Numeric>
1251 void text(Numeric x, Numeric y,
const std::string& s =
"")
1253 PyObject* args = PyTuple_New(3);
1254 PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
1255 PyTuple_SetItem(args, 1, PyFloat_FromDouble(y));
1256 PyTuple_SetItem(args, 2, PyString_FromString(s.c_str()));
1258 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_text, args);
1259 if(!res)
throw std::runtime_error(
"Call to text() failed.");
1266 inline long figure(
long number = -1)
1270 res = PyObject_CallObject(detail::Interpreter::get().s_python_function_figure, detail::Interpreter::get().s_python_empty_tuple);
1275 detail::Interpreter::get();
1277 PyObject *args = PyTuple_New(1);
1278 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1279 res = PyObject_CallObject(detail::Interpreter::get().s_python_function_figure, args);
1283 if(!res)
throw std::runtime_error(
"Call to figure() failed.");
1285 PyObject* num = PyObject_GetAttrString(res,
"number");
1286 if (!num)
throw std::runtime_error(
"Could not get number attribute of figure object");
1287 const long figureNumber = PyLong_AsLong(num);
1292 return figureNumber;
1295 inline bool fignum_exists(
long number)
1298 detail::Interpreter::get();
1300 PyObject *args = PyTuple_New(1);
1301 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1302 PyObject *res = PyObject_CallObject(detail::Interpreter::get().s_python_function_fignum_exists, args);
1303 if(!res)
throw std::runtime_error(
"Call to fignum_exists() failed.");
1305 bool ret = PyObject_IsTrue(res);
1312 inline void figure_size(
size_t w,
size_t h)
1315 detail::Interpreter::get();
1317 const size_t dpi = 100;
1318 PyObject* size = PyTuple_New(2);
1319 PyTuple_SetItem(size, 0, PyFloat_FromDouble((
double)w / dpi));
1320 PyTuple_SetItem(size, 1, PyFloat_FromDouble((
double)h / dpi));
1322 PyObject* kwargs = PyDict_New();
1323 PyDict_SetItemString(kwargs,
"figsize", size);
1324 PyDict_SetItemString(kwargs,
"dpi", PyLong_FromSize_t(dpi));
1326 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_figure,
1327 detail::Interpreter::get().s_python_empty_tuple, kwargs);
1331 if(!res)
throw std::runtime_error(
"Call to figure_size() failed.");
1335 inline void legend()
1337 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_legend, detail::Interpreter::get().s_python_empty_tuple);
1338 if(!res)
throw std::runtime_error(
"Call to legend() failed.");
1343 template<
typename Numeric>
1344 void ylim(Numeric left, Numeric right)
1346 PyObject* list = PyList_New(2);
1347 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
1348 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
1350 PyObject* args = PyTuple_New(1);
1351 PyTuple_SetItem(args, 0, list);
1353 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_ylim, args);
1354 if(!res)
throw std::runtime_error(
"Call to ylim() failed.");
1360 template<
typename Numeric>
1361 void xlim(Numeric left, Numeric right)
1363 PyObject* list = PyList_New(2);
1364 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
1365 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
1367 PyObject* args = PyTuple_New(1);
1368 PyTuple_SetItem(args, 0, list);
1370 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_xlim, args);
1371 if(!res)
throw std::runtime_error(
"Call to xlim() failed.");
1378 inline double* xlim()
1380 PyObject* args = PyTuple_New(0);
1381 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_xlim, args);
1382 PyObject* left = PyTuple_GetItem(res,0);
1383 PyObject* right = PyTuple_GetItem(res,1);
1385 double* arr =
new double[2];
1386 arr[0] = PyFloat_AsDouble(left);
1387 arr[1] = PyFloat_AsDouble(right);
1389 if(!res)
throw std::runtime_error(
"Call to xlim() failed.");
1396 inline double* ylim()
1398 PyObject* args = PyTuple_New(0);
1399 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_ylim, args);
1400 PyObject* left = PyTuple_GetItem(res,0);
1401 PyObject* right = PyTuple_GetItem(res,1);
1403 double* arr =
new double[2];
1404 arr[0] = PyFloat_AsDouble(left);
1405 arr[1] = PyFloat_AsDouble(right);
1407 if(!res)
throw std::runtime_error(
"Call to ylim() failed.");
1413 template<
typename Numeric>
1414 inline void xticks(
const std::vector<Numeric> &ticks,
const std::vector<std::string> &labels = {},
const std::map<std::string, std::string>& keywords = {})
1416 assert(labels.size() == 0 || ticks.size() == labels.size());
1419 PyObject* ticksarray = get_array(ticks);
1422 if(labels.size() == 0) {
1424 args = PyTuple_New(1);
1425 PyTuple_SetItem(args, 0, ticksarray);
1428 PyObject* labelstuple = PyTuple_New(labels.size());
1429 for (
size_t i = 0; i < labels.size(); i++)
1430 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
1433 args = PyTuple_New(2);
1434 PyTuple_SetItem(args, 0, ticksarray);
1435 PyTuple_SetItem(args, 1, labelstuple);
1439 PyObject* kwargs = PyDict_New();
1440 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1442 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1445 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_xticks, args, kwargs);
1449 if(!res)
throw std::runtime_error(
"Call to xticks() failed");
1454 template<
typename Numeric>
1455 inline void xticks(
const std::vector<Numeric> &ticks,
const std::map<std::string, std::string>& keywords)
1457 xticks(ticks, {}, keywords);
1460 template<
typename Numeric>
1461 inline void yticks(
const std::vector<Numeric> &ticks,
const std::vector<std::string> &labels = {},
const std::map<std::string, std::string>& keywords = {})
1463 assert(labels.size() == 0 || ticks.size() == labels.size());
1466 PyObject* ticksarray = get_array(ticks);
1469 if(labels.size() == 0) {
1471 args = PyTuple_New(1);
1472 PyTuple_SetItem(args, 0, ticksarray);
1475 PyObject* labelstuple = PyTuple_New(labels.size());
1476 for (
size_t i = 0; i < labels.size(); i++)
1477 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
1480 args = PyTuple_New(2);
1481 PyTuple_SetItem(args, 0, ticksarray);
1482 PyTuple_SetItem(args, 1, labelstuple);
1486 PyObject* kwargs = PyDict_New();
1487 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1489 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1492 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_yticks, args, kwargs);
1496 if(!res)
throw std::runtime_error(
"Call to yticks() failed");
1501 template<
typename Numeric>
1502 inline void yticks(
const std::vector<Numeric> &ticks,
const std::map<std::string, std::string>& keywords)
1504 yticks(ticks, {}, keywords);
1507 inline void subplot(
long nrows,
long ncols,
long plot_number)
1510 PyObject* args = PyTuple_New(3);
1511 PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
1512 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
1513 PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
1515 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_subplot, args);
1516 if(!res)
throw std::runtime_error(
"Call to subplot() failed.");
1522 inline void subplot2grid(
long nrows,
long ncols,
long rowid=0,
long colid=0,
long rowspan=1,
long colspan=1)
1524 PyObject* shape = PyTuple_New(2);
1525 PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows));
1526 PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols));
1528 PyObject* loc = PyTuple_New(2);
1529 PyTuple_SetItem(loc, 0, PyLong_FromLong(rowid));
1530 PyTuple_SetItem(loc, 1, PyLong_FromLong(colid));
1532 PyObject* args = PyTuple_New(4);
1533 PyTuple_SetItem(args, 0, shape);
1534 PyTuple_SetItem(args, 1, loc);
1535 PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan));
1536 PyTuple_SetItem(args, 3, PyLong_FromLong(colspan));
1538 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_subplot2grid, args);
1539 if(!res)
throw std::runtime_error(
"Call to subplot2grid() failed.");
1547 inline void title(
const std::string &titlestr,
const std::map<std::string, std::string> &keywords = {})
1549 PyObject* pytitlestr = PyString_FromString(titlestr.c_str());
1550 PyObject* args = PyTuple_New(1);
1551 PyTuple_SetItem(args, 0, pytitlestr);
1553 PyObject* kwargs = PyDict_New();
1554 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
1555 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1558 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_title, args, kwargs);
1559 if(!res)
throw std::runtime_error(
"Call to title() failed.");
1566 inline void suptitle(
const std::string &suptitlestr,
const std::map<std::string, std::string> &keywords = {})
1568 PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str());
1569 PyObject* args = PyTuple_New(1);
1570 PyTuple_SetItem(args, 0, pysuptitlestr);
1572 PyObject* kwargs = PyDict_New();
1573 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
1574 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1577 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_suptitle, args, kwargs);
1578 if(!res)
throw std::runtime_error(
"Call to suptitle() failed.");
1585 inline void axis(
const std::string &axisstr)
1587 PyObject* str = PyString_FromString(axisstr.c_str());
1588 PyObject* args = PyTuple_New(1);
1589 PyTuple_SetItem(args, 0, str);
1591 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_axis, args);
1592 if(!res)
throw std::runtime_error(
"Call to title() failed.");
1598 inline void xlabel(
const std::string &str,
const std::map<std::string, std::string> &keywords = {})
1600 PyObject* pystr = PyString_FromString(str.c_str());
1601 PyObject* args = PyTuple_New(1);
1602 PyTuple_SetItem(args, 0, pystr);
1604 PyObject* kwargs = PyDict_New();
1605 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
1606 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1609 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_xlabel, args, kwargs);
1610 if(!res)
throw std::runtime_error(
"Call to xlabel() failed.");
1617 inline void ylabel(
const std::string &str,
const std::map<std::string, std::string>& keywords = {})
1619 PyObject* pystr = PyString_FromString(str.c_str());
1620 PyObject* args = PyTuple_New(1);
1621 PyTuple_SetItem(args, 0, pystr);
1623 PyObject* kwargs = PyDict_New();
1624 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
1625 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1628 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_ylabel, args, kwargs);
1629 if(!res)
throw std::runtime_error(
"Call to ylabel() failed.");
1636 inline void grid(
bool flag)
1638 PyObject* pyflag = flag ? Py_True : Py_False;
1641 PyObject* args = PyTuple_New(1);
1642 PyTuple_SetItem(args, 0, pyflag);
1644 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_grid, args);
1645 if(!res)
throw std::runtime_error(
"Call to grid() failed.");
1651 inline void show(
const bool block =
true)
1656 res = PyObject_CallObject(
1657 detail::Interpreter::get().s_python_function_show,
1658 detail::Interpreter::get().s_python_empty_tuple);
1662 PyObject *kwargs = PyDict_New();
1663 PyDict_SetItemString(kwargs,
"block", Py_False);
1664 res = PyObject_Call( detail::Interpreter::get().s_python_function_show, detail::Interpreter::get().s_python_empty_tuple, kwargs);
1669 if (!res)
throw std::runtime_error(
"Call to show() failed.");
1676 PyObject* res = PyObject_CallObject(
1677 detail::Interpreter::get().s_python_function_close,
1678 detail::Interpreter::get().s_python_empty_tuple);
1680 if (!res)
throw std::runtime_error(
"Call to close() failed.");
1685 inline void xkcd() {
1687 PyObject *kwargs = PyDict_New();
1689 res = PyObject_Call(detail::Interpreter::get().s_python_function_xkcd,
1690 detail::Interpreter::get().s_python_empty_tuple, kwargs);
1695 throw std::runtime_error(
"Call to show() failed.");
1702 PyObject* res = PyObject_CallObject(
1703 detail::Interpreter::get().s_python_function_draw,
1704 detail::Interpreter::get().s_python_empty_tuple);
1706 if (!res)
throw std::runtime_error(
"Call to draw() failed.");
1711 template<
typename Numeric>
1712 inline void pause(Numeric interval)
1714 PyObject* args = PyTuple_New(1);
1715 PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
1717 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_pause, args);
1718 if(!res)
throw std::runtime_error(
"Call to pause() failed.");
1724 inline void save(
const std::string& filename)
1726 PyObject* pyfilename = PyString_FromString(filename.c_str());
1728 PyObject* args = PyTuple_New(1);
1729 PyTuple_SetItem(args, 0, pyfilename);
1731 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_save, args);
1732 if (!res)
throw std::runtime_error(
"Call to save() failed.");
1739 PyObject *res = PyObject_CallObject(
1740 detail::Interpreter::get().s_python_function_clf,
1741 detail::Interpreter::get().s_python_empty_tuple);
1743 if (!res)
throw std::runtime_error(
"Call to clf() failed.");
1749 PyObject *res = PyObject_CallObject(
1750 detail::Interpreter::get().s_python_function_ion,
1751 detail::Interpreter::get().s_python_empty_tuple);
1753 if (!res)
throw std::runtime_error(
"Call to ion() failed.");
1758 inline std::vector<std::array<double, 2>> ginput(
const int numClicks = 1,
const std::map<std::string, std::string>& keywords = {})
1760 PyObject *args = PyTuple_New(1);
1761 PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
1764 PyObject* kwargs = PyDict_New();
1765 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1767 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1770 PyObject* res = PyObject_Call(
1771 detail::Interpreter::get().s_python_function_ginput, args, kwargs);
1775 if (!res)
throw std::runtime_error(
"Call to ginput() failed.");
1777 const size_t len = PyList_Size(res);
1778 std::vector<std::array<double, 2>> out;
1780 for (
size_t i = 0; i < len; i++) {
1781 PyObject *current = PyList_GetItem(res, i);
1782 std::array<double, 2> position;
1783 position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
1784 position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
1785 out.push_back(position);
1793 inline void tight_layout() {
1794 PyObject *res = PyObject_CallObject(
1795 detail::Interpreter::get().s_python_function_tight_layout,
1796 detail::Interpreter::get().s_python_empty_tuple);
1798 if (!res)
throw std::runtime_error(
"Call to tight_layout() failed.");
1807 template<
typename T>
1808 using is_function =
typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type;
1810 template<
bool obj,
typename T>
1811 struct is_callable_impl;
1813 template<
typename T>
1814 struct is_callable_impl<false, T>
1816 typedef is_function<T> type;
1819 template<
typename T>
1820 struct is_callable_impl<true, T>
1822 struct Fallback {
void operator()(); };
1823 struct Derived : T, Fallback { };
1825 template<
typename U, U>
struct Check;
1827 template<
typename U>
1828 static std::true_type test( ... );
1830 template<
typename U>
1831 static std::false_type test( Check<
void(Fallback::*)(), &U::operator()>* );
1834 typedef decltype(test<Derived>(
nullptr)) type;
1835 typedef decltype(&Fallback::operator()) dtype;
1836 static constexpr
bool value = type::value;
1839 template<typename T>
1843 typedef typename is_callable_impl<std::is_class<T>::value, T>::type type;
1846 template<
typename IsYDataCallable>
1847 struct plot_impl { };
1850 struct plot_impl<std::false_type>
1852 template<
typename IterableX,
typename IterableY>
1853 bool operator()(
const IterableX& x,
const IterableY& y,
const std::string& format)
1856 using std::distance;
1860 auto xs = distance(begin(x), end(x));
1861 auto ys = distance(begin(y), end(y));
1862 assert(xs == ys &&
"x and y data must have the same number of elements!");
1864 PyObject* xlist = PyList_New(xs);
1865 PyObject* ylist = PyList_New(ys);
1866 PyObject* pystring = PyString_FromString(format.c_str());
1868 auto itx = begin(x), ity = begin(y);
1869 for(
size_t i = 0; i < xs; ++i) {
1870 PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++));
1871 PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++));
1874 PyObject* plot_args = PyTuple_New(3);
1875 PyTuple_SetItem(plot_args, 0, xlist);
1876 PyTuple_SetItem(plot_args, 1, ylist);
1877 PyTuple_SetItem(plot_args, 2, pystring);
1879 PyObject* res = PyObject_CallObject(detail::Interpreter::get().s_python_function_plot, plot_args);
1881 Py_DECREF(plot_args);
1882 if(res) Py_DECREF(res);
1889 struct plot_impl<std::true_type>
1891 template<
typename Iterable,
typename Callable>
1892 bool operator()(
const Iterable& ticks,
const Callable& f,
const std::string& format)
1894 if(begin(ticks) == end(ticks))
return true;
1898 std::vector<double> y;
1899 for(
auto x : ticks) y.push_back(f(x));
1900 return plot_impl<std::false_type>()(ticks,y,format);
1907 template<
typename... Args>
1908 bool plot() {
return true; }
1910 template<
typename A,
typename B,
typename... Args>
1911 bool plot(
const A& a,
const B& b,
const std::string& format, Args... args)
1913 return detail::plot_impl<typename detail::is_callable<B>::type>()(a,b,format) && plot(args...);
1920 inline bool plot(
const std::vector<double>& x,
const std::vector<double>& y,
const std::string& format =
"") {
1921 return plot<double,double>(x,y,format);
1924 inline bool plot(
const std::vector<double>& y,
const std::string& format =
"") {
1925 return plot<double>(y,format);
1928 inline bool plot(
const std::vector<double>& x,
const std::vector<double>& y,
const std::map<std::string, std::string>& keywords) {
1929 return plot<double>(x,y,keywords);
1940 template<
typename Numeric>
1941 Plot(
const std::string& name,
const std::vector<Numeric>& x,
const std::vector<Numeric>& y,
const std::string& format =
"") {
1943 assert(x.size() == y.size());
1945 PyObject* kwargs = PyDict_New();
1947 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1949 PyObject* xarray = get_array(x);
1950 PyObject* yarray = get_array(y);
1952 PyObject* pystring = PyString_FromString(format.c_str());
1954 PyObject* plot_args = PyTuple_New(3);
1955 PyTuple_SetItem(plot_args, 0, xarray);
1956 PyTuple_SetItem(plot_args, 1, yarray);
1957 PyTuple_SetItem(plot_args, 2, pystring);
1959 PyObject* res = PyObject_Call(detail::Interpreter::get().s_python_function_plot, plot_args, kwargs);
1962 Py_DECREF(plot_args);
1966 line= PyList_GetItem(res, 0);
1969 set_data_fct = PyObject_GetAttrString(line,
"set_data");
1978 Plot(
const std::string& name =
"",
const std::string& format =
"")
1979 : Plot(name, std::vector<double>(), std::vector<double>(), format) {}
1981 template<
typename Numeric>
1982 bool update(
const std::vector<Numeric>& x,
const std::vector<Numeric>& y) {
1983 assert(x.size() == y.size());
1986 PyObject* xarray = get_array(x);
1987 PyObject* yarray = get_array(y);
1989 PyObject* plot_args = PyTuple_New(2);
1990 PyTuple_SetItem(plot_args, 0, xarray);
1991 PyTuple_SetItem(plot_args, 1, yarray);
1993 PyObject* res = PyObject_CallObject(set_data_fct, plot_args);
1994 if (res) Py_DECREF(res);
2002 return update(std::vector<double>(), std::vector<double>());
2009 auto remove_fct = PyObject_GetAttrString(line,
"remove");
2010 PyObject* args = PyTuple_New(0);
2011 PyObject* res = PyObject_CallObject(remove_fct, args);
2012 if (res) Py_DECREF(res);
2026 Py_DECREF(set_data_fct);
2030 PyObject* line =
nullptr;
2031 PyObject* set_data_fct =
nullptr;