19 # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
20 # include <numpy/arrayobject.h>
23 # include <opencv2/opencv.hpp>
24 # endif // WITH_OPENCV
30 # if CV_MAJOR_VERSION > 3
31 # define CV_BGR2RGB cv::COLOR_BGR2RGB
32 # define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA
34 #endif // WITHOUT_NUMPY
36 #if PY_MAJOR_VERSION >= 3
37 # define PyString_FromString PyUnicode_FromString
38 # define PyInt_FromLong PyLong_FromLong
39 # define PyString_FromString PyUnicode_FromString
136 PyObject* fn = PyObject_GetAttrString(module, fname.c_str());
139 throw std::runtime_error(std::string(
"Couldn't find required function: ") + fname);
141 if (!PyFunction_Check(fn))
142 throw std::runtime_error(fname + std::string(
" is unexpectedly not a PyFunction."));
149 #ifndef WITHOUT_NUMPY
150 # if PY_MAJOR_VERSION >= 3
169 #if PY_MAJOR_VERSION >= 3
170 wchar_t name[] = L
"plotting";
172 char name[] =
"plotting";
174 Py_SetProgramName(name);
177 wchar_t const *dummy_args[] = {L
"Python", NULL};
178 wchar_t const **argv = dummy_args;
179 int argc =
sizeof(dummy_args)/
sizeof(dummy_args[0])-1;
181 #if PY_MAJOR_VERSION >= 3
182 PySys_SetArgv(argc,
const_cast<wchar_t **
>(argv));
184 PySys_SetArgv(argc, (
char **)(argv));
187 #ifndef WITHOUT_NUMPY
191 PyObject* matplotlibname = PyString_FromString(
"matplotlib");
192 PyObject* pyplotname = PyString_FromString(
"matplotlib.pyplot");
193 PyObject* cmname = PyString_FromString(
"matplotlib.cm");
194 PyObject* pylabname = PyString_FromString(
"pylab");
195 if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
196 throw std::runtime_error(
"couldnt create string");
199 PyObject* matplotlib = PyImport_Import(matplotlibname);
201 Py_DECREF(matplotlibname);
204 throw std::runtime_error(
"Error loading module matplotlib!");
210 PyObject_CallMethod(matplotlib,
const_cast<char*
>(
"use"),
const_cast<char*
>(
"s"),
s_backend.c_str());
215 PyObject* pymod = PyImport_Import(pyplotname);
216 Py_DECREF(pyplotname);
217 if (!pymod) {
throw std::runtime_error(
"Error loading module matplotlib.pyplot!"); }
221 if (!
s_python_colormap) {
throw std::runtime_error(
"Error loading module matplotlib.cm!"); }
223 PyObject* pylabmod = PyImport_Import(pylabname);
224 Py_DECREF(pylabname);
225 if (!pylabmod) {
throw std::runtime_error(
"Error loading module pylab!"); }
281 #ifndef WITHOUT_NUMPY
308 inline bool annotate(std::string annotation,
double x,
double y)
312 PyObject * xy = PyTuple_New(2);
313 PyObject * str = PyString_FromString(annotation.c_str());
315 PyTuple_SetItem(xy,0,PyFloat_FromDouble(
x));
316 PyTuple_SetItem(xy,1,PyFloat_FromDouble(
y));
318 PyObject* kwargs = PyDict_New();
319 PyDict_SetItemString(kwargs,
"xy", xy);
321 PyObject* args = PyTuple_New(1);
322 PyTuple_SetItem(args, 0, str);
329 if(res) Py_DECREF(res);
336 #ifndef WITHOUT_NUMPY
353 static_assert(
sizeof(
long long) == 8);
355 static_assert(
sizeof(
unsigned long long) == 8);
358 template<
typename Numeric>
361 npy_intp vsize = v.size();
363 if (
type == NPY_NOTYPE) {
364 size_t memsize = v.size()*
sizeof(double);
365 double* dp =
static_cast<double*
>(::malloc(memsize));
366 for (
size_t i=0;
i<v.size(); ++
i)
368 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, dp);
369 PyArray_UpdateFlags(
reinterpret_cast<PyArrayObject*
>(varray), NPY_ARRAY_OWNDATA);
373 PyObject* varray = PyArray_SimpleNewFromData(1, &vsize,
type, (
void*)(v.data()));
378 template<
typename Numeric>
379 PyObject*
get_2darray(
const std::vector<::std::vector<Numeric>>& v)
381 if (v.size() < 1)
throw std::runtime_error(
"get_2d_array v too small");
383 npy_intp vsize[2] = {
static_cast<npy_intp
>(v.size()),
384 static_cast<npy_intp
>(v[0].
size())};
386 PyArrayObject *varray =
387 (PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
389 double *vd_begin =
static_cast<double *
>(PyArray_DATA(varray));
391 for (const ::std::vector<Numeric> &v_row : v) {
392 if (v_row.size() !=
static_cast<size_t>(vsize[1]))
393 throw std::runtime_error(
"Missmatched array size");
394 std::copy(v_row.begin(), v_row.end(), vd_begin);
395 vd_begin += vsize[1];
398 return reinterpret_cast<PyObject *
>(varray);
401 #else // fallback if we don't have numpy: copy every element of the given vector
403 template<
typename Numeric>
404 PyObject*
get_array(
const std::vector<Numeric>& v)
406 PyObject* list = PyList_New(v.size());
407 for(
size_t i = 0;
i < v.size(); ++
i) {
408 PyList_SetItem(list,
i, PyFloat_FromDouble(v.at(
i)));
413 #endif // WITHOUT_NUMPY
416 inline PyObject *
get_array(
const std::vector<std::string>& strings)
418 PyObject* list = PyList_New(strings.size());
419 for (std::size_t
i = 0;
i < strings.size(); ++
i) {
420 PyList_SetItem(list,
i, PyString_FromString(strings[
i].c_str()));
426 template<
typename Numeric>
429 PyObject* listlist = PyList_New(ll.size());
430 for (std::size_t
i = 0;
i < ll.size(); ++
i) {
441 template<
typename Numeric>
442 bool plot(
const std::vector<Numeric> &
x,
const std::vector<Numeric> &
y,
const std::map<std::string, std::string>& keywords)
444 assert(
x.size() ==
y.size());
453 PyObject* args = PyTuple_New(2);
454 PyTuple_SetItem(args, 0, xarray);
455 PyTuple_SetItem(args, 1, yarray);
458 PyObject* kwargs = PyDict_New();
459 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
461 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
468 if(res) Py_DECREF(res);
475 #ifndef WITHOUT_NUMPY
476 template <
typename Numeric>
478 const std::vector<::std::vector<Numeric>> &
y,
479 const std::vector<::std::vector<Numeric>> &z,
480 const std::map<std::string, std::string> &keywords =
481 std::map<std::string, std::string>(),
482 const long fig_number=0)
490 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
491 if (!mpl_toolkitsmod) {
494 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
495 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
496 if (!mpl_toolkits || !axis3d) {
throw std::runtime_error(
"couldnt create string"); }
498 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
499 Py_DECREF(mpl_toolkits);
500 if (!mpl_toolkitsmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits!"); }
502 axis3dmod = PyImport_Import(axis3d);
504 if (!axis3dmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!"); }
507 assert(
x.size() ==
y.size());
508 assert(
y.size() == z.size());
516 PyObject *args = PyTuple_New(3);
517 PyTuple_SetItem(args, 0, xarray);
518 PyTuple_SetItem(args, 1, yarray);
519 PyTuple_SetItem(args, 2, zarray);
522 PyObject *kwargs = PyDict_New();
523 PyDict_SetItemString(kwargs,
"rstride", PyInt_FromLong(1));
524 PyDict_SetItemString(kwargs,
"cstride", PyInt_FromLong(1));
526 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
529 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
531 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
532 it != keywords.end(); ++it) {
533 if (it->first ==
"linewidth" || it->first ==
"alpha") {
534 PyDict_SetItemString(kwargs, it->first.c_str(),
535 PyFloat_FromDouble(std::stod(it->second)));
537 PyDict_SetItemString(kwargs, it->first.c_str(),
538 PyString_FromString(it->second.c_str()));
542 PyObject *fig_args = PyTuple_New(1);
543 PyObject* fig =
nullptr;
544 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
545 PyObject *fig_exists =
548 if (!PyObject_IsTrue(fig_exists)) {
555 Py_DECREF(fig_exists);
556 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
558 PyObject *gca_kwargs = PyDict_New();
559 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
561 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
562 if (!gca)
throw std::runtime_error(
"No gca");
564 PyObject *
axis = PyObject_Call(
567 if (!
axis)
throw std::runtime_error(
"No axis");
571 Py_DECREF(gca_kwargs);
574 if (!
plot_surface)
throw std::runtime_error(
"No surface");
576 PyObject *res = PyObject_Call(
plot_surface, args, kwargs);
577 if (!res)
throw std::runtime_error(
"failed surface");
583 if (res) Py_DECREF(res);
586 template <
typename Numeric>
587 void contour(
const std::vector<::std::vector<Numeric>> &
x,
588 const std::vector<::std::vector<Numeric>> &
y,
589 const std::vector<::std::vector<Numeric>> &z,
590 const std::map<std::string, std::string> &keywords = {})
600 PyObject *args = PyTuple_New(3);
601 PyTuple_SetItem(args, 0, xarray);
602 PyTuple_SetItem(args, 1, yarray);
603 PyTuple_SetItem(args, 2, zarray);
606 PyObject *kwargs = PyDict_New();
608 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
611 PyDict_SetItemString(kwargs,
"cmap", python_colormap_coolwarm);
613 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
614 it != keywords.end(); ++it) {
615 PyDict_SetItemString(kwargs, it->first.c_str(),
616 PyString_FromString(it->second.c_str()));
621 throw std::runtime_error(
"failed contour");
625 if (res) Py_DECREF(res);
628 template <
typename Numeric>
629 void spy(
const std::vector<::std::vector<Numeric>> &
x,
630 const double markersize = -1,
631 const std::map<std::string, std::string> &keywords = {})
637 PyObject *kwargs = PyDict_New();
638 if (markersize != -1) {
639 PyDict_SetItemString(kwargs,
"markersize", PyFloat_FromDouble(markersize));
641 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
642 it != keywords.end(); ++it) {
643 PyDict_SetItemString(kwargs, it->first.c_str(),
644 PyString_FromString(it->second.c_str()));
647 PyObject *plot_args = PyTuple_New(1);
648 PyTuple_SetItem(plot_args, 0, xarray);
650 PyObject *res = PyObject_Call(
653 Py_DECREF(plot_args);
655 if (res) Py_DECREF(res);
657 #endif // WITHOUT_NUMPY
659 template <
typename Numeric>
660 void plot3(
const std::vector<Numeric> &
x,
661 const std::vector<Numeric> &
y,
662 const std::vector<Numeric> &z,
663 const std::map<std::string, std::string> &keywords =
664 std::map<std::string, std::string>(),
665 const long fig_number=0)
673 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
674 if (!mpl_toolkitsmod) {
677 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
678 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
679 if (!mpl_toolkits || !axis3d) {
throw std::runtime_error(
"couldnt create string"); }
681 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
682 Py_DECREF(mpl_toolkits);
683 if (!mpl_toolkitsmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits!"); }
685 axis3dmod = PyImport_Import(axis3d);
687 if (!axis3dmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!"); }
690 assert(
x.size() ==
y.size());
691 assert(
y.size() == z.size());
698 PyObject *args = PyTuple_New(3);
699 PyTuple_SetItem(args, 0, xarray);
700 PyTuple_SetItem(args, 1, yarray);
701 PyTuple_SetItem(args, 2, zarray);
704 PyObject *kwargs = PyDict_New();
706 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
707 it != keywords.end(); ++it) {
708 PyDict_SetItemString(kwargs, it->first.c_str(),
709 PyString_FromString(it->second.c_str()));
712 PyObject *fig_args = PyTuple_New(1);
713 PyObject* fig =
nullptr;
714 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
715 PyObject *fig_exists =
717 if (!PyObject_IsTrue(fig_exists)) {
724 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
726 PyObject *gca_kwargs = PyDict_New();
727 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
729 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
730 if (!gca)
throw std::runtime_error(
"No gca");
732 PyObject *
axis = PyObject_Call(
735 if (!
axis)
throw std::runtime_error(
"No axis");
739 Py_DECREF(gca_kwargs);
741 PyObject *
plot3 = PyObject_GetAttrString(
axis,
"plot");
742 if (!
plot3)
throw std::runtime_error(
"No 3D line plot");
744 PyObject *res = PyObject_Call(
plot3, args, kwargs);
745 if (!res)
throw std::runtime_error(
"Failed 3D line plot");
751 if (res) Py_DECREF(res);
754 template<
typename Numeric>
755 bool stem(
const std::vector<Numeric> &
x,
const std::vector<Numeric> &
y,
const std::map<std::string, std::string>& keywords)
757 assert(
x.size() ==
y.size());
766 PyObject* args = PyTuple_New(2);
767 PyTuple_SetItem(args, 0, xarray);
768 PyTuple_SetItem(args, 1, yarray);
771 PyObject* kwargs = PyDict_New();
772 for (std::map<std::string, std::string>::const_iterator it =
773 keywords.begin(); it != keywords.end(); ++it) {
774 PyDict_SetItemString(kwargs, it->first.c_str(),
775 PyString_FromString(it->second.c_str()));
778 PyObject* res = PyObject_Call(
789 template<
typename Numeric >
790 bool fill(
const std::vector<Numeric>&
x,
const std::vector<Numeric>&
y,
const std::map<std::string, std::string>& keywords)
792 assert(
x.size() ==
y.size());
801 PyObject* args = PyTuple_New(2);
802 PyTuple_SetItem(args, 0, xarray);
803 PyTuple_SetItem(args, 1, yarray);
806 PyObject* kwargs = PyDict_New();
807 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
808 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
816 if (res) Py_DECREF(res);
821 template<
typename Numeric >
822 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)
824 assert(
x.size() ==
y1.size());
825 assert(
x.size() ==
y2.size());
835 PyObject* args = PyTuple_New(3);
836 PyTuple_SetItem(args, 0, xarray);
837 PyTuple_SetItem(args, 1, y1array);
838 PyTuple_SetItem(args, 2, y2array);
841 PyObject* kwargs = PyDict_New();
842 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it) {
843 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
850 if(res) Py_DECREF(res);
855 template <
typename Numeric>
856 bool arrow(Numeric
x, Numeric
y, Numeric end_x, Numeric end_y,
const std::string& fc =
"r",
857 const std::string ec =
"k", Numeric head_length = 0.25, Numeric head_width = 0.1625) {
858 PyObject* obj_x = PyFloat_FromDouble(
x);
859 PyObject* obj_y = PyFloat_FromDouble(
y);
860 PyObject* obj_end_x = PyFloat_FromDouble(end_x);
861 PyObject* obj_end_y = PyFloat_FromDouble(end_y);
863 PyObject* kwargs = PyDict_New();
864 PyDict_SetItemString(kwargs,
"fc", PyString_FromString(fc.c_str()));
865 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
866 PyDict_SetItemString(kwargs,
"head_width", PyFloat_FromDouble(head_width));
867 PyDict_SetItemString(kwargs,
"head_length", PyFloat_FromDouble(head_length));
869 PyObject* plot_args = PyTuple_New(4);
870 PyTuple_SetItem(plot_args, 0, obj_x);
871 PyTuple_SetItem(plot_args, 1, obj_y);
872 PyTuple_SetItem(plot_args, 2, obj_end_x);
873 PyTuple_SetItem(plot_args, 3, obj_end_y);
878 Py_DECREF(plot_args);
886 template<
typename Numeric>
887 bool hist(
const std::vector<Numeric>&
y,
long bins=10,std::string
color=
"b",
888 double alpha=1.0,
bool cumulative=
false)
894 PyObject* kwargs = PyDict_New();
895 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
896 PyDict_SetItemString(kwargs,
"color", PyString_FromString(
color.c_str()));
897 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
898 PyDict_SetItemString(kwargs,
"cumulative", cumulative ? Py_True : Py_False);
900 PyObject* plot_args = PyTuple_New(1);
902 PyTuple_SetItem(plot_args, 0, yarray);
908 Py_DECREF(plot_args);
910 if(res) Py_DECREF(res);
915 #ifndef WITHOUT_NUMPY
918 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, PyObject** out)
920 assert(
type == NPY_UINT8 ||
type == NPY_FLOAT);
921 assert(colors == 1 || colors == 3 || colors == 4);
926 npy_intp dims[3] = {
rows, columns, colors };
927 PyObject *args = PyTuple_New(1);
928 PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims,
type,
ptr));
931 PyObject* kwargs = PyDict_New();
932 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
934 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
941 throw std::runtime_error(
"Call to imshow() failed");
950 inline void imshow(
const unsigned char *
ptr,
const int rows,
const int columns,
const int colors,
const std::map<std::string, std::string> &keywords = {}, PyObject** out =
nullptr)
955 inline void imshow(
const float *
ptr,
const int rows,
const int columns,
const int colors,
const std::map<std::string, std::string> &keywords = {}, PyObject** out =
nullptr)
961 void imshow(
const cv::Mat &image,
const std::map<std::string, std::string> &keywords = {})
965 NPY_TYPES npy_type = NPY_UINT8;
966 switch (image.type() & CV_MAT_DEPTH_MASK) {
972 npy_type = NPY_FLOAT;
975 image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
979 switch (image2.channels()) {
981 cv::cvtColor(image2, image2, CV_BGR2RGB);
984 cv::cvtColor(image2, image2, CV_BGRA2RGBA);
987 detail::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords);
989 #endif // WITH_OPENCV
990 #endif // WITHOUT_NUMPY
992 template<
typename NumericX,
typename NumericY>
994 const std::vector<NumericY>&
y,
996 const std::map<std::string, std::string> & keywords = {})
1000 assert(
x.size() ==
y.size());
1005 PyObject* kwargs = PyDict_New();
1006 PyDict_SetItemString(kwargs,
"s", PyLong_FromLong(
s));
1007 for (
const auto& it : keywords)
1009 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1012 PyObject* plot_args = PyTuple_New(2);
1013 PyTuple_SetItem(plot_args, 0, xarray);
1014 PyTuple_SetItem(plot_args, 1, yarray);
1018 Py_DECREF(plot_args);
1020 if(res) Py_DECREF(res);
1025 template<
typename NumericX,
typename NumericY,
typename NumericColors>
1027 const std::vector<NumericY>&
y,
1028 const std::vector<NumericColors>& colors,
1030 const std::map<std::string, std::string> & keywords = {})
1034 assert(
x.size() ==
y.size());
1040 PyObject* kwargs = PyDict_New();
1041 PyDict_SetItemString(kwargs,
"s", PyLong_FromLong(
s));
1042 PyDict_SetItemString(kwargs,
"c", colors_array);
1044 for (
const auto& it : keywords)
1046 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1049 PyObject* plot_args = PyTuple_New(2);
1050 PyTuple_SetItem(plot_args, 0, xarray);
1051 PyTuple_SetItem(plot_args, 1, yarray);
1055 Py_DECREF(plot_args);
1057 if(res) Py_DECREF(res);
1063 template<
typename NumericX,
typename NumericY,
typename NumericZ>
1065 const std::vector<NumericY>&
y,
1066 const std::vector<NumericZ>& z,
1068 const std::map<std::string, std::string> & keywords = {},
1069 const long fig_number=0) {
1076 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
1077 if (!mpl_toolkitsmod) {
1080 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
1081 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
1082 if (!mpl_toolkits || !axis3d) {
throw std::runtime_error(
"couldnt create string"); }
1084 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1085 Py_DECREF(mpl_toolkits);
1086 if (!mpl_toolkitsmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits!"); }
1088 axis3dmod = PyImport_Import(axis3d);
1090 if (!axis3dmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!"); }
1093 assert(
x.size() ==
y.size());
1094 assert(
y.size() == z.size());
1101 PyObject *args = PyTuple_New(3);
1102 PyTuple_SetItem(args, 0, xarray);
1103 PyTuple_SetItem(args, 1, yarray);
1104 PyTuple_SetItem(args, 2, zarray);
1107 PyObject *kwargs = PyDict_New();
1109 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1110 it != keywords.end(); ++it) {
1111 PyDict_SetItemString(kwargs, it->first.c_str(),
1112 PyString_FromString(it->second.c_str()));
1114 PyObject *fig_args = PyTuple_New(1);
1115 PyObject* fig =
nullptr;
1116 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
1117 PyObject *fig_exists =
1119 if (!PyObject_IsTrue(fig_exists)) {
1126 Py_DECREF(fig_exists);
1127 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
1129 PyObject *gca_kwargs = PyDict_New();
1130 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
1132 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
1133 if (!gca)
throw std::runtime_error(
"No gca");
1135 PyObject *
axis = PyObject_Call(
1138 if (!
axis)
throw std::runtime_error(
"No axis");
1142 Py_DECREF(gca_kwargs);
1144 PyObject *
plot3 = PyObject_GetAttrString(
axis,
"scatter");
1145 if (!
plot3)
throw std::runtime_error(
"No 3D line plot");
1147 PyObject *res = PyObject_Call(
plot3, args, kwargs);
1148 if (!res)
throw std::runtime_error(
"Failed 3D line plot");
1155 if (res) Py_DECREF(res);
1160 template<
typename Numeric>
1162 const std::vector<std::string>& labels = {},
1163 const std::map<std::string, std::string> & keywords = {})
1168 PyObject* args = PyTuple_New(1);
1169 PyTuple_SetItem(args, 0, listlist);
1171 PyObject* kwargs = PyDict_New();
1174 if (!labels.empty() && labels.size() ==
data.size()) {
1179 for (
const auto& it : keywords)
1181 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1189 if(res) Py_DECREF(res);
1194 template<
typename Numeric>
1196 const std::map<std::string, std::string> & keywords = {})
1201 PyObject* args = PyTuple_New(1);
1202 PyTuple_SetItem(args, 0, vector);
1204 PyObject* kwargs = PyDict_New();
1205 for (
const auto& it : keywords)
1207 PyDict_SetItemString(kwargs, it.first.c_str(), PyString_FromString(it.second.c_str()));
1215 if(res) Py_DECREF(res);
1220 template <
typename Numeric>
1221 bool bar(
const std::vector<Numeric> &
x,
1222 const std::vector<Numeric> &
y,
1223 std::string ec =
"black",
1224 std::string ls =
"-",
1226 const std::map<std::string, std::string> & keywords = {})
1233 PyObject * kwargs = PyDict_New();
1235 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
1236 PyDict_SetItemString(kwargs,
"ls", PyString_FromString(ls.c_str()));
1237 PyDict_SetItemString(kwargs,
"lw", PyFloat_FromDouble(lw));
1239 for (std::map<std::string, std::string>::const_iterator it =
1241 it != keywords.end();
1243 PyDict_SetItemString(
1244 kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1247 PyObject * plot_args = PyTuple_New(2);
1248 PyTuple_SetItem(plot_args, 0, xarray);
1249 PyTuple_SetItem(plot_args, 1, yarray);
1251 PyObject * res = PyObject_Call(
1254 Py_DECREF(plot_args);
1256 if (res) Py_DECREF(res);
1261 template <
typename Numeric>
1262 bool bar(
const std::vector<Numeric> &
y,
1263 std::string ec =
"black",
1264 std::string ls =
"-",
1266 const std::map<std::string, std::string> & keywords = {})
1273 for (std::size_t
i = 0;
i <
y.size();
i++) {
x.push_back(
i); }
1275 return bar(
x,
y, ec, ls, lw, keywords);
1279 template<
typename Numeric>
1280 bool barh(
const std::vector<Numeric> &
x,
const std::vector<Numeric> &
y, std::string ec =
"black", std::string ls =
"-",
double lw = 1.0,
const std::map<std::string, std::string> &keywords = { }) {
1284 PyObject *kwargs = PyDict_New();
1286 PyDict_SetItemString(kwargs,
"ec", PyString_FromString(ec.c_str()));
1287 PyDict_SetItemString(kwargs,
"ls", PyString_FromString(ls.c_str()));
1288 PyDict_SetItemString(kwargs,
"lw", PyFloat_FromDouble(lw));
1290 for (std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it) {
1291 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1294 PyObject *plot_args = PyTuple_New(2);
1295 PyTuple_SetItem(plot_args, 0, xarray);
1296 PyTuple_SetItem(plot_args, 1, yarray);
1300 Py_DECREF(plot_args);
1302 if (res) Py_DECREF(res);
1312 PyObject* kwargs = PyDict_New();
1313 for (std::map<std::string, double>::const_iterator it =
1314 keywords.begin(); it != keywords.end(); ++it) {
1315 PyDict_SetItemString(kwargs, it->first.c_str(),
1316 PyFloat_FromDouble(it->second));
1320 PyObject* plot_args = PyTuple_New(0);
1324 Py_DECREF(plot_args);
1326 if(res) Py_DECREF(res);
1331 template<
typename Numeric>
1332 bool named_hist(std::string label,
const std::vector<Numeric>&
y,
long bins=10, std::string
color=
"b",
double alpha=1.0)
1338 PyObject* kwargs = PyDict_New();
1339 PyDict_SetItemString(kwargs,
"label", PyString_FromString(label.c_str()));
1340 PyDict_SetItemString(kwargs,
"bins", PyLong_FromLong(bins));
1341 PyDict_SetItemString(kwargs,
"color", PyString_FromString(
color.c_str()));
1342 PyDict_SetItemString(kwargs,
"alpha", PyFloat_FromDouble(alpha));
1345 PyObject* plot_args = PyTuple_New(1);
1346 PyTuple_SetItem(plot_args, 0, yarray);
1350 Py_DECREF(plot_args);
1352 if(res) Py_DECREF(res);
1357 template<
typename NumericX,
typename NumericY>
1358 bool plot(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
s =
"")
1360 assert(
x.size() ==
y.size());
1367 PyObject* pystring = PyString_FromString(
s.c_str());
1369 PyObject* plot_args = PyTuple_New(3);
1370 PyTuple_SetItem(plot_args, 0, xarray);
1371 PyTuple_SetItem(plot_args, 1, yarray);
1372 PyTuple_SetItem(plot_args, 2, pystring);
1376 Py_DECREF(plot_args);
1377 if(res) Py_DECREF(res);
1382 template <
typename NumericX,
typename NumericY,
typename NumericZ>
1383 bool contour(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
1384 const std::vector<NumericZ>& z,
1385 const std::map<std::string, std::string>& keywords = {}) {
1386 assert(
x.size() ==
y.size() &&
x.size() == z.size());
1392 PyObject* plot_args = PyTuple_New(3);
1393 PyTuple_SetItem(plot_args, 0, xarray);
1394 PyTuple_SetItem(plot_args, 1, yarray);
1395 PyTuple_SetItem(plot_args, 2, zarray);
1398 PyObject* kwargs = PyDict_New();
1399 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1400 it != keywords.end(); ++it) {
1401 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1408 Py_DECREF(plot_args);
1415 template<
typename NumericX,
typename NumericY,
typename NumericU,
typename NumericW>
1416 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 = {})
1418 assert(
x.size() ==
y.size() &&
x.size() ==
u.size() &&
u.size() ==
w.size());
1427 PyObject* plot_args = PyTuple_New(4);
1428 PyTuple_SetItem(plot_args, 0, xarray);
1429 PyTuple_SetItem(plot_args, 1, yarray);
1430 PyTuple_SetItem(plot_args, 2, uarray);
1431 PyTuple_SetItem(plot_args, 3, warray);
1434 PyObject* kwargs = PyDict_New();
1435 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1437 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1440 PyObject* res = PyObject_Call(
1444 Py_DECREF(plot_args);
1451 template<
typename NumericX,
typename NumericY,
typename NumericZ,
typename NumericU,
typename NumericW,
typename NumericV>
1452 bool quiver(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::vector<NumericZ>& z,
const std::vector<NumericU>&
u,
const std::vector<NumericW>&
w,
const std::vector<NumericV>& v,
const std::map<std::string, std::string>& keywords = {})
1455 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
1456 if (!mpl_toolkitsmod) {
1459 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
1460 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
1461 if (!mpl_toolkits || !axis3d) {
throw std::runtime_error(
"couldnt create string"); }
1463 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1464 Py_DECREF(mpl_toolkits);
1465 if (!mpl_toolkitsmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits!"); }
1467 axis3dmod = PyImport_Import(axis3d);
1469 if (!axis3dmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!"); }
1473 assert(
x.size() ==
y.size() &&
x.size() ==
u.size() &&
u.size() ==
w.size() &&
x.size() == z.size() &&
x.size() == v.size() &&
u.size() == v.size());
1485 PyObject* plot_args = PyTuple_New(6);
1486 PyTuple_SetItem(plot_args, 0, xarray);
1487 PyTuple_SetItem(plot_args, 1, yarray);
1488 PyTuple_SetItem(plot_args, 2, zarray);
1489 PyTuple_SetItem(plot_args, 3, uarray);
1490 PyTuple_SetItem(plot_args, 4, warray);
1491 PyTuple_SetItem(plot_args, 5, varray);
1494 PyObject* kwargs = PyDict_New();
1495 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1497 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1504 if (!fig)
throw std::runtime_error(
"Call to figure() failed.");
1506 PyObject *gca_kwargs = PyDict_New();
1507 PyDict_SetItemString(gca_kwargs,
"projection", PyString_FromString(
"3d"));
1509 PyObject *gca = PyObject_GetAttrString(fig,
"gca");
1510 if (!gca)
throw std::runtime_error(
"No gca");
1512 PyObject *
axis = PyObject_Call(
1515 if (!
axis)
throw std::runtime_error(
"No axis");
1518 Py_DECREF(gca_kwargs);
1521 PyObject *
plot3 = PyObject_GetAttrString(
axis,
"quiver");
1522 if (!
plot3)
throw std::runtime_error(
"No 3D line plot");
1524 PyObject* res = PyObject_Call(
1525 plot3, plot_args, kwargs);
1526 if (!res)
throw std::runtime_error(
"Failed 3D plot");
1530 Py_DECREF(plot_args);
1537 template<
typename NumericX,
typename NumericY>
1538 bool stem(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
s =
"")
1540 assert(
x.size() ==
y.size());
1547 PyObject* pystring = PyString_FromString(
s.c_str());
1549 PyObject* plot_args = PyTuple_New(3);
1550 PyTuple_SetItem(plot_args, 0, xarray);
1551 PyTuple_SetItem(plot_args, 1, yarray);
1552 PyTuple_SetItem(plot_args, 2, pystring);
1554 PyObject* res = PyObject_CallObject(
1557 Py_DECREF(plot_args);
1564 template<
typename NumericX,
typename NumericY>
1565 bool semilogx(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
s =
"")
1567 assert(
x.size() ==
y.size());
1574 PyObject* pystring = PyString_FromString(
s.c_str());
1576 PyObject* plot_args = PyTuple_New(3);
1577 PyTuple_SetItem(plot_args, 0, xarray);
1578 PyTuple_SetItem(plot_args, 1, yarray);
1579 PyTuple_SetItem(plot_args, 2, pystring);
1583 Py_DECREF(plot_args);
1584 if(res) Py_DECREF(res);
1589 template<
typename NumericX,
typename NumericY>
1590 bool semilogy(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
s =
"")
1592 assert(
x.size() ==
y.size());
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);
1608 Py_DECREF(plot_args);
1609 if(res) Py_DECREF(res);
1614 template<
typename NumericX,
typename NumericY>
1615 bool loglog(
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
s =
"")
1617 assert(
x.size() ==
y.size());
1624 PyObject* pystring = PyString_FromString(
s.c_str());
1626 PyObject* plot_args = PyTuple_New(3);
1627 PyTuple_SetItem(plot_args, 0, xarray);
1628 PyTuple_SetItem(plot_args, 1, yarray);
1629 PyTuple_SetItem(plot_args, 2, pystring);
1633 Py_DECREF(plot_args);
1634 if(res) Py_DECREF(res);
1639 template<
typename NumericX,
typename NumericY>
1640 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 = {})
1642 assert(
x.size() ==
y.size());
1651 PyObject* kwargs = PyDict_New();
1652 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1654 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1657 PyDict_SetItemString(kwargs,
"yerr", yerrarray);
1659 PyObject *plot_args = PyTuple_New(2);
1660 PyTuple_SetItem(plot_args, 0, xarray);
1661 PyTuple_SetItem(plot_args, 1, yarray);
1666 Py_DECREF(plot_args);
1671 throw std::runtime_error(
"Call to errorbar() failed.");
1676 template<
typename Numeric>
1677 bool named_plot(
const std::string& name,
const std::vector<Numeric>&
y,
const std::string&
format =
"")
1681 PyObject* kwargs = PyDict_New();
1682 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1686 PyObject* pystring = PyString_FromString(
format.c_str());
1688 PyObject* plot_args = PyTuple_New(2);
1690 PyTuple_SetItem(plot_args, 0, yarray);
1691 PyTuple_SetItem(plot_args, 1, pystring);
1696 Py_DECREF(plot_args);
1697 if (res) Py_DECREF(res);
1702 template<
typename NumericX,
typename NumericY>
1703 bool named_plot(
const std::string& name,
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
format =
"")
1707 PyObject* kwargs = PyDict_New();
1708 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1713 PyObject* pystring = PyString_FromString(
format.c_str());
1715 PyObject* plot_args = PyTuple_New(3);
1716 PyTuple_SetItem(plot_args, 0, xarray);
1717 PyTuple_SetItem(plot_args, 1, yarray);
1718 PyTuple_SetItem(plot_args, 2, pystring);
1723 Py_DECREF(plot_args);
1724 if (res) Py_DECREF(res);
1729 template<
typename NumericX,
typename NumericY>
1730 bool named_semilogx(
const std::string& name,
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
format =
"")
1734 PyObject* kwargs = PyDict_New();
1735 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1740 PyObject* pystring = PyString_FromString(
format.c_str());
1742 PyObject* plot_args = PyTuple_New(3);
1743 PyTuple_SetItem(plot_args, 0, xarray);
1744 PyTuple_SetItem(plot_args, 1, yarray);
1745 PyTuple_SetItem(plot_args, 2, pystring);
1750 Py_DECREF(plot_args);
1751 if (res) Py_DECREF(res);
1756 template<
typename NumericX,
typename NumericY>
1757 bool named_semilogy(
const std::string& name,
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
format =
"")
1761 PyObject* kwargs = PyDict_New();
1762 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1767 PyObject* pystring = PyString_FromString(
format.c_str());
1769 PyObject* plot_args = PyTuple_New(3);
1770 PyTuple_SetItem(plot_args, 0, xarray);
1771 PyTuple_SetItem(plot_args, 1, yarray);
1772 PyTuple_SetItem(plot_args, 2, pystring);
1777 Py_DECREF(plot_args);
1778 if (res) Py_DECREF(res);
1783 template<
typename NumericX,
typename NumericY>
1784 bool named_loglog(
const std::string& name,
const std::vector<NumericX>&
x,
const std::vector<NumericY>&
y,
const std::string&
format =
"")
1788 PyObject* kwargs = PyDict_New();
1789 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
1794 PyObject* pystring = PyString_FromString(
format.c_str());
1796 PyObject* plot_args = PyTuple_New(3);
1797 PyTuple_SetItem(plot_args, 0, xarray);
1798 PyTuple_SetItem(plot_args, 1, yarray);
1799 PyTuple_SetItem(plot_args, 2, pystring);
1803 Py_DECREF(plot_args);
1804 if (res) Py_DECREF(res);
1809 template<
typename Numeric>
1810 bool plot(
const std::vector<Numeric>&
y,
const std::string&
format =
"")
1812 std::vector<Numeric>
x(
y.size());
1813 for(
size_t i=0;
i<
x.size(); ++
i)
x.at(
i) =
i;
1817 template<
typename Numeric>
1818 bool plot(
const std::vector<Numeric>&
y,
const std::map<std::string, std::string>& keywords)
1820 std::vector<Numeric>
x(
y.size());
1821 for(
size_t i=0;
i<
x.size(); ++
i)
x.at(
i) =
i;
1822 return plot(
x,
y,keywords);
1825 template<
typename Numeric>
1826 bool stem(
const std::vector<Numeric>&
y,
const std::string&
format =
"")
1828 std::vector<Numeric>
x(
y.size());
1829 for (
size_t i = 0;
i <
x.size(); ++
i)
x.at(
i) =
i;
1833 template<
typename Numeric>
1834 void text(Numeric
x, Numeric
y,
const std::string&
s =
"")
1838 PyObject* args = PyTuple_New(3);
1839 PyTuple_SetItem(args, 0, PyFloat_FromDouble(
x));
1840 PyTuple_SetItem(args, 1, PyFloat_FromDouble(
y));
1841 PyTuple_SetItem(args, 2, PyString_FromString(
s.c_str()));
1844 if(!res)
throw std::runtime_error(
"Call to text() failed.");
1850 inline void colorbar(PyObject* mappable = NULL,
const std::map<std::string, float>& keywords = {})
1852 if (mappable == NULL)
1853 throw std::runtime_error(
"Must call colorbar with PyObject* returned from an image, contour, surface, etc.");
1857 PyObject* args = PyTuple_New(1);
1858 PyTuple_SetItem(args, 0, mappable);
1860 PyObject* kwargs = PyDict_New();
1861 for(std::map<std::string, float>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1863 PyDict_SetItemString(kwargs, it->first.c_str(), PyFloat_FromDouble(it->second));
1867 if(!res)
throw std::runtime_error(
"Call to colorbar() failed.");
1888 PyObject *args = PyTuple_New(1);
1889 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1894 if(!res)
throw std::runtime_error(
"Call to figure() failed.");
1896 PyObject* num = PyObject_GetAttrString(res,
"number");
1897 if (!num)
throw std::runtime_error(
"Could not get number attribute of figure object");
1898 const long figureNumber = PyLong_AsLong(num);
1903 return figureNumber;
1910 PyObject *args = PyTuple_New(1);
1911 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1913 if(!res)
throw std::runtime_error(
"Call to fignum_exists() failed.");
1915 bool ret = PyObject_IsTrue(res);
1926 const size_t dpi = 100;
1927 PyObject*
size = PyTuple_New(2);
1928 PyTuple_SetItem(
size, 0, PyFloat_FromDouble((
double)
w / dpi));
1929 PyTuple_SetItem(
size, 1, PyFloat_FromDouble((
double)h / dpi));
1931 PyObject* kwargs = PyDict_New();
1932 PyDict_SetItemString(kwargs,
"figsize",
size);
1933 PyDict_SetItemString(kwargs,
"dpi", PyLong_FromSize_t(dpi));
1940 if(!res)
throw std::runtime_error(
"Call to figure_size() failed.");
1949 if(!res)
throw std::runtime_error(
"Call to legend() failed.");
1954 inline void legend(
const std::map<std::string, std::string>& keywords)
1959 PyObject* kwargs = PyDict_New();
1960 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1962 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1966 if(!res)
throw std::runtime_error(
"Call to legend() failed.");
1972 template<
typename Numeric>
1977 PyObject* args = PyTuple_New(1);
1978 PyTuple_SetItem(args, 0, PyFloat_FromDouble(ratio));
1979 PyObject* kwargs = PyDict_New();
1984 if (!ax)
throw std::runtime_error(
"Call to gca() failed.");
1987 PyObject *
set_aspect = PyObject_GetAttrString(ax,
"set_aspect");
1988 if (!
set_aspect)
throw std::runtime_error(
"Attribute set_aspect not found.");
1991 PyObject *res = PyObject_Call(
set_aspect, args, kwargs);
1992 if (!res)
throw std::runtime_error(
"Call to set_aspect() failed.");
2005 PyObject* args = PyTuple_New(1);
2006 PyTuple_SetItem(args, 0, PyString_FromString(
"equal"));
2007 PyObject* kwargs = PyDict_New();
2012 if (!ax)
throw std::runtime_error(
"Call to gca() failed.");
2015 PyObject *
set_aspect = PyObject_GetAttrString(ax,
"set_aspect");
2016 if (!
set_aspect)
throw std::runtime_error(
"Attribute set_aspect not found.");
2019 PyObject *res = PyObject_Call(
set_aspect, args, kwargs);
2020 if (!res)
throw std::runtime_error(
"Call to set_aspect() failed.");
2028 template<
typename Numeric>
2033 PyObject* list = PyList_New(2);
2034 PyList_SetItem(list, 0, PyFloat_FromDouble(
left));
2035 PyList_SetItem(list, 1, PyFloat_FromDouble(
right));
2037 PyObject* args = PyTuple_New(1);
2038 PyTuple_SetItem(args, 0, list);
2041 if(!res)
throw std::runtime_error(
"Call to ylim() failed.");
2047 template<
typename Numeric>
2052 PyObject* list = PyList_New(2);
2053 PyList_SetItem(list, 0, PyFloat_FromDouble(
left));
2054 PyList_SetItem(list, 1, PyFloat_FromDouble(
right));
2056 PyObject* args = PyTuple_New(1);
2057 PyTuple_SetItem(args, 0, list);
2060 if(!res)
throw std::runtime_error(
"Call to xlim() failed.");
2067 inline std::array<double, 2>
xlim()
2069 PyObject* args = PyTuple_New(0);
2072 if(!res)
throw std::runtime_error(
"Call to xlim() failed.");
2076 PyObject*
left = PyTuple_GetItem(res,0);
2077 PyObject*
right = PyTuple_GetItem(res,1);
2078 return { PyFloat_AsDouble(
left), PyFloat_AsDouble(
right) };
2082 inline std::array<double, 2>
ylim()
2084 PyObject* args = PyTuple_New(0);
2087 if(!res)
throw std::runtime_error(
"Call to ylim() failed.");
2091 PyObject*
left = PyTuple_GetItem(res,0);
2092 PyObject*
right = PyTuple_GetItem(res,1);
2093 return { PyFloat_AsDouble(
left), PyFloat_AsDouble(
right) };
2096 template<
typename Numeric>
2097 inline void xticks(
const std::vector<Numeric> &ticks,
const std::vector<std::string> &labels = {},
const std::map<std::string, std::string>& keywords = {})
2099 assert(labels.size() == 0 || ticks.size() == labels.size());
2107 if(labels.size() == 0) {
2109 args = PyTuple_New(1);
2110 PyTuple_SetItem(args, 0, ticksarray);
2113 PyObject* labelstuple = PyTuple_New(labels.size());
2114 for (
size_t i = 0;
i < labels.size();
i++)
2115 PyTuple_SetItem(labelstuple,
i, PyUnicode_FromString(labels[
i].c_str()));
2118 args = PyTuple_New(2);
2119 PyTuple_SetItem(args, 0, ticksarray);
2120 PyTuple_SetItem(args, 1, labelstuple);
2124 PyObject* kwargs = PyDict_New();
2125 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2127 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2134 if(!res)
throw std::runtime_error(
"Call to xticks() failed");
2139 template<
typename Numeric>
2140 inline void xticks(
const std::vector<Numeric> &ticks,
const std::map<std::string, std::string>& keywords)
2142 xticks(ticks, {}, keywords);
2145 template<
typename Numeric>
2146 inline void yticks(
const std::vector<Numeric> &ticks,
const std::vector<std::string> &labels = {},
const std::map<std::string, std::string>& keywords = {})
2148 assert(labels.size() == 0 || ticks.size() == labels.size());
2156 if(labels.size() == 0) {
2158 args = PyTuple_New(1);
2159 PyTuple_SetItem(args, 0, ticksarray);
2162 PyObject* labelstuple = PyTuple_New(labels.size());
2163 for (
size_t i = 0;
i < labels.size();
i++)
2164 PyTuple_SetItem(labelstuple,
i, PyUnicode_FromString(labels[
i].c_str()));
2167 args = PyTuple_New(2);
2168 PyTuple_SetItem(args, 0, ticksarray);
2169 PyTuple_SetItem(args, 1, labelstuple);
2173 PyObject* kwargs = PyDict_New();
2174 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2176 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2183 if(!res)
throw std::runtime_error(
"Call to yticks() failed");
2188 template<
typename Numeric>
2189 inline void yticks(
const std::vector<Numeric> &ticks,
const std::map<std::string, std::string>& keywords)
2191 yticks(ticks, {}, keywords);
2194 template <
typename Numeric>
inline void margins(Numeric margin)
2197 PyObject* args = PyTuple_New(1);
2198 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin));
2203 throw std::runtime_error(
"Call to margins() failed.");
2209 template <
typename Numeric>
inline void margins(Numeric margin_x, Numeric margin_y)
2212 PyObject* args = PyTuple_New(2);
2213 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin_x));
2214 PyTuple_SetItem(args, 1, PyFloat_FromDouble(margin_y));
2219 throw std::runtime_error(
"Call to margins() failed.");
2226 inline void tick_params(
const std::map<std::string, std::string>& keywords,
const std::string
axis =
"both")
2232 args = PyTuple_New(1);
2233 PyTuple_SetItem(args, 0, PyString_FromString(
axis.c_str()));
2236 PyObject* kwargs = PyDict_New();
2237 for (std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2239 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2247 if (!res)
throw std::runtime_error(
"Call to tick_params() failed");
2252 inline void subplot(
long nrows,
long ncols,
long plot_number)
2257 PyObject* args = PyTuple_New(3);
2258 PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
2259 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
2260 PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
2263 if(!res)
throw std::runtime_error(
"Call to subplot() failed.");
2269 inline void subplot2grid(
long nrows,
long ncols,
long rowid=0,
long colid=0,
long rowspan=1,
long colspan=1)
2273 PyObject* shape = PyTuple_New(2);
2274 PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows));
2275 PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols));
2277 PyObject* loc = PyTuple_New(2);
2278 PyTuple_SetItem(loc, 0, PyLong_FromLong(rowid));
2279 PyTuple_SetItem(loc, 1, PyLong_FromLong(colid));
2281 PyObject* args = PyTuple_New(4);
2282 PyTuple_SetItem(args, 0, shape);
2283 PyTuple_SetItem(args, 1, loc);
2284 PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan));
2285 PyTuple_SetItem(args, 3, PyLong_FromLong(colspan));
2288 if(!res)
throw std::runtime_error(
"Call to subplot2grid() failed.");
2296 inline void title(
const std::string &titlestr,
const std::map<std::string, std::string> &keywords = {})
2300 PyObject* pytitlestr = PyString_FromString(titlestr.c_str());
2301 PyObject* args = PyTuple_New(1);
2302 PyTuple_SetItem(args, 0, pytitlestr);
2304 PyObject* kwargs = PyDict_New();
2305 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2306 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2310 if(!res)
throw std::runtime_error(
"Call to title() failed.");
2317 inline void suptitle(
const std::string &suptitlestr,
const std::map<std::string, std::string> &keywords = {})
2321 PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str());
2322 PyObject* args = PyTuple_New(1);
2323 PyTuple_SetItem(args, 0, pysuptitlestr);
2325 PyObject* kwargs = PyDict_New();
2326 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2327 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2331 if(!res)
throw std::runtime_error(
"Call to suptitle() failed.");
2338 inline void axis(
const std::string &axisstr)
2342 PyObject* str = PyString_FromString(axisstr.c_str());
2343 PyObject* args = PyTuple_New(1);
2344 PyTuple_SetItem(args, 0, str);
2347 if(!res)
throw std::runtime_error(
"Call to title() failed.");
2353 inline void axhline(
double y,
double xmin = 0.,
double xmax = 1.,
const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>())
2358 PyObject* args = PyTuple_New(3);
2359 PyTuple_SetItem(args, 0, PyFloat_FromDouble(
y));
2360 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmin));
2361 PyTuple_SetItem(args, 2, PyFloat_FromDouble(xmax));
2364 PyObject* kwargs = PyDict_New();
2365 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2367 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2375 if(res) Py_DECREF(res);
2378 inline void axvline(
double x,
double ymin = 0.,
double ymax = 1.,
const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>())
2383 PyObject* args = PyTuple_New(3);
2384 PyTuple_SetItem(args, 0, PyFloat_FromDouble(
x));
2385 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ymin));
2386 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymax));
2389 PyObject* kwargs = PyDict_New();
2390 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2392 PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2400 if(res) Py_DECREF(res);
2403 inline void axvspan(
double xmin,
double xmax,
double ymin = 0.,
double ymax = 1.,
const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>())
2406 PyObject* args = PyTuple_New(4);
2407 PyTuple_SetItem(args, 0, PyFloat_FromDouble(xmin));
2408 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmax));
2409 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymin));
2410 PyTuple_SetItem(args, 3, PyFloat_FromDouble(ymax));
2413 PyObject* kwargs = PyDict_New();
2414 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2415 if (it->first ==
"linewidth" || it->first ==
"alpha") {
2416 PyDict_SetItemString(kwargs, it->first.c_str(),
2417 PyFloat_FromDouble(std::stod(it->second)));
2419 PyDict_SetItemString(kwargs, it->first.c_str(),
2420 PyString_FromString(it->second.c_str()));
2428 if(res) Py_DECREF(res);
2431 inline void xlabel(
const std::string &str,
const std::map<std::string, std::string> &keywords = {})
2435 PyObject* pystr = PyString_FromString(str.c_str());
2436 PyObject* args = PyTuple_New(1);
2437 PyTuple_SetItem(args, 0, pystr);
2439 PyObject* kwargs = PyDict_New();
2440 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2441 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2445 if(!res)
throw std::runtime_error(
"Call to xlabel() failed.");
2452 inline void ylabel(
const std::string &str,
const std::map<std::string, std::string>& keywords = {})
2456 PyObject* pystr = PyString_FromString(str.c_str());
2457 PyObject* args = PyTuple_New(1);
2458 PyTuple_SetItem(args, 0, pystr);
2460 PyObject* kwargs = PyDict_New();
2461 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2462 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2466 if(!res)
throw std::runtime_error(
"Call to ylabel() failed.");
2473 inline void set_zlabel(
const std::string &str,
const std::map<std::string, std::string>& keywords = {})
2481 static PyObject *mpl_toolkitsmod =
nullptr, *axis3dmod =
nullptr;
2482 if (!mpl_toolkitsmod) {
2483 PyObject* mpl_toolkits = PyString_FromString(
"mpl_toolkits");
2484 PyObject* axis3d = PyString_FromString(
"mpl_toolkits.mplot3d");
2485 if (!mpl_toolkits || !axis3d) {
throw std::runtime_error(
"couldnt create string"); }
2487 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
2488 Py_DECREF(mpl_toolkits);
2489 if (!mpl_toolkitsmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits!"); }
2491 axis3dmod = PyImport_Import(axis3d);
2493 if (!axis3dmod) {
throw std::runtime_error(
"Error loading module mpl_toolkits.mplot3d!"); }
2496 PyObject* pystr = PyString_FromString(str.c_str());
2497 PyObject* args = PyTuple_New(1);
2498 PyTuple_SetItem(args, 0, pystr);
2500 PyObject* kwargs = PyDict_New();
2501 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2502 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2508 if (!ax)
throw std::runtime_error(
"Call to gca() failed.");
2511 PyObject *zlabel = PyObject_GetAttrString(ax,
"set_zlabel");
2512 if (!zlabel)
throw std::runtime_error(
"Attribute set_zlabel not found.");
2515 PyObject *res = PyObject_Call(zlabel, args, kwargs);
2516 if (!res)
throw std::runtime_error(
"Call to set_zlabel() failed.");
2522 if (res) Py_DECREF(res);
2529 PyObject* pyflag = flag ? Py_True : Py_False;
2532 PyObject* args = PyTuple_New(1);
2533 PyTuple_SetItem(args, 0, pyflag);
2536 if(!res)
throw std::runtime_error(
"Call to grid() failed.");
2542 inline void show(
const bool block =
true)
2549 res = PyObject_CallObject(
2555 PyObject *kwargs = PyDict_New();
2556 PyDict_SetItemString(kwargs,
"block", Py_False);
2562 if (!res)
throw std::runtime_error(
"Call to show() failed.");
2571 PyObject* res = PyObject_CallObject(
2575 if (!res)
throw std::runtime_error(
"Call to close() failed.");
2584 PyObject *kwargs = PyDict_New();
2592 throw std::runtime_error(
"Call to show() failed.");
2601 PyObject* res = PyObject_CallObject(
2605 if (!res)
throw std::runtime_error(
"Call to draw() failed.");
2610 template<
typename Numeric>
2615 PyObject* args = PyTuple_New(1);
2616 PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
2619 if(!res)
throw std::runtime_error(
"Call to pause() failed.");
2629 PyObject* pyfilename = PyString_FromString(
filename.c_str());
2631 PyObject* args = PyTuple_New(1);
2632 PyTuple_SetItem(args, 0, pyfilename);
2634 PyObject* kwargs = PyDict_New();
2638 PyDict_SetItemString(kwargs,
"dpi", PyLong_FromLong(dpi));
2642 if (!res)
throw std::runtime_error(
"Call to save() failed.");
2649 inline void rcparams(
const std::map<std::string, std::string>& keywords = {}) {
2651 PyObject* args = PyTuple_New(0);
2652 PyObject* kwargs = PyDict_New();
2653 for (
auto it = keywords.begin(); it != keywords.end(); ++it) {
2654 if (
"text.usetex" == it->first)
2655 PyDict_SetItemString(kwargs, it->first.c_str(), PyLong_FromLong(std::stoi(it->second.c_str())));
2656 else PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
2660 PyObject * res = PyObject_Call(update, args, kwargs);
2661 if(!res)
throw std::runtime_error(
"Call to rcParams.update() failed.");
2671 PyObject *res = PyObject_CallObject(
2675 if (!res)
throw std::runtime_error(
"Call to clf() failed.");
2687 throw std::runtime_error(
"Call to cla() failed.");
2695 PyObject *res = PyObject_CallObject(
2699 if (!res)
throw std::runtime_error(
"Call to ion() failed.");
2704 inline std::vector<std::array<double, 2>>
ginput(
const int numClicks = 1,
const std::map<std::string, std::string>& keywords = {})
2708 PyObject *args = PyTuple_New(1);
2709 PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
2712 PyObject* kwargs = PyDict_New();
2713 for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
2715 PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
2718 PyObject* res = PyObject_Call(
2723 if (!res)
throw std::runtime_error(
"Call to ginput() failed.");
2725 const size_t len = PyList_Size(res);
2726 std::vector<std::array<double, 2>> out;
2728 for (
size_t i = 0;
i <
len;
i++) {
2729 PyObject *current = PyList_GetItem(res,
i);
2730 std::array<double, 2> position;
2731 position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
2732 position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
2733 out.push_back(position);
2744 PyObject *res = PyObject_CallObject(
2748 if (!res)
throw std::runtime_error(
"Call to tight_layout() failed.");
2757 template<
typename T>
2760 template<
bool obj,
typename T>
2763 template<
typename T>
2769 template<
typename T>
2772 struct Fallback {
void operator()(); };
2773 struct Derived :
T, Fallback { };
2775 template<
typename U, U>
struct Check;
2777 template<
typename U>
2778 static std::true_type test( ... );
2780 template<
typename U>
2781 static std::false_type test( Check<
void(Fallback::*)(), &U::operator()>* );
2784 typedef decltype(test<Derived>(
nullptr))
type;
2785 typedef decltype(&Fallback::operator()) dtype;
2789 template<typename
T>
2796 template<
typename IsYDataCallable>
2802 template<
typename IterableX,
typename IterableY>
2808 using std::distance;
2814 assert(xs == ys &&
"x and y data must have the same number of elements!");
2816 PyObject* xlist = PyList_New(xs);
2817 PyObject* ylist = PyList_New(ys);
2818 PyObject* pystring = PyString_FromString(
format.c_str());
2821 for(
size_t i = 0;
i < xs; ++
i) {
2822 PyList_SetItem(xlist,
i, PyFloat_FromDouble(*itx++));
2823 PyList_SetItem(ylist,
i, PyFloat_FromDouble(*ity++));
2826 PyObject* plot_args = PyTuple_New(3);
2827 PyTuple_SetItem(plot_args, 0, xlist);
2828 PyTuple_SetItem(plot_args, 1, ylist);
2829 PyTuple_SetItem(plot_args, 2, pystring);
2833 Py_DECREF(plot_args);
2834 if(res) Py_DECREF(res);
2843 template<
typename Iterable,
typename Callable>
2846 if(
begin(ticks) ==
end(ticks))
return true;
2850 std::vector<double>
y;
2851 for(
auto x : ticks)
y.push_back(f(
x));
2859 template<
typename... Args>
2862 template<
typename A,
typename B,
typename... Args>
2863 bool plot(
const A& a,
const B& b,
const std::string&
format, Args... args)
2872 inline bool plot(
const std::vector<double>&
x,
const std::vector<double>&
y,
const std::string&
format =
"") {
2873 return plot<double,double>(
x,
y,
format);
2876 inline bool plot(
const std::vector<double>&
y,
const std::string&
format =
"") {
2877 return plot<double>(
y,
format);
2880 inline bool plot(
const std::vector<double>&
x,
const std::vector<double>&
y,
const std::map<std::string, std::string>& keywords) {
2881 return plot<double>(
x,
y,keywords);
2891 template<
typename Numeric>
2892 Plot(
const std::string& name,
const std::vector<Numeric>&
x,
const std::vector<Numeric>&
y,
const std::string&
format =
"") {
2895 assert(
x.size() ==
y.size());
2897 PyObject* kwargs = PyDict_New();
2899 PyDict_SetItemString(kwargs,
"label", PyString_FromString(name.c_str()));
2904 PyObject* pystring = PyString_FromString(
format.c_str());
2906 PyObject* plot_args = PyTuple_New(3);
2907 PyTuple_SetItem(plot_args, 0, xarray);
2908 PyTuple_SetItem(plot_args, 1, yarray);
2909 PyTuple_SetItem(plot_args, 2, pystring);
2914 Py_DECREF(plot_args);
2918 line= PyList_GetItem(res, 0);
2921 set_data_fct = PyObject_GetAttrString(line,
"set_data");
2930 Plot(
const std::string& name =
"",
const std::string&
format =
"")
2933 template<
typename Numeric>
2934 bool update(
const std::vector<Numeric>&
x,
const std::vector<Numeric>&
y) {
2935 assert(
x.size() ==
y.size());
2941 PyObject* plot_args = PyTuple_New(2);
2942 PyTuple_SetItem(plot_args, 0, xarray);
2943 PyTuple_SetItem(plot_args, 1, yarray);
2945 PyObject* res = PyObject_CallObject(set_data_fct, plot_args);
2946 if (res) Py_DECREF(res);
2954 return update(std::vector<double>(), std::vector<double>());
2961 auto remove_fct = PyObject_GetAttrString(line,
"remove");
2962 PyObject* args = PyTuple_New(0);
2963 PyObject* res = PyObject_CallObject(remove_fct, args);
2964 if (res) Py_DECREF(res);
2978 Py_DECREF(set_data_fct);
2982 PyObject* line =
nullptr;
2983 PyObject* set_data_fct =
nullptr;